From 7c04d1d97a8d918b7ae2ef478229862b71a65f06 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 23 Feb 2009 15:36:40 -0800 Subject: drm/i915: remove PLL debugging messages These are normal; we walk through different values looking for the right one, so why flood the screen with messages? Signed-off-by: Jesse Barnes Reviewed-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 65b635ce28c8..a2834276cb38 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -217,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) return false; } -#define INTELPllInvalid(s) do { DRM_DEBUG(s); return false; } while (0) +#define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) /** * Returns whether the given set of divisors are valid for a given refclk with * the given connectors. -- cgit v1.2.3 From 37df96736bfe6f5fd9a141d62946e1083d73e712 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 23 Feb 2009 15:36:42 -0800 Subject: drm/i915: handle bogus VBT panel timing We've seen cases in the wild where the VBT sync data is wrong, so add some code to fix it up in that case, taking care to make sure that the total is greater than the sync end. Signed-off-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/intel_bios.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 65be30dccc77..fc28e2bbd542 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -111,6 +111,12 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) panel_fixed_mode->clock = dvo_timing->clock * 10; panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; + /* Some VBTs have bogus h/vtotal values */ + if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) + panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; + if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) + panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; + drm_mode_set_name(panel_fixed_mode); dev_priv->vbt_mode = panel_fixed_mode; -- cgit v1.2.3 From c8766ac5933d6ee75e7ce379a1eb5ceb451fcb83 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 23 Feb 2009 08:44:33 -0800 Subject: drm: Fix shifts of EDID vsync offset/width fields. Signed-off-by: Linus Torvalds Reviewed-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 5a4d3244758a..e902b1cefc06 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -320,10 +320,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; - mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) | + mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) | pt->vsync_offset_lo); mode->vsync_end = mode->vsync_start + - ((pt->vsync_pulse_width_hi << 8) | + ((pt->vsync_pulse_width_hi << 4) | pt->vsync_pulse_width_lo); mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); -- cgit v1.2.3 From 7bec756c74b1a5079d5074144bb77a6b3e7d7783 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 23 Feb 2009 16:09:34 -0800 Subject: drm: disable encoders before re-routing them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some cases we may receive a mode config that has a different CRTC<->encoder map that the current configuration. In that case, we need to disable any re-routed encoders before setting the mode, otherwise they may not pick up the new CRTC (if the output types are incompatible for example). Tested-by: Kristian Høgsberg Signed-off-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 76 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 733028b4d45e..1c3a8c557140 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -452,6 +452,59 @@ static void drm_setup_crtcs(struct drm_device *dev) kfree(modes); kfree(enabled); } + +/** + * drm_encoder_crtc_ok - can a given crtc drive a given encoder? + * @encoder: encoder to test + * @crtc: crtc to test + * + * Return false if @encoder can't be driven by @crtc, true otherwise. + */ +static bool drm_encoder_crtc_ok(struct drm_encoder *encoder, + struct drm_crtc *crtc) +{ + struct drm_device *dev; + struct drm_crtc *tmp; + int crtc_mask = 1; + + WARN(!crtc, "checking null crtc?"); + + dev = crtc->dev; + + list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { + if (tmp == crtc) + break; + crtc_mask <<= 1; + } + + if (encoder->possible_crtcs & crtc_mask) + return true; + return false; +} + +/* + * Check the CRTC we're going to map each output to vs. its current + * CRTC. If they don't match, we have to disable the output and the CRTC + * since the driver will have to re-route things. + */ +static void +drm_crtc_prepare_encoders(struct drm_device *dev) +{ + struct drm_encoder_helper_funcs *encoder_funcs; + struct drm_encoder *encoder; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + encoder_funcs = encoder->helper_private; + /* Disable unused encoders */ + if (encoder->crtc == NULL) + (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); + /* Disable encoders whose CRTC is about to change */ + if (encoder_funcs->get_crtc && + encoder->crtc != (*encoder_funcs->get_crtc)(encoder)) + (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); + } +} + /** * drm_crtc_set_mode - set a mode * @crtc: CRTC to program @@ -547,6 +600,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, encoder_funcs->prepare(encoder); } + drm_crtc_prepare_encoders(dev); + crtc_funcs->prepare(crtc); /* Set up the DPLL and any encoders state that needs to adjust or depend @@ -617,7 +672,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) struct drm_device *dev; struct drm_crtc **save_crtcs, *new_crtc; struct drm_encoder **save_encoders, *new_encoder; - struct drm_framebuffer *old_fb; + struct drm_framebuffer *old_fb = NULL; bool save_enabled; bool mode_changed = false; bool fb_changed = false; @@ -668,9 +723,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) * and then just flip_or_move it */ if (set->crtc->fb != set->fb) { /* If we have no fb then treat it as a full mode set */ - if (set->crtc->fb == NULL) + if (set->crtc->fb == NULL) { + DRM_DEBUG("crtc has no fb, full mode set\n"); mode_changed = true; - else if ((set->fb->bits_per_pixel != + } else if ((set->fb->bits_per_pixel != set->crtc->fb->bits_per_pixel) || set->fb->depth != set->crtc->fb->depth) fb_changed = true; @@ -682,7 +738,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) fb_changed = true; if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { - DRM_DEBUG("modes are different\n"); + DRM_DEBUG("modes are different, full mode set\n"); drm_mode_debug_printmodeline(&set->crtc->mode); drm_mode_debug_printmodeline(set->mode); mode_changed = true; @@ -708,6 +764,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } if (new_encoder != connector->encoder) { + DRM_DEBUG("encoder changed, full mode switch\n"); mode_changed = true; connector->encoder = new_encoder; } @@ -734,10 +791,20 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (set->connectors[ro] == connector) new_crtc = set->crtc; } + + /* Make sure the new CRTC will work with the encoder */ + if (new_crtc && + !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { + ret = -EINVAL; + goto fail_set_mode; + } if (new_crtc != connector->encoder->crtc) { + DRM_DEBUG("crtc changed, full mode switch\n"); mode_changed = true; connector->encoder->crtc = new_crtc; } + DRM_DEBUG("setting connector %d crtc to %p\n", + connector->base.id, new_crtc); } /* mode_set_base is not a required function */ @@ -781,6 +848,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) fail_set_mode: set->crtc->enabled = save_enabled; + set->crtc->fb = old_fb; count = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (!connector->encoder) -- cgit v1.2.3 From b3f5e7329df1a508ac58ebe7509fb7a47b9eab6a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 19 Feb 2009 14:48:22 +0000 Subject: drm: Correct unbalanced drm_vblank_put() during mode setting. The first time we install a mode, the vblank will be disabled for a pipe and so drm_vblank_get() in drm_vblank_pre_modeset() will fail. As we unconditionally call drm_vblank_put() afterwards, the vblank reference counter becomes unbalanced. Signed-off-by: Chris Wilson Acked-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_irq.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3795dbc0f50c..93e677a481f5 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -435,6 +435,8 @@ EXPORT_SYMBOL(drm_vblank_get); */ void drm_vblank_put(struct drm_device *dev, int crtc) { + BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0); + /* Last user schedules interrupt disable */ if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); @@ -460,8 +462,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) * so that interrupts remain enabled in the interim. */ if (!dev->vblank_inmodeset[crtc]) { - dev->vblank_inmodeset[crtc] = 1; - drm_vblank_get(dev, crtc); + dev->vblank_inmodeset[crtc] = 0x1; + if (drm_vblank_get(dev, crtc) == 0) + dev->vblank_inmodeset[crtc] |= 0x2; } } EXPORT_SYMBOL(drm_vblank_pre_modeset); @@ -473,9 +476,12 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) if (dev->vblank_inmodeset[crtc]) { spin_lock_irqsave(&dev->vbl_lock, irqflags); dev->vblank_disable_allowed = 1; - dev->vblank_inmodeset[crtc] = 0; spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - drm_vblank_put(dev, crtc); + + if (dev->vblank_inmodeset[crtc] & 0x2) + drm_vblank_put(dev, crtc); + + dev->vblank_inmodeset[crtc] = 0; } } EXPORT_SYMBOL(drm_vblank_post_modeset); -- cgit v1.2.3 From d61e7380b402a481ab1fa8027068a24918f701c8 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 24 Feb 2009 20:31:53 -0500 Subject: drm: edid revision 0 is valid edid->revision == 0 should be valid (at least, so the error message indicates. :) and wikipedia seems to indicate that EDID 1.0 existed. We can dump the entire check, since edid->revision is a u8, so it can't ever be less than 0. Marko reports in RH bz#476735 that his monitor claims to be EDID 1.0, and therefore hits the check and is stuck at 800x600 because of it. Reported-by: Marko Ristola Signed-off-by: Kyle McMartin Acked-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index e902b1cefc06..a839a28d8ee6 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -125,7 +125,7 @@ static bool edid_is_valid(struct edid *edid) DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); goto bad; } - if (edid->revision <= 0 || edid->revision > 3) { + if (edid->revision > 3) { DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision); goto bad; } -- cgit v1.2.3 From dd0910b3c71b253c08111110f0399b924a8d5853 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 25 Feb 2009 14:49:21 +1000 Subject: drm/i915: make hw page ioremap use ioremap_wc However we still have another issue with ioremap_wc not falling back properly or somehow doing something else stupid, this probably needs to be tracked down. Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2d797ffe8137..cc4649577a61 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -811,7 +811,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data, dev_priv->hws_map.flags = 0; dev_priv->hws_map.mtrr = 0; - drm_core_ioremap(&dev_priv->hws_map, dev); + drm_core_ioremap_wc(&dev_priv->hws_map, dev); if (dev_priv->hws_map.handle == NULL) { i915_dma_cleanup(dev); dev_priv->status_gfx_addr = 0; -- cgit v1.2.3 From e08fb4f6d1dc95eff5b3fc1d0412bcb5afcae7f2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 25 Feb 2009 14:52:30 +1000 Subject: drm/i915: convert DRM_ERROR to DRM_DEBUG in phys object pwrite path This snuck in when I wrote phys object support. Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 28b726d07a0c..85685bfd12da 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3548,7 +3548,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, user_data = (char __user *) (uintptr_t) args->data_ptr; obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; - DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size); + DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size); ret = copy_from_user(obj_addr, user_data, args->size); if (ret) return -EFAULT; -- cgit v1.2.3 From f180053694b43d5714bf56cb95499a3c32ff155c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 2 Mar 2009 11:00:57 +0100 Subject: x86, mm: dont use non-temporal stores in pagecache accesses Impact: standardize IO on cached ops On modern CPUs it is almost always a bad idea to use non-temporal stores, as the regression in this commit has shown it: 30d697f: x86: fix performance regression in write() syscall The kernel simply has no good information about whether using non-temporal stores is a good idea or not - and trying to add heuristics only increases complexity and inserts fragility. The regression on cached write()s took very long to be found - over two years. So dont take any chances and let the hardware decide how it makes use of its caches. The only exception is drivers/gpu/drm/i915/i915_gem.c: there were we are absolutely sure that another entity (the GPU) will pick up the dirty data immediately and that the CPU will not touch that data before the GPU will. Also, keep the _nocache() primitives to make it easier for people to experiment with these details. There may be more clear-cut cases where non-cached copies can be used, outside of filemap.c. Cc: Salman Qazi Cc: Nick Piggin Cc: Linus Torvalds Signed-off-by: Ingo Molnar --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6b209db8370d..818576654092 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -215,7 +215,7 @@ fast_user_write(struct io_mapping *mapping, vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, - user_data, length, length); + user_data, length); io_mapping_unmap_atomic(vaddr_atomic); if (unwritten) return -EFAULT; -- cgit v1.2.3 From 4d77c88e912e5eb9480432af09e950ca8995c253 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 2 Mar 2009 11:10:54 +0100 Subject: drm: Don't return ERESTARTSYS to user-space. That return code is for in-kernel use only. Use EINTR instead. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_lock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 46e7b28f0707..b03586fdabbd 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -93,7 +93,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) /* Contention */ schedule(); if (signal_pending(current)) { - ret = -ERESTARTSYS; + ret = -EINTR; break; } } -- cgit v1.2.3 From 171901d15deeef61aa8e1b0d0772404f39691b73 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 2 Mar 2009 11:10:55 +0100 Subject: drm: Wake up all lock waiters when the master disappears. Currently only one waiter is woken up, leaving other waiters hanging waiting for the DRM lock. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_bufs.c | 2 +- drivers/gpu/drm/drm_stub.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 72c667f9bee1..12715d3c078d 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -420,7 +420,7 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) dev->sigdata.lock = NULL; master->lock.hw_lock = NULL; /* SHM removed */ master->lock.file_priv = NULL; - wake_up_interruptible(&master->lock.lock_queue); + wake_up_interruptible_all(&master->lock.lock_queue); } break; case _DRM_AGP: diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 46bb923b097c..7b251dd70811 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -151,7 +151,7 @@ static void drm_master_destroy(struct kref *kref) dev->sigdata.lock = NULL; master->lock.hw_lock = NULL; master->lock.file_priv = NULL; - wake_up_interruptible(&master->lock.lock_queue); + wake_up_interruptible_all(&master->lock.lock_queue); } drm_free(master, sizeof(*master), DRM_MEM_DRIVER); -- cgit v1.2.3 From fda714c29cdf360464059044b221450decb4b913 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 2 Mar 2009 11:10:56 +0100 Subject: drm: Avoid client deadlocks when the master disappears. This is done by 1) Wake up lock waiters when we close the master file descriptor. Not when the master structure is removed, since the latter requires the waiters themselves to release the refcount on the master structure -> Deadlock. 2) Send a SIGTERM to all clients waiting for the lock. Normally these clients will get a SIGPIPE when the X server dies, but clients may also spin trying to grab the DRM lock, without getting any sort of notification. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 14 ++++++++++++++ drivers/gpu/drm/drm_lock.c | 1 + drivers/gpu/drm/drm_stub.c | 8 -------- 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 6c020fe5431c..f52663ebe016 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -484,6 +484,7 @@ int drm_release(struct inode *inode, struct file *filp) mutex_lock(&dev->struct_mutex); if (file_priv->is_master) { + struct drm_master *master = file_priv->master; struct drm_file *temp; list_for_each_entry(temp, &dev->filelist, lhead) { if ((temp->master == file_priv->master) && @@ -491,6 +492,19 @@ int drm_release(struct inode *inode, struct file *filp) temp->authenticated = 0; } + /** + * Since the master is disappearing, so is the + * possibility to lock. + */ + + if (master->lock.hw_lock) { + if (dev->sigdata.lock == master->lock.hw_lock) + dev->sigdata.lock = NULL; + master->lock.hw_lock = NULL; + master->lock.file_priv = NULL; + wake_up_interruptible_all(&master->lock.lock_queue); + } + if (file_priv->minor->master == file_priv->master) { /* drop the reference held my the minor */ drm_master_put(&file_priv->minor->master); diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index b03586fdabbd..e2f70a516c34 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -80,6 +80,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) __set_current_state(TASK_INTERRUPTIBLE); if (!master->lock.hw_lock) { /* Device has been unregistered */ + send_sig(SIGTERM, current, 0); ret = -EINTR; break; } diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 7b251dd70811..096e2a37446d 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -146,14 +146,6 @@ static void drm_master_destroy(struct kref *kref) drm_ht_remove(&master->magiclist); - if (master->lock.hw_lock) { - if (dev->sigdata.lock == master->lock.hw_lock) - dev->sigdata.lock = NULL; - master->lock.hw_lock = NULL; - master->lock.file_priv = NULL; - wake_up_interruptible_all(&master->lock.lock_queue); - } - drm_free(master, sizeof(*master), DRM_MEM_DRIVER); } -- cgit v1.2.3 From 299eb93c5f651b2bc368ada67d8471e4c575fa21 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 24 Feb 2009 22:14:12 -0800 Subject: drm/i915: Fix use-before-null-check in i915_irq_emit(). This could be triggered by a client asking to emit an irq when the device wasn't initialized. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_irq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 548ff2c66431..87b6b603469e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -383,12 +383,13 @@ int i915_irq_emit(struct drm_device *dev, void *data, drm_i915_irq_emit_t *emit = data; int result; - RING_LOCK_TEST_WITH_RETURN(dev, file_priv); - if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } + + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); + mutex_lock(&dev->struct_mutex); result = i915_emit_irq(dev); mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3