1// SPDX-License-Identifier: MIT 2/* 3 * Copyright(c) 2019-2022, Intel Corporation. All rights reserved. 4 */ 5 6#include <linux/irq.h> 7#include <linux/mei_aux.h> 8#include "i915_drv.h" 9#include "i915_reg.h" 10#include "gem/i915_gem_lmem.h" 11#include "gem/i915_gem_region.h" 12#include "gt/intel_gsc.h" 13#include "gt/intel_gt.h" 14 15#define GSC_BAR_LENGTH 0x00000FFC 16 17#ifdef notyet 18static void gsc_irq_mask(struct irq_data *d) 19{ 20 /* generic irq handling */ 21} 22 23static void gsc_irq_unmask(struct irq_data *d) 24{ 25 /* generic irq handling */ 26} 27 28static struct irq_chip gsc_irq_chip = { 29 .name = "gsc_irq_chip", 30 .irq_mask = gsc_irq_mask, 31 .irq_unmask = gsc_irq_unmask, 32}; 33#endif 34 35static int gsc_irq_init(int irq) 36{ 37 STUB(); 38 return -ENOSYS; 39#ifdef notyet 40 irq_set_chip_and_handler_name(irq, &gsc_irq_chip, 41 handle_simple_irq, "gsc_irq_handler"); 42 43 return irq_set_chip_data(irq, NULL); 44#endif 45} 46 47static int 48gsc_ext_om_alloc(struct intel_gsc *gsc, struct intel_gsc_intf *intf, size_t size) 49{ 50 struct intel_gt *gt = gsc_to_gt(gsc); 51 struct drm_i915_gem_object *obj; 52 int err; 53 54 obj = i915_gem_object_create_lmem(gt->i915, size, 55 I915_BO_ALLOC_CONTIGUOUS | 56 I915_BO_ALLOC_CPU_CLEAR); 57 if (IS_ERR(obj)) { 58 drm_err(>->i915->drm, "Failed to allocate gsc memory\n"); 59 return PTR_ERR(obj); 60 } 61 62 err = i915_gem_object_pin_pages_unlocked(obj); 63 if (err) { 64 drm_err(>->i915->drm, "Failed to pin pages for gsc memory\n"); 65 goto out_put; 66 } 67 68 intf->gem_obj = obj; 69 70 return 0; 71 72out_put: 73 i915_gem_object_put(obj); 74 return err; 75} 76 77static void gsc_ext_om_destroy(struct intel_gsc_intf *intf) 78{ 79 struct drm_i915_gem_object *obj = fetch_and_zero(&intf->gem_obj); 80 81 if (!obj) 82 return; 83 84 if (i915_gem_object_has_pinned_pages(obj)) 85 i915_gem_object_unpin_pages(obj); 86 87 i915_gem_object_put(obj); 88} 89 90struct gsc_def { 91 const char *name; 92 unsigned long bar; 93 size_t bar_size; 94 bool use_polling; 95 bool slow_firmware; 96 size_t lmem_size; 97}; 98 99/* gsc resources and definitions (HECI1 and HECI2) */ 100static const struct gsc_def gsc_def_dg1[] = { 101 { 102 /* HECI1 not yet implemented. */ 103 }, 104 { 105 .name = "mei-gscfi", 106 .bar = DG1_GSC_HECI2_BASE, 107 .bar_size = GSC_BAR_LENGTH, 108 } 109}; 110 111static const struct gsc_def gsc_def_xehpsdv[] = { 112 { 113 /* HECI1 not enabled on the device. */ 114 }, 115 { 116 .name = "mei-gscfi", 117 .bar = DG1_GSC_HECI2_BASE, 118 .bar_size = GSC_BAR_LENGTH, 119 .use_polling = true, 120 .slow_firmware = true, 121 } 122}; 123 124static const struct gsc_def gsc_def_dg2[] = { 125 { 126 .name = "mei-gsc", 127 .bar = DG2_GSC_HECI1_BASE, 128 .bar_size = GSC_BAR_LENGTH, 129 .lmem_size = SZ_4M, 130 }, 131 { 132 .name = "mei-gscfi", 133 .bar = DG2_GSC_HECI2_BASE, 134 .bar_size = GSC_BAR_LENGTH, 135 } 136}; 137 138static void gsc_release_dev(struct device *dev) 139{ 140 STUB(); 141#ifdef notyet 142 struct auxiliary_device *aux_dev = to_auxiliary_dev(dev); 143 struct mei_aux_device *adev = auxiliary_dev_to_mei_aux_dev(aux_dev); 144 145 kfree(adev); 146#endif 147} 148 149static void gsc_destroy_one(struct drm_i915_private *i915, 150 struct intel_gsc *gsc, unsigned int intf_id) 151{ 152 STUB(); 153#ifdef notyet 154 struct intel_gsc_intf *intf = &gsc->intf[intf_id]; 155 156 if (intf->adev) { 157 struct auxiliary_device *aux_dev = &intf->adev->aux_dev; 158 159 if (intf_id == 0) 160 intel_huc_unregister_gsc_notifier(&gsc_to_gt(gsc)->uc.huc, 161 aux_dev->dev.bus); 162 163 auxiliary_device_delete(aux_dev); 164 auxiliary_device_uninit(aux_dev); 165 intf->adev = NULL; 166 } 167 168 if (intf->irq >= 0) 169 irq_free_desc(intf->irq); 170 intf->irq = -1; 171 172 gsc_ext_om_destroy(intf); 173#endif 174} 175 176static void gsc_init_one(struct drm_i915_private *i915, struct intel_gsc *gsc, 177 unsigned int intf_id) 178{ 179 STUB(); 180#ifdef notyet 181 struct pci_dev *pdev = i915->drm.pdev; 182 struct mei_aux_device *adev; 183 struct auxiliary_device *aux_dev; 184 const struct gsc_def *def; 185 struct intel_gsc_intf *intf = &gsc->intf[intf_id]; 186 int ret; 187 188 intf->irq = -1; 189 intf->id = intf_id; 190 191 /* 192 * On the multi-tile setups the GSC is functional on the first tile only 193 */ 194 if (gsc_to_gt(gsc)->info.id != 0) { 195 drm_dbg(&i915->drm, "Not initializing gsc for remote tiles\n"); 196 return; 197 } 198 199 if (intf_id == 0 && !HAS_HECI_PXP(i915)) 200 return; 201 202 if (IS_DG1(i915)) { 203 def = &gsc_def_dg1[intf_id]; 204 } else if (IS_XEHPSDV(i915)) { 205 def = &gsc_def_xehpsdv[intf_id]; 206 } else if (IS_DG2(i915)) { 207 def = &gsc_def_dg2[intf_id]; 208 } else { 209 drm_warn_once(&i915->drm, "Unknown platform\n"); 210 return; 211 } 212 213 if (!def->name) { 214 drm_warn_once(&i915->drm, "HECI%d is not implemented!\n", intf_id + 1); 215 return; 216 } 217 218 /* skip irq initialization */ 219 if (def->use_polling) 220 goto add_device; 221 222 intf->irq = irq_alloc_desc(0); 223 if (intf->irq < 0) { 224 drm_err(&i915->drm, "gsc irq error %d\n", intf->irq); 225 goto fail; 226 } 227 228 ret = gsc_irq_init(intf->irq); 229 if (ret < 0) { 230 drm_err(&i915->drm, "gsc irq init failed %d\n", ret); 231 goto fail; 232 } 233 234add_device: 235 adev = kzalloc(sizeof(*adev), GFP_KERNEL); 236 if (!adev) 237 goto fail; 238 239 if (def->lmem_size) { 240 drm_dbg(&i915->drm, "setting up GSC lmem\n"); 241 242 if (gsc_ext_om_alloc(gsc, intf, def->lmem_size)) { 243 drm_err(&i915->drm, "setting up gsc extended operational memory failed\n"); 244 kfree(adev); 245 goto fail; 246 } 247 248 adev->ext_op_mem.start = i915_gem_object_get_dma_address(intf->gem_obj, 0); 249 adev->ext_op_mem.end = adev->ext_op_mem.start + def->lmem_size; 250 } 251 252 adev->irq = intf->irq; 253 adev->bar.parent = &pdev->resource[0]; 254 adev->bar.start = def->bar + pdev->resource[0].start; 255 adev->bar.end = adev->bar.start + def->bar_size - 1; 256 adev->bar.flags = IORESOURCE_MEM; 257 adev->bar.desc = IORES_DESC_NONE; 258 adev->slow_firmware = def->slow_firmware; 259 260 aux_dev = &adev->aux_dev; 261 aux_dev->name = def->name; 262 aux_dev->id = (pci_domain_nr(pdev->bus) << 16) | 263 PCI_DEVID(pdev->bus->number, pdev->devfn); 264 aux_dev->dev.parent = &pdev->dev; 265 aux_dev->dev.release = gsc_release_dev; 266 267 ret = auxiliary_device_init(aux_dev); 268 if (ret < 0) { 269 drm_err(&i915->drm, "gsc aux init failed %d\n", ret); 270 kfree(adev); 271 goto fail; 272 } 273 274 intf->adev = adev; /* needed by the notifier */ 275 276 if (intf_id == 0) 277 intel_huc_register_gsc_notifier(&gsc_to_gt(gsc)->uc.huc, 278 aux_dev->dev.bus); 279 280 ret = auxiliary_device_add(aux_dev); 281 if (ret < 0) { 282 drm_err(&i915->drm, "gsc aux add failed %d\n", ret); 283 if (intf_id == 0) 284 intel_huc_unregister_gsc_notifier(&gsc_to_gt(gsc)->uc.huc, 285 aux_dev->dev.bus); 286 intf->adev = NULL; 287 288 /* adev will be freed with the put_device() and .release sequence */ 289 auxiliary_device_uninit(aux_dev); 290 goto fail; 291 } 292 293 return; 294fail: 295 gsc_destroy_one(i915, gsc, intf->id); 296#endif 297} 298 299static void gsc_irq_handler(struct intel_gt *gt, unsigned int intf_id) 300{ 301 STUB(); 302#ifdef notyet 303 int ret; 304 305 if (intf_id >= INTEL_GSC_NUM_INTERFACES) { 306 drm_warn_once(>->i915->drm, "GSC irq: intf_id %d is out of range", intf_id); 307 return; 308 } 309 310 if (!HAS_HECI_GSC(gt->i915)) { 311 drm_warn_once(>->i915->drm, "GSC irq: not supported"); 312 return; 313 } 314 315 if (gt->gsc.intf[intf_id].irq < 0) 316 return; 317 318 ret = generic_handle_irq(gt->gsc.intf[intf_id].irq); 319 if (ret) 320 drm_err_ratelimited(>->i915->drm, "error handling GSC irq: %d\n", ret); 321#endif 322} 323 324void intel_gsc_irq_handler(struct intel_gt *gt, u32 iir) 325{ 326 if (iir & GSC_IRQ_INTF(0)) 327 gsc_irq_handler(gt, 0); 328 if (iir & GSC_IRQ_INTF(1)) 329 gsc_irq_handler(gt, 1); 330} 331 332void intel_gsc_init(struct intel_gsc *gsc, struct drm_i915_private *i915) 333{ 334 unsigned int i; 335 336 if (!HAS_HECI_GSC(i915)) 337 return; 338 339 for (i = 0; i < INTEL_GSC_NUM_INTERFACES; i++) 340 gsc_init_one(i915, gsc, i); 341} 342 343void intel_gsc_fini(struct intel_gsc *gsc) 344{ 345 struct intel_gt *gt = gsc_to_gt(gsc); 346 unsigned int i; 347 348 if (!HAS_HECI_GSC(gt->i915)) 349 return; 350 351 for (i = 0; i < INTEL_GSC_NUM_INTERFACES; i++) 352 gsc_destroy_one(gt->i915, gsc, i); 353} 354