Skip to content

Commit

Permalink
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Browse files Browse the repository at this point in the history
Pull drm fixes from Dave Airlie:
 "Radeon, intel and nouveau, along with one mgag200 fix

   - intel fix for an ioctl overflow, along with a regression fix for
     some phantom irqs on Ironlake.
   - nouveau has a lockdep warning and a bunch of thermal fixes
   - radeon has new pci ids and some minor fixes."

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (26 commits)
  drm/mgag200: Bug fix: Modified pll algorithm for EH project
  drm/i915: stop using GMBUS IRQs on Gen4 chips
  drm/nv50/kms: prevent lockdep false-positive in page flipping path
  drm/nouveau/core: fix return value of nouveau_object_del()
  MAINTAINERS: intel-gfx is no longer subscribers-only
  drm/i915: Use the fixed pixel clock for eDP in intel_dp_set_m_n()
  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
  Revert "drm/i915: try to train DP even harder"
  drm/radeon: add Richland pci ids
  drm/radeon: add support for Richland APUs
  ...
  • Loading branch information
torvalds committed Mar 21, 2013
2 parents 85ab3c4 + b56fb70 commit 172a271
Show file tree
Hide file tree
Showing 19 changed files with 204 additions and 91 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Expand Up @@ -2623,7 +2623,7 @@ F: include/uapi/drm/

INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
M: Daniel Vetter <daniel.vetter@ffwll.ch>
L: intel-gfx@lists.freedesktop.org (subscribers-only)
L: intel-gfx@lists.freedesktop.org
L: dri-devel@lists.freedesktop.org
T: git git://people.freedesktop.org/~danvet/drm-intel
S: Supported
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_debugfs.c
Expand Up @@ -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),
Expand Down
11 changes: 8 additions & 3 deletions drivers/gpu/drm/i915/i915_gem_execbuffer.c
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
14 changes: 12 additions & 2 deletions drivers/gpu/drm/i915/intel_dp.c
Expand Up @@ -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
Expand All @@ -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),
Expand Down Expand Up @@ -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");
Expand Down
11 changes: 10 additions & 1 deletion drivers/gpu/drm/i915/intel_i2c.c
Expand Up @@ -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,
Expand All @@ -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. */
Expand Down
10 changes: 5 additions & 5 deletions drivers/gpu/drm/mgag200/mgag200_mode.c
Expand Up @@ -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)
Expand All @@ -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;
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/drm/nouveau/core/core/object.c
Expand Up @@ -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)
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/core/include/subdev/therm.h
Expand Up @@ -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,
Expand Down
18 changes: 12 additions & 6 deletions drivers/gpu/drm/nouveau/core/subdev/therm/base.c
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down
6 changes: 4 additions & 2 deletions drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
67 changes: 48 additions & 19 deletions drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
Expand Up @@ -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;
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
Expand Up @@ -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,
Expand All @@ -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);
Expand Down

0 comments on commit 172a271

Please sign in to comment.