pcic.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. // SPDX-License-Identifier: BSD-3-Clause-Clear
  2. /*
  3. * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include "core.h"
  7. #include "pcic.h"
  8. #include "debug.h"
  9. static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
  10. "bhi",
  11. "mhi-er0",
  12. "mhi-er1",
  13. "ce0",
  14. "ce1",
  15. "ce2",
  16. "ce3",
  17. "ce4",
  18. "ce5",
  19. "ce6",
  20. "ce7",
  21. "ce8",
  22. "ce9",
  23. "ce10",
  24. "ce11",
  25. "host2wbm-desc-feed",
  26. "host2reo-re-injection",
  27. "host2reo-command",
  28. "host2rxdma-monitor-ring3",
  29. "host2rxdma-monitor-ring2",
  30. "host2rxdma-monitor-ring1",
  31. "reo2ost-exception",
  32. "wbm2host-rx-release",
  33. "reo2host-status",
  34. "reo2host-destination-ring4",
  35. "reo2host-destination-ring3",
  36. "reo2host-destination-ring2",
  37. "reo2host-destination-ring1",
  38. "rxdma2host-monitor-destination-mac3",
  39. "rxdma2host-monitor-destination-mac2",
  40. "rxdma2host-monitor-destination-mac1",
  41. "ppdu-end-interrupts-mac3",
  42. "ppdu-end-interrupts-mac2",
  43. "ppdu-end-interrupts-mac1",
  44. "rxdma2host-monitor-status-ring-mac3",
  45. "rxdma2host-monitor-status-ring-mac2",
  46. "rxdma2host-monitor-status-ring-mac1",
  47. "host2rxdma-host-buf-ring-mac3",
  48. "host2rxdma-host-buf-ring-mac2",
  49. "host2rxdma-host-buf-ring-mac1",
  50. "rxdma2host-destination-ring-mac3",
  51. "rxdma2host-destination-ring-mac2",
  52. "rxdma2host-destination-ring-mac1",
  53. "host2tcl-input-ring4",
  54. "host2tcl-input-ring3",
  55. "host2tcl-input-ring2",
  56. "host2tcl-input-ring1",
  57. "wbm2host-tx-completions-ring3",
  58. "wbm2host-tx-completions-ring2",
  59. "wbm2host-tx-completions-ring1",
  60. "tcl2host-status-ring",
  61. };
  62. static const struct ath11k_msi_config ath11k_msi_config[] = {
  63. {
  64. .total_vectors = 32,
  65. .total_users = 4,
  66. .users = (struct ath11k_msi_user[]) {
  67. { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
  68. { .name = "CE", .num_vectors = 10, .base_vector = 3 },
  69. { .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
  70. { .name = "DP", .num_vectors = 18, .base_vector = 14 },
  71. },
  72. .hw_rev = ATH11K_HW_QCA6390_HW20,
  73. },
  74. {
  75. .total_vectors = 16,
  76. .total_users = 3,
  77. .users = (struct ath11k_msi_user[]) {
  78. { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
  79. { .name = "CE", .num_vectors = 5, .base_vector = 3 },
  80. { .name = "DP", .num_vectors = 8, .base_vector = 8 },
  81. },
  82. .hw_rev = ATH11K_HW_QCN9074_HW10,
  83. },
  84. {
  85. .total_vectors = 32,
  86. .total_users = 4,
  87. .users = (struct ath11k_msi_user[]) {
  88. { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
  89. { .name = "CE", .num_vectors = 10, .base_vector = 3 },
  90. { .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
  91. { .name = "DP", .num_vectors = 18, .base_vector = 14 },
  92. },
  93. .hw_rev = ATH11K_HW_WCN6855_HW20,
  94. },
  95. {
  96. .total_vectors = 32,
  97. .total_users = 4,
  98. .users = (struct ath11k_msi_user[]) {
  99. { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
  100. { .name = "CE", .num_vectors = 10, .base_vector = 3 },
  101. { .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
  102. { .name = "DP", .num_vectors = 18, .base_vector = 14 },
  103. },
  104. .hw_rev = ATH11K_HW_WCN6855_HW21,
  105. },
  106. {
  107. .total_vectors = 28,
  108. .total_users = 2,
  109. .users = (struct ath11k_msi_user[]) {
  110. { .name = "CE", .num_vectors = 10, .base_vector = 0 },
  111. { .name = "DP", .num_vectors = 18, .base_vector = 10 },
  112. },
  113. .hw_rev = ATH11K_HW_WCN6750_HW10,
  114. },
  115. };
  116. int ath11k_pcic_init_msi_config(struct ath11k_base *ab)
  117. {
  118. const struct ath11k_msi_config *msi_config;
  119. int i;
  120. for (i = 0; i < ARRAY_SIZE(ath11k_msi_config); i++) {
  121. msi_config = &ath11k_msi_config[i];
  122. if (msi_config->hw_rev == ab->hw_rev)
  123. break;
  124. }
  125. if (i == ARRAY_SIZE(ath11k_msi_config)) {
  126. ath11k_err(ab, "failed to fetch msi config, unsupported hw version: 0x%x\n",
  127. ab->hw_rev);
  128. return -EINVAL;
  129. }
  130. ab->pci.msi.config = msi_config;
  131. return 0;
  132. }
  133. EXPORT_SYMBOL(ath11k_pcic_init_msi_config);
  134. static void __ath11k_pcic_write32(struct ath11k_base *ab, u32 offset, u32 value)
  135. {
  136. if (offset < ATH11K_PCI_WINDOW_START)
  137. iowrite32(value, ab->mem + offset);
  138. else
  139. ab->pci.ops->window_write32(ab, offset, value);
  140. }
  141. void ath11k_pcic_write32(struct ath11k_base *ab, u32 offset, u32 value)
  142. {
  143. int ret = 0;
  144. bool wakeup_required;
  145. /* for offset beyond BAR + 4K - 32, may
  146. * need to wakeup the device to access.
  147. */
  148. wakeup_required = test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
  149. offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF;
  150. if (wakeup_required && ab->pci.ops->wakeup)
  151. ret = ab->pci.ops->wakeup(ab);
  152. __ath11k_pcic_write32(ab, offset, value);
  153. if (wakeup_required && !ret && ab->pci.ops->release)
  154. ab->pci.ops->release(ab);
  155. }
  156. EXPORT_SYMBOL(ath11k_pcic_write32);
  157. static u32 __ath11k_pcic_read32(struct ath11k_base *ab, u32 offset)
  158. {
  159. u32 val;
  160. if (offset < ATH11K_PCI_WINDOW_START)
  161. val = ioread32(ab->mem + offset);
  162. else
  163. val = ab->pci.ops->window_read32(ab, offset);
  164. return val;
  165. }
  166. u32 ath11k_pcic_read32(struct ath11k_base *ab, u32 offset)
  167. {
  168. int ret = 0;
  169. u32 val;
  170. bool wakeup_required;
  171. /* for offset beyond BAR + 4K - 32, may
  172. * need to wakeup the device to access.
  173. */
  174. wakeup_required = test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
  175. offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF;
  176. if (wakeup_required && ab->pci.ops->wakeup)
  177. ret = ab->pci.ops->wakeup(ab);
  178. val = __ath11k_pcic_read32(ab, offset);
  179. if (wakeup_required && !ret && ab->pci.ops->release)
  180. ab->pci.ops->release(ab);
  181. return val;
  182. }
  183. EXPORT_SYMBOL(ath11k_pcic_read32);
  184. int ath11k_pcic_read(struct ath11k_base *ab, void *buf, u32 start, u32 end)
  185. {
  186. int ret = 0;
  187. bool wakeup_required;
  188. u32 *data = buf;
  189. u32 i;
  190. /* for offset beyond BAR + 4K - 32, may
  191. * need to wakeup the device to access.
  192. */
  193. wakeup_required = test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
  194. end >= ATH11K_PCI_ACCESS_ALWAYS_OFF;
  195. if (wakeup_required && ab->pci.ops->wakeup) {
  196. ret = ab->pci.ops->wakeup(ab);
  197. if (ret) {
  198. ath11k_warn(ab, "failed to wakeup for read from 0x%x: %d\n",
  199. start, ret);
  200. return ret;
  201. }
  202. }
  203. for (i = start; i < end + 1; i += 4)
  204. *data++ = __ath11k_pcic_read32(ab, i);
  205. if (wakeup_required && ab->pci.ops->release)
  206. ab->pci.ops->release(ab);
  207. return 0;
  208. }
  209. EXPORT_SYMBOL(ath11k_pcic_read);
  210. void ath11k_pcic_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
  211. u32 *msi_addr_hi)
  212. {
  213. *msi_addr_lo = ab->pci.msi.addr_lo;
  214. *msi_addr_hi = ab->pci.msi.addr_hi;
  215. }
  216. EXPORT_SYMBOL(ath11k_pcic_get_msi_address);
  217. int ath11k_pcic_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
  218. int *num_vectors, u32 *user_base_data,
  219. u32 *base_vector)
  220. {
  221. const struct ath11k_msi_config *msi_config = ab->pci.msi.config;
  222. int idx;
  223. for (idx = 0; idx < msi_config->total_users; idx++) {
  224. if (strcmp(user_name, msi_config->users[idx].name) == 0) {
  225. *num_vectors = msi_config->users[idx].num_vectors;
  226. *base_vector = msi_config->users[idx].base_vector;
  227. *user_base_data = *base_vector + ab->pci.msi.ep_base_data;
  228. ath11k_dbg(ab, ATH11K_DBG_PCI,
  229. "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
  230. user_name, *num_vectors, *user_base_data,
  231. *base_vector);
  232. return 0;
  233. }
  234. }
  235. ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name);
  236. return -EINVAL;
  237. }
  238. EXPORT_SYMBOL(ath11k_pcic_get_user_msi_assignment);
  239. void ath11k_pcic_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx)
  240. {
  241. u32 i, msi_data_idx;
  242. for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
  243. if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
  244. continue;
  245. if (ce_id == i)
  246. break;
  247. msi_data_idx++;
  248. }
  249. *msi_idx = msi_data_idx;
  250. }
  251. EXPORT_SYMBOL(ath11k_pcic_get_ce_msi_idx);
  252. static void ath11k_pcic_free_ext_irq(struct ath11k_base *ab)
  253. {
  254. int i, j;
  255. for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
  256. struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
  257. for (j = 0; j < irq_grp->num_irq; j++)
  258. free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
  259. netif_napi_del(&irq_grp->napi);
  260. }
  261. }
  262. void ath11k_pcic_free_irq(struct ath11k_base *ab)
  263. {
  264. int i, irq_idx;
  265. for (i = 0; i < ab->hw_params.ce_count; i++) {
  266. if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
  267. continue;
  268. irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
  269. free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
  270. }
  271. ath11k_pcic_free_ext_irq(ab);
  272. }
  273. EXPORT_SYMBOL(ath11k_pcic_free_irq);
  274. static void ath11k_pcic_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
  275. {
  276. u32 irq_idx;
  277. /* In case of one MSI vector, we handle irq enable/disable in a
  278. * uniform way since we only have one irq
  279. */
  280. if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
  281. return;
  282. irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
  283. enable_irq(ab->irq_num[irq_idx]);
  284. }
  285. static void ath11k_pcic_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
  286. {
  287. u32 irq_idx;
  288. /* In case of one MSI vector, we handle irq enable/disable in a
  289. * uniform way since we only have one irq
  290. */
  291. if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
  292. return;
  293. irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
  294. disable_irq_nosync(ab->irq_num[irq_idx]);
  295. }
  296. static void ath11k_pcic_ce_irqs_disable(struct ath11k_base *ab)
  297. {
  298. int i;
  299. clear_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags);
  300. for (i = 0; i < ab->hw_params.ce_count; i++) {
  301. if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
  302. continue;
  303. ath11k_pcic_ce_irq_disable(ab, i);
  304. }
  305. }
  306. static void ath11k_pcic_sync_ce_irqs(struct ath11k_base *ab)
  307. {
  308. int i;
  309. int irq_idx;
  310. for (i = 0; i < ab->hw_params.ce_count; i++) {
  311. if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
  312. continue;
  313. irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
  314. synchronize_irq(ab->irq_num[irq_idx]);
  315. }
  316. }
  317. static void ath11k_pcic_ce_tasklet(struct tasklet_struct *t)
  318. {
  319. struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
  320. int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
  321. ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
  322. enable_irq(ce_pipe->ab->irq_num[irq_idx]);
  323. }
  324. static irqreturn_t ath11k_pcic_ce_interrupt_handler(int irq, void *arg)
  325. {
  326. struct ath11k_ce_pipe *ce_pipe = arg;
  327. struct ath11k_base *ab = ce_pipe->ab;
  328. int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
  329. if (!test_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags))
  330. return IRQ_HANDLED;
  331. /* last interrupt received for this CE */
  332. ce_pipe->timestamp = jiffies;
  333. disable_irq_nosync(ab->irq_num[irq_idx]);
  334. tasklet_schedule(&ce_pipe->intr_tq);
  335. return IRQ_HANDLED;
  336. }
  337. static void ath11k_pcic_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
  338. {
  339. struct ath11k_base *ab = irq_grp->ab;
  340. int i;
  341. /* In case of one MSI vector, we handle irq enable/disable
  342. * in a uniform way since we only have one irq
  343. */
  344. if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
  345. return;
  346. for (i = 0; i < irq_grp->num_irq; i++)
  347. disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
  348. }
  349. static void __ath11k_pcic_ext_irq_disable(struct ath11k_base *sc)
  350. {
  351. int i;
  352. clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &sc->dev_flags);
  353. for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
  354. struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];
  355. ath11k_pcic_ext_grp_disable(irq_grp);
  356. if (irq_grp->napi_enabled) {
  357. napi_synchronize(&irq_grp->napi);
  358. napi_disable(&irq_grp->napi);
  359. irq_grp->napi_enabled = false;
  360. }
  361. }
  362. }
  363. static void ath11k_pcic_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
  364. {
  365. struct ath11k_base *ab = irq_grp->ab;
  366. int i;
  367. /* In case of one MSI vector, we handle irq enable/disable in a
  368. * uniform way since we only have one irq
  369. */
  370. if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
  371. return;
  372. for (i = 0; i < irq_grp->num_irq; i++)
  373. enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
  374. }
  375. void ath11k_pcic_ext_irq_enable(struct ath11k_base *ab)
  376. {
  377. int i;
  378. set_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags);
  379. for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
  380. struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
  381. if (!irq_grp->napi_enabled) {
  382. dev_set_threaded(&irq_grp->napi_ndev, true);
  383. napi_enable(&irq_grp->napi);
  384. irq_grp->napi_enabled = true;
  385. }
  386. ath11k_pcic_ext_grp_enable(irq_grp);
  387. }
  388. }
  389. EXPORT_SYMBOL(ath11k_pcic_ext_irq_enable);
  390. static void ath11k_pcic_sync_ext_irqs(struct ath11k_base *ab)
  391. {
  392. int i, j, irq_idx;
  393. for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
  394. struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
  395. for (j = 0; j < irq_grp->num_irq; j++) {
  396. irq_idx = irq_grp->irqs[j];
  397. synchronize_irq(ab->irq_num[irq_idx]);
  398. }
  399. }
  400. }
  401. void ath11k_pcic_ext_irq_disable(struct ath11k_base *ab)
  402. {
  403. __ath11k_pcic_ext_irq_disable(ab);
  404. ath11k_pcic_sync_ext_irqs(ab);
  405. }
  406. EXPORT_SYMBOL(ath11k_pcic_ext_irq_disable);
  407. static int ath11k_pcic_ext_grp_napi_poll(struct napi_struct *napi, int budget)
  408. {
  409. struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
  410. struct ath11k_ext_irq_grp,
  411. napi);
  412. struct ath11k_base *ab = irq_grp->ab;
  413. int work_done;
  414. int i;
  415. work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
  416. if (work_done < budget) {
  417. napi_complete_done(napi, work_done);
  418. for (i = 0; i < irq_grp->num_irq; i++)
  419. enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
  420. }
  421. if (work_done > budget)
  422. work_done = budget;
  423. return work_done;
  424. }
  425. static irqreturn_t ath11k_pcic_ext_interrupt_handler(int irq, void *arg)
  426. {
  427. struct ath11k_ext_irq_grp *irq_grp = arg;
  428. struct ath11k_base *ab = irq_grp->ab;
  429. int i;
  430. if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags))
  431. return IRQ_HANDLED;
  432. ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
  433. /* last interrupt received for this group */
  434. irq_grp->timestamp = jiffies;
  435. for (i = 0; i < irq_grp->num_irq; i++)
  436. disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
  437. napi_schedule(&irq_grp->napi);
  438. return IRQ_HANDLED;
  439. }
  440. static int
  441. ath11k_pcic_get_msi_irq(struct ath11k_base *ab, unsigned int vector)
  442. {
  443. return ab->pci.ops->get_msi_irq(ab, vector);
  444. }
  445. static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab)
  446. {
  447. int i, j, ret, num_vectors = 0;
  448. u32 user_base_data = 0, base_vector = 0;
  449. unsigned long irq_flags;
  450. ret = ath11k_pcic_get_user_msi_assignment(ab, "DP", &num_vectors,
  451. &user_base_data,
  452. &base_vector);
  453. if (ret < 0)
  454. return ret;
  455. irq_flags = IRQF_SHARED;
  456. if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
  457. irq_flags |= IRQF_NOBALANCING;
  458. for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
  459. struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
  460. u32 num_irq = 0;
  461. irq_grp->ab = ab;
  462. irq_grp->grp_id = i;
  463. init_dummy_netdev(&irq_grp->napi_ndev);
  464. netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
  465. ath11k_pcic_ext_grp_napi_poll);
  466. if (ab->hw_params.ring_mask->tx[i] ||
  467. ab->hw_params.ring_mask->rx[i] ||
  468. ab->hw_params.ring_mask->rx_err[i] ||
  469. ab->hw_params.ring_mask->rx_wbm_rel[i] ||
  470. ab->hw_params.ring_mask->reo_status[i] ||
  471. ab->hw_params.ring_mask->rxdma2host[i] ||
  472. ab->hw_params.ring_mask->host2rxdma[i] ||
  473. ab->hw_params.ring_mask->rx_mon_status[i]) {
  474. num_irq = 1;
  475. }
  476. irq_grp->num_irq = num_irq;
  477. irq_grp->irqs[0] = ATH11K_PCI_IRQ_DP_OFFSET + i;
  478. for (j = 0; j < irq_grp->num_irq; j++) {
  479. int irq_idx = irq_grp->irqs[j];
  480. int vector = (i % num_vectors) + base_vector;
  481. int irq = ath11k_pcic_get_msi_irq(ab, vector);
  482. if (irq < 0)
  483. return irq;
  484. ab->irq_num[irq_idx] = irq;
  485. ath11k_dbg(ab, ATH11K_DBG_PCI,
  486. "irq:%d group:%d\n", irq, i);
  487. irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
  488. ret = request_irq(irq, ath11k_pcic_ext_interrupt_handler,
  489. irq_flags, "DP_EXT_IRQ", irq_grp);
  490. if (ret) {
  491. ath11k_err(ab, "failed request irq %d: %d\n",
  492. vector, ret);
  493. return ret;
  494. }
  495. }
  496. ath11k_pcic_ext_grp_disable(irq_grp);
  497. }
  498. return 0;
  499. }
  500. int ath11k_pcic_config_irq(struct ath11k_base *ab)
  501. {
  502. struct ath11k_ce_pipe *ce_pipe;
  503. u32 msi_data_start;
  504. u32 msi_data_count, msi_data_idx;
  505. u32 msi_irq_start;
  506. unsigned int msi_data;
  507. int irq, i, ret, irq_idx;
  508. unsigned long irq_flags;
  509. ret = ath11k_pcic_get_user_msi_assignment(ab, "CE", &msi_data_count,
  510. &msi_data_start, &msi_irq_start);
  511. if (ret)
  512. return ret;
  513. irq_flags = IRQF_SHARED;
  514. if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
  515. irq_flags |= IRQF_NOBALANCING;
  516. /* Configure CE irqs */
  517. for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
  518. if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
  519. continue;
  520. msi_data = (msi_data_idx % msi_data_count) + msi_irq_start;
  521. irq = ath11k_pcic_get_msi_irq(ab, msi_data);
  522. if (irq < 0)
  523. return irq;
  524. ce_pipe = &ab->ce.ce_pipe[i];
  525. irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
  526. tasklet_setup(&ce_pipe->intr_tq, ath11k_pcic_ce_tasklet);
  527. ret = request_irq(irq, ath11k_pcic_ce_interrupt_handler,
  528. irq_flags, irq_name[irq_idx], ce_pipe);
  529. if (ret) {
  530. ath11k_err(ab, "failed to request irq %d: %d\n",
  531. irq_idx, ret);
  532. return ret;
  533. }
  534. ab->irq_num[irq_idx] = irq;
  535. msi_data_idx++;
  536. ath11k_pcic_ce_irq_disable(ab, i);
  537. }
  538. ret = ath11k_pcic_ext_irq_config(ab);
  539. if (ret)
  540. return ret;
  541. return 0;
  542. }
  543. EXPORT_SYMBOL(ath11k_pcic_config_irq);
  544. void ath11k_pcic_ce_irqs_enable(struct ath11k_base *ab)
  545. {
  546. int i;
  547. set_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags);
  548. for (i = 0; i < ab->hw_params.ce_count; i++) {
  549. if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
  550. continue;
  551. ath11k_pcic_ce_irq_enable(ab, i);
  552. }
  553. }
  554. EXPORT_SYMBOL(ath11k_pcic_ce_irqs_enable);
  555. static void ath11k_pcic_kill_tasklets(struct ath11k_base *ab)
  556. {
  557. int i;
  558. for (i = 0; i < ab->hw_params.ce_count; i++) {
  559. struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
  560. if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
  561. continue;
  562. tasklet_kill(&ce_pipe->intr_tq);
  563. }
  564. }
  565. void ath11k_pcic_ce_irq_disable_sync(struct ath11k_base *ab)
  566. {
  567. ath11k_pcic_ce_irqs_disable(ab);
  568. ath11k_pcic_sync_ce_irqs(ab);
  569. ath11k_pcic_kill_tasklets(ab);
  570. }
  571. EXPORT_SYMBOL(ath11k_pcic_ce_irq_disable_sync);
  572. void ath11k_pcic_stop(struct ath11k_base *ab)
  573. {
  574. ath11k_pcic_ce_irq_disable_sync(ab);
  575. ath11k_ce_cleanup_pipes(ab);
  576. }
  577. EXPORT_SYMBOL(ath11k_pcic_stop);
  578. int ath11k_pcic_start(struct ath11k_base *ab)
  579. {
  580. set_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);
  581. ath11k_pcic_ce_irqs_enable(ab);
  582. ath11k_ce_rx_post_buf(ab);
  583. return 0;
  584. }
  585. EXPORT_SYMBOL(ath11k_pcic_start);
  586. int ath11k_pcic_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
  587. u8 *ul_pipe, u8 *dl_pipe)
  588. {
  589. const struct service_to_pipe *entry;
  590. bool ul_set = false, dl_set = false;
  591. int i;
  592. for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
  593. entry = &ab->hw_params.svc_to_ce_map[i];
  594. if (__le32_to_cpu(entry->service_id) != service_id)
  595. continue;
  596. switch (__le32_to_cpu(entry->pipedir)) {
  597. case PIPEDIR_NONE:
  598. break;
  599. case PIPEDIR_IN:
  600. WARN_ON(dl_set);
  601. *dl_pipe = __le32_to_cpu(entry->pipenum);
  602. dl_set = true;
  603. break;
  604. case PIPEDIR_OUT:
  605. WARN_ON(ul_set);
  606. *ul_pipe = __le32_to_cpu(entry->pipenum);
  607. ul_set = true;
  608. break;
  609. case PIPEDIR_INOUT:
  610. WARN_ON(dl_set);
  611. WARN_ON(ul_set);
  612. *dl_pipe = __le32_to_cpu(entry->pipenum);
  613. *ul_pipe = __le32_to_cpu(entry->pipenum);
  614. dl_set = true;
  615. ul_set = true;
  616. break;
  617. }
  618. }
  619. if (WARN_ON(!ul_set || !dl_set))
  620. return -ENOENT;
  621. return 0;
  622. }
  623. EXPORT_SYMBOL(ath11k_pcic_map_service_to_pipe);
  624. int ath11k_pcic_register_pci_ops(struct ath11k_base *ab,
  625. const struct ath11k_pci_ops *pci_ops)
  626. {
  627. if (!pci_ops)
  628. return 0;
  629. /* Return error if mandatory pci_ops callbacks are missing */
  630. if (!pci_ops->get_msi_irq || !pci_ops->window_write32 ||
  631. !pci_ops->window_read32)
  632. return -EINVAL;
  633. ab->pci.ops = pci_ops;
  634. return 0;
  635. }
  636. EXPORT_SYMBOL(ath11k_pcic_register_pci_ops);
  637. void ath11k_pci_enable_ce_irqs_except_wake_irq(struct ath11k_base *ab)
  638. {
  639. int i;
  640. for (i = 0; i < ab->hw_params.ce_count; i++) {
  641. if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR ||
  642. i == ATH11K_PCI_CE_WAKE_IRQ)
  643. continue;
  644. ath11k_pcic_ce_irq_enable(ab, i);
  645. }
  646. }
  647. EXPORT_SYMBOL(ath11k_pci_enable_ce_irqs_except_wake_irq);
  648. void ath11k_pci_disable_ce_irqs_except_wake_irq(struct ath11k_base *ab)
  649. {
  650. int i;
  651. int irq_idx;
  652. struct ath11k_ce_pipe *ce_pipe;
  653. for (i = 0; i < ab->hw_params.ce_count; i++) {
  654. ce_pipe = &ab->ce.ce_pipe[i];
  655. irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
  656. if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR ||
  657. i == ATH11K_PCI_CE_WAKE_IRQ)
  658. continue;
  659. disable_irq_nosync(ab->irq_num[irq_idx]);
  660. synchronize_irq(ab->irq_num[irq_idx]);
  661. tasklet_kill(&ce_pipe->intr_tq);
  662. }
  663. }
  664. EXPORT_SYMBOL(ath11k_pci_disable_ce_irqs_except_wake_irq);