]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Merge tag 'v3.6-rc2' into drm-intel-next
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 17 Aug 2012 06:57:56 +0000 (08:57 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 17 Aug 2012 07:01:08 +0000 (09:01 +0200)
Backmerge Linux 3.6-rc2 to resolve a few funny conflicts before we put
even more madness on top:

- drivers/gpu/drm/i915/i915_irq.c: Just a spurious WARN removed in
  -fixes, that has been changed in a variable-rename in -next, too.

- drivers/gpu/drm/i915/intel_ringbuffer.c: -next remove scratch_addr
  (since all their users have been extracted in another fucntion),
  -fixes added another user for a hw workaroudn.

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

index ff569cc353766208c3c597d838e5c578d0a43a70,a24ffbe97c01cffd8a8fa5093a5ba15ff04db30b..7ebb13b651338c7d300783326710a00e55d6601a
@@@ -346,11 -346,40 +346,40 @@@ static const struct pci_device_id pciid
        INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
        INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */
        INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */
+       INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT2 desktop */
        INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */
        INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */
+       INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT2 server */
        INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */
        INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */
-       INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */
+       INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */
+       INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */
+       INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */
+       INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT2 desktop */
+       INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */
+       INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */
+       INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT2 server */
+       INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */
+       INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */
+       INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT2 mobile */
+       INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */
+       INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */
+       INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT2 desktop */
+       INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */
+       INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */
+       INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT2 server */
+       INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */
+       INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */
+       INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */
+       INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT1 desktop */
+       INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */
+       INTEL_VGA_DEVICE(0x0D32, &intel_haswell_d_info), /* CRW GT2 desktop */
+       INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT1 server */
+       INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */
+       INTEL_VGA_DEVICE(0x0D3A, &intel_haswell_d_info), /* CRW GT2 server */
+       INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT1 mobile */
+       INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */
+       INTEL_VGA_DEVICE(0x0D36, &intel_haswell_m_info), /* CRW GT2 mobile */
        INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
@@@ -1031,7 -1060,7 +1060,7 @@@ static bool IS_DISPLAYREG(u32 reg
         * This should make it easier to transition modules over to the
         * new register block scheme, since we can do it incrementally.
         */
 -      if (reg >= 0x180000)
 +      if (reg >= VLV_DISPLAY_BASE)
                return false;
  
        if (reg >= RENDER_RING_BASE &&
@@@ -1151,49 -1180,3 +1180,49 @@@ __i915_write(16, w
  __i915_write(32, l)
  __i915_write(64, q)
  #undef __i915_write
 +
 +static const struct register_whitelist {
 +      uint64_t offset;
 +      uint32_t size;
 +      uint32_t gen_bitmask; /* support gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
 +} whitelist[] = {
 +      { RING_TIMESTAMP(RENDER_RING_BASE), 8, 0xF0 },
 +};
 +
 +int i915_reg_read_ioctl(struct drm_device *dev,
 +                      void *data, struct drm_file *file)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_reg_read *reg = data;
 +      struct register_whitelist const *entry = whitelist;
 +      int i;
 +
 +      for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
 +              if (entry->offset == reg->offset &&
 +                  (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
 +                      break;
 +      }
 +
 +      if (i == ARRAY_SIZE(whitelist))
 +              return -EINVAL;
 +
 +      switch (entry->size) {
 +      case 8:
 +              reg->val = I915_READ64(reg->offset);
 +              break;
 +      case 4:
 +              reg->val = I915_READ(reg->offset);
 +              break;
 +      case 2:
 +              reg->val = I915_READ16(reg->offset);
 +              break;
 +      case 1:
 +              reg->val = I915_READ8(reg->offset);
 +              break;
 +      default:
 +              WARN_ON(1);
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
index 25b2c54e1261e4736de842768330ae837a4a2301,ff2819ea08130fb98da5f67550a18d9ca3c5974d..afb312ee050ca972daf537061c68a1163df51e5a
  #include "intel_drv.h"
  #include <linux/dma_remapping.h>
  
 -struct change_domains {
 -      uint32_t invalidate_domains;
 -      uint32_t flush_domains;
 -      uint32_t flush_rings;
 -      uint32_t flips;
 -};
 -
 -/*
 - * Set the next domain for the specified object. This
 - * may not actually perform the necessary flushing/invaliding though,
 - * as that may want to be batched with other set_domain operations
 - *
 - * This is (we hope) the only really tricky part of gem. The goal
 - * is fairly simple -- track which caches hold bits of the object
 - * and make sure they remain coherent. A few concrete examples may
 - * help to explain how it works. For shorthand, we use the notation
 - * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the
 - * a pair of read and write domain masks.
 - *
 - * Case 1: the batch buffer
 - *
 - *    1. Allocated
 - *    2. Written by CPU
 - *    3. Mapped to GTT
 - *    4. Read by GPU
 - *    5. Unmapped from GTT
 - *    6. Freed
 - *
 - *    Let's take these a step at a time
 - *
 - *    1. Allocated
 - *            Pages allocated from the kernel may still have
 - *            cache contents, so we set them to (CPU, CPU) always.
 - *    2. Written by CPU (using pwrite)
 - *            The pwrite function calls set_domain (CPU, CPU) and
 - *            this function does nothing (as nothing changes)
 - *    3. Mapped by GTT
 - *            This function asserts that the object is not
 - *            currently in any GPU-based read or write domains
 - *    4. Read by GPU
 - *            i915_gem_execbuffer calls set_domain (COMMAND, 0).
 - *            As write_domain is zero, this function adds in the
 - *            current read domains (CPU+COMMAND, 0).
 - *            flush_domains is set to CPU.
 - *            invalidate_domains is set to COMMAND
 - *            clflush is run to get data out of the CPU caches
 - *            then i915_dev_set_domain calls i915_gem_flush to
 - *            emit an MI_FLUSH and drm_agp_chipset_flush
 - *    5. Unmapped from GTT
 - *            i915_gem_object_unbind calls set_domain (CPU, CPU)
 - *            flush_domains and invalidate_domains end up both zero
 - *            so no flushing/invalidating happens
 - *    6. Freed
 - *            yay, done
 - *
 - * Case 2: The shared render buffer
 - *
 - *    1. Allocated
 - *    2. Mapped to GTT
 - *    3. Read/written by GPU
 - *    4. set_domain to (CPU,CPU)
 - *    5. Read/written by CPU
 - *    6. Read/written by GPU
 - *
 - *    1. Allocated
 - *            Same as last example, (CPU, CPU)
 - *    2. Mapped to GTT
 - *            Nothing changes (assertions find that it is not in the GPU)
 - *    3. Read/written by GPU
 - *            execbuffer calls set_domain (RENDER, RENDER)
 - *            flush_domains gets CPU
 - *            invalidate_domains gets GPU
 - *            clflush (obj)
 - *            MI_FLUSH and drm_agp_chipset_flush
 - *    4. set_domain (CPU, CPU)
 - *            flush_domains gets GPU
 - *            invalidate_domains gets CPU
 - *            wait_rendering (obj) to make sure all drawing is complete.
 - *            This will include an MI_FLUSH to get the data from GPU
 - *            to memory
 - *            clflush (obj) to invalidate the CPU cache
 - *            Another MI_FLUSH in i915_gem_flush (eliminate this somehow?)
 - *    5. Read/written by CPU
 - *            cache lines are loaded and dirtied
 - *    6. Read written by GPU
 - *            Same as last GPU access
 - *
 - * Case 3: The constant buffer
 - *
 - *    1. Allocated
 - *    2. Written by CPU
 - *    3. Read by GPU
 - *    4. Updated (written) by CPU again
 - *    5. Read by GPU
 - *
 - *    1. Allocated
 - *            (CPU, CPU)
 - *    2. Written by CPU
 - *            (CPU, CPU)
 - *    3. Read by GPU
 - *            (CPU+RENDER, 0)
 - *            flush_domains = CPU
 - *            invalidate_domains = RENDER
 - *            clflush (obj)
 - *            MI_FLUSH
 - *            drm_agp_chipset_flush
 - *    4. Updated (written) by CPU again
 - *            (CPU, CPU)
 - *            flush_domains = 0 (no previous write domain)
 - *            invalidate_domains = 0 (no new read domains)
 - *    5. Read by GPU
 - *            (CPU+RENDER, 0)
 - *            flush_domains = CPU
 - *            invalidate_domains = RENDER
 - *            clflush (obj)
 - *            MI_FLUSH
 - *            drm_agp_chipset_flush
 - */
 -static void
 -i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj,
 -                                struct intel_ring_buffer *ring,
 -                                struct change_domains *cd)
 -{
 -      uint32_t invalidate_domains = 0, flush_domains = 0;
 -
 -      /*
 -       * If the object isn't moving to a new write domain,
 -       * let the object stay in multiple read domains
 -       */
 -      if (obj->base.pending_write_domain == 0)
 -              obj->base.pending_read_domains |= obj->base.read_domains;
 -
 -      /*
 -       * Flush the current write domain if
 -       * the new read domains don't match. Invalidate
 -       * any read domains which differ from the old
 -       * write domain
 -       */
 -      if (obj->base.write_domain &&
 -          (((obj->base.write_domain != obj->base.pending_read_domains ||
 -             obj->ring != ring)) ||
 -           (obj->fenced_gpu_access && !obj->pending_fenced_gpu_access))) {
 -              flush_domains |= obj->base.write_domain;
 -              invalidate_domains |=
 -                      obj->base.pending_read_domains & ~obj->base.write_domain;
 -      }
 -      /*
 -       * Invalidate any read caches which may have
 -       * stale data. That is, any new read domains.
 -       */
 -      invalidate_domains |= obj->base.pending_read_domains & ~obj->base.read_domains;
 -      if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU)
 -              i915_gem_clflush_object(obj);
 -
 -      if (obj->base.pending_write_domain)
 -              cd->flips |= atomic_read(&obj->pending_flip);
 -
 -      /* The actual obj->write_domain will be updated with
 -       * pending_write_domain after we emit the accumulated flush for all
 -       * of our domain changes in execbuffers (which clears objects'
 -       * write_domains).  So if we have a current write domain that we
 -       * aren't changing, set pending_write_domain to that.
 -       */
 -      if (flush_domains == 0 && obj->base.pending_write_domain == 0)
 -              obj->base.pending_write_domain = obj->base.write_domain;
 -
 -      cd->invalidate_domains |= invalidate_domains;
 -      cd->flush_domains |= flush_domains;
 -      if (flush_domains & I915_GEM_GPU_DOMAINS)
 -              cd->flush_rings |= intel_ring_flag(obj->ring);
 -      if (invalidate_domains & I915_GEM_GPU_DOMAINS)
 -              cd->flush_rings |= intel_ring_flag(ring);
 -}
 -
  struct eb_objects {
        int and;
        struct hlist_head buckets[0];
@@@ -117,6 -291,16 +117,16 @@@ i915_gem_execbuffer_relocate_entry(stru
        target_i915_obj = to_intel_bo(target_obj);
        target_offset = target_i915_obj->gtt_offset;
  
+       /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
+        * pipe_control writes because the gpu doesn't properly redirect them
+        * through the ppgtt for non_secure batchbuffers. */
+       if (unlikely(IS_GEN6(dev) &&
+           reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
+           !target_i915_obj->has_global_gtt_mapping)) {
+               i915_gem_gtt_bind_object(target_i915_obj,
+                                        target_i915_obj->cache_level);
+       }
        /* The target buffer should have appeared before us in the
         * exec_object list, so it should have a GTT space bound by now.
         */
                io_mapping_unmap_atomic(reloc_page);
        }
  
-       /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
-        * pipe_control writes because the gpu doesn't properly redirect them
-        * through the ppgtt for non_secure batchbuffers. */
-       if (unlikely(IS_GEN6(dev) &&
-           reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
-           !target_i915_obj->has_global_gtt_mapping)) {
-               i915_gem_gtt_bind_object(target_i915_obj,
-                                        target_i915_obj->cache_level);
-       }
        /* and update the user's relocation entry */
        reloc->presumed_offset = target_offset;
  
@@@ -413,7 -587,6 +413,7 @@@ i915_gem_execbuffer_reserve(struct inte
  
                obj->base.pending_read_domains = 0;
                obj->base.pending_write_domain = 0;
 +              obj->pending_fenced_gpu_access = false;
        }
        list_splice(&ordered_objects, objects);
  
@@@ -637,6 -810,18 +637,6 @@@ err
        return ret;
  }
  
 -static void
 -i915_gem_execbuffer_flush(struct drm_device *dev,
 -                        uint32_t invalidate_domains,
 -                        uint32_t flush_domains)
 -{
 -      if (flush_domains & I915_GEM_DOMAIN_CPU)
 -              intel_gtt_chipset_flush();
 -
 -      if (flush_domains & I915_GEM_DOMAIN_GTT)
 -              wmb();
 -}
 -
  static int
  i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips)
  {
        return 0;
  }
  
 -
  static int
  i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
                                struct list_head *objects)
  {
        struct drm_i915_gem_object *obj;
 -      struct change_domains cd;
 +      uint32_t flush_domains = 0;
 +      uint32_t flips = 0;
        int ret;
  
 -      memset(&cd, 0, sizeof(cd));
 -      list_for_each_entry(obj, objects, exec_list)
 -              i915_gem_object_set_to_gpu_domain(obj, ring, &cd);
 -
 -      if (cd.invalidate_domains | cd.flush_domains) {
 -              i915_gem_execbuffer_flush(ring->dev,
 -                                        cd.invalidate_domains,
 -                                        cd.flush_domains);
 -      }
 -
 -      if (cd.flips) {
 -              ret = i915_gem_execbuffer_wait_for_flips(ring, cd.flips);
 +      list_for_each_entry(obj, objects, exec_list) {
 +              ret = i915_gem_object_sync(obj, ring);
                if (ret)
                        return ret;
 +
 +              if (obj->base.write_domain & I915_GEM_DOMAIN_CPU)
 +                      i915_gem_clflush_object(obj);
 +
 +              if (obj->base.pending_write_domain)
 +                      flips |= atomic_read(&obj->pending_flip);
 +
 +              flush_domains |= obj->base.write_domain;
        }
  
 -      list_for_each_entry(obj, objects, exec_list) {
 -              ret = i915_gem_object_sync(obj, ring);
 +      if (flips) {
 +              ret = i915_gem_execbuffer_wait_for_flips(ring, flips);
                if (ret)
                        return ret;
        }
  
 +      if (flush_domains & I915_GEM_DOMAIN_CPU)
 +              intel_gtt_chipset_flush();
 +
 +      if (flush_domains & I915_GEM_DOMAIN_GTT)
 +              wmb();
 +
        /* Unconditionally invalidate gpu caches and ensure that we do flush
         * any residual writes from the previous batch.
         */
 -      ret = i915_gem_flush_ring(ring,
 -                                I915_GEM_GPU_DOMAINS,
 -                                ring->gpu_caches_dirty ? I915_GEM_GPU_DOMAINS : 0);
 -      if (ret)
 -              return ret;
 -
 -      ring->gpu_caches_dirty = false;
 -      return 0;
 +      return intel_ring_invalidate_all_caches(ring);
  }
  
  static bool
@@@ -755,8 -943,9 +755,8 @@@ i915_gem_execbuffer_move_to_active(stru
        struct drm_i915_gem_object *obj;
  
        list_for_each_entry(obj, objects, exec_list) {
 -                u32 old_read = obj->base.read_domains;
 -                u32 old_write = obj->base.write_domain;
 -
 +              u32 old_read = obj->base.read_domains;
 +              u32 old_write = obj->base.write_domain;
  
                obj->base.read_domains = obj->base.pending_read_domains;
                obj->base.write_domain = obj->base.pending_write_domain;
                i915_gem_object_move_to_active(obj, ring, seqno);
                if (obj->base.write_domain) {
                        obj->dirty = 1;
 -                      obj->pending_gpu_write = true;
 -                      list_move_tail(&obj->gpu_write_list,
 -                                     &ring->gpu_write_list);
 +                      obj->last_write_seqno = seqno;
                        if (obj->pin_count) /* check for potential scanout */
 -                              intel_mark_busy(ring->dev, obj);
 +                              intel_mark_fb_busy(obj);
                }
  
                trace_i915_gem_object_change_domain(obj, old_read, old_write);
        }
 -
 -      intel_mark_busy(ring->dev, NULL);
  }
  
  static void
@@@ -779,11 -972,16 +779,11 @@@ i915_gem_execbuffer_retire_commands(str
                                    struct drm_file *file,
                                    struct intel_ring_buffer *ring)
  {
 -      struct drm_i915_gem_request *request;
 -
        /* Unconditionally force add_request to emit a full flush. */
        ring->gpu_caches_dirty = true;
  
        /* Add a breadcrumb for the completion of the batch buffer */
 -      request = kzalloc(sizeof(*request), GFP_KERNEL);
 -      if (request == NULL || i915_add_request(ring, file, request)) {
 -              kfree(request);
 -      }
 +      (void)i915_add_request(ring, file, NULL);
  }
  
  static int
index 4584f7f0063ee56a17c180fd23eef56349e906a4,ee9b68f6bc36c938213931065c50bb5d60836b23..3b3b731a17c3418d132c4b0943ca7bbf4f305796
@@@ -361,7 -361,8 +361,8 @@@ int i915_gem_gtt_prepare_object(struct 
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
  
-       if (dev_priv->mm.gtt->needs_dmar)
+       /* don't map imported dma buf objects */
+       if (dev_priv->mm.gtt->needs_dmar && !obj->sg_table)
                return intel_gtt_map_memory(obj->pages,
                                            obj->base.size >> PAGE_SHIFT,
                                            &obj->sg_list,
@@@ -422,23 -423,6 +423,23 @@@ void i915_gem_gtt_finish_object(struct 
        undo_idling(dev_priv, interruptible);
  }
  
 +static void i915_gtt_color_adjust(struct drm_mm_node *node,
 +                                unsigned long color,
 +                                unsigned long *start,
 +                                unsigned long *end)
 +{
 +      if (node->color != color)
 +              *start += 4096;
 +
 +      if (!list_empty(&node->node_list)) {
 +              node = list_entry(node->node_list.next,
 +                                struct drm_mm_node,
 +                                node_list);
 +              if (node->allocated && node->color != color)
 +                      *end -= 4096;
 +      }
 +}
 +
  void i915_gem_init_global_gtt(struct drm_device *dev,
                              unsigned long start,
                              unsigned long mappable_end,
  
        /* Substract the guard page ... */
        drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE);
 +      if (!HAS_LLC(dev))
 +              dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust;
  
        dev_priv->mm.gtt_start = start;
        dev_priv->mm.gtt_mappable_end = mappable_end;
index 0c37101934f81c5b40373c4be7c867b7b9ff4fcb,8a3828528b9ddfa9678e7bfbf015bd7acdfdc29d..a61b41a8c607878cb82d881d8645d12dba9805b6
@@@ -296,21 -296,11 +296,21 @@@ static void i915_hotplug_work_func(stru
        drm_helper_hpd_irq_event(dev);
  }
  
 -static void i915_handle_rps_change(struct drm_device *dev)
 +/* defined intel_pm.c */
 +extern spinlock_t mchdev_lock;
 +
 +static void ironlake_handle_rps_change(struct drm_device *dev)
  {
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 busy_up, busy_down, max_avg, min_avg;
 -      u8 new_delay = dev_priv->cur_delay;
 +      u8 new_delay;
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&mchdev_lock, flags);
 +
 +      I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
 +
 +      new_delay = dev_priv->cur_delay;
  
        I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG);
        busy_up = I915_READ(RCPREVBSYTUPAVG);
        if (ironlake_set_drps(dev, new_delay))
                dev_priv->cur_delay = new_delay;
  
 +      spin_unlock_irqrestore(&mchdev_lock, flags);
 +
        return;
  }
  
@@@ -347,7 -335,7 +347,7 @@@ static void notify_ring(struct drm_devi
        if (ring->obj == NULL)
                return;
  
 -      trace_i915_gem_request_complete(ring, ring->get_seqno(ring));
 +      trace_i915_gem_request_complete(ring, ring->get_seqno(ring, false));
  
        wake_up_all(&ring->irq_queue);
        if (i915_enable_hangcheck) {
  static void gen6_pm_rps_work(struct work_struct *work)
  {
        drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
 -                                                  rps_work);
 +                                                  rps.work);
        u32 pm_iir, pm_imr;
        u8 new_delay;
  
 -      spin_lock_irq(&dev_priv->rps_lock);
 -      pm_iir = dev_priv->pm_iir;
 -      dev_priv->pm_iir = 0;
 +      spin_lock_irq(&dev_priv->rps.lock);
 +      pm_iir = dev_priv->rps.pm_iir;
 +      dev_priv->rps.pm_iir = 0;
        pm_imr = I915_READ(GEN6_PMIMR);
        I915_WRITE(GEN6_PMIMR, 0);
 -      spin_unlock_irq(&dev_priv->rps_lock);
 +      spin_unlock_irq(&dev_priv->rps.lock);
  
        if ((pm_iir & GEN6_PM_DEFERRED_EVENTS) == 0)
                return;
        mutex_lock(&dev_priv->dev->struct_mutex);
  
        if (pm_iir & GEN6_PM_RP_UP_THRESHOLD)
 -              new_delay = dev_priv->cur_delay + 1;
 +              new_delay = dev_priv->rps.cur_delay + 1;
        else
 -              new_delay = dev_priv->cur_delay - 1;
 +              new_delay = dev_priv->rps.cur_delay - 1;
  
        gen6_set_rps(dev_priv->dev, new_delay);
  
@@@ -456,7 -444,7 +456,7 @@@ static void ivybridge_handle_parity_err
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long flags;
  
 -      if (!IS_IVYBRIDGE(dev))
 +      if (!HAS_L3_GPU_CACHE(dev))
                return;
  
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
@@@ -500,20 -488,19 +500,19 @@@ static void gen6_queue_rps_work(struct 
         * IIR bits should never already be set because IMR should
         * prevent an interrupt from being shown in IIR. The warning
         * displays a case where we've unsafely cleared
 -       * dev_priv->pm_iir. Although missing an interrupt of the same
 +       * dev_priv->rps.pm_iir. Although missing an interrupt of the same
         * type is not a problem, it displays a problem in the logic.
         *
 -       * The mask bit in IMR is cleared by rps_work.
 +       * The mask bit in IMR is cleared by dev_priv->rps.work.
         */
  
 -      spin_lock_irqsave(&dev_priv->rps_lock, flags);
 -      dev_priv->pm_iir |= pm_iir;
 -      I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
 +      spin_lock_irqsave(&dev_priv->rps.lock, flags);
-       WARN(dev_priv->rps.pm_iir & pm_iir, "Missed a PM interrupt\n");
 +      dev_priv->rps.pm_iir |= pm_iir;
 +      I915_WRITE(GEN6_PMIMR, dev_priv->rps.pm_iir);
        POSTING_READ(GEN6_PMIMR);
 -      spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
 +      spin_unlock_irqrestore(&dev_priv->rps.lock, flags);
  
 -      queue_work(dev_priv->wq, &dev_priv->rps_work);
 +      queue_work(dev_priv->wq, &dev_priv->rps.work);
  }
  
  static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
@@@ -806,8 -793,10 +805,8 @@@ static irqreturn_t ironlake_irq_handler
                        ibx_irq_handler(dev, pch_iir);
        }
  
 -      if (de_iir & DE_PCU_EVENT) {
 -              I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
 -              i915_handle_rps_change(dev);
 -      }
 +      if (IS_GEN5(dev) &&  de_iir & DE_PCU_EVENT)
 +              ironlake_handle_rps_change(dev);
  
        if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS)
                gen6_queue_rps_work(dev_priv, pm_iir);
@@@ -960,8 -949,7 +959,8 @@@ static void capture_bo(struct drm_i915_
  {
        err->size = obj->base.size;
        err->name = obj->base.name;
 -      err->seqno = obj->last_rendering_seqno;
 +      err->rseqno = obj->last_read_seqno;
 +      err->wseqno = obj->last_write_seqno;
        err->gtt_offset = obj->gtt_offset;
        err->read_domains = obj->base.read_domains;
        err->write_domain = obj->base.write_domain;
@@@ -1051,12 -1039,12 +1050,12 @@@ i915_error_first_batchbuffer(struct drm
        if (!ring->get_seqno)
                return NULL;
  
 -      seqno = ring->get_seqno(ring);
 +      seqno = ring->get_seqno(ring, false);
        list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
                if (obj->ring != ring)
                        continue;
  
 -              if (i915_seqno_passed(seqno, obj->last_rendering_seqno))
 +              if (i915_seqno_passed(seqno, obj->last_read_seqno))
                        continue;
  
                if ((obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) == 0)
@@@ -1105,7 -1093,7 +1104,7 @@@ static void i915_record_ring_state(stru
  
        error->waiting[ring->id] = waitqueue_active(&ring->irq_queue);
        error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base));
 -      error->seqno[ring->id] = ring->get_seqno(ring);
 +      error->seqno[ring->id] = ring->get_seqno(ring, false);
        error->acthd[ring->id] = intel_ring_get_active_head(ring);
        error->head[ring->id] = I915_READ_HEAD(ring);
        error->tail[ring->id] = I915_READ_TAIL(ring);
@@@ -1602,8 -1590,7 +1601,8 @@@ ring_last_seqno(struct intel_ring_buffe
  static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
  {
        if (list_empty(&ring->request_list) ||
 -          i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) {
 +          i915_seqno_passed(ring->get_seqno(ring, false),
 +                            ring_last_seqno(ring))) {
                /* Issue a wake-up to catch stuck h/w. */
                if (waitqueue_active(&ring->irq_queue)) {
                        DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
@@@ -2660,7 -2647,7 +2659,7 @@@ void intel_irq_init(struct drm_device *
  
        INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
        INIT_WORK(&dev_priv->error_work, i915_error_work_func);
 -      INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
 +      INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
        INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work);
  
        dev->driver->get_vblank_counter = i915_get_vblank_counter;
index 77a97bfabb6bcd8004a021e573f33013b21665f6,7631807a27886e2483d77de1046461350f9c7d15..c5ee7ee3b17ed64c52f5e6cfd771f154b05631ac
@@@ -32,6 -32,7 +32,7 @@@
  #include "intel_drv.h"
  #include "i915_drv.h"
  
+ #ifdef CONFIG_PM
  static u32 calc_residency(struct drm_device *dev, const u32 reg)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@@ -212,7 -213,7 +213,7 @@@ void i915_setup_sysfs(struct drm_devic
                        DRM_ERROR("RC6 residency sysfs setup failed\n");
        }
  
 -      if (IS_IVYBRIDGE(dev)) {
 +      if (HAS_L3_GPU_CACHE(dev)) {
                ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs);
                if (ret)
                        DRM_ERROR("l3 parity sysfs setup failed\n");
@@@ -224,3 -225,14 +225,14 @@@ void i915_teardown_sysfs(struct drm_dev
        device_remove_bin_file(&dev->primary->kdev,  &dpf_attrs);
        sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
  }
+ #else
+ void i915_setup_sysfs(struct drm_device *dev)
+ {
+       return;
+ }
+ void i915_teardown_sysfs(struct drm_device *dev)
+ {
+       return;
+ }
+ #endif /* CONFIG_PM */
index e3afe9688905fe493e6d828aececd70d6fbfdca1,a69a3d0d3acf6c7bc81119342aa830b41c047025..a9ab1aff2c77a21d8714f3bc0b441bf1a3fb716f
@@@ -869,6 -869,7 +869,7 @@@ intel_vlv_find_best_pll(const intel_lim
        unsigned long bestppm, ppm, absppm;
        int dotclk, flag;
  
+       flag = 0;
        dotclk = target * 1000;
        bestppm = 1000000;
        ppm = absppm = 0;
@@@ -1428,10 -1429,8 +1429,10 @@@ static void assert_pch_ports_disabled(s
   * protect mechanism may be enabled.
   *
   * Note!  This is for pre-ILK only.
 + *
 + * Unfortunately needed by dvo_ns2501 since the dvo depends on it running.
   */
 -static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
 +void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
  {
        int reg;
        u32 val;
@@@ -2837,13 -2836,13 +2838,13 @@@ static void intel_crtc_wait_for_pending
  static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
 -      struct intel_encoder *encoder;
 +      struct intel_encoder *intel_encoder;
  
        /*
         * If there's a non-PCH eDP on this crtc, it must be DP_A, and that
         * must be driven by its own crtc; no sharing is possible.
         */
 -      for_each_encoder_on_crtc(dev, crtc, encoder) {
 +      for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
  
                /* On Haswell, LPT PCH handles the VGA connection via FDI, and Haswell
                 * CPU handles all others */
                        /* It is still unclear how this will work on PPT, so throw up a warning */
                        WARN_ON(!HAS_PCH_LPT(dev));
  
 -                      if (encoder->type == DRM_MODE_ENCODER_DAC) {
 +                      if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
                                DRM_DEBUG_KMS("Haswell detected DAC encoder, assuming is PCH\n");
                                return true;
                        } else {
                                DRM_DEBUG_KMS("Haswell detected encoder %d, assuming is CPU\n",
 -                                              encoder->type);
 +                                            intel_encoder->type);
                                return false;
                        }
                }
  
 -              switch (encoder->type) {
 +              switch (intel_encoder->type) {
                case INTEL_OUTPUT_EDP:
 -                      if (!intel_encoder_is_pch_edp(&encoder->base))
 +                      if (!intel_encoder_is_pch_edp(&intel_encoder->base))
                                return false;
                        continue;
                }
@@@ -3755,17 -3754,6 +3756,6 @@@ static bool intel_choose_pipe_bpp_dithe
                        continue;
                }
  
-               if (intel_encoder->type == INTEL_OUTPUT_EDP) {
-                       /* Use VBT settings if we have an eDP panel */
-                       unsigned int edp_bpc = dev_priv->edp.bpp / 3;
-                       if (edp_bpc < display_bpc) {
-                               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
-                               display_bpc = edp_bpc;
-                       }
-                       continue;
-               }
                /* Not one of the known troublemakers, check the EDID */
                list_for_each_entry(connector, &dev->mode_config.connector_list,
                                    head) {
@@@ -5860,6 -5848,46 +5850,6 @@@ struct drm_display_mode *intel_crtc_mod
        return mode;
  }
  
 -#define GPU_IDLE_TIMEOUT 500 /* ms */
 -
 -/* When this timer fires, we've been idle for awhile */
 -static void intel_gpu_idle_timer(unsigned long arg)
 -{
 -      struct drm_device *dev = (struct drm_device *)arg;
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -
 -      if (!list_empty(&dev_priv->mm.active_list)) {
 -              /* Still processing requests, so just re-arm the timer. */
 -              mod_timer(&dev_priv->idle_timer, jiffies +
 -                        msecs_to_jiffies(GPU_IDLE_TIMEOUT));
 -              return;
 -      }
 -
 -      dev_priv->busy = false;
 -      queue_work(dev_priv->wq, &dev_priv->idle_work);
 -}
 -
 -#define CRTC_IDLE_TIMEOUT 1000 /* ms */
 -
 -static void intel_crtc_idle_timer(unsigned long arg)
 -{
 -      struct intel_crtc *intel_crtc = (struct intel_crtc *)arg;
 -      struct drm_crtc *crtc = &intel_crtc->base;
 -      drm_i915_private_t *dev_priv = crtc->dev->dev_private;
 -      struct intel_framebuffer *intel_fb;
 -
 -      intel_fb = to_intel_framebuffer(crtc->fb);
 -      if (intel_fb && intel_fb->obj->active) {
 -              /* The framebuffer is still being accessed by the GPU. */
 -              mod_timer(&intel_crtc->idle_timer, jiffies +
 -                        msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
 -              return;
 -      }
 -
 -      intel_crtc->busy = false;
 -      queue_work(dev_priv->wq, &dev_priv->idle_work);
 -}
 -
  static void intel_increase_pllclock(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
                if (dpll & DISPLAY_RATE_SELECT_FPA1)
                        DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
        }
 -
 -      /* Schedule downclock */
 -      mod_timer(&intel_crtc->idle_timer, jiffies +
 -                msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
  }
  
  static void intel_decrease_pllclock(struct drm_crtc *crtc)
  
  }
  
 -/**
 - * intel_idle_update - adjust clocks for idleness
 - * @work: work struct
 - *
 - * Either the GPU or display (or both) went idle.  Check the busy status
 - * here and adjust the CRTC and GPU clocks as necessary.
 - */
 -static void intel_idle_update(struct work_struct *work)
 +void intel_mark_busy(struct drm_device *dev)
 +{
 +      i915_update_gfx_val(dev->dev_private);
 +}
 +
 +void intel_mark_idle(struct drm_device *dev)
  {
 -      drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
 -                                                  idle_work);
 -      struct drm_device *dev = dev_priv->dev;
 +}
 +
 +void intel_mark_fb_busy(struct drm_i915_gem_object *obj)
 +{
 +      struct drm_device *dev = obj->base.dev;
        struct drm_crtc *crtc;
 -      struct intel_crtc *intel_crtc;
  
        if (!i915_powersave)
                return;
  
 -      mutex_lock(&dev->struct_mutex);
 -
 -      i915_update_gfx_val(dev_priv);
 -
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 -              /* Skip inactive CRTCs */
                if (!crtc->fb)
                        continue;
  
 -              intel_crtc = to_intel_crtc(crtc);
 -              if (!intel_crtc->busy)
 -                      intel_decrease_pllclock(crtc);
 +              if (to_intel_framebuffer(crtc->fb)->obj == obj)
 +                      intel_increase_pllclock(crtc);
        }
 -
 -
 -      mutex_unlock(&dev->struct_mutex);
  }
  
 -/**
 - * intel_mark_busy - mark the GPU and possibly the display busy
 - * @dev: drm device
 - * @obj: object we're operating on
 - *
 - * Callers can use this function to indicate that the GPU is busy processing
 - * commands.  If @obj matches one of the CRTC objects (i.e. it's a scanout
 - * buffer), we'll also mark the display as busy, so we know to increase its
 - * clock frequency.
 - */
 -void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
 +void intel_mark_fb_idle(struct drm_i915_gem_object *obj)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      struct drm_crtc *crtc = NULL;
 -      struct intel_framebuffer *intel_fb;
 -      struct intel_crtc *intel_crtc;
 -
 -      if (!drm_core_check_feature(dev, DRIVER_MODESET))
 -              return;
 -
 -      if (!dev_priv->busy) {
 -              intel_sanitize_pm(dev);
 -              dev_priv->busy = true;
 -      } else
 -              mod_timer(&dev_priv->idle_timer, jiffies +
 -                        msecs_to_jiffies(GPU_IDLE_TIMEOUT));
 +      struct drm_device *dev = obj->base.dev;
 +      struct drm_crtc *crtc;
  
 -      if (obj == NULL)
 +      if (!i915_powersave)
                return;
  
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                if (!crtc->fb)
                        continue;
  
 -              intel_crtc = to_intel_crtc(crtc);
 -              intel_fb = to_intel_framebuffer(crtc->fb);
 -              if (intel_fb->obj == obj) {
 -                      if (!intel_crtc->busy) {
 -                              /* Non-busy -> busy, upclock */
 -                              intel_increase_pllclock(crtc);
 -                              intel_crtc->busy = true;
 -                      } else {
 -                              /* Busy -> busy, put off timer */
 -                              mod_timer(&intel_crtc->idle_timer, jiffies +
 -                                        msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
 -                      }
 -              }
 +              if (to_intel_framebuffer(crtc->fb)->obj == obj)
 +                      intel_decrease_pllclock(crtc);
        }
  }
  
@@@ -6317,7 -6392,7 +6307,7 @@@ static int intel_gen7_queue_flip(struc
        default:
                WARN_ONCE(1, "unknown plane in flip command\n");
                ret = -ENODEV;
 -              goto err;
 +              goto err_unpin;
        }
  
        ret = intel_ring_begin(ring, 4);
@@@ -6425,7 -6500,7 +6415,7 @@@ static int intel_crtc_page_flip(struct 
                goto cleanup_pending;
  
        intel_disable_fbc(dev);
 -      intel_mark_busy(dev, obj);
 +      intel_mark_fb_busy(obj);
        mutex_unlock(&dev->struct_mutex);
  
        trace_i915_flip_request(intel_crtc->plane, obj);
@@@ -6591,6 -6666,11 +6581,6 @@@ static void intel_crtc_init(struct drm_
        }
  
        drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 -
 -      intel_crtc->busy = false;
 -
 -      setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
 -                  (unsigned long)intel_crtc);
  }
  
  int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
        return 0;
  }
  
 -static int intel_encoder_clones(struct drm_device *dev, int type_mask)
 +static int intel_encoder_clones(struct intel_encoder *encoder)
  {
 -      struct intel_encoder *encoder;
 +      struct drm_device *dev = encoder->base.dev;
 +      struct intel_encoder *source_encoder;
        int index_mask = 0;
        int entry = 0;
  
 -      list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 -              if (type_mask & encoder->clone_mask)
 +      list_for_each_entry(source_encoder,
 +                          &dev->mode_config.encoder_list, base.head) {
 +
 +              if (encoder == source_encoder)
                        index_mask |= (1 << entry);
 +
 +              /* Intel hw has only one MUX where enocoders could be cloned. */
 +              if (encoder->cloneable && source_encoder->cloneable)
 +                      index_mask |= (1 << entry);
 +
                entry++;
        }
  
@@@ -6674,10 -6746,10 +6664,10 @@@ static void intel_setup_outputs(struct 
                dpd_is_edp = intel_dpd_is_edp(dev);
  
                if (has_edp_a(dev))
 -                      intel_dp_init(dev, DP_A);
 +                      intel_dp_init(dev, DP_A, PORT_A);
  
                if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
 -                      intel_dp_init(dev, PCH_DP_D);
 +                      intel_dp_init(dev, PCH_DP_D, PORT_D);
        }
  
        intel_crt_init(dev);
                        /* PCH SDVOB multiplex with HDMIB */
                        found = intel_sdvo_init(dev, PCH_SDVOB, true);
                        if (!found)
 -                              intel_hdmi_init(dev, HDMIB);
 +                              intel_hdmi_init(dev, HDMIB, PORT_B);
                        if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
 -                              intel_dp_init(dev, PCH_DP_B);
 +                              intel_dp_init(dev, PCH_DP_B, PORT_B);
                }
  
                if (I915_READ(HDMIC) & PORT_DETECTED)
 -                      intel_hdmi_init(dev, HDMIC);
 +                      intel_hdmi_init(dev, HDMIC, PORT_C);
  
                if (!dpd_is_edp && I915_READ(HDMID) & PORT_DETECTED)
 -                      intel_hdmi_init(dev, HDMID);
 +                      intel_hdmi_init(dev, HDMID, PORT_D);
  
                if (I915_READ(PCH_DP_C) & DP_DETECTED)
 -                      intel_dp_init(dev, PCH_DP_C);
 +                      intel_dp_init(dev, PCH_DP_C, PORT_C);
  
                if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
 -                      intel_dp_init(dev, PCH_DP_D);
 +                      intel_dp_init(dev, PCH_DP_D, PORT_D);
        } else if (IS_VALLEYVIEW(dev)) {
                int found;
  
                        /* SDVOB multiplex with HDMIB */
                        found = intel_sdvo_init(dev, SDVOB, true);
                        if (!found)
 -                              intel_hdmi_init(dev, SDVOB);
 +                              intel_hdmi_init(dev, SDVOB, PORT_B);
                        if (!found && (I915_READ(DP_B) & DP_DETECTED))
 -                              intel_dp_init(dev, DP_B);
 +                              intel_dp_init(dev, DP_B, PORT_B);
                }
  
                if (I915_READ(SDVOC) & PORT_DETECTED)
 -                      intel_hdmi_init(dev, SDVOC);
 +                      intel_hdmi_init(dev, SDVOC, PORT_C);
  
                /* Shares lanes with HDMI on SDVOC */
                if (I915_READ(DP_C) & DP_DETECTED)
 -                      intel_dp_init(dev, DP_C);
 +                      intel_dp_init(dev, DP_C, PORT_C);
        } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
                bool found = false;
  
                        found = intel_sdvo_init(dev, SDVOB, true);
                        if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
                                DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
 -                              intel_hdmi_init(dev, SDVOB);
 +                              intel_hdmi_init(dev, SDVOB, PORT_B);
                        }
  
                        if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
                                DRM_DEBUG_KMS("probing DP_B\n");
 -                              intel_dp_init(dev, DP_B);
 +                              intel_dp_init(dev, DP_B, PORT_B);
                        }
                }
  
  
                        if (SUPPORTS_INTEGRATED_HDMI(dev)) {
                                DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
 -                              intel_hdmi_init(dev, SDVOC);
 +                              intel_hdmi_init(dev, SDVOC, PORT_C);
                        }
                        if (SUPPORTS_INTEGRATED_DP(dev)) {
                                DRM_DEBUG_KMS("probing DP_C\n");
 -                              intel_dp_init(dev, DP_C);
 +                              intel_dp_init(dev, DP_C, PORT_C);
                        }
                }
  
                if (SUPPORTS_INTEGRATED_DP(dev) &&
                    (I915_READ(DP_D) & DP_DETECTED)) {
                        DRM_DEBUG_KMS("probing DP_D\n");
 -                      intel_dp_init(dev, DP_D);
 +                      intel_dp_init(dev, DP_D, PORT_D);
                }
        } else if (IS_GEN2(dev))
                intel_dvo_init(dev);
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
                encoder->base.possible_crtcs = encoder->crtc_mask;
                encoder->base.possible_clones =
 -                      intel_encoder_clones(dev, encoder->clone_mask);
 +                      intel_encoder_clones(encoder);
        }
  
        /* disable all the possible outputs/crtcs before entering KMS mode */
@@@ -7093,19 -7165,6 +7083,6 @@@ static void i915_disable_vga(struct drm
        POSTING_READ(vga_reg);
  }
  
- static void ivb_pch_pwm_override(struct drm_device *dev)
- {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       /*
-        * IVB has CPU eDP backlight regs too, set things up to let the
-        * PCH regs control the backlight
-        */
-       I915_WRITE(BLC_PWM_CPU_CTL2, BLM_PWM_ENABLE);
-       I915_WRITE(BLC_PWM_CPU_CTL, 0);
-       I915_WRITE(BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE | BLM_PCH_OVERRIDE_ENABLE);
- }
  void intel_modeset_init_hw(struct drm_device *dev)
  {
        /* We attempt to init the necessary power wells early in the initialization
        mutex_lock(&dev->struct_mutex);
        intel_enable_gt_powersave(dev);
        mutex_unlock(&dev->struct_mutex);
-       if (IS_IVYBRIDGE(dev))
-               ivb_pch_pwm_override(dev);
  }
  
  void intel_modeset_init(struct drm_device *dev)
        /* Just disable it once at startup */
        i915_disable_vga(dev);
        intel_setup_outputs(dev);
 -
 -      INIT_WORK(&dev_priv->idle_work, intel_idle_update);
 -      setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
 -                  (unsigned long)dev);
  }
  
  void intel_modeset_gem_init(struct drm_device *dev)
@@@ -7218,11 -7278,19 +7192,11 @@@ void intel_modeset_cleanup(struct drm_d
         * enqueue unpin/hotplug work. */
        drm_irq_uninstall(dev);
        cancel_work_sync(&dev_priv->hotplug_work);
 -      cancel_work_sync(&dev_priv->rps_work);
 +      cancel_work_sync(&dev_priv->rps.work);
  
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
  
 -      /* Shut off idle work before the crtcs get freed. */
 -      list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 -              intel_crtc = to_intel_crtc(crtc);
 -              del_timer_sync(&intel_crtc->idle_timer);
 -      }
 -      del_timer_sync(&dev_priv->idle_timer);
 -      cancel_work_sync(&dev_priv->idle_work);
 -
        drm_mode_config_cleanup(dev);
  }
  
index ad90a499dab71492d65f7716c5190de38ca93190,a6c426afaa7aca46144f5a3710c0ea6f10a46b83..977d9d216c73b24284507c557626d7c5c7ecb4e2
  #include "intel_drv.h"
  #include "i915_drm.h"
  #include "i915_drv.h"
 -#include "drm_dp_helper.h"
  
 -#define DP_RECEIVER_CAP_SIZE  0xf
  #define DP_LINK_STATUS_SIZE   6
  #define DP_LINK_CHECK_TIMEOUT (10 * 1000)
  
 -#define DP_LINK_CONFIGURATION_SIZE    9
 -
 -struct intel_dp {
 -      struct intel_encoder base;
 -      uint32_t output_reg;
 -      uint32_t DP;
 -      uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
 -      bool has_audio;
 -      enum hdmi_force_audio force_audio;
 -      uint32_t color_range;
 -      int dpms_mode;
 -      uint8_t link_bw;
 -      uint8_t lane_count;
 -      uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
 -      struct i2c_adapter adapter;
 -      struct i2c_algo_dp_aux_data algo;
 -      bool is_pch_edp;
 -      uint8_t train_set[4];
 -      int panel_power_up_delay;
 -      int panel_power_down_delay;
 -      int panel_power_cycle_delay;
 -      int backlight_on_delay;
 -      int backlight_off_delay;
 -      struct drm_display_mode *panel_fixed_mode;  /* for eDP */
 -      struct delayed_work panel_vdd_work;
 -      bool want_panel_vdd;
 -      struct edid *edid; /* cached EDID for eDP */
 -      int edid_mode_count;
 -};
 -
  /**
   * is_edp - is the given port attached to an eDP panel (either CPU or PCH)
   * @intel_dp: DP struct
@@@ -1142,10 -1174,14 +1142,14 @@@ static void ironlake_edp_panel_off(stru
        WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
  
        pp = ironlake_get_pp_control(dev_priv);
-       pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+       /* 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 | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
  
+       intel_dp->want_panel_vdd = false;
        ironlake_wait_panel_off(intel_dp);
  }
  
@@@ -1255,11 -1291,9 +1259,9 @@@ static void intel_dp_prepare(struct drm
         * ensure that we have vdd while we switch off the panel. */
        ironlake_edp_panel_vdd_on(intel_dp);
        ironlake_edp_backlight_off(intel_dp);
-       ironlake_edp_panel_off(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+       ironlake_edp_panel_off(intel_dp);
        intel_dp_link_down(intel_dp);
-       ironlake_edp_panel_vdd_off(intel_dp, false);
  }
  
  static void intel_dp_commit(struct drm_encoder *encoder)
@@@ -1294,11 -1328,9 +1296,9 @@@ intel_dp_dpms(struct drm_encoder *encod
                /* Switching the panel off requires vdd. */
                ironlake_edp_panel_vdd_on(intel_dp);
                ironlake_edp_backlight_off(intel_dp);
-               ironlake_edp_panel_off(intel_dp);
                intel_dp_sink_dpms(intel_dp, mode);
+               ironlake_edp_panel_off(intel_dp);
                intel_dp_link_down(intel_dp);
-               ironlake_edp_panel_vdd_off(intel_dp, false);
  
                if (is_cpu_edp(intel_dp))
                        ironlake_edp_pll_off(encoder);
@@@ -1636,45 -1668,6 +1636,45 @@@ intel_dp_set_link_train(struct intel_d
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
  
 +      if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
 +              dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT;
 +
 +              switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
 +              case DP_TRAINING_PATTERN_DISABLE:
 +                      dp_reg_value |= DP_LINK_TRAIN_OFF_CPT;
 +                      break;
 +              case DP_TRAINING_PATTERN_1:
 +                      dp_reg_value |= DP_LINK_TRAIN_PAT_1_CPT;
 +                      break;
 +              case DP_TRAINING_PATTERN_2:
 +                      dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT;
 +                      break;
 +              case DP_TRAINING_PATTERN_3:
 +                      DRM_ERROR("DP training pattern 3 not supported\n");
 +                      dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT;
 +                      break;
 +              }
 +
 +      } else {
 +              dp_reg_value &= ~DP_LINK_TRAIN_MASK;
 +
 +              switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
 +              case DP_TRAINING_PATTERN_DISABLE:
 +                      dp_reg_value |= DP_LINK_TRAIN_OFF;
 +                      break;
 +              case DP_TRAINING_PATTERN_1:
 +                      dp_reg_value |= DP_LINK_TRAIN_PAT_1;
 +                      break;
 +              case DP_TRAINING_PATTERN_2:
 +                      dp_reg_value |= DP_LINK_TRAIN_PAT_2;
 +                      break;
 +              case DP_TRAINING_PATTERN_3:
 +                      DRM_ERROR("DP training pattern 3 not supported\n");
 +                      dp_reg_value |= DP_LINK_TRAIN_PAT_2;
 +                      break;
 +              }
 +      }
 +
        I915_WRITE(intel_dp->output_reg, dp_reg_value);
        POSTING_READ(intel_dp->output_reg);
  
                                    DP_TRAINING_PATTERN_SET,
                                    dp_train_pat);
  
 -      ret = intel_dp_aux_native_write(intel_dp,
 -                                      DP_TRAINING_LANE0_SET,
 -                                      intel_dp->train_set,
 -                                      intel_dp->lane_count);
 -      if (ret != intel_dp->lane_count)
 -              return false;
 +      if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) !=
 +          DP_TRAINING_PATTERN_DISABLE) {
 +              ret = intel_dp_aux_native_write(intel_dp,
 +                                              DP_TRAINING_LANE0_SET,
 +                                              intel_dp->train_set,
 +                                              intel_dp->lane_count);
 +              if (ret != intel_dp->lane_count)
 +                      return false;
 +      }
  
        return true;
  }
@@@ -1706,6 -1696,7 +1706,6 @@@ intel_dp_start_link_train(struct intel_
        uint8_t voltage;
        bool clock_recovery = false;
        int voltage_tries, loop_tries;
 -      u32 reg;
        uint32_t DP = intel_dp->DP;
  
        /*
  
        DP |= DP_PORT_EN;
  
 -      if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 -              DP &= ~DP_LINK_TRAIN_MASK_CPT;
 -      else
 -              DP &= ~DP_LINK_TRAIN_MASK;
        memset(intel_dp->train_set, 0, 4);
        voltage = 0xff;
        voltage_tries = 0;
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
  
 -              if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 -                      reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
 -              else
 -                      reg = DP | DP_LINK_TRAIN_PAT_1;
 -
 -              if (!intel_dp_set_link_train(intel_dp, reg,
 +              if (!intel_dp_set_link_train(intel_dp, DP,
                                             DP_TRAINING_PATTERN_1 |
                                             DP_LINK_SCRAMBLING_DISABLE))
                        break;
@@@ -1804,8 -1804,10 +1804,8 @@@ static voi
  intel_dp_complete_link_train(struct intel_dp *intel_dp)
  {
        struct drm_device *dev = intel_dp->base.base.dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
        bool channel_eq = false;
        int tries, cr_tries;
 -      u32 reg;
        uint32_t DP = intel_dp->DP;
  
        /* channel equalization */
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
  
 -              if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 -                      reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
 -              else
 -                      reg = DP | DP_LINK_TRAIN_PAT_2;
 -
                /* channel eq pattern */
 -              if (!intel_dp_set_link_train(intel_dp, reg,
 +              if (!intel_dp_set_link_train(intel_dp, DP,
                                             DP_TRAINING_PATTERN_2 |
                                             DP_LINK_SCRAMBLING_DISABLE))
                        break;
                ++tries;
        }
  
 -      if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 -              reg = DP | DP_LINK_TRAIN_OFF_CPT;
 -      else
 -              reg = DP | DP_LINK_TRAIN_OFF;
 -
 -      I915_WRITE(intel_dp->output_reg, reg);
 -      POSTING_READ(intel_dp->output_reg);
 -      intel_dp_aux_native_write_1(intel_dp,
 -                                  DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
 +      intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE);
  }
  
  static void
@@@ -2426,7 -2441,7 +2426,7 @@@ intel_dp_add_properties(struct intel_d
  }
  
  void
 -intel_dp_init(struct drm_device *dev, int output_reg)
 +intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_connector *connector;
                return;
  
        intel_dp->output_reg = output_reg;
 +      intel_dp->port = port;
        intel_dp->dpms_mode = -1;
  
        intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
  
        connector->polled = DRM_CONNECTOR_POLL_HPD;
  
 -      if (output_reg == DP_B || output_reg == PCH_DP_B)
 -              intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
 -      else if (output_reg == DP_C || output_reg == PCH_DP_C)
 -              intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
 -      else if (output_reg == DP_D || output_reg == PCH_DP_D)
 -              intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
 +      intel_encoder->cloneable = false;
  
 -      if (is_edp(intel_dp)) {
 -              intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
 -              INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
 -                                ironlake_panel_vdd_work);
 -      }
 +      INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
 +                        ironlake_panel_vdd_work);
  
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
  
        drm_sysfs_connector_add(connector);
  
        /* Set up the DDC bus. */
 -      switch (output_reg) {
 -              case DP_A:
 -                      name = "DPDDC-A";
 -                      break;
 -              case DP_B:
 -              case PCH_DP_B:
 -                      dev_priv->hotplug_supported_mask |=
 -                              DPB_HOTPLUG_INT_STATUS;
 -                      name = "DPDDC-B";
 -                      break;
 -              case DP_C:
 -              case PCH_DP_C:
 -                      dev_priv->hotplug_supported_mask |=
 -                              DPC_HOTPLUG_INT_STATUS;
 -                      name = "DPDDC-C";
 -                      break;
 -              case DP_D:
 -              case PCH_DP_D:
 -                      dev_priv->hotplug_supported_mask |=
 -                              DPD_HOTPLUG_INT_STATUS;
 -                      name = "DPDDC-D";
 -                      break;
 +      switch (port) {
 +      case PORT_A:
 +              name = "DPDDC-A";
 +              break;
 +      case PORT_B:
 +              dev_priv->hotplug_supported_mask |= DPB_HOTPLUG_INT_STATUS;
 +              name = "DPDDC-B";
 +              break;
 +      case PORT_C:
 +              dev_priv->hotplug_supported_mask |= DPC_HOTPLUG_INT_STATUS;
 +              name = "DPDDC-C";
 +              break;
 +      case PORT_D:
 +              dev_priv->hotplug_supported_mask |= DPD_HOTPLUG_INT_STATUS;
 +              name = "DPDDC-D";
 +              break;
 +      default:
 +              WARN(1, "Invalid port %c\n", port_name(port));
 +              break;
        }
  
        intel_dp_i2c_init(intel_dp, intel_connector, name);
index 13f0467c1f4d8d4279f45296f26cf18308ef7288,132ab511b90cd24d5e26e4f41e86749d558670ac..6920bc26a2e96c71899cb52bcb0525788ce49837
@@@ -31,7 -31,6 +31,7 @@@
  #include "drm_crtc.h"
  #include "drm_crtc_helper.h"
  #include "drm_fb_helper.h"
 +#include "drm_dp_helper.h"
  
  #define _wait_for(COND, MS, W) ({ \
        unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);       \
  })
  
  #define wait_for_atomic_us(COND, US) ({ \
-       int i, ret__ = -ETIMEDOUT;      \
-       for (i = 0; i < (US); i++) {    \
-               if ((COND)) {           \
-                       ret__ = 0;      \
-                       break;          \
-               }                       \
-               udelay(1);              \
-       }                               \
-       ret__;                          \
+       unsigned long timeout__ = jiffies + usecs_to_jiffies(US);       \
+       int ret__ = 0;                                                  \
+       while (!(COND)) {                                               \
+               if (time_after(jiffies, timeout__)) {                   \
+                       ret__ = -ETIMEDOUT;                             \
+                       break;                                          \
+               }                                                       \
+               cpu_relax();                                            \
+       }                                                               \
+       ret__;                                                          \
  })
  
  #define wait_for(COND, MS) _wait_for(COND, MS, 1)
  #define INTEL_OUTPUT_DISPLAYPORT 7
  #define INTEL_OUTPUT_EDP 8
  
 -/* Intel Pipe Clone Bit */
 -#define INTEL_HDMIB_CLONE_BIT 1
 -#define INTEL_HDMIC_CLONE_BIT 2
 -#define INTEL_HDMID_CLONE_BIT 3
 -#define INTEL_HDMIE_CLONE_BIT 4
 -#define INTEL_HDMIF_CLONE_BIT 5
 -#define INTEL_SDVO_NON_TV_CLONE_BIT 6
 -#define INTEL_SDVO_TV_CLONE_BIT 7
 -#define INTEL_SDVO_LVDS_CLONE_BIT 8
 -#define INTEL_ANALOG_CLONE_BIT 9
 -#define INTEL_TV_CLONE_BIT 10
 -#define INTEL_DP_B_CLONE_BIT 11
 -#define INTEL_DP_C_CLONE_BIT 12
 -#define INTEL_DP_D_CLONE_BIT 13
 -#define INTEL_LVDS_CLONE_BIT 14
 -#define INTEL_DVO_TMDS_CLONE_BIT 15
 -#define INTEL_DVO_LVDS_CLONE_BIT 16
 -#define INTEL_EDP_CLONE_BIT 17
 -
  #define INTEL_DVO_CHIP_NONE 0
  #define INTEL_DVO_CHIP_LVDS 1
  #define INTEL_DVO_CHIP_TMDS 2
@@@ -134,13 -153,9 +135,13 @@@ struct intel_encoder 
        struct drm_encoder base;
        int type;
        bool needs_tv_clock;
 +      /*
 +       * Intel hw has only one MUX where encoders could be clone, hence a
 +       * simple flag is enough to compute the possible_clones mask.
 +       */
 +      bool cloneable;
        void (*hot_plug)(struct intel_encoder *);
        int crtc_mask;
 -      int clone_mask;
  };
  
  struct intel_connector {
@@@ -156,6 -171,8 +157,6 @@@ struct intel_crtc 
        int dpms_mode;
        bool active; /* is the crtc on? independent of the dpms mode */
        bool primary_disabled; /* is the crtc obscured by a plane? */
 -      bool busy; /* is scanout buffer being updated frequently? */
 -      struct timer_list idle_timer;
        bool lowfreq_avail;
        struct intel_overlay *overlay;
        struct intel_unpin_work *unpin_work;
@@@ -294,38 -311,6 +295,38 @@@ struct intel_hdmi 
                               struct drm_display_mode *adjusted_mode);
  };
  
 +#define DP_RECEIVER_CAP_SIZE          0xf
 +#define DP_LINK_CONFIGURATION_SIZE    9
 +
 +struct intel_dp {
 +      struct intel_encoder base;
 +      uint32_t output_reg;
 +      uint32_t DP;
 +      uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
 +      bool has_audio;
 +      enum hdmi_force_audio force_audio;
 +      enum port port;
 +      uint32_t color_range;
 +      int dpms_mode;
 +      uint8_t link_bw;
 +      uint8_t lane_count;
 +      uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
 +      struct i2c_adapter adapter;
 +      struct i2c_algo_dp_aux_data algo;
 +      bool is_pch_edp;
 +      uint8_t train_set[4];
 +      int panel_power_up_delay;
 +      int panel_power_down_delay;
 +      int panel_power_cycle_delay;
 +      int backlight_on_delay;
 +      int backlight_off_delay;
 +      struct drm_display_mode *panel_fixed_mode;  /* for eDP */
 +      struct delayed_work panel_vdd_work;
 +      bool want_panel_vdd;
 +      struct edid *edid; /* cached EDID for eDP */
 +      int edid_mode_count;
 +};
 +
  static inline struct drm_crtc *
  intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
  {
@@@ -363,21 -348,17 +364,21 @@@ extern void intel_attach_force_audio_pr
  extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
  
  extern void intel_crt_init(struct drm_device *dev);
 -extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
 +extern void intel_hdmi_init(struct drm_device *dev,
 +                          int sdvox_reg, enum port port);
  extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
  extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
  extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
                            bool is_sdvob);
  extern void intel_dvo_init(struct drm_device *dev);
  extern void intel_tv_init(struct drm_device *dev);
 -extern void intel_mark_busy(struct drm_device *dev,
 -                          struct drm_i915_gem_object *obj);
 +extern void intel_mark_busy(struct drm_device *dev);
 +extern void intel_mark_idle(struct drm_device *dev);
 +extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj);
 +extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj);
  extern bool intel_lvds_init(struct drm_device *dev);
 -extern void intel_dp_init(struct drm_device *dev, int dp_reg);
 +extern void intel_dp_init(struct drm_device *dev, int output_reg,
 +                        enum port port);
  void
  intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
                 struct drm_display_mode *adjusted_mode);
@@@ -390,6 -371,8 +391,6 @@@ extern int intel_plane_init(struct drm_
  extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
                                      enum plane plane);
  
 -void intel_sanitize_pm(struct drm_device *dev);
 -
  /* intel_panel.c */
  extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
                                   struct drm_display_mode *adjusted_mode);
@@@ -398,7 -381,6 +399,6 @@@ extern void intel_pch_panel_fitting(str
                                    const struct drm_display_mode *mode,
                                    struct drm_display_mode *adjusted_mode);
  extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
- extern u32 intel_panel_get_backlight(struct drm_device *dev);
  extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
  extern int intel_panel_setup_backlight(struct drm_device *dev);
  extern void intel_panel_enable_backlight(struct drm_device *dev,
index d64dffbe0e0dcd0a303bb8e780bba5534cbcfd15,58c07cdafb7ed6c5c5ce08216f3dca999efa2a19..c0407aa5baac14d5bfa0115ed819287f77fca6ec
@@@ -2160,28 -2160,11 +2160,28 @@@ err_unref
        return NULL;
  }
  
 +/**
 + * Lock protecting IPS related data structures
 + *   - i915_mch_dev
 + *   - dev_priv->max_delay
 + *   - dev_priv->min_delay
 + *   - dev_priv->fmax
 + *   - dev_priv->gpu_busy
 + *   - dev_priv->gfx_power
 + */
 +DEFINE_SPINLOCK(mchdev_lock);
 +
 +/* Global for IPS driver to get at the current i915 device. Protected by
 + * mchdev_lock. */
 +static struct drm_i915_private *i915_mch_dev;
 +
  bool ironlake_set_drps(struct drm_device *dev, u8 val)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u16 rgvswctl;
  
 +      assert_spin_locked(&mchdev_lock);
 +
        rgvswctl = I915_READ16(MEMSWCTL);
        if (rgvswctl & MEMCTL_CMD_STS) {
                DRM_DEBUG("gpu busy, RCS change rejected\n");
@@@ -2205,8 -2188,6 +2205,8 @@@ static void ironlake_enable_drps(struc
        u32 rgvmodectl = I915_READ(MEMMODECTL);
        u8 fmax, fmin, fstart, vstart;
  
 +      spin_lock_irq(&mchdev_lock);
 +
        /* Enable temp reporting */
        I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN);
        I915_WRITE16(TSC1, I915_READ(TSC1) | TSE);
        rgvmodectl |= MEMMODE_SWMODE_EN;
        I915_WRITE(MEMMODECTL, rgvmodectl);
  
 -      if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10))
 +      if (wait_for_atomic((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10))
                DRM_ERROR("stuck trying to change perf mode\n");
 -      msleep(1);
 +      mdelay(1);
  
        ironlake_set_drps(dev, fstart);
  
        dev_priv->last_time1 = jiffies_to_msecs(jiffies);
        dev_priv->last_count2 = I915_READ(0x112f4);
        getrawmonotonic(&dev_priv->last_time2);
 +
 +      spin_unlock_irq(&mchdev_lock);
  }
  
  static void ironlake_disable_drps(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      u16 rgvswctl = I915_READ16(MEMSWCTL);
 +      u16 rgvswctl;
 +
 +      spin_lock_irq(&mchdev_lock);
 +
 +      rgvswctl = I915_READ16(MEMSWCTL);
  
        /* Ack interrupts, disable EFC interrupt */
        I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
  
        /* Go back to the starting frequency */
        ironlake_set_drps(dev, dev_priv->fstart);
 -      msleep(1);
 +      mdelay(1);
        rgvswctl |= MEMCTL_CMD_STS;
        I915_WRITE(MEMSWCTL, rgvswctl);
 -      msleep(1);
 +      mdelay(1);
  
 +      spin_unlock_irq(&mchdev_lock);
  }
  
 -void gen6_set_rps(struct drm_device *dev, u8 val)
 +/* There's a funny hw issue where the hw returns all 0 when reading from
 + * GEN6_RP_INTERRUPT_LIMITS. Hence we always need to compute the desired value
 + * ourselves, instead of doing a rmw cycle (which might result in us clearing
 + * all limits and the gpu stuck at whatever frequency it is at atm).
 + */
 +static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
        u32 limits;
  
        limits = 0;
 -      if (val >= dev_priv->max_delay)
 -              val = dev_priv->max_delay;
 -      else
 -              limits |= dev_priv->max_delay << 24;
  
 -      if (val <= dev_priv->min_delay)
 -              val = dev_priv->min_delay;
 -      else
 -              limits |= dev_priv->min_delay << 16;
 +      if (*val >= dev_priv->rps.max_delay)
 +              *val = dev_priv->rps.max_delay;
 +      limits |= dev_priv->rps.max_delay << 24;
  
 -      if (val == dev_priv->cur_delay)
 +      /* Only set the down limit when we've reached the lowest level to avoid
 +       * getting more interrupts, otherwise leave this clear. This prevents a
 +       * race in the hw when coming out of rc6: There's a tiny window where
 +       * the hw runs at the minimal clock before selecting the desired
 +       * frequency, if the down threshold expires in that window we will not
 +       * receive a down interrupt. */
 +      if (*val <= dev_priv->rps.min_delay) {
 +              *val = dev_priv->rps.min_delay;
 +              limits |= dev_priv->rps.min_delay << 16;
 +      }
 +
 +      return limits;
 +}
 +
 +void gen6_set_rps(struct drm_device *dev, u8 val)
 +{
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      u32 limits = gen6_rps_limits(dev_priv, &val);
 +
 +      WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 +
 +      if (val == dev_priv->rps.cur_delay)
                return;
  
        I915_WRITE(GEN6_RPNSWREQ,
         */
        I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
  
 -      dev_priv->cur_delay = val;
 +      dev_priv->rps.cur_delay = val;
  }
  
  static void gen6_disable_rps(struct drm_device *dev)
         * register (PMIMR) to mask PM interrupts. The only risk is in leaving
         * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
  
 -      spin_lock_irq(&dev_priv->rps_lock);
 -      dev_priv->pm_iir = 0;
 -      spin_unlock_irq(&dev_priv->rps_lock);
 +      spin_lock_irq(&dev_priv->rps.lock);
 +      dev_priv->rps.pm_iir = 0;
 +      spin_unlock_irq(&dev_priv->rps.lock);
  
        I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
  }
  
  int intel_enable_rc6(const struct drm_device *dev)
  {
 -      /*
 -       * Respect the kernel parameter if it is set
 -       */
 +      /* Respect the kernel parameter if it is set */
        if (i915_enable_rc6 >= 0)
                return i915_enable_rc6;
  
 -      /*
 -       * Disable RC6 on Ironlake
 -       */
 -      if (INTEL_INFO(dev)->gen == 5)
 -              return 0;
 +      if (INTEL_INFO(dev)->gen == 5) {
 +              DRM_DEBUG_DRIVER("Ironlake: only RC6 available\n");
 +              return INTEL_RC6_ENABLE;
 +      }
  
 -      /* On Haswell, only RC6 is available. So let's enable it by default to
 -       * provide better testing and coverage since the beginning.
 -       */
 -      if (IS_HASWELL(dev))
 +      if (IS_HASWELL(dev)) {
 +              DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");
                return INTEL_RC6_ENABLE;
 +      }
  
 -      /*
 -       * Disable rc6 on Sandybridge
 -       */
 +      /* snb/ivb have more than one rc6 state. */
        if (INTEL_INFO(dev)->gen == 6) {
                DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");
                return INTEL_RC6_ENABLE;
        }
 +
        DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n");
        return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
  }
@@@ -2424,9 -2383,9 +2424,9 @@@ static void gen6_enable_rps(struct drm_
        gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
  
        /* In units of 100MHz */
 -      dev_priv->max_delay = rp_state_cap & 0xff;
 -      dev_priv->min_delay = (rp_state_cap & 0xff0000) >> 16;
 -      dev_priv->cur_delay = 0;
 +      dev_priv->rps.max_delay = rp_state_cap & 0xff;
 +      dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16;
 +      dev_priv->rps.cur_delay = 0;
  
        /* disable the counters and set deterministic thresholds */
        I915_WRITE(GEN6_RC_CONTROL, 0);
  
        I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000);
        I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
 -                 dev_priv->max_delay << 24 |
 -                 dev_priv->min_delay << 16);
 +                 dev_priv->rps.max_delay << 24 |
 +                 dev_priv->rps.min_delay << 16);
  
        if (IS_HASWELL(dev)) {
                I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
                     500))
                DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
        if (pcu_mbox & (1<<31)) { /* OC supported */
 -              dev_priv->max_delay = pcu_mbox & 0xff;
 +              dev_priv->rps.max_delay = pcu_mbox & 0xff;
                DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
        }
  
  
        /* requires MSI enabled */
        I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS);
 -      spin_lock_irq(&dev_priv->rps_lock);
 -      WARN_ON(dev_priv->pm_iir != 0);
 +      spin_lock_irq(&dev_priv->rps.lock);
 +      WARN_ON(dev_priv->rps.pm_iir != 0);
        I915_WRITE(GEN6_PMIMR, 0);
 -      spin_unlock_irq(&dev_priv->rps_lock);
 +      spin_unlock_irq(&dev_priv->rps.lock);
        /* enable all PM interrupts */
        I915_WRITE(GEN6_PMINTRMSK, 0);
  
@@@ -2568,9 -2527,9 +2568,9 @@@ static void gen6_update_ring_freq(struc
         * to use for memory access.  We do this by specifying the IA frequency
         * the PCU should use as a reference to determine the ring frequency.
         */
 -      for (gpu_freq = dev_priv->max_delay; gpu_freq >= dev_priv->min_delay;
 +      for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay;
             gpu_freq--) {
 -              int diff = dev_priv->max_delay - gpu_freq;
 +              int diff = dev_priv->rps.max_delay - gpu_freq;
  
                /*
                 * For GPU frequencies less than 750MHz, just use the lowest
@@@ -2741,8 -2700,6 +2741,8 @@@ unsigned long i915_chipset_val(struct d
        unsigned long now = jiffies_to_msecs(jiffies), diff1;
        int i;
  
 +      assert_spin_locked(&mchdev_lock);
 +
        diff1 = now - dev_priv->last_time1;
  
        /* Prevent division-by-zero if we are asking too fast.
@@@ -2944,14 -2901,15 +2944,14 @@@ static u16 pvid_to_extvid(struct drm_i9
                return v_table[pxvid].vd;
  }
  
 -void i915_update_gfx_val(struct drm_i915_private *dev_priv)
 +static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
  {
        struct timespec now, diff1;
        u64 diff;
        unsigned long diffms;
        u32 count;
  
 -      if (dev_priv->info->gen != 5)
 -              return;
 +      assert_spin_locked(&mchdev_lock);
  
        getrawmonotonic(&now);
        diff1 = timespec_sub(now, dev_priv->last_time2);
        dev_priv->gfx_power = diff;
  }
  
 +void i915_update_gfx_val(struct drm_i915_private *dev_priv)
 +{
 +      if (dev_priv->info->gen != 5)
 +              return;
 +
 +      spin_lock_irq(&mchdev_lock);
 +
 +      __i915_update_gfx_val(dev_priv);
 +
 +      spin_unlock_irq(&mchdev_lock);
 +}
 +
  unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
  {
        unsigned long t, corr, state1, corr2, state2;
        u32 pxvid, ext_v;
  
 -      pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->cur_delay * 4));
 +      assert_spin_locked(&mchdev_lock);
 +
 +      pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_delay * 4));
        pxvid = (pxvid >> 24) & 0x7f;
        ext_v = pvid_to_extvid(dev_priv, pxvid);
  
        state2 = (corr2 * state1) / 10000;
        state2 /= 100; /* convert to mW */
  
 -      i915_update_gfx_val(dev_priv);
 +      __i915_update_gfx_val(dev_priv);
  
        return dev_priv->gfx_power + state2;
  }
  
 -/* Global for IPS driver to get at the current i915 device */
 -static struct drm_i915_private *i915_mch_dev;
 -/*
 - * Lock protecting IPS related data structures
 - *   - i915_mch_dev
 - *   - dev_priv->max_delay
 - *   - dev_priv->min_delay
 - *   - dev_priv->fmax
 - *   - dev_priv->gpu_busy
 - */
 -static DEFINE_SPINLOCK(mchdev_lock);
 -
  /**
   * i915_read_mch_val - return value for IPS use
   *
@@@ -3039,7 -2995,7 +3039,7 @@@ unsigned long i915_read_mch_val(void
        struct drm_i915_private *dev_priv;
        unsigned long chipset_val, graphics_val, ret = 0;
  
 -      spin_lock(&mchdev_lock);
 +      spin_lock_irq(&mchdev_lock);
        if (!i915_mch_dev)
                goto out_unlock;
        dev_priv = i915_mch_dev;
        ret = chipset_val + graphics_val;
  
  out_unlock:
 -      spin_unlock(&mchdev_lock);
 +      spin_unlock_irq(&mchdev_lock);
  
        return ret;
  }
@@@ -3066,7 -3022,7 +3066,7 @@@ bool i915_gpu_raise(void
        struct drm_i915_private *dev_priv;
        bool ret = true;
  
 -      spin_lock(&mchdev_lock);
 +      spin_lock_irq(&mchdev_lock);
        if (!i915_mch_dev) {
                ret = false;
                goto out_unlock;
                dev_priv->max_delay--;
  
  out_unlock:
 -      spin_unlock(&mchdev_lock);
 +      spin_unlock_irq(&mchdev_lock);
  
        return ret;
  }
@@@ -3094,7 -3050,7 +3094,7 @@@ bool i915_gpu_lower(void
        struct drm_i915_private *dev_priv;
        bool ret = true;
  
 -      spin_lock(&mchdev_lock);
 +      spin_lock_irq(&mchdev_lock);
        if (!i915_mch_dev) {
                ret = false;
                goto out_unlock;
                dev_priv->max_delay++;
  
  out_unlock:
 -      spin_unlock(&mchdev_lock);
 +      spin_unlock_irq(&mchdev_lock);
  
        return ret;
  }
@@@ -3119,20 -3075,17 +3119,20 @@@ EXPORT_SYMBOL_GPL(i915_gpu_lower)
  bool i915_gpu_busy(void)
  {
        struct drm_i915_private *dev_priv;
 +      struct intel_ring_buffer *ring;
        bool ret = false;
 +      int i;
  
 -      spin_lock(&mchdev_lock);
 +      spin_lock_irq(&mchdev_lock);
        if (!i915_mch_dev)
                goto out_unlock;
        dev_priv = i915_mch_dev;
  
 -      ret = dev_priv->busy;
 +      for_each_ring(ring, dev_priv, i)
 +              ret |= !list_empty(&ring->request_list);
  
  out_unlock:
 -      spin_unlock(&mchdev_lock);
 +      spin_unlock_irq(&mchdev_lock);
  
        return ret;
  }
@@@ -3149,7 -3102,7 +3149,7 @@@ bool i915_gpu_turbo_disable(void
        struct drm_i915_private *dev_priv;
        bool ret = true;
  
 -      spin_lock(&mchdev_lock);
 +      spin_lock_irq(&mchdev_lock);
        if (!i915_mch_dev) {
                ret = false;
                goto out_unlock;
                ret = false;
  
  out_unlock:
 -      spin_unlock(&mchdev_lock);
 +      spin_unlock_irq(&mchdev_lock);
  
        return ret;
  }
@@@ -3190,20 -3143,19 +3190,20 @@@ ips_ping_for_i915_load(void
  
  void intel_gpu_ips_init(struct drm_i915_private *dev_priv)
  {
 -      spin_lock(&mchdev_lock);
 +      /* We only register the i915 ips part with intel-ips once everything is
 +       * set up, to avoid intel-ips sneaking in and reading bogus values. */
 +      spin_lock_irq(&mchdev_lock);
        i915_mch_dev = dev_priv;
 -      dev_priv->mchdev_lock = &mchdev_lock;
 -      spin_unlock(&mchdev_lock);
 +      spin_unlock_irq(&mchdev_lock);
  
        ips_ping_for_i915_load();
  }
  
  void intel_gpu_ips_teardown(void)
  {
 -      spin_lock(&mchdev_lock);
 +      spin_lock_irq(&mchdev_lock);
        i915_mch_dev = NULL;
 -      spin_unlock(&mchdev_lock);
 +      spin_unlock_irq(&mchdev_lock);
  }
  static void intel_init_emon(struct drm_device *dev)
  {
@@@ -3783,6 -3735,42 +3783,6 @@@ void intel_init_clock_gating(struct drm
                dev_priv->display.init_pch_clock_gating(dev);
  }
  
 -static void gen6_sanitize_pm(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      u32 limits, delay, old;
 -
 -      gen6_gt_force_wake_get(dev_priv);
 -
 -      old = limits = I915_READ(GEN6_RP_INTERRUPT_LIMITS);
 -      /* Make sure we continue to get interrupts
 -       * until we hit the minimum or maximum frequencies.
 -       */
 -      limits &= ~(0x3f << 16 | 0x3f << 24);
 -      delay = dev_priv->cur_delay;
 -      if (delay < dev_priv->max_delay)
 -              limits |= (dev_priv->max_delay & 0x3f) << 24;
 -      if (delay > dev_priv->min_delay)
 -              limits |= (dev_priv->min_delay & 0x3f) << 16;
 -
 -      if (old != limits) {
 -              /* Note that the known failure case is to read back 0. */
 -              DRM_DEBUG_DRIVER("Power management discrepancy: GEN6_RP_INTERRUPT_LIMITS "
 -                               "expected %08x, was %08x\n", limits, old);
 -              I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
 -      }
 -
 -      gen6_gt_force_wake_put(dev_priv);
 -}
 -
 -void intel_sanitize_pm(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -
 -      if (dev_priv->display.sanitize_pm)
 -              dev_priv->display.sanitize_pm(dev);
 -}
 -
  /* Starting with Haswell, we have different power wells for
   * different parts of the GPU. This attempts to enable them all.
   */
@@@ -3868,6 -3856,7 +3868,6 @@@ void intel_init_pm(struct drm_device *d
                                dev_priv->display.update_wm = NULL;
                        }
                        dev_priv->display.init_clock_gating = gen6_init_clock_gating;
 -                      dev_priv->display.sanitize_pm = gen6_sanitize_pm;
                } else if (IS_IVYBRIDGE(dev)) {
                        /* FIXME: detect B0+ stepping and use auto training */
                        if (SNB_READ_WM0_LATENCY()) {
                                dev_priv->display.update_wm = NULL;
                        }
                        dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
 -                      dev_priv->display.sanitize_pm = gen6_sanitize_pm;
                } else if (IS_HASWELL(dev)) {
                        if (SNB_READ_WM0_LATENCY()) {
                                dev_priv->display.update_wm = sandybridge_update_wm;
                                dev_priv->display.update_wm = NULL;
                        }
                        dev_priv->display.init_clock_gating = haswell_init_clock_gating;
 -                      dev_priv->display.sanitize_pm = gen6_sanitize_pm;
                } else
                        dev_priv->display.update_wm = NULL;
        } else if (IS_VALLEYVIEW(dev)) {
@@@ -3972,6 -3963,7 +3972,7 @@@ static void __gen6_gt_force_wake_get(st
                DRM_ERROR("Force wake wait timed out\n");
  
        I915_WRITE_NOTRACE(FORCEWAKE, 1);
+       POSTING_READ(FORCEWAKE);
  
        if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
                DRM_ERROR("Force wake wait timed out\n");
@@@ -3992,6 -3984,7 +3993,7 @@@ static void __gen6_gt_force_wake_mt_get
                DRM_ERROR("Force wake wait timed out\n");
  
        I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1));
+       POSTING_READ(FORCEWAKE_MT);
  
        if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
                DRM_ERROR("Force wake wait timed out\n");
@@@ -4027,14 -4020,14 +4029,14 @@@ void gen6_gt_check_fifodbg(struct drm_i
  static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
  {
        I915_WRITE_NOTRACE(FORCEWAKE, 0);
-       /* The below doubles as a POSTING_READ */
+       POSTING_READ(FORCEWAKE);
        gen6_gt_check_fifodbg(dev_priv);
  }
  
  static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
  {
        I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1));
-       /* The below doubles as a POSTING_READ */
+       POSTING_READ(FORCEWAKE_MT);
        gen6_gt_check_fifodbg(dev_priv);
  }
  
index e278675cdff9a94e3fdfabf29196f6a0b0034fa9,e2a73b38abe96e7dc49674d39806c5ca3cab6e51..c828169c73ae8103c351f177000688cd4500b6f4
@@@ -214,26 -214,40 +214,35 @@@ gen6_render_ring_flush(struct intel_rin
                           u32 invalidate_domains, u32 flush_domains)
  {
        u32 flags = 0;
+       struct pipe_control *pc = ring->private;
+       u32 scratch_addr = pc->gtt_offset + 128;
        int ret;
  
 -      /* Force SNB workarounds for PIPE_CONTROL flushes */
 -      ret = intel_emit_post_sync_nonzero_flush(ring);
 -      if (ret)
 -              return ret;
 -
        /* Just flush everything.  Experiments have shown that reducing the
         * number of bits based on the write domains has little performance
         * impact.
         */
-       flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
-       flags |= PIPE_CONTROL_TLB_INVALIDATE;
-       flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
-       flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
-       flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
-       flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
-       flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
-       flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
-       /*
-        * Ensure that any following seqno writes only happen when the render
-        * cache is indeed flushed (but only if the caller actually wants that).
-        */
-       if (flush_domains)
+       if (flush_domains) {
+               flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+               flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+               /*
+                * Ensure that any following seqno writes only happen
+                * when the render cache is indeed flushed.
+                */
                flags |= PIPE_CONTROL_CS_STALL;
+       }
+       if (invalidate_domains) {
+               flags |= PIPE_CONTROL_TLB_INVALIDATE;
+               flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
+               flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
+               flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
+               flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
+               flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
+               /*
+                * TLB invalidate requires a post-sync write.
+                */
+               flags |= PIPE_CONTROL_QW_WRITE;
+       }
  
        ret = intel_ring_begin(ring, 4);
        if (ret)
  
        intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
        intel_ring_emit(ring, flags);
-       intel_ring_emit(ring, 0);
+       intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
        intel_ring_emit(ring, 0);
        intel_ring_advance(ring);
  
        return 0;
  }
  
 +static int
 +gen6_render_ring_flush__wa(struct intel_ring_buffer *ring,
 +                         u32 invalidate_domains, u32 flush_domains)
 +{
 +      int ret;
 +
 +      /* Force SNB workarounds for PIPE_CONTROL flushes */
 +      ret = intel_emit_post_sync_nonzero_flush(ring);
 +      if (ret)
 +              return ret;
 +
 +      return gen6_render_ring_flush(ring, invalidate_domains, flush_domains);
 +}
 +
  static void ring_write_tail(struct intel_ring_buffer *ring,
                            u32 value)
  {
@@@ -294,8 -294,6 +303,6 @@@ static int init_ring_common(struct inte
        I915_WRITE_HEAD(ring, 0);
        ring->write_tail(ring, 0);
  
-       /* Initialize the ring. */
-       I915_WRITE_START(ring, obj->gtt_offset);
        head = I915_READ_HEAD(ring) & HEAD_ADDR;
  
        /* G45 ring initialization fails to reset head to zero */
                }
        }
  
+       /* Initialize the ring. This must happen _after_ we've cleared the ring
+        * registers with the above sequence (the readback of the HEAD registers
+        * also enforces ordering), otherwise the hw might lose the new ring
+        * register values. */
+       I915_WRITE_START(ring, obj->gtt_offset);
        I915_WRITE_CTL(ring,
                        ((ring->size - PAGE_SIZE) & RING_NR_PAGES)
                        | RING_VALID);
@@@ -459,7 -462,7 +471,7 @@@ static int init_render_ring(struct inte
        if (INTEL_INFO(dev)->gen >= 6)
                I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
  
 -      if (IS_IVYBRIDGE(dev))
 +      if (HAS_L3_GPU_CACHE(dev))
                I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR);
  
        return ret;
@@@ -625,24 -628,26 +637,24 @@@ pc_render_add_request(struct intel_ring
  }
  
  static u32
 -gen6_ring_get_seqno(struct intel_ring_buffer *ring)
 +gen6_ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
  {
 -      struct drm_device *dev = ring->dev;
 -
        /* Workaround to force correct ordering between irq and seqno writes on
         * ivb (and maybe also on snb) by reading from a CS register (like
         * ACTHD) before reading the status page. */
 -      if (IS_GEN6(dev) || IS_GEN7(dev))
 +      if (!lazy_coherency)
                intel_ring_get_active_head(ring);
        return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
  }
  
  static u32
 -ring_get_seqno(struct intel_ring_buffer *ring)
 +ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
  {
        return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
  }
  
  static u32
 -pc_render_get_seqno(struct intel_ring_buffer *ring)
 +pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
  {
        struct pipe_control *pc = ring->private;
        return pc->cpu_page[0];
@@@ -847,7 -852,7 +859,7 @@@ gen6_ring_get_irq(struct intel_ring_buf
  
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (ring->irq_refcount++ == 0) {
 -              if (IS_IVYBRIDGE(dev) && ring->id == RCS)
 +              if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
                        I915_WRITE_IMR(ring, ~(ring->irq_enable_mask |
                                                GEN6_RENDER_L3_PARITY_ERROR));
                else
@@@ -870,7 -875,7 +882,7 @@@ gen6_ring_put_irq(struct intel_ring_buf
  
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (--ring->irq_refcount == 0) {
 -              if (IS_IVYBRIDGE(dev) && ring->id == RCS)
 +              if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
                        I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR);
                else
                        I915_WRITE_IMR(ring, ~0);
@@@ -1005,6 -1010,7 +1017,6 @@@ static int intel_init_ring_buffer(struc
        ring->dev = dev;
        INIT_LIST_HEAD(&ring->active_list);
        INIT_LIST_HEAD(&ring->request_list);
 -      INIT_LIST_HEAD(&ring->gpu_write_list);
        ring->size = 32 * PAGE_SIZE;
  
        init_waitqueue_head(&ring->irq_queue);
@@@ -1374,8 -1380,6 +1386,8 @@@ int intel_init_render_ring_buffer(struc
        if (INTEL_INFO(dev)->gen >= 6) {
                ring->add_request = gen6_add_request;
                ring->flush = gen6_render_ring_flush;
 +              if (INTEL_INFO(dev)->gen == 6)
 +                      ring->flush = gen6_render_ring_flush__wa;
                ring->irq_get = gen6_ring_get_irq;
                ring->irq_put = gen6_ring_put_irq;
                ring->irq_enable_mask = GT_USER_INTERRUPT;
@@@ -1477,6 -1481,7 +1489,6 @@@ int intel_render_ring_init_dri(struct d
        ring->dev = dev;
        INIT_LIST_HEAD(&ring->active_list);
        INIT_LIST_HEAD(&ring->request_list);
 -      INIT_LIST_HEAD(&ring->gpu_write_list);
  
        ring->size = size;
        ring->effective_size = ring->size;
@@@ -1569,41 -1574,3 +1581,41 @@@ int intel_init_blt_ring_buffer(struct d
  
        return intel_init_ring_buffer(dev, ring);
  }
 +
 +int
 +intel_ring_flush_all_caches(struct intel_ring_buffer *ring)
 +{
 +      int ret;
 +
 +      if (!ring->gpu_caches_dirty)
 +              return 0;
 +
 +      ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS);
 +      if (ret)
 +              return ret;
 +
 +      trace_i915_gem_ring_flush(ring, 0, I915_GEM_GPU_DOMAINS);
 +
 +      ring->gpu_caches_dirty = false;
 +      return 0;
 +}
 +
 +int
 +intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring)
 +{
 +      uint32_t flush_domains;
 +      int ret;
 +
 +      flush_domains = 0;
 +      if (ring->gpu_caches_dirty)
 +              flush_domains = I915_GEM_GPU_DOMAINS;
 +
 +      ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains);
 +      if (ret)
 +              return ret;
 +
 +      trace_i915_gem_ring_flush(ring, I915_GEM_GPU_DOMAINS, flush_domains);
 +
 +      ring->gpu_caches_dirty = false;
 +      return 0;
 +}
index d881602a9155387fee0f82b400752c89e39c4d65,d172e9873131cc708a5351fdec3cc690a73cabcd..f3762f8b71941d85f0e8b48a737e341fcefdb825
@@@ -444,13 -444,16 +444,16 @@@ static bool intel_sdvo_write_cmd(struc
        struct i2c_msg *msgs;
        int i, ret = true;
  
+         /* Would be simpler to allocate both in one go ? */        
        buf = (u8 *)kzalloc(args_len * 2 + 2, GFP_KERNEL);
        if (!buf)
                return false;
  
        msgs = kcalloc(args_len + 3, sizeof(*msgs), GFP_KERNEL);
-       if (!msgs)
+       if (!msgs) {
+               kfree(buf);
                return false;
+         }
  
        intel_sdvo_debug_write(intel_sdvo, cmd, args, args_len);
  
@@@ -2078,7 -2081,8 +2081,7 @@@ intel_sdvo_dvi_init(struct intel_sdvo *
                connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
                intel_sdvo->is_hdmi = true;
        }
 -      intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
 -                                     (1 << INTEL_ANALOG_CLONE_BIT));
 +      intel_sdvo->base.cloneable = true;
  
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (intel_sdvo->is_hdmi)
@@@ -2109,7 -2113,7 +2112,7 @@@ intel_sdvo_tv_init(struct intel_sdvo *i
  
        intel_sdvo->is_tv = true;
        intel_sdvo->base.needs_tv_clock = true;
 -      intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
 +      intel_sdvo->base.cloneable = false;
  
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
  
@@@ -2152,7 -2156,8 +2155,7 @@@ intel_sdvo_analog_init(struct intel_sdv
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
        }
  
 -      intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
 -                                     (1 << INTEL_ANALOG_CLONE_BIT));
 +      intel_sdvo->base.cloneable = true;
  
        intel_sdvo_connector_init(intel_sdvo_connector,
                                  intel_sdvo);
@@@ -2184,10 -2189,8 +2187,10 @@@ intel_sdvo_lvds_init(struct intel_sdvo 
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
        }
  
 -      intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) |
 -                                     (1 << INTEL_SDVO_LVDS_CLONE_BIT));
 +      /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
 +       * as opposed to native LVDS, where we upscale with the panel-fitter
 +       * (and hence only the native LVDS resolution could be cloned). */
 +      intel_sdvo->base.cloneable = true;
  
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))