[Nouveau] [PATCH 14/14] drm/nouveau/therm: Rework nouveau_therm_create()
Emil Velikov
emil.l.velikov at gmail.com
Sun May 20 16:15:03 PDT 2012
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
More information about the Nouveau
mailing list