Hello all, this series includes a wide range of fixes - from a few month's old one-liners from Andreas Heider regarding vga_switcheroo, via a null pointer dereference and double memory allocation, to a buffer overflow. Please review and comment --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 3 ++- drivers/gpu/drm/nouveau/nouveau_device.c | 26 +++++++++++++++----------- drivers/gpu/drm/nouveau/nouveau_fb.h | 1 - drivers/gpu/drm/nouveau/nouveau_gpio.h | 3 --- drivers/gpu/drm/nouveau/nouveau_gpuobj.c | 12 ++++-------- drivers/gpu/drm/nouveau/nouveau_perf.c | 2 +- drivers/gpu/drm/nouveau/nouveau_pm.c | 6 +++--- drivers/gpu/drm/nouveau/nouveau_state.c | 2 ++ drivers/gpu/drm/nouveau/nouveau_therm.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- drivers/gpu/drm/nouveau/nv04_instmem.c | 3 +-- drivers/gpu/drm/nouveau/nv10_fb.c | 4 ---- drivers/gpu/drm/nouveau/nv10_gpio.c | 16 ++++++++-------- drivers/gpu/drm/nouveau/nv30_fb.c | 3 +-- drivers/gpu/drm/nouveau/nv40_fanpwm.c | 14 +++++++------- drivers/gpu/drm/nouveau/nv40_fb.c | 11 ++++------- drivers/gpu/drm/nouveau/nv50_bar.c | 2 -- drivers/gpu/drm/nouveau/nv50_fanpwm.c | 20 ++++++++++---------- drivers/gpu/drm/nouveau/nv50_gpio.c | 16 ++++++++-------- drivers/gpu/drm/nouveau/nv50_instmem.c | 10 +++------- drivers/gpu/drm/nouveau/nvc0_instmem.c | 10 +++------- drivers/gpu/drm/nouveau/nvd0_gpio.c | 16 ++++++++-------- 21 files changed, 129 insertions(+), 114 deletions(-)
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 01/14] drm/nouveau: Check dsm on switcheroo unregister
From: Andreas Heider <andreas at meetr.de> Currently vga_switcheroo_unregister_handler is called unconditionally when nouveau is unloaded, even when nouveau never registered a handler. This interferes with other switcheroo handlers, as vga_switcheroo doesn't check who called unregister_handler, but simply unregisters the current handler. This patch adds a check so unregister is only called if a handler was registered by nouveau before. Signed-off-by: Andreas Heider <andreas at meetr.de> --- v2: Rebased on top of master drivers/gpu/drm/nouveau/nouveau_acpi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 0156d83..38a85b3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -338,7 +338,8 @@ void nouveau_switcheroo_optimus_dsm(void) void nouveau_unregister_dsm_handler(void) { - vga_switcheroo_unregister_handler(); + if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected) + vga_switcheroo_unregister_handler(); } /* retrieve the ROM in 4k blocks */ -- 1.7.10.2
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 02/14] drm/nouveau: Unregister switcheroo client on exit
From: Andreas Heider <andreas at meetr.de> Currently nouveau only registers as a vga_switcheroo client, but never unregisters. This patch adds the necessary unregister calls. Signed-off-by: Andreas Heider <andreas at meetr.de> --- v2: Rebased on top of master drivers/gpu/drm/nouveau/nouveau_state.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 1a70d07..b84db66 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -344,6 +344,7 @@ out_device_init: out_display_early: engine->display.late_takedown(ndev); out: + vga_switcheroo_unregister_client(dev->pdev); vga_client_register(dev->pdev, NULL, NULL, NULL); return ret; } @@ -387,6 +388,7 @@ static void nouveau_card_takedown(struct nouveau_device *ndev) nouveau_irq_fini(ndev); + vga_switcheroo_unregister_client(dev->pdev); vga_client_register(dev->pdev, NULL, NULL, NULL); } -- 1.7.10.2
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 03/14] drm/nouveau/device: Simplify init, fini fuction
Removes unnecessary goto statement fini subdevices before destroying them Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nouveau_device.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_device.c b/drivers/gpu/drm/nouveau/nouveau_device.c index 9cc21d1..38ed71a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_device.c +++ b/drivers/gpu/drm/nouveau/nouveau_device.c @@ -55,13 +55,13 @@ nouveau_device_init(struct nouveau_device *ndev) for (i = 0; i < NVDEV_SUBDEV_NR; i++) { ret = nouveau_subdev_init(ndev, i, 0); - if (ret) - goto error; + if (ret) { + for (--i; i >= 0; i--) + nouveau_subdev_fini(ndev, i, false); + break; + } } -error: - for (--i; ret && i >= 0; i--) - nouveau_subdev_fini(ndev, i, false); return ret; } @@ -72,13 +72,13 @@ nouveau_device_fini(struct nouveau_device *ndev, bool suspend) for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) { ret = nouveau_subdev_fini(ndev, i, suspend); - if (ret) - goto error; + if (ret) { + for (--i; i >= 0; i--) + nouveau_subdev_init(ndev, i, 0); + break; + } } -error: - for (--i; ret && i >= 0; i--) - nouveau_subdev_init(ndev, i, 0); return ret; } @@ -96,6 +96,7 @@ nouveau_device_create(struct nouveau_device *ndev) { int disable = nouveau_noaccel; int ret = 0; + int i; /* mask out any engines that are known not to work as they should, * these can be overridden by the user @@ -553,7 +554,10 @@ nouveau_device_create(struct nouveau_device *ndev) break; } - if (ret) + if (ret) { + for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) + nouveau_subdev_fini(ndev, i, false); nouveau_device_destroy(ndev); + } return ret; } -- 1.7.10.2
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 04/14] drm/nouveau: Remove non-relevant function prototypes
Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nouveau_fb.h | 1 - drivers/gpu/drm/nouveau/nouveau_gpio.h | 3 --- 2 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h index b804fd0..5f62743 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fb.h +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h @@ -37,7 +37,6 @@ void nv30_fb_free_tile_region(struct nouveau_fb *, int i); int nv40_fb_create(struct nouveau_device *, int); int nv50_fb_create(struct nouveau_device *, int); -void nv50_fb_vram_fini(struct nouveau_fb *); void nv50_fb_vram_del(struct nouveau_fb *, struct nouveau_mem **); void nv50_fb_vm_trap(struct nouveau_device *, int display); diff --git a/drivers/gpu/drm/nouveau/nouveau_gpio.h b/drivers/gpu/drm/nouveau/nouveau_gpio.h index 1814c19..5bd66e8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gpio.h +++ b/drivers/gpu/drm/nouveau/nouveau_gpio.h @@ -53,9 +53,6 @@ struct gpio_func { /* nouveau_gpio.c */ int nouveau_gpio_create(struct nouveau_device *, int subdev); -void nouveau_gpio_destroy(struct nouveau_device *); -int nouveau_gpio_init(struct nouveau_device *); -void nouveau_gpio_fini(struct nouveau_device *); void nouveau_gpio_reset(struct nouveau_device *); int nouveau_gpio_drive(struct nouveau_device *, int idx, int line, int dir, int out); -- 1.7.10.2
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 05/14] drm/nouveau/gpuobj: Do not handle gpuobj_init during fail path in gpuobj_fini
This approach is already handled by the subdev system. Remove unneeded variable in the process Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nouveau_gpuobj.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_gpuobj.c b/drivers/gpu/drm/nouveau/nouveau_gpuobj.c index 2eed5c3..43a7cd2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gpuobj.c +++ b/drivers/gpu/drm/nouveau/nouveau_gpuobj.c @@ -757,7 +757,7 @@ nouveau_gpuobj_fini(struct nouveau_device *ndev, int subdev, bool suspend) { struct nouveau_gpuobj_priv *priv = nv_subdev(ndev, subdev); struct nouveau_gpuobj *gpuobj; - int i, ret = 0; + int i; if (suspend) { list_for_each_entry(gpuobj, &priv->list, list) { @@ -766,8 +766,7 @@ nouveau_gpuobj_fini(struct nouveau_device *ndev, int subdev, bool suspend) gpuobj->suspend = vmalloc(gpuobj->size); if (!gpuobj->suspend) { - ret = -ENOMEM; - goto error; + return -ENOMEM; } for (i = 0; i < gpuobj->size; i += 4) @@ -775,16 +774,13 @@ nouveau_gpuobj_fini(struct nouveau_device *ndev, int subdev, bool suspend) } } -error: - if (ret) - priv->base.init(ndev, subdev); - return ret; + return 0; } static void nouveau_gpuobj_destroy(struct nouveau_device *ndev, int subdev) { - struct nouveau_gpuobj_priv *priv = nv_subdev(ndev, NVDEV_SUBDEV_GPUOBJ); + struct nouveau_gpuobj_priv *priv = nv_subdev(ndev, subdev); struct nouveau_gpuobj_method *om, *tm; struct nouveau_gpuobj_class *oc, *tc; -- 1.7.10.2
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 06/14] drm/nouveau/instmem: Do not handle instmem_init during fail path in instmem_fini
This approach is already handled by the subdev system. Remove unneeded variable in the process Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nv50_instmem.c | 10 +++------- drivers/gpu/drm/nouveau/nvc0_instmem.c | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index f954e87..79e78d0 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -201,7 +201,7 @@ static int nv50_instmem_init(struct nouveau_device *ndev, int subdev) { struct nv50_instmem_priv *priv = nv_subdev(ndev, subdev); - int ret = 0, i; + int i; nv_wr32(ndev, 0x001700, priv->mem->offset >> 16); @@ -224,15 +224,11 @@ nv50_instmem_init(struct nouveau_device *ndev, int subdev) for (i = 0; i < 64 * 1024; i += 4) { if (nv_rd32(ndev, 0x705000 + i) != nv_ri32(ndev, i)) { NV_ERROR(ndev, "INSTMEM: readback failed\n"); - ret = -EIO; - goto error; + return -EIO; } } -error: - if (ret) - priv->base.base.fini(ndev, subdev, false); - return ret; + return 0; } int diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c index 2df078b..59e28f7 100644 --- a/drivers/gpu/drm/nouveau/nvc0_instmem.c +++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c @@ -107,7 +107,7 @@ static int nvc0_instmem_init(struct nouveau_device *ndev, int subdev) { struct nvc0_instmem_priv *priv = nv_subdev(ndev, subdev); - int ret = 0, i; + int i; nv_wr32(ndev, 0x001700, priv->mem->offset >> 16); @@ -128,15 +128,11 @@ nvc0_instmem_init(struct nouveau_device *ndev, int subdev) for (i = 0; i < 64 * 1024; i += 4) { if (nv_rd32(ndev, 0x702000 + i) != nv_ri32(ndev, i)) { NV_ERROR(ndev, "INSTMEM: readback failed\n"); - ret = -EIO; - goto error; + return -EIO; } } -error: - if (ret) - priv->base.base.fini(ndev, subdev, false); - return ret; + return 0; } int -- 1.7.10.2
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 07/14] drm/nouveau/volt: Purge volt->get and volt->set checks
Both functions are constantly present if the volt subdev is created Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nouveau_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index b6bde18..9dd34fe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -60,7 +60,7 @@ nouveau_pm_perflvl_aux(struct nouveau_device *ndev, struct nouveau_pm_level *per } } - if (pvolt && pvolt->set) { + if (pvolt) { if (perflvl->volt_min && b->volt_min > a->volt_min) { ret = pvolt->set(pvolt, perflvl->volt_min); if (ret) { @@ -234,7 +234,7 @@ nouveau_pm_perflvl_get(struct nouveau_device *ndev, struct nouveau_pm_level *per return ret; } - if (pvolt && pvolt->get) { + if (pvolt) { ret = pvolt->get(pvolt); if (ret > 0) { perflvl->volt_min = ret; -- 1.7.10.2
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 08/14] drm/nv50_bar: Remove duplicate assignments
Both variables are already set in nouveau_subdev_create() Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nv50_bar.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_bar.c b/drivers/gpu/drm/nouveau/nv50_bar.c index 0dc1895..6499a30 100644 --- a/drivers/gpu/drm/nouveau/nv50_bar.c +++ b/drivers/gpu/drm/nouveau/nv50_bar.c @@ -92,8 +92,6 @@ nv50_bar_create(struct nouveau_device *ndev, int subdev) if (ret) return ret; - priv->base.base.name = "BAR"; - priv->base.base.device = ndev; priv->base.base.destroy = nv50_bar_destroy; priv->base.base.init = nv50_bar_init; priv->base.map = nv50_bar_map; -- 1.7.10.2
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 09/14] drm/nv04_instmem: Remove duplicate assignment
The variable is already set in nouveau_subdev_create() Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nv04_instmem.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c index 362b23f..47d70fe 100644 --- a/drivers/gpu/drm/nouveau/nv04_instmem.c +++ b/drivers/gpu/drm/nouveau/nv04_instmem.c @@ -108,7 +108,6 @@ nv04_instmem_create(struct nouveau_device *ndev, int subdev) if (ret) return ret; - priv->base.base.device = ndev; priv->base.base.destroy = nv04_instmem_destroy; priv->base.get = nv04_instmem_get; priv->base.put = nv04_instmem_put; -- 1.7.10.2
Emil Velikov
2012-May-20 23:14 UTC
[Nouveau] [PATCH 10/14] drm/nv30_fb: Purge optional variable
Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nv30_fb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv30_fb.c b/drivers/gpu/drm/nouveau/nv30_fb.c index ce08f08..bc1c65b 100644 --- a/drivers/gpu/drm/nouveau/nv30_fb.c +++ b/drivers/gpu/drm/nouveau/nv30_fb.c @@ -113,7 +113,6 @@ nv30_fb_init(struct nouveau_device *ndev, int subdev) int nv30_fb_create(struct nouveau_device *ndev, int subdev) { - u32 mem_size = nv_rd32(ndev, 0x10020c); u32 pbus1218 = nv_rd32(ndev, 0x001218); struct nv30_fb_priv *priv; int ret; @@ -128,7 +127,7 @@ nv30_fb_create(struct nouveau_device *ndev, int subdev) case 0x00000200: ndev->vram_type = NV_MEM_TYPE_GDDR3; break; case 0x00000300: ndev->vram_type = NV_MEM_TYPE_GDDR2; break; } - ndev->vram_size = mem_size & 0xff000000; + ndev->vram_size = nv_rd32(ndev, 0x10020c) & 0xff000000; priv->base.base.destroy = nv10_fb_destroy; priv->base.base.init = nv30_fb_init; -- 1.7.10.2
Emil Velikov
2012-May-20 23:15 UTC
[Nouveau] [PATCH 11/14] drm/nv40/fb: Blend if statement within the switch
No functional change, just bike-shedding Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nv40_fb.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c index 879678b..4f2d436 100644 --- a/drivers/gpu/drm/nouveau/nv40_fb.c +++ b/drivers/gpu/drm/nouveau/nv40_fb.c @@ -107,13 +107,6 @@ nv40_fb_init(struct nouveau_device *ndev, int subdev) u32 tmp; int i; - if (ndev->chipset != 0x40 && ndev->chipset != 0x45) { - if (nv44_graph_class(ndev)) - nv44_fb_init_gart(ndev); - else - nv40_fb_init_gart(ndev); - } - switch (ndev->chipset) { case 0x40: case 0x45: @@ -121,6 +114,10 @@ nv40_fb_init(struct nouveau_device *ndev, int subdev) nv_wr32(ndev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15)); break; default: + if (nv44_graph_class(ndev)) + nv44_fb_init_gart(ndev); + else + nv40_fb_init_gart(ndev); break; } -- 1.7.10.2
Emil Velikov
2012-May-20 23:15 UTC
[Nouveau] [PATCH 12/14] drm/nv10/fb: Prevent double memory allocation
Appropriate memory is allocated in nouveau_subdev_create() Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nv10_fb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv10_fb.c b/drivers/gpu/drm/nouveau/nv10_fb.c index a886098..80b3e41 100644 --- a/drivers/gpu/drm/nouveau/nv10_fb.c +++ b/drivers/gpu/drm/nouveau/nv10_fb.c @@ -132,10 +132,6 @@ nv10_fb_create(struct nouveau_device *ndev, int subdev) ndev->vram_size = data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; } - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - priv->base.base.destroy = nv10_fb_destroy; priv->base.base.init = nv10_fb_init; priv->base.memtype_valid = nv04_fb_memtype_valid; -- 1.7.10.2
Emil Velikov
2012-May-20 23:15 UTC
[Nouveau] [PATCH 13/14] drm/nouveau/perf: Prevent buffer oveflow
If the vbios is corrupted it can indicate more performance entries than the ones statically allocated, causing overwriting of kernel memory Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nouveau_perf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index af03fb4..36a9ae3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -61,7 +61,7 @@ nouveau_perf_entry(struct nouveau_device *ndev, int idx, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { u8 *perf = nouveau_perf_table(ndev, ver); - if (perf) { + if (perf && idx < NOUVEAU_PM_MAX_LEVEL) { if (*ver >= 0x12 && *ver < 0x20 && idx < perf[2]) { *hdr = perf[3]; *cnt = 0; -- 1.7.10.2
Emil Velikov
2012-May-20 23:15 UTC
[Nouveau] [PATCH 14/14] drm/nouveau/therm: Rework nouveau_therm_create()
It contains a few changes mainly targeting the following * Therm table is present in BIT vbios * Parse the vbios table before hooking temp_get(), as it contains the therm sensor calibration data * Add dummy_therm_temp_get() function to prevent multiple null dereff's Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> --- drivers/gpu/drm/nouveau/nouveau_pm.c | 2 +- drivers/gpu/drm/nouveau/nouveau_therm.c | 63 ++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 9dd34fe..1b4422b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -693,7 +693,7 @@ nouveau_hwmon_init(struct nouveau_device *ndev) } /* if the card can read the fan rpm */ - if (nouveau_gpio_func_valid(ndev, DCB_GPIO_FAN_SENSE)) { + if (pfan && pfan->sense(pfan) >= 0) { ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_fan_rpm_attrgroup); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_therm.c b/drivers/gpu/drm/nouveau/nouveau_therm.c index acf81a9..91095be 100644 --- a/drivers/gpu/drm/nouveau/nouveau_therm.c +++ b/drivers/gpu/drm/nouveau/nouveau_therm.c @@ -30,6 +30,12 @@ #include "nouveau_pm.h" #include "nouveau_therm.h" +static inline int +dummy_therm_temp_get(struct nouveau_therm *ptherm) +{ + return 0; +} + static int nv40_sensor_setup(struct nouveau_therm *ptherm) { @@ -181,7 +187,7 @@ nouveau_therm_vbios_parse(struct nouveau_therm *ptherm, u8 *temp) temp = temp + headerlen; /* Read the entries from the table */ - for (i = 0; i < entries; i++) { + for (i = 0; i < entries; i++, temp += recordlen) { s16 value = ROM16(temp[1]); switch (temp[0]) { @@ -228,7 +234,6 @@ nouveau_therm_vbios_parse(struct nouveau_therm *ptherm, u8 *temp) ptherm->fan.pwm_freq = value; break; } - temp += recordlen; } nouveau_therm_safety_checks(ptherm); @@ -299,6 +304,12 @@ nouveau_therm_probe_i2c(struct nouveau_device *ndev) probe_monitoring_device, NV_I2C_DEFAULT(0)); } +static void +nouveau_ptherm_destroy(struct nouveau_device *ndev, int subdev) +{ +// XXX: Undo probe_monitoring_device +} + int nouveau_therm_create(struct nouveau_device *ndev, int subdev) { @@ -307,29 +318,53 @@ nouveau_therm_create(struct nouveau_device *ndev, int subdev) u8 *temp = NULL; int ret; - ret = nouveau_subdev_create(ndev, subdev, "THERM", "thermal", &ptherm); - if (ret) - return ret; + if (bios->type == NVBIOS_BIT) { + if (bit_table(ndev, 'P', &P)) + return 0; - if (ndev->chipset >= 0x40 && ndev->chipset < 0x84) - ptherm->temp_get = nv40_therm_temp_get; - else - if (ndev->chipset <= 0xd9) - ptherm->temp_get = nv84_therm_temp_get; - - if (bit_table(ndev, 'P', &P) == 0) { if (P.version == 1) temp = ROMPTR(ndev, P.data[12]); else if (P.version == 2) temp = ROMPTR(ndev, P.data[16]); - else + else { NV_WARN(ndev, "unknown temp for BIT P %d\n", P.version); + } + } else { + return 0; + } - nouveau_therm_vbios_parse(ptherm, temp); + if (!temp) { + NV_DEBUG(ndev, "temp table pointer invalid\n"); + return 0; } + ret = nouveau_subdev_create(ndev, subdev, "THERM", "thermal", &ptherm); + if (ret) + return ret; + + nouveau_therm_vbios_parse(ptherm, temp); nouveau_therm_probe_i2c(ndev); + ptherm->base.destroy = nouveau_ptherm_destroy; + switch (ndev->card_type) { + case NV_40: + case NV_50: + case NV_C0: + case NV_D0: + case NV_E0: + if (ndev->chipset < 0x84) { + ptherm->temp_get = nv40_therm_temp_get; + break; + } else + if (ndev->chipset <= 0xd9) { + ptherm->temp_get = nv84_therm_temp_get; + break; + } + default: + ptherm->temp_get = dummy_therm_temp_get; + break; + } + return nouveau_subdev_init(ndev, subdev, ret); } -- 1.7.10.2
On Mon, May 21, 2012 at 12:14:49AM +0100, Emil Velikov wrote:> Hello all, this series includes a wide range of fixes - from a few > month's old one-liners from Andreas Heider regarding vga_switcheroo, via a > null pointer dereference and double memory allocation, to a buffer overflow.Hey, Thanks for these! I've pulled most of them directly for the moment, comments on specific patches will follow. Cheers, Ben.> > Please review and comment > > --- > drivers/gpu/drm/nouveau/nouveau_acpi.c | 3 ++- > drivers/gpu/drm/nouveau/nouveau_device.c | 26 +++++++++++++++----------- > drivers/gpu/drm/nouveau/nouveau_fb.h | 1 - > drivers/gpu/drm/nouveau/nouveau_gpio.h | 3 --- > drivers/gpu/drm/nouveau/nouveau_gpuobj.c | 12 ++++-------- > drivers/gpu/drm/nouveau/nouveau_perf.c | 2 +- > drivers/gpu/drm/nouveau/nouveau_pm.c | 6 +++--- > drivers/gpu/drm/nouveau/nouveau_state.c | 2 ++ > drivers/gpu/drm/nouveau/nouveau_therm.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- > drivers/gpu/drm/nouveau/nv04_instmem.c | 3 +-- > drivers/gpu/drm/nouveau/nv10_fb.c | 4 ---- > drivers/gpu/drm/nouveau/nv10_gpio.c | 16 ++++++++-------- > drivers/gpu/drm/nouveau/nv30_fb.c | 3 +-- > drivers/gpu/drm/nouveau/nv40_fanpwm.c | 14 +++++++------- > drivers/gpu/drm/nouveau/nv40_fb.c | 11 ++++------- > drivers/gpu/drm/nouveau/nv50_bar.c | 2 -- > drivers/gpu/drm/nouveau/nv50_fanpwm.c | 20 ++++++++++---------- > drivers/gpu/drm/nouveau/nv50_gpio.c | 16 ++++++++-------- > drivers/gpu/drm/nouveau/nv50_instmem.c | 10 +++------- > drivers/gpu/drm/nouveau/nvc0_instmem.c | 10 +++------- > drivers/gpu/drm/nouveau/nvd0_gpio.c | 16 ++++++++-------- > 21 files changed, 129 insertions(+), 114 deletions(-) > > > _______________________________________________ > Nouveau mailing list > Nouveau at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/nouveau
Ben Skeggs
2012-May-21 06:27 UTC
[Nouveau] [PATCH 03/14] drm/nouveau/device: Simplify init, fini fuction
On Mon, May 21, 2012 at 12:14:52AM +0100, Emil Velikov wrote:> Removes unnecessary goto statementI dropped these changes from this patch for the moment, I might want them yet.> fini subdevices before destroying themI took this hunk, and reworded the commit message to match.> > Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com> > --- > drivers/gpu/drm/nouveau/nouveau_device.c | 26 +++++++++++++++----------- > 1 file changed, 15 insertions(+), 11 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nouveau_device.c b/drivers/gpu/drm/nouveau/nouveau_device.c > index 9cc21d1..38ed71a 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_device.c > +++ b/drivers/gpu/drm/nouveau/nouveau_device.c > @@ -55,13 +55,13 @@ nouveau_device_init(struct nouveau_device *ndev) > > for (i = 0; i < NVDEV_SUBDEV_NR; i++) { > ret = nouveau_subdev_init(ndev, i, 0); > - if (ret) > - goto error; > + if (ret) { > + for (--i; i >= 0; i--) > + nouveau_subdev_fini(ndev, i, false); > + break; > + } > } > > -error: > - for (--i; ret && i >= 0; i--) > - nouveau_subdev_fini(ndev, i, false); > return ret; > } > > @@ -72,13 +72,13 @@ nouveau_device_fini(struct nouveau_device *ndev, bool suspend) > > for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) { > ret = nouveau_subdev_fini(ndev, i, suspend); > - if (ret) > - goto error; > + if (ret) { > + for (--i; i >= 0; i--) > + nouveau_subdev_init(ndev, i, 0); > + break; > + } > } > > -error: > - for (--i; ret && i >= 0; i--) > - nouveau_subdev_init(ndev, i, 0); > return ret; > } > > @@ -96,6 +96,7 @@ nouveau_device_create(struct nouveau_device *ndev) > { > int disable = nouveau_noaccel; > int ret = 0; > + int i; > > /* mask out any engines that are known not to work as they should, > * these can be overridden by the user > @@ -553,7 +554,10 @@ nouveau_device_create(struct nouveau_device *ndev) > break; > } > > - if (ret) > + if (ret) { > + for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) > + nouveau_subdev_fini(ndev, i, false); > nouveau_device_destroy(ndev); > + } > return ret; > } > -- > 1.7.10.2 > > _______________________________________________ > Nouveau mailing list > Nouveau at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/nouveau
Seemingly Similar Threads
- [PATCH v2 4/4] drm/nouveau: gpu lockup recovery
- [PATCH 1/2] drm/nouveau/pm: Prepare for more GDDR5 MR values
- [PATCH] [RFC] drm/nouveau: bring back hdmi audio device after switcheroo power down
- [RFC] kvm tools: Implement multiple VQ for virtio-net
- [RFC] kvm tools: Implement multiple VQ for virtio-net