Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Prepare for multiple GTs

On a multi-tile platform, each tile has its own registers + GGTT
space, and BAR 0 is extended to cover all of them.

Up to four GTs are supported in i915->gt[], with slot zero
shadowing the existing i915->gt0 to enable source compatibility
with legacy driver paths. A for_each_gt macro is added to iterate
over the GTs and will be used by upcoming patches that convert
various parts of the driver to be multi-gt aware.

Only the primary/root tile is initialized for now; the other
tiles will be detected and plugged in by future patches once the
necessary infrastructure is in place to handle them.

Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220318233938.149744-4-andi.shyti@linux.intel.com

authored by

Tvrtko Ursulin and committed by
Matthew Auld
bec68cc9 b9741faa

+184 -46
+121 -12
drivers/gpu/drm/i915/gt/intel_gt.c
··· 29 29 #include "intel_uncore.h" 30 30 #include "shmem_utils.h" 31 31 32 - void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) 32 + static void __intel_gt_init_early(struct intel_gt *gt) 33 33 { 34 34 spin_lock_init(&gt->irq_lock); 35 35 ··· 51 51 intel_rps_init_early(&gt->rps); 52 52 } 53 53 54 - void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) 54 + /* Preliminary initialization of Tile 0 */ 55 + void intel_root_gt_init_early(struct drm_i915_private *i915) 55 56 { 57 + struct intel_gt *gt = to_gt(i915); 58 + 56 59 gt->i915 = i915; 57 60 gt->uncore = &i915->uncore; 61 + 62 + __intel_gt_init_early(gt); 58 63 } 59 64 60 - int intel_gt_probe_lmem(struct intel_gt *gt) 65 + static int intel_gt_probe_lmem(struct intel_gt *gt) 61 66 { 62 67 struct drm_i915_private *i915 = gt->i915; 68 + unsigned int instance = gt->info.id; 69 + int id = INTEL_REGION_LMEM_0 + instance; 63 70 struct intel_memory_region *mem; 64 - int id; 65 71 int err; 66 72 67 73 mem = intel_gt_setup_lmem(gt); ··· 82 76 return err; 83 77 } 84 78 85 - id = INTEL_REGION_LMEM_0; 86 - 87 79 mem->id = id; 80 + mem->instance = instance; 88 81 89 82 intel_memory_region_set_name(mem, "local%u", mem->instance); 90 83 ··· 812 807 intel_gt_fini_hwconfig(gt); 813 808 } 814 809 815 - void intel_gt_driver_late_release(struct intel_gt *gt) 810 + void intel_gt_driver_late_release_all(struct drm_i915_private *i915) 816 811 { 812 + struct intel_gt *gt; 813 + unsigned int id; 814 + 817 815 /* We need to wait for inflight RCU frees to release their grip */ 818 816 rcu_barrier(); 819 817 820 - intel_uc_driver_late_release(&gt->uc); 821 - intel_gt_fini_requests(gt); 822 - intel_gt_fini_reset(gt); 823 - intel_gt_fini_timelines(gt); 824 - intel_engines_free(gt); 818 + for_each_gt(gt, i915, id) { 819 + intel_uc_driver_late_release(&gt->uc); 820 + intel_gt_fini_requests(gt); 821 + intel_gt_fini_reset(gt); 822 + intel_gt_fini_timelines(gt); 823 + intel_engines_free(gt); 824 + } 825 825 } 826 826 827 827 /** ··· 1020 1010 if (HAS_MSLICES(gt->i915)) { 1021 1011 report_steering_type(p, gt, MSLICE, dump_table); 1022 1012 report_steering_type(p, gt, LNCF, dump_table); 1013 + } 1014 + } 1015 + 1016 + static int intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr) 1017 + { 1018 + int ret; 1019 + 1020 + if (!gt_is_root(gt)) { 1021 + struct intel_uncore_mmio_debug *mmio_debug; 1022 + struct intel_uncore *uncore; 1023 + 1024 + uncore = kzalloc(sizeof(*uncore), GFP_KERNEL); 1025 + if (!uncore) 1026 + return -ENOMEM; 1027 + 1028 + mmio_debug = kzalloc(sizeof(*mmio_debug), GFP_KERNEL); 1029 + if (!mmio_debug) { 1030 + kfree(uncore); 1031 + return -ENOMEM; 1032 + } 1033 + 1034 + gt->uncore = uncore; 1035 + gt->uncore->debug = mmio_debug; 1036 + 1037 + __intel_gt_init_early(gt); 1038 + } 1039 + 1040 + intel_uncore_init_early(gt->uncore, gt); 1041 + 1042 + ret = intel_uncore_setup_mmio(gt->uncore, phys_addr); 1043 + if (ret) 1044 + return ret; 1045 + 1046 + gt->phys_addr = phys_addr; 1047 + 1048 + return 0; 1049 + } 1050 + 1051 + static void 1052 + intel_gt_tile_cleanup(struct intel_gt *gt) 1053 + { 1054 + intel_uncore_cleanup_mmio(gt->uncore); 1055 + 1056 + if (!gt_is_root(gt)) { 1057 + kfree(gt->uncore->debug); 1058 + kfree(gt->uncore); 1059 + kfree(gt); 1060 + } 1061 + } 1062 + 1063 + int intel_gt_probe_all(struct drm_i915_private *i915) 1064 + { 1065 + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 1066 + struct intel_gt *gt = &i915->gt0; 1067 + phys_addr_t phys_addr; 1068 + unsigned int mmio_bar; 1069 + int ret; 1070 + 1071 + mmio_bar = GRAPHICS_VER(i915) == 2 ? 1 : 0; 1072 + phys_addr = pci_resource_start(pdev, mmio_bar); 1073 + 1074 + /* 1075 + * We always have at least one primary GT on any device 1076 + * and it has been already initialized early during probe 1077 + * in i915_driver_probe() 1078 + */ 1079 + ret = intel_gt_tile_setup(gt, phys_addr); 1080 + if (ret) 1081 + return ret; 1082 + 1083 + i915->gt[0] = gt; 1084 + 1085 + /* TODO: add more tiles */ 1086 + return 0; 1087 + } 1088 + 1089 + int intel_gt_tiles_init(struct drm_i915_private *i915) 1090 + { 1091 + struct intel_gt *gt; 1092 + unsigned int id; 1093 + int ret; 1094 + 1095 + for_each_gt(gt, i915, id) { 1096 + ret = intel_gt_probe_lmem(gt); 1097 + if (ret) 1098 + return ret; 1099 + } 1100 + 1101 + return 0; 1102 + } 1103 + 1104 + void intel_gt_release_all(struct drm_i915_private *i915) 1105 + { 1106 + struct intel_gt *gt; 1107 + unsigned int id; 1108 + 1109 + for_each_gt(gt, i915, id) { 1110 + intel_gt_tile_cleanup(gt); 1111 + i915->gt[id] = NULL; 1023 1112 } 1024 1113 } 1025 1114
+13 -4
drivers/gpu/drm/i915/gt/intel_gt.h
··· 39 39 return container_of(huc, struct intel_gt, uc.huc); 40 40 } 41 41 42 - void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915); 43 - void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915); 42 + void intel_root_gt_init_early(struct drm_i915_private *i915); 44 43 int intel_gt_assign_ggtt(struct intel_gt *gt); 45 - int intel_gt_probe_lmem(struct intel_gt *gt); 46 44 int intel_gt_init_mmio(struct intel_gt *gt); 47 45 int __must_check intel_gt_init_hw(struct intel_gt *gt); 48 46 int intel_gt_init(struct intel_gt *gt); ··· 50 52 void intel_gt_driver_remove(struct intel_gt *gt); 51 53 void intel_gt_driver_release(struct intel_gt *gt); 52 54 53 - void intel_gt_driver_late_release(struct intel_gt *gt); 55 + void intel_gt_driver_late_release_all(struct drm_i915_private *i915); 54 56 55 57 int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout); 56 58 ··· 95 97 96 98 void intel_gt_report_steering(struct drm_printer *p, struct intel_gt *gt, 97 99 bool dump_table); 100 + 101 + int intel_gt_probe_all(struct drm_i915_private *i915); 102 + int intel_gt_tiles_init(struct drm_i915_private *i915); 103 + void intel_gt_release_all(struct drm_i915_private *i915); 104 + 105 + #define for_each_gt(gt__, i915__, id__) \ 106 + for ((id__) = 0; \ 107 + (id__) < I915_MAX_GT; \ 108 + (id__)++) \ 109 + for_each_if(((gt__) = (i915__)->gt[(id__)])) 110 + 98 111 void intel_gt_info_print(const struct intel_gt_info *info, 99 112 struct drm_printer *p); 100 113
+8 -1
drivers/gpu/drm/i915/gt/intel_gt_pm.c
··· 128 128 129 129 void intel_gt_pm_init_early(struct intel_gt *gt) 130 130 { 131 - intel_wakeref_init(&gt->wakeref, gt->uncore->rpm, &wf_ops); 131 + /* 132 + * We access the runtime_pm structure via gt->i915 here rather than 133 + * gt->uncore as we do elsewhere in the file because gt->uncore is not 134 + * yet initialized for all tiles at this point in the driver startup. 135 + * runtime_pm is per-device rather than per-tile, so this is still the 136 + * correct structure. 137 + */ 138 + intel_wakeref_init(&gt->wakeref, &gt->i915->runtime_pm, &wf_ops); 132 139 seqcount_mutex_init(&gt->stats.lock, &gt->wakeref.mutex); 133 140 } 134 141
+7
drivers/gpu/drm/i915/gt/intel_gt_types.h
··· 188 188 u8 instanceid; 189 189 } default_steering; 190 190 191 + /* 192 + * Base of per-tile GTTMMADR where we can derive the MMIO and the GGTT. 193 + */ 194 + phys_addr_t phys_addr; 195 + 191 196 struct intel_gt_info { 197 + unsigned int id; 198 + 192 199 intel_engine_mask_t engine_mask; 193 200 194 201 u32 l3bank_mask;
+12 -16
drivers/gpu/drm/i915/i915_driver.c
··· 320 320 intel_device_info_subplatform_init(dev_priv); 321 321 intel_step_init(dev_priv); 322 322 323 - intel_gt_init_early(to_gt(dev_priv), dev_priv); 324 323 intel_uncore_mmio_debug_init_early(&dev_priv->mmio_debug); 325 - intel_uncore_init_early(&dev_priv->uncore, to_gt(dev_priv)); 326 324 327 325 spin_lock_init(&dev_priv->irq_lock); 328 326 spin_lock_init(&dev_priv->gpu_error.lock); ··· 351 353 352 354 intel_wopcm_init_early(&dev_priv->wopcm); 353 355 354 - __intel_gt_init_early(to_gt(dev_priv), dev_priv); 356 + intel_root_gt_init_early(dev_priv); 355 357 356 358 i915_gem_init_early(dev_priv); 357 359 ··· 372 374 373 375 err_gem: 374 376 i915_gem_cleanup_early(dev_priv); 375 - intel_gt_driver_late_release(to_gt(dev_priv)); 377 + intel_gt_driver_late_release_all(dev_priv); 376 378 intel_region_ttm_device_fini(dev_priv); 377 379 err_ttm: 378 380 vlv_suspend_cleanup(dev_priv); ··· 391 393 intel_irq_fini(dev_priv); 392 394 intel_power_domains_cleanup(dev_priv); 393 395 i915_gem_cleanup_early(dev_priv); 394 - intel_gt_driver_late_release(to_gt(dev_priv)); 396 + intel_gt_driver_late_release_all(dev_priv); 395 397 intel_region_ttm_device_fini(dev_priv); 396 398 vlv_suspend_cleanup(dev_priv); 397 399 i915_workqueues_cleanup(dev_priv); ··· 422 424 if (ret < 0) 423 425 return ret; 424 426 425 - ret = intel_uncore_setup_mmio(&dev_priv->uncore); 426 - if (ret < 0) 427 - goto err_bridge; 428 - 429 427 ret = intel_uncore_init_mmio(&dev_priv->uncore); 430 428 if (ret) 431 - goto err_mmio; 429 + return ret; 432 430 433 431 /* Try to make sure MCHBAR is enabled before poking at it */ 434 432 intel_setup_mchbar(dev_priv); ··· 442 448 err_uncore: 443 449 intel_teardown_mchbar(dev_priv); 444 450 intel_uncore_fini_mmio(&dev_priv->uncore); 445 - err_mmio: 446 - intel_uncore_cleanup_mmio(&dev_priv->uncore); 447 - err_bridge: 448 451 pci_dev_put(dev_priv->bridge_dev); 449 452 450 453 return ret; ··· 455 464 { 456 465 intel_teardown_mchbar(dev_priv); 457 466 intel_uncore_fini_mmio(&dev_priv->uncore); 458 - intel_uncore_cleanup_mmio(&dev_priv->uncore); 459 467 pci_dev_put(dev_priv->bridge_dev); 460 468 } 461 469 ··· 587 597 if (ret) 588 598 goto err_ggtt; 589 599 590 - ret = intel_gt_probe_lmem(to_gt(dev_priv)); 600 + ret = intel_gt_tiles_init(dev_priv); 591 601 if (ret) 592 602 goto err_mem_regions; 593 603 ··· 837 847 838 848 intel_vgpu_detect(i915); 839 849 840 - ret = i915_driver_mmio_probe(i915); 850 + ret = intel_gt_probe_all(i915); 841 851 if (ret < 0) 842 852 goto out_runtime_pm_put; 853 + 854 + ret = i915_driver_mmio_probe(i915); 855 + if (ret < 0) 856 + goto out_tiles_cleanup; 843 857 844 858 ret = i915_driver_hw_probe(i915); 845 859 if (ret < 0) ··· 901 907 i915_ggtt_driver_late_release(i915); 902 908 out_cleanup_mmio: 903 909 i915_driver_mmio_release(i915); 910 + out_tiles_cleanup: 911 + intel_gt_release_all(i915); 904 912 out_runtime_pm_put: 905 913 enable_rpm_wakeref_asserts(&i915->runtime_pm); 906 914 i915_driver_late_release(i915);
+6
drivers/gpu/drm/i915/i915_drv.h
··· 808 808 /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ 809 809 struct intel_gt gt0; 810 810 811 + /* 812 + * i915->gt[0] == &i915->gt0 813 + */ 814 + #define I915_MAX_GT 4 815 + struct intel_gt *gt[I915_MAX_GT]; 816 + 811 817 struct { 812 818 struct i915_gem_contexts { 813 819 spinlock_t lock; /* locks list */
+3
drivers/gpu/drm/i915/intel_memory_region.h
··· 30 30 enum intel_region_id { 31 31 INTEL_REGION_SMEM = 0, 32 32 INTEL_REGION_LMEM_0, 33 + INTEL_REGION_LMEM_1, 34 + INTEL_REGION_LMEM_2, 35 + INTEL_REGION_LMEM_3, 33 36 INTEL_REGION_STOLEN_SMEM, 34 37 INTEL_REGION_STOLEN_LMEM, 35 38 INTEL_REGION_UNKNOWN, /* Should be last */
+3 -8
drivers/gpu/drm/i915/intel_uncore.c
··· 2039 2039 return NOTIFY_OK; 2040 2040 } 2041 2041 2042 - int intel_uncore_setup_mmio(struct intel_uncore *uncore) 2042 + int intel_uncore_setup_mmio(struct intel_uncore *uncore, phys_addr_t phys_addr) 2043 2043 { 2044 2044 struct drm_i915_private *i915 = uncore->i915; 2045 - struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 2046 - int mmio_bar; 2047 2045 int mmio_size; 2048 2046 2049 - mmio_bar = GRAPHICS_VER(i915) == 2 ? 1 : 0; 2050 2047 /* 2051 2048 * Before gen4, the registers and the GTT are behind different BARs. 2052 2049 * However, from gen4 onwards, the registers and the GTT are shared ··· 2060 2063 else 2061 2064 mmio_size = 2 * 1024 * 1024; 2062 2065 2063 - uncore->regs = pci_iomap(pdev, mmio_bar, mmio_size); 2066 + uncore->regs = ioremap(phys_addr, mmio_size); 2064 2067 if (uncore->regs == NULL) { 2065 2068 drm_err(&i915->drm, "failed to map registers\n"); 2066 2069 return -EIO; ··· 2071 2074 2072 2075 void intel_uncore_cleanup_mmio(struct intel_uncore *uncore) 2073 2076 { 2074 - struct pci_dev *pdev = to_pci_dev(uncore->i915->drm.dev); 2075 - 2076 - pci_iounmap(pdev, uncore->regs); 2077 + iounmap(uncore->regs); 2077 2078 } 2078 2079 2079 2080 void intel_uncore_init_early(struct intel_uncore *uncore,
+2 -1
drivers/gpu/drm/i915/intel_uncore.h
··· 29 29 #include <linux/notifier.h> 30 30 #include <linux/hrtimer.h> 31 31 #include <linux/io-64-nonatomic-lo-hi.h> 32 + #include <linux/types.h> 32 33 33 34 #include "i915_reg_defs.h" 34 35 ··· 222 221 intel_uncore_mmio_debug_init_early(struct intel_uncore_mmio_debug *mmio_debug); 223 222 void intel_uncore_init_early(struct intel_uncore *uncore, 224 223 struct intel_gt *gt); 225 - int intel_uncore_setup_mmio(struct intel_uncore *uncore); 224 + int intel_uncore_setup_mmio(struct intel_uncore *uncore, phys_addr_t phys_addr); 226 225 int intel_uncore_init_mmio(struct intel_uncore *uncore); 227 226 void intel_uncore_prune_engine_fw_domains(struct intel_uncore *uncore, 228 227 struct intel_gt *gt);
+9 -4
drivers/gpu/drm/i915/selftests/mock_gem_device.c
··· 73 73 destroy_workqueue(i915->wq); 74 74 75 75 intel_region_ttm_device_fini(i915); 76 - intel_gt_driver_late_release(to_gt(i915)); 76 + intel_gt_driver_late_release_all(i915); 77 77 intel_memory_regions_driver_release(i915); 78 78 79 79 drm_mode_config_cleanup(&i915->drm); ··· 111 111 .runtime_resume = pm_domain_resume, 112 112 }, 113 113 }; 114 + 115 + static void mock_gt_probe(struct drm_i915_private *i915) 116 + { 117 + i915->gt[0] = &i915->gt0; 118 + } 114 119 115 120 struct drm_i915_private *mock_gem_device(void) 116 121 { ··· 185 180 spin_lock_init(&i915->gpu_error.lock); 186 181 187 182 i915_gem_init__mm(i915); 188 - intel_gt_init_early(to_gt(i915), i915); 189 - __intel_gt_init_early(to_gt(i915), i915); 183 + intel_root_gt_init_early(i915); 190 184 mock_uncore_init(&i915->uncore, i915); 191 185 atomic_inc(&to_gt(i915)->wakeref.count); /* disable; no hw support */ 192 186 to_gt(i915)->awake = -ENODEV; 187 + mock_gt_probe(i915); 193 188 194 189 ret = intel_region_ttm_device_init(i915); 195 190 if (ret) ··· 234 229 err_drv: 235 230 intel_region_ttm_device_fini(i915); 236 231 err_ttm: 237 - intel_gt_driver_late_release(to_gt(i915)); 232 + intel_gt_driver_late_release_all(i915); 238 233 intel_memory_regions_driver_release(i915); 239 234 drm_mode_config_cleanup(&i915->drm); 240 235 mock_destroy_device(i915);