From 863a6670a4f1901d1c9088f357337f3c8a17ab35 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 17 Jul 2019 14:56:26 +0800 Subject: drm/nouveau/secboot: Make acr_r352_ls_gpccs_func static Fix sparse warning: drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c:1092:1: warning: symbol 'acr_r352_ls_gpccs_func' was not declared. Should it be static? Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c index 4fd4cfe459b8..7af971db91bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c @@ -1088,7 +1088,7 @@ acr_r352_ls_gpccs_func_0 = { .lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, }; -const struct acr_r352_ls_func +static const struct acr_r352_ls_func acr_r352_ls_gpccs_func = { .load = acr_ls_ucode_load_gpccs, .version_max = 0, -- cgit v1.2.3 From fcca420d66046d5ddac55a9ddecb0e387547f7a0 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 14 May 2019 21:57:01 +0100 Subject: drm/nouveau/bios/init: fix spelling mistake "CONDITON" -> "CONDITION" There is a spelling mistake in a warning message. Fix it. Signed-off-by: Colin Ian King Reviewed-by: Mukesh Ojha Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index ec0e9f7224b5..3f4f27d191ae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c @@ -834,7 +834,7 @@ init_generic_condition(struct nvbios_init *init) init_exec_set(init, false); break; default: - warn("INIT_GENERIC_CONDITON: unknown 0x%02x\n", cond); + warn("INIT_GENERIC_CONDITION: unknown 0x%02x\n", cond); init->offset += size; break; } -- cgit v1.2.3 From 66cbcc72ae34711854ae7af8056bfb7169f874fd Mon Sep 17 00:00:00 2001 From: Rhys Kidd Date: Mon, 3 Jun 2019 00:13:14 +1000 Subject: drm/nouveau/bios/init: handle INIT_RESET_BEGUN devinit opcode Signal that the reset sequence has begun. This opcode signals that the software reset sequence has begun. Ordinarily, no actual operations are performed by the opcode. However it allows for possible software work arounds by devinit engines in software agents other than the VBIOS, such as the resman, FCODE, and EFI driver. Signed-off-by: Rhys Kidd Reviewed-by: Lyude Paul Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index 3f4f27d191ae..5e02832304e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c @@ -1934,6 +1934,17 @@ init_ram_restrict_pll(struct nvbios_init *init) } } +/** + * INIT_RESET_BEGUN - opcode 0x8c + * + */ +static void +init_reset_begun(struct nvbios_init *init) +{ + trace("RESET_BEGUN\n"); + init->offset += 1; +} + /** * INIT_GPIO - opcode 0x8e * @@ -2260,7 +2271,7 @@ static struct nvbios_init_opcode { [0x79] = { init_pll }, [0x7a] = { init_zm_reg }, [0x87] = { init_ram_restrict_pll }, - [0x8c] = { init_reserved }, + [0x8c] = { init_reset_begun }, [0x8d] = { init_reserved }, [0x8e] = { init_gpio }, [0x8f] = { init_ram_restrict_zm_reg_group }, -- cgit v1.2.3 From 9f9b450752d38c86f4f830214bb9276ed174d5d3 Mon Sep 17 00:00:00 2001 From: Rhys Kidd Date: Mon, 3 Jun 2019 00:13:15 +1000 Subject: drm/nouveau/bios/init: handle INIT_RESET_END devinit opcode Signal that the reset sequence has completed. This opcode signals that the software reset sequence has completed. Ordinarily, no actual operations are performed by the opcode. However it allows for possible software work arounds by devinit engines in software agents other than the VBIOS, such as the resman, FCODE, and EFI driver. Signed-off-by: Rhys Kidd Reviewed-by: Lyude Paul Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index 5e02832304e2..9de74f41dcd2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c @@ -1945,6 +1945,17 @@ init_reset_begun(struct nvbios_init *init) init->offset += 1; } +/** + * INIT_RESET_END - opcode 0x8d + * + */ +static void +init_reset_end(struct nvbios_init *init) +{ + trace("RESET_END\n"); + init->offset += 1; +} + /** * INIT_GPIO - opcode 0x8e * @@ -2272,7 +2283,7 @@ static struct nvbios_init_opcode { [0x7a] = { init_zm_reg }, [0x87] = { init_ram_restrict_pll }, [0x8c] = { init_reset_begun }, - [0x8d] = { init_reserved }, + [0x8d] = { init_reset_end }, [0x8e] = { init_gpio }, [0x8f] = { init_ram_restrict_zm_reg_group }, [0x90] = { init_copy_zm_reg }, -- cgit v1.2.3 From cf9518b50a9c68cafb07e05fc54731071228ced3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 13 Jun 2019 13:58:50 +1000 Subject: drm/nouveau/fifo/gf1xx: convert to using nvkm_fault_data Would like to be able to reuse gf100_fifo_intr_fault() for (some of) the later chipsets too, as it's identical. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 188 +++++++++++++---------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 2 + 3 files changed, 106 insertions(+), 86 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 10a2e7039a75..5a39e51d42d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -193,68 +194,6 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, nvkm_fifo_kevent(&fifo->base, chid); } -static const struct nvkm_enum -gf100_fifo_sched_reason[] = { - { 0x0a, "CTXSW_TIMEOUT" }, - {} -}; - -static void -gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo) -{ - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nvkm_engine *engine; - struct gf100_fifo_chan *chan; - unsigned long flags; - u32 engn; - - spin_lock_irqsave(&fifo->base.lock, flags); - for (engn = 0; engn < 6; engn++) { - u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04)); - u32 busy = (stat & 0x80000000); - u32 save = (stat & 0x00100000); /* maybe? */ - u32 unk0 = (stat & 0x00040000); - u32 unk1 = (stat & 0x00001000); - u32 chid = (stat & 0x0000007f); - (void)save; - - if (busy && unk0 && unk1) { - list_for_each_entry(chan, &fifo->chan, head) { - if (chan->base.chid == chid) { - engine = gf100_fifo_engine(fifo, engn); - if (!engine) - break; - gf100_fifo_recover(fifo, engine, chan); - break; - } - } - } - } - spin_unlock_irqrestore(&fifo->base.lock, flags); -} - -static void -gf100_fifo_intr_sched(struct gf100_fifo *fifo) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 intr = nvkm_rd32(device, 0x00254c); - u32 code = intr & 0x000000ff; - const struct nvkm_enum *en; - - en = nvkm_enum_find(gf100_fifo_sched_reason, code); - - nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : ""); - - switch (code) { - case 0x0a: - gf100_fifo_intr_sched_ctxsw(fifo); - break; - default: - break; - } -} - static const struct nvkm_enum gf100_fifo_fault_engine[] = { { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR }, @@ -315,32 +254,24 @@ gf100_fifo_fault_gpcclient[] = { }; static void -gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit) +gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) { + struct gf100_fifo *fifo = gf100_fifo(base); struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; - u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); - u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10)); - u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10)); - u32 stat = nvkm_rd32(device, 0x00280c + (unit * 0x10)); - u32 gpc = (stat & 0x1f000000) >> 24; - u32 client = (stat & 0x00001f00) >> 8; - u32 write = (stat & 0x00000080); - u32 hub = (stat & 0x00000040); - u32 reason = (stat & 0x0000000f); const struct nvkm_enum *er, *eu, *ec; struct nvkm_engine *engine = NULL; struct nvkm_fifo_chan *chan; unsigned long flags; char gpcid[8] = ""; - er = nvkm_enum_find(gf100_fifo_fault_reason, reason); - eu = nvkm_enum_find(gf100_fifo_fault_engine, unit); - if (hub) { - ec = nvkm_enum_find(gf100_fifo_fault_hubclient, client); + er = nvkm_enum_find(gf100_fifo_fault_reason, info->reason); + eu = nvkm_enum_find(gf100_fifo_fault_engine, info->engine); + if (info->hub) { + ec = nvkm_enum_find(gf100_fifo_fault_hubclient, info->client); } else { - ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, client); - snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc); + ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, info->client); + snprintf(gpcid, sizeof(gpcid), "GPC%d/", info->gpc); } if (eu && eu->data2) { @@ -360,22 +291,108 @@ gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit) } } - chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags); + chan = nvkm_fifo_chan_inst(&fifo->base, info->inst, &flags); nvkm_error(subdev, "%s fault at %010llx engine %02x [%s] client %02x [%s%s] " "reason %02x [%s] on channel %d [%010llx %s]\n", - write ? "write" : "read", (u64)vahi << 32 | valo, - unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "", - reason, er ? er->name : "", chan ? chan->chid : -1, - (u64)inst << 12, - chan ? chan->object.client->name : "unknown"); + info->access ? "write" : "read", info->addr, + info->engine, eu ? eu->name : "", + info->client, gpcid, ec ? ec->name : "", + info->reason, er ? er->name : "", chan ? chan->chid : -1, + info->inst, chan ? chan->object.client->name : "unknown"); if (engine && chan) gf100_fifo_recover(fifo, engine, (void *)chan); nvkm_fifo_chan_put(&fifo->base, flags, &chan); } +static const struct nvkm_enum +gf100_fifo_sched_reason[] = { + { 0x0a, "CTXSW_TIMEOUT" }, + {} +}; + +static void +gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo) +{ + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_engine *engine; + struct gf100_fifo_chan *chan; + unsigned long flags; + u32 engn; + + spin_lock_irqsave(&fifo->base.lock, flags); + for (engn = 0; engn < 6; engn++) { + u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04)); + u32 busy = (stat & 0x80000000); + u32 save = (stat & 0x00100000); /* maybe? */ + u32 unk0 = (stat & 0x00040000); + u32 unk1 = (stat & 0x00001000); + u32 chid = (stat & 0x0000007f); + (void)save; + + if (busy && unk0 && unk1) { + list_for_each_entry(chan, &fifo->chan, head) { + if (chan->base.chid == chid) { + engine = gf100_fifo_engine(fifo, engn); + if (!engine) + break; + gf100_fifo_recover(fifo, engine, chan); + break; + } + } + } + } + spin_unlock_irqrestore(&fifo->base.lock, flags); +} + +static void +gf100_fifo_intr_sched(struct gf100_fifo *fifo) +{ + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 intr = nvkm_rd32(device, 0x00254c); + u32 code = intr & 0x000000ff; + const struct nvkm_enum *en; + + en = nvkm_enum_find(gf100_fifo_sched_reason, code); + + nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : ""); + + switch (code) { + case 0x0a: + gf100_fifo_intr_sched_ctxsw(fifo); + break; + default: + break; + } +} + +void +gf100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); + u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10)); + u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10)); + u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10)); + struct nvkm_fault_data info; + + info.inst = (u64)inst << 12; + info.addr = ((u64)vahi << 32) | valo; + info.time = 0; + info.engine = unit; + info.valid = 1; + info.gpc = (type & 0x1f000000) >> 24; + info.client = (type & 0x00001f00) >> 8; + info.access = (type & 0x00000080) >> 7; + info.hub = (type & 0x00000040) >> 6; + info.reason = (type & 0x0000000f); + + nvkm_fifo_fault(fifo, &info); +} + static const struct nvkm_bitfield gf100_fifo_pbdma_intr[] = { /* { 0x00008000, "" } seen with null ib push */ @@ -518,7 +535,7 @@ gf100_fifo_intr(struct nvkm_fifo *base) u32 mask = nvkm_rd32(device, 0x00259c); while (mask) { u32 unit = __ffs(mask); - gf100_fifo_intr_fault(fifo, unit); + gf100_fifo_intr_fault(&fifo->base, unit); nvkm_wr32(device, 0x00259c, (1 << unit)); mask &= ~(1 << unit); } @@ -655,6 +672,7 @@ gf100_fifo = { .init = gf100_fifo_init, .fini = gf100_fifo_fini, .intr = gf100_fifo_intr, + .fault = gf100_fifo_fault, .uevent_init = gf100_fifo_uevent_init, .uevent_fini = gf100_fifo_uevent_fini, .chan = { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 1053fe796466..ac9abcc1470a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -666,7 +666,7 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit) info.client = (type & 0x00001f00) >> 8; info.access = (type & 0x00000080) >> 7; info.hub = (type & 0x00000040) >> 6; - info.reason = (type & 0x000000ff); + info.reason = (type & 0x0000001f); nvkm_fifo_fault(&fifo->base, &info); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index c66f5370b21f..0ef8baab513e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -37,4 +37,6 @@ struct nvkm_fifo_func { void nv04_fifo_intr(struct nvkm_fifo *); void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *); void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); + +void gf100_fifo_intr_fault(struct nvkm_fifo *, int); #endif -- cgit v1.2.3 From cde540211ab1346a262ad9a5ecc52c9ff8f5975f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 13 Jun 2019 14:23:04 +1000 Subject: drm/nouveau/fifo/gk104-: fix parsing of mmu fault data Pascal was particularly incorrect, as the register changed to be more in the same format as the MMU fault buffers are. Shouldn't have impacted much more than confusing MMU fault log messages. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 28 ++---------------------- drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 6 +++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c | 26 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c | 27 +++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c | 1 + 10 files changed, 67 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index ac9abcc1470a..5d4b695cab8e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -646,31 +646,6 @@ gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo) nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat); } -static void -gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit) -{ - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; - u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); - u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10)); - u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10)); - u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10)); - struct nvkm_fault_data info; - - info.inst = (u64)inst << 12; - info.addr = ((u64)vahi << 32) | valo; - info.time = 0; - info.engine = unit; - info.valid = 1; - info.gpc = (type & 0x1f000000) >> 24; - info.client = (type & 0x00001f00) >> 8; - info.access = (type & 0x00000080) >> 7; - info.hub = (type & 0x00000040) >> 6; - info.reason = (type & 0x0000001f); - - nvkm_fifo_fault(&fifo->base, &info); -} - static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { { 0x00000001, "MEMREQ" }, { 0x00000002, "MEMACK_TIMEOUT" }, @@ -849,7 +824,7 @@ gk104_fifo_intr(struct nvkm_fifo *base) u32 mask = nvkm_rd32(device, 0x00259c); while (mask) { u32 unit = __ffs(mask); - gk104_fifo_intr_fault(fifo, unit); + fifo->func->intr.fault(&fifo->base, unit); nvkm_wr32(device, 0x00259c, (1 << unit)); mask &= ~(1 << unit); } @@ -1204,6 +1179,7 @@ gk104_fifo_fault_gpcclient[] = { static const struct gk104_fifo_func gk104_fifo = { + .intr.fault = gf100_fifo_intr_fault, .pbdma = &gk104_fifo_pbdma, .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index c33f4593cbc6..6407a4a174cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -45,6 +45,10 @@ struct gk104_fifo { }; struct gk104_fifo_func { + struct { + void (*fault)(struct nvkm_fifo *, int unit); + } intr; + const struct gk104_fifo_pbdma_func { int (*nr)(struct gk104_fifo *); void (*init)(struct gk104_fifo *); @@ -110,12 +114,14 @@ void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, extern const struct gk104_fifo_pbdma_func gk208_fifo_pbdma; void gk208_fifo_pbdma_init_timeout(struct gk104_fifo *); +void gm107_fifo_intr_fault(struct nvkm_fifo *, int); extern const struct nvkm_enum gm107_fifo_fault_engine[]; extern const struct gk104_fifo_runlist_func gm107_fifo_runlist; extern const struct gk104_fifo_pbdma_func gm200_fifo_pbdma; int gm200_fifo_pbdma_nr(struct gk104_fifo *); +void gp100_fifo_intr_fault(struct nvkm_fifo *, int); extern const struct nvkm_enum gp100_fifo_fault_engine[]; extern const struct nvkm_enum gv100_fifo_fault_access[]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index 8adfa6b182cb..f820969e4405 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -48,6 +48,7 @@ gk110_fifo_runlist = { static const struct gk104_fifo_func gk110_fifo = { + .intr.fault = gf100_fifo_intr_fault, .pbdma = &gk104_fifo_pbdma, .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 9553fb4af601..2f54787b5fd0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -45,6 +45,7 @@ gk208_fifo_pbdma = { static const struct gk104_fifo_func gk208_fifo = { + .intr.fault = gf100_fifo_intr_fault, .pbdma = &gk208_fifo_pbdma, .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index a4c6ac3cd6c7..a814c4e0ed3e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -26,6 +26,7 @@ static const struct gk104_fifo_func gk20a_fifo = { + .intr.fault = gf100_fifo_intr_fault, .pbdma = &gk208_fifo_pbdma, .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index acf230764cb0..c2a2e4572f6c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -25,6 +25,7 @@ #include "changk104.h" #include +#include #include @@ -67,8 +68,33 @@ gm107_fifo_fault_engine[] = { {} }; +void +gm107_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); + u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10)); + u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10)); + u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10)); + struct nvkm_fault_data info; + + info.inst = (u64)inst << 12; + info.addr = ((u64)vahi << 32) | valo; + info.time = 0; + info.engine = unit; + info.valid = 1; + info.gpc = (type & 0x1f000000) >> 24; + info.client = (type & 0x00003f00) >> 8; + info.access = (type & 0x00000080) >> 7; + info.hub = (type & 0x00000040) >> 6; + info.reason = (type & 0x0000000f); + + nvkm_fifo_fault(fifo, &info); +} + static const struct gk104_fifo_func gm107_fifo = { + .intr.fault = gm107_fifo_intr_fault, .pbdma = &gk208_fifo_pbdma, .fault.access = gk104_fifo_fault_access, .fault.engine = gm107_fifo_fault_engine, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index b96c1c5d6577..b8cfe3b28c4f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -42,6 +42,7 @@ gm200_fifo_pbdma = { static const struct gk104_fifo_func gm200_fifo = { + .intr.fault = gm107_fifo_intr_fault, .pbdma = &gm200_fifo_pbdma, .fault.access = gk104_fifo_fault_access, .fault.engine = gm107_fifo_fault_engine, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c index a49539b9e4ec..70b4feebc1fa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c @@ -26,6 +26,7 @@ static const struct gk104_fifo_func gm20b_fifo = { + .intr.fault = gm107_fifo_intr_fault, .pbdma = &gm200_fifo_pbdma, .fault.access = gk104_fifo_fault_access, .fault.engine = gm107_fifo_fault_engine, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 54377e0f6a88..2c7a0176b3c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -24,6 +24,8 @@ #include "gk104.h" #include "changk104.h" +#include + #include const struct nvkm_enum @@ -50,8 +52,33 @@ gp100_fifo_fault_engine[] = { {} }; +void +gp100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); + u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10)); + u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10)); + u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10)); + struct nvkm_fault_data info; + + info.inst = (u64)inst << 12; + info.addr = ((u64)vahi << 32) | valo; + info.time = 0; + info.engine = unit; + info.valid = 1; + info.gpc = (type & 0x1f000000) >> 24; + info.hub = (type & 0x00100000) >> 20; + info.access = (type & 0x00070000) >> 16; + info.client = (type & 0x00007f00) >> 8; + info.reason = (type & 0x0000001f); + + nvkm_fifo_fault(fifo, &info); +} + static const struct gk104_fifo_func gp100_fifo = { + .intr.fault = gp100_fifo_intr_fault, .pbdma = &gm200_fifo_pbdma, .fault.access = gk104_fifo_fault_access, .fault.engine = gp100_fifo_fault_engine, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c index 778ba7e46fb3..8c65ad4feedb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c @@ -26,6 +26,7 @@ static const struct gk104_fifo_func gp10b_fifo = { + .intr.fault = gp100_fifo_intr_fault, .pbdma = &gm200_fifo_pbdma, .fault.access = gk104_fifo_fault_access, .fault.engine = gp100_fifo_fault_engine, -- cgit v1.2.3 From f0790cda65a1f1a3818db16e95c04c06cb7f2421 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 2 Jul 2019 12:52:11 +1000 Subject: drm/nouveau/therm: skip probing for devices not specified in thermal tables Saves some time during driver load, as described by the relevant section[1] of the DCB 4.x specification. [1] https://nvidia.github.io/open-gpu-doc/DCB/DCB-4.x-Specification.html#_i2c_device_table Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c | 13 +++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c | 3 +++ 3 files changed, 18 insertions(+) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h index f29f2d8da142..9ac3dda4b44f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h @@ -26,4 +26,6 @@ nvbios_extdev_parse(struct nvkm_bios *, int, struct nvbios_extdev_func *); int nvbios_extdev_find(struct nvkm_bios *, enum nvbios_extdev_type, struct nvbios_extdev_func *); + +bool nvbios_extdev_skip_probe(struct nvkm_bios *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c index b8578359e61b..118e33174cbe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c @@ -46,6 +46,19 @@ extdev_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt) return extdev + *hdr; } +bool +nvbios_extdev_skip_probe(struct nvkm_bios *bios) +{ + u8 ver, hdr, len, cnt; + u16 data = extdev_table(bios, &ver, &hdr, &len, &cnt); + if (data && ver == 0x40 && hdr >= 5) { + u8 flags = nvbios_rd08(bios, data - hdr + 4); + if (flags & 1) + return true; + } + return false; +} + static u16 nvbios_extdev_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c index 6e0ddc1bb583..03b355dabab3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c @@ -116,6 +116,9 @@ nvkm_therm_ic_ctor(struct nvkm_therm *therm) return; } + if (nvbios_extdev_skip_probe(bios)) + return; + /* The vbios doesn't provide the address of an exisiting monitoring device. Let's try our static list. */ -- cgit v1.2.3 From 69cbbb7b04ff57c17018b27a86e9c2d758d4366e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 2 Jul 2019 14:19:12 +1000 Subject: drm/nouveau/therm: don't attempt fan control where PMU is already managing it There's already a condition in place which attempts to detect this, but since we've begun to require a PMU subdev even on boards where we don't load a custom FW, it's become inaccurate. This will prevent unnecessarily running a periodic fan update thread on GP100 and newer, where we don't yet override the default PMU FW. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 18 ++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c | 7 ++++--- 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 24fbcccd93eb..4752006880f3 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -30,6 +30,7 @@ struct nvkm_pmu { int nvkm_pmu_send(struct nvkm_pmu *, u32 reply[2], u32 process, u32 message, u32 data0, u32 data1); void nvkm_pmu_pgob(struct nvkm_pmu *, bool enable); +bool nvkm_pmu_fan_controlled(struct nvkm_device *); int gt215_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); int gf100_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index ce70a193caa7..ea2e11771bca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -26,6 +26,24 @@ #include #include +bool +nvkm_pmu_fan_controlled(struct nvkm_device *device) +{ + struct nvkm_pmu *pmu = device->pmu; + + /* Internal PMU FW does not currently control fans in any way, + * allow SW control of fans instead. + */ + if (pmu && pmu->func->code.size) + return false; + + /* Default (board-loaded, or VBIOS PMU/PREOS) PMU FW on Fermi + * and newer automatically control the fan speed, which would + * interfere with SW control. + */ + return (device->chipset >= 0xc0); +} + void nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index 07914e36939e..4a4d1e224126 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -21,9 +21,11 @@ * * Authors: Martin Peres */ -#include #include "priv.h" +#include +#include + int nvkm_therm_temp_get(struct nvkm_therm *therm) { @@ -192,8 +194,7 @@ nvkm_therm_fan_mode(struct nvkm_therm *therm, int mode) /* The default PPWR ucode on fermi interferes with fan management */ if ((mode >= ARRAY_SIZE(name)) || - (mode != NVKM_THERM_CTRL_NONE && device->card_type >= NV_C0 && - !device->pmu)) + (mode != NVKM_THERM_CTRL_NONE && nvkm_pmu_fan_controlled(device))) return -EINVAL; /* do not allow automatic fan management if the thermal sensor is -- cgit v1.2.3 From 72251fac062c0b4fe98670ec9e3db3f0702c50ae Mon Sep 17 00:00:00 2001 From: Mark Menzynski Date: Thu, 18 Jul 2019 10:07:39 +0200 Subject: drm/nouveau/gpio: fail if gpu external power is missing Currently, nouveau doesn't check if GPU is missing power. This patch makes nouveau fail when this happens on latest GPUs. It checks GPIO function 121 (External Power Emergency), which should detect power problems on GPU initialization. This can be disabled with nouveau.config=NvPowerChecks=1 Tested on TU104, GP106 and GF100. v3: * Add config override for disabling power checks Signed-off-by: Mark Menzynski Signed-off-by: Ben Skeggs --- .../drm/nouveau/include/nvkm/subdev/bios/gpio.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c | 30 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h index 3f74b2726cf2..d036cdc45201 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h @@ -7,6 +7,7 @@ enum dcb_gpio_func_name { DCB_GPIO_TVDAC0 = 0x0c, DCB_GPIO_TVDAC1 = 0x2d, DCB_GPIO_FAN_SENSE = 0x3d, + DCB_GPIO_EXT_POWER_LOW = 0x79, DCB_GPIO_LOGO_LED_PWM = 0x84, DCB_GPIO_UNUSED = 0xff, DCB_GPIO_VID0 = 0x04, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c index 1399d923d446..1337a110c0e3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c @@ -23,6 +23,7 @@ */ #include "priv.h" +#include #include static int @@ -182,12 +183,41 @@ static const struct dmi_system_id gpio_reset_ids[] = { { } }; +static enum dcb_gpio_func_name power_checks[] = { + DCB_GPIO_EXT_POWER_LOW, +}; + static int nvkm_gpio_init(struct nvkm_subdev *subdev) { struct nvkm_gpio *gpio = nvkm_gpio(subdev); + struct dcb_gpio_func func; + int ret; + int i; + if (dmi_check_system(gpio_reset_ids)) nvkm_gpio_reset(gpio, DCB_GPIO_UNUSED); + + if (nvkm_boolopt(subdev->device->cfgopt, "NvPowerChecks", true)) { + for (i = 0; i < ARRAY_SIZE(power_checks); ++i) { + ret = nvkm_gpio_find(gpio, 0, power_checks[i], + DCB_GPIO_UNUSED, &func); + if (ret) + continue; + + ret = nvkm_gpio_get(gpio, 0, func.func, func.line); + if (!ret) + continue; + + nvkm_error(&gpio->subdev, + "GPU is missing power, check its power " + "cables. Boot with " + "nouveau.config=NvPowerChecks=0 to " + "disable.\n"); + return -EINVAL; + } + } + return 0; } -- cgit v1.2.3 From 940794b3dd343ba86a4c50f7e6db285c0a9c8776 Mon Sep 17 00:00:00 2001 From: Mark Menzynski Date: Thu, 18 Jul 2019 10:07:40 +0200 Subject: drm/nouveau/gpio: check the gpio function 16 in the power check as well Added GPIO is "Thermal and External Power Detect". It's uncertain if this GPIO is set on GPU initialization or only if a change is detected by the GPU at runtime. This GPIO can be found in Rankine and Curie and rarely on Tesla GPUs VBIOS. Untested, wrote according to documentation. Signed-off-by: Mark Menzynski Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h index d036cdc45201..f454bbd29a7a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h @@ -5,6 +5,7 @@ enum dcb_gpio_func_name { DCB_GPIO_PANEL_POWER = 0x01, DCB_GPIO_FAN = 0x09, DCB_GPIO_TVDAC0 = 0x0c, + DCB_GPIO_THERM_EXT_POWER_EVENT = 0x10, DCB_GPIO_TVDAC1 = 0x2d, DCB_GPIO_FAN_SENSE = 0x3d, DCB_GPIO_EXT_POWER_LOW = 0x79, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c index 1337a110c0e3..2aa809ce7ff3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c @@ -184,6 +184,7 @@ static const struct dmi_system_id gpio_reset_ids[] = { }; static enum dcb_gpio_func_name power_checks[] = { + DCB_GPIO_THERM_EXT_POWER_EVENT, DCB_GPIO_EXT_POWER_LOW, }; -- cgit v1.2.3 From 3c978f73959c295ac737b917795926534a7aea01 Mon Sep 17 00:00:00 2001 From: Mark Menzynski Date: Thu, 18 Jul 2019 10:07:41 +0200 Subject: drm/nouveau/gpio: check function 76 in the power check as well Added GPIO is "Power Alert". It's uncertain if this GPIO is set on GPU initialization or only if a change is detected by the GPU at runtime. This GPIO can be found on Tesla and sometimes on Fermi GPUs. Untested, wrote according to documentation. Signed-off-by: Mark Menzynski Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h index f454bbd29a7a..3f785f29dfac 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h @@ -8,6 +8,7 @@ enum dcb_gpio_func_name { DCB_GPIO_THERM_EXT_POWER_EVENT = 0x10, DCB_GPIO_TVDAC1 = 0x2d, DCB_GPIO_FAN_SENSE = 0x3d, + DCB_GPIO_POWER_ALERT = 0x4c, DCB_GPIO_EXT_POWER_LOW = 0x79, DCB_GPIO_LOGO_LED_PWM = 0x84, DCB_GPIO_UNUSED = 0xff, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c index 2aa809ce7ff3..914276410ef8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c @@ -185,6 +185,7 @@ static const struct dmi_system_id gpio_reset_ids[] = { static enum dcb_gpio_func_name power_checks[] = { DCB_GPIO_THERM_EXT_POWER_EVENT, + DCB_GPIO_POWER_ALERT, DCB_GPIO_EXT_POWER_LOW, }; -- cgit v1.2.3 From a1af2afbd244089560794c260b2d4326a86e39b6 Mon Sep 17 00:00:00 2001 From: Mark Menzynski Date: Fri, 2 Aug 2019 11:21:00 +0200 Subject: drm/nouveau/volt: Fix for some cards having 0 maximum voltage Some, mostly Fermi, vbioses appear to have zero max voltage. That causes Nouveau to not parse voltage entries, thus users not being able to set higher clocks. When changing this value Nvidia driver still appeared to ignore it, and I wasn't able to find out why, thus the code is ignoring the value if it is zero. CC: Maarten Lankhorst Signed-off-by: Mark Menzynski Reviewed-by: Karol Herbst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c index 7143ea4611aa..33a9fb5ac558 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c @@ -96,6 +96,8 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, info->min = min(info->base, info->base + info->step * info->vidmask); info->max = nvbios_rd32(bios, volt + 0x0e); + if (!info->max) + info->max = max(info->base, info->base + info->step * info->vidmask); break; case 0x50: info->min = nvbios_rd32(bios, volt + 0x0a); -- cgit v1.2.3 From b568db62c5c46c8d859f1b9538495ea0fcbe7000 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 16 Sep 2019 16:19:26 +0200 Subject: drm/nouveau/bar/gm20b: Avoid BAR1 teardown during init Writing the 0x1704 (BUS_BAR1_BLOCK) register causes the GPU to probe the memory region at the programmed address. The result is an address decode error in the external memory controller because address 0, which is what is written to the register, is not designated as accessible to devices. Avoid triggering DMA from the GPU by removing teardown of the BAR1. Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c index 950bff1955ad..1ed6170891c4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c @@ -26,7 +26,6 @@ gm20b_bar_func = { .dtor = gf100_bar_dtor, .oneinit = gf100_bar_oneinit, .bar1.init = gf100_bar_bar1_init, - .bar1.fini = gf100_bar_bar1_fini, .bar1.wait = gm107_bar_bar1_wait, .bar1.vmm = gf100_bar_bar1_vmm, .flush = g84_bar_flush, -- cgit v1.2.3