intel_gsc.c 6.9 KB

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