nitrox_isr.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/pci.h>
  3. #include <linux/printk.h>
  4. #include <linux/slab.h>
  5. #include "nitrox_dev.h"
  6. #include "nitrox_csr.h"
  7. #include "nitrox_common.h"
  8. #define NR_RING_VECTORS 3
  9. #define NPS_CORE_INT_ACTIVE_ENTRY 192
  10. /**
  11. * nps_pkt_slc_isr - IRQ handler for NPS solicit port
  12. * @irq: irq number
  13. * @data: argument
  14. */
  15. static irqreturn_t nps_pkt_slc_isr(int irq, void *data)
  16. {
  17. struct bh_data *slc = data;
  18. union nps_pkt_slc_cnts pkt_slc_cnts;
  19. pkt_slc_cnts.value = readq(slc->completion_cnt_csr_addr);
  20. /* New packet on SLC output port */
  21. if (pkt_slc_cnts.s.slc_int)
  22. tasklet_hi_schedule(&slc->resp_handler);
  23. return IRQ_HANDLED;
  24. }
  25. static void clear_nps_core_err_intr(struct nitrox_device *ndev)
  26. {
  27. u64 value;
  28. /* Write 1 to clear */
  29. value = nitrox_read_csr(ndev, NPS_CORE_INT);
  30. nitrox_write_csr(ndev, NPS_CORE_INT, value);
  31. dev_err_ratelimited(DEV(ndev), "NSP_CORE_INT 0x%016llx\n", value);
  32. }
  33. static void clear_nps_pkt_err_intr(struct nitrox_device *ndev)
  34. {
  35. union nps_pkt_int pkt_int;
  36. unsigned long value, offset;
  37. int i;
  38. pkt_int.value = nitrox_read_csr(ndev, NPS_PKT_INT);
  39. dev_err_ratelimited(DEV(ndev), "NPS_PKT_INT 0x%016llx\n",
  40. pkt_int.value);
  41. if (pkt_int.s.slc_err) {
  42. offset = NPS_PKT_SLC_ERR_TYPE;
  43. value = nitrox_read_csr(ndev, offset);
  44. nitrox_write_csr(ndev, offset, value);
  45. dev_err_ratelimited(DEV(ndev),
  46. "NPS_PKT_SLC_ERR_TYPE 0x%016lx\n", value);
  47. offset = NPS_PKT_SLC_RERR_LO;
  48. value = nitrox_read_csr(ndev, offset);
  49. nitrox_write_csr(ndev, offset, value);
  50. /* enable the solicit ports */
  51. for_each_set_bit(i, &value, BITS_PER_LONG)
  52. enable_pkt_solicit_port(ndev, i);
  53. dev_err_ratelimited(DEV(ndev),
  54. "NPS_PKT_SLC_RERR_LO 0x%016lx\n", value);
  55. offset = NPS_PKT_SLC_RERR_HI;
  56. value = nitrox_read_csr(ndev, offset);
  57. nitrox_write_csr(ndev, offset, value);
  58. dev_err_ratelimited(DEV(ndev),
  59. "NPS_PKT_SLC_RERR_HI 0x%016lx\n", value);
  60. }
  61. if (pkt_int.s.in_err) {
  62. offset = NPS_PKT_IN_ERR_TYPE;
  63. value = nitrox_read_csr(ndev, offset);
  64. nitrox_write_csr(ndev, offset, value);
  65. dev_err_ratelimited(DEV(ndev),
  66. "NPS_PKT_IN_ERR_TYPE 0x%016lx\n", value);
  67. offset = NPS_PKT_IN_RERR_LO;
  68. value = nitrox_read_csr(ndev, offset);
  69. nitrox_write_csr(ndev, offset, value);
  70. /* enable the input ring */
  71. for_each_set_bit(i, &value, BITS_PER_LONG)
  72. enable_pkt_input_ring(ndev, i);
  73. dev_err_ratelimited(DEV(ndev),
  74. "NPS_PKT_IN_RERR_LO 0x%016lx\n", value);
  75. offset = NPS_PKT_IN_RERR_HI;
  76. value = nitrox_read_csr(ndev, offset);
  77. nitrox_write_csr(ndev, offset, value);
  78. dev_err_ratelimited(DEV(ndev),
  79. "NPS_PKT_IN_RERR_HI 0x%016lx\n", value);
  80. }
  81. }
  82. static void clear_pom_err_intr(struct nitrox_device *ndev)
  83. {
  84. u64 value;
  85. value = nitrox_read_csr(ndev, POM_INT);
  86. nitrox_write_csr(ndev, POM_INT, value);
  87. dev_err_ratelimited(DEV(ndev), "POM_INT 0x%016llx\n", value);
  88. }
  89. static void clear_pem_err_intr(struct nitrox_device *ndev)
  90. {
  91. u64 value;
  92. value = nitrox_read_csr(ndev, PEM0_INT);
  93. nitrox_write_csr(ndev, PEM0_INT, value);
  94. dev_err_ratelimited(DEV(ndev), "PEM(0)_INT 0x%016llx\n", value);
  95. }
  96. static void clear_lbc_err_intr(struct nitrox_device *ndev)
  97. {
  98. union lbc_int lbc_int;
  99. u64 value, offset;
  100. int i;
  101. lbc_int.value = nitrox_read_csr(ndev, LBC_INT);
  102. dev_err_ratelimited(DEV(ndev), "LBC_INT 0x%016llx\n", lbc_int.value);
  103. if (lbc_int.s.dma_rd_err) {
  104. for (i = 0; i < NR_CLUSTERS; i++) {
  105. offset = EFL_CORE_VF_ERR_INT0X(i);
  106. value = nitrox_read_csr(ndev, offset);
  107. nitrox_write_csr(ndev, offset, value);
  108. offset = EFL_CORE_VF_ERR_INT1X(i);
  109. value = nitrox_read_csr(ndev, offset);
  110. nitrox_write_csr(ndev, offset, value);
  111. }
  112. }
  113. if (lbc_int.s.cam_soft_err) {
  114. dev_err_ratelimited(DEV(ndev), "CAM_SOFT_ERR, invalidating LBC\n");
  115. invalidate_lbc(ndev);
  116. }
  117. if (lbc_int.s.pref_dat_len_mismatch_err) {
  118. offset = LBC_PLM_VF1_64_INT;
  119. value = nitrox_read_csr(ndev, offset);
  120. nitrox_write_csr(ndev, offset, value);
  121. offset = LBC_PLM_VF65_128_INT;
  122. value = nitrox_read_csr(ndev, offset);
  123. nitrox_write_csr(ndev, offset, value);
  124. }
  125. if (lbc_int.s.rd_dat_len_mismatch_err) {
  126. offset = LBC_ELM_VF1_64_INT;
  127. value = nitrox_read_csr(ndev, offset);
  128. nitrox_write_csr(ndev, offset, value);
  129. offset = LBC_ELM_VF65_128_INT;
  130. value = nitrox_read_csr(ndev, offset);
  131. nitrox_write_csr(ndev, offset, value);
  132. }
  133. nitrox_write_csr(ndev, LBC_INT, lbc_int.value);
  134. }
  135. static void clear_efl_err_intr(struct nitrox_device *ndev)
  136. {
  137. int i;
  138. for (i = 0; i < NR_CLUSTERS; i++) {
  139. union efl_core_int core_int;
  140. u64 value, offset;
  141. offset = EFL_CORE_INTX(i);
  142. core_int.value = nitrox_read_csr(ndev, offset);
  143. nitrox_write_csr(ndev, offset, core_int.value);
  144. dev_err_ratelimited(DEV(ndev), "ELF_CORE(%d)_INT 0x%016llx\n",
  145. i, core_int.value);
  146. if (core_int.s.se_err) {
  147. offset = EFL_CORE_SE_ERR_INTX(i);
  148. value = nitrox_read_csr(ndev, offset);
  149. nitrox_write_csr(ndev, offset, value);
  150. }
  151. }
  152. }
  153. static void clear_bmi_err_intr(struct nitrox_device *ndev)
  154. {
  155. u64 value;
  156. value = nitrox_read_csr(ndev, BMI_INT);
  157. nitrox_write_csr(ndev, BMI_INT, value);
  158. dev_err_ratelimited(DEV(ndev), "BMI_INT 0x%016llx\n", value);
  159. }
  160. /**
  161. * clear_nps_core_int_active - clear NPS_CORE_INT_ACTIVE interrupts
  162. * @ndev: NITROX device
  163. */
  164. static void clear_nps_core_int_active(struct nitrox_device *ndev)
  165. {
  166. union nps_core_int_active core_int_active;
  167. core_int_active.value = nitrox_read_csr(ndev, NPS_CORE_INT_ACTIVE);
  168. if (core_int_active.s.nps_core)
  169. clear_nps_core_err_intr(ndev);
  170. if (core_int_active.s.nps_pkt)
  171. clear_nps_pkt_err_intr(ndev);
  172. if (core_int_active.s.pom)
  173. clear_pom_err_intr(ndev);
  174. if (core_int_active.s.pem)
  175. clear_pem_err_intr(ndev);
  176. if (core_int_active.s.lbc)
  177. clear_lbc_err_intr(ndev);
  178. if (core_int_active.s.efl)
  179. clear_efl_err_intr(ndev);
  180. if (core_int_active.s.bmi)
  181. clear_bmi_err_intr(ndev);
  182. /* If more work callback the ISR, set resend */
  183. core_int_active.s.resend = 1;
  184. nitrox_write_csr(ndev, NPS_CORE_INT_ACTIVE, core_int_active.value);
  185. }
  186. static irqreturn_t nps_core_int_isr(int irq, void *data)
  187. {
  188. struct nitrox_device *ndev = data;
  189. clear_nps_core_int_active(ndev);
  190. return IRQ_HANDLED;
  191. }
  192. static int nitrox_enable_msix(struct nitrox_device *ndev)
  193. {
  194. struct msix_entry *entries;
  195. char **names;
  196. int i, nr_entries, ret;
  197. /*
  198. * PF MSI-X vectors
  199. *
  200. * Entry 0: NPS PKT ring 0
  201. * Entry 1: AQMQ ring 0
  202. * Entry 2: ZQM ring 0
  203. * Entry 3: NPS PKT ring 1
  204. * Entry 4: AQMQ ring 1
  205. * Entry 5: ZQM ring 1
  206. * ....
  207. * Entry 192: NPS_CORE_INT_ACTIVE
  208. */
  209. nr_entries = (ndev->nr_queues * NR_RING_VECTORS) + 1;
  210. entries = kcalloc_node(nr_entries, sizeof(struct msix_entry),
  211. GFP_KERNEL, ndev->node);
  212. if (!entries)
  213. return -ENOMEM;
  214. names = kcalloc(nr_entries, sizeof(char *), GFP_KERNEL);
  215. if (!names) {
  216. kfree(entries);
  217. return -ENOMEM;
  218. }
  219. /* fill entires */
  220. for (i = 0; i < (nr_entries - 1); i++)
  221. entries[i].entry = i;
  222. entries[i].entry = NPS_CORE_INT_ACTIVE_ENTRY;
  223. for (i = 0; i < nr_entries; i++) {
  224. *(names + i) = kzalloc(MAX_MSIX_VECTOR_NAME, GFP_KERNEL);
  225. if (!(*(names + i))) {
  226. ret = -ENOMEM;
  227. goto msix_fail;
  228. }
  229. }
  230. ndev->msix.entries = entries;
  231. ndev->msix.names = names;
  232. ndev->msix.nr_entries = nr_entries;
  233. ret = pci_enable_msix_exact(ndev->pdev, ndev->msix.entries,
  234. ndev->msix.nr_entries);
  235. if (ret) {
  236. dev_err(&ndev->pdev->dev, "Failed to enable MSI-X IRQ(s) %d\n",
  237. ret);
  238. goto msix_fail;
  239. }
  240. return 0;
  241. msix_fail:
  242. for (i = 0; i < nr_entries; i++)
  243. kfree(*(names + i));
  244. kfree(entries);
  245. kfree(names);
  246. return ret;
  247. }
  248. static void nitrox_cleanup_pkt_slc_bh(struct nitrox_device *ndev)
  249. {
  250. int i;
  251. if (!ndev->bh.slc)
  252. return;
  253. for (i = 0; i < ndev->nr_queues; i++) {
  254. struct bh_data *bh = &ndev->bh.slc[i];
  255. tasklet_disable(&bh->resp_handler);
  256. tasklet_kill(&bh->resp_handler);
  257. }
  258. kfree(ndev->bh.slc);
  259. ndev->bh.slc = NULL;
  260. }
  261. static int nitrox_setup_pkt_slc_bh(struct nitrox_device *ndev)
  262. {
  263. u32 size;
  264. int i;
  265. size = ndev->nr_queues * sizeof(struct bh_data);
  266. ndev->bh.slc = kzalloc(size, GFP_KERNEL);
  267. if (!ndev->bh.slc)
  268. return -ENOMEM;
  269. for (i = 0; i < ndev->nr_queues; i++) {
  270. struct bh_data *bh = &ndev->bh.slc[i];
  271. u64 offset;
  272. offset = NPS_PKT_SLC_CNTSX(i);
  273. /* pre calculate completion count address */
  274. bh->completion_cnt_csr_addr = NITROX_CSR_ADDR(ndev, offset);
  275. bh->cmdq = &ndev->pkt_cmdqs[i];
  276. tasklet_init(&bh->resp_handler, pkt_slc_resp_handler,
  277. (unsigned long)bh);
  278. }
  279. return 0;
  280. }
  281. static int nitrox_request_irqs(struct nitrox_device *ndev)
  282. {
  283. struct pci_dev *pdev = ndev->pdev;
  284. struct msix_entry *msix_ent = ndev->msix.entries;
  285. int nr_ring_vectors, i = 0, ring, cpu, ret;
  286. char *name;
  287. /*
  288. * PF MSI-X vectors
  289. *
  290. * Entry 0: NPS PKT ring 0
  291. * Entry 1: AQMQ ring 0
  292. * Entry 2: ZQM ring 0
  293. * Entry 3: NPS PKT ring 1
  294. * ....
  295. * Entry 192: NPS_CORE_INT_ACTIVE
  296. */
  297. nr_ring_vectors = ndev->nr_queues * NR_RING_VECTORS;
  298. /* request irq for pkt ring/ports only */
  299. while (i < nr_ring_vectors) {
  300. name = *(ndev->msix.names + i);
  301. ring = (i / NR_RING_VECTORS);
  302. snprintf(name, MAX_MSIX_VECTOR_NAME, "n5(%d)-slc-ring%d",
  303. ndev->idx, ring);
  304. ret = request_irq(msix_ent[i].vector, nps_pkt_slc_isr, 0,
  305. name, &ndev->bh.slc[ring]);
  306. if (ret) {
  307. dev_err(&pdev->dev, "failed to get irq %d for %s\n",
  308. msix_ent[i].vector, name);
  309. return ret;
  310. }
  311. cpu = ring % num_online_cpus();
  312. irq_set_affinity_hint(msix_ent[i].vector, get_cpu_mask(cpu));
  313. set_bit(i, ndev->msix.irqs);
  314. i += NR_RING_VECTORS;
  315. }
  316. /* Request IRQ for NPS_CORE_INT_ACTIVE */
  317. name = *(ndev->msix.names + i);
  318. snprintf(name, MAX_MSIX_VECTOR_NAME, "n5(%d)-nps-core-int", ndev->idx);
  319. ret = request_irq(msix_ent[i].vector, nps_core_int_isr, 0, name, ndev);
  320. if (ret) {
  321. dev_err(&pdev->dev, "failed to get irq %d for %s\n",
  322. msix_ent[i].vector, name);
  323. return ret;
  324. }
  325. set_bit(i, ndev->msix.irqs);
  326. return 0;
  327. }
  328. static void nitrox_disable_msix(struct nitrox_device *ndev)
  329. {
  330. struct msix_entry *msix_ent = ndev->msix.entries;
  331. char **names = ndev->msix.names;
  332. int i = 0, ring, nr_ring_vectors;
  333. nr_ring_vectors = ndev->msix.nr_entries - 1;
  334. /* clear pkt ring irqs */
  335. while (i < nr_ring_vectors) {
  336. if (test_and_clear_bit(i, ndev->msix.irqs)) {
  337. ring = (i / NR_RING_VECTORS);
  338. irq_set_affinity_hint(msix_ent[i].vector, NULL);
  339. free_irq(msix_ent[i].vector, &ndev->bh.slc[ring]);
  340. }
  341. i += NR_RING_VECTORS;
  342. }
  343. irq_set_affinity_hint(msix_ent[i].vector, NULL);
  344. free_irq(msix_ent[i].vector, ndev);
  345. clear_bit(i, ndev->msix.irqs);
  346. kfree(ndev->msix.entries);
  347. for (i = 0; i < ndev->msix.nr_entries; i++)
  348. kfree(*(names + i));
  349. kfree(names);
  350. pci_disable_msix(ndev->pdev);
  351. }
  352. /**
  353. * nitrox_pf_cleanup_isr: Cleanup PF MSI-X and IRQ
  354. * @ndev: NITROX device
  355. */
  356. void nitrox_pf_cleanup_isr(struct nitrox_device *ndev)
  357. {
  358. nitrox_disable_msix(ndev);
  359. nitrox_cleanup_pkt_slc_bh(ndev);
  360. }
  361. /**
  362. * nitrox_init_isr - Initialize PF MSI-X vectors and IRQ
  363. * @ndev: NITROX device
  364. *
  365. * Return: 0 on success, a negative value on failure.
  366. */
  367. int nitrox_pf_init_isr(struct nitrox_device *ndev)
  368. {
  369. int err;
  370. err = nitrox_setup_pkt_slc_bh(ndev);
  371. if (err)
  372. return err;
  373. err = nitrox_enable_msix(ndev);
  374. if (err)
  375. goto msix_fail;
  376. err = nitrox_request_irqs(ndev);
  377. if (err)
  378. goto irq_fail;
  379. return 0;
  380. irq_fail:
  381. nitrox_disable_msix(ndev);
  382. msix_fail:
  383. nitrox_cleanup_pkt_slc_bh(ndev);
  384. return err;
  385. }