Commit cf9a625f authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-nouveau-fixes-3.9' of...

Merge branch 'drm-nouveau-fixes-3.9' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next

Lots of thermal fixes and fix a lockdep warning we've been seeing.

* 'drm-nouveau-fixes-3.9' of git://anongit.freedesktop.org/git/nouveau/linux-2.6:
  drm/nv50/kms: prevent lockdep false-positive in page flipping path
  drm/nouveau/core: fix return value of nouveau_object_del()
  drm/nouveau/hwmon: do not expose a buggy temperature if it is unavailable
  drm/nouveau/therm: display the availability of the internal sensor
  drm/nouveau/therm: disable temperature management if the sensor isn't readable
  drm/nouveau/therm: disable auto fan management if temperature is not available
  drm/nv40/therm: reserve negative temperatures for errors
  drm/nv40/therm: disable temperature reading if the bios misses some parameters
  drm/nouveau/therm-ic: the temperature is off by sensor_constant, warn the user
  drm/nouveau/therm: remove some confusion introduced by therm_mode
  drm/nouveau/therm: do not make assumptions on temperature
  drm/nv40/therm: increase the sensor's settling delay to 20ms
  drm/nv40/therm: improve selection between the old and the new style
parents 10b38669 f60b6e7a
...@@ -278,7 +278,6 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle) ...@@ -278,7 +278,6 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle)
struct nouveau_object *parent = NULL; struct nouveau_object *parent = NULL;
struct nouveau_object *namedb = NULL; struct nouveau_object *namedb = NULL;
struct nouveau_handle *handle = NULL; struct nouveau_handle *handle = NULL;
int ret = -EINVAL;
parent = nouveau_handle_ref(client, _parent); parent = nouveau_handle_ref(client, _parent);
if (!parent) if (!parent)
...@@ -295,7 +294,7 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle) ...@@ -295,7 +294,7 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle)
} }
nouveau_object_ref(NULL, &parent); nouveau_object_ref(NULL, &parent);
return ret; return handle ? 0 : -EINVAL;
} }
int int
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include <core/device.h> #include <core/device.h>
#include <core/subdev.h> #include <core/subdev.h>
enum nouveau_therm_mode { enum nouveau_therm_fan_mode {
NOUVEAU_THERM_CTRL_NONE = 0, NOUVEAU_THERM_CTRL_NONE = 0,
NOUVEAU_THERM_CTRL_MANUAL = 1, NOUVEAU_THERM_CTRL_MANUAL = 1,
NOUVEAU_THERM_CTRL_AUTO = 2, NOUVEAU_THERM_CTRL_AUTO = 2,
......
...@@ -134,7 +134,7 @@ nouveau_therm_alarm(struct nouveau_alarm *alarm) ...@@ -134,7 +134,7 @@ nouveau_therm_alarm(struct nouveau_alarm *alarm)
} }
int int
nouveau_therm_mode(struct nouveau_therm *therm, int mode) nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode)
{ {
struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_therm_priv *priv = (void *)therm;
struct nouveau_device *device = nv_device(therm); struct nouveau_device *device = nv_device(therm);
...@@ -149,10 +149,15 @@ nouveau_therm_mode(struct nouveau_therm *therm, int mode) ...@@ -149,10 +149,15 @@ nouveau_therm_mode(struct nouveau_therm *therm, int mode)
(mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0)) (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0))
return -EINVAL; return -EINVAL;
/* do not allow automatic fan management if the thermal sensor is
* not available */
if (priv->mode == 2 && therm->temp_get(therm) < 0)
return -EINVAL;
if (priv->mode == mode) if (priv->mode == mode)
return 0; return 0;
nv_info(therm, "Thermal management: %s\n", name[mode]); nv_info(therm, "fan management: %s\n", name[mode]);
nouveau_therm_update(therm, mode); nouveau_therm_update(therm, mode);
return 0; return 0;
} }
...@@ -213,7 +218,7 @@ nouveau_therm_attr_set(struct nouveau_therm *therm, ...@@ -213,7 +218,7 @@ nouveau_therm_attr_set(struct nouveau_therm *therm,
priv->fan->bios.max_duty = value; priv->fan->bios.max_duty = value;
return 0; return 0;
case NOUVEAU_THERM_ATTR_FAN_MODE: case NOUVEAU_THERM_ATTR_FAN_MODE:
return nouveau_therm_mode(therm, value); return nouveau_therm_fan_mode(therm, value);
case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST:
priv->bios_sensor.thrs_fan_boost.temp = value; priv->bios_sensor.thrs_fan_boost.temp = value;
priv->sensor.program_alarms(therm); priv->sensor.program_alarms(therm);
...@@ -263,7 +268,7 @@ _nouveau_therm_init(struct nouveau_object *object) ...@@ -263,7 +268,7 @@ _nouveau_therm_init(struct nouveau_object *object)
return ret; return ret;
if (priv->suspend >= 0) if (priv->suspend >= 0)
nouveau_therm_mode(therm, priv->mode); nouveau_therm_fan_mode(therm, priv->mode);
priv->sensor.program_alarms(therm); priv->sensor.program_alarms(therm);
return 0; return 0;
} }
...@@ -313,11 +318,12 @@ nouveau_therm_create_(struct nouveau_object *parent, ...@@ -313,11 +318,12 @@ nouveau_therm_create_(struct nouveau_object *parent,
int int
nouveau_therm_preinit(struct nouveau_therm *therm) nouveau_therm_preinit(struct nouveau_therm *therm)
{ {
nouveau_therm_ic_ctor(therm);
nouveau_therm_sensor_ctor(therm); nouveau_therm_sensor_ctor(therm);
nouveau_therm_ic_ctor(therm);
nouveau_therm_fan_ctor(therm); nouveau_therm_fan_ctor(therm);
nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE); nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_NONE);
nouveau_therm_sensor_preinit(therm);
return 0; return 0;
} }
......
...@@ -32,6 +32,7 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, ...@@ -32,6 +32,7 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c);
struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
struct i2c_client *client; struct i2c_client *client;
request_module("%s%s", I2C_MODULE_PREFIX, info->type); request_module("%s%s", I2C_MODULE_PREFIX, info->type);
...@@ -46,8 +47,9 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, ...@@ -46,8 +47,9 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,
} }
nv_info(priv, nv_info(priv,
"Found an %s at address 0x%x (controlled by lm_sensors)\n", "Found an %s at address 0x%x (controlled by lm_sensors, "
info->type, info->addr); "temp offset %+i C)\n",
info->type, info->addr, sensor->offset_constant);
priv->ic = client; priv->ic = client;
return true; return true;
......
...@@ -29,54 +29,83 @@ struct nv40_therm_priv { ...@@ -29,54 +29,83 @@ struct nv40_therm_priv {
struct nouveau_therm_priv base; struct nouveau_therm_priv base;
}; };
enum nv40_sensor_style { INVALID_STYLE = -1, OLD_STYLE = 0, NEW_STYLE = 1 };
static enum nv40_sensor_style
nv40_sensor_style(struct nouveau_therm *therm)
{
struct nouveau_device *device = nv_device(therm);
switch (device->chipset) {
case 0x43:
case 0x44:
case 0x4a:
case 0x47:
return OLD_STYLE;
case 0x46:
case 0x49:
case 0x4b:
case 0x4e:
case 0x4c:
case 0x67:
case 0x68:
case 0x63:
return NEW_STYLE;
default:
return INVALID_STYLE;
}
}
static int static int
nv40_sensor_setup(struct nouveau_therm *therm) nv40_sensor_setup(struct nouveau_therm *therm)
{ {
struct nouveau_device *device = nv_device(therm); enum nv40_sensor_style style = nv40_sensor_style(therm);
/* enable ADC readout and disable the ALARM threshold */ /* enable ADC readout and disable the ALARM threshold */
if (device->chipset >= 0x46) { if (style == NEW_STYLE) {
nv_mask(therm, 0x15b8, 0x80000000, 0); nv_mask(therm, 0x15b8, 0x80000000, 0);
nv_wr32(therm, 0x15b0, 0x80003fff); nv_wr32(therm, 0x15b0, 0x80003fff);
mdelay(10); /* wait for the temperature to stabilize */ mdelay(20); /* wait for the temperature to stabilize */
return nv_rd32(therm, 0x15b4) & 0x3fff; return nv_rd32(therm, 0x15b4) & 0x3fff;
} else { } else if (style == OLD_STYLE) {
nv_wr32(therm, 0x15b0, 0xff); nv_wr32(therm, 0x15b0, 0xff);
mdelay(20); /* wait for the temperature to stabilize */
return nv_rd32(therm, 0x15b4) & 0xff; return nv_rd32(therm, 0x15b4) & 0xff;
} } else
return -ENODEV;
} }
static int static int
nv40_temp_get(struct nouveau_therm *therm) nv40_temp_get(struct nouveau_therm *therm)
{ {
struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_therm_priv *priv = (void *)therm;
struct nouveau_device *device = nv_device(therm);
struct nvbios_therm_sensor *sensor = &priv->bios_sensor; struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
enum nv40_sensor_style style = nv40_sensor_style(therm);
int core_temp; int core_temp;
if (device->chipset >= 0x46) { if (style == NEW_STYLE) {
nv_wr32(therm, 0x15b0, 0x80003fff); nv_wr32(therm, 0x15b0, 0x80003fff);
core_temp = nv_rd32(therm, 0x15b4) & 0x3fff; core_temp = nv_rd32(therm, 0x15b4) & 0x3fff;
} else { } else if (style == OLD_STYLE) {
nv_wr32(therm, 0x15b0, 0xff); nv_wr32(therm, 0x15b0, 0xff);
core_temp = nv_rd32(therm, 0x15b4) & 0xff; core_temp = nv_rd32(therm, 0x15b4) & 0xff;
} } else
return -ENODEV;
/* Setup the sensor if the temperature is 0 */
if (core_temp == 0)
core_temp = nv40_sensor_setup(therm);
if (sensor->slope_div == 0) /* if the slope or the offset is unset, do no use the sensor */
sensor->slope_div = 1; if (!sensor->slope_div || !sensor->slope_mult ||
if (sensor->offset_den == 0) !sensor->offset_num || !sensor->offset_den)
sensor->offset_den = 1; return -ENODEV;
if (sensor->slope_mult < 1)
sensor->slope_mult = 1;
core_temp = core_temp * sensor->slope_mult / sensor->slope_div; core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
core_temp = core_temp + sensor->offset_num / sensor->offset_den; core_temp = core_temp + sensor->offset_num / sensor->offset_den;
core_temp = core_temp + sensor->offset_constant - 8; core_temp = core_temp + sensor->offset_constant - 8;
/* reserve negative temperatures for errors */
if (core_temp < 0)
core_temp = 0;
return core_temp; return core_temp;
} }
......
...@@ -102,7 +102,7 @@ struct nouveau_therm_priv { ...@@ -102,7 +102,7 @@ struct nouveau_therm_priv {
struct i2c_client *ic; struct i2c_client *ic;
}; };
int nouveau_therm_mode(struct nouveau_therm *therm, int mode); int nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode);
int nouveau_therm_attr_get(struct nouveau_therm *therm, int nouveau_therm_attr_get(struct nouveau_therm *therm,
enum nouveau_therm_attr_type type); enum nouveau_therm_attr_type type);
int nouveau_therm_attr_set(struct nouveau_therm *therm, int nouveau_therm_attr_set(struct nouveau_therm *therm,
...@@ -122,6 +122,7 @@ int nouveau_therm_fan_sense(struct nouveau_therm *therm); ...@@ -122,6 +122,7 @@ int nouveau_therm_fan_sense(struct nouveau_therm *therm);
int nouveau_therm_preinit(struct nouveau_therm *); int nouveau_therm_preinit(struct nouveau_therm *);
void nouveau_therm_sensor_preinit(struct nouveau_therm *);
void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm,
enum nouveau_therm_thrs thrs, enum nouveau_therm_thrs thrs,
enum nouveau_therm_thrs_state st); enum nouveau_therm_thrs_state st);
......
...@@ -34,10 +34,6 @@ nouveau_therm_temp_set_defaults(struct nouveau_therm *therm) ...@@ -34,10 +34,6 @@ nouveau_therm_temp_set_defaults(struct nouveau_therm *therm)
{ {
struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_therm_priv *priv = (void *)therm;
priv->bios_sensor.slope_mult = 1;
priv->bios_sensor.slope_div = 1;
priv->bios_sensor.offset_num = 0;
priv->bios_sensor.offset_den = 1;
priv->bios_sensor.offset_constant = 0; priv->bios_sensor.offset_constant = 0;
priv->bios_sensor.thrs_fan_boost.temp = 90; priv->bios_sensor.thrs_fan_boost.temp = 90;
...@@ -60,11 +56,6 @@ nouveau_therm_temp_safety_checks(struct nouveau_therm *therm) ...@@ -60,11 +56,6 @@ nouveau_therm_temp_safety_checks(struct nouveau_therm *therm)
struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_therm_priv *priv = (void *)therm;
struct nvbios_therm_sensor *s = &priv->bios_sensor; struct nvbios_therm_sensor *s = &priv->bios_sensor;
if (!priv->bios_sensor.slope_div)
priv->bios_sensor.slope_div = 1;
if (!priv->bios_sensor.offset_den)
priv->bios_sensor.offset_den = 1;
/* enforce a minimum hysteresis on thresholds */ /* enforce a minimum hysteresis on thresholds */
s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2); s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2);
s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2); 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,16 +97,16 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm,
const char *thresolds[] = { const char *thresolds[] = {
"fanboost", "downclock", "critical", "shutdown" "fanboost", "downclock", "critical", "shutdown"
}; };
uint8_t temperature = therm->temp_get(therm); int temperature = therm->temp_get(therm);
if (thrs < 0 || thrs > 3) if (thrs < 0 || thrs > 3)
return; return;
if (dir == NOUVEAU_THERM_THRS_FALLING) if (dir == NOUVEAU_THERM_THRS_FALLING)
nv_info(therm, "temperature (%u C) went below the '%s' threshold\n", nv_info(therm, "temperature (%i C) went below the '%s' threshold\n",
temperature, thresolds[thrs]); temperature, thresolds[thrs]);
else else
nv_info(therm, "temperature (%u C) hit the '%s' threshold\n", nv_info(therm, "temperature (%i C) hit the '%s' threshold\n",
temperature, thresolds[thrs]); temperature, thresolds[thrs]);
active = (dir == NOUVEAU_THERM_THRS_RISING); active = (dir == NOUVEAU_THERM_THRS_RISING);
...@@ -123,7 +114,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm, ...@@ -123,7 +114,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm,
case NOUVEAU_THERM_THRS_FANBOOST: case NOUVEAU_THERM_THRS_FANBOOST:
if (active) { if (active) {
nouveau_therm_fan_set(therm, true, 100); nouveau_therm_fan_set(therm, true, 100);
nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO); nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_AUTO);
} }
break; break;
case NOUVEAU_THERM_THRS_DOWNCLOCK: case NOUVEAU_THERM_THRS_DOWNCLOCK:
...@@ -202,7 +193,7 @@ alarm_timer_callback(struct nouveau_alarm *alarm) ...@@ -202,7 +193,7 @@ alarm_timer_callback(struct nouveau_alarm *alarm)
NOUVEAU_THERM_THRS_SHUTDOWN); NOUVEAU_THERM_THRS_SHUTDOWN);
/* schedule the next poll in one second */ /* schedule the next poll in one second */
if (list_empty(&alarm->head)) if (therm->temp_get(therm) >= 0 && list_empty(&alarm->head))
ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm); ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm);
spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
...@@ -225,6 +216,17 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm) ...@@ -225,6 +216,17 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm)
alarm_timer_callback(&priv->sensor.therm_poll_alarm); alarm_timer_callback(&priv->sensor.therm_poll_alarm);
} }
void
nouveau_therm_sensor_preinit(struct nouveau_therm *therm)
{
const char *sensor_avail = "yes";
if (therm->temp_get(therm) < 0)
sensor_avail = "no";
nv_info(therm, "internal sensor: %s\n", sensor_avail);
}
int int
nouveau_therm_sensor_ctor(struct nouveau_therm *therm) nouveau_therm_sensor_ctor(struct nouveau_therm *therm)
{ {
......
...@@ -402,8 +402,12 @@ nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) ...@@ -402,8 +402,12 @@ nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
struct drm_device *dev = dev_get_drvdata(d); struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_therm *therm = nouveau_therm(drm->device); struct nouveau_therm *therm = nouveau_therm(drm->device);
int temp = therm->temp_get(therm);
return snprintf(buf, PAGE_SIZE, "%d\n", therm->temp_get(therm) * 1000); if (temp < 0)
return temp;
return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000);
} }
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
NULL, 0); NULL, 0);
...@@ -871,7 +875,12 @@ static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR, ...@@ -871,7 +875,12 @@ static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR,
nouveau_hwmon_get_pwm1_max, nouveau_hwmon_get_pwm1_max,
nouveau_hwmon_set_pwm1_max, 0); nouveau_hwmon_set_pwm1_max, 0);
static struct attribute *hwmon_attributes[] = { static struct attribute *hwmon_default_attributes[] = {
&sensor_dev_attr_name.dev_attr.attr,
&sensor_dev_attr_update_rate.dev_attr.attr,
NULL
};
static struct attribute *hwmon_temp_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr,
&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
...@@ -882,8 +891,6 @@ static struct attribute *hwmon_attributes[] = { ...@@ -882,8 +891,6 @@ static struct attribute *hwmon_attributes[] = {
&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_emergency.dev_attr.attr, &sensor_dev_attr_temp1_emergency.dev_attr.attr,
&sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr,
&sensor_dev_attr_name.dev_attr.attr,
&sensor_dev_attr_update_rate.dev_attr.attr,
NULL NULL
}; };
static struct attribute *hwmon_fan_rpm_attributes[] = { static struct attribute *hwmon_fan_rpm_attributes[] = {
...@@ -898,8 +905,11 @@ static struct attribute *hwmon_pwm_fan_attributes[] = { ...@@ -898,8 +905,11 @@ static struct attribute *hwmon_pwm_fan_attributes[] = {
NULL NULL
}; };
static const struct attribute_group hwmon_attrgroup = { static const struct attribute_group hwmon_default_attrgroup = {
.attrs = hwmon_attributes, .attrs = hwmon_default_attributes,
};
static const struct attribute_group hwmon_temp_attrgroup = {
.attrs = hwmon_temp_attributes,
}; };
static const struct attribute_group hwmon_fan_rpm_attrgroup = { static const struct attribute_group hwmon_fan_rpm_attrgroup = {
.attrs = hwmon_fan_rpm_attributes, .attrs = hwmon_fan_rpm_attributes,
...@@ -931,13 +941,22 @@ nouveau_hwmon_init(struct drm_device *dev) ...@@ -931,13 +941,22 @@ nouveau_hwmon_init(struct drm_device *dev)
} }
dev_set_drvdata(hwmon_dev, dev); dev_set_drvdata(hwmon_dev, dev);
/* default sysfs entries */ /* set the default attributes */
ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_attrgroup); ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
if (ret) { if (ret) {
if (ret) if (ret)
goto error; goto error;
} }
/* if the card has a working thermal sensor */
if (therm->temp_get(therm) >= 0) {
ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup);
if (ret) {
if (ret)
goto error;
}
}
/* if the card has a pwm fan */ /* if the card has a pwm fan */
/*XXX: incorrect, need better detection for this, some boards have /*XXX: incorrect, need better detection for this, some boards have
* the gpio entries for pwm fan control even when there's no * the gpio entries for pwm fan control even when there's no
...@@ -979,11 +998,10 @@ nouveau_hwmon_fini(struct drm_device *dev) ...@@ -979,11 +998,10 @@ nouveau_hwmon_fini(struct drm_device *dev)
struct nouveau_pm *pm = nouveau_pm(dev); struct nouveau_pm *pm = nouveau_pm(dev);
if (pm->hwmon) { if (pm->hwmon) {
sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); sysfs_remove_group(&pm->hwmon->kobj, &hwmon_default_attrgroup);
sysfs_remove_group(&pm->hwmon->kobj, sysfs_remove_group(&pm->hwmon->kobj, &hwmon_temp_attrgroup);
&hwmon_pwm_fan_attrgroup); sysfs_remove_group(&pm->hwmon->kobj, &hwmon_pwm_fan_attrgroup);
sysfs_remove_group(&pm->hwmon->kobj, sysfs_remove_group(&pm->hwmon->kobj, &hwmon_fan_rpm_attrgroup);
&hwmon_fan_rpm_attrgroup);
hwmon_device_unregister(pm->hwmon); hwmon_device_unregister(pm->hwmon);
} }
......
...@@ -524,6 +524,8 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -524,6 +524,8 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
swap_interval <<= 4; swap_interval <<= 4;
if (swap_interval == 0) if (swap_interval == 0)
swap_interval |= 0x100; swap_interval |= 0x100;
if (chan == NULL)
evo_sync(crtc->dev);
push = evo_wait(sync, 128); push = evo_wait(sync, 128);
if (unlikely(push == NULL)) if (unlikely(push == NULL))
...@@ -586,8 +588,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -586,8 +588,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
sync->addr ^= 0x10; sync->addr ^= 0x10;
sync->data++; sync->data++;
FIRE_RING (chan); FIRE_RING (chan);
} else {
evo_sync(crtc->dev);
} }
/* queue the flip */ /* queue the flip */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment