Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 18 Mar 2014 08:43:56 +0000 (09:43 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 18 Mar 2014 08:43:56 +0000 (09:43 +0100)
Conflicts:
drivers/gpu/drm/i915/Makefile

Makefile cleanup in drm-intel-next conflicts with a build-fix to move
intel_opregion under CONFIG_ACPI.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
1  2 
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h

@@@ -3,70 -3,58 +3,69 @@@
  # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
  
  ccflags-y := -Iinclude/drm
 -i915-y := i915_drv.o i915_dma.o i915_irq.o \
 -        i915_gpu_error.o \
 +
 +# Please keep these build lists sorted!
 +
 +# core driver code
 +i915-y := i915_drv.o \
 +        i915_params.o \
            i915_suspend.o \
 -        i915_gem.o \
 +        i915_sysfs.o \
 +        intel_pm.o
 +i915-$(CONFIG_COMPAT)   += i915_ioc32.o
 +i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o
 +
 +# GEM code
 +i915-y += i915_cmd_parser.o \
          i915_gem_context.o \
          i915_gem_debug.o \
 +        i915_gem_dmabuf.o \
          i915_gem_evict.o \
          i915_gem_execbuffer.o \
          i915_gem_gtt.o \
 +        i915_gem.o \
          i915_gem_stolen.o \
          i915_gem_tiling.o \
 -        i915_params.o \
 -        i915_sysfs.o \
 +        i915_gpu_error.o \
 +        i915_irq.o \
          i915_trace_points.o \
 -        i915_ums.o \
 +        intel_ringbuffer.o \
 +        intel_uncore.o
 +
 +# modesetting core code
 +i915-y += intel_bios.o \
          intel_display.o \
 -        intel_crt.o \
 -        intel_lvds.o \
 -        intel_dsi.o \
 -        intel_dsi_cmd.o \
 -        intel_dsi_pll.o \
 -        intel_bios.o \
 -        intel_ddi.o \
 -        intel_dp.o \
 -        intel_hdmi.o \
 -        intel_sdvo.o \
          intel_modes.o \
-         intel_opregion.o \
 -        intel_panel.o \
 -        intel_pm.o \
 -        intel_i2c.o \
 -        intel_tv.o \
 -        intel_dvo.o \
 -        intel_ringbuffer.o \
          intel_overlay.o \
 -        intel_sprite.o \
          intel_sideband.o \
 -        intel_uncore.o \
 +        intel_sprite.o
- i915-$(CONFIG_ACPI)           += intel_acpi.o
++i915-$(CONFIG_ACPI)           += intel_acpi.o intel_opregion.o
 +i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o
 +
 +# modesetting output/encoder code
 +i915-y += dvo_ch7017.o \
          dvo_ch7xxx.o \
 -        dvo_ch7017.o \
          dvo_ivch.o \
 -        dvo_tfp410.o \
 -        dvo_sil164.o \
          dvo_ns2501.o \
 -        i915_gem_dmabuf.o
 -
 -i915-$(CONFIG_COMPAT)   += i915_ioc32.o
 -
 -i915-$(CONFIG_ACPI)   += intel_acpi.o intel_opregion.o
 -
 -i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o
 +        dvo_sil164.o \
 +        dvo_tfp410.o \
 +        intel_crt.o \
 +        intel_ddi.o \
 +        intel_dp.o \
 +        intel_dsi_cmd.o \
 +        intel_dsi.o \
 +        intel_dsi_pll.o \
 +        intel_dvo.o \
 +        intel_hdmi.o \
 +        intel_i2c.o \
 +        intel_lvds.o \
 +        intel_panel.o \
 +        intel_sdvo.o \
 +        intel_tv.o
  
 -i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o
 +# legacy horrors
 +i915-y += i915_dma.o \
 +        i915_ums.o
  
  obj-$(CONFIG_DRM_I915)  += i915.o
  
@@@ -79,7 -79,7 +79,7 @@@ enum plane 
  };
  #define plane_name(p) ((p) + 'A')
  
 -#define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites + (s) + 'A')
 +#define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites[(p)] + (s) + 'A')
  
  enum port {
        PORT_A = 0,
@@@ -114,17 -114,6 +114,17 @@@ enum intel_display_power_domain 
        POWER_DOMAIN_TRANSCODER_B,
        POWER_DOMAIN_TRANSCODER_C,
        POWER_DOMAIN_TRANSCODER_EDP,
 +      POWER_DOMAIN_PORT_DDI_A_2_LANES,
 +      POWER_DOMAIN_PORT_DDI_A_4_LANES,
 +      POWER_DOMAIN_PORT_DDI_B_2_LANES,
 +      POWER_DOMAIN_PORT_DDI_B_4_LANES,
 +      POWER_DOMAIN_PORT_DDI_C_2_LANES,
 +      POWER_DOMAIN_PORT_DDI_C_4_LANES,
 +      POWER_DOMAIN_PORT_DDI_D_2_LANES,
 +      POWER_DOMAIN_PORT_DDI_D_4_LANES,
 +      POWER_DOMAIN_PORT_DSI,
 +      POWER_DOMAIN_PORT_CRT,
 +      POWER_DOMAIN_PORT_OTHER,
        POWER_DOMAIN_VGA,
        POWER_DOMAIN_AUDIO,
        POWER_DOMAIN_INIT,
        POWER_DOMAIN_NUM,
  };
  
 -#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
 -
  #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
  #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
                ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
        ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \
         (tran) + POWER_DOMAIN_TRANSCODER_A)
  
 -#define HSW_ALWAYS_ON_POWER_DOMAINS (         \
 -      BIT(POWER_DOMAIN_PIPE_A) |              \
 -      BIT(POWER_DOMAIN_TRANSCODER_EDP))
 -#define BDW_ALWAYS_ON_POWER_DOMAINS (         \
 -      BIT(POWER_DOMAIN_PIPE_A) |              \
 -      BIT(POWER_DOMAIN_TRANSCODER_EDP) |      \
 -      BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
 -
  enum hpd_pin {
        HPD_NONE = 0,
        HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
         I915_GEM_DOMAIN_VERTEX)
  
  #define for_each_pipe(p) for ((p) = 0; (p) < INTEL_INFO(dev)->num_pipes; (p)++)
 +#define for_each_sprite(p, s) for ((s) = 0; (s) < INTEL_INFO(dev)->num_sprites[(p)]; (s)++)
  
  #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
        list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
@@@ -305,10 -303,6 +305,10 @@@ struct drm_i915_error_state 
        struct kref ref;
        struct timeval time;
  
 +      char error_msg[128];
 +      u32 reset_count;
 +      u32 suspend_count;
 +
        /* Generic register state */
        u32 eir;
        u32 pgtbl_er;
                        int page_count;
                        u32 gtt_offset;
                        u32 *pages[0];
 -              } *ringbuffer, *batchbuffer, *ctx, *hws_page;
 +              } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
  
                struct drm_i915_error_request {
                        long jiffies;
                                u32 pp_dir_base;
                        };
                } vm_info;
 +
 +              pid_t pid;
 +              char comm[TASK_COMM_LEN];
        } ring[I915_NUM_RINGS];
        struct drm_i915_error_buffer {
                u32 size;
@@@ -508,7 -499,7 +508,7 @@@ struct intel_uncore 
        unsigned fw_rendercount;
        unsigned fw_mediacount;
  
 -      struct delayed_work force_wake_work;
 +      struct timer_list force_wake_timer;
  };
  
  #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
  struct intel_device_info {
        u32 display_mmio_offset;
        u8 num_pipes:3;
 -      u8 num_sprites:2;
 +      u8 num_sprites[I915_MAX_PIPES];
        u8 gen;
        u8 ring_mask; /* Rings supported by the HW */
        DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON);
@@@ -661,12 -652,12 +661,12 @@@ struct i915_address_space 
                                     enum i915_cache_level level,
                                     bool valid); /* Create a valid PTE */
        void (*clear_range)(struct i915_address_space *vm,
 -                          unsigned int first_entry,
 -                          unsigned int num_entries,
 +                          uint64_t start,
 +                          uint64_t length,
                            bool use_scratch);
        void (*insert_entries)(struct i915_address_space *vm,
                               struct sg_table *st,
 -                             unsigned int first_entry,
 +                             uint64_t start,
                               enum i915_cache_level cache_level);
        void (*cleanup)(struct i915_address_space *vm);
  };
@@@ -700,21 -691,21 +700,21 @@@ struct i915_gtt 
  };
  #define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT)
  
 +#define GEN8_LEGACY_PDPS 4
  struct i915_hw_ppgtt {
        struct i915_address_space base;
        struct kref ref;
        struct drm_mm_node node;
        unsigned num_pd_entries;
 +      unsigned num_pd_pages; /* gen8+ */
        union {
                struct page **pt_pages;
 -              struct page *gen8_pt_pages;
 +              struct page **gen8_pt_pages[GEN8_LEGACY_PDPS];
        };
        struct page *pd_pages;
 -      int num_pd_pages;
 -      int num_pt_pages;
        union {
                uint32_t pd_offset;
 -              dma_addr_t pd_dma_addr[4];
 +              dma_addr_t pd_dma_addr[GEN8_LEGACY_PDPS];
        };
        union {
                dma_addr_t *pt_dma_addr;
@@@ -1025,36 -1016,6 +1025,36 @@@ struct intel_ilk_power_mgmt 
        struct drm_i915_gem_object *renderctx;
  };
  
 +struct drm_i915_private;
 +struct i915_power_well;
 +
 +struct i915_power_well_ops {
 +      /*
 +       * Synchronize the well's hw state to match the current sw state, for
 +       * example enable/disable it based on the current refcount. Called
 +       * during driver init and resume time, possibly after first calling
 +       * the enable/disable handlers.
 +       */
 +      void (*sync_hw)(struct drm_i915_private *dev_priv,
 +                      struct i915_power_well *power_well);
 +      /*
 +       * Enable the well and resources that depend on it (for example
 +       * interrupts located on the well). Called after the 0->1 refcount
 +       * transition.
 +       */
 +      void (*enable)(struct drm_i915_private *dev_priv,
 +                     struct i915_power_well *power_well);
 +      /*
 +       * Disable the well and resources that depend on it. Called after
 +       * the 1->0 refcount transition.
 +       */
 +      void (*disable)(struct drm_i915_private *dev_priv,
 +                      struct i915_power_well *power_well);
 +      /* Returns the hw enabled state. */
 +      bool (*is_enabled)(struct drm_i915_private *dev_priv,
 +                         struct i915_power_well *power_well);
 +};
 +
  /* Power well structure for haswell */
  struct i915_power_well {
        const char *name;
        /* power well enable/disable usage count */
        int count;
        unsigned long domains;
 -      void *data;
 -      void (*set)(struct drm_device *dev, struct i915_power_well *power_well,
 -                  bool enable);
 -      bool (*is_enabled)(struct drm_device *dev,
 -                         struct i915_power_well *power_well);
 +      unsigned long data;
 +      const struct i915_power_well_ops *ops;
  };
  
  struct i915_power_domains {
@@@ -1160,14 -1124,6 +1160,14 @@@ struct i915_gem_mm 
         */
        bool interruptible;
  
 +      /**
 +       * Is the GPU currently considered idle, or busy executing userspace
 +       * requests?  Whilst idle, we attempt to power down the hardware and
 +       * display clocks. In order to reduce the effect on performance, there
 +       * is a slight delay before we do so.
 +       */
 +      bool busy;
 +
        /** Bit 6 swizzling required for X tiling */
        uint32_t bit_6_swizzle_x;
        /** Bit 6 swizzling required for Y tiling */
@@@ -1357,10 -1313,11 +1357,10 @@@ struct ilk_wm_values 
   * Ideally every piece of our code that needs PC8+ disabled would call
   * hsw_disable_package_c8, which would increment disable_count and prevent the
   * system from reaching PC8+. But we don't have a symmetric way to do this for
 - * everything, so we have the requirements_met and gpu_idle variables. When we
 - * switch requirements_met or gpu_idle to true we decrease disable_count, and
 - * increase it in the opposite case. The requirements_met variable is true when
 - * all the CRTCs, encoders and the power well are disabled. The gpu_idle
 - * variable is true when the GPU is idle.
 + * everything, so we have the requirements_met variable. When we switch
 + * requirements_met to true we decrease disable_count, and increase it in the
 + * opposite case. The requirements_met variable is true when all the CRTCs,
 + * encoders and the power well are disabled.
   *
   * In addition to everything, we only actually enable PC8+ if disable_count
   * stays at zero for at least some seconds. This is implemented with the
   */
  struct i915_package_c8 {
        bool requirements_met;
 -      bool gpu_idle;
        bool irqs_disabled;
        /* Only true after the delayed work task actually enables it. */
        bool enabled;
@@@ -1469,8 -1427,6 +1469,8 @@@ typedef struct drm_i915_private 
        /* protects the irq masks */
        spinlock_t irq_lock;
  
 +      bool display_irqs_enabled;
 +
        /* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
        struct pm_qos_request pm_qos;
  
        struct i915_dri1_state dri1;
        /* Old ums support infrastructure, same warning applies. */
        struct i915_ums_state ums;
 +
 +      u32 suspend_count;
  } drm_i915_private_t;
  
  static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
@@@ -1791,6 -1745,7 +1791,6 @@@ struct drm_i915_gem_object 
        /** for phy allocated objects */
        struct drm_i915_gem_phys_object *phys_obj;
  };
 -#define to_gem_object(obj) (&((struct drm_i915_gem_object *)(obj))->base)
  
  #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
  
@@@ -1836,7 -1791,6 +1836,7 @@@ struct drm_i915_gem_request 
  
  struct drm_i915_file_private {
        struct drm_i915_private *dev_priv;
 +      struct drm_file *file;
  
        struct {
                spinlock_t lock;
        atomic_t rps_wait_boost;
  };
  
 +/*
 + * A command that requires special handling by the command parser.
 + */
 +struct drm_i915_cmd_descriptor {
 +      /*
 +       * Flags describing how the command parser processes the command.
 +       *
 +       * CMD_DESC_FIXED: The command has a fixed length if this is set,
 +       *                 a length mask if not set
 +       * CMD_DESC_SKIP: The command is allowed but does not follow the
 +       *                standard length encoding for the opcode range in
 +       *                which it falls
 +       * CMD_DESC_REJECT: The command is never allowed
 +       * CMD_DESC_REGISTER: The command should be checked against the
 +       *                    register whitelist for the appropriate ring
 +       * CMD_DESC_MASTER: The command is allowed if the submitting process
 +       *                  is the DRM master
 +       */
 +      u32 flags;
 +#define CMD_DESC_FIXED    (1<<0)
 +#define CMD_DESC_SKIP     (1<<1)
 +#define CMD_DESC_REJECT   (1<<2)
 +#define CMD_DESC_REGISTER (1<<3)
 +#define CMD_DESC_BITMASK  (1<<4)
 +#define CMD_DESC_MASTER   (1<<5)
 +
 +      /*
 +       * The command's unique identification bits and the bitmask to get them.
 +       * This isn't strictly the opcode field as defined in the spec and may
 +       * also include type, subtype, and/or subop fields.
 +       */
 +      struct {
 +              u32 value;
 +              u32 mask;
 +      } cmd;
 +
 +      /*
 +       * The command's length. The command is either fixed length (i.e. does
 +       * not include a length field) or has a length field mask. The flag
 +       * CMD_DESC_FIXED indicates a fixed length. Otherwise, the command has
 +       * a length mask. All command entries in a command table must include
 +       * length information.
 +       */
 +      union {
 +              u32 fixed;
 +              u32 mask;
 +      } length;
 +
 +      /*
 +       * Describes where to find a register address in the command to check
 +       * against the ring's register whitelist. Only valid if flags has the
 +       * CMD_DESC_REGISTER bit set.
 +       */
 +      struct {
 +              u32 offset;
 +              u32 mask;
 +      } reg;
 +
 +#define MAX_CMD_DESC_BITMASKS 3
 +      /*
 +       * Describes command checks where a particular dword is masked and
 +       * compared against an expected value. If the command does not match
 +       * the expected value, the parser rejects it. Only valid if flags has
 +       * the CMD_DESC_BITMASK bit set. Only entries where mask is non-zero
 +       * are valid.
 +       */
 +      struct {
 +              u32 offset;
 +              u32 mask;
 +              u32 expected;
 +      } bits[MAX_CMD_DESC_BITMASKS];
 +};
 +
 +/*
 + * A table of commands requiring special handling by the command parser.
 + *
 + * Each ring has an array of tables. Each table consists of an array of command
 + * descriptors, which must be sorted with command opcodes in ascending order.
 + */
 +struct drm_i915_cmd_table {
 +      const struct drm_i915_cmd_descriptor *table;
 +      int count;
 +};
 +
  #define INTEL_INFO(dev)       (&to_i915(dev)->info)
  
  #define IS_I830(dev)          ((dev)->pdev->device == 0x3577)
  
  /* Early gen2 have a totally busted CS tlb and require pinned batches. */
  #define HAS_BROKEN_CS_TLB(dev)                (IS_I830(dev) || IS_845G(dev))
+ /*
+  * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts
+  * even when in MSI mode. This results in spurious interrupt warnings if the
+  * legacy irq no. is shared with another device. The kernel then disables that
+  * interrupt source and so prevents the other device from working properly.
+  */
+ #define HAS_AUX_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
+ #define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
  
  /* 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.
@@@ -2087,7 -1965,6 +2095,7 @@@ struct i915_params 
        int enable_pc8;
        int pc8_timeout;
        int invert_brightness;
 +      int enable_cmd_parser;
        /* leave bools at the end to not create holes */
        bool enable_hangcheck;
        bool fastboot;
@@@ -2127,9 -2004,7 +2135,9 @@@ extern void intel_console_resume(struc
  
  /* i915_irq.c */
  void i915_queue_hangcheck(struct drm_device *dev);
 -void i915_handle_error(struct drm_device *dev, bool wedged);
 +__printf(3, 4)
 +void i915_handle_error(struct drm_device *dev, bool wedged,
 +                     const char *fmt, ...);
  
  void gen6_set_pm_mask(struct drm_i915_private *dev_priv, u32 pm_iir,
                                                        int new_delay);
@@@ -2150,9 -2025,6 +2158,9 @@@ voi
  i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
                      u32 status_mask);
  
 +void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
 +void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
 +
  /* i915_gem.c */
  int i915_gem_init_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
@@@ -2225,9 -2097,6 +2233,9 @@@ void i915_gem_release_all_mmaps(struct 
  void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
  void i915_gem_lastclose(struct drm_device *dev);
  
 +int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj,
 +                                  int *needs_clflush);
 +
  int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
  static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
  {
@@@ -2294,10 -2163,8 +2302,10 @@@ i915_gem_object_unpin_fence(struct drm_
        }
  }
  
 +struct drm_i915_gem_request *
 +i915_gem_find_active_request(struct intel_ring_buffer *ring);
 +
  bool i915_gem_retire_requests(struct drm_device *dev);
 -void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring);
  int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
                                      bool interruptible);
  static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
@@@ -2498,7 -2365,63 +2506,7 @@@ static inline void i915_gem_chipset_flu
                intel_gtt_chipset_flush();
  }
  int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt);
 -static inline bool intel_enable_ppgtt(struct drm_device *dev, bool full)
 -{
 -      if (i915.enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev))
 -              return false;
 -
 -      if (i915.enable_ppgtt == 1 && full)
 -              return false;
 -
 -#ifdef CONFIG_INTEL_IOMMU
 -      /* Disable ppgtt on SNB if VT-d is on. */
 -      if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) {
 -              DRM_INFO("Disabling PPGTT because VT-d is on\n");
 -              return false;
 -      }
 -#endif
 -
 -      if (full)
 -              return HAS_PPGTT(dev);
 -      else
 -              return HAS_ALIASING_PPGTT(dev);
 -}
 -
 -static inline void ppgtt_release(struct kref *kref)
 -{
 -      struct i915_hw_ppgtt *ppgtt = container_of(kref, struct i915_hw_ppgtt, ref);
 -      struct drm_device *dev = ppgtt->base.dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct i915_address_space *vm = &ppgtt->base;
 -
 -      if (ppgtt == dev_priv->mm.aliasing_ppgtt ||
 -          (list_empty(&vm->active_list) && list_empty(&vm->inactive_list))) {
 -              ppgtt->base.cleanup(&ppgtt->base);
 -              return;
 -      }
 -
 -      /*
 -       * Make sure vmas are unbound before we take down the drm_mm
 -       *
 -       * FIXME: Proper refcounting should take care of this, this shouldn't be
 -       * needed at all.
 -       */
 -      if (!list_empty(&vm->active_list)) {
 -              struct i915_vma *vma;
 -
 -              list_for_each_entry(vma, &vm->active_list, mm_list)
 -                      if (WARN_ON(list_empty(&vma->vma_link) ||
 -                                  list_is_singular(&vma->vma_link)))
 -                              break;
 -
 -              i915_gem_evict_vm(&ppgtt->base, true);
 -      } else {
 -              i915_gem_retire_requests(dev);
 -              i915_gem_evict_vm(&ppgtt->base, false);
 -      }
 -
 -      ppgtt->base.cleanup(&ppgtt->base);
 -}
 +bool intel_enable_ppgtt(struct drm_device *dev, bool full);
  
  /* i915_gem_stolen.c */
  int i915_gem_init_stolen(struct drm_device *dev);
@@@ -2555,8 -2478,7 +2563,8 @@@ static inline void i915_error_state_buf
  {
        kfree(eb->buf);
  }
 -void i915_capture_error_state(struct drm_device *dev);
 +void i915_capture_error_state(struct drm_device *dev, bool wedge,
 +                            const char *error_msg);
  void i915_error_state_get(struct drm_device *dev,
                          struct i915_error_state_file_priv *error_priv);
  void i915_error_state_put(struct i915_error_state_file_priv *error_priv);
@@@ -2565,14 -2487,6 +2573,14 @@@ void i915_destroy_error_state(struct dr
  void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone);
  const char *i915_cache_level_str(int type);
  
 +/* i915_cmd_parser.c */
 +void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring);
 +bool i915_needs_cmd_parser(struct intel_ring_buffer *ring);
 +int i915_parse_cmds(struct intel_ring_buffer *ring,
 +                  struct drm_i915_gem_object *batch_obj,
 +                  u32 batch_start_offset,
 +                  bool is_master);
 +
  /* i915_suspend.c */
  extern int i915_save_state(struct drm_device *dev);
  extern int i915_restore_state(struct drm_device *dev);
@@@ -2605,8 -2519,8 +2613,8 @@@ extern void intel_i2c_reset(struct drm_
  
  /* intel_opregion.c */
  struct intel_encoder;
- extern int intel_opregion_setup(struct drm_device *dev);
  #ifdef CONFIG_ACPI
+ extern int intel_opregion_setup(struct drm_device *dev);
  extern void intel_opregion_init(struct drm_device *dev);
  extern void intel_opregion_fini(struct drm_device *dev);
  extern void intel_opregion_asle_intr(struct drm_device *dev);
@@@ -2615,6 -2529,7 +2623,7 @@@ extern int intel_opregion_notify_encode
  extern int intel_opregion_notify_adapter(struct drm_device *dev,
                                         pci_power_t state);
  #else
+ static inline int intel_opregion_setup(struct drm_device *dev) { return 0; }
  static inline void intel_opregion_init(struct drm_device *dev) { return; }
  static inline void intel_opregion_fini(struct drm_device *dev) { return; }
  static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; }
@@@ -2650,7 -2565,6 +2659,7 @@@ extern int intel_modeset_vga_set_state(
  extern void intel_modeset_setup_hw_state(struct drm_device *dev,
                                         bool force_restore);
  extern void i915_redisable_vga(struct drm_device *dev);
 +extern void i915_redisable_vga_power_on(struct drm_device *dev);
  extern bool intel_fbc_enabled(struct drm_device *dev);
  extern void intel_disable_fbc(struct drm_device *dev);
  extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
@@@ -2685,7 -2599,6 +2694,7 @@@ extern void intel_display_print_error_s
   */
  void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine);
  void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine);
 +void assert_force_wake_inactive(struct drm_i915_private *dev_priv);
  
  int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
  int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
@@@ -1,6 -1,5 +1,6 @@@
  /*
   * Copyright Â© 2010 Daniel Vetter
 + * Copyright Â© 2011-2014 Intel Corporation
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
  #include "i915_trace.h"
  #include "intel_drv.h"
  
 +bool intel_enable_ppgtt(struct drm_device *dev, bool full)
 +{
 +      if (i915.enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev))
 +              return false;
 +
 +      if (i915.enable_ppgtt == 1 && full)
 +              return false;
 +
 +#ifdef CONFIG_INTEL_IOMMU
 +      /* Disable ppgtt on SNB if VT-d is on. */
 +      if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) {
 +              DRM_INFO("Disabling PPGTT because VT-d is on\n");
 +              return false;
 +      }
 +#endif
 +
 +      /* Full ppgtt disabled by default for now due to issues. */
 +      if (full)
 +              return false; /* HAS_PPGTT(dev) */
 +      else
 +              return HAS_ALIASING_PPGTT(dev);
 +}
 +
  #define GEN6_PPGTT_PD_ENTRIES 512
  #define I915_PPGTT_PT_ENTRIES (PAGE_SIZE / sizeof(gen6_gtt_pte_t))
  typedef uint64_t gen8_gtt_pte_t;
@@@ -88,19 -64,7 +88,19 @@@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t
  
  #define GEN8_PTES_PER_PAGE            (PAGE_SIZE / sizeof(gen8_gtt_pte_t))
  #define GEN8_PDES_PER_PAGE            (PAGE_SIZE / sizeof(gen8_ppgtt_pde_t))
 -#define GEN8_LEGACY_PDPS              4
 +
 +/* GEN8 legacy style addressis defined as a 3 level page table:
 + * 31:30 | 29:21 | 20:12 |  11:0
 + * PDPE  |  PDE  |  PTE  | offset
 + * The difference as compared to normal x86 3 level page table is the PDPEs are
 + * programmed via register.
 + */
 +#define GEN8_PDPE_SHIFT                       30
 +#define GEN8_PDPE_MASK                        0x3
 +#define GEN8_PDE_SHIFT                        21
 +#define GEN8_PDE_MASK                 0x1ff
 +#define GEN8_PTE_SHIFT                        12
 +#define GEN8_PTE_MASK                 0x1ff
  
  #define PPAT_UNCACHED_INDEX           (_PAGE_PWT | _PAGE_PCD)
  #define PPAT_CACHED_PDE_INDEX         0 /* WB LLC */
@@@ -290,113 -254,84 +290,113 @@@ static int gen8_mm_switch(struct i915_h
  }
  
  static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
 -                                 unsigned first_entry,
 -                                 unsigned num_entries,
 +                                 uint64_t start,
 +                                 uint64_t length,
                                   bool use_scratch)
  {
        struct i915_hw_ppgtt *ppgtt =
                container_of(vm, struct i915_hw_ppgtt, base);
        gen8_gtt_pte_t *pt_vaddr, scratch_pte;
 -      unsigned act_pt = first_entry / GEN8_PTES_PER_PAGE;
 -      unsigned first_pte = first_entry % GEN8_PTES_PER_PAGE;
 +      unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK;
 +      unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK;
 +      unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK;
 +      unsigned num_entries = length >> PAGE_SHIFT;
        unsigned last_pte, i;
  
        scratch_pte = gen8_pte_encode(ppgtt->base.scratch.addr,
                                      I915_CACHE_LLC, use_scratch);
  
        while (num_entries) {
 -              struct page *page_table = &ppgtt->gen8_pt_pages[act_pt];
 +              struct page *page_table = ppgtt->gen8_pt_pages[pdpe][pde];
  
 -              last_pte = first_pte + num_entries;
 +              last_pte = pte + num_entries;
                if (last_pte > GEN8_PTES_PER_PAGE)
                        last_pte = GEN8_PTES_PER_PAGE;
  
                pt_vaddr = kmap_atomic(page_table);
  
 -              for (i = first_pte; i < last_pte; i++)
 +              for (i = pte; i < last_pte; i++) {
                        pt_vaddr[i] = scratch_pte;
 +                      num_entries--;
 +              }
  
                kunmap_atomic(pt_vaddr);
  
 -              num_entries -= last_pte - first_pte;
 -              first_pte = 0;
 -              act_pt++;
 +              pte = 0;
 +              if (++pde == GEN8_PDES_PER_PAGE) {
 +                      pdpe++;
 +                      pde = 0;
 +              }
        }
  }
  
  static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
                                      struct sg_table *pages,
 -                                    unsigned first_entry,
 +                                    uint64_t start,
                                      enum i915_cache_level cache_level)
  {
        struct i915_hw_ppgtt *ppgtt =
                container_of(vm, struct i915_hw_ppgtt, base);
        gen8_gtt_pte_t *pt_vaddr;
 -      unsigned act_pt = first_entry / GEN8_PTES_PER_PAGE;
 -      unsigned act_pte = first_entry % GEN8_PTES_PER_PAGE;
 +      unsigned pdpe = start >> GEN8_PDPE_SHIFT & GEN8_PDPE_MASK;
 +      unsigned pde = start >> GEN8_PDE_SHIFT & GEN8_PDE_MASK;
 +      unsigned pte = start >> GEN8_PTE_SHIFT & GEN8_PTE_MASK;
        struct sg_page_iter sg_iter;
  
        pt_vaddr = NULL;
 +
        for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
 +              if (WARN_ON(pdpe >= GEN8_LEGACY_PDPS))
 +                      break;
 +
                if (pt_vaddr == NULL)
 -                      pt_vaddr = kmap_atomic(&ppgtt->gen8_pt_pages[act_pt]);
 +                      pt_vaddr = kmap_atomic(ppgtt->gen8_pt_pages[pdpe][pde]);
  
 -              pt_vaddr[act_pte] =
 +              pt_vaddr[pte] =
                        gen8_pte_encode(sg_page_iter_dma_address(&sg_iter),
                                        cache_level, true);
 -              if (++act_pte == GEN8_PTES_PER_PAGE) {
 +              if (++pte == GEN8_PTES_PER_PAGE) {
                        kunmap_atomic(pt_vaddr);
                        pt_vaddr = NULL;
 -                      act_pt++;
 -                      act_pte = 0;
 +                      if (++pde == GEN8_PDES_PER_PAGE) {
 +                              pdpe++;
 +                              pde = 0;
 +                      }
 +                      pte = 0;
                }
        }
        if (pt_vaddr)
                kunmap_atomic(pt_vaddr);
  }
  
 -static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt)
 +static void gen8_free_page_tables(struct page **pt_pages)
 +{
 +      int i;
 +
 +      if (pt_pages == NULL)
 +              return;
 +
 +      for (i = 0; i < GEN8_PDES_PER_PAGE; i++)
 +              if (pt_pages[i])
 +                      __free_pages(pt_pages[i], 0);
 +}
 +
 +static void gen8_ppgtt_free(const struct i915_hw_ppgtt *ppgtt)
  {
        int i;
  
 -      for (i = 0; i < ppgtt->num_pd_pages ; i++)
 +      for (i = 0; i < ppgtt->num_pd_pages; i++) {
 +              gen8_free_page_tables(ppgtt->gen8_pt_pages[i]);
 +              kfree(ppgtt->gen8_pt_pages[i]);
                kfree(ppgtt->gen8_pt_dma_addr[i]);
 +      }
  
 -      __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
        __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
  }
  
  static void gen8_ppgtt_unmap_pages(struct i915_hw_ppgtt *ppgtt)
  {
 +      struct pci_dev *hwdev = ppgtt->base.dev->pdev;
        int i, j;
  
        for (i = 0; i < ppgtt->num_pd_pages; i++) {
                if (!ppgtt->pd_dma_addr[i])
                        continue;
  
 -              pci_unmap_page(ppgtt->base.dev->pdev,
 -                             ppgtt->pd_dma_addr[i],
 -                             PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 +              pci_unmap_page(hwdev, ppgtt->pd_dma_addr[i], PAGE_SIZE,
 +                             PCI_DMA_BIDIRECTIONAL);
  
                for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
                        dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j];
                        if (addr)
 -                              pci_unmap_page(ppgtt->base.dev->pdev,
 -                                     addr,
 -                                     PAGE_SIZE,
 -                                     PCI_DMA_BIDIRECTIONAL);
 -
 +                              pci_unmap_page(hwdev, addr, PAGE_SIZE,
 +                                             PCI_DMA_BIDIRECTIONAL);
                }
        }
  }
@@@ -429,198 -368,88 +429,198 @@@ static void gen8_ppgtt_cleanup(struct i
        gen8_ppgtt_free(ppgtt);
  }
  
 -/**
 - * GEN8 legacy ppgtt programming is accomplished through 4 PDP registers with a
 - * net effect resembling a 2-level page table in normal x86 terms. Each PDP
 - * represents 1GB of memory
 - * 4 * 512 * 512 * 4096 = 4GB legacy 32b address space.
 - *
 - * TODO: Do something with the size parameter
 - **/
 -static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
 +static struct page **__gen8_alloc_page_tables(void)
  {
 -      struct page *pt_pages;
 -      int i, j, ret = -ENOMEM;
 -      const int max_pdp = DIV_ROUND_UP(size, 1 << 30);
 -      const int num_pt_pages = GEN8_PDES_PER_PAGE * max_pdp;
 +      struct page **pt_pages;
 +      int i;
  
 -      if (size % (1<<30))
 -              DRM_INFO("Pages will be wasted unless GTT size (%llu) is divisible by 1GB\n", size);
 +      pt_pages = kcalloc(GEN8_PDES_PER_PAGE, sizeof(struct page *), GFP_KERNEL);
 +      if (!pt_pages)
 +              return ERR_PTR(-ENOMEM);
 +
 +      for (i = 0; i < GEN8_PDES_PER_PAGE; i++) {
 +              pt_pages[i] = alloc_page(GFP_KERNEL);
 +              if (!pt_pages[i])
 +                      goto bail;
 +      }
  
 -      /* FIXME: split allocation into smaller pieces. For now we only ever do
 -       * this once, but with full PPGTT, the multiple contiguous allocations
 -       * will be bad.
 +      return pt_pages;
 +
 +bail:
 +      gen8_free_page_tables(pt_pages);
 +      kfree(pt_pages);
 +      return ERR_PTR(-ENOMEM);
 +}
 +
 +static int gen8_ppgtt_allocate_page_tables(struct i915_hw_ppgtt *ppgtt,
 +                                         const int max_pdp)
 +{
 +      struct page **pt_pages[GEN8_LEGACY_PDPS];
 +      int i, ret;
 +
 +      for (i = 0; i < max_pdp; i++) {
 +              pt_pages[i] = __gen8_alloc_page_tables();
 +              if (IS_ERR(pt_pages[i])) {
 +                      ret = PTR_ERR(pt_pages[i]);
 +                      goto unwind_out;
 +              }
 +      }
 +
 +      /* NB: Avoid touching gen8_pt_pages until last to keep the allocation,
 +       * "atomic" - for cleanup purposes.
         */
 +      for (i = 0; i < max_pdp; i++)
 +              ppgtt->gen8_pt_pages[i] = pt_pages[i];
 +
 +      return 0;
 +
 +unwind_out:
 +      while (i--) {
 +              gen8_free_page_tables(pt_pages[i]);
 +              kfree(pt_pages[i]);
 +      }
 +
 +      return ret;
 +}
 +
 +static int gen8_ppgtt_allocate_dma(struct i915_hw_ppgtt *ppgtt)
 +{
 +      int i;
 +
 +      for (i = 0; i < ppgtt->num_pd_pages; i++) {
 +              ppgtt->gen8_pt_dma_addr[i] = kcalloc(GEN8_PDES_PER_PAGE,
 +                                                   sizeof(dma_addr_t),
 +                                                   GFP_KERNEL);
 +              if (!ppgtt->gen8_pt_dma_addr[i])
 +                      return -ENOMEM;
 +      }
 +
 +      return 0;
 +}
 +
 +static int gen8_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt,
 +                                              const int max_pdp)
 +{
        ppgtt->pd_pages = alloc_pages(GFP_KERNEL, get_order(max_pdp << PAGE_SHIFT));
        if (!ppgtt->pd_pages)
                return -ENOMEM;
  
 -      pt_pages = alloc_pages(GFP_KERNEL, get_order(num_pt_pages << PAGE_SHIFT));
 -      if (!pt_pages) {
 +      ppgtt->num_pd_pages = 1 << get_order(max_pdp << PAGE_SHIFT);
 +      BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS);
 +
 +      return 0;
 +}
 +
 +static int gen8_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt,
 +                          const int max_pdp)
 +{
 +      int ret;
 +
 +      ret = gen8_ppgtt_allocate_page_directories(ppgtt, max_pdp);
 +      if (ret)
 +              return ret;
 +
 +      ret = gen8_ppgtt_allocate_page_tables(ppgtt, max_pdp);
 +      if (ret) {
                __free_pages(ppgtt->pd_pages, get_order(max_pdp << PAGE_SHIFT));
 -              return -ENOMEM;
 +              return ret;
        }
  
 -      ppgtt->gen8_pt_pages = pt_pages;
 -      ppgtt->num_pd_pages = 1 << get_order(max_pdp << PAGE_SHIFT);
 -      ppgtt->num_pt_pages = 1 << get_order(num_pt_pages << PAGE_SHIFT);
        ppgtt->num_pd_entries = max_pdp * GEN8_PDES_PER_PAGE;
 -      ppgtt->enable = gen8_ppgtt_enable;
 -      ppgtt->switch_mm = gen8_mm_switch;
 -      ppgtt->base.clear_range = gen8_ppgtt_clear_range;
 -      ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
 -      ppgtt->base.cleanup = gen8_ppgtt_cleanup;
 -      ppgtt->base.start = 0;
 -      ppgtt->base.total = ppgtt->num_pt_pages * GEN8_PTES_PER_PAGE * PAGE_SIZE;
  
 -      BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS);
 +      ret = gen8_ppgtt_allocate_dma(ppgtt);
 +      if (ret)
 +              gen8_ppgtt_free(ppgtt);
  
 -      /*
 -       * - Create a mapping for the page directories.
 -       * - For each page directory:
 -       *      allocate space for page table mappings.
 -       *      map each page table
 -       */
 -      for (i = 0; i < max_pdp; i++) {
 -              dma_addr_t temp;
 -              temp = pci_map_page(ppgtt->base.dev->pdev,
 -                                  &ppgtt->pd_pages[i], 0,
 -                                  PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 -              if (pci_dma_mapping_error(ppgtt->base.dev->pdev, temp))
 -                      goto err_out;
 +      return ret;
 +}
  
 -              ppgtt->pd_dma_addr[i] = temp;
 +static int gen8_ppgtt_setup_page_directories(struct i915_hw_ppgtt *ppgtt,
 +                                           const int pd)
 +{
 +      dma_addr_t pd_addr;
 +      int ret;
  
 -              ppgtt->gen8_pt_dma_addr[i] = kmalloc(sizeof(dma_addr_t) * GEN8_PDES_PER_PAGE, GFP_KERNEL);
 -              if (!ppgtt->gen8_pt_dma_addr[i])
 -                      goto err_out;
 +      pd_addr = pci_map_page(ppgtt->base.dev->pdev,
 +                             &ppgtt->pd_pages[pd], 0,
 +                             PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
  
 -              for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
 -                      struct page *p = &pt_pages[i * GEN8_PDES_PER_PAGE + j];
 -                      temp = pci_map_page(ppgtt->base.dev->pdev,
 -                                          p, 0, PAGE_SIZE,
 -                                          PCI_DMA_BIDIRECTIONAL);
 +      ret = pci_dma_mapping_error(ppgtt->base.dev->pdev, pd_addr);
 +      if (ret)
 +              return ret;
 +
 +      ppgtt->pd_dma_addr[pd] = pd_addr;
 +
 +      return 0;
 +}
  
 -                      if (pci_dma_mapping_error(ppgtt->base.dev->pdev, temp))
 -                              goto err_out;
 +static int gen8_ppgtt_setup_page_tables(struct i915_hw_ppgtt *ppgtt,
 +                                      const int pd,
 +                                      const int pt)
 +{
 +      dma_addr_t pt_addr;
 +      struct page *p;
 +      int ret;
  
 -                      ppgtt->gen8_pt_dma_addr[i][j] = temp;
 +      p = ppgtt->gen8_pt_pages[pd][pt];
 +      pt_addr = pci_map_page(ppgtt->base.dev->pdev,
 +                             p, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 +      ret = pci_dma_mapping_error(ppgtt->base.dev->pdev, pt_addr);
 +      if (ret)
 +              return ret;
 +
 +      ppgtt->gen8_pt_dma_addr[pd][pt] = pt_addr;
 +
 +      return 0;
 +}
 +
 +/**
 + * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
 + * with a net effect resembling a 2-level page table in normal x86 terms. Each
 + * PDP represents 1GB of memory 4 * 512 * 512 * 4096 = 4GB legacy 32b address
 + * space.
 + *
 + * FIXME: split allocation into smaller pieces. For now we only ever do this
 + * once, but with full PPGTT, the multiple contiguous allocations will be bad.
 + * TODO: Do something with the size parameter
 + */
 +static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
 +{
 +      const int max_pdp = DIV_ROUND_UP(size, 1 << 30);
 +      const int min_pt_pages = GEN8_PDES_PER_PAGE * max_pdp;
 +      int i, j, ret;
 +
 +      if (size % (1<<30))
 +              DRM_INFO("Pages will be wasted unless GTT size (%llu) is divisible by 1GB\n", size);
 +
 +      /* 1. Do all our allocations for page directories and page tables. */
 +      ret = gen8_ppgtt_alloc(ppgtt, max_pdp);
 +      if (ret)
 +              return ret;
 +
 +      /*
 +       * 2. Create DMA mappings for the page directories and page tables.
 +       */
 +      for (i = 0; i < max_pdp; i++) {
 +              ret = gen8_ppgtt_setup_page_directories(ppgtt, i);
 +              if (ret)
 +                      goto bail;
 +
 +              for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
 +                      ret = gen8_ppgtt_setup_page_tables(ppgtt, i, j);
 +                      if (ret)
 +                              goto bail;
                }
        }
  
 -      /* For now, the PPGTT helper functions all require that the PDEs are
 +      /*
 +       * 3. Map all the page directory entires to point to the page tables
 +       * we've allocated.
 +       *
 +       * For now, the PPGTT helper functions all require that the PDEs are
         * plugged in correctly. So we do that now/here. For aliasing PPGTT, we
 -       * will never need to touch the PDEs again */
 +       * will never need to touch the PDEs again.
 +       */
        for (i = 0; i < max_pdp; i++) {
                gen8_ppgtt_pde_t *pd_vaddr;
                pd_vaddr = kmap_atomic(&ppgtt->pd_pages[i]);
                kunmap_atomic(pd_vaddr);
        }
  
 -      ppgtt->base.clear_range(&ppgtt->base, 0,
 -                              ppgtt->num_pd_entries * GEN8_PTES_PER_PAGE,
 -                              true);
 +      ppgtt->enable = gen8_ppgtt_enable;
 +      ppgtt->switch_mm = gen8_mm_switch;
 +      ppgtt->base.clear_range = gen8_ppgtt_clear_range;
 +      ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
 +      ppgtt->base.cleanup = gen8_ppgtt_cleanup;
 +      ppgtt->base.start = 0;
 +      ppgtt->base.total = ppgtt->num_pd_entries * GEN8_PTES_PER_PAGE * PAGE_SIZE;
 +
 +      ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true);
  
        DRM_DEBUG_DRIVER("Allocated %d pages for page directories (%d wasted)\n",
                         ppgtt->num_pd_pages, ppgtt->num_pd_pages - max_pdp);
        DRM_DEBUG_DRIVER("Allocated %d pages for page tables (%lld wasted)\n",
 -                       ppgtt->num_pt_pages,
 -                       (ppgtt->num_pt_pages - num_pt_pages) +
 -                       size % (1<<30));
 +                       ppgtt->num_pd_entries,
 +                       (ppgtt->num_pd_entries - min_pt_pages) + size % (1<<30));
        return 0;
  
 -err_out:
 -      ppgtt->base.cleanup(&ppgtt->base);
 +bail:
 +      gen8_ppgtt_unmap_pages(ppgtt);
 +      gen8_ppgtt_free(ppgtt);
        return ret;
  }
  
@@@ -953,15 -776,13 +953,15 @@@ static int gen6_ppgtt_enable(struct i91
  
  /* PPGTT support for Sandybdrige/Gen6 and later */
  static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
 -                                 unsigned first_entry,
 -                                 unsigned num_entries,
 +                                 uint64_t start,
 +                                 uint64_t length,
                                   bool use_scratch)
  {
        struct i915_hw_ppgtt *ppgtt =
                container_of(vm, struct i915_hw_ppgtt, base);
        gen6_gtt_pte_t *pt_vaddr, scratch_pte;
 +      unsigned first_entry = start >> PAGE_SHIFT;
 +      unsigned num_entries = length >> PAGE_SHIFT;
        unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES;
        unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
        unsigned last_pte, i;
  
  static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
                                      struct sg_table *pages,
 -                                    unsigned first_entry,
 +                                    uint64_t start,
                                      enum i915_cache_level cache_level)
  {
        struct i915_hw_ppgtt *ppgtt =
                container_of(vm, struct i915_hw_ppgtt, base);
        gen6_gtt_pte_t *pt_vaddr;
 +      unsigned first_entry = start >> PAGE_SHIFT;
        unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES;
        unsigned act_pte = first_entry % I915_PPGTT_PT_ENTRIES;
        struct sg_page_iter sg_iter;
                kunmap_atomic(pt_vaddr);
  }
  
 -static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
 +static void gen6_ppgtt_unmap_pages(struct i915_hw_ppgtt *ppgtt)
  {
 -      struct i915_hw_ppgtt *ppgtt =
 -              container_of(vm, struct i915_hw_ppgtt, base);
        int i;
  
 -      list_del(&vm->global_link);
 -      drm_mm_takedown(&ppgtt->base.mm);
 -      drm_mm_remove_node(&ppgtt->node);
 -
        if (ppgtt->pt_dma_addr) {
                for (i = 0; i < ppgtt->num_pd_entries; i++)
                        pci_unmap_page(ppgtt->base.dev->pdev,
                                       ppgtt->pt_dma_addr[i],
                                       4096, PCI_DMA_BIDIRECTIONAL);
        }
 +}
 +
 +static void gen6_ppgtt_free(struct i915_hw_ppgtt *ppgtt)
 +{
 +      int i;
  
        kfree(ppgtt->pt_dma_addr);
        for (i = 0; i < ppgtt->num_pd_entries; i++)
                __free_page(ppgtt->pt_pages[i]);
        kfree(ppgtt->pt_pages);
 -      kfree(ppgtt);
  }
  
 -static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 +static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
 +{
 +      struct i915_hw_ppgtt *ppgtt =
 +              container_of(vm, struct i915_hw_ppgtt, base);
 +
 +      list_del(&vm->global_link);
 +      drm_mm_takedown(&ppgtt->base.mm);
 +      drm_mm_remove_node(&ppgtt->node);
 +
 +      gen6_ppgtt_unmap_pages(ppgtt);
 +      gen6_ppgtt_free(ppgtt);
 +}
 +
 +static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
  {
  #define GEN6_PD_ALIGN (PAGE_SIZE * 16)
  #define GEN6_PD_SIZE (GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE)
        struct drm_device *dev = ppgtt->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        bool retried = false;
 -      int i, ret;
 +      int ret;
  
        /* PPGTT PDEs reside in the GGTT and consists of 512 entries. The
         * allocator works in address space sizes, so it's multiplied by page
@@@ -1087,60 -896,42 +1087,60 @@@ alloc
        if (ppgtt->node.start < dev_priv->gtt.mappable_end)
                DRM_DEBUG("Forced to use aperture for PDEs\n");
  
 -      ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode;
        ppgtt->num_pd_entries = GEN6_PPGTT_PD_ENTRIES;
 -      if (IS_GEN6(dev)) {
 -              ppgtt->enable = gen6_ppgtt_enable;
 -              ppgtt->switch_mm = gen6_mm_switch;
 -      } else if (IS_HASWELL(dev)) {
 -              ppgtt->enable = gen7_ppgtt_enable;
 -              ppgtt->switch_mm = hsw_mm_switch;
 -      } else if (IS_GEN7(dev)) {
 -              ppgtt->enable = gen7_ppgtt_enable;
 -              ppgtt->switch_mm = gen7_mm_switch;
 -      } else
 -              BUG();
 -      ppgtt->base.clear_range = gen6_ppgtt_clear_range;
 -      ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
 -      ppgtt->base.cleanup = gen6_ppgtt_cleanup;
 -      ppgtt->base.scratch = dev_priv->gtt.base.scratch;
 -      ppgtt->base.start = 0;
 -      ppgtt->base.total = GEN6_PPGTT_PD_ENTRIES * I915_PPGTT_PT_ENTRIES * PAGE_SIZE;
 +      return ret;
 +}
 +
 +static int gen6_ppgtt_allocate_page_tables(struct i915_hw_ppgtt *ppgtt)
 +{
 +      int i;
 +
        ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *),
                                  GFP_KERNEL);
 -      if (!ppgtt->pt_pages) {
 -              drm_mm_remove_node(&ppgtt->node);
 +
 +      if (!ppgtt->pt_pages)
                return -ENOMEM;
 -      }
  
        for (i = 0; i < ppgtt->num_pd_entries; i++) {
                ppgtt->pt_pages[i] = alloc_page(GFP_KERNEL);
 -              if (!ppgtt->pt_pages[i])
 -                      goto err_pt_alloc;
 +              if (!ppgtt->pt_pages[i]) {
 +                      gen6_ppgtt_free(ppgtt);
 +                      return -ENOMEM;
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static int gen6_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt)
 +{
 +      int ret;
 +
 +      ret = gen6_ppgtt_allocate_page_directories(ppgtt);
 +      if (ret)
 +              return ret;
 +
 +      ret = gen6_ppgtt_allocate_page_tables(ppgtt);
 +      if (ret) {
 +              drm_mm_remove_node(&ppgtt->node);
 +              return ret;
        }
  
        ppgtt->pt_dma_addr = kcalloc(ppgtt->num_pd_entries, sizeof(dma_addr_t),
                                     GFP_KERNEL);
 -      if (!ppgtt->pt_dma_addr)
 -              goto err_pt_alloc;
 +      if (!ppgtt->pt_dma_addr) {
 +              drm_mm_remove_node(&ppgtt->node);
 +              gen6_ppgtt_free(ppgtt);
 +              return -ENOMEM;
 +      }
 +
 +      return 0;
 +}
 +
 +static int gen6_ppgtt_setup_page_tables(struct i915_hw_ppgtt *ppgtt)
 +{
 +      struct drm_device *dev = ppgtt->base.dev;
 +      int i;
  
        for (i = 0; i < ppgtt->num_pd_entries; i++) {
                dma_addr_t pt_addr;
                                       PCI_DMA_BIDIRECTIONAL);
  
                if (pci_dma_mapping_error(dev->pdev, pt_addr)) {
 -                      ret = -EIO;
 -                      goto err_pd_pin;
 -
 +                      gen6_ppgtt_unmap_pages(ppgtt);
 +                      return -EIO;
                }
 +
                ppgtt->pt_dma_addr[i] = pt_addr;
        }
  
 -      ppgtt->base.clear_range(&ppgtt->base, 0,
 -                              ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true);
 +      return 0;
 +}
 +
 +static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 +{
 +      struct drm_device *dev = ppgtt->base.dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int ret;
 +
 +      ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode;
 +      if (IS_GEN6(dev)) {
 +              ppgtt->enable = gen6_ppgtt_enable;
 +              ppgtt->switch_mm = gen6_mm_switch;
 +      } else if (IS_HASWELL(dev)) {
 +              ppgtt->enable = gen7_ppgtt_enable;
 +              ppgtt->switch_mm = hsw_mm_switch;
 +      } else if (IS_GEN7(dev)) {
 +              ppgtt->enable = gen7_ppgtt_enable;
 +              ppgtt->switch_mm = gen7_mm_switch;
 +      } else
 +              BUG();
 +
 +      ret = gen6_ppgtt_alloc(ppgtt);
 +      if (ret)
 +              return ret;
 +
 +      ret = gen6_ppgtt_setup_page_tables(ppgtt);
 +      if (ret) {
 +              gen6_ppgtt_free(ppgtt);
 +              return ret;
 +      }
 +
 +      ppgtt->base.clear_range = gen6_ppgtt_clear_range;
 +      ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
 +      ppgtt->base.cleanup = gen6_ppgtt_cleanup;
 +      ppgtt->base.scratch = dev_priv->gtt.base.scratch;
 +      ppgtt->base.start = 0;
 +      ppgtt->base.total = GEN6_PPGTT_PD_ENTRIES * I915_PPGTT_PT_ENTRIES * PAGE_SIZE;
        ppgtt->debug_dump = gen6_dump_ppgtt;
  
 -      DRM_DEBUG_DRIVER("Allocated pde space (%ldM) at GTT entry: %lx\n",
 -                       ppgtt->node.size >> 20,
 -                       ppgtt->node.start / PAGE_SIZE);
        ppgtt->pd_offset =
                ppgtt->node.start / PAGE_SIZE * sizeof(gen6_gtt_pte_t);
  
 -      return 0;
 +      ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true);
  
 -err_pd_pin:
 -      if (ppgtt->pt_dma_addr) {
 -              for (i--; i >= 0; i--)
 -                      pci_unmap_page(dev->pdev, ppgtt->pt_dma_addr[i],
 -                                     4096, PCI_DMA_BIDIRECTIONAL);
 -      }
 -err_pt_alloc:
 -      kfree(ppgtt->pt_dma_addr);
 -      for (i = 0; i < ppgtt->num_pd_entries; i++) {
 -              if (ppgtt->pt_pages[i])
 -                      __free_page(ppgtt->pt_pages[i]);
 -      }
 -      kfree(ppgtt->pt_pages);
 -      drm_mm_remove_node(&ppgtt->node);
 +      DRM_DEBUG_DRIVER("Allocated pde space (%ldM) at GTT entry: %lx\n",
 +                       ppgtt->node.size >> 20,
 +                       ppgtt->node.start / PAGE_SIZE);
  
 -      return ret;
 +      return 0;
  }
  
  int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
@@@ -1243,17 -1012,20 +1243,17 @@@ ppgtt_bind_vma(struct i915_vma *vma
               enum i915_cache_level cache_level,
               u32 flags)
  {
 -      const unsigned long entry = vma->node.start >> PAGE_SHIFT;
 -
        WARN_ON(flags);
  
 -      vma->vm->insert_entries(vma->vm, vma->obj->pages, entry, cache_level);
 +      vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start,
 +                              cache_level);
  }
  
  static void ppgtt_unbind_vma(struct i915_vma *vma)
  {
 -      const unsigned long entry = vma->node.start >> PAGE_SHIFT;
 -
        vma->vm->clear_range(vma->vm,
 -                           entry,
 -                           vma->obj->base.size >> PAGE_SHIFT,
 +                           vma->node.start,
 +                           vma->obj->base.size,
                             true);
  }
  
@@@ -1337,8 -1109,8 +1337,8 @@@ void i915_gem_suspend_gtt_mappings(stru
        i915_check_and_clear_faults(dev);
  
        dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
 -                                     dev_priv->gtt.base.start / PAGE_SIZE,
 -                                     dev_priv->gtt.base.total / PAGE_SIZE,
 +                                     dev_priv->gtt.base.start,
 +                                     dev_priv->gtt.base.total,
                                       false);
  }
  
@@@ -1352,8 -1124,8 +1352,8 @@@ void i915_gem_restore_gtt_mappings(stru
  
        /* First fill our portion of the GTT with scratch pages */
        dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
 -                                     dev_priv->gtt.base.start / PAGE_SIZE,
 -                                     dev_priv->gtt.base.total / PAGE_SIZE,
 +                                     dev_priv->gtt.base.start,
 +                                     dev_priv->gtt.base.total,
                                       true);
  
        list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
@@@ -1414,11 -1186,10 +1414,11 @@@ static inline void gen8_set_pte(void __
  
  static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
                                     struct sg_table *st,
 -                                   unsigned int first_entry,
 +                                   uint64_t start,
                                     enum i915_cache_level level)
  {
        struct drm_i915_private *dev_priv = vm->dev->dev_private;
 +      unsigned first_entry = start >> PAGE_SHIFT;
        gen8_gtt_pte_t __iomem *gtt_entries =
                (gen8_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
        int i = 0;
   */
  static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
                                     struct sg_table *st,
 -                                   unsigned int first_entry,
 +                                   uint64_t start,
                                     enum i915_cache_level level)
  {
        struct drm_i915_private *dev_priv = vm->dev->dev_private;
 +      unsigned first_entry = start >> PAGE_SHIFT;
        gen6_gtt_pte_t __iomem *gtt_entries =
                (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
        int i = 0;
  }
  
  static void gen8_ggtt_clear_range(struct i915_address_space *vm,
 -                                unsigned int first_entry,
 -                                unsigned int num_entries,
 +                                uint64_t start,
 +                                uint64_t length,
                                  bool use_scratch)
  {
        struct drm_i915_private *dev_priv = vm->dev->dev_private;
 +      unsigned first_entry = start >> PAGE_SHIFT;
 +      unsigned num_entries = length >> PAGE_SHIFT;
        gen8_gtt_pte_t scratch_pte, __iomem *gtt_base =
                (gen8_gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
        const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
  }
  
  static void gen6_ggtt_clear_range(struct i915_address_space *vm,
 -                                unsigned int first_entry,
 -                                unsigned int num_entries,
 +                                uint64_t start,
 +                                uint64_t length,
                                  bool use_scratch)
  {
        struct drm_i915_private *dev_priv = vm->dev->dev_private;
 +      unsigned first_entry = start >> PAGE_SHIFT;
 +      unsigned num_entries = length >> PAGE_SHIFT;
        gen6_gtt_pte_t scratch_pte, __iomem *gtt_base =
                (gen6_gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
        const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
@@@ -1561,12 -1327,10 +1561,12 @@@ static void i915_ggtt_bind_vma(struct i
  }
  
  static void i915_ggtt_clear_range(struct i915_address_space *vm,
 -                                unsigned int first_entry,
 -                                unsigned int num_entries,
 +                                uint64_t start,
 +                                uint64_t length,
                                  bool unused)
  {
 +      unsigned first_entry = start >> PAGE_SHIFT;
 +      unsigned num_entries = length >> PAGE_SHIFT;
        intel_gtt_clear_range(first_entry, num_entries);
  }
  
@@@ -1587,6 -1351,7 +1587,6 @@@ static void ggtt_bind_vma(struct i915_v
        struct drm_device *dev = vma->vm->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj = vma->obj;
 -      const unsigned long entry = vma->node.start >> PAGE_SHIFT;
  
        /* If there is no aliasing PPGTT, or the caller needs a global mapping,
         * or we have a global mapping already but the cacheability flags have
        if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) {
                if (!obj->has_global_gtt_mapping ||
                    (cache_level != obj->cache_level)) {
 -                      vma->vm->insert_entries(vma->vm, obj->pages, entry,
 +                      vma->vm->insert_entries(vma->vm, obj->pages,
 +                                              vma->node.start,
                                                cache_level);
                        obj->has_global_gtt_mapping = 1;
                }
             (cache_level != obj->cache_level))) {
                struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
                appgtt->base.insert_entries(&appgtt->base,
 -                                          vma->obj->pages, entry, cache_level);
 +                                          vma->obj->pages,
 +                                          vma->node.start,
 +                                          cache_level);
                vma->obj->has_aliasing_ppgtt_mapping = 1;
        }
  }
@@@ -1626,11 -1388,11 +1626,11 @@@ static void ggtt_unbind_vma(struct i915
        struct drm_device *dev = vma->vm->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj = vma->obj;
 -      const unsigned long entry = vma->node.start >> PAGE_SHIFT;
  
        if (obj->has_global_gtt_mapping) {
 -              vma->vm->clear_range(vma->vm, entry,
 -                                   vma->obj->base.size >> PAGE_SHIFT,
 +              vma->vm->clear_range(vma->vm,
 +                                   vma->node.start,
 +                                   obj->base.size,
                                     true);
                obj->has_global_gtt_mapping = 0;
        }
        if (obj->has_aliasing_ppgtt_mapping) {
                struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
                appgtt->base.clear_range(&appgtt->base,
 -                                       entry,
 -                                       obj->base.size >> PAGE_SHIFT,
 +                                       vma->node.start,
 +                                       obj->base.size,
                                         true);
                obj->has_aliasing_ppgtt_mapping = 0;
        }
@@@ -1724,14 -1486,14 +1724,14 @@@ void i915_gem_setup_global_gtt(struct d
  
        /* Clear any non-preallocated blocks */
        drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) {
 -              const unsigned long count = (hole_end - hole_start) / PAGE_SIZE;
                DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
                              hole_start, hole_end);
 -              ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count, true);
 +              ggtt_vm->clear_range(ggtt_vm, hole_start,
 +                                   hole_end - hole_start, true);
        }
  
        /* And finally clear the reserved guard page */
 -      ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1, true);
 +      ggtt_vm->clear_range(ggtt_vm, end - PAGE_SIZE, PAGE_SIZE, true);
  }
  
  void i915_gem_init_global_gtt(struct drm_device *dev)
@@@ -1796,6 -1558,11 +1796,6 @@@ static inline unsigned int gen8_get_tot
        bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK;
        if (bdw_gmch_ctl)
                bdw_gmch_ctl = 1 << bdw_gmch_ctl;
 -      if (bdw_gmch_ctl > 4) {
 -              WARN_ON(!i915.preliminary_hw_support);
 -              return 4<<20;
 -      }
 -
        return bdw_gmch_ctl << 20;
  }
  
@@@ -1817,14 -1584,14 +1817,14 @@@ static int ggtt_probe_common(struct drm
                             size_t gtt_size)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       phys_addr_t gtt_bus_addr;
+       phys_addr_t gtt_phys_addr;
        int ret;
  
        /* For Modern GENs the PTEs and register space are split in the BAR */
-       gtt_bus_addr = pci_resource_start(dev->pdev, 0) +
+       gtt_phys_addr = pci_resource_start(dev->pdev, 0) +
                (pci_resource_len(dev->pdev, 0) / 2);
  
-       dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size);
+       dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size);
        if (!dev_priv->gtt.gsm) {
                DRM_ERROR("Failed to map the gtt page table\n");
                return -ENOMEM;
@@@ -146,7 -146,10 +146,10 @@@ static void i915_error_vprintf(struct d
                va_list tmp;
  
                va_copy(tmp, args);
-               if (!__i915_error_seek(e, vsnprintf(NULL, 0, f, tmp)))
+               len = vsnprintf(NULL, 0, f, tmp);
+               va_end(tmp);
+               if (!__i915_error_seek(e, len))
                        return;
        }
  
@@@ -301,54 -304,22 +304,54 @@@ void i915_error_printf(struct drm_i915_
        va_end(args);
  }
  
 +static void print_error_obj(struct drm_i915_error_state_buf *m,
 +                          struct drm_i915_error_object *obj)
 +{
 +      int page, offset, elt;
 +
 +      for (page = offset = 0; page < obj->page_count; page++) {
 +              for (elt = 0; elt < PAGE_SIZE/4; elt++) {
 +                      err_printf(m, "%08x :  %08x\n", offset,
 +                                 obj->pages[page][elt]);
 +                      offset += 4;
 +              }
 +      }
 +}
 +
  int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
                            const struct i915_error_state_file_priv *error_priv)
  {
        struct drm_device *dev = error_priv->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_error_state *error = error_priv->error;
 -      int i, j, page, offset, elt;
 +      int i, j, offset, elt;
 +      int max_hangcheck_score;
  
        if (!error) {
                err_printf(m, "no error state collected\n");
                goto out;
        }
  
 +      err_printf(m, "%s\n", error->error_msg);
        err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
                   error->time.tv_usec);
        err_printf(m, "Kernel: " UTS_RELEASE "\n");
 +      max_hangcheck_score = 0;
 +      for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
 +              if (error->ring[i].hangcheck_score > max_hangcheck_score)
 +                      max_hangcheck_score = error->ring[i].hangcheck_score;
 +      }
 +      for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
 +              if (error->ring[i].hangcheck_score == max_hangcheck_score &&
 +                  error->ring[i].pid != -1) {
 +                      err_printf(m, "Active process (on ring %s): %s [%d]\n",
 +                                 ring_str(i),
 +                                 error->ring[i].comm,
 +                                 error->ring[i].pid);
 +              }
 +      }
 +      err_printf(m, "Reset count: %u\n", error->reset_count);
 +      err_printf(m, "Suspend count: %u\n", error->suspend_count);
        err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device);
        err_printf(m, "EIR: 0x%08x\n", error->eir);
        err_printf(m, "IER: 0x%08x\n", error->ier);
        for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
                struct drm_i915_error_object *obj;
  
 -              if ((obj = error->ring[i].batchbuffer)) {
 -                      err_printf(m, "%s --- gtt_offset = 0x%08x\n",
 -                                 dev_priv->ring[i].name,
 +              obj = error->ring[i].batchbuffer;
 +              if (obj) {
 +                      err_puts(m, dev_priv->ring[i].name);
 +                      if (error->ring[i].pid != -1)
 +                              err_printf(m, " (submitted by %s [%d])",
 +                                         error->ring[i].comm,
 +                                         error->ring[i].pid);
 +                      err_printf(m, " --- gtt_offset = 0x%08x\n",
                                   obj->gtt_offset);
 -                      offset = 0;
 -                      for (page = 0; page < obj->page_count; page++) {
 -                              for (elt = 0; elt < PAGE_SIZE/4; elt++) {
 -                                      err_printf(m, "%08x :  %08x\n", offset,
 -                                                 obj->pages[page][elt]);
 -                                      offset += 4;
 -                              }
 -                      }
 +                      print_error_obj(m, obj);
 +              }
 +
 +              obj = error->ring[i].wa_batchbuffer;
 +              if (obj) {
 +                      err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n",
 +                                 dev_priv->ring[i].name, obj->gtt_offset);
 +                      print_error_obj(m, obj);
                }
  
                if (error->ring[i].num_requests) {
                        err_printf(m, "%s --- ringbuffer = 0x%08x\n",
                                   dev_priv->ring[i].name,
                                   obj->gtt_offset);
 -                      offset = 0;
 -                      for (page = 0; page < obj->page_count; page++) {
 -                              for (elt = 0; elt < PAGE_SIZE/4; elt++) {
 -                                      err_printf(m, "%08x :  %08x\n",
 -                                                 offset,
 -                                                 obj->pages[page][elt]);
 -                                      offset += 4;
 -                              }
 -                      }
 +                      print_error_obj(m, obj);
                }
  
                if ((obj = error->ring[i].hws_page)) {
@@@ -692,8 -666,7 +695,8 @@@ static u32 capture_pinned_bo(struct drm
   * It's only a small step better than a random number in its current form.
   */
  static uint32_t i915_error_generate_code(struct drm_i915_private *dev_priv,
 -                                       struct drm_i915_error_state *error)
 +                                       struct drm_i915_error_state *error,
 +                                       int *ring_id)
  {
        uint32_t error_code = 0;
        int i;
         * synchronization commands which almost always appear in the case
         * strictly a client bug. Use instdone to differentiate those some.
         */
 -      for (i = 0; i < I915_NUM_RINGS; i++)
 -              if (error->ring[i].hangcheck_action == HANGCHECK_HUNG)
 +      for (i = 0; i < I915_NUM_RINGS; i++) {
 +              if (error->ring[i].hangcheck_action == HANGCHECK_HUNG) {
 +                      if (ring_id)
 +                              *ring_id = i;
 +
                        return error->ring[i].ipehr ^ error->ring[i].instdone;
 +              }
 +      }
  
        return error_code;
  }
@@@ -748,6 -716,87 +751,6 @@@ static void i915_gem_record_fences(stru
        }
  }
  
 -/* This assumes all batchbuffers are executed from the PPGTT. It might have to
 - * change in the future. */
 -static bool is_active_vm(struct i915_address_space *vm,
 -                       struct intel_ring_buffer *ring)
 -{
 -      struct drm_device *dev = vm->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct i915_hw_ppgtt *ppgtt;
 -
 -      if (INTEL_INFO(dev)->gen < 7)
 -              return i915_is_ggtt(vm);
 -
 -      /* FIXME: This ignores that the global gtt vm is also on this list. */
 -      ppgtt = container_of(vm, struct i915_hw_ppgtt, base);
 -
 -      if (INTEL_INFO(dev)->gen >= 8) {
 -              u64 pdp0 = (u64)I915_READ(GEN8_RING_PDP_UDW(ring, 0)) << 32;
 -              pdp0 |=  I915_READ(GEN8_RING_PDP_LDW(ring, 0));
 -              return pdp0 == ppgtt->pd_dma_addr[0];
 -      } else {
 -              u32 pp_db;
 -              pp_db = I915_READ(RING_PP_DIR_BASE(ring));
 -              return (pp_db >> 10) == ppgtt->pd_offset;
 -      }
 -}
 -
 -static struct drm_i915_error_object *
 -i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 -                           struct intel_ring_buffer *ring)
 -{
 -      struct i915_address_space *vm;
 -      struct i915_vma *vma;
 -      struct drm_i915_gem_object *obj;
 -      bool found_active = false;
 -      u32 seqno;
 -
 -      if (!ring->get_seqno)
 -              return NULL;
 -
 -      if (HAS_BROKEN_CS_TLB(dev_priv->dev)) {
 -              u32 acthd = I915_READ(ACTHD);
 -
 -              if (WARN_ON(ring->id != RCS))
 -                      return NULL;
 -
 -              obj = ring->scratch.obj;
 -              if (obj != NULL &&
 -                  acthd >= i915_gem_obj_ggtt_offset(obj) &&
 -                  acthd < i915_gem_obj_ggtt_offset(obj) + obj->base.size)
 -                      return i915_error_ggtt_object_create(dev_priv, obj);
 -      }
 -
 -      seqno = ring->get_seqno(ring, false);
 -      list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
 -              if (!is_active_vm(vm, ring))
 -                      continue;
 -
 -              found_active = true;
 -
 -              list_for_each_entry(vma, &vm->active_list, mm_list) {
 -                      obj = vma->obj;
 -                      if (obj->ring != ring)
 -                              continue;
 -
 -                      if (i915_seqno_passed(seqno, obj->last_read_seqno))
 -                              continue;
 -
 -                      if ((obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) == 0)
 -                              continue;
 -
 -                      /* We need to copy these to an anonymous buffer as the simplest
 -                       * method to avoid being overwritten by userspace.
 -                       */
 -                      return i915_error_object_create(dev_priv, obj, vm);
 -              }
 -      }
 -
 -      WARN_ON(!found_active);
 -      return NULL;
 -}
 -
  static void i915_record_ring_state(struct drm_device *dev,
                                   struct intel_ring_buffer *ring,
                                   struct drm_i915_error_ring *ering)
@@@ -896,39 -945,8 +899,39 @@@ static void i915_gem_record_rings(struc
  
                i915_record_ring_state(dev, ring, &error->ring[i]);
  
 -              error->ring[i].batchbuffer =
 -                      i915_error_first_batchbuffer(dev_priv, ring);
 +              error->ring[i].pid = -1;
 +              request = i915_gem_find_active_request(ring);
 +              if (request) {
 +                      /* We need to copy these to an anonymous buffer
 +                       * as the simplest method to avoid being overwritten
 +                       * by userspace.
 +                       */
 +                      error->ring[i].batchbuffer =
 +                              i915_error_object_create(dev_priv,
 +                                                       request->batch_obj,
 +                                                       request->ctx ?
 +                                                       request->ctx->vm :
 +                                                       &dev_priv->gtt.base);
 +
 +                      if (HAS_BROKEN_CS_TLB(dev_priv->dev) &&
 +                          ring->scratch.obj)
 +                              error->ring[i].wa_batchbuffer =
 +                                      i915_error_ggtt_object_create(dev_priv,
 +                                                           ring->scratch.obj);
 +
 +                      if (request->file_priv) {
 +                              struct task_struct *task;
 +
 +                              rcu_read_lock();
 +                              task = pid_task(request->file_priv->file->pid,
 +                                              PIDTYPE_PID);
 +                              if (task) {
 +                                      strcpy(error->ring[i].comm, task->comm);
 +                                      error->ring[i].pid = task->pid;
 +                              }
 +                              rcu_read_unlock();
 +                      }
 +              }
  
                error->ring[i].ringbuffer =
                        i915_error_ggtt_object_create(dev_priv, ring->obj);
@@@ -1095,40 -1113,6 +1098,40 @@@ static void i915_capture_reg_state(stru
        i915_get_extra_instdone(dev, error->extra_instdone);
  }
  
 +static void i915_error_capture_msg(struct drm_device *dev,
 +                                 struct drm_i915_error_state *error,
 +                                 bool wedged,
 +                                 const char *error_msg)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      u32 ecode;
 +      int ring_id = -1, len;
 +
 +      ecode = i915_error_generate_code(dev_priv, error, &ring_id);
 +
 +      len = scnprintf(error->error_msg, sizeof(error->error_msg),
 +                      "GPU HANG: ecode %d:0x%08x", ring_id, ecode);
 +
 +      if (ring_id != -1 && error->ring[ring_id].pid != -1)
 +              len += scnprintf(error->error_msg + len,
 +                               sizeof(error->error_msg) - len,
 +                               ", in %s [%d]",
 +                               error->ring[ring_id].comm,
 +                               error->ring[ring_id].pid);
 +
 +      scnprintf(error->error_msg + len, sizeof(error->error_msg) - len,
 +                ", reason: %s, action: %s",
 +                error_msg,
 +                wedged ? "reset" : "continue");
 +}
 +
 +static void i915_capture_gen_state(struct drm_i915_private *dev_priv,
 +                                 struct drm_i915_error_state *error)
 +{
 +      error->reset_count = i915_reset_count(&dev_priv->gpu_error);
 +      error->suspend_count = dev_priv->suspend_count;
 +}
 +
  /**
   * i915_capture_error_state - capture an error record for later analysis
   * @dev: drm device
   * out a structure which becomes available in debugfs for user level tools
   * to pick up.
   */
 -void i915_capture_error_state(struct drm_device *dev)
 +void i915_capture_error_state(struct drm_device *dev, bool wedged,
 +                            const char *error_msg)
  {
        static bool warned;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_error_state *error;
        unsigned long flags;
 -      uint32_t ecode;
 -
 -      spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
 -      error = dev_priv->gpu_error.first_error;
 -      spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
 -      if (error)
 -              return;
  
        /* Account for pipe specific data like PIPE*STAT */
        error = kzalloc(sizeof(*error), GFP_ATOMIC);
                return;
        }
  
 -      DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n",
 -               dev->primary->index);
        kref_init(&error->ref);
  
 +      i915_capture_gen_state(dev_priv, error);
        i915_capture_reg_state(dev_priv, error);
        i915_gem_capture_buffers(dev_priv, error);
        i915_gem_record_fences(dev, error);
        i915_gem_record_rings(dev, error);
 -      ecode = i915_error_generate_code(dev_priv, error);
 -
 -      if (!warned) {
 -              DRM_INFO("GPU HANG [%x]\n", ecode);
 -              DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
 -              DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
 -              DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
 -              DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n");
 -              warned = true;
 -      }
  
        do_gettimeofday(&error->time);
  
        error->overlay = intel_overlay_capture_error_state(dev);
        error->display = intel_display_capture_error_state(dev);
  
 +      i915_error_capture_msg(dev, error, wedged, error_msg);
 +      DRM_INFO("%s\n", error->error_msg);
 +
        spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
        if (dev_priv->gpu_error.first_error == NULL) {
                dev_priv->gpu_error.first_error = error;
        }
        spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
  
 -      if (error)
 +      if (error) {
                i915_error_state_free(&error->ref);
 +              return;
 +      }
 +
 +      if (!warned) {
 +              DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
 +              DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
 +              DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
 +              DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n");
 +              DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n", dev->primary->index);
 +              warned = true;
 +      }
  }
  
  void i915_error_state_get(struct drm_device *dev,
@@@ -387,15 -387,16 +387,15 @@@ static void cpt_set_fifo_underrun_repor
   *
   * Returns the previous state of underrun reporting.
   */
 -bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
 -                                         enum pipe pipe, bool enable)
 +bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
 +                                           enum pipe pipe, bool enable)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      unsigned long flags;
        bool ret;
  
 -      spin_lock_irqsave(&dev_priv->irq_lock, flags);
 +      assert_spin_locked(&dev_priv->irq_lock);
  
        ret = !intel_crtc->cpu_fifo_underrun_disabled;
  
                broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
  
  done:
 +      return ret;
 +}
 +
 +bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
 +                                         enum pipe pipe, bool enable)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      unsigned long flags;
 +      bool ret;
 +
 +      spin_lock_irqsave(&dev_priv->irq_lock, flags);
 +      ret = __intel_set_cpu_fifo_underrun_reporting(dev, pipe, enable);
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 +
        return ret;
  }
  
@@@ -494,7 -482,7 +494,7 @@@ done
  }
  
  
 -void
 +static void
  __i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
                       u32 enable_mask, u32 status_mask)
  {
        POSTING_READ(reg);
  }
  
 -void
 +static void
  __i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
                        u32 enable_mask, u32 status_mask)
  {
@@@ -667,8 -655,7 +667,7 @@@ static u32 i915_get_vblank_counter(stru
  
                vbl_start = mode->crtc_vblank_start * mode->crtc_htotal;
        } else {
-               enum transcoder cpu_transcoder =
-                       intel_pipe_to_cpu_transcoder(dev_priv, pipe);
+               enum transcoder cpu_transcoder = (enum transcoder) pipe;
                u32 htotal;
  
                htotal = ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff) + 1;
@@@ -1309,8 -1296,8 +1308,8 @@@ static void snb_gt_irq_handler(struct d
        if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
                      GT_BSD_CS_ERROR_INTERRUPT |
                      GT_RENDER_CS_MASTER_ERROR_INTERRUPT)) {
 -              DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir);
 -              i915_handle_error(dev, false);
 +              i915_handle_error(dev, false, "GT error interrupt 0x%08x",
 +                                gt_iir);
        }
  
        if (gt_iir & GT_PARITY_ERROR(dev))
@@@ -1557,9 -1544,8 +1556,9 @@@ static void gen6_rps_irq_handler(struc
                        notify_ring(dev_priv->dev, &dev_priv->ring[VECS]);
  
                if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) {
 -                      DRM_ERROR("VEBOX CS error interrupt 0x%08x\n", pm_iir);
 -                      i915_handle_error(dev_priv->dev, false);
 +                      i915_handle_error(dev_priv->dev, false,
 +                                        "VEBOX CS error interrupt 0x%08x",
 +                                        pm_iir);
                }
        }
  }
@@@ -1879,7 -1865,7 +1878,7 @@@ static void ilk_display_irq_handler(str
  static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      enum pipe i;
 +      enum pipe pipe;
  
        if (de_iir & DE_ERR_INT_IVB)
                ivb_err_int_handler(dev);
        if (de_iir & DE_GSE_IVB)
                intel_opregion_asle_intr(dev);
  
 -      for_each_pipe(i) {
 -              if (de_iir & (DE_PIPE_VBLANK_IVB(i)))
 -                      drm_handle_vblank(dev, i);
 +      for_each_pipe(pipe) {
 +              if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)))
 +                      drm_handle_vblank(dev, pipe);
  
                /* plane/pipes map 1:1 on ilk+ */
 -              if (de_iir & DE_PLANE_FLIP_DONE_IVB(i)) {
 -                      intel_prepare_page_flip(dev, i);
 -                      intel_finish_page_flip_plane(dev, i);
 +              if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) {
 +                      intel_prepare_page_flip(dev, pipe);
 +                      intel_finish_page_flip_plane(dev, pipe);
                }
        }
  
@@@ -2291,18 -2277,11 +2290,18 @@@ static void i915_report_and_clear_eir(s
   * so userspace knows something bad happened (should trigger collection
   * of a ring dump etc.).
   */
 -void i915_handle_error(struct drm_device *dev, bool wedged)
 +void i915_handle_error(struct drm_device *dev, bool wedged,
 +                     const char *fmt, ...)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 +      va_list args;
 +      char error_msg[80];
 +
 +      va_start(args, fmt);
 +      vscnprintf(error_msg, sizeof(error_msg), fmt, args);
 +      va_end(args);
  
 -      i915_capture_error_state(dev);
 +      i915_capture_error_state(dev, wedged, error_msg);
        i915_report_and_clear_eir(dev);
  
        if (wedged) {
@@@ -2605,9 -2584,9 +2604,9 @@@ ring_stuck(struct intel_ring_buffer *ri
         */
        tmp = I915_READ_CTL(ring);
        if (tmp & RING_WAIT) {
 -              DRM_ERROR("Kicking stuck wait on %s\n",
 -                        ring->name);
 -              i915_handle_error(dev, false);
 +              i915_handle_error(dev, false,
 +                                "Kicking stuck wait on %s",
 +                                ring->name);
                I915_WRITE_CTL(ring, tmp);
                return HANGCHECK_KICK;
        }
                default:
                        return HANGCHECK_HUNG;
                case 1:
 -                      DRM_ERROR("Kicking stuck semaphore on %s\n",
 -                                ring->name);
 -                      i915_handle_error(dev, false);
 +                      i915_handle_error(dev, false,
 +                                        "Kicking stuck semaphore on %s",
 +                                        ring->name);
                        I915_WRITE_CTL(ring, tmp);
                        return HANGCHECK_KICK;
                case 0:
@@@ -2741,7 -2720,7 +2740,7 @@@ static void i915_hangcheck_elapsed(unsi
        }
  
        if (rings_hung)
 -              return i915_handle_error(dev, true);
 +              return i915_handle_error(dev, true, "Ring hung");
  
        if (busy_count)
                /* Reset timer case chip hangs without another request
@@@ -3037,113 -3016,44 +3036,113 @@@ static int ironlake_irq_postinstall(str
        return 0;
  }
  
 +static void valleyview_display_irqs_install(struct drm_i915_private *dev_priv)
 +{
 +      u32 pipestat_mask;
 +      u32 iir_mask;
 +
 +      pipestat_mask = PIPESTAT_INT_STATUS_MASK |
 +                      PIPE_FIFO_UNDERRUN_STATUS;
 +
 +      I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
 +      I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
 +      POSTING_READ(PIPESTAT(PIPE_A));
 +
 +      pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
 +                      PIPE_CRC_DONE_INTERRUPT_STATUS;
 +
 +      i915_enable_pipestat(dev_priv, PIPE_A, pipestat_mask |
 +                                             PIPE_GMBUS_INTERRUPT_STATUS);
 +      i915_enable_pipestat(dev_priv, PIPE_B, pipestat_mask);
 +
 +      iir_mask = I915_DISPLAY_PORT_INTERRUPT |
 +                 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
 +                 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
 +      dev_priv->irq_mask &= ~iir_mask;
 +
 +      I915_WRITE(VLV_IIR, iir_mask);
 +      I915_WRITE(VLV_IIR, iir_mask);
 +      I915_WRITE(VLV_IMR, dev_priv->irq_mask);
 +      I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
 +      POSTING_READ(VLV_IER);
 +}
 +
 +static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
 +{
 +      u32 pipestat_mask;
 +      u32 iir_mask;
 +
 +      iir_mask = I915_DISPLAY_PORT_INTERRUPT |
 +                 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
 +                 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
 +
 +      dev_priv->irq_mask |= iir_mask;
 +      I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
 +      I915_WRITE(VLV_IMR, dev_priv->irq_mask);
 +      I915_WRITE(VLV_IIR, iir_mask);
 +      I915_WRITE(VLV_IIR, iir_mask);
 +      POSTING_READ(VLV_IIR);
 +
 +      pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
 +                      PIPE_CRC_DONE_INTERRUPT_STATUS;
 +
 +      i915_disable_pipestat(dev_priv, PIPE_A, pipestat_mask |
 +                                              PIPE_GMBUS_INTERRUPT_STATUS);
 +      i915_disable_pipestat(dev_priv, PIPE_B, pipestat_mask);
 +
 +      pipestat_mask = PIPESTAT_INT_STATUS_MASK |
 +                      PIPE_FIFO_UNDERRUN_STATUS;
 +      I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
 +      I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
 +      POSTING_READ(PIPESTAT(PIPE_A));
 +}
 +
 +void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
 +{
 +      assert_spin_locked(&dev_priv->irq_lock);
 +
 +      if (dev_priv->display_irqs_enabled)
 +              return;
 +
 +      dev_priv->display_irqs_enabled = true;
 +
 +      if (dev_priv->dev->irq_enabled)
 +              valleyview_display_irqs_install(dev_priv);
 +}
 +
 +void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
 +{
 +      assert_spin_locked(&dev_priv->irq_lock);
 +
 +      if (!dev_priv->display_irqs_enabled)
 +              return;
 +
 +      dev_priv->display_irqs_enabled = false;
 +
 +      if (dev_priv->dev->irq_enabled)
 +              valleyview_display_irqs_uninstall(dev_priv);
 +}
 +
  static int valleyview_irq_postinstall(struct drm_device *dev)
  {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 -      u32 enable_mask;
 -      u32 pipestat_enable = PLANE_FLIP_DONE_INT_STATUS_VLV |
 -              PIPE_CRC_DONE_INTERRUPT_STATUS;
        unsigned long irqflags;
  
 -      enable_mask = I915_DISPLAY_PORT_INTERRUPT;
 -      enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
 -              I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
 -              I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
 -              I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
 -
 -      /*
 -       *Leave vblank interrupts masked initially.  enable/disable will
 -       * toggle them based on usage.
 -       */
 -      dev_priv->irq_mask = (~enable_mask) |
 -              I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
 -              I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
 +      dev_priv->irq_mask = ~0;
  
        I915_WRITE(PORT_HOTPLUG_EN, 0);
        POSTING_READ(PORT_HOTPLUG_EN);
  
        I915_WRITE(VLV_IMR, dev_priv->irq_mask);
 -      I915_WRITE(VLV_IER, enable_mask);
 +      I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
        I915_WRITE(VLV_IIR, 0xffffffff);
 -      I915_WRITE(PIPESTAT(0), 0xffff);
 -      I915_WRITE(PIPESTAT(1), 0xffff);
        POSTING_READ(VLV_IER);
  
        /* Interrupt setup is already guaranteed to be single-threaded, this is
         * just to make the assert_spin_locked check happy. */
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 -      i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable);
 -      i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
 -      i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable);
 +      if (dev_priv->display_irqs_enabled)
 +              valleyview_display_irqs_install(dev_priv);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
  
        I915_WRITE(VLV_IIR, 0xffffffff);
@@@ -3274,7 -3184,6 +3273,7 @@@ static void gen8_irq_uninstall(struct d
  static void valleyview_irq_uninstall(struct drm_device *dev)
  {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      unsigned long irqflags;
        int pipe;
  
        if (!dev_priv)
        I915_WRITE(HWSTAM, 0xffffffff);
        I915_WRITE(PORT_HOTPLUG_EN, 0);
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 -      for_each_pipe(pipe)
 -              I915_WRITE(PIPESTAT(pipe), 0xffff);
 +
 +      spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 +      if (dev_priv->display_irqs_enabled)
 +              valleyview_display_irqs_uninstall(dev_priv);
 +      spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 +
 +      dev_priv->irq_mask = 0;
 +
        I915_WRITE(VLV_IIR, 0xffffffff);
        I915_WRITE(VLV_IMR, 0xffffffff);
        I915_WRITE(VLV_IER, 0x0);
@@@ -3434,9 -3337,7 +3433,9 @@@ static irqreturn_t i8xx_irq_handler(in
                 */
                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
                if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 -                      i915_handle_error(dev, false);
 +                      i915_handle_error(dev, false,
 +                                        "Command parser error, iir 0x%08x",
 +                                        iir);
  
                for_each_pipe(pipe) {
                        int reg = PIPESTAT(pipe);
@@@ -3618,9 -3519,7 +3617,9 @@@ static irqreturn_t i915_irq_handler(in
                 */
                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
                if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 -                      i915_handle_error(dev, false);
 +                      i915_handle_error(dev, false,
 +                                        "Command parser error, iir 0x%08x",
 +                                        iir);
  
                for_each_pipe(pipe) {
                        int reg = PIPESTAT(pipe);
@@@ -3857,9 -3756,7 +3856,9 @@@ static irqreturn_t i965_irq_handler(in
                 */
                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
                if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 -                      i915_handle_error(dev, false);
 +                      i915_handle_error(dev, false,
 +                                        "Command parser error, iir 0x%08x",
 +                                        iir);
  
                for_each_pipe(pipe) {
                        int reg = PIPESTAT(pipe);
@@@ -1122,7 -1122,7 +1122,7 @@@ void assert_pipe(struct drm_i915_privat
        if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
                state = true;
  
 -      if (!intel_display_power_enabled(dev_priv->dev,
 +      if (!intel_display_power_enabled(dev_priv,
                                POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
                cur_state = false;
        } else {
@@@ -1188,16 -1188,16 +1188,16 @@@ static void assert_sprites_disabled(str
                                    enum pipe pipe)
  {
        struct drm_device *dev = dev_priv->dev;
 -      int reg, i;
 +      int reg, sprite;
        u32 val;
  
        if (IS_VALLEYVIEW(dev)) {
 -              for (i = 0; i < INTEL_INFO(dev)->num_sprites; i++) {
 -                      reg = SPCNTR(pipe, i);
 +              for_each_sprite(pipe, sprite) {
 +                      reg = SPCNTR(pipe, sprite);
                        val = I915_READ(reg);
                        WARN((val & SP_ENABLE),
                             "sprite %c assertion failure, should be off on pipe %c but is still active\n",
 -                           sprite_name(pipe, i), pipe_name(pipe));
 +                           sprite_name(pipe, sprite), pipe_name(pipe));
                }
        } else if (INTEL_INFO(dev)->gen >= 7) {
                reg = SPRCTL(pipe);
@@@ -2321,25 -2321,6 +2321,25 @@@ intel_finish_fb(struct drm_framebuffer 
        return ret;
  }
  
 +static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
 +{
 +      struct drm_device *dev = crtc->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +      unsigned long flags;
 +      bool pending;
 +
 +      if (i915_reset_in_progress(&dev_priv->gpu_error) ||
 +          intel_crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
 +              return false;
 +
 +      spin_lock_irqsave(&dev->event_lock, flags);
 +      pending = to_intel_crtc(crtc)->unpin_work != NULL;
 +      spin_unlock_irqrestore(&dev->event_lock, flags);
 +
 +      return pending;
 +}
 +
  static int
  intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                    struct drm_framebuffer *fb)
        struct drm_framebuffer *old_fb;
        int ret;
  
 +      if (intel_crtc_has_pending_flip(crtc)) {
 +              DRM_ERROR("pipe is still busy with an old pageflip\n");
 +              return -EBUSY;
 +      }
 +
        /* no fb bound */
        if (!fb) {
                DRM_ERROR("No FB bound\n");
@@@ -2980,6 -2956,25 +2980,6 @@@ static void ironlake_fdi_disable(struc
        udelay(100);
  }
  
 -static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
 -{
 -      struct drm_device *dev = crtc->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      unsigned long flags;
 -      bool pending;
 -
 -      if (i915_reset_in_progress(&dev_priv->gpu_error) ||
 -          intel_crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
 -              return false;
 -
 -      spin_lock_irqsave(&dev->event_lock, flags);
 -      pending = to_intel_crtc(crtc)->unpin_work != NULL;
 -      spin_unlock_irqrestore(&dev->event_lock, flags);
 -
 -      return pending;
 -}
 -
  bool intel_has_pending_fb_unpin(struct drm_device *dev)
  {
        struct intel_crtc *crtc;
@@@ -3958,117 -3953,6 +3958,117 @@@ static void i9xx_pfit_enable(struct int
        I915_WRITE(BCLRPAT(crtc->pipe), 0);
  }
  
 +#define for_each_power_domain(domain, mask)                           \
 +      for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)     \
 +              if ((1 << (domain)) & (mask))
 +
 +enum intel_display_power_domain
 +intel_display_port_power_domain(struct intel_encoder *intel_encoder)
 +{
 +      struct drm_device *dev = intel_encoder->base.dev;
 +      struct intel_digital_port *intel_dig_port;
 +
 +      switch (intel_encoder->type) {
 +      case INTEL_OUTPUT_UNKNOWN:
 +              /* Only DDI platforms should ever use this output type */
 +              WARN_ON_ONCE(!HAS_DDI(dev));
 +      case INTEL_OUTPUT_DISPLAYPORT:
 +      case INTEL_OUTPUT_HDMI:
 +      case INTEL_OUTPUT_EDP:
 +              intel_dig_port = enc_to_dig_port(&intel_encoder->base);
 +              switch (intel_dig_port->port) {
 +              case PORT_A:
 +                      return POWER_DOMAIN_PORT_DDI_A_4_LANES;
 +              case PORT_B:
 +                      return POWER_DOMAIN_PORT_DDI_B_4_LANES;
 +              case PORT_C:
 +                      return POWER_DOMAIN_PORT_DDI_C_4_LANES;
 +              case PORT_D:
 +                      return POWER_DOMAIN_PORT_DDI_D_4_LANES;
 +              default:
 +                      WARN_ON_ONCE(1);
 +                      return POWER_DOMAIN_PORT_OTHER;
 +              }
 +      case INTEL_OUTPUT_ANALOG:
 +              return POWER_DOMAIN_PORT_CRT;
 +      case INTEL_OUTPUT_DSI:
 +              return POWER_DOMAIN_PORT_DSI;
 +      default:
 +              return POWER_DOMAIN_PORT_OTHER;
 +      }
 +}
 +
 +static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
 +{
 +      struct drm_device *dev = crtc->dev;
 +      struct intel_encoder *intel_encoder;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +      enum pipe pipe = intel_crtc->pipe;
 +      bool pfit_enabled = intel_crtc->config.pch_pfit.enabled;
 +      unsigned long mask;
 +      enum transcoder transcoder;
 +
 +      transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
 +
 +      mask = BIT(POWER_DOMAIN_PIPE(pipe));
 +      mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
 +      if (pfit_enabled)
 +              mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
 +
 +      for_each_encoder_on_crtc(dev, crtc, intel_encoder)
 +              mask |= BIT(intel_display_port_power_domain(intel_encoder));
 +
 +      return mask;
 +}
 +
 +void intel_display_set_init_power(struct drm_i915_private *dev_priv,
 +                                bool enable)
 +{
 +      if (dev_priv->power_domains.init_power_on == enable)
 +              return;
 +
 +      if (enable)
 +              intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 +      else
 +              intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 +
 +      dev_priv->power_domains.init_power_on = enable;
 +}
 +
 +static void modeset_update_crtc_power_domains(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
 +      struct intel_crtc *crtc;
 +
 +      /*
 +       * First get all needed power domains, then put all unneeded, to avoid
 +       * any unnecessary toggling of the power wells.
 +       */
 +      list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
 +              enum intel_display_power_domain domain;
 +
 +              if (!crtc->base.enabled)
 +                      continue;
 +
 +              pipe_domains[crtc->pipe] = get_crtc_power_domains(&crtc->base);
 +
 +              for_each_power_domain(domain, pipe_domains[crtc->pipe])
 +                      intel_display_power_get(dev_priv, domain);
 +      }
 +
 +      list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
 +              enum intel_display_power_domain domain;
 +
 +              for_each_power_domain(domain, crtc->enabled_power_domains)
 +                      intel_display_power_put(dev_priv, domain);
 +
 +              crtc->enabled_power_domains = pipe_domains[crtc->pipe];
 +      }
 +
 +      intel_display_set_init_power(dev_priv, false);
 +}
 +
  int valleyview_get_vco(struct drm_i915_private *dev_priv)
  {
        int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
@@@ -4229,7 -4113,6 +4229,7 @@@ static void valleyview_modeset_global_r
  
        if (req_cdclk != cur_cdclk)
                valleyview_set_cdclk(dev, req_cdclk);
 +      modeset_update_crtc_power_domains(dev);
  }
  
  static void valleyview_crtc_enable(struct drm_crtc *crtc)
@@@ -5612,10 -5495,6 +5612,10 @@@ static bool i9xx_get_pipe_config(struc
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
  
 +      if (!intel_display_power_enabled(dev_priv,
 +                                       POWER_DOMAIN_PIPE(crtc->pipe)))
 +              return false;
 +
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = DPLL_ID_PRIVATE;
  
@@@ -6277,7 -6156,7 +6277,7 @@@ int ironlake_get_lanes_required(int tar
         * is 2.5%; use 5% for safety's sake.
         */
        u32 bps = target_clock * bpp * 21 / 20;
 -      return bps / (link_bw * 8) + 1;
 +      return DIV_ROUND_UP(bps, link_bw * 8);
  }
  
  static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor)
@@@ -6933,9 -6812,105 +6933,9 @@@ done
        mutex_unlock(&dev_priv->pc8.lock);
  }
  
 -static void hsw_package_c8_gpu_idle(struct drm_i915_private *dev_priv)
 -{
 -      if (!HAS_PC8(dev_priv->dev))
 -              return;
 -
 -      mutex_lock(&dev_priv->pc8.lock);
 -      if (!dev_priv->pc8.gpu_idle) {
 -              dev_priv->pc8.gpu_idle = true;
 -              __hsw_enable_package_c8(dev_priv);
 -      }
 -      mutex_unlock(&dev_priv->pc8.lock);
 -}
 -
 -static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv)
 -{
 -      if (!HAS_PC8(dev_priv->dev))
 -              return;
 -
 -      mutex_lock(&dev_priv->pc8.lock);
 -      if (dev_priv->pc8.gpu_idle) {
 -              dev_priv->pc8.gpu_idle = false;
 -              __hsw_disable_package_c8(dev_priv);
 -      }
 -      mutex_unlock(&dev_priv->pc8.lock);
 -}
 -
 -#define for_each_power_domain(domain, mask)                           \
 -      for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)     \
 -              if ((1 << (domain)) & (mask))
 -
 -static unsigned long get_pipe_power_domains(struct drm_device *dev,
 -                                          enum pipe pipe, bool pfit_enabled)
 -{
 -      unsigned long mask;
 -      enum transcoder transcoder;
 -
 -      transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
 -
 -      mask = BIT(POWER_DOMAIN_PIPE(pipe));
 -      mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
 -      if (pfit_enabled)
 -              mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
 -
 -      return mask;
 -}
 -
 -void intel_display_set_init_power(struct drm_device *dev, bool enable)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -
 -      if (dev_priv->power_domains.init_power_on == enable)
 -              return;
 -
 -      if (enable)
 -              intel_display_power_get(dev, POWER_DOMAIN_INIT);
 -      else
 -              intel_display_power_put(dev, POWER_DOMAIN_INIT);
 -
 -      dev_priv->power_domains.init_power_on = enable;
 -}
 -
 -static void modeset_update_power_wells(struct drm_device *dev)
 -{
 -      unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
 -      struct intel_crtc *crtc;
 -
 -      /*
 -       * First get all needed power domains, then put all unneeded, to avoid
 -       * any unnecessary toggling of the power wells.
 -       */
 -      list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
 -              enum intel_display_power_domain domain;
 -
 -              if (!crtc->base.enabled)
 -                      continue;
 -
 -              pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
 -                                              crtc->pipe,
 -                                              crtc->config.pch_pfit.enabled);
 -
 -              for_each_power_domain(domain, pipe_domains[crtc->pipe])
 -                      intel_display_power_get(dev, domain);
 -      }
 -
 -      list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
 -              enum intel_display_power_domain domain;
 -
 -              for_each_power_domain(domain, crtc->enabled_power_domains)
 -                      intel_display_power_put(dev, domain);
 -
 -              crtc->enabled_power_domains = pipe_domains[crtc->pipe];
 -      }
 -
 -      intel_display_set_init_power(dev, false);
 -}
 -
  static void haswell_modeset_global_resources(struct drm_device *dev)
  {
 -      modeset_update_power_wells(dev);
 +      modeset_update_crtc_power_domains(dev);
        hsw_update_package_c8(dev);
  }
  
@@@ -6986,10 -6961,6 +6986,10 @@@ static bool haswell_get_pipe_config(str
        enum intel_display_power_domain pfit_domain;
        uint32_t tmp;
  
 +      if (!intel_display_power_enabled(dev_priv,
 +                                       POWER_DOMAIN_PIPE(crtc->pipe)))
 +              return false;
 +
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = DPLL_ID_PRIVATE;
  
                        pipe_config->cpu_transcoder = TRANSCODER_EDP;
        }
  
 -      if (!intel_display_power_enabled(dev,
 +      if (!intel_display_power_enabled(dev_priv,
                        POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
                return false;
  
        intel_get_pipe_timings(crtc, pipe_config);
  
        pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
 -      if (intel_display_power_enabled(dev, pfit_domain))
 +      if (intel_display_power_enabled(dev_priv, pfit_domain))
                ironlake_get_pfit_config(crtc, pipe_config);
  
        if (IS_HASWELL(dev))
@@@ -7578,7 -7549,7 +7578,7 @@@ static int intel_crtc_cursor_set(struc
                return -ENOENT;
  
        if (obj->base.size < width * height * 4) {
 -              DRM_ERROR("buffer is to small\n");
 +              DRM_DEBUG_KMS("buffer is to small\n");
                ret = -ENOMEM;
                goto fail;
        }
                unsigned alignment;
  
                if (obj->tiling_mode) {
 -                      DRM_ERROR("cursor cannot be tiled\n");
 +                      DRM_DEBUG_KMS("cursor cannot be tiled\n");
                        ret = -EINVAL;
                        goto fail_locked;
                }
  
                ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL);
                if (ret) {
 -                      DRM_ERROR("failed to move cursor bo into the GTT\n");
 +                      DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n");
                        goto fail_locked;
                }
  
                ret = i915_gem_object_put_fence(obj);
                if (ret) {
 -                      DRM_ERROR("failed to release fence for cursor");
 +                      DRM_DEBUG_KMS("failed to release fence for cursor");
                        goto fail_unpin;
                }
  
                                                  (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1,
                                                  align);
                if (ret) {
 -                      DRM_ERROR("failed to attach phys object\n");
 +                      DRM_DEBUG_KMS("failed to attach phys object\n");
                        goto fail_locked;
                }
                addr = obj->phys_obj->handle->busaddr;
@@@ -7721,7 -7692,7 +7721,7 @@@ err
        return ERR_PTR(ret);
  }
  
 -struct drm_framebuffer *
 +static struct drm_framebuffer *
  intel_framebuffer_create(struct drm_device *dev,
                         struct drm_mode_fb_cmd2 *mode_cmd,
                         struct drm_i915_gem_object *obj)
@@@ -8221,12 -8192,8 +8221,12 @@@ void intel_mark_busy(struct drm_device 
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
  
 -      hsw_package_c8_gpu_busy(dev_priv);
 +      if (dev_priv->mm.busy)
 +              return;
 +
 +      hsw_disable_package_c8(dev_priv);
        i915_update_gfx_val(dev_priv);
 +      dev_priv->mm.busy = true;
  }
  
  void intel_mark_idle(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
  
 -      hsw_package_c8_gpu_idle(dev_priv);
 +      if (!dev_priv->mm.busy)
 +              return;
 +
 +      dev_priv->mm.busy = false;
  
        if (!i915.powersave)
 -              return;
 +              goto out;
  
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                if (!crtc->fb)
  
        if (INTEL_INFO(dev)->gen >= 6)
                gen6_rps_idle(dev->dev_private);
 +
 +out:
 +      hsw_enable_package_c8(dev_priv);
  }
  
  void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
@@@ -8627,6 -8588,20 +8627,20 @@@ static int intel_gen7_queue_flip(struc
        if (ring->id == RCS)
                len += 6;
  
+       /*
+        * BSpec MI_DISPLAY_FLIP for IVB:
+        * "The full packet must be contained within the same cache line."
+        *
+        * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same
+        * cacheline, if we ever start emitting more commands before
+        * the MI_DISPLAY_FLIP we may need to first emit everything else,
+        * then do the cacheline alignment, and finally emit the
+        * MI_DISPLAY_FLIP.
+        */
+       ret = intel_ring_cacheline_align(ring);
+       if (ret)
+               goto err_unpin;
        ret = intel_ring_begin(ring, len);
        if (ret)
                goto err_unpin;
@@@ -8703,9 -8678,6 +8717,9 @@@ static int intel_crtc_page_flip(struct 
             fb->pitches[0] != crtc->fb->pitches[0]))
                return -EINVAL;
  
 +      if (i915_terminally_wedged(&dev_priv->gpu_error))
 +              goto out_hang;
 +
        work = kzalloc(sizeof(*work), GFP_KERNEL);
        if (work == NULL)
                return -ENOMEM;
@@@ -8780,13 -8752,6 +8794,13 @@@ cleanup
  free_work:
        kfree(work);
  
 +      if (ret == -EIO) {
 +out_hang:
 +              intel_crtc_wait_for_pending_flips(crtc);
 +              ret = intel_pipe_set_base(crtc, crtc->x, crtc->y, fb);
 +              if (ret == 0 && event)
 +                      drm_send_vblank_event(dev, intel_crtc->pipe, event);
 +      }
        return ret;
  }
  
@@@ -10590,10 -10555,10 +10604,10 @@@ static const struct drm_framebuffer_fun
        .create_handle = intel_user_framebuffer_create_handle,
  };
  
 -int intel_framebuffer_init(struct drm_device *dev,
 -                         struct intel_framebuffer *intel_fb,
 -                         struct drm_mode_fb_cmd2 *mode_cmd,
 -                         struct drm_i915_gem_object *obj)
 +static int intel_framebuffer_init(struct drm_device *dev,
 +                                struct intel_framebuffer *intel_fb,
 +                                struct drm_mode_fb_cmd2 *mode_cmd,
 +                                struct drm_i915_gem_object *obj)
  {
        int aligned_height;
        int pitch_limit;
@@@ -11031,8 -10996,7 +11045,8 @@@ void intel_modeset_suspend_hw(struct dr
  void intel_modeset_init(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      int i, j, ret;
 +      int sprite, ret;
 +      enum pipe pipe;
  
        drm_mode_config_init(dev);
  
                      INTEL_INFO(dev)->num_pipes,
                      INTEL_INFO(dev)->num_pipes > 1 ? "s" : "");
  
 -      for_each_pipe(i) {
 -              intel_crtc_init(dev, i);
 -              for (j = 0; j < INTEL_INFO(dev)->num_sprites; j++) {
 -                      ret = intel_plane_init(dev, i, j);
 +      for_each_pipe(pipe) {
 +              intel_crtc_init(dev, pipe);
 +              for_each_sprite(pipe, sprite) {
 +                      ret = intel_plane_init(dev, pipe, sprite);
                        if (ret)
                                DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
 -                                            pipe_name(i), sprite_name(i, j), ret);
 +                                            pipe_name(pipe), sprite_name(pipe, sprite), ret);
                }
        }
  
        /* Just in case the BIOS is doing something questionable. */
        intel_disable_fbc(dev);
  
 +      mutex_lock(&dev->mode_config.mutex);
        intel_modeset_setup_hw_state(dev, false);
 +      mutex_unlock(&dev->mode_config.mutex);
  }
  
  static void
@@@ -11277,21 -11239,11 +11291,21 @@@ static void intel_sanitize_encoder(stru
         * the crtc fixup. */
  }
  
 -void i915_redisable_vga(struct drm_device *dev)
 +void i915_redisable_vga_power_on(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 vga_reg = i915_vgacntrl_reg(dev);
  
 +      if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
 +              DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
 +              i915_disable_vga(dev);
 +      }
 +}
 +
 +void i915_redisable_vga(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
        /* This function can be called both from intel_modeset_setup_hw_state or
         * at a very early point in our resume sequence, where the power well
         * structures are not yet restored. Since this function is at a very
         * level, just check if the power well is enabled instead of trying to
         * follow the "don't touch the power well if we don't need it" policy
         * the rest of the driver uses. */
 -      if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) &&
 -          (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0)
 +      if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_VGA))
                return;
  
 -      if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
 -              DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
 -              i915_disable_vga(dev);
 -      }
 +      i915_redisable_vga_power_on(dev);
  }
  
  static void intel_modeset_readout_hw_state(struct drm_device *dev)
@@@ -11646,8 -11602,7 +11660,8 @@@ intel_display_capture_error_state(struc
  
        for_each_pipe(i) {
                error->pipe[i].power_domain_on =
 -                      intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
 +                      intel_display_power_enabled_sw(dev_priv,
 +                                                     POWER_DOMAIN_PIPE(i));
                if (!error->pipe[i].power_domain_on)
                        continue;
  
                enum transcoder cpu_transcoder = transcoders[i];
  
                error->transcoder[i].power_domain_on =
 -                      intel_display_power_enabled_sw(dev,
 +                      intel_display_power_enabled_sw(dev_priv,
                                POWER_DOMAIN_TRANSCODER(cpu_transcoder));
                if (!error->transcoder[i].power_domain_on)
                        continue;
@@@ -459,7 -459,7 +459,7 @@@ intel_dp_aux_ch(struct intel_dp *intel_
        int i, ret, recv_bytes;
        uint32_t status;
        int try, clock = 0;
-       bool has_aux_irq = true;
+       bool has_aux_irq = HAS_AUX_IRQ(dev);
  
        /* dp aux is extremely sensitive to irq latency, hence request the
         * lowest possible wakeup latency and so prevent the cpu from going into
@@@ -577,6 -577,7 +577,7 @@@ intel_dp_aux_native_write(struct intel_
        uint8_t msg[20];
        int msg_bytes;
        uint8_t ack;
+       int retry;
  
        if (WARN_ON(send_bytes > 16))
                return -E2BIG;
        msg[3] = send_bytes - 1;
        memcpy(&msg[4], send, send_bytes);
        msg_bytes = send_bytes + 4;
-       for (;;) {
+       for (retry = 0; retry < 7; retry++) {
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
                ack >>= 4;
                if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
-                       break;
+                       return send_bytes;
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       udelay(100);
+                       usleep_range(400, 500);
                else
                        return -EIO;
        }
-       return send_bytes;
+       DRM_ERROR("too many retries, giving up\n");
+       return -EIO;
  }
  
  /* Write a single byte to the aux channel in native mode */
@@@ -622,6 -625,7 +625,7 @@@ intel_dp_aux_native_read(struct intel_d
        int reply_bytes;
        uint8_t ack;
        int ret;
+       int retry;
  
        if (WARN_ON(recv_bytes > 19))
                return -E2BIG;
        msg_bytes = 4;
        reply_bytes = recv_bytes + 1;
  
-       for (;;) {
+       for (retry = 0; retry < 7; retry++) {
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
                                      reply, reply_bytes);
                if (ret == 0)
                        return ret - 1;
                }
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       udelay(100);
+                       usleep_range(400, 500);
                else
                        return -EIO;
        }
+       DRM_ERROR("too many retries, giving up\n");
+       return -EIO;
  }
  
  static int
@@@ -909,8 -916,8 +916,8 @@@ intel_dp_compute_config(struct intel_en
                mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock,
                                                   bpp);
  
 -              for (clock = 0; clock <= max_clock; clock++) {
 -                      for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
 +              for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
 +                      for (clock = 0; clock <= max_clock; clock++) {
                                link_clock = drm_dp_bw_code_to_link_rate(bws[clock]);
                                link_avail = intel_dp_max_data_rate(link_clock,
                                                                    lane_count);
@@@ -1326,8 -1333,7 +1333,8 @@@ void intel_edp_panel_off(struct intel_d
        pp = ironlake_get_pp_control(intel_dp);
        /* We need to switch off panel power _and_ force vdd, for otherwise some
         * panels get very unhappy and cease to work. */
 -      pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
 +      pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
 +              EDP_BLC_ENABLE);
  
        pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
  
@@@ -1479,14 -1485,7 +1486,14 @@@ static bool intel_dp_get_hw_state(struc
        enum port port = dp_to_dig_port(intel_dp)->port;
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      u32 tmp = I915_READ(intel_dp->output_reg);
 +      enum intel_display_power_domain power_domain;
 +      u32 tmp;
 +
 +      power_domain = intel_display_port_power_domain(encoder);
 +      if (!intel_display_power_enabled(dev_priv, power_domain))
 +              return false;
 +
 +      tmp = I915_READ(intel_dp->output_reg);
  
        if (!(tmp & DP_PORT_EN))
                return false;
@@@ -1869,11 -1868,9 +1876,11 @@@ static void intel_disable_dp(struct int
  
        /* Make sure the panel is off before trying to change the mode. But also
         * ensure that we have vdd while we switch off the panel. */
 +      edp_panel_vdd_on(intel_dp);
        intel_edp_backlight_off(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
        intel_edp_panel_off(intel_dp);
 +      edp_panel_vdd_off(intel_dp, true);
  
        /* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */
        if (!(port == PORT_A || IS_VALLEYVIEW(dev)))
@@@ -1963,10 -1960,12 +1970,12 @@@ static void vlv_pre_enable_dp(struct in
  
        mutex_unlock(&dev_priv->dpio_lock);
  
-       /* init power sequencer on this pipe and port */
-       intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-                                                     &power_seq);
+       if (is_edp(intel_dp)) {
+               /* init power sequencer on this pipe and port */
+               intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+               intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+                                                             &power_seq);
+       }
  
        intel_enable_dp(encoder);
  
@@@ -3225,14 -3224,10 +3234,14 @@@ intel_dp_detect(struct drm_connector *c
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum drm_connector_status status;
 +      enum intel_display_power_domain power_domain;
        struct edid *edid = NULL;
  
        intel_runtime_pm_get(dev_priv);
  
 +      power_domain = intel_display_port_power_domain(intel_encoder);
 +      intel_display_power_get(dev_priv, power_domain);
 +
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, drm_get_connector_name(connector));
  
        status = connector_status_connected;
  
  out:
 +      intel_display_power_put(dev_priv, power_domain);
 +
        intel_runtime_pm_put(dev_priv);
 +
        return status;
  }
  
  static int intel_dp_get_modes(struct drm_connector *connector)
  {
        struct intel_dp *intel_dp = intel_attached_dp(connector);
 +      struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 +      struct intel_encoder *intel_encoder = &intel_dig_port->base;
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct drm_device *dev = connector->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      enum intel_display_power_domain power_domain;
        int ret;
  
        /* We should parse the EDID data and find out if it has an audio sink
         */
  
 +      power_domain = intel_display_port_power_domain(intel_encoder);
 +      intel_display_power_get(dev_priv, power_domain);
 +
        ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
 +      intel_display_power_put(dev_priv, power_domain);
        if (ret)
                return ret;
  
@@@ -3309,25 -3293,15 +3318,25 @@@ static boo
  intel_dp_detect_audio(struct drm_connector *connector)
  {
        struct intel_dp *intel_dp = intel_attached_dp(connector);
 +      struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 +      struct intel_encoder *intel_encoder = &intel_dig_port->base;
 +      struct drm_device *dev = connector->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      enum intel_display_power_domain power_domain;
        struct edid *edid;
        bool has_audio = false;
  
 +      power_domain = intel_display_port_power_domain(intel_encoder);
 +      intel_display_power_get(dev_priv, power_domain);
 +
        edid = intel_dp_get_edid(connector, &intel_dp->adapter);
        if (edid) {
                has_audio = drm_detect_monitor_audio(edid);
                kfree(edid);
        }
  
 +      intel_display_power_put(dev_priv, power_domain);
 +
        return has_audio;
  }
  
@@@ -571,7 -571,7 +571,7 @@@ static int init_render_ring(struct inte
         * to use MI_WAIT_FOR_EVENT within the CS. It should already be
         * programmed to '1' on all products.
         *
 -       * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv
 +       * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw
         */
        if (INTEL_INFO(dev)->gen >= 6)
                I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
@@@ -1388,8 -1388,6 +1388,8 @@@ static int intel_init_ring_buffer(struc
        if (IS_I830(ring->dev) || IS_845G(ring->dev))
                ring->effective_size -= 128;
  
 +      i915_cmd_parser_init_ring(ring);
 +
        return 0;
  
  err_unmap:
@@@ -1644,6 -1642,27 +1644,27 @@@ int intel_ring_begin(struct intel_ring_
        return 0;
  }
  
+ /* Align the ring tail to a cacheline boundary */
+ int intel_ring_cacheline_align(struct intel_ring_buffer *ring)
+ {
+       int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t);
+       int ret;
+       if (num_dwords == 0)
+               return 0;
+       ret = intel_ring_begin(ring, num_dwords);
+       if (ret)
+               return ret;
+       while (num_dwords--)
+               intel_ring_emit(ring, MI_NOOP);
+       intel_ring_advance(ring);
+       return 0;
+ }
  void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
  {
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
@@@ -164,38 -164,6 +164,38 @@@ struct  intel_ring_buffer 
                u32 gtt_offset;
                volatile u32 *cpu_page;
        } scratch;
 +
 +      /*
 +       * Tables of commands the command parser needs to know about
 +       * for this ring.
 +       */
 +      const struct drm_i915_cmd_table *cmd_tables;
 +      int cmd_table_count;
 +
 +      /*
 +       * Table of registers allowed in commands that read/write registers.
 +       */
 +      const u32 *reg_table;
 +      int reg_count;
 +
 +      /*
 +       * Table of registers allowed in commands that read/write registers, but
 +       * only from the DRM master.
 +       */
 +      const u32 *master_reg_table;
 +      int master_reg_count;
 +
 +      /*
 +       * Returns the bitmask for the length field of the specified command.
 +       * Return 0 for an unrecognized/invalid command.
 +       *
 +       * If the command parser finds an entry for a command in the ring's
 +       * cmd_tables, it gets the command's length based on the table entry.
 +       * If not, it calls this function to determine the per-ring length field
 +       * encoding for the command (i.e. certain opcode ranges use certain bits
 +       * to encode the command length in the header).
 +       */
 +      u32 (*get_cmd_length_mask)(u32 cmd_header);
  };
  
  static inline bool
@@@ -267,6 -235,7 +267,7 @@@ intel_write_status_page(struct intel_ri
  void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
  
  int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
+ int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring);
  static inline void intel_ring_emit(struct intel_ring_buffer *ring,
                                   u32 data)
  {