summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_edid.c3
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c11
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c14
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c11
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/core/object.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/therm.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/base.c18
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/ic.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c67
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/temp.c30
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_pm.c44
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c4
-rw-r--r--drivers/gpu/drm/radeon/ni.c33
-rw-r--r--drivers/gpu/drm/radeon/radeon_benchmark.c21
-rw-r--r--drivers/gpu/drm/radeon/si.c1
18 files changed, 193 insertions, 90 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index c194f4e680ad..e2acfdbf7d3c 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1634,7 +1634,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
- unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
+ unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 2 | pt->vsync_offset_pulse_width_lo >> 4;
unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
/* ignore tiny modes */
@@ -1715,6 +1715,7 @@ set_size:
}
mode->type = DRM_MODE_TYPE_DRIVER;
+ mode->vrefresh = drm_mode_vrefresh(mode);
drm_mode_set_name(mode);
return mode;
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index aae31489c893..7299ea45dd03 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -103,7 +103,7 @@ static const char *cache_level_str(int type)
static void
describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
{
- seq_printf(m, "%p: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s",
+ seq_printf(m, "%pK: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s",
&obj->base,
get_pin_flag(obj),
get_tiling_flag(obj),
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 2f2daebd0eef..3b11ab0fbc96 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -732,6 +732,8 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
int count)
{
int i;
+ int relocs_total = 0;
+ int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry);
for (i = 0; i < count; i++) {
char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
@@ -740,10 +742,13 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
if (exec[i].flags & __EXEC_OBJECT_UNKNOWN_FLAGS)
return -EINVAL;
- /* First check for malicious input causing overflow */
- if (exec[i].relocation_count >
- INT_MAX / sizeof(struct drm_i915_gem_relocation_entry))
+ /* First check for malicious input causing overflow in
+ * the worst case where we need to allocate the entire
+ * relocation tree as a single array.
+ */
+ if (exec[i].relocation_count > relocs_max - relocs_total)
return -EINVAL;
+ relocs_total += exec[i].relocation_count;
length = exec[i].relocation_count *
sizeof(struct drm_i915_gem_relocation_entry);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6f728e5ee793..d7d4afe01341 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -820,6 +820,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct intel_link_m_n m_n;
int pipe = intel_crtc->pipe;
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+ int target_clock;
/*
* Find the lane count in the intel_encoder private
@@ -835,13 +836,22 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
}
}
+ target_clock = mode->clock;
+ for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+ if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+ target_clock = intel_edp_target_clock(intel_encoder,
+ mode);
+ break;
+ }
+ }
+
/*
* Compute the GMCH and Link ratios. The '3' here is
* the number of bytes_per_pixel post-LUT, which we always
* set up for 8-bits of R/G/B, or 3 bytes total.
*/
intel_link_compute_m_n(intel_crtc->bpp, lane_count,
- mode->clock, adjusted_mode->clock, &m_n);
+ target_clock, adjusted_mode->clock, &m_n);
if (IS_HASWELL(dev)) {
I915_WRITE(PIPE_DATA_M1(cpu_transcoder),
@@ -1930,7 +1940,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
for (i = 0; i < intel_dp->lane_count; i++)
if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
break;
- if (i == intel_dp->lane_count && voltage_tries == 5) {
+ if (i == intel_dp->lane_count) {
++loop_tries;
if (loop_tries == 5) {
DRM_DEBUG_KMS("too many full retries, give up\n");
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index acf8aec9ada7..ef4744e1bf0b 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -203,7 +203,13 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin)
algo->data = bus;
}
-#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 4)
+/*
+ * gmbus on gen4 seems to be able to generate legacy interrupts even when in MSI
+ * mode. This results in spurious interrupt warnings if the legacy irq no. is
+ * shared with another device. The kernel then disables that interrupt source
+ * and so prevents the other device from working properly.
+ */
+#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
static int
gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
u32 gmbus2_status,
@@ -214,6 +220,9 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
u32 gmbus2 = 0;
DEFINE_WAIT(wait);
+ if (!HAS_GMBUS_IRQ(dev_priv->dev))
+ gmbus4_irq_en = 0;
+
/* Important: The hw handles only the first bit, so set only one! Since
* we also need to check for NAKs besides the hw ready/idle signal, we
* need to wake up periodically and check that ourselves. */
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index a274b9906ef8..fe22bb780e1d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -382,19 +382,19 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
m = n = p = 0;
vcomax = 800000;
vcomin = 400000;
- pllreffreq = 3333;
+ pllreffreq = 33333;
delta = 0xffffffff;
permitteddelta = clock * 5 / 1000;
- for (testp = 16; testp > 0; testp--) {
+ for (testp = 16; testp > 0; testp >>= 1) {
if (clock * testp > vcomax)
continue;
if (clock * testp < vcomin)
continue;
for (testm = 1; testm < 33; testm++) {
- for (testn = 1; testn < 257; testn++) {
+ for (testn = 17; testn < 257; testn++) {
computed = (pllreffreq * testn) /
(testm * testp);
if (computed > clock)
@@ -404,11 +404,11 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
if (tmpdelta < delta) {
delta = tmpdelta;
n = testn - 1;
- m = (testm - 1) | ((n >> 1) & 0x80);
+ m = (testm - 1);
p = testp - 1;
}
if ((clock * testp) >= 600000)
- p |= 80;
+ p |= 0x80;
}
}
}
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)
struct nouveau_object *parent = NULL;
struct nouveau_object *namedb = NULL;
struct nouveau_handle *handle = NULL;
- int ret = -EINVAL;
parent = nouveau_handle_ref(client, _parent);
if (!parent)
@@ -295,7 +294,7 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle)
}
nouveau_object_ref(NULL, &parent);
- return ret;
+ return handle ? 0 : -EINVAL;
}
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 @@
#include <core/device.h>
#include <core/subdev.h>
-enum nouveau_therm_mode {
+enum nouveau_therm_fan_mode {
NOUVEAU_THERM_CTRL_NONE = 0,
NOUVEAU_THERM_CTRL_MANUAL = 1,
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)
}
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_device *device = nv_device(therm);
@@ -149,10 +149,15 @@ nouveau_therm_mode(struct nouveau_therm *therm, int mode)
(mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0))
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)
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);
return 0;
}
@@ -213,7 +218,7 @@ nouveau_therm_attr_set(struct nouveau_therm *therm,
priv->fan->bios.max_duty = value;
return 0;
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:
priv->bios_sensor.thrs_fan_boost.temp = value;
priv->sensor.program_alarms(therm);
@@ -263,7 +268,7 @@ _nouveau_therm_init(struct nouveau_object *object)
return ret;
if (priv->suspend >= 0)
- nouveau_therm_mode(therm, priv->mode);
+ nouveau_therm_fan_mode(therm, priv->mode);
priv->sensor.program_alarms(therm);
return 0;
}
@@ -313,11 +318,12 @@ nouveau_therm_create_(struct nouveau_object *parent,
int
nouveau_therm_preinit(struct nouveau_therm *therm)
{
- nouveau_therm_ic_ctor(therm);
nouveau_therm_sensor_ctor(therm);
+ nouveau_therm_ic_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;
}
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,
struct i2c_board_info *info)
{
struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c);
+ struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
struct i2c_client *client;
request_module("%s%s", I2C_MODULE_PREFIX, info->type);
@@ -46,8 +47,9 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,
}
nv_info(priv,
- "Found an %s at address 0x%x (controlled by lm_sensors)\n",
- info->type, info->addr);
+ "Found an %s at address 0x%x (controlled by lm_sensors, "
+ "temp offset %+i C)\n",
+ info->type, info->addr, sensor->offset_constant);
priv->ic = client;
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 {
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
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 */
- if (device->chipset >= 0x46) {
+ if (style == NEW_STYLE) {
nv_mask(therm, 0x15b8, 0x80000000, 0);
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;
- } else {
+ } else if (style == OLD_STYLE) {
nv_wr32(therm, 0x15b0, 0xff);
+ mdelay(20); /* wait for the temperature to stabilize */
return nv_rd32(therm, 0x15b4) & 0xff;
- }
+ } else
+ return -ENODEV;
}
static int
nv40_temp_get(struct nouveau_therm *therm)
{
struct nouveau_therm_priv *priv = (void *)therm;
- struct nouveau_device *device = nv_device(therm);
struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
+ enum nv40_sensor_style style = nv40_sensor_style(therm);
int core_temp;
- if (device->chipset >= 0x46) {
+ if (style == NEW_STYLE) {
nv_wr32(therm, 0x15b0, 0x80003fff);
core_temp = nv_rd32(therm, 0x15b4) & 0x3fff;
- } else {
+ } else if (style == OLD_STYLE) {
nv_wr32(therm, 0x15b0, 0xff);
core_temp = nv_rd32(therm, 0x15b4) & 0xff;
- }
-
- /* Setup the sensor if the temperature is 0 */
- if (core_temp == 0)
- core_temp = nv40_sensor_setup(therm);
+ } else
+ return -ENODEV;
- if (sensor->slope_div == 0)
- sensor->slope_div = 1;
- if (sensor->offset_den == 0)
- sensor->offset_den = 1;
- if (sensor->slope_mult < 1)
- sensor->slope_mult = 1;
+ /* if the slope or the offset is unset, do no use the sensor */
+ if (!sensor->slope_div || !sensor->slope_mult ||
+ !sensor->offset_num || !sensor->offset_den)
+ return -ENODEV;
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_constant - 8;
+ /* reserve negative temperatures for errors */
+ if (core_temp < 0)
+ core_temp = 0;
+
return core_temp;
}
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 {
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,
enum nouveau_therm_attr_type type);
int nouveau_therm_attr_set(struct nouveau_therm *therm,
@@ -122,6 +122,7 @@ int nouveau_therm_fan_sense(struct nouveau_therm *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,
enum nouveau_therm_thrs thrs,
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)
{
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.thrs_fan_boost.temp = 90;
@@ -60,11 +56,6 @@ nouveau_therm_temp_safety_checks(struct nouveau_therm *therm)
struct nouveau_therm_priv *priv = (void *)therm;
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 */
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);
@@ -106,16 +97,16 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm,
const char *thresolds[] = {
"fanboost", "downclock", "critical", "shutdown"
};
- uint8_t temperature = therm->temp_get(therm);
+ int temperature = therm->temp_get(therm);
if (thrs < 0 || thrs > 3)
return;
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]);
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]);
active = (dir == NOUVEAU_THERM_THRS_RISING);
@@ -123,7 +114,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm,
case NOUVEAU_THERM_THRS_FANBOOST:
if (active) {
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;
case NOUVEAU_THERM_THRS_DOWNCLOCK:
@@ -202,7 +193,7 @@ alarm_timer_callback(struct nouveau_alarm *alarm)
NOUVEAU_THERM_THRS_SHUTDOWN);
/* 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);
spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
@@ -225,6 +216,17 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm)
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
nouveau_therm_sensor_ctor(struct nouveau_therm *therm)
{
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)
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
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,
NULL, 0);
@@ -871,7 +875,12 @@ static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR,
nouveau_hwmon_get_pwm1_max,
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_auto_point1_pwm.dev_attr.attr,
&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
@@ -882,8 +891,6 @@ static struct attribute *hwmon_attributes[] = {
&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_emergency.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
};
static struct attribute *hwmon_fan_rpm_attributes[] = {
@@ -898,8 +905,11 @@ static struct attribute *hwmon_pwm_fan_attributes[] = {
NULL
};
-static const struct attribute_group hwmon_attrgroup = {
- .attrs = hwmon_attributes,
+static const struct attribute_group hwmon_default_attrgroup = {
+ .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 = {
.attrs = hwmon_fan_rpm_attributes,
@@ -931,13 +941,22 @@ nouveau_hwmon_init(struct drm_device *dev)
}
dev_set_drvdata(hwmon_dev, dev);
- /* default sysfs entries */
- ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_attrgroup);
+ /* set the default attributes */
+ ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
if (ret) {
if (ret)
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 */
/*XXX: incorrect, need better detection for this, some boards have
* the gpio entries for pwm fan control even when there's no
@@ -979,11 +998,10 @@ nouveau_hwmon_fini(struct drm_device *dev)
struct nouveau_pm *pm = nouveau_pm(dev);
if (pm->hwmon) {
- sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup);
- sysfs_remove_group(&pm->hwmon->kobj,
- &hwmon_pwm_fan_attrgroup);
- sysfs_remove_group(&pm->hwmon->kobj,
- &hwmon_fan_rpm_attrgroup);
+ sysfs_remove_group(&pm->hwmon->kobj, &hwmon_default_attrgroup);
+ sysfs_remove_group(&pm->hwmon->kobj, &hwmon_temp_attrgroup);
+ sysfs_remove_group(&pm->hwmon->kobj, &hwmon_pwm_fan_attrgroup);
+ sysfs_remove_group(&pm->hwmon->kobj, &hwmon_fan_rpm_attrgroup);
hwmon_device_unregister(pm->hwmon);
}
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,
swap_interval <<= 4;
if (swap_interval == 0)
swap_interval |= 0x100;
+ if (chan == NULL)
+ evo_sync(crtc->dev);
push = evo_wait(sync, 128);
if (unlikely(push == NULL))
@@ -586,8 +588,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
sync->addr ^= 0x10;
sync->data++;
FIRE_RING (chan);
- } else {
- evo_sync(crtc->dev);
}
/* queue the flip */
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index d4c633e12863..27769e724b6d 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -468,13 +468,19 @@ static void cayman_gpu_init(struct radeon_device *rdev)
(rdev->pdev->device == 0x9907) ||
(rdev->pdev->device == 0x9908) ||
(rdev->pdev->device == 0x9909) ||
+ (rdev->pdev->device == 0x990B) ||
+ (rdev->pdev->device == 0x990C) ||
+ (rdev->pdev->device == 0x990F) ||
(rdev->pdev->device == 0x9910) ||
- (rdev->pdev->device == 0x9917)) {
+ (rdev->pdev->device == 0x9917) ||
+ (rdev->pdev->device == 0x9999)) {
rdev->config.cayman.max_simds_per_se = 6;
rdev->config.cayman.max_backends_per_se = 2;
} else if ((rdev->pdev->device == 0x9903) ||
(rdev->pdev->device == 0x9904) ||
(rdev->pdev->device == 0x990A) ||
+ (rdev->pdev->device == 0x990D) ||
+ (rdev->pdev->device == 0x990E) ||
(rdev->pdev->device == 0x9913) ||
(rdev->pdev->device == 0x9918)) {
rdev->config.cayman.max_simds_per_se = 4;
@@ -483,6 +489,9 @@ static void cayman_gpu_init(struct radeon_device *rdev)
(rdev->pdev->device == 0x9990) ||
(rdev->pdev->device == 0x9991) ||
(rdev->pdev->device == 0x9994) ||
+ (rdev->pdev->device == 0x9995) ||
+ (rdev->pdev->device == 0x9996) ||
+ (rdev->pdev->device == 0x999A) ||
(rdev->pdev->device == 0x99A0)) {
rdev->config.cayman.max_simds_per_se = 3;
rdev->config.cayman.max_backends_per_se = 1;
@@ -616,11 +625,22 @@ static void cayman_gpu_init(struct radeon_device *rdev)
WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
- tmp = gb_addr_config & NUM_PIPES_MASK;
- tmp = r6xx_remap_render_backend(rdev, tmp,
- rdev->config.cayman.max_backends_per_se *
- rdev->config.cayman.max_shader_engines,
- CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+ if ((rdev->config.cayman.max_backends_per_se == 1) &&
+ (rdev->flags & RADEON_IS_IGP)) {
+ if ((disabled_rb_mask & 3) == 1) {
+ /* RB0 disabled, RB1 enabled */
+ tmp = 0x11111111;
+ } else {
+ /* RB1 disabled, RB0 enabled */
+ tmp = 0x00000000;
+ }
+ } else {
+ tmp = gb_addr_config & NUM_PIPES_MASK;
+ tmp = r6xx_remap_render_backend(rdev, tmp,
+ rdev->config.cayman.max_backends_per_se *
+ rdev->config.cayman.max_shader_engines,
+ CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+ }
WREG32(GB_BACKEND_MAP, tmp);
cgts_tcc_disable = 0xffff0000;
@@ -1771,6 +1791,7 @@ int cayman_resume(struct radeon_device *rdev)
int cayman_suspend(struct radeon_device *rdev)
{
r600_audio_fini(rdev);
+ radeon_vm_manager_fini(rdev);
cayman_cp_enable(rdev, false);
cayman_dma_stop(rdev);
evergreen_irq_suspend(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c
index bedda9caadd9..6e05a2e75a46 100644
--- a/drivers/gpu/drm/radeon/radeon_benchmark.c
+++ b/drivers/gpu/drm/radeon/radeon_benchmark.c
@@ -122,10 +122,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
goto out_cleanup;
}
- /* r100 doesn't have dma engine so skip the test */
- /* also, VRAM-to-VRAM test doesn't make much sense for DMA */
- /* skip it as well if domains are the same */
- if ((rdev->asic->copy.dma) && (sdomain != ddomain)) {
+ if (rdev->asic->copy.dma) {
time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
RADEON_BENCHMARK_COPY_DMA, n);
if (time < 0)
@@ -135,13 +132,15 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
sdomain, ddomain, "dma");
}
- time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
- RADEON_BENCHMARK_COPY_BLIT, n);
- if (time < 0)
- goto out_cleanup;
- if (time > 0)
- radeon_benchmark_log_results(n, size, time,
- sdomain, ddomain, "blit");
+ if (rdev->asic->copy.blit) {
+ time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+ RADEON_BENCHMARK_COPY_BLIT, n);
+ if (time < 0)
+ goto out_cleanup;
+ if (time > 0)
+ radeon_benchmark_log_results(n, size, time,
+ sdomain, ddomain, "blit");
+ }
out_cleanup:
if (sobj) {
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 9128120da044..bafbe3216952 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -4469,6 +4469,7 @@ int si_resume(struct radeon_device *rdev)
int si_suspend(struct radeon_device *rdev)
{
+ radeon_vm_manager_fini(rdev);
si_cp_enable(rdev, false);
cayman_dma_stop(rdev);
si_irq_suspend(rdev);