Commit 8639dad8 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/i915: Save/restore HWS_PGA on suspend/resume
  drm: move drm vblank initialization/cleanup to driver load/unload
  drm/i915: execbuffer pins objects, no need to ensure they're still in the GTT
  drm/i915: Always read pipestat in irq_handler
  drm/i915: Subtract total pinned bytes from available aperture size
  drm/i915: Avoid BUG_ONs on VT switch with a wedged chipset.
  drm/i915: Remove IMR masking during interrupt handler, and restart it if needed.
  drm/i915: Manage PIPESTAT to control vblank interrupts instead of IMR.
parents 9297524f 461cba2d
...@@ -305,6 +305,8 @@ static void drm_cleanup(struct drm_device * dev) ...@@ -305,6 +305,8 @@ static void drm_cleanup(struct drm_device * dev)
return; return;
} }
drm_vblank_cleanup(dev);
drm_lastclose(dev); drm_lastclose(dev);
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
......
...@@ -94,7 +94,7 @@ static void vblank_disable_fn(unsigned long arg) ...@@ -94,7 +94,7 @@ static void vblank_disable_fn(unsigned long arg)
} }
} }
static void drm_vblank_cleanup(struct drm_device *dev) void drm_vblank_cleanup(struct drm_device *dev)
{ {
/* Bail if the driver didn't call drm_vblank_init() */ /* Bail if the driver didn't call drm_vblank_init() */
if (dev->num_crtcs == 0) if (dev->num_crtcs == 0)
...@@ -278,8 +278,6 @@ int drm_irq_uninstall(struct drm_device * dev) ...@@ -278,8 +278,6 @@ int drm_irq_uninstall(struct drm_device * dev)
free_irq(dev->pdev->irq, dev); free_irq(dev->pdev->irq, dev);
drm_vblank_cleanup(dev);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_irq_uninstall); EXPORT_SYMBOL(drm_irq_uninstall);
......
...@@ -856,6 +856,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -856,6 +856,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
spin_lock_init(&dev_priv->user_irq_lock); spin_lock_init(&dev_priv->user_irq_lock);
ret = drm_vblank_init(dev, I915_NUM_PIPE);
if (ret) {
(void) i915_driver_unload(dev);
return ret;
}
return ret; return ret;
} }
......
...@@ -47,6 +47,8 @@ enum pipe { ...@@ -47,6 +47,8 @@ enum pipe {
PIPE_B, PIPE_B,
}; };
#define I915_NUM_PIPE 2
/* Interface history: /* Interface history:
* *
* 1.1: Original. * 1.1: Original.
...@@ -132,6 +134,7 @@ typedef struct drm_i915_private { ...@@ -132,6 +134,7 @@ typedef struct drm_i915_private {
int user_irq_refcount; int user_irq_refcount;
/** Cached value of IMR to avoid reads in updating the bitfield */ /** Cached value of IMR to avoid reads in updating the bitfield */
u32 irq_mask_reg; u32 irq_mask_reg;
u32 pipestat[2];
int tex_lru_log_granularity; int tex_lru_log_granularity;
int allow_batchbuffer; int allow_batchbuffer;
...@@ -147,6 +150,7 @@ typedef struct drm_i915_private { ...@@ -147,6 +150,7 @@ typedef struct drm_i915_private {
u32 saveDSPBCNTR; u32 saveDSPBCNTR;
u32 saveDSPARB; u32 saveDSPARB;
u32 saveRENDERSTANDBY; u32 saveRENDERSTANDBY;
u32 saveHWS;
u32 savePIPEACONF; u32 savePIPEACONF;
u32 savePIPEBCONF; u32 savePIPEBCONF;
u32 savePIPEASRC; u32 savePIPEASRC;
...@@ -446,6 +450,13 @@ extern int i915_vblank_swap(struct drm_device *dev, void *data, ...@@ -446,6 +450,13 @@ extern int i915_vblank_swap(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask); extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
void
i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
void
i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
/* i915_mem.c */ /* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data, extern int i915_mem_alloc(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include "i915_drv.h" #include "i915_drv.h"
#include <linux/swap.h> #include <linux/swap.h>
#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
static int static int
i915_gem_object_set_domain(struct drm_gem_object *obj, i915_gem_object_set_domain(struct drm_gem_object *obj,
uint32_t read_domains, uint32_t read_domains,
...@@ -83,20 +85,14 @@ int ...@@ -83,20 +85,14 @@ int
i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_get_aperture *args = data; struct drm_i915_gem_get_aperture *args = data;
struct drm_i915_gem_object *obj_priv;
if (!(dev->driver->driver_features & DRIVER_GEM)) if (!(dev->driver->driver_features & DRIVER_GEM))
return -ENODEV; return -ENODEV;
args->aper_size = dev->gtt_total; args->aper_size = dev->gtt_total;
args->aper_available_size = args->aper_size; args->aper_available_size = (args->aper_size -
atomic_read(&dev->pin_memory));
list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
if (obj_priv->pin_count > 0)
args->aper_available_size -= obj_priv->obj->size;
}
return 0; return 0;
} }
...@@ -1870,17 +1866,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -1870,17 +1866,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
for (i = 0; i < args->buffer_count; i++) { for (i = 0; i < args->buffer_count; i++) {
struct drm_gem_object *obj = object_list[i]; struct drm_gem_object *obj = object_list[i];
struct drm_i915_gem_object *obj_priv = obj->driver_private;
if (obj_priv->gtt_space == NULL) {
/* We evicted the buffer in the process of validating
* our set of buffers in. We could try to recover by
* kicking them everything out and trying again from
* the start.
*/
ret = -ENOMEM;
goto err;
}
/* make sure all previous memory operations have passed */ /* make sure all previous memory operations have passed */
ret = i915_gem_object_set_domain(obj, ret = i915_gem_object_set_domain(obj,
...@@ -2299,29 +2284,52 @@ i915_gem_idle(struct drm_device *dev) ...@@ -2299,29 +2284,52 @@ i915_gem_idle(struct drm_device *dev)
i915_gem_retire_requests(dev); i915_gem_retire_requests(dev);
/* Active and flushing should now be empty as we've if (!dev_priv->mm.wedged) {
* waited for a sequence higher than any pending execbuffer /* Active and flushing should now be empty as we've
*/ * waited for a sequence higher than any pending execbuffer
BUG_ON(!list_empty(&dev_priv->mm.active_list)); */
BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); WARN_ON(!list_empty(&dev_priv->mm.active_list));
WARN_ON(!list_empty(&dev_priv->mm.flushing_list));
/* Request should now be empty as we've also waited
* for the last request in the list
*/
WARN_ON(!list_empty(&dev_priv->mm.request_list));
}
/* Request should now be empty as we've also waited /* Empty the active and flushing lists to inactive. If there's
* for the last request in the list * anything left at this point, it means that we're wedged and
* nothing good's going to happen by leaving them there. So strip
* the GPU domains and just stuff them onto inactive.
*/ */
BUG_ON(!list_empty(&dev_priv->mm.request_list)); while (!list_empty(&dev_priv->mm.active_list)) {
struct drm_i915_gem_object *obj_priv;
/* Move all buffers out of the GTT. */ obj_priv = list_first_entry(&dev_priv->mm.active_list,
struct drm_i915_gem_object,
list);
obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
i915_gem_object_move_to_inactive(obj_priv->obj);
}
while (!list_empty(&dev_priv->mm.flushing_list)) {
struct drm_i915_gem_object *obj_priv;
obj_priv = list_first_entry(&dev_priv->mm.active_list,
struct drm_i915_gem_object,
list);
obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
i915_gem_object_move_to_inactive(obj_priv->obj);
}
/* Move all inactive buffers out of the GTT. */
ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list); ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
WARN_ON(!list_empty(&dev_priv->mm.inactive_list));
if (ret) { if (ret) {
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret; return ret;
} }
BUG_ON(!list_empty(&dev_priv->mm.active_list));
BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
BUG_ON(!list_empty(&dev_priv->mm.request_list));
i915_gem_cleanup_ringbuffer(dev); i915_gem_cleanup_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
......
This diff is collapsed.
...@@ -235,17 +235,15 @@ void opregion_enable_asle(struct drm_device *dev) ...@@ -235,17 +235,15 @@ void opregion_enable_asle(struct drm_device *dev)
struct opregion_asle *asle = dev_priv->opregion.asle; struct opregion_asle *asle = dev_priv->opregion.asle;
if (asle) { if (asle) {
u32 pipeb_stats = I915_READ(PIPEBSTAT);
if (IS_MOBILE(dev)) { if (IS_MOBILE(dev)) {
/* Many devices trigger events with a write to the unsigned long irqflags;
legacy backlight controller, so we need to ensure
that it's able to generate interrupts */ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
I915_WRITE(PIPEBSTAT, pipeb_stats |= i915_enable_pipestat(dev_priv, 1,
I915_LEGACY_BLC_EVENT_ENABLE); I915_LEGACY_BLC_EVENT_ENABLE);
i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT | spin_unlock_irqrestore(&dev_priv->user_irq_lock,
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT); irqflags);
} else }
i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT);
asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN | asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
ASLE_PFMB_EN; ASLE_PFMB_EN;
......
...@@ -244,6 +244,9 @@ int i915_save_state(struct drm_device *dev) ...@@ -244,6 +244,9 @@ int i915_save_state(struct drm_device *dev)
if (IS_I965G(dev) && IS_MOBILE(dev)) if (IS_I965G(dev) && IS_MOBILE(dev))
dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
/* Hardware status page */
dev_priv->saveHWS = I915_READ(HWS_PGA);
/* Display arbitration control */ /* Display arbitration control */
dev_priv->saveDSPARB = I915_READ(DSPARB); dev_priv->saveDSPARB = I915_READ(DSPARB);
...@@ -373,6 +376,9 @@ int i915_restore_state(struct drm_device *dev) ...@@ -373,6 +376,9 @@ int i915_restore_state(struct drm_device *dev)
if (IS_I965G(dev) && IS_MOBILE(dev)) if (IS_I965G(dev) && IS_MOBILE(dev))
I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY); I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
/* Hardware status page */
I915_WRITE(HWS_PGA, dev_priv->saveHWS);
/* Display arbitration */ /* Display arbitration */
I915_WRITE(DSPARB, dev_priv->saveDSPARB); I915_WRITE(DSPARB, dev_priv->saveDSPARB);
......
...@@ -396,6 +396,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf) ...@@ -396,6 +396,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
int mga_driver_load(struct drm_device * dev, unsigned long flags) int mga_driver_load(struct drm_device * dev, unsigned long flags)
{ {
drm_mga_private_t *dev_priv; drm_mga_private_t *dev_priv;
int ret;
dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
if (!dev_priv) if (!dev_priv)
...@@ -415,6 +416,13 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags) ...@@ -415,6 +416,13 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags)
dev->types[7] = _DRM_STAT_PRIMARY; dev->types[7] = _DRM_STAT_PRIMARY;
dev->types[8] = _DRM_STAT_SECONDARY; dev->types[8] = _DRM_STAT_SECONDARY;
ret = drm_vblank_init(dev, 1);
if (ret) {
(void) mga_driver_unload(dev);
return ret;
}
return 0; return 0;
} }
......
...@@ -152,11 +152,6 @@ void mga_driver_irq_preinstall(struct drm_device * dev) ...@@ -152,11 +152,6 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
int mga_driver_irq_postinstall(struct drm_device *dev) int mga_driver_irq_postinstall(struct drm_device *dev)
{ {
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
int ret;
ret = drm_vblank_init(dev, 1);
if (ret)
return ret;
DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
......
...@@ -45,6 +45,7 @@ static struct drm_driver driver = { ...@@ -45,6 +45,7 @@ static struct drm_driver driver = {
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.dev_priv_size = sizeof(drm_r128_buf_priv_t), .dev_priv_size = sizeof(drm_r128_buf_priv_t),
.load = r128_driver_load,
.preclose = r128_driver_preclose, .preclose = r128_driver_preclose,
.lastclose = r128_driver_lastclose, .lastclose = r128_driver_lastclose,
.get_vblank_counter = r128_get_vblank_counter, .get_vblank_counter = r128_get_vblank_counter,
...@@ -84,6 +85,11 @@ static struct drm_driver driver = { ...@@ -84,6 +85,11 @@ static struct drm_driver driver = {
.patchlevel = DRIVER_PATCHLEVEL, .patchlevel = DRIVER_PATCHLEVEL,
}; };
int r128_driver_load(struct drm_device * dev, unsigned long flags)
{
return drm_vblank_init(dev, 1);
}
static int __init r128_init(void) static int __init r128_init(void)
{ {
driver.num_ioctls = r128_max_ioctl; driver.num_ioctls = r128_max_ioctl;
......
...@@ -159,6 +159,7 @@ extern void r128_driver_irq_preinstall(struct drm_device * dev); ...@@ -159,6 +159,7 @@ extern void r128_driver_irq_preinstall(struct drm_device * dev);
extern int r128_driver_irq_postinstall(struct drm_device *dev); extern int r128_driver_irq_postinstall(struct drm_device *dev);
extern void r128_driver_irq_uninstall(struct drm_device * dev); extern void r128_driver_irq_uninstall(struct drm_device * dev);
extern void r128_driver_lastclose(struct drm_device * dev); extern void r128_driver_lastclose(struct drm_device * dev);
extern int r128_driver_load(struct drm_device * dev, unsigned long flags);
extern void r128_driver_preclose(struct drm_device * dev, extern void r128_driver_preclose(struct drm_device * dev,
struct drm_file *file_priv); struct drm_file *file_priv);
......
...@@ -102,7 +102,7 @@ void r128_driver_irq_preinstall(struct drm_device * dev) ...@@ -102,7 +102,7 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
int r128_driver_irq_postinstall(struct drm_device *dev) int r128_driver_irq_postinstall(struct drm_device *dev)
{ {
return drm_vblank_init(dev, 1); return 0;
} }
void r128_driver_irq_uninstall(struct drm_device * dev) void r128_driver_irq_uninstall(struct drm_device * dev)
......
...@@ -1757,6 +1757,12 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1757,6 +1757,12 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
if (ret != 0) if (ret != 0)
return ret; return ret;
ret = drm_vblank_init(dev, 2);
if (ret) {
radeon_driver_unload(dev);
return ret;
}
DRM_DEBUG("%s card detected\n", DRM_DEBUG("%s card detected\n",
((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
return ret; return ret;
......
...@@ -337,15 +337,10 @@ int radeon_driver_irq_postinstall(struct drm_device *dev) ...@@ -337,15 +337,10 @@ int radeon_driver_irq_postinstall(struct drm_device *dev)
{ {
drm_radeon_private_t *dev_priv = drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private; (drm_radeon_private_t *) dev->dev_private;
int ret;
atomic_set(&dev_priv->swi_emitted, 0); atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
ret = drm_vblank_init(dev, 2);
if (ret)
return ret;
dev->max_vblank_count = 0x001fffff; dev->max_vblank_count = 0x001fffff;
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
......
...@@ -314,7 +314,6 @@ int via_driver_irq_postinstall(struct drm_device *dev) ...@@ -314,7 +314,6 @@ int via_driver_irq_postinstall(struct drm_device *dev)
if (!dev_priv) if (!dev_priv)
return -EINVAL; return -EINVAL;
drm_vblank_init(dev, 1);
status = VIA_READ(VIA_REG_INTERRUPT); status = VIA_READ(VIA_REG_INTERRUPT);
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
| dev_priv->irq_enable_mask); | dev_priv->irq_enable_mask);
......
...@@ -107,8 +107,17 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset) ...@@ -107,8 +107,17 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset)
ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
if (ret) { if (ret) {
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
return ret;
} }
return ret;
ret = drm_vblank_init(dev, 1);
if (ret) {
drm_sman_takedown(&dev_priv->sman);
drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
return ret;
}
return 0;
} }
int via_driver_unload(struct drm_device *dev) int via_driver_unload(struct drm_device *dev)
......
...@@ -1151,6 +1151,7 @@ extern u32 drm_vblank_count(struct drm_device *dev, int crtc); ...@@ -1151,6 +1151,7 @@ extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
extern void drm_handle_vblank(struct drm_device *dev, int crtc); extern void drm_handle_vblank(struct drm_device *dev, int crtc);
extern int drm_vblank_get(struct drm_device *dev, int crtc); extern int drm_vblank_get(struct drm_device *dev, int crtc);
extern void drm_vblank_put(struct drm_device *dev, int crtc); extern void drm_vblank_put(struct drm_device *dev, int crtc);
extern void drm_vblank_cleanup(struct drm_device *dev);
/* Modesetting support */ /* Modesetting support */
extern int drm_modeset_ctl(struct drm_device *dev, void *data, extern int drm_modeset_ctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
......
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