drm/i915: Combine scratch members into a struct
[deliverable/linux.git] / drivers / gpu / drm / i915 / i915_gem_gtt.c
index bdb0d7717bc77937dce3c4de563f1e7066c7bb2e..cdd7b45cd501fa97d7d57596fcda260ffa108b18 100644 (file)
@@ -28,7 +28,8 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 
-typedef uint32_t gen6_gtt_pte_t;
+#define GEN6_PPGTT_PD_ENTRIES 512
+#define I915_PPGTT_PT_ENTRIES (PAGE_SIZE / sizeof(gen6_gtt_pte_t))
 
 /* PPGTT stuff */
 #define GEN6_GTT_ADDR_ENCODE(addr)     ((addr) | (((addr) >> 28) & 0xff0))
@@ -44,29 +45,22 @@ typedef uint32_t gen6_gtt_pte_t;
 #define GEN6_PTE_CACHE_LLC_MLC         (3 << 1)
 #define GEN6_PTE_ADDR_ENCODE(addr)     GEN6_GTT_ADDR_ENCODE(addr)
 
-static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
-                                            dma_addr_t addr,
-                                            enum i915_cache_level level)
+static gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
+                                     dma_addr_t addr,
+                                     enum i915_cache_level level)
 {
        gen6_gtt_pte_t pte = GEN6_PTE_VALID;
        pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
        switch (level) {
        case I915_CACHE_LLC_MLC:
-               /* Haswell doesn't set L3 this way */
-               if (IS_HASWELL(dev))
-                       pte |= GEN6_PTE_CACHE_LLC;
-               else
-                       pte |= GEN6_PTE_CACHE_LLC_MLC;
+               pte |= GEN6_PTE_CACHE_LLC_MLC;
                break;
        case I915_CACHE_LLC:
                pte |= GEN6_PTE_CACHE_LLC;
                break;
        case I915_CACHE_NONE:
-               if (IS_HASWELL(dev))
-                       pte |= HSW_PTE_UNCACHED;
-               else
-                       pte |= GEN6_PTE_UNCACHED;
+               pte |= GEN6_PTE_UNCACHED;
                break;
        default:
                BUG();
@@ -75,16 +69,48 @@ static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
        return pte;
 }
 
-static int gen6_ppgtt_enable(struct drm_device *dev)
+#define BYT_PTE_WRITEABLE              (1 << 1)
+#define BYT_PTE_SNOOPED_BY_CPU_CACHES  (1 << 2)
+
+static gen6_gtt_pte_t byt_pte_encode(struct drm_device *dev,
+                                    dma_addr_t addr,
+                                    enum i915_cache_level level)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       uint32_t pd_offset;
-       struct intel_ring_buffer *ring;
-       struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+       gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+       pte |= GEN6_PTE_ADDR_ENCODE(addr);
+
+       /* Mark the page as writeable.  Other platforms don't have a
+        * setting for read-only/writable, so this matches that behavior.
+        */
+       pte |= BYT_PTE_WRITEABLE;
+
+       if (level != I915_CACHE_NONE)
+               pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
+
+       return pte;
+}
+
+static gen6_gtt_pte_t hsw_pte_encode(struct drm_device *dev,
+                                    dma_addr_t addr,
+                                    enum i915_cache_level level)
+{
+       gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+       pte |= GEN6_PTE_ADDR_ENCODE(addr);
+
+       if (level != I915_CACHE_NONE)
+               pte |= GEN6_PTE_CACHE_LLC;
+
+       return pte;
+}
+
+static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
+{
+       struct drm_i915_private *dev_priv = ppgtt->dev->dev_private;
        gen6_gtt_pte_t __iomem *pd_addr;
        uint32_t pd_entry;
        int i;
 
+       WARN_ON(ppgtt->pd_offset & 0x3f);
        pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm +
                ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
        for (i = 0; i < ppgtt->num_pd_entries; i++) {
@@ -97,6 +123,19 @@ static int gen6_ppgtt_enable(struct drm_device *dev)
                writel(pd_entry, pd_addr + i);
        }
        readl(pd_addr);
+}
+
+static int gen6_ppgtt_enable(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       uint32_t pd_offset;
+       struct intel_ring_buffer *ring;
+       struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+       int i;
+
+       BUG_ON(ppgtt->pd_offset & 0x3f);
+
+       gen6_write_pdes(ppgtt);
 
        pd_offset = ppgtt->pd_offset;
        pd_offset /= 64; /* in cachelines, */
@@ -149,14 +188,15 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
                                   unsigned first_entry,
                                   unsigned num_entries)
 {
+       struct drm_i915_private *dev_priv = ppgtt->dev->dev_private;
        gen6_gtt_pte_t *pt_vaddr, scratch_pte;
        unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES;
        unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
        unsigned last_pte, i;
 
-       scratch_pte = gen6_pte_encode(ppgtt->dev,
-                                     ppgtt->scratch_page_dma_addr,
-                                     I915_CACHE_LLC);
+       scratch_pte = ppgtt->pte_encode(ppgtt->dev,
+                                       dev_priv->gtt.scratch.addr,
+                                       I915_CACHE_LLC);
 
        while (num_entries) {
                last_pte = first_pte + num_entries;
@@ -191,8 +231,8 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
                dma_addr_t page_addr;
 
                page_addr = sg_page_iter_dma_address(&sg_iter);
-               pt_vaddr[act_pte] = gen6_pte_encode(ppgtt->dev, page_addr,
-                                                   cache_level);
+               pt_vaddr[act_pte] = ppgtt->pte_encode(ppgtt->dev, page_addr,
+                                                     cache_level);
                if (++act_pte == I915_PPGTT_PT_ENTRIES) {
                        kunmap_atomic(pt_vaddr);
                        act_pt++;
@@ -233,9 +273,16 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
        /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
         * entries. For aliasing ppgtt support we just steal them at the end for
         * now. */
-       first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
+       first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
 
-       ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
+       if (IS_HASWELL(dev)) {
+               ppgtt->pte_encode = hsw_pte_encode;
+       } else if (IS_VALLEYVIEW(dev)) {
+               ppgtt->pte_encode = byt_pte_encode;
+       } else {
+               ppgtt->pte_encode = gen6_pte_encode;
+       }
+       ppgtt->num_pd_entries = GEN6_PPGTT_PD_ENTRIES;
        ppgtt->enable = gen6_ppgtt_enable;
        ppgtt->clear_range = gen6_ppgtt_clear_range;
        ppgtt->insert_entries = gen6_ppgtt_insert_entries;
@@ -305,7 +352,6 @@ static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
                return -ENOMEM;
 
        ppgtt->dev = dev;
-       ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma;
 
        if (INTEL_INFO(dev)->gen < 8)
                ret = gen6_ppgtt_init(ppgtt);
@@ -396,7 +442,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
        dev_priv->gtt.gtt_clear_range(dev, dev_priv->gtt.start / PAGE_SIZE,
                                      dev_priv->gtt.total / PAGE_SIZE);
 
-       list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
+       list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
                i915_gem_clflush_object(obj);
                i915_gem_gtt_bind_object(obj, obj->cache_level);
        }
@@ -437,7 +483,8 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
 
        for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
                addr = sg_page_iter_dma_address(&sg_iter);
-               iowrite32(gen6_pte_encode(dev, addr, level), &gtt_entries[i]);
+               iowrite32(dev_priv->gtt.pte_encode(dev, addr, level),
+                         &gtt_entries[i]);
                i++;
        }
 
@@ -449,7 +496,7 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
         */
        if (i != 0)
                WARN_ON(readl(&gtt_entries[i-1])
-                       != gen6_pte_encode(dev, addr, level));
+                       != dev_priv->gtt.pte_encode(dev, addr, level));
 
        /* This next bit makes the above posting read even more important. We
         * want to flush the TLBs only after we're certain all the PTE updates
@@ -474,8 +521,8 @@ static void gen6_ggtt_clear_range(struct drm_device *dev,
                 first_entry, num_entries, max_entries))
                num_entries = max_entries;
 
-       scratch_pte = gen6_pte_encode(dev, dev_priv->gtt.scratch_page_dma,
-                                     I915_CACHE_LLC);
+       scratch_pte = dev_priv->gtt.pte_encode(dev, dev_priv->gtt.scratch.addr,
+                                              I915_CACHE_LLC);
        for (i = 0; i < num_entries; i++)
                iowrite32(scratch_pte, &gtt_base[i]);
        readl(gtt_base);
@@ -586,7 +633,7 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
                dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust;
 
        /* Mark any preallocated objects as occupied */
-       list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
+       list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
                DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n",
                              obj->gtt_offset, obj->base.size);
 
@@ -643,7 +690,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
                if (INTEL_INFO(dev)->gen <= 7) {
                        /* PPGTT pdes are stolen from global gtt ptes, so shrink the
                         * aperture accordingly when using aliasing ppgtt. */
-                       gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
+                       gtt_size -= GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE;
                }
 
                i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
@@ -654,7 +701,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
 
                DRM_ERROR("Aliased PPGTT setup failed %d\n", ret);
                drm_mm_takedown(&dev_priv->mm.gtt_space);
-               gtt_size += I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
+               gtt_size += GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE;
        }
        i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
 }
@@ -679,8 +726,8 @@ static int setup_scratch_page(struct drm_device *dev)
 #else
        dma_addr = page_to_phys(page);
 #endif
-       dev_priv->gtt.scratch_page = page;
-       dev_priv->gtt.scratch_page_dma = dma_addr;
+       dev_priv->gtt.scratch.page = page;
+       dev_priv->gtt.scratch.addr = dma_addr;
 
        return 0;
 }
@@ -688,11 +735,11 @@ static int setup_scratch_page(struct drm_device *dev)
 static void teardown_scratch_page(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       set_pages_wb(dev_priv->gtt.scratch_page, 1);
-       pci_unmap_page(dev->pdev, dev_priv->gtt.scratch_page_dma,
+       set_pages_wb(dev_priv->gtt.scratch.page, 1);
+       pci_unmap_page(dev->pdev, dev_priv->gtt.scratch.addr,
                       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-       put_page(dev_priv->gtt.scratch_page);
-       __free_page(dev_priv->gtt.scratch_page);
+       put_page(dev_priv->gtt.scratch.page);
+       __free_page(dev_priv->gtt.scratch.page);
 }
 
 static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
@@ -809,6 +856,13 @@ int i915_gem_gtt_init(struct drm_device *dev)
        } else {
                dev_priv->gtt.gtt_probe = gen6_gmch_probe;
                dev_priv->gtt.gtt_remove = gen6_gmch_remove;
+               if (IS_HASWELL(dev)) {
+                       dev_priv->gtt.pte_encode = hsw_pte_encode;
+               } else if (IS_VALLEYVIEW(dev)) {
+                       dev_priv->gtt.pte_encode = byt_pte_encode;
+               } else {
+                       dev_priv->gtt.pte_encode = gen6_pte_encode;
+               }
        }
 
        ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total,
This page took 0.030155 seconds and 5 git commands to generate.