diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/core/core/object.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/subdev/therm.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/base.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/ic.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c | 67 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/temp.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_pm.c | 44 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 4 |
9 files changed, 117 insertions, 60 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c index 0daab62ea14c..3b2e7b6304d3 100644 --- a/drivers/gpu/drm/nouveau/core/core/object.c +++ b/drivers/gpu/drm/nouveau/core/core/object.c | |||
@@ -278,7 +278,6 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle) | |||
278 | struct nouveau_object *parent = NULL; | 278 | struct nouveau_object *parent = NULL; |
279 | struct nouveau_object *namedb = NULL; | 279 | struct nouveau_object *namedb = NULL; |
280 | struct nouveau_handle *handle = NULL; | 280 | struct nouveau_handle *handle = NULL; |
281 | int ret = -EINVAL; | ||
282 | 281 | ||
283 | parent = nouveau_handle_ref(client, _parent); | 282 | parent = nouveau_handle_ref(client, _parent); |
284 | if (!parent) | 283 | if (!parent) |
@@ -295,7 +294,7 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle) | |||
295 | } | 294 | } |
296 | 295 | ||
297 | nouveau_object_ref(NULL, &parent); | 296 | nouveau_object_ref(NULL, &parent); |
298 | return ret; | 297 | return handle ? 0 : -EINVAL; |
299 | } | 298 | } |
300 | 299 | ||
301 | int | 300 | int |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h index 6b17b614629f..0b20fc0d19c1 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <core/device.h> | 4 | #include <core/device.h> |
5 | #include <core/subdev.h> | 5 | #include <core/subdev.h> |
6 | 6 | ||
7 | enum nouveau_therm_mode { | 7 | enum nouveau_therm_fan_mode { |
8 | NOUVEAU_THERM_CTRL_NONE = 0, | 8 | NOUVEAU_THERM_CTRL_NONE = 0, |
9 | NOUVEAU_THERM_CTRL_MANUAL = 1, | 9 | NOUVEAU_THERM_CTRL_MANUAL = 1, |
10 | NOUVEAU_THERM_CTRL_AUTO = 2, | 10 | NOUVEAU_THERM_CTRL_AUTO = 2, |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c index f794dc89a3b2..a00a5a76e2d6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c | |||
@@ -134,7 +134,7 @@ nouveau_therm_alarm(struct nouveau_alarm *alarm) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | int | 136 | int |
137 | nouveau_therm_mode(struct nouveau_therm *therm, int mode) | 137 | nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode) |
138 | { | 138 | { |
139 | struct nouveau_therm_priv *priv = (void *)therm; | 139 | struct nouveau_therm_priv *priv = (void *)therm; |
140 | struct nouveau_device *device = nv_device(therm); | 140 | struct nouveau_device *device = nv_device(therm); |
@@ -149,10 +149,15 @@ nouveau_therm_mode(struct nouveau_therm *therm, int mode) | |||
149 | (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0)) | 149 | (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0)) |
150 | return -EINVAL; | 150 | return -EINVAL; |
151 | 151 | ||
152 | /* do not allow automatic fan management if the thermal sensor is | ||
153 | * not available */ | ||
154 | if (priv->mode == 2 && therm->temp_get(therm) < 0) | ||
155 | return -EINVAL; | ||
156 | |||
152 | if (priv->mode == mode) | 157 | if (priv->mode == mode) |
153 | return 0; | 158 | return 0; |
154 | 159 | ||
155 | nv_info(therm, "Thermal management: %s\n", name[mode]); | 160 | nv_info(therm, "fan management: %s\n", name[mode]); |
156 | nouveau_therm_update(therm, mode); | 161 | nouveau_therm_update(therm, mode); |
157 | return 0; | 162 | return 0; |
158 | } | 163 | } |
@@ -213,7 +218,7 @@ nouveau_therm_attr_set(struct nouveau_therm *therm, | |||
213 | priv->fan->bios.max_duty = value; | 218 | priv->fan->bios.max_duty = value; |
214 | return 0; | 219 | return 0; |
215 | case NOUVEAU_THERM_ATTR_FAN_MODE: | 220 | case NOUVEAU_THERM_ATTR_FAN_MODE: |
216 | return nouveau_therm_mode(therm, value); | 221 | return nouveau_therm_fan_mode(therm, value); |
217 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: | 222 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: |
218 | priv->bios_sensor.thrs_fan_boost.temp = value; | 223 | priv->bios_sensor.thrs_fan_boost.temp = value; |
219 | priv->sensor.program_alarms(therm); | 224 | priv->sensor.program_alarms(therm); |
@@ -263,7 +268,7 @@ _nouveau_therm_init(struct nouveau_object *object) | |||
263 | return ret; | 268 | return ret; |
264 | 269 | ||
265 | if (priv->suspend >= 0) | 270 | if (priv->suspend >= 0) |
266 | nouveau_therm_mode(therm, priv->mode); | 271 | nouveau_therm_fan_mode(therm, priv->mode); |
267 | priv->sensor.program_alarms(therm); | 272 | priv->sensor.program_alarms(therm); |
268 | return 0; | 273 | return 0; |
269 | } | 274 | } |
@@ -313,11 +318,12 @@ nouveau_therm_create_(struct nouveau_object *parent, | |||
313 | int | 318 | int |
314 | nouveau_therm_preinit(struct nouveau_therm *therm) | 319 | nouveau_therm_preinit(struct nouveau_therm *therm) |
315 | { | 320 | { |
316 | nouveau_therm_ic_ctor(therm); | ||
317 | nouveau_therm_sensor_ctor(therm); | 321 | nouveau_therm_sensor_ctor(therm); |
322 | nouveau_therm_ic_ctor(therm); | ||
318 | nouveau_therm_fan_ctor(therm); | 323 | nouveau_therm_fan_ctor(therm); |
319 | 324 | ||
320 | nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE); | 325 | nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_NONE); |
326 | nouveau_therm_sensor_preinit(therm); | ||
321 | return 0; | 327 | return 0; |
322 | } | 328 | } |
323 | 329 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index e24090bac195..8b3adec5fbb1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c | |||
@@ -32,6 +32,7 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, | |||
32 | struct i2c_board_info *info) | 32 | struct i2c_board_info *info) |
33 | { | 33 | { |
34 | struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); | 34 | struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); |
35 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; | ||
35 | struct i2c_client *client; | 36 | struct i2c_client *client; |
36 | 37 | ||
37 | request_module("%s%s", I2C_MODULE_PREFIX, info->type); | 38 | request_module("%s%s", I2C_MODULE_PREFIX, info->type); |
@@ -46,8 +47,9 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, | |||
46 | } | 47 | } |
47 | 48 | ||
48 | nv_info(priv, | 49 | nv_info(priv, |
49 | "Found an %s at address 0x%x (controlled by lm_sensors)\n", | 50 | "Found an %s at address 0x%x (controlled by lm_sensors, " |
50 | info->type, info->addr); | 51 | "temp offset %+i C)\n", |
52 | info->type, info->addr, sensor->offset_constant); | ||
51 | priv->ic = client; | 53 | priv->ic = client; |
52 | 54 | ||
53 | return true; | 55 | return true; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c index 0f5363edb964..a70d1b7e397b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c | |||
@@ -29,54 +29,83 @@ struct nv40_therm_priv { | |||
29 | struct nouveau_therm_priv base; | 29 | struct nouveau_therm_priv base; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | enum nv40_sensor_style { INVALID_STYLE = -1, OLD_STYLE = 0, NEW_STYLE = 1 }; | ||
33 | |||
34 | static enum nv40_sensor_style | ||
35 | nv40_sensor_style(struct nouveau_therm *therm) | ||
36 | { | ||
37 | struct nouveau_device *device = nv_device(therm); | ||
38 | |||
39 | switch (device->chipset) { | ||
40 | case 0x43: | ||
41 | case 0x44: | ||
42 | case 0x4a: | ||
43 | case 0x47: | ||
44 | return OLD_STYLE; | ||
45 | |||
46 | case 0x46: | ||
47 | case 0x49: | ||
48 | case 0x4b: | ||
49 | case 0x4e: | ||
50 | case 0x4c: | ||
51 | case 0x67: | ||
52 | case 0x68: | ||
53 | case 0x63: | ||
54 | return NEW_STYLE; | ||
55 | default: | ||
56 | return INVALID_STYLE; | ||
57 | } | ||
58 | } | ||
59 | |||
32 | static int | 60 | static int |
33 | nv40_sensor_setup(struct nouveau_therm *therm) | 61 | nv40_sensor_setup(struct nouveau_therm *therm) |
34 | { | 62 | { |
35 | struct nouveau_device *device = nv_device(therm); | 63 | enum nv40_sensor_style style = nv40_sensor_style(therm); |
36 | 64 | ||
37 | /* enable ADC readout and disable the ALARM threshold */ | 65 | /* enable ADC readout and disable the ALARM threshold */ |
38 | if (device->chipset >= 0x46) { | 66 | if (style == NEW_STYLE) { |
39 | nv_mask(therm, 0x15b8, 0x80000000, 0); | 67 | nv_mask(therm, 0x15b8, 0x80000000, 0); |
40 | nv_wr32(therm, 0x15b0, 0x80003fff); | 68 | nv_wr32(therm, 0x15b0, 0x80003fff); |
41 | mdelay(10); /* wait for the temperature to stabilize */ | 69 | mdelay(20); /* wait for the temperature to stabilize */ |
42 | return nv_rd32(therm, 0x15b4) & 0x3fff; | 70 | return nv_rd32(therm, 0x15b4) & 0x3fff; |
43 | } else { | 71 | } else if (style == OLD_STYLE) { |
44 | nv_wr32(therm, 0x15b0, 0xff); | 72 | nv_wr32(therm, 0x15b0, 0xff); |
73 | mdelay(20); /* wait for the temperature to stabilize */ | ||
45 | return nv_rd32(therm, 0x15b4) & 0xff; | 74 | return nv_rd32(therm, 0x15b4) & 0xff; |
46 | } | 75 | } else |
76 | return -ENODEV; | ||
47 | } | 77 | } |
48 | 78 | ||
49 | static int | 79 | static int |
50 | nv40_temp_get(struct nouveau_therm *therm) | 80 | nv40_temp_get(struct nouveau_therm *therm) |
51 | { | 81 | { |
52 | struct nouveau_therm_priv *priv = (void *)therm; | 82 | struct nouveau_therm_priv *priv = (void *)therm; |
53 | struct nouveau_device *device = nv_device(therm); | ||
54 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; | 83 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; |
84 | enum nv40_sensor_style style = nv40_sensor_style(therm); | ||
55 | int core_temp; | 85 | int core_temp; |
56 | 86 | ||
57 | if (device->chipset >= 0x46) { | 87 | if (style == NEW_STYLE) { |
58 | nv_wr32(therm, 0x15b0, 0x80003fff); | 88 | nv_wr32(therm, 0x15b0, 0x80003fff); |
59 | core_temp = nv_rd32(therm, 0x15b4) & 0x3fff; | 89 | core_temp = nv_rd32(therm, 0x15b4) & 0x3fff; |
60 | } else { | 90 | } else if (style == OLD_STYLE) { |
61 | nv_wr32(therm, 0x15b0, 0xff); | 91 | nv_wr32(therm, 0x15b0, 0xff); |
62 | core_temp = nv_rd32(therm, 0x15b4) & 0xff; | 92 | core_temp = nv_rd32(therm, 0x15b4) & 0xff; |
63 | } | 93 | } else |
64 | 94 | return -ENODEV; | |
65 | /* Setup the sensor if the temperature is 0 */ | ||
66 | if (core_temp == 0) | ||
67 | core_temp = nv40_sensor_setup(therm); | ||
68 | 95 | ||
69 | if (sensor->slope_div == 0) | 96 | /* if the slope or the offset is unset, do no use the sensor */ |
70 | sensor->slope_div = 1; | 97 | if (!sensor->slope_div || !sensor->slope_mult || |
71 | if (sensor->offset_den == 0) | 98 | !sensor->offset_num || !sensor->offset_den) |
72 | sensor->offset_den = 1; | 99 | return -ENODEV; |
73 | if (sensor->slope_mult < 1) | ||
74 | sensor->slope_mult = 1; | ||
75 | 100 | ||
76 | core_temp = core_temp * sensor->slope_mult / sensor->slope_div; | 101 | core_temp = core_temp * sensor->slope_mult / sensor->slope_div; |
77 | core_temp = core_temp + sensor->offset_num / sensor->offset_den; | 102 | core_temp = core_temp + sensor->offset_num / sensor->offset_den; |
78 | core_temp = core_temp + sensor->offset_constant - 8; | 103 | core_temp = core_temp + sensor->offset_constant - 8; |
79 | 104 | ||
105 | /* reserve negative temperatures for errors */ | ||
106 | if (core_temp < 0) | ||
107 | core_temp = 0; | ||
108 | |||
80 | return core_temp; | 109 | return core_temp; |
81 | } | 110 | } |
82 | 111 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index 06b98706b3fc..438d9824b774 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | |||
@@ -102,7 +102,7 @@ struct nouveau_therm_priv { | |||
102 | struct i2c_client *ic; | 102 | struct i2c_client *ic; |
103 | }; | 103 | }; |
104 | 104 | ||
105 | int nouveau_therm_mode(struct nouveau_therm *therm, int mode); | 105 | int nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode); |
106 | int nouveau_therm_attr_get(struct nouveau_therm *therm, | 106 | int nouveau_therm_attr_get(struct nouveau_therm *therm, |
107 | enum nouveau_therm_attr_type type); | 107 | enum nouveau_therm_attr_type type); |
108 | int nouveau_therm_attr_set(struct nouveau_therm *therm, | 108 | int nouveau_therm_attr_set(struct nouveau_therm *therm, |
@@ -122,6 +122,7 @@ int nouveau_therm_fan_sense(struct nouveau_therm *therm); | |||
122 | 122 | ||
123 | int nouveau_therm_preinit(struct nouveau_therm *); | 123 | int nouveau_therm_preinit(struct nouveau_therm *); |
124 | 124 | ||
125 | void nouveau_therm_sensor_preinit(struct nouveau_therm *); | ||
125 | void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, | 126 | void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, |
126 | enum nouveau_therm_thrs thrs, | 127 | enum nouveau_therm_thrs thrs, |
127 | enum nouveau_therm_thrs_state st); | 128 | enum nouveau_therm_thrs_state st); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c index b37624af8297..470f6a47b656 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c | |||
@@ -34,10 +34,6 @@ nouveau_therm_temp_set_defaults(struct nouveau_therm *therm) | |||
34 | { | 34 | { |
35 | struct nouveau_therm_priv *priv = (void *)therm; | 35 | struct nouveau_therm_priv *priv = (void *)therm; |
36 | 36 | ||
37 | priv->bios_sensor.slope_mult = 1; | ||
38 | priv->bios_sensor.slope_div = 1; | ||
39 | priv->bios_sensor.offset_num = 0; | ||
40 | priv->bios_sensor.offset_den = 1; | ||
41 | priv->bios_sensor.offset_constant = 0; | 37 | priv->bios_sensor.offset_constant = 0; |
42 | 38 | ||
43 | priv->bios_sensor.thrs_fan_boost.temp = 90; | 39 | priv->bios_sensor.thrs_fan_boost.temp = 90; |
@@ -60,11 +56,6 @@ nouveau_therm_temp_safety_checks(struct nouveau_therm *therm) | |||
60 | struct nouveau_therm_priv *priv = (void *)therm; | 56 | struct nouveau_therm_priv *priv = (void *)therm; |
61 | struct nvbios_therm_sensor *s = &priv->bios_sensor; | 57 | struct nvbios_therm_sensor *s = &priv->bios_sensor; |
62 | 58 | ||
63 | if (!priv->bios_sensor.slope_div) | ||
64 | priv->bios_sensor.slope_div = 1; | ||
65 | if (!priv->bios_sensor.offset_den) | ||
66 | priv->bios_sensor.offset_den = 1; | ||
67 | |||
68 | /* enforce a minimum hysteresis on thresholds */ | 59 | /* enforce a minimum hysteresis on thresholds */ |
69 | s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2); | 60 | s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2); |
70 | s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2); | 61 | s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2); |
@@ -106,16 +97,16 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm, | |||
106 | const char *thresolds[] = { | 97 | const char *thresolds[] = { |
107 | "fanboost", "downclock", "critical", "shutdown" | 98 | "fanboost", "downclock", "critical", "shutdown" |
108 | }; | 99 | }; |
109 | uint8_t temperature = therm->temp_get(therm); | 100 | int temperature = therm->temp_get(therm); |
110 | 101 | ||
111 | if (thrs < 0 || thrs > 3) | 102 | if (thrs < 0 || thrs > 3) |
112 | return; | 103 | return; |
113 | 104 | ||
114 | if (dir == NOUVEAU_THERM_THRS_FALLING) | 105 | if (dir == NOUVEAU_THERM_THRS_FALLING) |
115 | nv_info(therm, "temperature (%u C) went below the '%s' threshold\n", | 106 | nv_info(therm, "temperature (%i C) went below the '%s' threshold\n", |
116 | temperature, thresolds[thrs]); | 107 | temperature, thresolds[thrs]); |
117 | else | 108 | else |
118 | nv_info(therm, "temperature (%u C) hit the '%s' threshold\n", | 109 | nv_info(therm, "temperature (%i C) hit the '%s' threshold\n", |
119 | temperature, thresolds[thrs]); | 110 | temperature, thresolds[thrs]); |
120 | 111 | ||
121 | active = (dir == NOUVEAU_THERM_THRS_RISING); | 112 | active = (dir == NOUVEAU_THERM_THRS_RISING); |
@@ -123,7 +114,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm, | |||
123 | case NOUVEAU_THERM_THRS_FANBOOST: | 114 | case NOUVEAU_THERM_THRS_FANBOOST: |
124 | if (active) { | 115 | if (active) { |
125 | nouveau_therm_fan_set(therm, true, 100); | 116 | nouveau_therm_fan_set(therm, true, 100); |
126 | nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO); | 117 | nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_AUTO); |
127 | } | 118 | } |
128 | break; | 119 | break; |
129 | case NOUVEAU_THERM_THRS_DOWNCLOCK: | 120 | case NOUVEAU_THERM_THRS_DOWNCLOCK: |
@@ -202,7 +193,7 @@ alarm_timer_callback(struct nouveau_alarm *alarm) | |||
202 | NOUVEAU_THERM_THRS_SHUTDOWN); | 193 | NOUVEAU_THERM_THRS_SHUTDOWN); |
203 | 194 | ||
204 | /* schedule the next poll in one second */ | 195 | /* schedule the next poll in one second */ |
205 | if (list_empty(&alarm->head)) | 196 | if (therm->temp_get(therm) >= 0 && list_empty(&alarm->head)) |
206 | ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm); | 197 | ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm); |
207 | 198 | ||
208 | spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); | 199 | spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); |
@@ -225,6 +216,17 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm) | |||
225 | alarm_timer_callback(&priv->sensor.therm_poll_alarm); | 216 | alarm_timer_callback(&priv->sensor.therm_poll_alarm); |
226 | } | 217 | } |
227 | 218 | ||
219 | void | ||
220 | nouveau_therm_sensor_preinit(struct nouveau_therm *therm) | ||
221 | { | ||
222 | const char *sensor_avail = "yes"; | ||
223 | |||
224 | if (therm->temp_get(therm) < 0) | ||
225 | sensor_avail = "no"; | ||
226 | |||
227 | nv_info(therm, "internal sensor: %s\n", sensor_avail); | ||
228 | } | ||
229 | |||
228 | int | 230 | int |
229 | nouveau_therm_sensor_ctor(struct nouveau_therm *therm) | 231 | nouveau_therm_sensor_ctor(struct nouveau_therm *therm) |
230 | { | 232 | { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index bb54098c6d97..936b442a6ab7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c | |||
@@ -402,8 +402,12 @@ nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) | |||
402 | struct drm_device *dev = dev_get_drvdata(d); | 402 | struct drm_device *dev = dev_get_drvdata(d); |
403 | struct nouveau_drm *drm = nouveau_drm(dev); | 403 | struct nouveau_drm *drm = nouveau_drm(dev); |
404 | struct nouveau_therm *therm = nouveau_therm(drm->device); | 404 | struct nouveau_therm *therm = nouveau_therm(drm->device); |
405 | int temp = therm->temp_get(therm); | ||
405 | 406 | ||
406 | return snprintf(buf, PAGE_SIZE, "%d\n", therm->temp_get(therm) * 1000); | 407 | if (temp < 0) |
408 | return temp; | ||
409 | |||
410 | return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000); | ||
407 | } | 411 | } |
408 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, | 412 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, |
409 | NULL, 0); | 413 | NULL, 0); |
@@ -871,7 +875,12 @@ static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR, | |||
871 | nouveau_hwmon_get_pwm1_max, | 875 | nouveau_hwmon_get_pwm1_max, |
872 | nouveau_hwmon_set_pwm1_max, 0); | 876 | nouveau_hwmon_set_pwm1_max, 0); |
873 | 877 | ||
874 | static struct attribute *hwmon_attributes[] = { | 878 | static struct attribute *hwmon_default_attributes[] = { |
879 | &sensor_dev_attr_name.dev_attr.attr, | ||
880 | &sensor_dev_attr_update_rate.dev_attr.attr, | ||
881 | NULL | ||
882 | }; | ||
883 | static struct attribute *hwmon_temp_attributes[] = { | ||
875 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 884 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
876 | &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr, | 885 | &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr, |
877 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, | 886 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, |
@@ -882,8 +891,6 @@ static struct attribute *hwmon_attributes[] = { | |||
882 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, | 891 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, |
883 | &sensor_dev_attr_temp1_emergency.dev_attr.attr, | 892 | &sensor_dev_attr_temp1_emergency.dev_attr.attr, |
884 | &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, | 893 | &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, |
885 | &sensor_dev_attr_name.dev_attr.attr, | ||
886 | &sensor_dev_attr_update_rate.dev_attr.attr, | ||
887 | NULL | 894 | NULL |
888 | }; | 895 | }; |
889 | static struct attribute *hwmon_fan_rpm_attributes[] = { | 896 | static struct attribute *hwmon_fan_rpm_attributes[] = { |
@@ -898,8 +905,11 @@ static struct attribute *hwmon_pwm_fan_attributes[] = { | |||
898 | NULL | 905 | NULL |
899 | }; | 906 | }; |
900 | 907 | ||
901 | static const struct attribute_group hwmon_attrgroup = { | 908 | static const struct attribute_group hwmon_default_attrgroup = { |
902 | .attrs = hwmon_attributes, | 909 | .attrs = hwmon_default_attributes, |
910 | }; | ||
911 | static const struct attribute_group hwmon_temp_attrgroup = { | ||
912 | .attrs = hwmon_temp_attributes, | ||
903 | }; | 913 | }; |
904 | static const struct attribute_group hwmon_fan_rpm_attrgroup = { | 914 | static const struct attribute_group hwmon_fan_rpm_attrgroup = { |
905 | .attrs = hwmon_fan_rpm_attributes, | 915 | .attrs = hwmon_fan_rpm_attributes, |
@@ -931,13 +941,22 @@ nouveau_hwmon_init(struct drm_device *dev) | |||
931 | } | 941 | } |
932 | dev_set_drvdata(hwmon_dev, dev); | 942 | dev_set_drvdata(hwmon_dev, dev); |
933 | 943 | ||
934 | /* default sysfs entries */ | 944 | /* set the default attributes */ |
935 | ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_attrgroup); | 945 | ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup); |
936 | if (ret) { | 946 | if (ret) { |
937 | if (ret) | 947 | if (ret) |
938 | goto error; | 948 | goto error; |
939 | } | 949 | } |
940 | 950 | ||
951 | /* if the card has a working thermal sensor */ | ||
952 | if (therm->temp_get(therm) >= 0) { | ||
953 | ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup); | ||
954 | if (ret) { | ||
955 | if (ret) | ||
956 | goto error; | ||
957 | } | ||
958 | } | ||
959 | |||
941 | /* if the card has a pwm fan */ | 960 | /* if the card has a pwm fan */ |
942 | /*XXX: incorrect, need better detection for this, some boards have | 961 | /*XXX: incorrect, need better detection for this, some boards have |
943 | * the gpio entries for pwm fan control even when there's no | 962 | * the gpio entries for pwm fan control even when there's no |
@@ -979,11 +998,10 @@ nouveau_hwmon_fini(struct drm_device *dev) | |||
979 | struct nouveau_pm *pm = nouveau_pm(dev); | 998 | struct nouveau_pm *pm = nouveau_pm(dev); |
980 | 999 | ||
981 | if (pm->hwmon) { | 1000 | if (pm->hwmon) { |
982 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); | 1001 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_default_attrgroup); |
983 | sysfs_remove_group(&pm->hwmon->kobj, | 1002 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_temp_attrgroup); |
984 | &hwmon_pwm_fan_attrgroup); | 1003 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_pwm_fan_attrgroup); |
985 | sysfs_remove_group(&pm->hwmon->kobj, | 1004 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_fan_rpm_attrgroup); |
986 | &hwmon_fan_rpm_attrgroup); | ||
987 | 1005 | ||
988 | hwmon_device_unregister(pm->hwmon); | 1006 | hwmon_device_unregister(pm->hwmon); |
989 | } | 1007 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 2db57990f65c..7f0e6c3f37d1 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -524,6 +524,8 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
524 | swap_interval <<= 4; | 524 | swap_interval <<= 4; |
525 | if (swap_interval == 0) | 525 | if (swap_interval == 0) |
526 | swap_interval |= 0x100; | 526 | swap_interval |= 0x100; |
527 | if (chan == NULL) | ||
528 | evo_sync(crtc->dev); | ||
527 | 529 | ||
528 | push = evo_wait(sync, 128); | 530 | push = evo_wait(sync, 128); |
529 | if (unlikely(push == NULL)) | 531 | if (unlikely(push == NULL)) |
@@ -586,8 +588,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
586 | sync->addr ^= 0x10; | 588 | sync->addr ^= 0x10; |
587 | sync->data++; | 589 | sync->data++; |
588 | FIRE_RING (chan); | 590 | FIRE_RING (chan); |
589 | } else { | ||
590 | evo_sync(crtc->dev); | ||
591 | } | 591 | } |
592 | 592 | ||
593 | /* queue the flip */ | 593 | /* queue the flip */ |