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
Reasonably Related 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