diff options
Diffstat (limited to 'drivers/gpu/drm')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 111 |
2 files changed, 65 insertions, 56 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fb0815bebe0f..4be7c68bf5fd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -412,6 +412,15 @@ struct i915_hw_ppgtt { | |||
| 412 | uint32_t pd_offset; | 412 | uint32_t pd_offset; |
| 413 | dma_addr_t *pt_dma_addr; | 413 | dma_addr_t *pt_dma_addr; |
| 414 | dma_addr_t scratch_page_dma_addr; | 414 | dma_addr_t scratch_page_dma_addr; |
| 415 | |||
| 416 | /* pte functions, mirroring the interface of the global gtt. */ | ||
| 417 | void (*clear_range)(struct i915_hw_ppgtt *ppgtt, | ||
| 418 | unsigned int first_entry, | ||
| 419 | unsigned int num_entries); | ||
| 420 | void (*insert_entries)(struct i915_hw_ppgtt *ppgtt, | ||
| 421 | struct sg_table *st, | ||
| 422 | unsigned int pg_start, | ||
| 423 | enum i915_cache_level cache_level); | ||
| 415 | }; | 424 | }; |
| 416 | 425 | ||
| 417 | 426 | ||
| @@ -1662,7 +1671,6 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, | |||
| 1662 | struct drm_file *file); | 1671 | struct drm_file *file); |
| 1663 | 1672 | ||
| 1664 | /* i915_gem_gtt.c */ | 1673 | /* i915_gem_gtt.c */ |
| 1665 | int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); | ||
| 1666 | void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev); | 1674 | void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev); |
| 1667 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, | 1675 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, |
| 1668 | struct drm_i915_gem_object *obj, | 1676 | struct drm_i915_gem_object *obj, |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 4712626f8dc1..f63dbc7a89ce 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
| @@ -77,7 +77,7 @@ static inline gtt_pte_t pte_encode(struct drm_device *dev, | |||
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | /* PPGTT support for Sandybdrige/Gen6 and later */ | 79 | /* PPGTT support for Sandybdrige/Gen6 and later */ |
| 80 | static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, | 80 | static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, |
| 81 | unsigned first_entry, | 81 | unsigned first_entry, |
| 82 | unsigned num_entries) | 82 | unsigned num_entries) |
| 83 | { | 83 | { |
| @@ -108,7 +108,51 @@ static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt, | |||
| 108 | } | 108 | } |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) | 111 | static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt, |
| 112 | struct sg_table *pages, | ||
| 113 | unsigned first_entry, | ||
| 114 | enum i915_cache_level cache_level) | ||
| 115 | { | ||
| 116 | gtt_pte_t *pt_vaddr; | ||
| 117 | unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; | ||
| 118 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; | ||
| 119 | unsigned i, j, m, segment_len; | ||
| 120 | dma_addr_t page_addr; | ||
| 121 | struct scatterlist *sg; | ||
| 122 | |||
| 123 | /* init sg walking */ | ||
| 124 | sg = pages->sgl; | ||
| 125 | i = 0; | ||
| 126 | segment_len = sg_dma_len(sg) >> PAGE_SHIFT; | ||
| 127 | m = 0; | ||
| 128 | |||
| 129 | while (i < pages->nents) { | ||
| 130 | pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]); | ||
| 131 | |||
| 132 | for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) { | ||
| 133 | page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT); | ||
| 134 | pt_vaddr[j] = pte_encode(ppgtt->dev, page_addr, | ||
| 135 | cache_level); | ||
| 136 | |||
| 137 | /* grab the next page */ | ||
| 138 | if (++m == segment_len) { | ||
| 139 | if (++i == pages->nents) | ||
| 140 | break; | ||
| 141 | |||
| 142 | sg = sg_next(sg); | ||
| 143 | segment_len = sg_dma_len(sg) >> PAGE_SHIFT; | ||
| 144 | m = 0; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | kunmap_atomic(pt_vaddr); | ||
| 149 | |||
| 150 | first_pte = 0; | ||
| 151 | act_pd++; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) | ||
| 112 | { | 156 | { |
| 113 | struct drm_i915_private *dev_priv = dev->dev_private; | 157 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 114 | struct i915_hw_ppgtt *ppgtt; | 158 | struct i915_hw_ppgtt *ppgtt; |
| @@ -127,6 +171,8 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) | |||
| 127 | 171 | ||
| 128 | ppgtt->dev = dev; | 172 | ppgtt->dev = dev; |
| 129 | ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; | 173 | ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES; |
| 174 | ppgtt->clear_range = gen6_ppgtt_clear_range; | ||
| 175 | ppgtt->insert_entries = gen6_ppgtt_insert_entries; | ||
| 130 | ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, | 176 | ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, |
| 131 | GFP_KERNEL); | 177 | GFP_KERNEL); |
| 132 | if (!ppgtt->pt_pages) | 178 | if (!ppgtt->pt_pages) |
| @@ -159,8 +205,8 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) | |||
| 159 | 205 | ||
| 160 | ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma; | 206 | ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma; |
| 161 | 207 | ||
| 162 | i915_ppgtt_clear_range(ppgtt, 0, | 208 | ppgtt->clear_range(ppgtt, 0, |
| 163 | ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); | 209 | ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES); |
| 164 | 210 | ||
| 165 | ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(gtt_pte_t); | 211 | ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(gtt_pte_t); |
| 166 | 212 | ||
| @@ -209,66 +255,21 @@ void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev) | |||
| 209 | kfree(ppgtt); | 255 | kfree(ppgtt); |
| 210 | } | 256 | } |
| 211 | 257 | ||
| 212 | static void i915_ppgtt_insert_sg_entries(struct i915_hw_ppgtt *ppgtt, | ||
| 213 | const struct sg_table *pages, | ||
| 214 | unsigned first_entry, | ||
| 215 | enum i915_cache_level cache_level) | ||
| 216 | { | ||
| 217 | gtt_pte_t *pt_vaddr; | ||
| 218 | unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES; | ||
| 219 | unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; | ||
| 220 | unsigned i, j, m, segment_len; | ||
| 221 | dma_addr_t page_addr; | ||
| 222 | struct scatterlist *sg; | ||
| 223 | |||
| 224 | /* init sg walking */ | ||
| 225 | sg = pages->sgl; | ||
| 226 | i = 0; | ||
| 227 | segment_len = sg_dma_len(sg) >> PAGE_SHIFT; | ||
| 228 | m = 0; | ||
| 229 | |||
| 230 | while (i < pages->nents) { | ||
| 231 | pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pd]); | ||
| 232 | |||
| 233 | for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) { | ||
| 234 | page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT); | ||
| 235 | pt_vaddr[j] = pte_encode(ppgtt->dev, page_addr, | ||
| 236 | cache_level); | ||
| 237 | |||
| 238 | /* grab the next page */ | ||
| 239 | if (++m == segment_len) { | ||
| 240 | if (++i == pages->nents) | ||
| 241 | break; | ||
| 242 | |||
| 243 | sg = sg_next(sg); | ||
| 244 | segment_len = sg_dma_len(sg) >> PAGE_SHIFT; | ||
| 245 | m = 0; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | kunmap_atomic(pt_vaddr); | ||
| 250 | |||
| 251 | first_pte = 0; | ||
| 252 | act_pd++; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, | 258 | void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, |
| 257 | struct drm_i915_gem_object *obj, | 259 | struct drm_i915_gem_object *obj, |
| 258 | enum i915_cache_level cache_level) | 260 | enum i915_cache_level cache_level) |
| 259 | { | 261 | { |
| 260 | i915_ppgtt_insert_sg_entries(ppgtt, | 262 | ppgtt->insert_entries(ppgtt, obj->pages, |
| 261 | obj->pages, | 263 | obj->gtt_space->start >> PAGE_SHIFT, |
| 262 | obj->gtt_space->start >> PAGE_SHIFT, | 264 | cache_level); |
| 263 | cache_level); | ||
| 264 | } | 265 | } |
| 265 | 266 | ||
| 266 | void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, | 267 | void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, |
| 267 | struct drm_i915_gem_object *obj) | 268 | struct drm_i915_gem_object *obj) |
| 268 | { | 269 | { |
| 269 | i915_ppgtt_clear_range(ppgtt, | 270 | ppgtt->clear_range(ppgtt, |
| 270 | obj->gtt_space->start >> PAGE_SHIFT, | 271 | obj->gtt_space->start >> PAGE_SHIFT, |
| 271 | obj->base.size >> PAGE_SHIFT); | 272 | obj->base.size >> PAGE_SHIFT); |
| 272 | } | 273 | } |
| 273 | 274 | ||
| 274 | void i915_gem_init_ppgtt(struct drm_device *dev) | 275 | void i915_gem_init_ppgtt(struct drm_device *dev) |
