aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c146
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.h2
2 files changed, 129 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index a322e31655b5..641d3f45aa1e 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -346,7 +346,7 @@ static struct i915_page_table_entry *alloc_pt_single(struct drm_device *dev)
346 if (!pt->used_ptes) 346 if (!pt->used_ptes)
347 goto fail_bitmap; 347 goto fail_bitmap;
348 348
349 pt->page = alloc_page(GFP_KERNEL | __GFP_ZERO); 349 pt->page = alloc_page(GFP_KERNEL);
350 if (!pt->page) 350 if (!pt->page)
351 goto fail_page; 351 goto fail_page;
352 352
@@ -381,7 +381,7 @@ fail_bitmap:
381 * Return: 0 if allocation succeeded. 381 * Return: 0 if allocation succeeded.
382 */ 382 */
383static int alloc_pt_range(struct i915_page_directory_entry *pd, uint16_t pde, size_t count, 383static int alloc_pt_range(struct i915_page_directory_entry *pd, uint16_t pde, size_t count,
384 struct drm_device *dev) 384 struct drm_device *dev)
385{ 385{
386 int i, ret; 386 int i, ret;
387 387
@@ -1165,13 +1165,70 @@ static inline void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
1165 ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask; 1165 ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask;
1166} 1166}
1167 1167
1168static void gen6_initialize_pt(struct i915_address_space *vm,
1169 struct i915_page_table_entry *pt)
1170{
1171 gen6_pte_t *pt_vaddr, scratch_pte;
1172 int i;
1173
1174 WARN_ON(vm->scratch.addr == 0);
1175
1176 scratch_pte = vm->pte_encode(vm->scratch.addr,
1177 I915_CACHE_LLC, true, 0);
1178
1179 pt_vaddr = kmap_atomic(pt->page);
1180
1181 for (i = 0; i < GEN6_PTES; i++)
1182 pt_vaddr[i] = scratch_pte;
1183
1184 kunmap_atomic(pt_vaddr);
1185}
1186
1168static int gen6_alloc_va_range(struct i915_address_space *vm, 1187static int gen6_alloc_va_range(struct i915_address_space *vm,
1169 uint64_t start, uint64_t length) 1188 uint64_t start, uint64_t length)
1170{ 1189{
1190 DECLARE_BITMAP(new_page_tables, I915_PDES);
1191 struct drm_device *dev = vm->dev;
1192 struct drm_i915_private *dev_priv = dev->dev_private;
1171 struct i915_hw_ppgtt *ppgtt = 1193 struct i915_hw_ppgtt *ppgtt =
1172 container_of(vm, struct i915_hw_ppgtt, base); 1194 container_of(vm, struct i915_hw_ppgtt, base);
1173 struct i915_page_table_entry *pt; 1195 struct i915_page_table_entry *pt;
1196 const uint32_t start_save = start, length_save = length;
1174 uint32_t pde, temp; 1197 uint32_t pde, temp;
1198 int ret;
1199
1200 WARN_ON(upper_32_bits(start));
1201
1202 bitmap_zero(new_page_tables, I915_PDES);
1203
1204 /* The allocation is done in two stages so that we can bail out with
1205 * minimal amount of pain. The first stage finds new page tables that
1206 * need allocation. The second stage marks use ptes within the page
1207 * tables.
1208 */
1209 gen6_for_each_pde(pt, &ppgtt->pd, start, length, temp, pde) {
1210 if (pt != ppgtt->scratch_pt) {
1211 WARN_ON(bitmap_empty(pt->used_ptes, GEN6_PTES));
1212 continue;
1213 }
1214
1215 /* We've already allocated a page table */
1216 WARN_ON(!bitmap_empty(pt->used_ptes, GEN6_PTES));
1217
1218 pt = alloc_pt_single(dev);
1219 if (IS_ERR(pt)) {
1220 ret = PTR_ERR(pt);
1221 goto unwind_out;
1222 }
1223
1224 gen6_initialize_pt(vm, pt);
1225
1226 ppgtt->pd.page_table[pde] = pt;
1227 set_bit(pde, new_page_tables);
1228 }
1229
1230 start = start_save;
1231 length = length_save;
1175 1232
1176 gen6_for_each_pde(pt, &ppgtt->pd, start, length, temp, pde) { 1233 gen6_for_each_pde(pt, &ppgtt->pd, start, length, temp, pde) {
1177 DECLARE_BITMAP(tmp_bitmap, GEN6_PTES); 1234 DECLARE_BITMAP(tmp_bitmap, GEN6_PTES);
@@ -1180,21 +1237,46 @@ static int gen6_alloc_va_range(struct i915_address_space *vm,
1180 bitmap_set(tmp_bitmap, gen6_pte_index(start), 1237 bitmap_set(tmp_bitmap, gen6_pte_index(start),
1181 gen6_pte_count(start, length)); 1238 gen6_pte_count(start, length));
1182 1239
1183 bitmap_or(pt->used_ptes, pt->used_ptes, tmp_bitmap, 1240 if (test_and_clear_bit(pde, new_page_tables))
1241 gen6_write_pde(&ppgtt->pd, pde, pt);
1242
1243 bitmap_or(pt->used_ptes, tmp_bitmap, pt->used_ptes,
1184 GEN6_PTES); 1244 GEN6_PTES);
1185 } 1245 }
1186 1246
1247 WARN_ON(!bitmap_empty(new_page_tables, I915_PDES));
1248
1249 /* Make sure write is complete before other code can use this page
1250 * table. Also require for WC mapped PTEs */
1251 readl(dev_priv->gtt.gsm);
1252
1187 mark_tlbs_dirty(ppgtt); 1253 mark_tlbs_dirty(ppgtt);
1188 return 0; 1254 return 0;
1255
1256unwind_out:
1257 for_each_set_bit(pde, new_page_tables, I915_PDES) {
1258 struct i915_page_table_entry *pt = ppgtt->pd.page_table[pde];
1259
1260 ppgtt->pd.page_table[pde] = ppgtt->scratch_pt;
1261 unmap_and_free_pt(pt, vm->dev);
1262 }
1263
1264 mark_tlbs_dirty(ppgtt);
1265 return ret;
1189} 1266}
1190 1267
1191static void gen6_ppgtt_free(struct i915_hw_ppgtt *ppgtt) 1268static void gen6_ppgtt_free(struct i915_hw_ppgtt *ppgtt)
1192{ 1269{
1193 int i; 1270 int i;
1194 1271
1195 for (i = 0; i < ppgtt->num_pd_entries; i++) 1272 for (i = 0; i < ppgtt->num_pd_entries; i++) {
1196 unmap_and_free_pt(ppgtt->pd.page_table[i], ppgtt->base.dev); 1273 struct i915_page_table_entry *pt = ppgtt->pd.page_table[i];
1274
1275 if (pt != ppgtt->scratch_pt)
1276 unmap_and_free_pt(ppgtt->pd.page_table[i], ppgtt->base.dev);
1277 }
1197 1278
1279 unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev);
1198 unmap_and_free_pd(&ppgtt->pd); 1280 unmap_and_free_pd(&ppgtt->pd);
1199} 1281}
1200 1282
@@ -1220,6 +1302,12 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
1220 * size. We allocate at the top of the GTT to avoid fragmentation. 1302 * size. We allocate at the top of the GTT to avoid fragmentation.
1221 */ 1303 */
1222 BUG_ON(!drm_mm_initialized(&dev_priv->gtt.base.mm)); 1304 BUG_ON(!drm_mm_initialized(&dev_priv->gtt.base.mm));
1305 ppgtt->scratch_pt = alloc_pt_single(ppgtt->base.dev);
1306 if (IS_ERR(ppgtt->scratch_pt))
1307 return PTR_ERR(ppgtt->scratch_pt);
1308
1309 gen6_initialize_pt(&ppgtt->base, ppgtt->scratch_pt);
1310
1223alloc: 1311alloc:
1224 ret = drm_mm_insert_node_in_range_generic(&dev_priv->gtt.base.mm, 1312 ret = drm_mm_insert_node_in_range_generic(&dev_priv->gtt.base.mm,
1225 &ppgtt->node, GEN6_PD_SIZE, 1313 &ppgtt->node, GEN6_PD_SIZE,
@@ -1250,6 +1338,7 @@ alloc:
1250 return 0; 1338 return 0;
1251 1339
1252err_out: 1340err_out:
1341 unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev);
1253 return ret; 1342 return ret;
1254} 1343}
1255 1344
@@ -1261,18 +1350,20 @@ static int gen6_ppgtt_alloc(struct i915_hw_ppgtt *ppgtt)
1261 if (ret) 1350 if (ret)
1262 return ret; 1351 return ret;
1263 1352
1264 ret = alloc_pt_range(&ppgtt->pd, 0, ppgtt->num_pd_entries, 1353 return 0;
1265 ppgtt->base.dev); 1354}
1266 1355
1267 if (ret) { 1356static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt,
1268 drm_mm_remove_node(&ppgtt->node); 1357 uint64_t start, uint64_t length)
1269 return ret; 1358{
1270 } 1359 struct i915_page_table_entry *unused;
1360 uint32_t pde, temp;
1271 1361
1272 return 0; 1362 gen6_for_each_pde(unused, &ppgtt->pd, start, length, temp, pde)
1363 ppgtt->pd.page_table[pde] = ppgtt->scratch_pt;
1273} 1364}
1274 1365
1275static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) 1366static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt, bool aliasing)
1276{ 1367{
1277 struct drm_device *dev = ppgtt->base.dev; 1368 struct drm_device *dev = ppgtt->base.dev;
1278 struct drm_i915_private *dev_priv = dev->dev_private; 1369 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1295,6 +1386,17 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
1295 if (ret) 1386 if (ret)
1296 return ret; 1387 return ret;
1297 1388
1389 if (aliasing) {
1390 /* preallocate all pts */
1391 ret = alloc_pt_range(&ppgtt->pd, 0, ppgtt->num_pd_entries,
1392 ppgtt->base.dev);
1393
1394 if (ret) {
1395 gen6_ppgtt_cleanup(&ppgtt->base);
1396 return ret;
1397 }
1398 }
1399
1298 ppgtt->base.allocate_va_range = gen6_alloc_va_range; 1400 ppgtt->base.allocate_va_range = gen6_alloc_va_range;
1299 ppgtt->base.clear_range = gen6_ppgtt_clear_range; 1401 ppgtt->base.clear_range = gen6_ppgtt_clear_range;
1300 ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; 1402 ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
@@ -1309,7 +1411,10 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
1309 ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm + 1411 ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm +
1310 ppgtt->pd.pd_offset / sizeof(gen6_pte_t); 1412 ppgtt->pd.pd_offset / sizeof(gen6_pte_t);
1311 1413
1312 ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true); 1414 if (aliasing)
1415 ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true);
1416 else
1417 gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total);
1313 1418
1314 gen6_write_page_range(dev_priv, &ppgtt->pd, 0, ppgtt->base.total); 1419 gen6_write_page_range(dev_priv, &ppgtt->pd, 0, ppgtt->base.total);
1315 1420
@@ -1323,7 +1428,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
1323 return 0; 1428 return 0;
1324} 1429}
1325 1430
1326static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) 1431static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt,
1432 bool aliasing)
1327{ 1433{
1328 struct drm_i915_private *dev_priv = dev->dev_private; 1434 struct drm_i915_private *dev_priv = dev->dev_private;
1329 1435
@@ -1331,7 +1437,7 @@ static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
1331 ppgtt->base.scratch = dev_priv->gtt.base.scratch; 1437 ppgtt->base.scratch = dev_priv->gtt.base.scratch;
1332 1438
1333 if (INTEL_INFO(dev)->gen < 8) 1439 if (INTEL_INFO(dev)->gen < 8)
1334 return gen6_ppgtt_init(ppgtt); 1440 return gen6_ppgtt_init(ppgtt, aliasing);
1335 else 1441 else
1336 return gen8_ppgtt_init(ppgtt, dev_priv->gtt.base.total); 1442 return gen8_ppgtt_init(ppgtt, dev_priv->gtt.base.total);
1337} 1443}
@@ -1340,7 +1446,7 @@ int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
1340 struct drm_i915_private *dev_priv = dev->dev_private; 1446 struct drm_i915_private *dev_priv = dev->dev_private;
1341 int ret = 0; 1447 int ret = 0;
1342 1448
1343 ret = __hw_ppgtt_init(dev, ppgtt); 1449 ret = __hw_ppgtt_init(dev, ppgtt, false);
1344 if (ret == 0) { 1450 if (ret == 0) {
1345 kref_init(&ppgtt->ref); 1451 kref_init(&ppgtt->ref);
1346 drm_mm_init(&ppgtt->base.mm, ppgtt->base.start, 1452 drm_mm_init(&ppgtt->base.mm, ppgtt->base.start,
@@ -1975,9 +2081,11 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
1975 if (!ppgtt) 2081 if (!ppgtt)
1976 return -ENOMEM; 2082 return -ENOMEM;
1977 2083
1978 ret = __hw_ppgtt_init(dev, ppgtt); 2084 ret = __hw_ppgtt_init(dev, ppgtt, true);
1979 if (ret != 0) 2085 if (ret) {
2086 kfree(ppgtt);
1980 return ret; 2087 return ret;
2088 }
1981 2089
1982 dev_priv->mm.aliasing_ppgtt = ppgtt; 2090 dev_priv->mm.aliasing_ppgtt = ppgtt;
1983 } 2091 }
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 3d873467377e..3f0ad9f25441 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -320,6 +320,8 @@ struct i915_hw_ppgtt {
320 struct i915_page_directory_entry pd; 320 struct i915_page_directory_entry pd;
321 }; 321 };
322 322
323 struct i915_page_table_entry *scratch_pt;
324
323 struct drm_i915_file_private *file_priv; 325 struct drm_i915_file_private *file_priv;
324 326
325 gen6_pte_t __iomem *pd_addr; 327 gen6_pte_t __iomem *pd_addr;