| From 951c1081a166a1a0f58a7a310c3c72057d097631 Mon Sep 17 00:00:00 2001 |
| From: Kenneth Graunke <kenneth@whitecape.org> |
| Date: Mon, 22 Apr 2013 00:53:49 -0700 |
| Subject: drm/i915: Add PTE encoding function to the gtt/ppgtt vtables. |
| |
| Sandybridge/Ivybridge, Bay Trail, and Haswell all have slightly |
| different page table entry formats. Rather than polluting one function |
| with generation checks, simply use a function pointer and set up the |
| correct PTE encoding function at startup. |
| |
| v2: Move the gen6_gtt_pte_t typedef to i915_drv.h so that the function |
| pointers and implementations have identical signatures. Also remove |
| inline keyword on gen6_pte_encode. Both suggested by Jani Nikula. |
| |
| Signed-off-by: Kenneth Graunke <kenneth@whitecape.org> |
| Reviewed-by: Jani Nikula <jani.nikula@linux.intel.com> |
| Tested-by: Daniel Leung <daniel.leung@linux.intel.com> [v1] |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| (cherry picked from commit 2d04befb949744998284d8551ae7cd47059b8a53) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/gpu/drm/i915/i915_drv.h | 8 ++++++++ |
| drivers/gpu/drm/i915/i915_gem_gtt.c | 30 ++++++++++++++++-------------- |
| 2 files changed, 24 insertions(+), 14 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h |
| index b32a0b18f003..0ede85bcb45b 100644 |
| --- a/drivers/gpu/drm/i915/i915_drv.h |
| +++ b/drivers/gpu/drm/i915/i915_drv.h |
| @@ -395,6 +395,8 @@ enum i915_cache_level { |
| I915_CACHE_LLC_MLC, /* gen6+, in docs at least! */ |
| }; |
| |
| +typedef uint32_t gen6_gtt_pte_t; |
| + |
| /* The Graphics Translation Table is the way in which GEN hardware translates a |
| * Graphics Virtual Address into a Physical Address. In addition to the normal |
| * collateral associated with any va->pa translations GEN hardware also has a |
| @@ -430,6 +432,9 @@ struct i915_gtt { |
| struct sg_table *st, |
| unsigned int pg_start, |
| enum i915_cache_level cache_level); |
| + gen6_gtt_pte_t (*pte_encode)(struct drm_device *dev, |
| + dma_addr_t addr, |
| + enum i915_cache_level level); |
| }; |
| #define gtt_total_entries(gtt) ((gtt).total >> PAGE_SHIFT) |
| |
| @@ -451,6 +456,9 @@ struct i915_hw_ppgtt { |
| struct sg_table *st, |
| unsigned int pg_start, |
| enum i915_cache_level cache_level); |
| + gen6_gtt_pte_t (*pte_encode)(struct drm_device *dev, |
| + dma_addr_t addr, |
| + enum i915_cache_level level); |
| int (*enable)(struct drm_device *dev); |
| void (*cleanup)(struct i915_hw_ppgtt *ppgtt); |
| }; |
| diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c |
| index bdb0d7717bc7..a6b4af7b425a 100644 |
| --- a/drivers/gpu/drm/i915/i915_gem_gtt.c |
| +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c |
| @@ -28,8 +28,6 @@ |
| #include "i915_trace.h" |
| #include "intel_drv.h" |
| |
| -typedef uint32_t gen6_gtt_pte_t; |
| - |
| /* PPGTT stuff */ |
| #define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) |
| |
| @@ -44,9 +42,9 @@ 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); |
| @@ -154,9 +152,9 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, |
| 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, |
| + ppgtt->scratch_page_dma_addr, |
| + I915_CACHE_LLC); |
| |
| while (num_entries) { |
| last_pte = first_pte + num_entries; |
| @@ -191,8 +189,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++; |
| @@ -235,6 +233,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) |
| * now. */ |
| first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt); |
| |
| + ppgtt->pte_encode = gen6_pte_encode; |
| ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; |
| ppgtt->enable = gen6_ppgtt_enable; |
| ppgtt->clear_range = gen6_ppgtt_clear_range; |
| @@ -437,7 +436,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), >t_entries[i]); |
| + iowrite32(dev_priv->gtt.pte_encode(dev, addr, level), |
| + >t_entries[i]); |
| i++; |
| } |
| |
| @@ -449,7 +449,7 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev, |
| */ |
| if (i != 0) |
| WARN_ON(readl(>t_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 +474,9 @@ 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_page_dma, |
| + I915_CACHE_LLC); |
| for (i = 0; i < num_entries; i++) |
| iowrite32(scratch_pte, >t_base[i]); |
| readl(gtt_base); |
| @@ -809,6 +810,7 @@ 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; |
| + dev_priv->gtt.pte_encode = gen6_pte_encode; |
| } |
| |
| ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total, |
| -- |
| 1.8.5.rc3 |
| |