]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'drm-intel-fixes' into drm-intel-next
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 15 Nov 2010 06:49:30 +0000 (06:49 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 15 Nov 2010 06:49:30 +0000 (06:49 +0000)
Conflicts:
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_ringbuffer.c

1  2 
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_i2c.c

index ecf12f9de1e07580f490a62b7b14441b63279fba,409826da3099dcb594473685bdf4b5f2e78183c9..73a41f7ab8c68fac6ab388f5f4a9173720ce0aca
@@@ -32,7 -32,6 +32,7 @@@
  
  #include "i915_reg.h"
  #include "intel_bios.h"
 +#include "i915_trace.h"
  #include "intel_ringbuffer.h"
  #include <linux/io-mapping.h>
  #include <linux/i2c.h>
@@@ -149,17 -148,6 +149,17 @@@ struct drm_i915_error_state 
        u32 ipehr;
        u32 instdone;
        u32 acthd;
 +      u32 error; /* gen6+ */
 +      u32 bcs_acthd; /* gen6+ blt engine */
 +      u32 bcs_ipehr;
 +      u32 bcs_ipeir;
 +      u32 bcs_instdone;
 +      u32 bcs_seqno;
 +      u32 vcs_acthd; /* gen6+ bsd engine */
 +      u32 vcs_ipehr;
 +      u32 vcs_ipeir;
 +      u32 vcs_instdone;
 +      u32 vcs_seqno;
        u32 instpm;
        u32 instps;
        u32 instdone1;
                u32 tiling:2;
                u32 dirty:1;
                u32 purgeable:1;
 +              u32 ring:4;
        } *active_bo;
        u32 active_bo_count;
        struct intel_overlay_error_state *overlay;
@@@ -288,7 -275,11 +288,7 @@@ typedef struct drm_i915_private 
        int front_offset;
        int current_page;
        int page_flipping;
 -#define I915_DEBUG_READ (1<<0)
 -#define I915_DEBUG_WRITE (1<<1)
 -      unsigned long debug_flags;
  
 -      wait_queue_head_t irq_queue;
        atomic_t irq_received;
        /** Protects user_irq_refcount and irq_mask_reg */
        spinlock_t user_irq_lock;
                struct drm_mm vram;
                /** Memory allocator for GTT */
                struct drm_mm gtt_space;
 +              /** End of mappable part of GTT */
 +              unsigned long gtt_mappable_end;
  
                struct io_mapping *gtt_mapping;
                int gtt_mtrr;
  
 -              /**
 -               * Membership on list of all loaded devices, used to evict
 -               * inactive buffers under memory pressure.
 -               *
 -               * Modifications should only be done whilst holding the
 -               * shrink_list_lock spinlock.
 -               */
 -              struct list_head shrink_list;
 +              struct shrinker inactive_shrinker;
  
                /**
                 * List of objects currently involved in rendering.
                 */
                struct delayed_work retire_work;
  
 -              /**
 -               * Waiting sequence number, if any
 -               */
 -              uint32_t waiting_gem_seqno;
 -
 -              /**
 -               * Last seq seen at irq time
 -               */
 -              uint32_t irq_gem_seqno;
 -
                /**
                 * Flag if the X Server, and thus DRM, is not currently in
                 * control of the device.
                /* storage for physical objects */
                struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
  
 -              uint32_t flush_rings;
 -
                /* accounting, useful for userland debugging */
                size_t object_memory;
                size_t pin_memory;
                size_t gtt_memory;
 +              size_t gtt_mappable_memory;
 +              size_t mappable_gtt_used;
 +              size_t mappable_gtt_total;
                size_t gtt_total;
                u32 object_count;
                u32 pin_count;
 +              u32 gtt_mappable_count;
                u32 gtt_count;
        } mm;
        struct sdvo_device_mapping sdvo_mappings[2];
@@@ -753,6 -757,15 +753,6 @@@ struct drm_i915_gem_object 
         */
        unsigned int madv : 2;
  
 -      /**
 -       * Refcount for the pages array. With the current locking scheme, there
 -       * are at most two concurrent users: Binding a bo to the gtt and
 -       * pwrite/pread using physical addresses. So two bits for a maximum
 -       * of two users are enough.
 -       */
 -      unsigned int pages_refcount : 2;
 -#define DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT 0x3
 -
        /**
         * Current tiling mode for the object.
         */
        unsigned int pin_count : 4;
  #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
  
 +      /**
 +       * Is the object at the current location in the gtt mappable and
 +       * fenceable? Used to avoid costly recalculations.
 +       */
 +      unsigned int map_and_fenceable : 1;
 +
 +      /**
 +       * Whether the current gtt mapping needs to be mappable (and isn't just
 +       * mappable by accident). Track pin and fault separate for a more
 +       * accurate mappable working set.
 +       */
 +      unsigned int fault_mappable : 1;
 +      unsigned int pin_mappable : 1;
 +
        /** AGP memory structure for our GTT binding. */
        DRM_AGP_MEM *agp_mem;
  
        /* Which ring is refering to is this object */
        struct intel_ring_buffer *ring;
  
 -      /**
 -       * Fake offset for use by mmap(2)
 -       */
 -      uint64_t mmap_offset;
 -
        /** Breadcrumb of last rendering to the buffer. */
        uint32_t last_rendering_seqno;
  
@@@ -876,67 -880,6 +876,67 @@@ enum intel_chip_family 
        CHIP_I965 = 0x08,
  };
  
 +#define INTEL_INFO(dev)       (((struct drm_i915_private *) (dev)->dev_private)->info)
 +
 +#define IS_I830(dev)          ((dev)->pci_device == 0x3577)
 +#define IS_845G(dev)          ((dev)->pci_device == 0x2562)
 +#define IS_I85X(dev)          (INTEL_INFO(dev)->is_i85x)
 +#define IS_I865G(dev)         ((dev)->pci_device == 0x2572)
 +#define IS_I915G(dev)         (INTEL_INFO(dev)->is_i915g)
 +#define IS_I915GM(dev)                ((dev)->pci_device == 0x2592)
 +#define IS_I945G(dev)         ((dev)->pci_device == 0x2772)
 +#define IS_I945GM(dev)                (INTEL_INFO(dev)->is_i945gm)
 +#define IS_BROADWATER(dev)    (INTEL_INFO(dev)->is_broadwater)
 +#define IS_CRESTLINE(dev)     (INTEL_INFO(dev)->is_crestline)
 +#define IS_GM45(dev)          ((dev)->pci_device == 0x2A42)
 +#define IS_G4X(dev)           (INTEL_INFO(dev)->is_g4x)
 +#define IS_PINEVIEW_G(dev)    ((dev)->pci_device == 0xa001)
 +#define IS_PINEVIEW_M(dev)    ((dev)->pci_device == 0xa011)
 +#define IS_PINEVIEW(dev)      (INTEL_INFO(dev)->is_pineview)
 +#define IS_G33(dev)           (INTEL_INFO(dev)->is_g33)
 +#define IS_IRONLAKE_D(dev)    ((dev)->pci_device == 0x0042)
 +#define IS_IRONLAKE_M(dev)    ((dev)->pci_device == 0x0046)
 +#define IS_MOBILE(dev)                (INTEL_INFO(dev)->is_mobile)
 +
 +#define IS_GEN2(dev)  (INTEL_INFO(dev)->gen == 2)
 +#define IS_GEN3(dev)  (INTEL_INFO(dev)->gen == 3)
 +#define IS_GEN4(dev)  (INTEL_INFO(dev)->gen == 4)
 +#define IS_GEN5(dev)  (INTEL_INFO(dev)->gen == 5)
 +#define IS_GEN6(dev)  (INTEL_INFO(dev)->gen == 6)
 +
 +#define HAS_BSD(dev)            (INTEL_INFO(dev)->has_bsd_ring)
 +#define HAS_BLT(dev)            (INTEL_INFO(dev)->has_blt_ring)
 +#define I915_NEED_GFX_HWS(dev)        (INTEL_INFO(dev)->need_gfx_hws)
 +
 +#define HAS_OVERLAY(dev)              (INTEL_INFO(dev)->has_overlay)
 +#define OVERLAY_NEEDS_PHYSICAL(dev)   (INTEL_INFO(dev)->overlay_needs_physical)
 +
 +/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
 + * rows, which changed the alignment requirements and fence programming.
 + */
 +#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \
 +                                                    IS_I915GM(dev)))
 +#define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev))
 +#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev))
 +#define SUPPORTS_INTEGRATED_DP(dev)   (IS_G4X(dev) || IS_GEN5(dev))
 +#define SUPPORTS_EDP(dev)             (IS_IRONLAKE_M(dev))
 +#define SUPPORTS_TV(dev)              (INTEL_INFO(dev)->supports_tv)
 +#define I915_HAS_HOTPLUG(dev)          (INTEL_INFO(dev)->has_hotplug)
 +/* dsparb controlled by hw only */
 +#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
 +
 +#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2)
 +#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
 +#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
 +#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
 +
 +#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev))
 +#define HAS_PIPE_CONTROL(dev) (IS_GEN5(dev) || IS_GEN6(dev))
 +
 +#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type)
 +#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
 +#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
 +
  extern struct drm_ioctl_desc i915_ioctls[];
  extern int i915_max_ioctl;
  extern unsigned int i915_fbpercrtc;
@@@ -975,7 -918,6 +975,7 @@@ extern void i915_update_gfx_val(struct 
  
  /* i915_irq.c */
  void i915_hangcheck_elapsed(unsigned long data);
 +void i915_handle_error(struct drm_device *dev, bool wedged);
  extern int i915_irq_emit(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
  extern int i915_irq_wait(struct drm_device *dev, void *data,
@@@ -1078,8 -1020,7 +1078,8 @@@ int i915_gem_init_object(struct drm_gem
  struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev,
                                              size_t size);
  void i915_gem_free_object(struct drm_gem_object *obj);
 -int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
 +int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment,
 +                      bool map_and_fenceable);
  void i915_gem_object_unpin(struct drm_gem_object *obj);
  int i915_gem_object_unbind(struct drm_gem_object *obj);
  void i915_gem_release_mmap(struct drm_gem_object *obj);
@@@ -1104,16 -1045,18 +1104,18 @@@ void i915_gem_clflush_object(struct drm
  int i915_gem_object_set_domain(struct drm_gem_object *obj,
                               uint32_t read_domains,
                               uint32_t write_domain);
+ int i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
+                             bool interruptible);
  int i915_gem_init_ringbuffer(struct drm_device *dev);
  void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
  int i915_gem_do_init(struct drm_device *dev, unsigned long start,
 -                   unsigned long end);
 +                   unsigned long mappable_end, unsigned long end);
  int i915_gpu_idle(struct drm_device *dev);
  int i915_gem_idle(struct drm_device *dev);
 -uint32_t i915_add_request(struct drm_device *dev,
 -                        struct drm_file *file_priv,
 -                        struct drm_i915_gem_request *request,
 -                        struct intel_ring_buffer *ring);
 +int i915_add_request(struct drm_device *dev,
 +                   struct drm_file *file_priv,
 +                   struct drm_i915_gem_request *request,
 +                   struct intel_ring_buffer *ring);
  int i915_do_wait_request(struct drm_device *dev,
                         uint32_t seqno,
                         bool interruptible,
@@@ -1132,16 -1075,22 +1134,16 @@@ void i915_gem_detach_phys_object(struc
  void i915_gem_free_all_phys_object(struct drm_device *dev);
  void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
  
 -void i915_gem_shrinker_init(void);
 -void i915_gem_shrinker_exit(void);
 -
  /* i915_gem_evict.c */
 -int i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment);
 -int i915_gem_evict_everything(struct drm_device *dev);
 -int i915_gem_evict_inactive(struct drm_device *dev);
 +int i915_gem_evict_something(struct drm_device *dev, int min_size,
 +                           unsigned alignment, bool mappable);
 +int i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only);
 +int i915_gem_evict_inactive(struct drm_device *dev, bool purgeable_only);
  
  /* i915_gem_tiling.c */
  void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
  void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
  void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
 -bool i915_tiling_ok(struct drm_device *dev, int stride, int size,
 -                  int tiling_mode);
 -bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj,
 -                                   int tiling_mode);
  
  /* i915_gem_debug.c */
  void i915_gem_dump_object(struct drm_gem_object *obj, int len,
@@@ -1235,92 -1184,64 +1237,92 @@@ extern void intel_overlay_print_error_s
                LOCK_TEST_WITH_RETURN(dev, file_priv);                  \
  } while (0)
  
 -static inline u32 i915_read(struct drm_i915_private *dev_priv, u32 reg)
 -{
 -      u32 val;
 +#define I915_READ(reg)                i915_read(dev_priv, (reg), 4)
 +#define I915_WRITE(reg, val)  i915_write(dev_priv, (reg), (val), 4)
 +#define I915_READ16(reg)      i915_read(dev_priv, (reg), 2)
 +#define I915_WRITE16(reg, val)        i915_write(dev_priv, (reg), (val), 2)
 +#define I915_READ8(reg)               i915_read(dev_priv, (reg), 1)
 +#define I915_WRITE8(reg, val) i915_write(dev_priv, (reg), (val), 1)
 +#define I915_WRITE64(reg, val)        i915_write(dev_priv, (reg), (val), 8)
 +#define I915_READ64(reg)      i915_read(dev_priv, (reg), 8)
 +
 +#define I915_READ_NOTRACE(reg)                readl(dev_priv->regs + (reg))
 +#define I915_WRITE_NOTRACE(reg, val)  writel(val, dev_priv->regs + (reg))
 +#define I915_READ16_NOTRACE(reg)              readw(dev_priv->regs + (reg))
 +#define I915_WRITE16_NOTRACE(reg, val)        writew(val, dev_priv->regs + (reg))
  
 -      val = readl(dev_priv->regs + reg);
 -      if (dev_priv->debug_flags & I915_DEBUG_READ)
 -              printk(KERN_ERR "read 0x%08x from 0x%08x\n", val, reg);
 -      return val;
 +#define POSTING_READ(reg)     (void)I915_READ_NOTRACE(reg)
 +#define POSTING_READ16(reg)   (void)I915_READ16_NOTRACE(reg)
 +
 +static inline u32 i915_read(struct drm_i915_private *dev_priv, u32 reg, int len)
 +{
 +       u64 val = 0;
 +
 +       switch (len) {
 +       case 8:
 +               val = readq(dev_priv->regs + reg);
 +               break;
 +       case 4:
 +               val = readl(dev_priv->regs + reg);
 +               break;
 +       case 2:
 +               val = readw(dev_priv->regs + reg);
 +               break;
 +       case 1:
 +               val = readb(dev_priv->regs + reg);
 +               break;
 +       }
 +       trace_i915_reg_rw('R', reg, val, len);
 +
 +       return val;
  }
  
 -static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg,
 -                            u32 val)
 +/* On SNB platform, before reading ring registers forcewake bit
 + * must be set to prevent GT core from power down and stale values being
 + * returned.
 + */
 +static inline u32 i915_safe_read(struct drm_i915_private *dev_priv, u32 reg)
  {
 -      writel(val, dev_priv->regs + reg);
 -      if (dev_priv->debug_flags & I915_DEBUG_WRITE)
 -              printk(KERN_ERR "wrote 0x%08x to 0x%08x\n", val, reg);
 +      if (IS_GEN6(dev_priv->dev)) {
 +              I915_WRITE_NOTRACE(FORCEWAKE, 1);
 +              POSTING_READ(FORCEWAKE);
 +              /* XXX How long do we really need to wait here?
 +               * Will different registers/engines require different periods?
 +               */
 +              udelay(100);
 +      }
 +      return I915_READ(reg);
  }
  
 -#define I915_READ(reg)          i915_read(dev_priv, (reg))
 -#define I915_WRITE(reg, val)    i915_write(dev_priv, (reg), (val))
 -#define I915_READ16(reg)      readw(dev_priv->regs + (reg))
 -#define I915_WRITE16(reg, val)        writel(val, dev_priv->regs + (reg))
 -#define I915_READ8(reg)               readb(dev_priv->regs + (reg))
 -#define I915_WRITE8(reg, val) writeb(val, dev_priv->regs + (reg))
 -#define I915_WRITE64(reg, val)        writeq(val, dev_priv->regs + (reg))
 -#define I915_READ64(reg)      readq(dev_priv->regs + (reg))
 -#define POSTING_READ(reg)     (void)I915_READ(reg)
 -#define POSTING_READ16(reg)   (void)I915_READ16(reg)
 -
 -#define I915_DEBUG_ENABLE_IO() (dev_priv->debug_flags |= I915_DEBUG_READ | \
 -                              I915_DEBUG_WRITE)
 -#define I915_DEBUG_DISABLE_IO() (dev_priv->debug_flags &= ~(I915_DEBUG_READ | \
 -                                                          I915_DEBUG_WRITE))
 -
 -#define I915_VERBOSE 0
 -
 -#define BEGIN_LP_RING(n)  do { \
 -      drm_i915_private_t *dev_priv__ = dev->dev_private;                \
 -      if (I915_VERBOSE)                                               \
 -              DRM_DEBUG("   BEGIN_LP_RING %x\n", (int)(n));           \
 -      intel_ring_begin(dev, &dev_priv__->render_ring, (n));           \
 -} while (0)
 +static inline void
 +i915_write(struct drm_i915_private *dev_priv, u32 reg, u64 val, int len)
 +{
 +       /* Trace down the write operation before the real write */
 +       trace_i915_reg_rw('W', reg, val, len);
 +       switch (len) {
 +       case 8:
 +               writeq(val, dev_priv->regs + reg);
 +               break;
 +       case 4:
 +               writel(val, dev_priv->regs + reg);
 +               break;
 +       case 2:
 +               writew(val, dev_priv->regs + reg);
 +               break;
 +       case 1:
 +               writeb(val, dev_priv->regs + reg);
 +               break;
 +       }
 +}
  
 +#define BEGIN_LP_RING(n) \
 +      intel_ring_begin(&dev_priv->render_ring, (n))
  
 -#define OUT_RING(x) do {                                              \
 -      drm_i915_private_t *dev_priv__ = dev->dev_private;              \
 -      if (I915_VERBOSE)                                               \
 -              DRM_DEBUG("   OUT_RING %x\n", (int)(x));                \
 -      intel_ring_emit(dev, &dev_priv__->render_ring, x);              \
 -} while (0)
 +#define OUT_RING(x) \
 +      intel_ring_emit(&dev_priv->render_ring, x)
  
 -#define ADVANCE_LP_RING() do {                                                \
 -      drm_i915_private_t *dev_priv__ = dev->dev_private;                \
 -      if (I915_VERBOSE)                                               \
 -              DRM_DEBUG("ADVANCE_LP_RING %x\n",                       \
 -                              dev_priv__->render_ring.tail);          \
 -      intel_ring_advance(dev, &dev_priv__->render_ring);              \
 -} while(0)
 +#define ADVANCE_LP_RING() \
 +      intel_ring_advance(&dev_priv->render_ring)
  
  /**
   * Reads a dword out of the status page, which is written to from the command
  #define I915_GEM_HWS_INDEX            0x20
  #define I915_BREADCRUMB_INDEX         0x21
  
 -#define INTEL_INFO(dev)       (((struct drm_i915_private *) (dev)->dev_private)->info)
 -
 -#define IS_I830(dev)          ((dev)->pci_device == 0x3577)
 -#define IS_845G(dev)          ((dev)->pci_device == 0x2562)
 -#define IS_I85X(dev)          (INTEL_INFO(dev)->is_i85x)
 -#define IS_I865G(dev)         ((dev)->pci_device == 0x2572)
 -#define IS_I915G(dev)         (INTEL_INFO(dev)->is_i915g)
 -#define IS_I915GM(dev)                ((dev)->pci_device == 0x2592)
 -#define IS_I945G(dev)         ((dev)->pci_device == 0x2772)
 -#define IS_I945GM(dev)                (INTEL_INFO(dev)->is_i945gm)
 -#define IS_BROADWATER(dev)    (INTEL_INFO(dev)->is_broadwater)
 -#define IS_CRESTLINE(dev)     (INTEL_INFO(dev)->is_crestline)
 -#define IS_GM45(dev)          ((dev)->pci_device == 0x2A42)
 -#define IS_G4X(dev)           (INTEL_INFO(dev)->is_g4x)
 -#define IS_PINEVIEW_G(dev)    ((dev)->pci_device == 0xa001)
 -#define IS_PINEVIEW_M(dev)    ((dev)->pci_device == 0xa011)
 -#define IS_PINEVIEW(dev)      (INTEL_INFO(dev)->is_pineview)
 -#define IS_G33(dev)           (INTEL_INFO(dev)->is_g33)
 -#define IS_IRONLAKE_D(dev)    ((dev)->pci_device == 0x0042)
 -#define IS_IRONLAKE_M(dev)    ((dev)->pci_device == 0x0046)
 -#define IS_MOBILE(dev)                (INTEL_INFO(dev)->is_mobile)
 -
 -#define IS_GEN2(dev)  (INTEL_INFO(dev)->gen == 2)
 -#define IS_GEN3(dev)  (INTEL_INFO(dev)->gen == 3)
 -#define IS_GEN4(dev)  (INTEL_INFO(dev)->gen == 4)
 -#define IS_GEN5(dev)  (INTEL_INFO(dev)->gen == 5)
 -#define IS_GEN6(dev)  (INTEL_INFO(dev)->gen == 6)
 -
 -#define HAS_BSD(dev)            (INTEL_INFO(dev)->has_bsd_ring)
 -#define HAS_BLT(dev)            (INTEL_INFO(dev)->has_blt_ring)
 -#define I915_NEED_GFX_HWS(dev)        (INTEL_INFO(dev)->need_gfx_hws)
 -
 -#define HAS_OVERLAY(dev)              (INTEL_INFO(dev)->has_overlay)
 -#define OVERLAY_NEEDS_PHYSICAL(dev)   (INTEL_INFO(dev)->overlay_needs_physical)
 -
 -/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
 - * rows, which changed the alignment requirements and fence programming.
 - */
 -#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \
 -                                                    IS_I915GM(dev)))
 -#define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev))
 -#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev))
 -#define SUPPORTS_INTEGRATED_DP(dev)   (IS_G4X(dev) || IS_GEN5(dev))
 -#define SUPPORTS_EDP(dev)             (IS_IRONLAKE_M(dev))
 -#define SUPPORTS_TV(dev)              (INTEL_INFO(dev)->supports_tv)
 -#define I915_HAS_HOTPLUG(dev)          (INTEL_INFO(dev)->has_hotplug)
 -/* dsparb controlled by hw only */
 -#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
 -
 -#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2)
 -#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
 -#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
 -#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
 -
 -#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev))
 -#define HAS_PIPE_CONTROL(dev) (IS_GEN5(dev) || IS_GEN6(dev))
 -
 -#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type)
 -#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
 -#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
 -
 -#define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 -
  #endif
index f2038f6df3b095872fcfc077fae278bfa5f2771f,781c26c37b3880309734f4066dd05062e1628698..54fc1e7eb872105a574669c03c0d4fa41de55d28
  #include <linux/pci.h>
  #include <linux/intel-gtt.h>
  
 -static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj);
 +struct change_domains {
 +      uint32_t invalidate_domains;
 +      uint32_t flush_domains;
 +      uint32_t flush_rings;
 +};
 +
 +static uint32_t i915_gem_get_gtt_alignment(struct drm_i915_gem_object *obj_priv);
 +static uint32_t i915_gem_get_gtt_size(struct drm_i915_gem_object *obj_priv);
  
  static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj,
                                                  bool pipelined);
@@@ -58,18 -51,22 +58,18 @@@ static void i915_gem_object_set_to_full
  static int i915_gem_object_wait_rendering(struct drm_gem_object *obj,
                                          bool interruptible);
  static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
 -                                         unsigned alignment);
 +                                     unsigned alignment,
 +                                     bool map_and_fenceable);
  static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
  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);
  static void i915_gem_free_object_tail(struct drm_gem_object *obj);
  
 -static int
 -i915_gem_object_get_pages(struct drm_gem_object *obj,
 -                        gfp_t gfpmask);
 -
 -static void
 -i915_gem_object_put_pages(struct drm_gem_object *obj);
 +static int i915_gem_inactive_shrink(struct shrinker *shrinker,
 +                                  int nr_to_scan,
 +                                  gfp_t gfp_mask);
  
 -static LIST_HEAD(shrink_list);
 -static DEFINE_SPINLOCK(shrink_list_lock);
  
  /* some bookkeeping */
  static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
@@@ -87,75 -84,31 +87,75 @@@ static void i915_gem_info_remove_obj(st
  }
  
  static void i915_gem_info_add_gtt(struct drm_i915_private *dev_priv,
 -                                size_t size)
 +                                struct drm_i915_gem_object *obj)
  {
        dev_priv->mm.gtt_count++;
 -      dev_priv->mm.gtt_memory += size;
 +      dev_priv->mm.gtt_memory += obj->gtt_space->size;
 +      if (obj->gtt_offset < dev_priv->mm.gtt_mappable_end) {
 +              dev_priv->mm.mappable_gtt_used +=
 +                      min_t(size_t, obj->gtt_space->size,
 +                            dev_priv->mm.gtt_mappable_end - obj->gtt_offset);
 +      }
  }
  
  static void i915_gem_info_remove_gtt(struct drm_i915_private *dev_priv,
 -                                   size_t size)
 +                                   struct drm_i915_gem_object *obj)
  {
        dev_priv->mm.gtt_count--;
 -      dev_priv->mm.gtt_memory -= size;
 +      dev_priv->mm.gtt_memory -= obj->gtt_space->size;
 +      if (obj->gtt_offset < dev_priv->mm.gtt_mappable_end) {
 +              dev_priv->mm.mappable_gtt_used -=
 +                      min_t(size_t, obj->gtt_space->size,
 +                            dev_priv->mm.gtt_mappable_end - obj->gtt_offset);
 +      }
 +}
 +
 +/**
 + * Update the mappable working set counters. Call _only_ when there is a change
 + * in one of (pin|fault)_mappable and update *_mappable _before_ calling.
 + * @mappable: new state the changed mappable flag (either pin_ or fault_).
 + */
 +static void
 +i915_gem_info_update_mappable(struct drm_i915_private *dev_priv,
 +                            struct drm_i915_gem_object *obj,
 +                            bool mappable)
 +{
 +      if (mappable) {
 +              if (obj->pin_mappable && obj->fault_mappable)
 +                      /* Combined state was already mappable. */
 +                      return;
 +              dev_priv->mm.gtt_mappable_count++;
 +              dev_priv->mm.gtt_mappable_memory += obj->gtt_space->size;
 +      } else {
 +              if (obj->pin_mappable || obj->fault_mappable)
 +                      /* Combined state still mappable. */
 +                      return;
 +              dev_priv->mm.gtt_mappable_count--;
 +              dev_priv->mm.gtt_mappable_memory -= obj->gtt_space->size;
 +      }
  }
  
  static void i915_gem_info_add_pin(struct drm_i915_private *dev_priv,
 -                                size_t size)
 +                                struct drm_i915_gem_object *obj,
 +                                bool mappable)
  {
        dev_priv->mm.pin_count++;
 -      dev_priv->mm.pin_memory += size;
 +      dev_priv->mm.pin_memory += obj->gtt_space->size;
 +      if (mappable) {
 +              obj->pin_mappable = true;
 +              i915_gem_info_update_mappable(dev_priv, obj, true);
 +      }
  }
  
  static void i915_gem_info_remove_pin(struct drm_i915_private *dev_priv,
 -                                   size_t size)
 +                                   struct drm_i915_gem_object *obj)
  {
        dev_priv->mm.pin_count--;
 -      dev_priv->mm.pin_memory -= size;
 +      dev_priv->mm.pin_memory -= obj->gtt_space->size;
 +      if (obj->pin_mappable) {
 +              obj->pin_mappable = false;
 +              i915_gem_info_update_mappable(dev_priv, obj, false);
 +      }
  }
  
  int
@@@ -220,7 -173,6 +220,7 @@@ i915_gem_object_is_inactive(struct drm_
  
  int i915_gem_do_init(struct drm_device *dev,
                     unsigned long start,
 +                   unsigned long mappable_end,
                     unsigned long end)
  {
        drm_i915_private_t *dev_priv = dev->dev_private;
                    end - start);
  
        dev_priv->mm.gtt_total = end - start;
 +      dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start;
 +      dev_priv->mm.gtt_mappable_end = mappable_end;
  
        return 0;
  }
@@@ -249,7 -199,7 +249,7 @@@ i915_gem_init_ioctl(struct drm_device *
        int ret;
  
        mutex_lock(&dev->struct_mutex);
 -      ret = i915_gem_do_init(dev, args->gtt_start, args->gtt_end);
 +      ret = i915_gem_do_init(dev, args->gtt_start, args->gtt_end, args->gtt_end);
        mutex_unlock(&dev->struct_mutex);
  
        return ret;
@@@ -309,6 -259,22 +309,6 @@@ i915_gem_create_ioctl(struct drm_devic
        return 0;
  }
  
 -static inline int
 -fast_shmem_read(struct page **pages,
 -              loff_t page_base, int page_offset,
 -              char __user *data,
 -              int length)
 -{
 -      char *vaddr;
 -      int ret;
 -
 -      vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]);
 -      ret = __copy_to_user_inatomic(data, vaddr + page_offset, length);
 -      kunmap_atomic(vaddr);
 -
 -      return ret;
 -}
 -
  static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj)
  {
        drm_i915_private_t *dev_priv = obj->dev->dev_private;
@@@ -396,9 -362,8 +396,9 @@@ i915_gem_shmem_pread_fast(struct drm_de
                          struct drm_file *file_priv)
  {
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 +      struct address_space *mapping = obj->filp->f_path.dentry->d_inode->i_mapping;
        ssize_t remain;
 -      loff_t offset, page_base;
 +      loff_t offset;
        char __user *user_data;
        int page_offset, page_length;
  
        offset = args->offset;
  
        while (remain > 0) {
 +              struct page *page;
 +              char *vaddr;
 +              int ret;
 +
                /* Operation in this page
                 *
 -               * page_base = page offset within aperture
                 * page_offset = offset within page
                 * page_length = bytes to copy for this page
                 */
 -              page_base = (offset & ~(PAGE_SIZE-1));
                page_offset = offset & (PAGE_SIZE-1);
                page_length = remain;
                if ((page_offset + remain) > PAGE_SIZE)
                        page_length = PAGE_SIZE - page_offset;
  
 -              if (fast_shmem_read(obj_priv->pages,
 -                                  page_base, page_offset,
 -                                  user_data, page_length))
 +              page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
 +                                         GFP_HIGHUSER | __GFP_RECLAIMABLE);
 +              if (IS_ERR(page))
 +                      return PTR_ERR(page);
 +
 +              vaddr = kmap_atomic(page);
 +              ret = __copy_to_user_inatomic(user_data,
 +                                            vaddr + page_offset,
 +                                            page_length);
 +              kunmap_atomic(vaddr);
 +
 +              mark_page_accessed(page);
 +              page_cache_release(page);
 +              if (ret)
                        return -EFAULT;
  
                remain -= page_length;
        return 0;
  }
  
 -static int
 -i915_gem_object_get_pages_or_evict(struct drm_gem_object *obj)
 -{
 -      int ret;
 -
 -      ret = i915_gem_object_get_pages(obj, __GFP_NORETRY | __GFP_NOWARN);
 -
 -      /* If we've insufficient memory to map in the pages, attempt
 -       * to make some space by throwing out some old buffers.
 -       */
 -      if (ret == -ENOMEM) {
 -              struct drm_device *dev = obj->dev;
 -
 -              ret = i915_gem_evict_something(dev, obj->size,
 -                                             i915_gem_get_gtt_alignment(obj));
 -              if (ret)
 -                      return ret;
 -
 -              ret = i915_gem_object_get_pages(obj, 0);
 -      }
 -
 -      return ret;
 -}
 -
  /**
   * This is the fallback shmem pread path, which allocates temporary storage
   * in kernel space to copy_to_user into outside of the struct_mutex, so we
@@@ -458,15 -434,14 +458,15 @@@ i915_gem_shmem_pread_slow(struct drm_de
                          struct drm_i915_gem_pread *args,
                          struct drm_file *file_priv)
  {
 +      struct address_space *mapping = obj->filp->f_path.dentry->d_inode->i_mapping;
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        struct mm_struct *mm = current->mm;
        struct page **user_pages;
        ssize_t remain;
        loff_t offset, pinned_pages, i;
        loff_t first_data_page, last_data_page, num_pages;
 -      int shmem_page_index, shmem_page_offset;
 -      int data_page_index,  data_page_offset;
 +      int shmem_page_offset;
 +      int data_page_index, data_page_offset;
        int page_length;
        int ret;
        uint64_t data_ptr = args->data_ptr;
        offset = args->offset;
  
        while (remain > 0) {
 +              struct page *page;
 +
                /* Operation in this page
                 *
 -               * shmem_page_index = page number within shmem file
                 * shmem_page_offset = offset within page in shmem file
                 * data_page_index = page number in get_user_pages return
                 * data_page_offset = offset with data_page_index page.
                 * page_length = bytes to copy for this page
                 */
 -              shmem_page_index = offset / PAGE_SIZE;
                shmem_page_offset = offset & ~PAGE_MASK;
                data_page_index = data_ptr / PAGE_SIZE - first_data_page;
                data_page_offset = data_ptr & ~PAGE_MASK;
                if ((data_page_offset + page_length) > PAGE_SIZE)
                        page_length = PAGE_SIZE - data_page_offset;
  
 +              page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
 +                                         GFP_HIGHUSER | __GFP_RECLAIMABLE);
 +              if (IS_ERR(page))
 +                      return PTR_ERR(page);
 +
                if (do_bit17_swizzling) {
 -                      slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
 +                      slow_shmem_bit17_copy(page,
                                              shmem_page_offset,
                                              user_pages[data_page_index],
                                              data_page_offset,
                } else {
                        slow_shmem_copy(user_pages[data_page_index],
                                        data_page_offset,
 -                                      obj_priv->pages[shmem_page_index],
 +                                      page,
                                        shmem_page_offset,
                                        page_length);
                }
  
 +              mark_page_accessed(page);
 +              page_cache_release(page);
 +
                remain -= page_length;
                data_ptr += page_length;
                offset += page_length;
  out:
        for (i = 0; i < pinned_pages; i++) {
                SetPageDirty(user_pages[i]);
 +              mark_page_accessed(user_pages[i]);
                page_cache_release(user_pages[i]);
        }
        drm_free_large(user_pages);
@@@ -615,11 -581,15 +615,11 @@@ i915_gem_pread_ioctl(struct drm_device 
                goto out;
        }
  
 -      ret = i915_gem_object_get_pages_or_evict(obj);
 -      if (ret)
 -              goto out;
 -
        ret = i915_gem_object_set_cpu_read_domain_range(obj,
                                                        args->offset,
                                                        args->size);
        if (ret)
 -              goto out_put;
 +              goto out;
  
        ret = -EFAULT;
        if (!i915_gem_object_needs_bit17_swizzle(obj))
        if (ret == -EFAULT)
                ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv);
  
 -out_put:
 -      i915_gem_object_put_pages(obj);
  out:
        drm_gem_object_unreference(obj);
  unlock:
@@@ -678,6 -650,22 +678,6 @@@ slow_kernel_write(struct io_mapping *ma
        io_mapping_unmap(dst_vaddr);
  }
  
 -static inline int
 -fast_shmem_write(struct page **pages,
 -               loff_t page_base, int page_offset,
 -               char __user *data,
 -               int length)
 -{
 -      char *vaddr;
 -      int ret;
 -
 -      vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]);
 -      ret = __copy_from_user_inatomic(vaddr + page_offset, data, length);
 -      kunmap_atomic(vaddr);
 -
 -      return ret;
 -}
 -
  /**
   * This is the fast pwrite path, where we copy the data directly from the
   * user into the GTT, uncached.
@@@ -834,10 -822,9 +834,10 @@@ i915_gem_shmem_pwrite_fast(struct drm_d
                           struct drm_i915_gem_pwrite *args,
                           struct drm_file *file_priv)
  {
 +      struct address_space *mapping = obj->filp->f_path.dentry->d_inode->i_mapping;
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        ssize_t remain;
 -      loff_t offset, page_base;
 +      loff_t offset;
        char __user *user_data;
        int page_offset, page_length;
  
        obj_priv->dirty = 1;
  
        while (remain > 0) {
 +              struct page *page;
 +              char *vaddr;
 +              int ret;
 +
                /* Operation in this page
                 *
 -               * page_base = page offset within aperture
                 * page_offset = offset within page
                 * page_length = bytes to copy for this page
                 */
 -              page_base = (offset & ~(PAGE_SIZE-1));
                page_offset = offset & (PAGE_SIZE-1);
                page_length = remain;
                if ((page_offset + remain) > PAGE_SIZE)
                        page_length = PAGE_SIZE - page_offset;
  
 -              if (fast_shmem_write(obj_priv->pages,
 -                                     page_base, page_offset,
 -                                     user_data, page_length))
 +              page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
 +                                         GFP_HIGHUSER | __GFP_RECLAIMABLE);
 +              if (IS_ERR(page))
 +                      return PTR_ERR(page);
 +
 +              vaddr = kmap_atomic(page, KM_USER0);
 +              ret = __copy_from_user_inatomic(vaddr + page_offset,
 +                                              user_data,
 +                                              page_length);
 +              kunmap_atomic(vaddr, KM_USER0);
 +
 +              set_page_dirty(page);
 +              mark_page_accessed(page);
 +              page_cache_release(page);
 +
 +              /* If we get a fault while copying data, then (presumably) our
 +               * source page isn't available.  Return the error and we'll
 +               * retry in the slow path.
 +               */
 +              if (ret)
                        return -EFAULT;
  
                remain -= page_length;
@@@ -905,14 -873,13 +905,14 @@@ i915_gem_shmem_pwrite_slow(struct drm_d
                           struct drm_i915_gem_pwrite *args,
                           struct drm_file *file_priv)
  {
 +      struct address_space *mapping = obj->filp->f_path.dentry->d_inode->i_mapping;
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        struct mm_struct *mm = current->mm;
        struct page **user_pages;
        ssize_t remain;
        loff_t offset, pinned_pages, i;
        loff_t first_data_page, last_data_page, num_pages;
 -      int shmem_page_index, shmem_page_offset;
 +      int shmem_page_offset;
        int data_page_index,  data_page_offset;
        int page_length;
        int ret;
        obj_priv->dirty = 1;
  
        while (remain > 0) {
 +              struct page *page;
 +
                /* Operation in this page
                 *
 -               * shmem_page_index = page number within shmem file
                 * shmem_page_offset = offset within page in shmem file
                 * data_page_index = page number in get_user_pages return
                 * data_page_offset = offset with data_page_index page.
                 * page_length = bytes to copy for this page
                 */
 -              shmem_page_index = offset / PAGE_SIZE;
                shmem_page_offset = offset & ~PAGE_MASK;
                data_page_index = data_ptr / PAGE_SIZE - first_data_page;
                data_page_offset = data_ptr & ~PAGE_MASK;
                if ((data_page_offset + page_length) > PAGE_SIZE)
                        page_length = PAGE_SIZE - data_page_offset;
  
 +              page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
 +                                         GFP_HIGHUSER | __GFP_RECLAIMABLE);
 +              if (IS_ERR(page)) {
 +                      ret = PTR_ERR(page);
 +                      goto out;
 +              }
 +
                if (do_bit17_swizzling) {
 -                      slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
 +                      slow_shmem_bit17_copy(page,
                                              shmem_page_offset,
                                              user_pages[data_page_index],
                                              data_page_offset,
                                              page_length,
                                              0);
                } else {
 -                      slow_shmem_copy(obj_priv->pages[shmem_page_index],
 +                      slow_shmem_copy(page,
                                        shmem_page_offset,
                                        user_pages[data_page_index],
                                        data_page_offset,
                                        page_length);
                }
  
 +              set_page_dirty(page);
 +              mark_page_accessed(page);
 +              page_cache_release(page);
 +
                remain -= page_length;
                data_ptr += page_length;
                offset += page_length;
@@@ -1073,7 -1029,7 +1073,7 @@@ i915_gem_pwrite_ioctl(struct drm_devic
        else if (obj_priv->tiling_mode == I915_TILING_NONE &&
                 obj_priv->gtt_space &&
                 obj->write_domain != I915_GEM_DOMAIN_CPU) {
 -              ret = i915_gem_object_pin(obj, 0);
 +              ret = i915_gem_object_pin(obj, 0, true);
                if (ret)
                        goto out;
  
  out_unpin:
                i915_gem_object_unpin(obj);
        } else {
 -              ret = i915_gem_object_get_pages_or_evict(obj);
 -              if (ret)
 -                      goto out;
 -
                ret = i915_gem_object_set_to_cpu_domain(obj, 1);
                if (ret)
 -                      goto out_put;
 +                      goto out;
  
                ret = -EFAULT;
                if (!i915_gem_object_needs_bit17_swizzle(obj))
                        ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file);
                if (ret == -EFAULT)
                        ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file);
 -
 -out_put:
 -              i915_gem_object_put_pages(obj);
        }
  
  out:
@@@ -1229,7 -1192,6 +1229,7 @@@ in
  i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
                   struct drm_file *file_priv)
  {
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_mmap *args = data;
        struct drm_gem_object *obj;
        loff_t offset;
        if (obj == NULL)
                return -ENOENT;
  
 +      if (obj->size > dev_priv->mm.gtt_mappable_end) {
 +              drm_gem_object_unreference_unlocked(obj);
 +              return -E2BIG;
 +      }
 +
        offset = args->offset;
  
        down_write(&current->mm->mmap_sem);
@@@ -1296,29 -1253,14 +1296,29 @@@ int i915_gem_fault(struct vm_area_struc
  
        /* Now bind it into the GTT if needed */
        mutex_lock(&dev->struct_mutex);
 +      BUG_ON(obj_priv->pin_count && !obj_priv->pin_mappable);
 +
 +      if (obj_priv->gtt_space) {
 +              if (!obj_priv->map_and_fenceable) {
 +                      ret = i915_gem_object_unbind(obj);
 +                      if (ret)
 +                              goto unlock;
 +              }
 +      }
 +
        if (!obj_priv->gtt_space) {
 -              ret = i915_gem_object_bind_to_gtt(obj, 0);
 +              ret = i915_gem_object_bind_to_gtt(obj, 0, true);
                if (ret)
                        goto unlock;
 +      }
  
 -              ret = i915_gem_object_set_to_gtt_domain(obj, write);
 -              if (ret)
 -                      goto unlock;
 +      ret = i915_gem_object_set_to_gtt_domain(obj, write);
 +      if (ret)
 +              goto unlock;
 +
 +      if (!obj_priv->fault_mappable) {
 +              obj_priv->fault_mappable = true;
 +              i915_gem_info_update_mappable(dev_priv, obj_priv, true);
        }
  
        /* Need a new fence register? */
@@@ -1340,12 -1282,11 +1340,12 @@@ unlock
        mutex_unlock(&dev->struct_mutex);
  
        switch (ret) {
 +      case -EAGAIN:
 +              set_need_resched();
        case 0:
        case -ERESTARTSYS:
                return VM_FAULT_NOPAGE;
        case -ENOMEM:
 -      case -EAGAIN:
                return VM_FAULT_OOM;
        default:
                return VM_FAULT_SIGBUS;
@@@ -1368,6 -1309,7 +1368,6 @@@ i915_gem_create_mmap_offset(struct drm_
  {
        struct drm_device *dev = obj->dev;
        struct drm_gem_mm *mm = dev->mm_private;
 -      struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        struct drm_map_list *list;
        struct drm_local_map *map;
        int ret = 0;
                goto out_free_mm;
        }
  
 -      /* By now we should be all set, any drm_mmap request on the offset
 -       * below will get to our mmap & fault handler */
 -      obj_priv->mmap_offset = ((uint64_t) list->hash.key) << PAGE_SHIFT;
 -
        return 0;
  
  out_free_mm:
        drm_mm_put_block(list->file_offset_node);
  out_free_list:
        kfree(list->map);
 +      list->map = NULL;
  
        return ret;
  }
  i915_gem_release_mmap(struct drm_gem_object *obj)
  {
        struct drm_device *dev = obj->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
  
 -      if (dev->dev_mapping)
 +      if (unlikely(obj->map_list.map && dev->dev_mapping))
                unmap_mapping_range(dev->dev_mapping,
 -                                  obj_priv->mmap_offset, obj->size, 1);
 +                                  (loff_t)obj->map_list.hash.key<<PAGE_SHIFT,
 +                                  obj->size, 1);
 +
 +      if (obj_priv->fault_mappable) {
 +              obj_priv->fault_mappable = false;
 +              i915_gem_info_update_mappable(dev_priv, obj_priv, false);
 +      }
  }
  
  static void
  i915_gem_free_mmap_offset(struct drm_gem_object *obj)
  {
        struct drm_device *dev = obj->dev;
 -      struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        struct drm_gem_mm *mm = dev->mm_private;
 -      struct drm_map_list *list;
 +      struct drm_map_list *list = &obj->map_list;
  
 -      list = &obj->map_list;
        drm_ht_remove_item(&mm->offset_hash, &list->hash);
 -
 -      if (list->file_offset_node) {
 -              drm_mm_put_block(list->file_offset_node);
 -              list->file_offset_node = NULL;
 -      }
 -
 -      if (list->map) {
 -              kfree(list->map);
 -              list->map = NULL;
 -      }
 -
 -      obj_priv->mmap_offset = 0;
 +      drm_mm_put_block(list->file_offset_node);
 +      kfree(list->map);
 +      list->map = NULL;
  }
  
  /**
   * @obj: object to check
   *
   * Return the required GTT alignment for an object, taking into account
 - * potential fence register mapping if needed.
 + * potential fence register mapping.
   */
  static uint32_t
 -i915_gem_get_gtt_alignment(struct drm_gem_object *obj)
 +i915_gem_get_gtt_alignment(struct drm_i915_gem_object *obj_priv)
  {
 -      struct drm_device *dev = obj->dev;
 -      struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 -      int start, i;
 +      struct drm_device *dev = obj_priv->base.dev;
  
        /*
         * Minimum alignment is 4k (GTT page size), but might be greater
         * if a fence register is needed for the object.
         */
 -      if (INTEL_INFO(dev)->gen >= 4 || obj_priv->tiling_mode == I915_TILING_NONE)
 +      if (INTEL_INFO(dev)->gen >= 4 ||
 +          obj_priv->tiling_mode == I915_TILING_NONE)
                return 4096;
  
 +      /*
 +       * Previous chips need to be aligned to the size of the smallest
 +       * fence register that can contain the object.
 +       */
 +      return i915_gem_get_gtt_size(obj_priv);
 +}
 +
 +/**
 + * i915_gem_get_unfenced_gtt_alignment - return required GTT alignment for an
 + *                                     unfenced object
 + * @obj: object to check
 + *
 + * Return the required GTT alignment for an object, only taking into account
 + * unfenced tiled surface requirements.
 + */
 +static uint32_t
 +i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj_priv)
 +{
 +      struct drm_device *dev = obj_priv->base.dev;
 +      int tile_height;
 +
 +      /*
 +       * Minimum alignment is 4k (GTT page size) for sane hw.
 +       */
 +      if (INTEL_INFO(dev)->gen >= 4 || IS_G33(dev) ||
 +          obj_priv->tiling_mode == I915_TILING_NONE)
 +              return 4096;
 +
 +      /*
 +       * Older chips need unfenced tiled buffers to be aligned to the left
 +       * edge of an even tile row (where tile rows are counted as if the bo is
 +       * placed in a fenced gtt region).
 +       */
 +      if (IS_GEN2(dev) ||
 +          (obj_priv->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
 +              tile_height = 32;
 +      else
 +              tile_height = 8;
 +
 +      return tile_height * obj_priv->stride * 2;
 +}
 +
 +static uint32_t
 +i915_gem_get_gtt_size(struct drm_i915_gem_object *obj_priv)
 +{
 +      struct drm_device *dev = obj_priv->base.dev;
 +      uint32_t size;
 +
 +      /*
 +       * Minimum alignment is 4k (GTT page size), but might be greater
 +       * if a fence register is needed for the object.
 +       */
 +      if (INTEL_INFO(dev)->gen >= 4)
 +              return obj_priv->base.size;
 +
        /*
         * Previous chips need to be aligned to the size of the smallest
         * fence register that can contain the object.
         */
        if (INTEL_INFO(dev)->gen == 3)
 -              start = 1024*1024;
 +              size = 1024*1024;
        else
 -              start = 512*1024;
 +              size = 512*1024;
  
 -      for (i = start; i < obj->size; i <<= 1)
 -              ;
 +      while (size < obj_priv->base.size)
 +              size <<= 1;
  
 -      return i;
 +      return size;
  }
  
  /**
@@@ -1571,7 -1466,6 +1571,7 @@@ in
  i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv)
  {
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_mmap_gtt *args = data;
        struct drm_gem_object *obj;
        struct drm_i915_gem_object *obj_priv;
        }
        obj_priv = to_intel_bo(obj);
  
 +      if (obj->size > dev_priv->mm.gtt_mappable_end) {
 +              ret = -E2BIG;
 +              goto unlock;
 +      }
 +
        if (obj_priv->madv != I915_MADV_WILLNEED) {
                DRM_ERROR("Attempting to mmap a purgeable buffer\n");
                ret = -EINVAL;
                goto out;
        }
  
 -      if (!obj_priv->mmap_offset) {
 +      if (!obj->map_list.map) {
                ret = i915_gem_create_mmap_offset(obj);
                if (ret)
                        goto out;
        }
  
 -      args->offset = obj_priv->mmap_offset;
 -
 -      /*
 -       * Pull it into the GTT so that we have a page list (makes the
 -       * initial fault faster and any subsequent flushing possible).
 -       */
 -      if (!obj_priv->agp_mem) {
 -              ret = i915_gem_object_bind_to_gtt(obj, 0);
 -              if (ret)
 -                      goto out;
 -      }
 +      args->offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
  
  out:
        drm_gem_object_unreference(obj);
@@@ -1617,62 -1516,19 +1617,62 @@@ unlock
        return ret;
  }
  
 +static int
 +i915_gem_object_get_pages_gtt(struct drm_gem_object *obj,
 +                            gfp_t gfpmask)
 +{
 +      struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 +      int page_count, i;
 +      struct address_space *mapping;
 +      struct inode *inode;
 +      struct page *page;
 +
 +      /* Get the list of pages out of our struct file.  They'll be pinned
 +       * at this point until we release them.
 +       */
 +      page_count = obj->size / PAGE_SIZE;
 +      BUG_ON(obj_priv->pages != NULL);
 +      obj_priv->pages = drm_malloc_ab(page_count, sizeof(struct page *));
 +      if (obj_priv->pages == NULL)
 +              return -ENOMEM;
 +
 +      inode = obj->filp->f_path.dentry->d_inode;
 +      mapping = inode->i_mapping;
 +      for (i = 0; i < page_count; i++) {
 +              page = read_cache_page_gfp(mapping, i,
 +                                         GFP_HIGHUSER |
 +                                         __GFP_COLD |
 +                                         __GFP_RECLAIMABLE |
 +                                         gfpmask);
 +              if (IS_ERR(page))
 +                      goto err_pages;
 +
 +              obj_priv->pages[i] = page;
 +      }
 +
 +      if (obj_priv->tiling_mode != I915_TILING_NONE)
 +              i915_gem_object_do_bit_17_swizzle(obj);
 +
 +      return 0;
 +
 +err_pages:
 +      while (i--)
 +              page_cache_release(obj_priv->pages[i]);
 +
 +      drm_free_large(obj_priv->pages);
 +      obj_priv->pages = NULL;
 +      return PTR_ERR(page);
 +}
 +
  static void
 -i915_gem_object_put_pages(struct drm_gem_object *obj)
 +i915_gem_object_put_pages_gtt(struct drm_gem_object *obj)
  {
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
        int page_count = obj->size / PAGE_SIZE;
        int i;
  
 -      BUG_ON(obj_priv->pages_refcount == 0);
        BUG_ON(obj_priv->madv == __I915_MADV_PURGED);
  
 -      if (--obj_priv->pages_refcount != 0)
 -              return;
 -
        if (obj_priv->tiling_mode != I915_TILING_NONE)
                i915_gem_object_save_bit_17_swizzle(obj);
  
@@@ -1699,7 -1555,9 +1699,7 @@@ i915_gem_next_request_seqno(struct drm_
                            struct intel_ring_buffer *ring)
  {
        drm_i915_private_t *dev_priv = dev->dev_private;
 -
 -      ring->outstanding_lazy_request = true;
 -      return dev_priv->next_seqno;
 +      return ring->outstanding_lazy_request = dev_priv->next_seqno;
  }
  
  static void
@@@ -1825,7 -1683,7 +1825,7 @@@ i915_gem_process_flushing_list(struct d
        }
  }
  
 -uint32_t
 +int
  i915_add_request(struct drm_device *dev,
                 struct drm_file *file,
                 struct drm_i915_gem_request *request,
        struct drm_i915_file_private *file_priv = NULL;
        uint32_t seqno;
        int was_empty;
 +      int ret;
 +
 +      BUG_ON(request == NULL);
  
        if (file != NULL)
                file_priv = file->driver_priv;
  
 -      if (request == NULL) {
 -              request = kzalloc(sizeof(*request), GFP_KERNEL);
 -              if (request == NULL)
 -                      return 0;
 -      }
 +      ret = ring->add_request(ring, &seqno);
 +      if (ret)
 +          return ret;
  
 -      seqno = ring->add_request(dev, ring, 0);
        ring->outstanding_lazy_request = false;
  
        request->seqno = seqno;
                        queue_delayed_work(dev_priv->wq,
                                           &dev_priv->mm.retire_work, HZ);
        }
 -      return seqno;
 +      return 0;
  }
  
  /**
@@@ -1887,7 -1745,8 +1887,7 @@@ i915_retire_commands(struct drm_device 
        if (INTEL_INFO(dev)->gen >= 4)
                flush_domains |= I915_GEM_DOMAIN_SAMPLER;
  
 -      ring->flush(dev, ring,
 -                      I915_GEM_DOMAIN_COMMAND, flush_domains);
 +      ring->flush(ring, I915_GEM_DOMAIN_COMMAND, flush_domains);
  }
  
  static inline void
@@@ -1994,7 -1853,7 +1994,7 @@@ i915_gem_retire_requests_ring(struct dr
  
        WARN_ON(i915_verify_lists(dev));
  
 -      seqno = ring->get_seqno(dev, ring);
 +      seqno = ring->get_seqno(ring);
        while (!list_empty(&ring->request_list)) {
                struct drm_i915_gem_request *request;
  
  
        if (unlikely (dev_priv->trace_irq_seqno &&
                      i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) {
 -              ring->user_irq_put(dev, ring);
 +              ring->user_irq_put(ring);
                dev_priv->trace_irq_seqno = 0;
        }
  
@@@ -2105,23 -1964,14 +2105,23 @@@ i915_do_wait_request(struct drm_device 
        if (atomic_read(&dev_priv->mm.wedged))
                return -EAGAIN;
  
 -      if (ring->outstanding_lazy_request) {
 -              seqno = i915_add_request(dev, NULL, NULL, ring);
 -              if (seqno == 0)
 +      if (seqno == ring->outstanding_lazy_request) {
 +              struct drm_i915_gem_request *request;
 +
 +              request = kzalloc(sizeof(*request), GFP_KERNEL);
 +              if (request == NULL)
                        return -ENOMEM;
 +
 +              ret = i915_add_request(dev, NULL, request, ring);
 +              if (ret) {
 +                      kfree(request);
 +                      return ret;
 +              }
 +
 +              seqno = request->seqno;
        }
 -      BUG_ON(seqno == dev_priv->next_seqno);
  
 -      if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) {
 +      if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) {
                if (HAS_PCH_SPLIT(dev))
                        ier = I915_READ(DEIER) | I915_READ(GTIER);
                else
  
                trace_i915_gem_request_wait_begin(dev, seqno);
  
 -              ring->waiting_gem_seqno = seqno;
 -              ring->user_irq_get(dev, ring);
 +              ring->waiting_seqno = seqno;
 +              ring->user_irq_get(ring);
                if (interruptible)
                        ret = wait_event_interruptible(ring->irq_queue,
 -                              i915_seqno_passed(
 -                                      ring->get_seqno(dev, ring), seqno)
 +                              i915_seqno_passed(ring->get_seqno(ring), seqno)
                                || atomic_read(&dev_priv->mm.wedged));
                else
                        wait_event(ring->irq_queue,
 -                              i915_seqno_passed(
 -                                      ring->get_seqno(dev, ring), seqno)
 +                              i915_seqno_passed(ring->get_seqno(ring), seqno)
                                || atomic_read(&dev_priv->mm.wedged));
  
 -              ring->user_irq_put(dev, ring);
 -              ring->waiting_gem_seqno = 0;
 +              ring->user_irq_put(ring);
 +              ring->waiting_seqno = 0;
  
                trace_i915_gem_request_wait_end(dev, seqno);
        }
  
        if (ret && ret != -ERESTARTSYS)
                DRM_ERROR("%s returns %d (awaiting %d at %d, next %d)\n",
 -                        __func__, ret, seqno, ring->get_seqno(dev, ring),
 +                        __func__, ret, seqno, ring->get_seqno(ring),
                          dev_priv->next_seqno);
  
        /* Directly dispatch request retiring.  While we have the work queue
@@@ -2188,7 -2040,7 +2188,7 @@@ i915_gem_flush_ring(struct drm_device *
                    uint32_t invalidate_domains,
                    uint32_t flush_domains)
  {
 -      ring->flush(dev, ring, invalidate_domains, flush_domains);
 +      ring->flush(ring, invalidate_domains, flush_domains);
        i915_gem_process_flushing_list(dev, flush_domains, ring);
  }
  
@@@ -2299,12 -2151,11 +2299,12 @@@ i915_gem_object_unbind(struct drm_gem_o
        drm_unbind_agp(obj_priv->agp_mem);
        drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE);
  
 -      i915_gem_object_put_pages(obj);
 -      BUG_ON(obj_priv->pages_refcount);
 +      i915_gem_object_put_pages_gtt(obj);
  
 -      i915_gem_info_remove_gtt(dev_priv, obj->size);
 +      i915_gem_info_remove_gtt(dev_priv, obj_priv);
        list_del_init(&obj_priv->mm_list);
 +      /* Avoid an unnecessary call to unbind on rebind. */
 +      obj_priv->map_and_fenceable = true;
  
        drm_mm_put_block(obj_priv->gtt_space);
        obj_priv->gtt_space = NULL;
@@@ -2359,16 -2210,72 +2359,16 @@@ i915_gpu_idle(struct drm_device *dev
        return 0;
  }
  
 -static int
 -i915_gem_object_get_pages(struct drm_gem_object *obj,
 -                        gfp_t gfpmask)
 +static void sandybridge_write_fence_reg(struct drm_gem_object *obj)
  {
 -      struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 -      int page_count, i;
 -      struct address_space *mapping;
 -      struct inode *inode;
 -      struct page *page;
 -
 -      BUG_ON(obj_priv->pages_refcount
 -                      == DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT);
 -
 -      if (obj_priv->pages_refcount++ != 0)
 -              return 0;
 -
 -      /* Get the list of pages out of our struct file.  They'll be pinned
 -       * at this point until we release them.
 -       */
 -      page_count = obj->size / PAGE_SIZE;
 -      BUG_ON(obj_priv->pages != NULL);
 -      obj_priv->pages = drm_calloc_large(page_count, sizeof(struct page *));
 -      if (obj_priv->pages == NULL) {
 -              obj_priv->pages_refcount--;
 -              return -ENOMEM;
 -      }
 -
 -      inode = obj->filp->f_path.dentry->d_inode;
 -      mapping = inode->i_mapping;
 -      for (i = 0; i < page_count; i++) {
 -              page = read_cache_page_gfp(mapping, i,
 -                                         GFP_HIGHUSER |
 -                                         __GFP_COLD |
 -                                         __GFP_RECLAIMABLE |
 -                                         gfpmask);
 -              if (IS_ERR(page))
 -                      goto err_pages;
 -
 -              obj_priv->pages[i] = page;
 -      }
 -
 -      if (obj_priv->tiling_mode != I915_TILING_NONE)
 -              i915_gem_object_do_bit_17_swizzle(obj);
 -
 -      return 0;
 -
 -err_pages:
 -      while (i--)
 -              page_cache_release(obj_priv->pages[i]);
 -
 -      drm_free_large(obj_priv->pages);
 -      obj_priv->pages = NULL;
 -      obj_priv->pages_refcount--;
 -      return PTR_ERR(page);
 -}
 -
 -static void sandybridge_write_fence_reg(struct drm_i915_fence_reg *reg)
 -{
 -      struct drm_gem_object *obj = reg->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);
 +      u32 size = i915_gem_get_gtt_size(obj_priv);
        int regnum = obj_priv->fence_reg;
        uint64_t val;
  
 -      val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
 +      val = (uint64_t)((obj_priv->gtt_offset + size - 4096) &
                    0xfffff000) << 32;
        val |= obj_priv->gtt_offset & 0xfffff000;
        val |= (uint64_t)((obj_priv->stride / 128) - 1) <<
        I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (regnum * 8), val);
  }
  
 -static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
 +static void i965_write_fence_reg(struct drm_gem_object *obj)
  {
 -      struct drm_gem_object *obj = reg->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);
 +      u32 size = i915_gem_get_gtt_size(obj_priv);
        int regnum = obj_priv->fence_reg;
        uint64_t val;
  
 -      val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
 +      val = (uint64_t)((obj_priv->gtt_offset + size - 4096) &
                    0xfffff000) << 32;
        val |= obj_priv->gtt_offset & 0xfffff000;
        val |= ((obj_priv->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT;
        I915_WRITE64(FENCE_REG_965_0 + (regnum * 8), val);
  }
  
 -static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
 +static void i915_write_fence_reg(struct drm_gem_object *obj)
  {
 -      struct drm_gem_object *obj = reg->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);
 -      int regnum = obj_priv->fence_reg;
 +      u32 size = i915_gem_get_gtt_size(obj_priv);
 +      uint32_t fence_reg, val, pitch_val;
        int tile_width;
 -      uint32_t fence_reg, val;
 -      uint32_t pitch_val;
  
        if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
 -          (obj_priv->gtt_offset & (obj->size - 1))) {
 -              WARN(1, "%s: object 0x%08x not 1M or size (0x%zx) aligned\n",
 -                   __func__, obj_priv->gtt_offset, obj->size);
 +          (obj_priv->gtt_offset & (size - 1))) {
 +              WARN(1, "%s: object 0x%08x [fenceable? %d] not 1M or size (0x%08x) aligned [gtt_space offset=%lx, size=%lx]\n",
 +                   __func__, obj_priv->gtt_offset, obj_priv->map_and_fenceable, size,
 +                   obj_priv->gtt_space->start, obj_priv->gtt_space->size);
                return;
        }
  
        val = obj_priv->gtt_offset;
        if (obj_priv->tiling_mode == I915_TILING_Y)
                val |= 1 << I830_FENCE_TILING_Y_SHIFT;
 -      val |= I915_FENCE_SIZE_BITS(obj->size);
 +      val |= I915_FENCE_SIZE_BITS(size);
        val |= pitch_val << I830_FENCE_PITCH_SHIFT;
        val |= I830_FENCE_REG_VALID;
  
 -      if (regnum < 8)
 -              fence_reg = FENCE_REG_830_0 + (regnum * 4);
 +      fence_reg = obj_priv->fence_reg;
 +      if (fence_reg < 8)
 +              fence_reg = FENCE_REG_830_0 + fence_reg * 4;
        else
 -              fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4);
 +              fence_reg = FENCE_REG_945_8 + (fence_reg - 8) * 4;
        I915_WRITE(fence_reg, val);
  }
  
 -static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
 +static void i830_write_fence_reg(struct drm_gem_object *obj)
  {
 -      struct drm_gem_object *obj = reg->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);
 +      u32 size = i915_gem_get_gtt_size(obj_priv);
        int regnum = obj_priv->fence_reg;
        uint32_t val;
        uint32_t pitch_val;
        val = obj_priv->gtt_offset;
        if (obj_priv->tiling_mode == I915_TILING_Y)
                val |= 1 << I830_FENCE_TILING_Y_SHIFT;
 -      fence_size_bits = I830_FENCE_SIZE_BITS(obj->size);
 +      fence_size_bits = I830_FENCE_SIZE_BITS(size);
        WARN_ON(fence_size_bits & ~0x00000f00);
        val |= fence_size_bits;
        val |= pitch_val << I830_FENCE_PITCH_SHIFT;
  static int i915_find_fence_reg(struct drm_device *dev,
                               bool interruptible)
  {
 -      struct drm_i915_fence_reg *reg = NULL;
 -      struct drm_i915_gem_object *obj_priv = NULL;
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct drm_gem_object *obj = NULL;
 +      struct drm_i915_fence_reg *reg;
 +      struct drm_i915_gem_object *obj_priv = NULL;
        int i, avail, ret;
  
        /* First try to find a free reg */
                return -ENOSPC;
  
        /* None available, try to steal one or wait for a user to finish */
 -      i = I915_FENCE_REG_NONE;
 +      avail = I915_FENCE_REG_NONE;
        list_for_each_entry(reg, &dev_priv->mm.fence_list,
                            lru_list) {
 -              obj = reg->obj;
 -              obj_priv = to_intel_bo(obj);
 -
 +              obj_priv = to_intel_bo(reg->obj);
                if (obj_priv->pin_count)
                        continue;
  
                /* found one! */
 -              i = obj_priv->fence_reg;
 +              avail = obj_priv->fence_reg;
                break;
        }
  
 -      BUG_ON(i == I915_FENCE_REG_NONE);
 +      BUG_ON(avail == I915_FENCE_REG_NONE);
  
        /* We only have a reference on obj from the active list. put_fence_reg
         * might drop that one, causing a use-after-free in it. So hold a
         * private reference to obj like the other callers of put_fence_reg
         * (set_tiling ioctl) do. */
 -      drm_gem_object_reference(obj);
 -      ret = i915_gem_object_put_fence_reg(obj, interruptible);
 -      drm_gem_object_unreference(obj);
 +      drm_gem_object_reference(&obj_priv->base);
 +      ret = i915_gem_object_put_fence_reg(&obj_priv->base, interruptible);
 +      drm_gem_object_unreference(&obj_priv->base);
        if (ret != 0)
                return ret;
  
 -      return i;
 +      return avail;
  }
  
  /**
@@@ -2596,23 -2506,22 +2596,23 @@@ i915_gem_object_get_fence_reg(struct dr
  
        switch (INTEL_INFO(dev)->gen) {
        case 6:
 -              sandybridge_write_fence_reg(reg);
 +              sandybridge_write_fence_reg(obj);
                break;
        case 5:
        case 4:
 -              i965_write_fence_reg(reg);
 +              i965_write_fence_reg(obj);
                break;
        case 3:
 -              i915_write_fence_reg(reg);
 +              i915_write_fence_reg(obj);
                break;
        case 2:
 -              i830_write_fence_reg(reg);
 +              i830_write_fence_reg(obj);
                break;
        }
  
 -      trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg,
 -                      obj_priv->tiling_mode);
 +      trace_i915_gem_object_get_fence(obj,
 +                                      obj_priv->fence_reg,
 +                                      obj_priv->tiling_mode);
  
        return 0;
  }
@@@ -2715,17 -2624,13 +2715,17 @@@ i915_gem_object_put_fence_reg(struct dr
   * Finds free space in the GTT aperture and binds the object there.
   */
  static int
 -i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
 +i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
 +                          unsigned alignment,
 +                          bool map_and_fenceable)
  {
        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);
        struct drm_mm_node *free_space;
 -      gfp_t gfpmask =  __GFP_NORETRY | __GFP_NOWARN;
 +      gfp_t gfpmask = __GFP_NORETRY | __GFP_NOWARN;
 +      u32 size, fence_size, fence_alignment, unfenced_alignment;
 +      bool mappable, fenceable;
        int ret;
  
        if (obj_priv->madv != I915_MADV_WILLNEED) {
                return -EINVAL;
        }
  
 +      fence_size = i915_gem_get_gtt_size(obj_priv);
 +      fence_alignment = i915_gem_get_gtt_alignment(obj_priv);
 +      unfenced_alignment = i915_gem_get_unfenced_gtt_alignment(obj_priv);
 +
        if (alignment == 0)
 -              alignment = i915_gem_get_gtt_alignment(obj);
 -      if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) {
 +              alignment = map_and_fenceable ? fence_alignment :
 +                                              unfenced_alignment;
 +      if (map_and_fenceable && alignment & (fence_alignment - 1)) {
                DRM_ERROR("Invalid object alignment requested %u\n", alignment);
                return -EINVAL;
        }
  
 +      size = map_and_fenceable ? fence_size : obj->size;
 +
        /* If the object is bigger than the entire aperture, reject it early
         * before evicting everything in a vain attempt to find space.
         */
 -      if (obj->size > dev_priv->mm.gtt_total) {
 +      if (obj->size >
 +          (map_and_fenceable ? dev_priv->mm.gtt_mappable_end : dev_priv->mm.gtt_total)) {
                DRM_ERROR("Attempting to bind an object larger than the aperture\n");
                return -E2BIG;
        }
  
   search_free:
 -      free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
 -                                      obj->size, alignment, 0);
 -      if (free_space != NULL)
 -              obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
 -                                                     alignment);
 +      if (map_and_fenceable)
 +              free_space =
 +                      drm_mm_search_free_in_range(&dev_priv->mm.gtt_space,
 +                                                  size, alignment, 0,
 +                                                  dev_priv->mm.gtt_mappable_end,
 +                                                  0);
 +      else
 +              free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
 +                                              size, alignment, 0);
 +
 +      if (free_space != NULL) {
 +              if (map_and_fenceable)
 +                      obj_priv->gtt_space =
 +                              drm_mm_get_block_range_generic(free_space,
 +                                                             size, alignment, 0,
 +                                                             dev_priv->mm.gtt_mappable_end,
 +                                                             0);
 +              else
 +                      obj_priv->gtt_space =
 +                              drm_mm_get_block(free_space, size, alignment);
 +      }
        if (obj_priv->gtt_space == NULL) {
                /* If the gtt is empty and we're still having trouble
                 * fitting our object in, we're out of memory.
                 */
 -              ret = i915_gem_evict_something(dev, obj->size, alignment);
 +              ret = i915_gem_evict_something(dev, size, alignment,
 +                                             map_and_fenceable);
                if (ret)
                        return ret;
  
                goto search_free;
        }
  
 -      ret = i915_gem_object_get_pages(obj, gfpmask);
 +      ret = i915_gem_object_get_pages_gtt(obj, gfpmask);
        if (ret) {
                drm_mm_put_block(obj_priv->gtt_space);
                obj_priv->gtt_space = NULL;
  
                if (ret == -ENOMEM) {
                        /* first try to clear up some space from the GTT */
 -                      ret = i915_gem_evict_something(dev, obj->size,
 -                                                     alignment);
 +                      ret = i915_gem_evict_something(dev, size,
 +                                                     alignment,
 +                                                     map_and_fenceable);
                        if (ret) {
                                /* now try to shrink everyone else */
                                if (gfpmask) {
                                               obj_priv->gtt_space->start,
                                               obj_priv->agp_type);
        if (obj_priv->agp_mem == NULL) {
 -              i915_gem_object_put_pages(obj);
 +              i915_gem_object_put_pages_gtt(obj);
                drm_mm_put_block(obj_priv->gtt_space);
                obj_priv->gtt_space = NULL;
  
 -              ret = i915_gem_evict_something(dev, obj->size, alignment);
 +              ret = i915_gem_evict_something(dev, size,
 +                                             alignment, map_and_fenceable);
                if (ret)
                        return ret;
  
                goto search_free;
        }
  
 +      obj_priv->gtt_offset = obj_priv->gtt_space->start;
 +
        /* keep track of bounds object by adding it to the inactive list */
        list_add_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list);
 -      i915_gem_info_add_gtt(dev_priv, obj->size);
 +      i915_gem_info_add_gtt(dev_priv, obj_priv);
  
        /* 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
        BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS);
        BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS);
  
 -      obj_priv->gtt_offset = obj_priv->gtt_space->start;
 -      trace_i915_gem_object_bind(obj, obj_priv->gtt_offset);
 +      trace_i915_gem_object_bind(obj, obj_priv->gtt_offset, map_and_fenceable);
 +
 +      fenceable =
 +              obj_priv->gtt_space->size == fence_size &&
 +              (obj_priv->gtt_space->start & (fence_alignment -1)) == 0;
 +
 +      mappable =
 +              obj_priv->gtt_offset + obj->size <= dev_priv->mm.gtt_mappable_end;
 +
 +      obj_priv->map_and_fenceable = mappable && fenceable;
  
        return 0;
  }
@@@ -2887,16 -2755,22 +2887,16 @@@ i915_gem_object_flush_gpu_write_domain(
                                       bool pipelined)
  {
        struct drm_device *dev = obj->dev;
 -      uint32_t old_write_domain;
  
        if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
                return 0;
  
        /* Queue the GPU write cache flushing we need. */
 -      old_write_domain = obj->write_domain;
        i915_gem_flush_ring(dev, NULL,
                            to_intel_bo(obj)->ring,
                            0, obj->write_domain);
        BUG_ON(obj->write_domain);
  
 -      trace_i915_gem_object_change_domain(obj,
 -                                          obj->read_domains,
 -                                          old_write_domain);
 -
        if (pipelined)
                return 0;
  
@@@ -2916,8 -2790,6 +2916,8 @@@ i915_gem_object_flush_gtt_write_domain(
         * to it immediately go to main memory as far as we know, so there's
         * no chipset flush.  It also doesn't land in render cache.
         */
 +      i915_gem_release_mmap(obj);
 +
        old_write_domain = obj->write_domain;
        obj->write_domain = 0;
  
@@@ -3035,6 -2907,20 +3035,20 @@@ i915_gem_object_set_to_display_plane(st
        return 0;
  }
  
+ int
+ i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
+                         bool interruptible)
+ {
+       if (!obj->active)
+               return 0;
+       if (obj->base.write_domain & I915_GEM_GPU_DOMAINS)
+               i915_gem_flush_ring(obj->base.dev, NULL, obj->ring,
+                                   0, obj->base.write_domain);
+       return i915_gem_object_wait_rendering(&obj->base, interruptible);
+ }
  /**
   * Moves a single object to the CPU read, and possibly write domain.
   *
@@@ -3207,12 -3093,16 +3221,12 @@@ i915_gem_object_set_to_cpu_domain(struc
   */
  static void
  i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
 -                                struct intel_ring_buffer *ring)
 +                                struct intel_ring_buffer *ring,
 +                                struct change_domains *cd)
  {
 -      struct drm_device               *dev = obj->dev;
 -      struct drm_i915_private         *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;
 -      uint32_t                        old_read_domains;
 -
 -      intel_mark_busy(dev, obj);
  
        /*
         * If the object isn't moving to a new write domain,
         */
        if (obj->pending_write_domain == 0)
                obj->pending_read_domains |= obj->read_domains;
 -      else
 -              obj_priv->dirty = 1;
  
        /*
         * Flush the current write domain if
        if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU)
                i915_gem_clflush_object(obj);
  
 -      old_read_domains = obj->read_domains;
 +      /* blow away mappings if mapped through GTT */
 +      if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT)
 +              i915_gem_release_mmap(obj);
  
        /* The actual obj->write_domain will be updated with
         * pending_write_domain after we emit the accumulated flush for all
         */
        if (flush_domains == 0 && obj->pending_write_domain == 0)
                obj->pending_write_domain = obj->write_domain;
 -      obj->read_domains = obj->pending_read_domains;
  
 -      dev->invalidate_domains |= invalidate_domains;
 -      dev->flush_domains |= flush_domains;
 +      cd->invalidate_domains |= invalidate_domains;
 +      cd->flush_domains |= flush_domains;
        if (flush_domains & I915_GEM_GPU_DOMAINS)
 -              dev_priv->mm.flush_rings |= obj_priv->ring->id;
 +              cd->flush_rings |= obj_priv->ring->id;
        if (invalidate_domains & I915_GEM_GPU_DOMAINS)
 -              dev_priv->mm.flush_rings |= ring->id;
 -
 -      trace_i915_gem_object_change_domain(obj,
 -                                          old_read_domains,
 -                                          obj->write_domain);
 +              cd->flush_rings |= ring->id;
  }
  
  /**
@@@ -3559,30 -3454,25 +3573,30 @@@ i915_gem_execbuffer_pin(struct drm_devi
        int ret, i, retry;
  
        /* attempt to pin all of the buffers into the GTT */
 -      for (retry = 0; retry < 2; retry++) {
 +      retry = 0;
 +      do {
                ret = 0;
                for (i = 0; i < count; i++) {
                        struct drm_i915_gem_exec_object2 *entry = &exec_list[i];
 -                      struct drm_i915_gem_object *obj= to_intel_bo(object_list[i]);
 +                      struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]);
                        bool need_fence =
                                entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
                                obj->tiling_mode != I915_TILING_NONE;
  
 +                      /* g33/pnv can't fence buffers in the unmappable part */
 +                      bool need_mappable =
 +                              entry->relocation_count ? true : need_fence;
 +
                        /* Check fence reg constraints and rebind if necessary */
 -                      if (need_fence &&
 -                          !i915_gem_object_fence_offset_ok(&obj->base,
 -                                                           obj->tiling_mode)) {
 +                      if (need_mappable && !obj->map_and_fenceable) {
                                ret = i915_gem_object_unbind(&obj->base);
                                if (ret)
                                        break;
                        }
  
 -                      ret = i915_gem_object_pin(&obj->base, entry->alignment);
 +                      ret = i915_gem_object_pin(&obj->base,
 +                                                entry->alignment,
 +                                                need_mappable);
                        if (ret)
                                break;
  
                while (i--)
                        i915_gem_object_unpin(object_list[i]);
  
 -              if (ret == 0)
 -                      break;
 -
 -              if (ret != -ENOSPC || retry)
 +              if (ret != -ENOSPC || retry > 1)
                        return ret;
  
 -              ret = i915_gem_evict_everything(dev);
 +              /* First attempt, just clear anything that is purgeable.
 +               * Second attempt, clear the entire GTT.
 +               */
 +              ret = i915_gem_evict_everything(dev, retry == 0);
                if (ret)
                        return ret;
 -      }
  
 -      return 0;
 +              retry++;
 +      } while (1);
  }
  
  static int
@@@ -3627,26 -3517,30 +3641,26 @@@ i915_gem_execbuffer_move_to_gpu(struct 
                                struct drm_gem_object **objects,
                                int count)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct change_domains cd;
        int ret, i;
  
 -      /* Zero the global flush/invalidate flags. These
 -       * will be modified as new domains are computed
 -       * for each object
 -       */
 -      dev->invalidate_domains = 0;
 -      dev->flush_domains = 0;
 -      dev_priv->mm.flush_rings = 0;
 +      cd.invalidate_domains = 0;
 +      cd.flush_domains = 0;
 +      cd.flush_rings = 0;
        for (i = 0; i < count; i++)
 -              i915_gem_object_set_to_gpu_domain(objects[i], ring);
 +              i915_gem_object_set_to_gpu_domain(objects[i], ring, &cd);
  
 -      if (dev->invalidate_domains | dev->flush_domains) {
 +      if (cd.invalidate_domains | cd.flush_domains) {
  #if WATCH_EXEC
                DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
                          __func__,
 -                       dev->invalidate_domains,
 -                       dev->flush_domains);
 +                       cd.invalidate_domains,
 +                       cd.flush_domains);
  #endif
                i915_gem_flush(dev, file,
 -                             dev->invalidate_domains,
 -                             dev->flush_domains,
 -                             dev_priv->mm.flush_rings);
 +                             cd.invalidate_domains,
 +                             cd.flush_domains,
 +                             cd.flush_rings);
        }
  
        for (i = 0; i < count; i++) {
@@@ -3697,17 -3591,17 +3711,17 @@@ i915_gem_ring_throttle(struct drm_devic
                return 0;
  
        ret = 0;
 -      if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) {
 +      if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) {
                /* And wait for the seqno passing without holding any locks and
                 * causing extra latency for others. This is safe as the irq
                 * generation is designed to be run atomically and so is
                 * lockless.
                 */
 -              ring->user_irq_get(dev, ring);
 +              ring->user_irq_get(ring);
                ret = wait_event_interruptible(ring->irq_queue,
 -                                             i915_seqno_passed(ring->get_seqno(dev, ring), seqno)
 +                                             i915_seqno_passed(ring->get_seqno(ring), seqno)
                                               || atomic_read(&dev_priv->mm.wedged));
 -              ring->user_irq_put(dev, ring);
 +              ring->user_irq_put(ring);
  
                if (ret == 0 && atomic_read(&dev_priv->mm.wedged))
                        ret = -EIO;
@@@ -3770,6 -3664,7 +3784,6 @@@ i915_gem_do_execbuffer(struct drm_devic
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_gem_object **object_list = NULL;
        struct drm_gem_object *batch_obj;
 -      struct drm_i915_gem_object *obj_priv;
        struct drm_clip_rect *cliprects = NULL;
        struct drm_i915_gem_request *request = NULL;
        int ret, i, flips;
  
        /* Look up object handles */
        for (i = 0; i < args->buffer_count; i++) {
 +              struct drm_i915_gem_object *obj_priv;
 +
                object_list[i] = drm_gem_object_lookup(dev, file,
                                                       exec_list[i].handle);
                if (object_list[i] == NULL) {
        if (ret)
                goto err;
  
 -      for (i = 0; i < args->buffer_count; i++) {
 -              struct drm_gem_object *obj = object_list[i];
 -              uint32_t old_write_domain = obj->write_domain;
 -              obj->write_domain = obj->pending_write_domain;
 -              trace_i915_gem_object_change_domain(obj,
 -                                                  obj->read_domains,
 -                                                  old_write_domain);
 -      }
 -
  #if WATCH_COHERENCY
        for (i = 0; i < args->buffer_count; i++) {
                i915_gem_object_check_coherency(object_list[i],
                        else
                                flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
  
 -                      intel_ring_begin(dev, ring, 2);
 -                      intel_ring_emit(dev, ring,
 -                                      MI_WAIT_FOR_EVENT | flip_mask);
 -                      intel_ring_emit(dev, ring, MI_NOOP);
 -                      intel_ring_advance(dev, ring);
 +                      ret = intel_ring_begin(ring, 2);
 +                      if (ret)
 +                              goto err;
 +
 +                      intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
 +                      intel_ring_emit(ring, MI_NOOP);
 +                      intel_ring_advance(ring);
                }
        }
  
        /* Exec the batchbuffer */
 -      ret = ring->dispatch_gem_execbuffer(dev, ring, args,
 -                                          cliprects, exec_offset);
 +      ret = ring->dispatch_execbuffer(ring, args, cliprects, exec_offset);
        if (ret) {
                DRM_ERROR("dispatch failed %d\n", ret);
                goto err;
        }
  
 -      /*
 -       * Ensure that the commands in the batch buffer are
 -       * finished before the interrupt fires
 -       */
 -      i915_retire_commands(dev, ring);
 -
        for (i = 0; i < args->buffer_count; i++) {
                struct drm_gem_object *obj = object_list[i];
  
 +              obj->read_domains = obj->pending_read_domains;
 +              obj->write_domain = obj->pending_write_domain;
 +
                i915_gem_object_move_to_active(obj, ring);
 -              if (obj->write_domain)
 -                      list_move_tail(&to_intel_bo(obj)->gpu_write_list,
 +              if (obj->write_domain) {
 +                      struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 +                      obj_priv->dirty = 1;
 +                      list_move_tail(&obj_priv->gpu_write_list,
                                       &ring->gpu_write_list);
 +                      intel_mark_busy(dev, obj);
 +              }
 +
 +              trace_i915_gem_object_change_domain(obj,
 +                                                  obj->read_domains,
 +                                                  obj->write_domain);
        }
  
 -      i915_add_request(dev, file, request, ring);
 -      request = NULL;
 +      /*
 +       * Ensure that the commands in the batch buffer are
 +       * finished before the interrupt fires
 +       */
 +      i915_retire_commands(dev, ring);
 +
 +      if (i915_add_request(dev, file, request, ring))
 +              i915_gem_next_request_seqno(dev, ring);
 +      else
 +              request = NULL;
  
  err:
        for (i = 0; i < args->buffer_count; i++) {
 -              if (object_list[i]) {
 -                      obj_priv = to_intel_bo(object_list[i]);
 -                      obj_priv->in_execbuffer = false;
 -              }
 +              if (object_list[i] == NULL)
 +                  break;
 +
 +              to_intel_bo(object_list[i])->in_execbuffer = false;
                drm_gem_object_unreference(object_list[i]);
        }
  
@@@ -4176,8 -4064,7 +4190,8 @@@ i915_gem_execbuffer2(struct drm_device 
  }
  
  int
 -i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
 +i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment,
 +                  bool map_and_fenceable)
  {
        struct drm_device *dev = obj->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
  
        BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
 +      BUG_ON(map_and_fenceable && !map_and_fenceable);
        WARN_ON(i915_verify_lists(dev));
  
        if (obj_priv->gtt_space != NULL) {
 -              if (alignment == 0)
 -                      alignment = i915_gem_get_gtt_alignment(obj);
 -              if (obj_priv->gtt_offset & (alignment - 1)) {
 +              if ((alignment && obj_priv->gtt_offset & (alignment - 1)) ||
 +                  (map_and_fenceable && !obj_priv->map_and_fenceable)) {
                        WARN(obj_priv->pin_count,
 -                           "bo is already pinned with incorrect alignment: offset=%x, req.alignment=%x\n",
 -                           obj_priv->gtt_offset, alignment);
 +                           "bo is already pinned with incorrect alignment:"
 +                           " offset=%x, req.alignment=%x, req.map_and_fenceable=%d,"
 +                           " obj->map_and_fenceable=%d\n",
 +                           obj_priv->gtt_offset, alignment,
 +                           map_and_fenceable,
 +                           obj_priv->map_and_fenceable);
                        ret = i915_gem_object_unbind(obj);
                        if (ret)
                                return ret;
        }
  
        if (obj_priv->gtt_space == NULL) {
 -              ret = i915_gem_object_bind_to_gtt(obj, alignment);
 +              ret = i915_gem_object_bind_to_gtt(obj, alignment,
 +                                                map_and_fenceable);
                if (ret)
                        return ret;
        }
  
 -      obj_priv->pin_count++;
 -
 -      /* If the object is not active and not pending a flush,
 -       * remove it from the inactive list
 -       */
 -      if (obj_priv->pin_count == 1) {
 -              i915_gem_info_add_pin(dev_priv, obj->size);
 +      if (obj_priv->pin_count++ == 0) {
 +              i915_gem_info_add_pin(dev_priv, obj_priv, map_and_fenceable);
                if (!obj_priv->active)
                        list_move_tail(&obj_priv->mm_list,
                                       &dev_priv->mm.pinned_list);
        }
 +      BUG_ON(!obj_priv->pin_mappable && map_and_fenceable);
  
        WARN_ON(i915_verify_lists(dev));
        return 0;
@@@ -4231,14 -4117,19 +4245,14 @@@ i915_gem_object_unpin(struct drm_gem_ob
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
  
        WARN_ON(i915_verify_lists(dev));
 -      obj_priv->pin_count--;
 -      BUG_ON(obj_priv->pin_count < 0);
 +      BUG_ON(obj_priv->pin_count == 0);
        BUG_ON(obj_priv->gtt_space == NULL);
  
 -      /* If the object is no longer pinned, and is
 -       * neither active nor being flushed, then stick it on
 -       * the inactive list
 -       */
 -      if (obj_priv->pin_count == 0) {
 +      if (--obj_priv->pin_count == 0) {
                if (!obj_priv->active)
                        list_move_tail(&obj_priv->mm_list,
                                       &dev_priv->mm.inactive_list);
 -              i915_gem_info_remove_pin(dev_priv, obj->size);
 +              i915_gem_info_remove_pin(dev_priv, obj_priv);
        }
        WARN_ON(i915_verify_lists(dev));
  }
@@@ -4279,7 -4170,7 +4293,7 @@@ i915_gem_pin_ioctl(struct drm_device *d
        obj_priv->user_pin_count++;
        obj_priv->pin_filp = file_priv;
        if (obj_priv->user_pin_count == 1) {
 -              ret = i915_gem_object_pin(obj, args->alignment);
 +              ret = i915_gem_object_pin(obj, args->alignment, true);
                if (ret)
                        goto out;
        }
@@@ -4472,8 -4363,6 +4486,8 @@@ struct drm_gem_object * i915_gem_alloc_
        INIT_LIST_HEAD(&obj->ring_list);
        INIT_LIST_HEAD(&obj->gpu_write_list);
        obj->madv = I915_MADV_WILLNEED;
 +      /* Avoid an unnecessary call to unbind on the first bind. */
 +      obj->map_and_fenceable = true;
  
        return &obj->base;
  }
@@@ -4499,7 -4388,7 +4513,7 @@@ static void i915_gem_free_object_tail(s
                return;
        }
  
 -      if (obj_priv->mmap_offset)
 +      if (obj->map_list.map)
                i915_gem_free_mmap_offset(obj);
  
        drm_gem_object_release(obj);
@@@ -4547,7 -4436,7 +4561,7 @@@ 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_inactive(dev);
 +              ret = i915_gem_evict_inactive(dev, false);
                if (ret) {
                        mutex_unlock(&dev->struct_mutex);
                        return ret;
@@@ -4593,7 -4482,7 +4607,7 @@@ i915_gem_init_pipe_control(struct drm_d
        obj_priv = to_intel_bo(obj);
        obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
  
 -      ret = i915_gem_object_pin(obj, 4096);
 +      ret = i915_gem_object_pin(obj, 4096, true);
        if (ret)
                goto err_unref;
  
@@@ -4666,9 -4555,9 +4680,9 @@@ i915_gem_init_ringbuffer(struct drm_dev
        return 0;
  
  cleanup_bsd_ring:
 -      intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
 +      intel_cleanup_ring_buffer(&dev_priv->bsd_ring);
  cleanup_render_ring:
 -      intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
 +      intel_cleanup_ring_buffer(&dev_priv->render_ring);
  cleanup_pipe_control:
        if (HAS_PIPE_CONTROL(dev))
                i915_gem_cleanup_pipe_control(dev);
@@@ -4680,9 -4569,9 +4694,9 @@@ i915_gem_cleanup_ringbuffer(struct drm_
  {
        drm_i915_private_t *dev_priv = dev->dev_private;
  
 -      intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
 -      intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
 -      intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring);
 +      intel_cleanup_ring_buffer(&dev_priv->render_ring);
 +      intel_cleanup_ring_buffer(&dev_priv->bsd_ring);
 +      intel_cleanup_ring_buffer(&dev_priv->blt_ring);
        if (HAS_PIPE_CONTROL(dev))
                i915_gem_cleanup_pipe_control(dev);
  }
@@@ -4789,6 -4678,9 +4803,6 @@@ i915_gem_load(struct drm_device *dev
        INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
                          i915_gem_retire_work_handler);
        init_completion(&dev_priv->error_completion);
 -      spin_lock(&shrink_list_lock);
 -      list_add(&dev_priv->mm.shrink_list, &shrink_list);
 -      spin_unlock(&shrink_list_lock);
  
        /* On GEN3 we really need to make sure the ARB C3 LP bit is set */
        if (IS_GEN3(dev)) {
        }
        i915_gem_detect_bit_6_swizzle(dev);
        init_waitqueue_head(&dev_priv->pending_flip_queue);
 +
 +      dev_priv->mm.inactive_shrinker.shrink = i915_gem_inactive_shrink;
 +      dev_priv->mm.inactive_shrinker.seeks = DEFAULT_SEEKS;
 +      register_shrinker(&dev_priv->mm.inactive_shrinker);
  }
  
  /*
@@@ -4906,35 -4794,33 +4920,35 @@@ void i915_gem_free_all_phys_object(stru
  void i915_gem_detach_phys_object(struct drm_device *dev,
                                 struct drm_gem_object *obj)
  {
 -      struct drm_i915_gem_object *obj_priv;
 +      struct address_space *mapping = obj->filp->f_path.dentry->d_inode->i_mapping;
 +      struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 +      char *vaddr;
        int i;
 -      int ret;
        int page_count;
  
 -      obj_priv = to_intel_bo(obj);
        if (!obj_priv->phys_obj)
                return;
 -
 -      ret = i915_gem_object_get_pages(obj, 0);
 -      if (ret)
 -              goto out;
 +      vaddr = obj_priv->phys_obj->handle->vaddr;
  
        page_count = obj->size / PAGE_SIZE;
  
        for (i = 0; i < page_count; i++) {
 -              char *dst = kmap_atomic(obj_priv->pages[i]);
 -              char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
 -
 -              memcpy(dst, src, PAGE_SIZE);
 -              kunmap_atomic(dst);
 +              struct page *page = read_cache_page_gfp(mapping, i,
 +                                                      GFP_HIGHUSER | __GFP_RECLAIMABLE);
 +              if (!IS_ERR(page)) {
 +                      char *dst = kmap_atomic(page);
 +                      memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE);
 +                      kunmap_atomic(dst);
 +
 +                      drm_clflush_pages(&page, 1);
 +
 +                      set_page_dirty(page);
 +                      mark_page_accessed(page);
 +                      page_cache_release(page);
 +              }
        }
 -      drm_clflush_pages(obj_priv->pages, page_count);
        drm_agp_chipset_flush(dev);
  
 -      i915_gem_object_put_pages(obj);
 -out:
        obj_priv->phys_obj->cur_obj = NULL;
        obj_priv->phys_obj = NULL;
  }
@@@ -4945,7 -4831,6 +4959,7 @@@ i915_gem_attach_phys_object(struct drm_
                            int id,
                            int align)
  {
 +      struct address_space *mapping = obj->filp->f_path.dentry->d_inode->i_mapping;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj_priv;
        int ret = 0;
                                                obj->size, align);
                if (ret) {
                        DRM_ERROR("failed to init phys object %d size: %zu\n", id, obj->size);
 -                      goto out;
 +                      return ret;
                }
        }
  
        obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1];
        obj_priv->phys_obj->cur_obj = obj;
  
 -      ret = i915_gem_object_get_pages(obj, 0);
 -      if (ret) {
 -              DRM_ERROR("failed to get page list\n");
 -              goto out;
 -      }
 -
        page_count = obj->size / PAGE_SIZE;
  
        for (i = 0; i < page_count; i++) {
 -              char *src = kmap_atomic(obj_priv->pages[i]);
 -              char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
 +              struct page *page;
 +              char *dst, *src;
  
 +              page = read_cache_page_gfp(mapping, i,
 +                                         GFP_HIGHUSER | __GFP_RECLAIMABLE);
 +              if (IS_ERR(page))
 +                      return PTR_ERR(page);
 +
 +              src = kmap_atomic(page);
 +              dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
                memcpy(dst, src, PAGE_SIZE);
                kunmap_atomic(src);
 -      }
  
 -      i915_gem_object_put_pages(obj);
 +              mark_page_accessed(page);
 +              page_cache_release(page);
 +      }
  
        return 0;
 -out:
 -      return ret;
  }
  
  static int
@@@ -5006,17 -4891,24 +5020,24 @@@ i915_gem_phys_pwrite(struct drm_device 
                     struct drm_file *file_priv)
  {
        struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
-       void *obj_addr;
-       int ret;
-       char __user *user_data;
+       void *vaddr = obj_priv->phys_obj->handle->vaddr + args->offset;
+       char __user *user_data = (char __user *) (uintptr_t) args->data_ptr;
  
-       user_data = (char __user *) (uintptr_t) args->data_ptr;
-       obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
+       DRM_DEBUG_DRIVER("vaddr %p, %lld\n", vaddr, args->size);
  
-       DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size);
-       ret = copy_from_user(obj_addr, user_data, args->size);
-       if (ret)
-               return -EFAULT;
+       if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
+               unsigned long unwritten;
+               /* The physical object once assigned is fixed for the lifetime
+                * of the obj, so we can safely drop the lock and continue
+                * to access vaddr.
+                */
+               mutex_unlock(&dev->struct_mutex);
+               unwritten = copy_from_user(vaddr, user_data, args->size);
+               mutex_lock(&dev->struct_mutex);
+               if (unwritten)
+                       return -EFAULT;
+       }
  
        drm_agp_chipset_flush(dev);
        return 0;
@@@ -5056,68 -4948,144 +5077,68 @@@ i915_gpu_is_active(struct drm_device *d
  }
  
  static int
 -i915_gem_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
 +i915_gem_inactive_shrink(struct shrinker *shrinker,
 +                       int nr_to_scan,
 +                       gfp_t gfp_mask)
  {
 -      drm_i915_private_t *dev_priv, *next_dev;
 -      struct drm_i915_gem_object *obj_priv, *next_obj;
 -      int cnt = 0;
 -      int would_deadlock = 1;
 +      struct drm_i915_private *dev_priv =
 +              container_of(shrinker,
 +                           struct drm_i915_private,
 +                           mm.inactive_shrinker);
 +      struct drm_device *dev = dev_priv->dev;
 +      struct drm_i915_gem_object *obj, *next;
 +      int cnt;
 +
 +      if (!mutex_trylock(&dev->struct_mutex))
 +              return 0;
  
        /* "fast-path" to count number of available objects */
        if (nr_to_scan == 0) {
 -              spin_lock(&shrink_list_lock);
 -              list_for_each_entry(dev_priv, &shrink_list, mm.shrink_list) {
 -                      struct drm_device *dev = dev_priv->dev;
 -
 -                      if (mutex_trylock(&dev->struct_mutex)) {
 -                              list_for_each_entry(obj_priv,
 -                                                  &dev_priv->mm.inactive_list,
 -                                                  mm_list)
 -                                      cnt++;
 -                              mutex_unlock(&dev->struct_mutex);
 -                      }
 -              }
 -              spin_unlock(&shrink_list_lock);
 -
 -              return (cnt / 100) * sysctl_vfs_cache_pressure;
 +              cnt = 0;
 +              list_for_each_entry(obj,
 +                                  &dev_priv->mm.inactive_list,
 +                                  mm_list)
 +                      cnt++;
 +              mutex_unlock(&dev->struct_mutex);
 +              return cnt / 100 * sysctl_vfs_cache_pressure;
        }
  
 -      spin_lock(&shrink_list_lock);
 -
  rescan:
        /* first scan for clean buffers */
 -      list_for_each_entry_safe(dev_priv, next_dev,
 -                               &shrink_list, mm.shrink_list) {
 -              struct drm_device *dev = dev_priv->dev;
 -
 -              if (! mutex_trylock(&dev->struct_mutex))
 -                      continue;
 -
 -              spin_unlock(&shrink_list_lock);
 -              i915_gem_retire_requests(dev);
 +      i915_gem_retire_requests(dev);
  
 -              list_for_each_entry_safe(obj_priv, next_obj,
 -                                       &dev_priv->mm.inactive_list,
 -                                       mm_list) {
 -                      if (i915_gem_object_is_purgeable(obj_priv)) {
 -                              i915_gem_object_unbind(&obj_priv->base);
 -                              if (--nr_to_scan <= 0)
 -                                      break;
 -                      }
 +      list_for_each_entry_safe(obj, next,
 +                               &dev_priv->mm.inactive_list,
 +                               mm_list) {
 +              if (i915_gem_object_is_purgeable(obj)) {
 +                      i915_gem_object_unbind(&obj->base);
 +                      if (--nr_to_scan == 0)
 +                              break;
                }
 -
 -              spin_lock(&shrink_list_lock);
 -              mutex_unlock(&dev->struct_mutex);
 -
 -              would_deadlock = 0;
 -
 -              if (nr_to_scan <= 0)
 -                      break;
        }
  
        /* second pass, evict/count anything still on the inactive list */
 -      list_for_each_entry_safe(dev_priv, next_dev,
 -                               &shrink_list, mm.shrink_list) {
 -              struct drm_device *dev = dev_priv->dev;
 -
 -              if (! mutex_trylock(&dev->struct_mutex))
 -                      continue;
 -
 -              spin_unlock(&shrink_list_lock);
 -
 -              list_for_each_entry_safe(obj_priv, next_obj,
 -                                       &dev_priv->mm.inactive_list,
 -                                       mm_list) {
 -                      if (nr_to_scan > 0) {
 -                              i915_gem_object_unbind(&obj_priv->base);
 -                              nr_to_scan--;
 -                      } else
 -                              cnt++;
 -              }
 -
 -              spin_lock(&shrink_list_lock);
 -              mutex_unlock(&dev->struct_mutex);
 -
 -              would_deadlock = 0;
 -      }
 -
 -      if (nr_to_scan) {
 -              int active = 0;
 -
 +      cnt = 0;
 +      list_for_each_entry_safe(obj, next,
 +                               &dev_priv->mm.inactive_list,
 +                               mm_list) {
 +              if (nr_to_scan) {
 +                      i915_gem_object_unbind(&obj->base);
 +                      nr_to_scan--;
 +              } else
 +                      cnt++;
 +      }
 +
 +      if (nr_to_scan && i915_gpu_is_active(dev)) {
                /*
                 * We are desperate for pages, so as a last resort, wait
                 * for the GPU to finish and discard whatever we can.
                 * This has a dramatic impact to reduce the number of
                 * OOM-killer events whilst running the GPU aggressively.
                 */
 -              list_for_each_entry(dev_priv, &shrink_list, mm.shrink_list) {
 -                      struct drm_device *dev = dev_priv->dev;
 -
 -                      if (!mutex_trylock(&dev->struct_mutex))
 -                              continue;
 -
 -                      spin_unlock(&shrink_list_lock);
 -
 -                      if (i915_gpu_is_active(dev)) {
 -                              i915_gpu_idle(dev);
 -                              active++;
 -                      }
 -
 -                      spin_lock(&shrink_list_lock);
 -                      mutex_unlock(&dev->struct_mutex);
 -              }
 -
 -              if (active)
 +              if (i915_gpu_idle(dev) == 0)
                        goto rescan;
        }
 -
 -      spin_unlock(&shrink_list_lock);
 -
 -      if (would_deadlock)
 -              return -1;
 -      else if (cnt > 0)
 -              return (cnt / 100) * sysctl_vfs_cache_pressure;
 -      else
 -              return 0;
 -}
 -
 -static struct shrinker shrinker = {
 -      .shrink = i915_gem_shrink,
 -      .seeks = DEFAULT_SEEKS,
 -};
 -
 -__init void
 -i915_gem_shrinker_init(void)
 -{
 -    register_shrinker(&shrinker);
 -}
 -
 -__exit void
 -i915_gem_shrinker_exit(void)
 -{
 -    unregister_shrinker(&shrinker);
 +      mutex_unlock(&dev->struct_mutex);
 +      return cnt / 100 * sysctl_vfs_cache_pressure;
  }
index 6a7f11ff66f5f5c0c0187a279430bb0ea5129bf7,bee24b1a58e86b5dc1d1c038f8f1a653848bec97..3fa5aaa941d2dd9b54c4441d5180885672b5f6c2
@@@ -1461,7 -1461,7 +1461,7 @@@ intel_pin_and_fence_fb_obj(struct drm_d
                BUG();
        }
  
 -      ret = i915_gem_object_pin(obj, alignment);
 +      ret = i915_gem_object_pin(obj, alignment, true);
        if (ret)
                return ret;
  
         * framebuffer compression.  For simplicity, we always install
         * a fence as the cost is not that onerous.
         */
 -      if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
 -          obj_priv->tiling_mode != I915_TILING_NONE) {
 +      if (obj_priv->tiling_mode != I915_TILING_NONE) {
                ret = i915_gem_object_get_fence_reg(obj, false);
                if (ret)
                        goto err_unpin;
@@@ -1610,6 -1611,18 +1610,18 @@@ intel_pipe_set_base(struct drm_crtc *cr
  
                wait_event(dev_priv->pending_flip_queue,
                           atomic_read(&obj_priv->pending_flip) == 0);
+               /* Big Hammer, we also need to ensure that any pending
+                * MI_WAIT_FOR_EVENT inside a user batch buffer on the
+                * current scanout is retired before unpinning the old
+                * framebuffer.
+                */
+               ret = i915_gem_object_flush_gpu(obj_priv, false);
+               if (ret) {
+                       i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
+                       mutex_unlock(&dev->struct_mutex);
+                       return ret;
+               }
        }
  
        ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
@@@ -1983,17 -1996,17 +1995,17 @@@ static void intel_flush_display_plane(s
  static void intel_clear_scanline_wait(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_ring_buffer *ring;
        u32 tmp;
  
        if (IS_GEN2(dev))
                /* Can't break the hang on i8xx */
                return;
  
 -      tmp = I915_READ(PRB0_CTL);
 -      if (tmp & RING_WAIT) {
 -              I915_WRITE(PRB0_CTL, tmp);
 -              POSTING_READ(PRB0_CTL);
 -      }
 +      ring = &dev_priv->render_ring;
 +      tmp = I915_READ_CTL(ring);
 +      if (tmp & RING_WAIT)
 +              I915_WRITE_CTL(ring, tmp);
  }
  
  static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
@@@ -4365,7 -4378,7 +4377,7 @@@ static int intel_crtc_cursor_set(struc
        /* we only need to pin inside GTT if cursor is non-phy */
        mutex_lock(&dev->struct_mutex);
        if (!dev_priv->info->cursor_needs_physical) {
 -              ret = i915_gem_object_pin(bo, PAGE_SIZE);
 +              ret = i915_gem_object_pin(bo, PAGE_SIZE, true);
                if (ret) {
                        DRM_ERROR("failed to pin cursor bo\n");
                        goto fail_locked;
@@@ -5102,16 -5115,22 +5114,16 @@@ static int intel_crtc_page_flip(struct 
        if (ret)
                goto cleanup_objs;
  
 -      /* Block clients from rendering to the new back buffer until
 -       * the flip occurs and the object is no longer visible.
 -       */
 -      atomic_add(1 << intel_crtc->plane,
 -                 &to_intel_bo(work->old_fb_obj)->pending_flip);
 -
 -      work->pending_flip_obj = obj;
 -      obj_priv = to_intel_bo(obj);
 -
        if (IS_GEN3(dev) || IS_GEN2(dev)) {
                u32 flip_mask;
  
                /* Can't queue multiple flips, so wait for the previous
                 * one to finish before executing the next.
                 */
 -              BEGIN_LP_RING(2);
 +              ret = BEGIN_LP_RING(2);
 +              if (ret)
 +                      goto cleanup_objs;
 +
                if (intel_crtc->plane)
                        flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
                else
                ADVANCE_LP_RING();
        }
  
 +      work->pending_flip_obj = obj;
 +      obj_priv = to_intel_bo(obj);
 +
        work->enable_stall_check = true;
  
        /* Offset into the new buffer for cases of shared fbs between CRTCs */
        offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
  
 -      BEGIN_LP_RING(4);
 -      switch(INTEL_INFO(dev)->gen) {
 +      ret = BEGIN_LP_RING(4);
 +      if (ret)
 +              goto cleanup_objs;
 +
 +      /* Block clients from rendering to the new back buffer until
 +       * the flip occurs and the object is no longer visible.
 +       */
 +      atomic_add(1 << intel_crtc->plane,
 +                 &to_intel_bo(work->old_fb_obj)->pending_flip);
 +
 +      switch (INTEL_INFO(dev)->gen) {
        case 2:
                OUT_RING(MI_DISPLAY_FLIP |
                         MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
@@@ -5529,7 -5536,7 +5541,7 @@@ intel_alloc_context_page(struct drm_dev
        }
  
        mutex_lock(&dev->struct_mutex);
 -      ret = i915_gem_object_pin(ctx, 4096);
 +      ret = i915_gem_object_pin(ctx, 4096, true);
        if (ret) {
                DRM_ERROR("failed to pin power context: %d\n", ret);
                goto err_unref;
@@@ -5817,16 -5824,6 +5829,16 @@@ void intel_init_clock_gating(struct drm
                                   ILK_DPFC_DIS2 |
                                   ILK_CLK_FBC);
                }
 +
 +              I915_WRITE(ILK_DISPLAY_CHICKEN2,
 +                         I915_READ(ILK_DISPLAY_CHICKEN2) |
 +                         ILK_ELPIN_409_SELECT);
 +
 +              if (IS_GEN5(dev)) {
 +                      I915_WRITE(_3D_CHICKEN2,
 +                                 _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
 +                                 _3D_CHICKEN2_WM_READ_PIPELINED);
 +              }
                return;
        } else if (IS_G4X(dev)) {
                uint32_t dspclk_gate;
                        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();
 +                              if (BEGIN_LP_RING(4) == 0) {
 +                                      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."
index d2d493a24e6525897c2be5999f4d209baa772749,3dba086e7eea012947c410738e208a9ef39bfa9e..58040f68ed7a7daa4496036a6570a6c095f09bb2
@@@ -85,9 -85,8 +85,9 @@@ static u32 get_reserved(struct intel_gp
  
        /* On most chips, these bits must be preserved in software. */
        if (!IS_I830(dev) && !IS_845G(dev))
 -              reserved = I915_READ(gpio->reg) & (GPIO_DATA_PULLUP_DISABLE |
 -                                                 GPIO_CLOCK_PULLUP_DISABLE);
 +              reserved = I915_READ_NOTRACE(gpio->reg) &
 +                                           (GPIO_DATA_PULLUP_DISABLE |
 +                                            GPIO_CLOCK_PULLUP_DISABLE);
  
        return reserved;
  }
@@@ -97,9 -96,9 +97,9 @@@ static int get_clock(void *data
        struct intel_gpio *gpio = data;
        struct drm_i915_private *dev_priv = gpio->dev_priv;
        u32 reserved = get_reserved(gpio);
 -      I915_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK);
 -      I915_WRITE(gpio->reg, reserved);
 -      return (I915_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0;
 +      I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK);
 +      I915_WRITE_NOTRACE(gpio->reg, reserved);
 +      return (I915_READ_NOTRACE(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0;
  }
  
  static int get_data(void *data)
        struct intel_gpio *gpio = data;
        struct drm_i915_private *dev_priv = gpio->dev_priv;
        u32 reserved = get_reserved(gpio);
 -      I915_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK);
 -      I915_WRITE(gpio->reg, reserved);
 -      return (I915_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
 +      I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_DATA_DIR_MASK);
 +      I915_WRITE_NOTRACE(gpio->reg, reserved);
 +      return (I915_READ_NOTRACE(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
  }
  
  static void set_clock(void *data, int state_high)
                clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
                        GPIO_CLOCK_VAL_MASK;
  
 -      I915_WRITE(gpio->reg, reserved | clock_bits);
 +      I915_WRITE_NOTRACE(gpio->reg, reserved | clock_bits);
        POSTING_READ(gpio->reg);
  }
  
@@@ -142,7 -141,7 +142,7 @@@ static void set_data(void *data, int st
                data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
                        GPIO_DATA_VAL_MASK;
  
 -      I915_WRITE(gpio->reg, reserved | data_bits);
 +      I915_WRITE_NOTRACE(gpio->reg, reserved | data_bits);
        POSTING_READ(gpio->reg);
  }
  
@@@ -161,7 -160,7 +161,7 @@@ intel_gpio_create(struct drm_i915_priva
        };
        struct intel_gpio *gpio;
  
-       if (pin < 1 || pin > 7)
+       if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin])
                return NULL;
  
        gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL);
                gpio->reg += PCH_GPIOA - GPIOA;
        gpio->dev_priv = dev_priv;
  
-       snprintf(gpio->adapter.name, I2C_NAME_SIZE, "GPIO%c", "?BACDEF?"[pin]);
+       snprintf(gpio->adapter.name, sizeof(gpio->adapter.name),
+                "i915 GPIO%c", "?BACDE?F"[pin]);
        gpio->adapter.owner = THIS_MODULE;
        gpio->adapter.algo_data = &gpio->algo;
        gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev;
@@@ -350,7 -350,7 +351,7 @@@ int intel_setup_gmbus(struct drm_devic
                "panel",
                "dpc",
                "dpb",
-               "reserved"
+               "reserved",
                "dpd",
        };
        struct drm_i915_private *dev_priv = dev->dev_private;
                bus->adapter.owner = THIS_MODULE;
                bus->adapter.class = I2C_CLASS_DDC;
                snprintf(bus->adapter.name,
-                        I2C_NAME_SIZE,
-                        "gmbus %s",
+                        sizeof(bus->adapter.name),
+                        "i915 gmbus %s",
                         names[i]);
  
                bus->adapter.dev.parent = &dev->pdev->dev;