]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Aug 2010 18:03:27 +0000 (11:03 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Aug 2010 18:03:27 +0000 (11:03 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel: (58 commits)
  drm/i915,intel_agp: Add support for Sandybridge D0
  drm/i915: fix render pipe control notify on sandybridge
  agp/intel: set 40-bit dma mask on Sandybridge
  drm/i915: Remove the conflicting BUG_ON()
  drm/i915/suspend: s/IS_IRONLAKE/HAS_PCH_SPLIT/
  drm/i915/suspend: Flush register writes before busy-waiting.
  i915: disable DAC on Ironlake also when doing CRT load detection.
  drm/i915: wait for actual vblank, not just 20ms
  drm/i915: make sure eDP PLL is enabled at the right time
  drm/i915: fix VGA plane disable for Ironlake+
  drm/i915: eDP mode set sequence corrections
  drm/i915: add panel reset workaround
  drm/i915: Enable RC6 on Ironlake.
  drm/i915/sdvo: Only set is_lvds if we have a valid fixed mode.
  drm/i915: Set up a render context on Ironlake
  drm/i915 invalidate indirect state pointers at end of ring exec
  drm/i915: Wake-up wait_request() from elapsed hang-check (v2)
  drm/i915: Apply i830 errata for cursor alignment
  drm/i915: Only update i845/i865 CURBASE when disabled (v2)
  drm/i915: FBC is updated within set_base() so remove second call in mode_set()
  ...

1  2 
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_opregion.c
drivers/gpu/drm/i915/intel_display.c

index 0758c7802e6b7e59e6f8993296a64856760cbd65,994e9f2d688b383ca32895ae16176630784cdcd0..df5a7135c2614c8de55e309c5dfad82efcf618ac
@@@ -35,6 -35,7 +35,7 @@@
  #include <linux/swap.h>
  #include <linux/pci.h>
  
+ static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj);
  static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
  static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
  static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
@@@ -48,8 -49,6 +49,6 @@@ static int i915_gem_object_wait_renderi
  static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
                                           unsigned alignment);
  static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
- static int i915_gem_evict_something(struct drm_device *dev, int min_size);
- static int i915_gem_evict_from_inactive_list(struct drm_device *dev);
  static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
                                struct drm_i915_gem_pwrite *args,
                                struct drm_file *file_priv);
@@@ -58,6 -57,14 +57,14 @@@ static void i915_gem_free_object_tail(s
  static LIST_HEAD(shrink_list);
  static DEFINE_SPINLOCK(shrink_list_lock);
  
+ static inline bool
+ i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv)
+ {
+       return obj_priv->gtt_space &&
+               !obj_priv->active &&
+               obj_priv->pin_count == 0;
+ }
  int i915_gem_do_init(struct drm_device *dev, unsigned long start,
                     unsigned long end)
  {
@@@ -313,7 -320,8 +320,8 @@@ i915_gem_object_get_pages_or_evict(stru
        if (ret == -ENOMEM) {
                struct drm_device *dev = obj->dev;
  
-               ret = i915_gem_evict_something(dev, obj->size);
+               ret = i915_gem_evict_something(dev, obj->size,
+                                              i915_gem_get_gtt_alignment(obj));
                if (ret)
                        return ret;
  
@@@ -456,7 -464,7 +464,7 @@@ i915_gem_pread_ioctl(struct drm_device 
  
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (obj == NULL)
 -              return -EBADF;
 +              return -ENOENT;
        obj_priv = to_intel_bo(obj);
  
        /* Bounds check source.
@@@ -919,7 -927,7 +927,7 @@@ i915_gem_pwrite_ioctl(struct drm_devic
  
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (obj == NULL)
 -              return -EBADF;
 +              return -ENOENT;
        obj_priv = to_intel_bo(obj);
  
        /* Bounds check destination.
@@@ -1002,7 -1010,7 +1010,7 @@@ i915_gem_set_domain_ioctl(struct drm_de
  
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (obj == NULL)
 -              return -EBADF;
 +              return -ENOENT;
        obj_priv = to_intel_bo(obj);
  
        mutex_lock(&dev->struct_mutex);
                ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
        }
  
+       
+       /* Maintain LRU order of "inactive" objects */
+       if (ret == 0 && i915_gem_object_is_inactive(obj_priv))
+               list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
        drm_gem_object_unreference(obj);
        mutex_unlock(&dev->struct_mutex);
        return ret;
@@@ -1060,7 -1073,7 +1073,7 @@@ i915_gem_sw_finish_ioctl(struct drm_dev
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (obj == NULL) {
                mutex_unlock(&dev->struct_mutex);
 -              return -EBADF;
 +              return -ENOENT;
        }
  
  #if WATCH_BUF
@@@ -1099,7 -1112,7 +1112,7 @@@ i915_gem_mmap_ioctl(struct drm_device *
  
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (obj == NULL)
 -              return -EBADF;
 +              return -ENOENT;
  
        offset = args->offset;
  
@@@ -1137,7 -1150,7 +1150,7 @@@ int i915_gem_fault(struct vm_area_struc
  {
        struct drm_gem_object *obj = vma->vm_private_data;
        struct drm_device *dev = obj->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        pgoff_t page_offset;
        unsigned long pfn;
                if (ret)
                        goto unlock;
  
-               list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
                ret = i915_gem_object_set_to_gtt_domain(obj, write);
                if (ret)
                        goto unlock;
                        goto unlock;
        }
  
+       if (i915_gem_object_is_inactive(obj_priv))
+               list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
        pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
                page_offset;
  
@@@ -1363,7 -1377,6 +1377,6 @@@ i915_gem_mmap_gtt_ioctl(struct drm_devi
                        struct drm_file *file_priv)
  {
        struct drm_i915_gem_mmap_gtt *args = data;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_gem_object *obj;
        struct drm_i915_gem_object *obj_priv;
        int ret;
  
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (obj == NULL)
 -              return -EBADF;
 +              return -ENOENT;
  
        mutex_lock(&dev->struct_mutex);
  
                        mutex_unlock(&dev->struct_mutex);
                        return ret;
                }
-               list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
        }
  
        drm_gem_object_unreference(obj);
@@@ -1493,9 -1505,16 +1505,16 @@@ i915_gem_object_truncate(struct drm_gem
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        struct inode *inode;
  
+       /* Our goal here is to return as much of the memory as
+        * is possible back to the system as we are called from OOM.
+        * To do this we must instruct the shmfs to drop all of its
+        * backing pages, *now*. Here we mirror the actions taken
+        * when by shmem_delete_inode() to release the backing store.
+        */
        inode = obj->filp->f_path.dentry->d_inode;
-       if (inode->i_op->truncate)
-               inode->i_op->truncate (inode);
+       truncate_inode_pages(inode->i_mapping, 0);
+       if (inode->i_op->truncate_range)
+               inode->i_op->truncate_range(inode, 0, (loff_t)-1);
  
        obj_priv->madv = __I915_MADV_PURGED;
  }
@@@ -1887,19 -1906,6 +1906,6 @@@ i915_gem_flush(struct drm_device *dev
                                flush_domains);
  }
  
- static void
- i915_gem_flush_ring(struct drm_device *dev,
-              uint32_t invalidate_domains,
-              uint32_t flush_domains,
-              struct intel_ring_buffer *ring)
- {
-       if (flush_domains & I915_GEM_DOMAIN_CPU)
-               drm_agp_chipset_flush(dev);
-       ring->flush(dev, ring,
-                       invalidate_domains,
-                       flush_domains);
- }
  /**
   * Ensures that all rendering to the object has completed and the object is
   * safe to unbind from the GTT or access from the CPU.
@@@ -1973,8 -1979,6 +1979,6 @@@ i915_gem_object_unbind(struct drm_gem_o
         * cause memory corruption through use-after-free.
         */
  
-       BUG_ON(obj_priv->active);
        /* release the fence reg _after_ flushing */
        if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
                i915_gem_clear_fence_reg(obj);
        return ret;
  }
  
- static struct drm_gem_object *
- i915_gem_find_inactive_object(struct drm_device *dev, int min_size)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_gem_object *obj_priv;
-       struct drm_gem_object *best = NULL;
-       struct drm_gem_object *first = NULL;
-       /* Try to find the smallest clean object */
-       list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
-               struct drm_gem_object *obj = &obj_priv->base;
-               if (obj->size >= min_size) {
-                       if ((!obj_priv->dirty ||
-                            i915_gem_object_is_purgeable(obj_priv)) &&
-                           (!best || obj->size < best->size)) {
-                               best = obj;
-                               if (best->size == min_size)
-                                       return best;
-                       }
-                       if (!first)
-                           first = obj;
-               }
-       }
-       return best ? best : first;
- }
- static int
+ int
  i915_gpu_idle(struct drm_device *dev)
  {
        drm_i915_private_t *dev_priv = dev->dev_private;
        return ret;
  }
  
- static int
- i915_gem_evict_everything(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       int ret;
-       bool lists_empty;
-       spin_lock(&dev_priv->mm.active_list_lock);
-       lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
-                      list_empty(&dev_priv->mm.flushing_list) &&
-                      list_empty(&dev_priv->render_ring.active_list) &&
-                      (!HAS_BSD(dev)
-                       || list_empty(&dev_priv->bsd_ring.active_list)));
-       spin_unlock(&dev_priv->mm.active_list_lock);
-       if (lists_empty)
-               return -ENOSPC;
-       /* Flush everything (on to the inactive lists) and evict */
-       ret = i915_gpu_idle(dev);
-       if (ret)
-               return ret;
-       BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
-       ret = i915_gem_evict_from_inactive_list(dev);
-       if (ret)
-               return ret;
-       spin_lock(&dev_priv->mm.active_list_lock);
-       lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
-                      list_empty(&dev_priv->mm.flushing_list) &&
-                      list_empty(&dev_priv->render_ring.active_list) &&
-                      (!HAS_BSD(dev)
-                       || list_empty(&dev_priv->bsd_ring.active_list)));
-       spin_unlock(&dev_priv->mm.active_list_lock);
-       BUG_ON(!lists_empty);
-       return 0;
- }
- static int
- i915_gem_evict_something(struct drm_device *dev, int min_size)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_gem_object *obj;
-       int ret;
-       struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
-       struct intel_ring_buffer *bsd_ring = &dev_priv->bsd_ring;
-       for (;;) {
-               i915_gem_retire_requests(dev);
-               /* If there's an inactive buffer available now, grab it
-                * and be done.
-                */
-               obj = i915_gem_find_inactive_object(dev, min_size);
-               if (obj) {
-                       struct drm_i915_gem_object *obj_priv;
- #if WATCH_LRU
-                       DRM_INFO("%s: evicting %p\n", __func__, obj);
- #endif
-                       obj_priv = to_intel_bo(obj);
-                       BUG_ON(obj_priv->pin_count != 0);
-                       BUG_ON(obj_priv->active);
-                       /* Wait on the rendering and unbind the buffer. */
-                       return i915_gem_object_unbind(obj);
-               }
-               /* If we didn't get anything, but the ring is still processing
-                * things, wait for the next to finish and hopefully leave us
-                * a buffer to evict.
-                */
-               if (!list_empty(&render_ring->request_list)) {
-                       struct drm_i915_gem_request *request;
-                       request = list_first_entry(&render_ring->request_list,
-                                                  struct drm_i915_gem_request,
-                                                  list);
-                       ret = i915_wait_request(dev,
-                                       request->seqno, request->ring);
-                       if (ret)
-                               return ret;
-                       continue;
-               }
-               if (HAS_BSD(dev) && !list_empty(&bsd_ring->request_list)) {
-                       struct drm_i915_gem_request *request;
-                       request = list_first_entry(&bsd_ring->request_list,
-                                                  struct drm_i915_gem_request,
-                                                  list);
-                       ret = i915_wait_request(dev,
-                                       request->seqno, request->ring);
-                       if (ret)
-                               return ret;
-                       continue;
-               }
-               /* If we didn't have anything on the request list but there
-                * are buffers awaiting a flush, emit one and try again.
-                * When we wait on it, those buffers waiting for that flush
-                * will get moved to inactive.
-                */
-               if (!list_empty(&dev_priv->mm.flushing_list)) {
-                       struct drm_i915_gem_object *obj_priv;
-                       /* Find an object that we can immediately reuse */
-                       list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, list) {
-                               obj = &obj_priv->base;
-                               if (obj->size >= min_size)
-                                       break;
-                               obj = NULL;
-                       }
-                       if (obj != NULL) {
-                               uint32_t seqno;
-                               i915_gem_flush_ring(dev,
-                                              obj->write_domain,
-                                              obj->write_domain,
-                                              obj_priv->ring);
-                               seqno = i915_add_request(dev, NULL,
-                                               obj->write_domain,
-                                               obj_priv->ring);
-                               if (seqno == 0)
-                                       return -ENOMEM;
-                               continue;
-                       }
-               }
-               /* If we didn't do any of the above, there's no single buffer
-                * large enough to swap out for the new one, so just evict
-                * everything and start again. (This should be rare.)
-                */
-               if (!list_empty (&dev_priv->mm.inactive_list))
-                       return i915_gem_evict_from_inactive_list(dev);
-               else
-                       return i915_gem_evict_everything(dev);
-       }
- }
  int
  i915_gem_object_get_pages(struct drm_gem_object *obj,
                          gfp_t gfpmask)
@@@ -2666,7 -2494,7 +2494,7 @@@ i915_gem_object_bind_to_gtt(struct drm_
  #if WATCH_LRU
                DRM_INFO("%s: GTT full, evicting something\n", __func__);
  #endif
-               ret = i915_gem_evict_something(dev, obj->size);
+               ret = i915_gem_evict_something(dev, obj->size, alignment);
                if (ret)
                        return ret;
  
  
                if (ret == -ENOMEM) {
                        /* first try to clear up some space from the GTT */
-                       ret = i915_gem_evict_something(dev, obj->size);
+                       ret = i915_gem_evict_something(dev, obj->size,
+                                                      alignment);
                        if (ret) {
                                /* now try to shrink everyone else */
                                if (gfpmask) {
                drm_mm_put_block(obj_priv->gtt_space);
                obj_priv->gtt_space = NULL;
  
-               ret = i915_gem_evict_something(dev, obj->size);
+               ret = i915_gem_evict_something(dev, obj->size, alignment);
                if (ret)
                        return ret;
  
        atomic_inc(&dev->gtt_count);
        atomic_add(obj->size, &dev->gtt_memory);
  
+       /* keep track of bounds object by adding it to the inactive list */
+       list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
        /* Assert that the object is not currently in any GPU domain. As it
         * wasn't in the GTT, there shouldn't be any way it could have been in
         * a GPU cache
@@@ -3117,6 -2949,7 +2949,7 @@@ static voi
  i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
  {
        struct drm_device               *dev = obj->dev;
+       drm_i915_private_t              *dev_priv = dev->dev_private;
        struct drm_i915_gem_object      *obj_priv = to_intel_bo(obj);
        uint32_t                        invalidate_domains = 0;
        uint32_t                        flush_domains = 0;
                obj->pending_write_domain = obj->write_domain;
        obj->read_domains = obj->pending_read_domains;
  
+       if (flush_domains & I915_GEM_GPU_DOMAINS) {
+               if (obj_priv->ring == &dev_priv->render_ring)
+                       dev_priv->flush_rings |= FLUSH_RENDER_RING;
+               else if (obj_priv->ring == &dev_priv->bsd_ring)
+                       dev_priv->flush_rings |= FLUSH_BSD_RING;
+       }
        dev->invalidate_domains |= invalidate_domains;
        dev->flush_domains |= flush_domains;
  #if WATCH_BUF
@@@ -3364,7 -3204,7 +3204,7 @@@ i915_gem_object_pin_and_relocate(struc
                                                   reloc->target_handle);
                if (target_obj == NULL) {
                        i915_gem_object_unpin(obj);
 -                      return -EBADF;
 +                      return -ENOENT;
                }
                target_obj_priv = to_intel_bo(target_obj);
  
@@@ -3718,7 -3558,6 +3558,6 @@@ i915_gem_do_execbuffer(struct drm_devic
                ring = &dev_priv->render_ring;
        }
  
        if (args->buffer_count < 1) {
                DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
                return -EINVAL;
                                   exec_list[i].handle, i);
                        /* prevent error path from reading uninitialized data */
                        args->buffer_count = i + 1;
 -                      ret = -EBADF;
 +                      ret = -ENOENT;
                        goto err;
                }
  
                                   object_list[i]);
                        /* prevent error path from reading uninitialized data */
                        args->buffer_count = i + 1;
 -                      ret = -EBADF;
 +                      ret = -EINVAL;
                        goto err;
                }
                obj_priv->in_execbuffer = true;
         */
        dev->invalidate_domains = 0;
        dev->flush_domains = 0;
+       dev_priv->flush_rings = 0;
  
        for (i = 0; i < args->buffer_count; i++) {
                struct drm_gem_object *obj = object_list[i];
                i915_gem_flush(dev,
                               dev->invalidate_domains,
                               dev->flush_domains);
-               if (dev->flush_domains & I915_GEM_GPU_DOMAINS) {
+               if (dev_priv->flush_rings & FLUSH_RENDER_RING)
                        (void)i915_add_request(dev, file_priv,
-                                       dev->flush_domains,
-                                       &dev_priv->render_ring);
-                       if (HAS_BSD(dev))
-                               (void)i915_add_request(dev, file_priv,
-                                               dev->flush_domains,
-                                               &dev_priv->bsd_ring);
-               }
+                                              dev->flush_domains,
+                                              &dev_priv->render_ring);
+               if (dev_priv->flush_rings & FLUSH_BSD_RING)
+                       (void)i915_add_request(dev, file_priv,
+                                              dev->flush_domains,
+                                              &dev_priv->bsd_ring);
        }
  
        for (i = 0; i < args->buffer_count; i++) {
@@@ -4192,6 -4030,10 +4030,10 @@@ i915_gem_object_pin(struct drm_gem_obje
                if (alignment == 0)
                        alignment = i915_gem_get_gtt_alignment(obj);
                if (obj_priv->gtt_offset & (alignment - 1)) {
+                       WARN(obj_priv->pin_count,
+                            "bo is already pinned with incorrect alignment:"
+                            " offset=%x, req.alignment=%x\n",
+                            obj_priv->gtt_offset, alignment);
                        ret = i915_gem_object_unbind(obj);
                        if (ret)
                                return ret;
                atomic_inc(&dev->pin_count);
                atomic_add(obj->size, &dev->pin_memory);
                if (!obj_priv->active &&
-                   (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0 &&
-                   !list_empty(&obj_priv->list))
+                   (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
                        list_del_init(&obj_priv->list);
        }
        i915_verify_inactive(dev, __FILE__, __LINE__);
@@@ -4265,7 -4106,7 +4106,7 @@@ i915_gem_pin_ioctl(struct drm_device *d
                DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n",
                          args->handle);
                mutex_unlock(&dev->struct_mutex);
 -              return -EBADF;
 +              return -ENOENT;
        }
        obj_priv = to_intel_bo(obj);
  
@@@ -4321,7 -4162,7 +4162,7 @@@ i915_gem_unpin_ioctl(struct drm_device 
                DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n",
                          args->handle);
                mutex_unlock(&dev->struct_mutex);
 -              return -EBADF;
 +              return -ENOENT;
        }
  
        obj_priv = to_intel_bo(obj);
@@@ -4355,26 -4196,38 +4196,38 @@@ i915_gem_busy_ioctl(struct drm_device *
        if (obj == NULL) {
                DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n",
                          args->handle);
 -              return -EBADF;
 +              return -ENOENT;
        }
  
        mutex_lock(&dev->struct_mutex);
-       /* Update the active list for the hardware's current position.
-        * Otherwise this only updates on a delayed timer or when irqs are
-        * actually unmasked, and our working set ends up being larger than
-        * required.
-        */
-       i915_gem_retire_requests(dev);
  
-       obj_priv = to_intel_bo(obj);
-       /* Don't count being on the flushing list against the object being
-        * done.  Otherwise, a buffer left on the flushing list but not getting
-        * flushed (because nobody's flushing that domain) won't ever return
-        * unbusy and get reused by libdrm's bo cache.  The other expected
-        * consumer of this interface, OpenGL's occlusion queries, also specs
-        * that the objects get unbusy "eventually" without any interference.
+       /* Count all active objects as busy, even if they are currently not used
+        * by the gpu. Users of this interface expect objects to eventually
+        * become non-busy without any further actions, therefore emit any
+        * necessary flushes here.
         */
-       args->busy = obj_priv->active && obj_priv->last_rendering_seqno != 0;
+       obj_priv = to_intel_bo(obj);
+       args->busy = obj_priv->active;
+       if (args->busy) {
+               /* Unconditionally flush objects, even when the gpu still uses this
+                * object. Userspace calling this function indicates that it wants to
+                * use this buffer rather sooner than later, so issuing the required
+                * flush earlier is beneficial.
+                */
+               if (obj->write_domain) {
+                       i915_gem_flush(dev, 0, obj->write_domain);
+                       (void)i915_add_request(dev, file_priv, obj->write_domain, obj_priv->ring);
+               }
+               /* Update the active list for the hardware's current position.
+                * Otherwise this only updates on a delayed timer or when irqs
+                * are actually unmasked, and our working set ends up being
+                * larger than required.
+                */
+               i915_gem_retire_requests_ring(dev, obj_priv->ring);
+               args->busy = obj_priv->active;
+       }
  
        drm_gem_object_unreference(obj);
        mutex_unlock(&dev->struct_mutex);
@@@ -4408,7 -4261,7 +4261,7 @@@ i915_gem_madvise_ioctl(struct drm_devic
        if (obj == NULL) {
                DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n",
                          args->handle);
 -              return -EBADF;
 +              return -ENOENT;
        }
  
        mutex_lock(&dev->struct_mutex);
@@@ -4514,30 -4367,6 +4367,6 @@@ void i915_gem_free_object(struct drm_ge
        i915_gem_free_object_tail(obj);
  }
  
- /** Unbinds all inactive objects. */
- static int
- i915_gem_evict_from_inactive_list(struct drm_device *dev)
- {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       while (!list_empty(&dev_priv->mm.inactive_list)) {
-               struct drm_gem_object *obj;
-               int ret;
-               obj = &list_first_entry(&dev_priv->mm.inactive_list,
-                                       struct drm_i915_gem_object,
-                                       list)->base;
-               ret = i915_gem_object_unbind(obj);
-               if (ret != 0) {
-                       DRM_ERROR("Error unbinding object: %d\n", ret);
-                       return ret;
-               }
-       }
-       return 0;
- }
  int
  i915_gem_idle(struct drm_device *dev)
  {
  
        /* Under UMS, be paranoid and evict. */
        if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
-               ret = i915_gem_evict_from_inactive_list(dev);
+               ret = i915_gem_evict_inactive(dev);
                if (ret) {
                        mutex_unlock(&dev->struct_mutex);
                        return ret;
@@@ -4680,6 -4509,8 +4509,8 @@@ i915_gem_init_ringbuffer(struct drm_dev
                        goto cleanup_render_ring;
        }
  
+       dev_priv->next_seqno = 1;
        return 0;
  
  cleanup_render_ring:
@@@ -4841,7 -4672,7 +4672,7 @@@ i915_gem_load(struct drm_device *dev
   * e.g. for cursor + overlay regs
   */
  int i915_gem_init_phys_object(struct drm_device *dev,
-                             int id, int size)
+                             int id, int size, int align)
  {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_phys_object *phys_obj;
  
        phys_obj->id = id;
  
-       phys_obj->handle = drm_pci_alloc(dev, size, 0);
+       phys_obj->handle = drm_pci_alloc(dev, size, align);
        if (!phys_obj->handle) {
                ret = -ENOMEM;
                goto kfree_obj;
@@@ -4938,7 -4769,9 +4769,9 @@@ out
  
  int
  i915_gem_attach_phys_object(struct drm_device *dev,
-                           struct drm_gem_object *obj, int id)
+                           struct drm_gem_object *obj,
+                           int id,
+                           int align)
  {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj_priv;
                i915_gem_detach_phys_object(dev, obj);
        }
  
        /* create a new object */
        if (!dev_priv->mm.phys_objs[id - 1]) {
                ret = i915_gem_init_phys_object(dev, id,
-                                               obj->size);
+                                               obj->size, align);
                if (ret) {
                        DRM_ERROR("failed to init phys object %d size: %zu\n", id, obj->size);
                        goto out;
index d1bf92b99788807759b70436c7f53c48c4487f1e,ce402b2568be733a5c5a3c102a81fd2ab4eefe2b..ea5d3fea4b61a2cd56dc4d2da4bad6fe3d94ea43
@@@ -114,10 -114,6 +114,6 @@@ struct opregion_asle 
  #define ASLE_REQ_MSK           0xf
  
  /* response bits of ASLE irq request */
- #define ASLE_ALS_ILLUM_FAIL    (2<<10)
- #define ASLE_BACKLIGHT_FAIL    (2<<12)
- #define ASLE_PFIT_FAIL         (2<<14)
- #define ASLE_PWM_FREQ_FAIL     (2<<16)
  #define ASLE_ALS_ILLUM_FAILED (1<<10)
  #define ASLE_BACKLIGHT_FAILED (1<<12)
  #define ASLE_PFIT_FAILED      (1<<14)
@@@ -155,11 -151,11 +151,11 @@@ static u32 asle_set_backlight(struct dr
        u32 max_backlight, level, shift;
  
        if (!(bclp & ASLE_BCLP_VALID))
-               return ASLE_BACKLIGHT_FAIL;
+               return ASLE_BACKLIGHT_FAILED;
  
        bclp &= ASLE_BCLP_MSK;
        if (bclp < 0 || bclp > 255)
-               return ASLE_BACKLIGHT_FAIL;
+               return ASLE_BACKLIGHT_FAILED;
  
        blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
        blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2);
@@@ -211,7 -207,7 +207,7 @@@ static u32 asle_set_pfit(struct drm_dev
        /* Panel fitting is currently controlled by the X code, so this is a
           noop until modesetting support works fully */
        if (!(pfit & ASLE_PFIT_VALID))
-               return ASLE_PFIT_FAIL;
+               return ASLE_PFIT_FAILED;
        return 0;
  }
  
@@@ -535,7 -531,6 +531,7 @@@ int intel_opregion_init(struct drm_devi
  err_out:
        iounmap(opregion->header);
        opregion->header = NULL;
 +      acpi_video_register();
        return err;
  }
  
index 5ec10e02341b44f6fa5b6ebe6c6e9f78bd9f2ad2,bdea9464b6783332a0437724a0a0aad85a78c631..23157e1de3bec24339f21ed95fac72bd341ab0fb
@@@ -29,6 -29,7 +29,7 @@@
  #include <linux/i2c.h>
  #include <linux/kernel.h>
  #include <linux/slab.h>
+ #include <linux/vgaarb.h>
  #include "drmP.h"
  #include "intel_drv.h"
  #include "i915_drm.h"
@@@ -976,14 -977,54 +977,54 @@@ intel_find_pll_g4x_dp(const intel_limit
      return true;
  }
  
- void
- intel_wait_for_vblank(struct drm_device *dev)
+ /**
+  * intel_wait_for_vblank - wait for vblank on a given pipe
+  * @dev: drm device
+  * @pipe: pipe to wait for
+  *
+  * Wait for vblank to occur on a given pipe.  Needed for various bits of
+  * mode setting code.
+  */
+ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
  {
-       /* Wait for 20ms, i.e. one cycle at 50hz. */
-       if (in_dbg_master())
-               mdelay(20); /* The kernel debugger cannot call msleep() */
-       else
-               msleep(20);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT);
+       /* Wait for vblank interrupt bit to set */
+       if (wait_for((I915_READ(pipestat_reg) &
+                     PIPE_VBLANK_INTERRUPT_STATUS) == 0,
+                    50, 0))
+               DRM_DEBUG_KMS("vblank wait timed out\n");
+ }
+ /**
+  * intel_wait_for_vblank_off - wait for vblank after disabling a pipe
+  * @dev: drm device
+  * @pipe: pipe to wait for
+  *
+  * After disabling a pipe, we can't wait for vblank in the usual way,
+  * spinning on the vblank interrupt status bit, since we won't actually
+  * see an interrupt when the pipe is disabled.
+  *
+  * So this function waits for the display line value to settle (it
+  * usually ends up stopping at the start of the next frame).
+  */
+ void intel_wait_for_vblank_off(struct drm_device *dev, int pipe)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL);
+       unsigned long timeout = jiffies + msecs_to_jiffies(100);
+       u32 last_line;
+       /* Wait for the display line to settle */
+       do {
+               last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK;
+               mdelay(5);
+       } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) &&
+                time_after(timeout, jiffies));
+       if (time_after(jiffies, timeout))
+               DRM_DEBUG_KMS("vblank wait timed out\n");
  }
  
  /* Parameters have changed, update FBC info */
@@@ -1037,7 -1078,6 +1078,6 @@@ static void i8xx_enable_fbc(struct drm_
  void i8xx_disable_fbc(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long timeout = jiffies + msecs_to_jiffies(1);
        u32 fbc_ctl;
  
        if (!I915_HAS_FBC(dev))
        I915_WRITE(FBC_CONTROL, fbc_ctl);
  
        /* Wait for compressing bit to clear */
-       while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) {
-               if (time_after(jiffies, timeout)) {
-                       DRM_DEBUG_DRIVER("FBC idle timed out\n");
-                       break;
-               }
-               ; /* do nothing */
+       if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10, 0)) {
+               DRM_DEBUG_KMS("FBC idle timed out\n");
+               return;
        }
  
-       intel_wait_for_vblank(dev);
        DRM_DEBUG_KMS("disabled FBC\n");
  }
  
@@@ -1118,7 -1153,6 +1153,6 @@@ void g4x_disable_fbc(struct drm_device 
        dpfc_ctl = I915_READ(DPFC_CONTROL);
        dpfc_ctl &= ~DPFC_CTL_EN;
        I915_WRITE(DPFC_CONTROL, dpfc_ctl);
-       intel_wait_for_vblank(dev);
  
        DRM_DEBUG_KMS("disabled FBC\n");
  }
@@@ -1179,7 -1213,6 +1213,6 @@@ void ironlake_disable_fbc(struct drm_de
        dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
        dpfc_ctl &= ~DPFC_CTL_EN;
        I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
-       intel_wait_for_vblank(dev);
  
        DRM_DEBUG_KMS("disabled FBC\n");
  }
@@@ -1478,7 -1511,7 +1511,7 @@@ intel_pipe_set_base_atomic(struct drm_c
        if ((IS_I965G(dev) || plane == 0))
                intel_update_fbc(crtc, &crtc->mode);
  
-       intel_wait_for_vblank(dev);
+       intel_wait_for_vblank(dev, intel_crtc->pipe);
        intel_increase_pllclock(crtc, true);
  
        return 0;
@@@ -1585,20 -1618,18 +1618,18 @@@ intel_pipe_set_base(struct drm_crtc *cr
                      Start, Offset, x, y, crtc->fb->pitch);
        I915_WRITE(dspstride, crtc->fb->pitch);
        if (IS_I965G(dev)) {
-               I915_WRITE(dspbase, Offset);
-               I915_READ(dspbase);
                I915_WRITE(dspsurf, Start);
-               I915_READ(dspsurf);
                I915_WRITE(dsptileoff, (y << 16) | x);
+               I915_WRITE(dspbase, Offset);
        } else {
                I915_WRITE(dspbase, Start + Offset);
-               I915_READ(dspbase);
        }
+       POSTING_READ(dspbase);
  
        if ((IS_I965G(dev) || plane == 0))
                intel_update_fbc(crtc, &crtc->mode);
  
-       intel_wait_for_vblank(dev);
+       intel_wait_for_vblank(dev, pipe);
  
        if (old_fb) {
                intel_fb = to_intel_framebuffer(old_fb);
        return 0;
  }
  
- /* Disable the VGA plane that we never use */
- static void i915_disable_vga (struct drm_device *dev)
- {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u8 sr1;
-       u32 vga_reg;
-       if (HAS_PCH_SPLIT(dev))
-               vga_reg = CPU_VGACNTRL;
-       else
-               vga_reg = VGACNTRL;
-       if (I915_READ(vga_reg) & VGA_DISP_DISABLE)
-               return;
-       I915_WRITE8(VGA_SR_INDEX, 1);
-       sr1 = I915_READ8(VGA_SR_DATA);
-       I915_WRITE8(VGA_SR_DATA, sr1 | (1 << 5));
-       udelay(100);
-       I915_WRITE(vga_reg, VGA_DISP_DISABLE);
- }
- static void ironlake_disable_pll_edp (struct drm_crtc *crtc)
- {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 dpa_ctl;
-       DRM_DEBUG_KMS("\n");
-       dpa_ctl = I915_READ(DP_A);
-       dpa_ctl &= ~DP_PLL_ENABLE;
-       I915_WRITE(DP_A, dpa_ctl);
- }
- static void ironlake_enable_pll_edp (struct drm_crtc *crtc)
- {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 dpa_ctl;
-       dpa_ctl = I915_READ(DP_A);
-       dpa_ctl |= DP_PLL_ENABLE;
-       I915_WRITE(DP_A, dpa_ctl);
-       udelay(200);
- }
  static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock)
  {
        struct drm_device *dev = crtc->dev;
@@@ -1945,7 -1928,6 +1928,6 @@@ static void ironlake_crtc_dpms(struct d
        int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
        int trans_dpll_sel = (pipe == 0) ? 0 : 1;
        u32 temp;
-       int n;
        u32 pipe_bpc;
  
        temp = I915_READ(pipeconf_reg);
        case DRM_MODE_DPMS_ON:
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
-               DRM_DEBUG_KMS("crtc %d dpms on\n", pipe);
+               DRM_DEBUG_KMS("crtc %d/%d dpms on\n", pipe, plane);
  
                if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
                        temp = I915_READ(PCH_LVDS);
                        }
                }
  
-               if (HAS_eDP) {
-                       /* enable eDP PLL */
-                       ironlake_enable_pll_edp(crtc);
-               } else {
+               if (!HAS_eDP) {
  
                        /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
                        temp = I915_READ(fdi_rx_reg);
                /* Enable panel fitting for LVDS */
                if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
                    || HAS_eDP || intel_pch_has_edp(crtc)) {
-                       temp = I915_READ(pf_ctl_reg);
-                       I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3);
-                       /* currently full aspect */
-                       I915_WRITE(pf_win_pos, 0);
-                       I915_WRITE(pf_win_size,
-                                  (dev_priv->panel_fixed_mode->hdisplay << 16) |
-                                  (dev_priv->panel_fixed_mode->vdisplay));
+                       if (dev_priv->pch_pf_size) {
+                               temp = I915_READ(pf_ctl_reg);
+                               I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3);
+                               I915_WRITE(pf_win_pos, dev_priv->pch_pf_pos);
+                               I915_WRITE(pf_win_size, dev_priv->pch_pf_size);
+                       } else
+                               I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
                }
  
                /* Enable CPU pipe */
                                int reg;
  
                                reg = I915_READ(trans_dp_ctl);
-                               reg &= ~TRANS_DP_PORT_SEL_MASK;
-                               reg = TRANS_DP_OUTPUT_ENABLE |
-                                     TRANS_DP_ENH_FRAMING;
+                               reg &= ~(TRANS_DP_PORT_SEL_MASK |
+                                        TRANS_DP_SYNC_MASK);
+                               reg |= (TRANS_DP_OUTPUT_ENABLE |
+                                       TRANS_DP_ENH_FRAMING);
  
                                if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
                                      reg |= TRANS_DP_HSYNC_ACTIVE_HIGH;
                        I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
                        I915_READ(transconf_reg);
  
-                       while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
-                               ;
+                       if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 10, 0))
+                               DRM_ERROR("failed to enable transcoder\n");
                }
  
                intel_crtc_load_lut(crtc);
  
                intel_update_fbc(crtc, &crtc->mode);
+               break;
  
-       break;
        case DRM_MODE_DPMS_OFF:
-               DRM_DEBUG_KMS("crtc %d dpms off\n", pipe);
+               DRM_DEBUG_KMS("crtc %d/%d dpms off\n", pipe, plane);
  
                drm_vblank_off(dev, pipe);
                /* Disable display plane */
                    dev_priv->display.disable_fbc)
                        dev_priv->display.disable_fbc(dev);
  
-               i915_disable_vga(dev);
                /* disable cpu pipe, disable after all planes disabled */
                temp = I915_READ(pipeconf_reg);
                if ((temp & PIPEACONF_ENABLE) != 0) {
                        I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-                       I915_READ(pipeconf_reg);
-                       n = 0;
                        /* wait for cpu pipe off, pipe state */
-                       while ((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0) {
-                               n++;
-                               if (n < 60) {
-                                       udelay(500);
-                                       continue;
-                               } else {
-                                       DRM_DEBUG_KMS("pipe %d off delay\n",
-                                                               pipe);
-                                       break;
-                               }
-                       }
+                       if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0, 50, 1))
+                               DRM_ERROR("failed to turn off cpu pipe\n");
                } else
                        DRM_DEBUG_KMS("crtc %d is disabled\n", pipe);
  
                temp = I915_READ(transconf_reg);
                if ((temp & TRANS_ENABLE) != 0) {
                        I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE);
-                       I915_READ(transconf_reg);
-                       n = 0;
                        /* wait for PCH transcoder off, transcoder state */
-                       while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) != 0) {
-                               n++;
-                               if (n < 60) {
-                                       udelay(500);
-                                       continue;
-                               } else {
-                                       DRM_DEBUG_KMS("transcoder %d off "
-                                                       "delay\n", pipe);
-                                       break;
-                               }
-                       }
+                       if (wait_for((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0, 50, 1))
+                               DRM_ERROR("failed to disable transcoder\n");
                }
  
                temp = I915_READ(transconf_reg);
                I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
                I915_READ(pch_dpll_reg);
  
-               if (HAS_eDP) {
-                       ironlake_disable_pll_edp(crtc);
-               }
                /* Switch from PCDclk to Rawclk */
                temp = I915_READ(fdi_rx_reg);
                temp &= ~FDI_SEL_PCDCLK;
@@@ -2372,8 -2323,6 +2323,6 @@@ static void i9xx_crtc_dpms(struct drm_c
        case DRM_MODE_DPMS_ON:
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
-               intel_update_watermarks(dev);
                /* Enable the DPLL */
                temp = I915_READ(dpll_reg);
                if ((temp & DPLL_VCO_ENABLE) == 0) {
                intel_crtc_dpms_overlay(intel_crtc, true);
        break;
        case DRM_MODE_DPMS_OFF:
-               intel_update_watermarks(dev);
                /* Give the overlay scaler a chance to disable if it's on this pipe */
                intel_crtc_dpms_overlay(intel_crtc, false);
                drm_vblank_off(dev, pipe);
                    dev_priv->display.disable_fbc)
                        dev_priv->display.disable_fbc(dev);
  
-               /* Disable the VGA plane that we never use */
-               i915_disable_vga(dev);
                /* Disable display plane */
                temp = I915_READ(dspcntr_reg);
                if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
                        I915_READ(dspbase_reg);
                }
  
-               if (!IS_I9XX(dev)) {
-                       /* Wait for vblank for the disable to take effect */
-                       intel_wait_for_vblank(dev);
-               }
+               /* Wait for vblank for the disable to take effect */
+               intel_wait_for_vblank_off(dev, pipe);
  
                /* Don't disable pipe A or pipe A PLLs if needed */
                if (pipeconf_reg == PIPEACONF &&
                }
  
                /* Wait for vblank for the disable to take effect. */
-               intel_wait_for_vblank(dev);
+               intel_wait_for_vblank_off(dev, pipe);
  
                temp = I915_READ(dpll_reg);
                if ((temp & DPLL_VCO_ENABLE) != 0) {
  
  /**
   * Sets the power management mode of the pipe and plane.
-  *
-  * This code should probably grow support for turning the cursor off and back
-  * on appropriately at the same time as we're turning the pipe off/on.
   */
  static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
  {
        int pipe = intel_crtc->pipe;
        bool enabled;
  
+       intel_crtc->dpms_mode = mode;
+       intel_crtc->cursor_on = mode == DRM_MODE_DPMS_ON;
+       /* When switching on the display, ensure that SR is disabled
+        * with multiple pipes prior to enabling to new pipe.
+        *
+        * When switching off the display, make sure the cursor is
+        * properly hidden prior to disabling the pipe.
+        */
+       if (mode == DRM_MODE_DPMS_ON)
+               intel_update_watermarks(dev);
+       else
+               intel_crtc_update_cursor(crtc);
        dev_priv->display.dpms(crtc, mode);
  
-       intel_crtc->dpms_mode = mode;
+       if (mode == DRM_MODE_DPMS_ON)
+               intel_crtc_update_cursor(crtc);
+       else
+               intel_update_watermarks(dev);
  
        if (!dev->primary->master)
                return;
@@@ -2536,6 -2492,20 +2492,20 @@@ void intel_encoder_commit (struct drm_e
        encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
  }
  
+ void intel_encoder_destroy(struct drm_encoder *encoder)
+ {
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+       if (intel_encoder->ddc_bus)
+               intel_i2c_destroy(intel_encoder->ddc_bus);
+       if (intel_encoder->i2c_bus)
+               intel_i2c_destroy(intel_encoder->i2c_bus);
+       drm_encoder_cleanup(encoder);
+       kfree(intel_encoder);
+ }
  static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
                                  struct drm_display_mode *mode,
                                  struct drm_display_mode *adjusted_mode)
@@@ -2867,7 -2837,7 +2837,7 @@@ struct cxsr_latency 
        unsigned long cursor_hpll_disable;
  };
  
- static struct cxsr_latency cxsr_latency_table[] = {
+ static const struct cxsr_latency cxsr_latency_table[] = {
        {1, 0, 800, 400, 3382, 33382, 3983, 33983},    /* DDR2-400 SC */
        {1, 0, 800, 667, 3354, 33354, 3807, 33807},    /* DDR2-667 SC */
        {1, 0, 800, 800, 3347, 33347, 3763, 33763},    /* DDR2-800 SC */
        {0, 1, 400, 800, 6042, 36042, 6584, 36584},    /* DDR3-800 SC */
  };
  
- static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int is_ddr3, 
-                                                  int fsb, int mem)
+ static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop,
+                                                        int is_ddr3,
+                                                        int fsb,
+                                                        int mem)
  {
+       const struct cxsr_latency *latency;
        int i;
-       struct cxsr_latency *latency;
  
        if (fsb == 0 || mem == 0)
                return NULL;
  static void pineview_disable_cxsr(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 reg;
  
        /* deactivate cxsr */
-       reg = I915_READ(DSPFW3);
-       reg &= ~(PINEVIEW_SELF_REFRESH_EN);
-       I915_WRITE(DSPFW3, reg);
-       DRM_INFO("Big FIFO is disabled\n");
+       I915_WRITE(DSPFW3, I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN);
  }
  
  /*
@@@ -3024,12 -2992,12 +2992,12 @@@ static void pineview_update_wm(struct d
                          int pixel_size)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       const struct cxsr_latency *latency;
        u32 reg;
        unsigned long wm;
-       struct cxsr_latency *latency;
        int sr_clock;
  
-       latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, 
+       latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3,
                                         dev_priv->fsb_freq, dev_priv->mem_freq);
        if (!latency) {
                DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
                DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg);
  
                /* activate cxsr */
-               reg = I915_READ(DSPFW3);
-               reg |= PINEVIEW_SELF_REFRESH_EN;
-               I915_WRITE(DSPFW3, reg);
+               I915_WRITE(DSPFW3,
+                          I915_READ(DSPFW3) | PINEVIEW_SELF_REFRESH_EN);
                DRM_DEBUG_KMS("Self-refresh is enabled\n");
        } else {
                pineview_disable_cxsr(dev);
@@@ -3354,12 -3321,11 +3321,11 @@@ static void ironlake_update_wm(struct d
        int line_count;
        int planea_htotal = 0, planeb_htotal = 0;
        struct drm_crtc *crtc;
-       struct intel_crtc *intel_crtc;
  
        /* Need htotal for all active display plane */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               intel_crtc = to_intel_crtc(crtc);
-               if (crtc->enabled) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+               if (intel_crtc->dpms_mode == DRM_MODE_DPMS_ON) {
                        if (intel_crtc->plane == 0)
                                planea_htotal = crtc->mode.htotal;
                        else
@@@ -3519,7 -3485,6 +3485,6 @@@ static void intel_update_watermarks(str
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
-       struct intel_crtc *intel_crtc;
        int sr_hdisplay = 0;
        unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
        int enabled = 0, pixel_size = 0;
  
        /* Get the clock config from both planes */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               intel_crtc = to_intel_crtc(crtc);
-               if (crtc->enabled) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+               if (intel_crtc->dpms_mode == DRM_MODE_DPMS_ON) {
                        enabled++;
                        if (intel_crtc->plane == 0) {
                                DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n",
@@@ -3966,9 -3931,7 +3931,7 @@@ static int intel_crtc_mode_set(struct d
                dpll_reg = pch_dpll_reg;
        }
  
-       if (is_edp) {
-               ironlake_disable_pll_edp(crtc);
-       } else if ((dpll & DPLL_VCO_ENABLE)) {
+       if (!is_edp) {
                I915_WRITE(fp_reg, fp);
                I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
                I915_READ(dpll_reg);
        I915_WRITE(pipeconf_reg, pipeconf);
        I915_READ(pipeconf_reg);
  
-       intel_wait_for_vblank(dev);
+       intel_wait_for_vblank(dev, pipe);
  
        if (IS_IRONLAKE(dev)) {
                /* enable address swizzle for tiling buffer */
        /* Flush the plane changes */
        ret = intel_pipe_set_base(crtc, x, y, old_fb);
  
-       if ((IS_I965G(dev) || plane == 0))
-               intel_update_fbc(crtc, &crtc->mode);
        intel_update_watermarks(dev);
  
        drm_vblank_post_modeset(dev, pipe);
@@@ -4216,6 -4176,62 +4176,62 @@@ void intel_crtc_load_lut(struct drm_crt
        }
  }
  
+ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
+ {
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       bool visible = base != 0;
+       u32 cntl;
+       if (intel_crtc->cursor_visible == visible)
+               return;
+       cntl = I915_READ(CURACNTR);
+       if (visible) {
+               /* On these chipsets we can only modify the base whilst
+                * the cursor is disabled.
+                */
+               I915_WRITE(CURABASE, base);
+               cntl &= ~(CURSOR_FORMAT_MASK);
+               /* XXX width must be 64, stride 256 => 0x00 << 28 */
+               cntl |= CURSOR_ENABLE |
+                       CURSOR_GAMMA_ENABLE |
+                       CURSOR_FORMAT_ARGB;
+       } else
+               cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
+       I915_WRITE(CURACNTR, cntl);
+       intel_crtc->cursor_visible = visible;
+ }
+ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
+ {
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       bool visible = base != 0;
+       if (intel_crtc->cursor_visible != visible) {
+               uint32_t cntl = I915_READ(pipe == 0 ? CURACNTR : CURBCNTR);
+               if (base) {
+                       cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
+                       cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+                       cntl |= pipe << 28; /* Connect to correct pipe */
+               } else {
+                       cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
+                       cntl |= CURSOR_MODE_DISABLE;
+               }
+               I915_WRITE(pipe == 0 ? CURACNTR : CURBCNTR, cntl);
+               intel_crtc->cursor_visible = visible;
+       }
+       /* and commit changes on next vblank */
+       I915_WRITE(pipe == 0 ? CURABASE : CURBBASE, base);
+ }
  /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
  static void intel_crtc_update_cursor(struct drm_crtc *crtc)
  {
        int pipe = intel_crtc->pipe;
        int x = intel_crtc->cursor_x;
        int y = intel_crtc->cursor_y;
-       uint32_t base, pos;
+       u32 base, pos;
        bool visible;
  
        pos = 0;
  
-       if (crtc->fb) {
+       if (intel_crtc->cursor_on && crtc->fb) {
                base = intel_crtc->cursor_addr;
                if (x > (int) crtc->fb->width)
                        base = 0;
        pos |= y << CURSOR_Y_SHIFT;
  
        visible = base != 0;
-       if (!visible && !intel_crtc->cursor_visble)
+       if (!visible && !intel_crtc->cursor_visible)
                return;
  
        I915_WRITE(pipe == 0 ? CURAPOS : CURBPOS, pos);
-       if (intel_crtc->cursor_visble != visible) {
-               uint32_t cntl = I915_READ(pipe == 0 ? CURACNTR : CURBCNTR);
-               if (base) {
-                       /* Hooray for CUR*CNTR differences */
-                       if (IS_MOBILE(dev) || IS_I9XX(dev)) {
-                               cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
-                               cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-                               cntl |= pipe << 28; /* Connect to correct pipe */
-                       } else {
-                               cntl &= ~(CURSOR_FORMAT_MASK);
-                               cntl |= CURSOR_ENABLE;
-                               cntl |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
-                       }
-               } else {
-                       if (IS_MOBILE(dev) || IS_I9XX(dev)) {
-                               cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
-                               cntl |= CURSOR_MODE_DISABLE;
-                       } else {
-                               cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
-                       }
-               }
-               I915_WRITE(pipe == 0 ? CURACNTR : CURBCNTR, cntl);
-               intel_crtc->cursor_visble = visible;
-       }
-       /* and commit changes on next vblank */
-       I915_WRITE(pipe == 0 ? CURABASE : CURBBASE, base);
+       if (IS_845G(dev) || IS_I865G(dev))
+               i845_update_cursor(crtc, base);
+       else
+               i9xx_update_cursor(crtc, base);
  
        if (visible)
                intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
@@@ -4354,8 -4347,10 +4347,10 @@@ static int intel_crtc_cursor_set(struc
  
                addr = obj_priv->gtt_offset;
        } else {
+               int align = IS_I830(dev) ? 16 * 1024 : 256;
                ret = i915_gem_attach_phys_object(dev, bo,
-                                                 (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
+                                                 (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1,
+                                                 align);
                if (ret) {
                        DRM_ERROR("failed to attach phys object\n");
                        goto fail_locked;
@@@ -4429,12 -4424,15 +4424,12 @@@ void intel_crtc_fb_gamma_get(struct drm
  }
  
  static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
 -                               u16 *blue, uint32_t size)
 +                               u16 *blue, uint32_t start, uint32_t size)
  {
 +      int end = (start + size > 256) ? 256 : start + size, i;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      int i;
 -
 -      if (size != 256)
 -              return;
  
 -      for (i = 0; i < 256; i++) {
 +      for (i = start; i < end; i++) {
                intel_crtc->lut_r[i] = red[i] >> 8;
                intel_crtc->lut_g[i] = green[i] >> 8;
                intel_crtc->lut_b[i] = blue[i] >> 8;
@@@ -4544,7 -4542,7 +4539,7 @@@ struct drm_crtc *intel_get_load_detect_
                encoder_funcs->commit(encoder);
        }
        /* let the connector get through one full cycle before testing */
-       intel_wait_for_vblank(dev);
+       intel_wait_for_vblank(dev, intel_crtc->pipe);
  
        return crtc;
  }
@@@ -4749,7 -4747,7 +4744,7 @@@ static void intel_increase_pllclock(str
                dpll &= ~DISPLAY_RATE_SELECT_FPA1;
                I915_WRITE(dpll_reg, dpll);
                dpll = I915_READ(dpll_reg);
-               intel_wait_for_vblank(dev);
+               intel_wait_for_vblank(dev, pipe);
                dpll = I915_READ(dpll_reg);
                if (dpll & DISPLAY_RATE_SELECT_FPA1)
                        DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
@@@ -4793,7 -4791,7 +4788,7 @@@ static void intel_decrease_pllclock(str
                dpll |= DISPLAY_RATE_SELECT_FPA1;
                I915_WRITE(dpll_reg, dpll);
                dpll = I915_READ(dpll_reg);
-               intel_wait_for_vblank(dev);
+               intel_wait_for_vblank(dev, pipe);
                dpll = I915_READ(dpll_reg);
                if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
                        DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
@@@ -5083,14 -5081,16 +5078,16 @@@ static int intel_crtc_page_flip(struct 
        work->pending_flip_obj = obj;
  
        if (intel_crtc->plane)
-               flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+               flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
        else
-               flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
+               flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
  
-       /* Wait for any previous flip to finish */
-       if (IS_GEN3(dev))
-               while (I915_READ(ISR) & flip_mask)
-                       ;
+       if (IS_GEN3(dev) || IS_GEN2(dev)) {
+               BEGIN_LP_RING(2);
+               OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       }
  
        /* Offset into the new buffer for cases of shared fbs between CRTCs */
        offset = obj_priv->gtt_offset;
                OUT_RING(offset | obj_priv->tiling_mode);
                pipesrc = I915_READ(pipesrc_reg); 
                OUT_RING(pipesrc & 0x0fff0fff);
-       } else {
+       } else if (IS_GEN3(dev)) {
                OUT_RING(MI_DISPLAY_FLIP_I915 |
                         MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
                OUT_RING(fb->pitch);
                OUT_RING(offset);
                OUT_RING(MI_NOOP);
+       } else {
+               OUT_RING(MI_DISPLAY_FLIP |
+                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+               OUT_RING(fb->pitch);
+               OUT_RING(offset);
+               OUT_RING(MI_NOOP);
        }
        ADVANCE_LP_RING();
  
@@@ -5409,18 -5415,18 +5412,18 @@@ intel_user_framebuffer_create(struct dr
  
        obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle);
        if (!obj)
 -              return NULL;
 +              return ERR_PTR(-ENOENT);
  
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
        if (!intel_fb)
 -              return NULL;
 +              return ERR_PTR(-ENOMEM);
  
        ret = intel_framebuffer_init(dev, intel_fb,
                                     mode_cmd, obj);
        if (ret) {
                drm_gem_object_unreference_unlocked(obj);
                kfree(intel_fb);
 -              return NULL;
 +              return ERR_PTR(ret);
        }
  
        return &intel_fb->base;
@@@ -5432,37 -5438,37 +5435,37 @@@ static const struct drm_mode_config_fun
  };
  
  static struct drm_gem_object *
- intel_alloc_power_context(struct drm_device *dev)
+ intel_alloc_context_page(struct drm_device *dev)
  {
-       struct drm_gem_object *pwrctx;
+       struct drm_gem_object *ctx;
        int ret;
  
-       pwrctx = i915_gem_alloc_object(dev, 4096);
-       if (!pwrctx) {
+       ctx = i915_gem_alloc_object(dev, 4096);
+       if (!ctx) {
                DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
                return NULL;
        }
  
        mutex_lock(&dev->struct_mutex);
-       ret = i915_gem_object_pin(pwrctx, 4096);
+       ret = i915_gem_object_pin(ctx, 4096);
        if (ret) {
                DRM_ERROR("failed to pin power context: %d\n", ret);
                goto err_unref;
        }
  
-       ret = i915_gem_object_set_to_gtt_domain(pwrctx, 1);
+       ret = i915_gem_object_set_to_gtt_domain(ctx, 1);
        if (ret) {
                DRM_ERROR("failed to set-domain on power context: %d\n", ret);
                goto err_unpin;
        }
        mutex_unlock(&dev->struct_mutex);
  
-       return pwrctx;
+       return ctx;
  
  err_unpin:
-       i915_gem_object_unpin(pwrctx);
+       i915_gem_object_unpin(ctx);
  err_unref:
-       drm_gem_object_unreference(pwrctx);
+       drm_gem_object_unreference(ctx);
        mutex_unlock(&dev->struct_mutex);
        return NULL;
  }
@@@ -5494,7 -5500,6 +5497,6 @@@ void ironlake_enable_drps(struct drm_de
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 rgvmodectl = I915_READ(MEMMODECTL);
        u8 fmax, fmin, fstart, vstart;
-       int i = 0;
  
        /* 100ms RC evaluation intervals */
        I915_WRITE(RCUPEI, 100000);
        rgvmodectl |= MEMMODE_SWMODE_EN;
        I915_WRITE(MEMMODECTL, rgvmodectl);
  
-       while (I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) {
-               if (i++ > 100) {
-                       DRM_ERROR("stuck trying to change perf mode\n");
-                       break;
-               }
-               msleep(1);
-       }
+       if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 1, 0))
+               DRM_ERROR("stuck trying to change perf mode\n");
        msleep(1);
  
        ironlake_set_drps(dev, fstart);
@@@ -5725,7 -5725,8 +5722,8 @@@ void intel_init_clock_gating(struct drm
                                   ILK_DPFC_DIS2 |
                                   ILK_CLK_FBC);
                }
-               return;
+               if (IS_GEN6(dev))
+                       return;
        } else if (IS_G4X(dev)) {
                uint32_t dspclk_gate;
                I915_WRITE(RENCLK_GATE_D1, 0);
         * GPU can automatically power down the render unit if given a page
         * to save state.
         */
+       if (IS_IRONLAKE_M(dev)) {
+               if (dev_priv->renderctx == NULL)
+                       dev_priv->renderctx = intel_alloc_context_page(dev);
+               if (dev_priv->renderctx) {
+                       struct drm_i915_gem_object *obj_priv;
+                       obj_priv = to_intel_bo(dev_priv->renderctx);
+                       if (obj_priv) {
+                               BEGIN_LP_RING(4);
+                               OUT_RING(MI_SET_CONTEXT);
+                               OUT_RING(obj_priv->gtt_offset |
+                                               MI_MM_SPACE_GTT |
+                                               MI_SAVE_EXT_STATE_EN |
+                                               MI_RESTORE_EXT_STATE_EN |
+                                               MI_RESTORE_INHIBIT);
+                               OUT_RING(MI_NOOP);
+                               OUT_RING(MI_FLUSH);
+                               ADVANCE_LP_RING();
+                       }
+               } else {
+                       DRM_DEBUG_KMS("Failed to allocate render context."
+                                     "Disable RC6\n");
+                       return;
+               }
+       }
        if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) {
                struct drm_i915_gem_object *obj_priv = NULL;
  
                } else {
                        struct drm_gem_object *pwrctx;
  
-                       pwrctx = intel_alloc_power_context(dev);
+                       pwrctx = intel_alloc_context_page(dev);
                        if (pwrctx) {
                                dev_priv->pwrctx = pwrctx;
                                obj_priv = to_intel_bo(pwrctx);
@@@ -5948,6 -5974,29 +5971,29 @@@ static void intel_init_quirks(struct dr
        }
  }
  
+ /* Disable the VGA plane that we never use */
+ static void i915_disable_vga(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u8 sr1;
+       u32 vga_reg;
+       if (HAS_PCH_SPLIT(dev))
+               vga_reg = CPU_VGACNTRL;
+       else
+               vga_reg = VGACNTRL;
+       vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
+       outb(1, VGA_SR_INDEX);
+       sr1 = inb(VGA_SR_DATA);
+       outb(sr1 | 1<<5, VGA_SR_DATA);
+       vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
+       udelay(300);
+       I915_WRITE(vga_reg, VGA_DISP_DISABLE);
+       POSTING_READ(vga_reg);
+ }
  void intel_modeset_init(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
  
        intel_init_clock_gating(dev);
  
+       /* Just disable it once at startup */
+       i915_disable_vga(dev);
        if (IS_IRONLAKE_M(dev)) {
                ironlake_enable_drps(dev);
                intel_init_emon(dev);
@@@ -6034,6 -6086,16 +6083,16 @@@ void intel_modeset_cleanup(struct drm_d
        if (dev_priv->display.disable_fbc)
                dev_priv->display.disable_fbc(dev);
  
+       if (dev_priv->renderctx) {
+               struct drm_i915_gem_object *obj_priv;
+               obj_priv = to_intel_bo(dev_priv->renderctx);
+               I915_WRITE(CCID, obj_priv->gtt_offset &~ CCID_EN);
+               I915_READ(CCID);
+               i915_gem_object_unpin(dev_priv->renderctx);
+               drm_gem_object_unreference(dev_priv->renderctx);
+       }
        if (dev_priv->pwrctx) {
                struct drm_i915_gem_object *obj_priv;