bfa_msgq.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Linux network driver for QLogic BR-series Converged Network Adapter.
  4. */
  5. /*
  6. * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
  7. * Copyright (c) 2014-2015 QLogic Corporation
  8. * All rights reserved
  9. * www.qlogic.com
  10. */
  11. /* MSGQ module source file. */
  12. #include "bfi.h"
  13. #include "bfa_msgq.h"
  14. #include "bfa_ioc.h"
  15. #define call_cmdq_ent_cbfn(_cmdq_ent, _status) \
  16. { \
  17. bfa_msgq_cmdcbfn_t cbfn; \
  18. void *cbarg; \
  19. cbfn = (_cmdq_ent)->cbfn; \
  20. cbarg = (_cmdq_ent)->cbarg; \
  21. (_cmdq_ent)->cbfn = NULL; \
  22. (_cmdq_ent)->cbarg = NULL; \
  23. if (cbfn) { \
  24. cbfn(cbarg, (_status)); \
  25. } \
  26. }
  27. static void bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq);
  28. static void bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq);
  29. enum cmdq_event {
  30. CMDQ_E_START = 1,
  31. CMDQ_E_STOP = 2,
  32. CMDQ_E_FAIL = 3,
  33. CMDQ_E_POST = 4,
  34. CMDQ_E_INIT_RESP = 5,
  35. CMDQ_E_DB_READY = 6,
  36. };
  37. bfa_fsm_state_decl(cmdq, stopped, struct bfa_msgq_cmdq, enum cmdq_event);
  38. bfa_fsm_state_decl(cmdq, init_wait, struct bfa_msgq_cmdq, enum cmdq_event);
  39. bfa_fsm_state_decl(cmdq, ready, struct bfa_msgq_cmdq, enum cmdq_event);
  40. bfa_fsm_state_decl(cmdq, dbell_wait, struct bfa_msgq_cmdq,
  41. enum cmdq_event);
  42. static void
  43. cmdq_sm_stopped_entry(struct bfa_msgq_cmdq *cmdq)
  44. {
  45. struct bfa_msgq_cmd_entry *cmdq_ent;
  46. cmdq->producer_index = 0;
  47. cmdq->consumer_index = 0;
  48. cmdq->flags = 0;
  49. cmdq->token = 0;
  50. cmdq->offset = 0;
  51. cmdq->bytes_to_copy = 0;
  52. while (!list_empty(&cmdq->pending_q)) {
  53. cmdq_ent = list_first_entry(&cmdq->pending_q,
  54. struct bfa_msgq_cmd_entry, qe);
  55. list_del(&cmdq_ent->qe);
  56. call_cmdq_ent_cbfn(cmdq_ent, BFA_STATUS_FAILED);
  57. }
  58. }
  59. static void
  60. cmdq_sm_stopped(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
  61. {
  62. switch (event) {
  63. case CMDQ_E_START:
  64. bfa_fsm_set_state(cmdq, cmdq_sm_init_wait);
  65. break;
  66. case CMDQ_E_STOP:
  67. case CMDQ_E_FAIL:
  68. /* No-op */
  69. break;
  70. case CMDQ_E_POST:
  71. cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
  72. break;
  73. default:
  74. bfa_sm_fault(event);
  75. }
  76. }
  77. static void
  78. cmdq_sm_init_wait_entry(struct bfa_msgq_cmdq *cmdq)
  79. {
  80. bfa_wc_down(&cmdq->msgq->init_wc);
  81. }
  82. static void
  83. cmdq_sm_init_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
  84. {
  85. switch (event) {
  86. case CMDQ_E_STOP:
  87. case CMDQ_E_FAIL:
  88. bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
  89. break;
  90. case CMDQ_E_POST:
  91. cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
  92. break;
  93. case CMDQ_E_INIT_RESP:
  94. if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
  95. cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
  96. bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
  97. } else
  98. bfa_fsm_set_state(cmdq, cmdq_sm_ready);
  99. break;
  100. default:
  101. bfa_sm_fault(event);
  102. }
  103. }
  104. static void
  105. cmdq_sm_ready_entry(struct bfa_msgq_cmdq *cmdq)
  106. {
  107. }
  108. static void
  109. cmdq_sm_ready(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
  110. {
  111. switch (event) {
  112. case CMDQ_E_STOP:
  113. case CMDQ_E_FAIL:
  114. bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
  115. break;
  116. case CMDQ_E_POST:
  117. bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
  118. break;
  119. default:
  120. bfa_sm_fault(event);
  121. }
  122. }
  123. static void
  124. cmdq_sm_dbell_wait_entry(struct bfa_msgq_cmdq *cmdq)
  125. {
  126. bfa_msgq_cmdq_dbell(cmdq);
  127. }
  128. static void
  129. cmdq_sm_dbell_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
  130. {
  131. switch (event) {
  132. case CMDQ_E_STOP:
  133. case CMDQ_E_FAIL:
  134. bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
  135. break;
  136. case CMDQ_E_POST:
  137. cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
  138. break;
  139. case CMDQ_E_DB_READY:
  140. if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
  141. cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
  142. bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
  143. } else
  144. bfa_fsm_set_state(cmdq, cmdq_sm_ready);
  145. break;
  146. default:
  147. bfa_sm_fault(event);
  148. }
  149. }
  150. static void
  151. bfa_msgq_cmdq_dbell_ready(void *arg)
  152. {
  153. struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
  154. bfa_fsm_send_event(cmdq, CMDQ_E_DB_READY);
  155. }
  156. static void
  157. bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq)
  158. {
  159. struct bfi_msgq_h2i_db *dbell =
  160. (struct bfi_msgq_h2i_db *)(&cmdq->dbell_mb.msg[0]);
  161. memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
  162. bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_PI, 0);
  163. dbell->mh.mtag.i2htok = 0;
  164. dbell->idx.cmdq_pi = htons(cmdq->producer_index);
  165. if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->dbell_mb,
  166. bfa_msgq_cmdq_dbell_ready, cmdq)) {
  167. bfa_msgq_cmdq_dbell_ready(cmdq);
  168. }
  169. }
  170. static void
  171. __cmd_copy(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq_cmd_entry *cmd)
  172. {
  173. size_t len = cmd->msg_size;
  174. size_t to_copy;
  175. u8 *src, *dst;
  176. src = (u8 *)cmd->msg_hdr;
  177. dst = (u8 *)cmdq->addr.kva;
  178. dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
  179. while (len) {
  180. to_copy = (len < BFI_MSGQ_CMD_ENTRY_SIZE) ?
  181. len : BFI_MSGQ_CMD_ENTRY_SIZE;
  182. memcpy(dst, src, to_copy);
  183. len -= to_copy;
  184. src += BFI_MSGQ_CMD_ENTRY_SIZE;
  185. BFA_MSGQ_INDX_ADD(cmdq->producer_index, 1, cmdq->depth);
  186. dst = (u8 *)cmdq->addr.kva;
  187. dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
  188. }
  189. }
  190. static void
  191. bfa_msgq_cmdq_ci_update(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
  192. {
  193. struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
  194. struct bfa_msgq_cmd_entry *cmd;
  195. int posted = 0;
  196. cmdq->consumer_index = ntohs(dbell->idx.cmdq_ci);
  197. /* Walk through pending list to see if the command can be posted */
  198. while (!list_empty(&cmdq->pending_q)) {
  199. cmd = list_first_entry(&cmdq->pending_q,
  200. struct bfa_msgq_cmd_entry, qe);
  201. if (ntohs(cmd->msg_hdr->num_entries) <=
  202. BFA_MSGQ_FREE_CNT(cmdq)) {
  203. list_del(&cmd->qe);
  204. __cmd_copy(cmdq, cmd);
  205. posted = 1;
  206. call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
  207. } else {
  208. break;
  209. }
  210. }
  211. if (posted)
  212. bfa_fsm_send_event(cmdq, CMDQ_E_POST);
  213. }
  214. static void
  215. bfa_msgq_cmdq_copy_next(void *arg)
  216. {
  217. struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
  218. if (cmdq->bytes_to_copy)
  219. bfa_msgq_cmdq_copy_rsp(cmdq);
  220. }
  221. static void
  222. bfa_msgq_cmdq_copy_req(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
  223. {
  224. struct bfi_msgq_i2h_cmdq_copy_req *req =
  225. (struct bfi_msgq_i2h_cmdq_copy_req *)mb;
  226. cmdq->token = 0;
  227. cmdq->offset = ntohs(req->offset);
  228. cmdq->bytes_to_copy = ntohs(req->len);
  229. bfa_msgq_cmdq_copy_rsp(cmdq);
  230. }
  231. static void
  232. bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq)
  233. {
  234. struct bfi_msgq_h2i_cmdq_copy_rsp *rsp =
  235. (struct bfi_msgq_h2i_cmdq_copy_rsp *)&cmdq->copy_mb.msg[0];
  236. int copied;
  237. u8 *addr = (u8 *)cmdq->addr.kva;
  238. memset(rsp, 0, sizeof(struct bfi_msgq_h2i_cmdq_copy_rsp));
  239. bfi_h2i_set(rsp->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_CMDQ_COPY_RSP, 0);
  240. rsp->mh.mtag.i2htok = htons(cmdq->token);
  241. copied = (cmdq->bytes_to_copy >= BFI_CMD_COPY_SZ) ? BFI_CMD_COPY_SZ :
  242. cmdq->bytes_to_copy;
  243. addr += cmdq->offset;
  244. memcpy(rsp->data, addr, copied);
  245. cmdq->token++;
  246. cmdq->offset += copied;
  247. cmdq->bytes_to_copy -= copied;
  248. if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->copy_mb,
  249. bfa_msgq_cmdq_copy_next, cmdq)) {
  250. bfa_msgq_cmdq_copy_next(cmdq);
  251. }
  252. }
  253. static void
  254. bfa_msgq_cmdq_attach(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq *msgq)
  255. {
  256. cmdq->depth = BFA_MSGQ_CMDQ_NUM_ENTRY;
  257. INIT_LIST_HEAD(&cmdq->pending_q);
  258. cmdq->msgq = msgq;
  259. bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
  260. }
  261. static void bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq);
  262. enum rspq_event {
  263. RSPQ_E_START = 1,
  264. RSPQ_E_STOP = 2,
  265. RSPQ_E_FAIL = 3,
  266. RSPQ_E_RESP = 4,
  267. RSPQ_E_INIT_RESP = 5,
  268. RSPQ_E_DB_READY = 6,
  269. };
  270. bfa_fsm_state_decl(rspq, stopped, struct bfa_msgq_rspq, enum rspq_event);
  271. bfa_fsm_state_decl(rspq, init_wait, struct bfa_msgq_rspq,
  272. enum rspq_event);
  273. bfa_fsm_state_decl(rspq, ready, struct bfa_msgq_rspq, enum rspq_event);
  274. bfa_fsm_state_decl(rspq, dbell_wait, struct bfa_msgq_rspq,
  275. enum rspq_event);
  276. static void
  277. rspq_sm_stopped_entry(struct bfa_msgq_rspq *rspq)
  278. {
  279. rspq->producer_index = 0;
  280. rspq->consumer_index = 0;
  281. rspq->flags = 0;
  282. }
  283. static void
  284. rspq_sm_stopped(struct bfa_msgq_rspq *rspq, enum rspq_event event)
  285. {
  286. switch (event) {
  287. case RSPQ_E_START:
  288. bfa_fsm_set_state(rspq, rspq_sm_init_wait);
  289. break;
  290. case RSPQ_E_STOP:
  291. case RSPQ_E_FAIL:
  292. /* No-op */
  293. break;
  294. default:
  295. bfa_sm_fault(event);
  296. }
  297. }
  298. static void
  299. rspq_sm_init_wait_entry(struct bfa_msgq_rspq *rspq)
  300. {
  301. bfa_wc_down(&rspq->msgq->init_wc);
  302. }
  303. static void
  304. rspq_sm_init_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
  305. {
  306. switch (event) {
  307. case RSPQ_E_FAIL:
  308. case RSPQ_E_STOP:
  309. bfa_fsm_set_state(rspq, rspq_sm_stopped);
  310. break;
  311. case RSPQ_E_INIT_RESP:
  312. bfa_fsm_set_state(rspq, rspq_sm_ready);
  313. break;
  314. default:
  315. bfa_sm_fault(event);
  316. }
  317. }
  318. static void
  319. rspq_sm_ready_entry(struct bfa_msgq_rspq *rspq)
  320. {
  321. }
  322. static void
  323. rspq_sm_ready(struct bfa_msgq_rspq *rspq, enum rspq_event event)
  324. {
  325. switch (event) {
  326. case RSPQ_E_STOP:
  327. case RSPQ_E_FAIL:
  328. bfa_fsm_set_state(rspq, rspq_sm_stopped);
  329. break;
  330. case RSPQ_E_RESP:
  331. bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
  332. break;
  333. default:
  334. bfa_sm_fault(event);
  335. }
  336. }
  337. static void
  338. rspq_sm_dbell_wait_entry(struct bfa_msgq_rspq *rspq)
  339. {
  340. if (!bfa_nw_ioc_is_disabled(rspq->msgq->ioc))
  341. bfa_msgq_rspq_dbell(rspq);
  342. }
  343. static void
  344. rspq_sm_dbell_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
  345. {
  346. switch (event) {
  347. case RSPQ_E_STOP:
  348. case RSPQ_E_FAIL:
  349. bfa_fsm_set_state(rspq, rspq_sm_stopped);
  350. break;
  351. case RSPQ_E_RESP:
  352. rspq->flags |= BFA_MSGQ_RSPQ_F_DB_UPDATE;
  353. break;
  354. case RSPQ_E_DB_READY:
  355. if (rspq->flags & BFA_MSGQ_RSPQ_F_DB_UPDATE) {
  356. rspq->flags &= ~BFA_MSGQ_RSPQ_F_DB_UPDATE;
  357. bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
  358. } else
  359. bfa_fsm_set_state(rspq, rspq_sm_ready);
  360. break;
  361. default:
  362. bfa_sm_fault(event);
  363. }
  364. }
  365. static void
  366. bfa_msgq_rspq_dbell_ready(void *arg)
  367. {
  368. struct bfa_msgq_rspq *rspq = (struct bfa_msgq_rspq *)arg;
  369. bfa_fsm_send_event(rspq, RSPQ_E_DB_READY);
  370. }
  371. static void
  372. bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq)
  373. {
  374. struct bfi_msgq_h2i_db *dbell =
  375. (struct bfi_msgq_h2i_db *)(&rspq->dbell_mb.msg[0]);
  376. memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
  377. bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_CI, 0);
  378. dbell->mh.mtag.i2htok = 0;
  379. dbell->idx.rspq_ci = htons(rspq->consumer_index);
  380. if (!bfa_nw_ioc_mbox_queue(rspq->msgq->ioc, &rspq->dbell_mb,
  381. bfa_msgq_rspq_dbell_ready, rspq)) {
  382. bfa_msgq_rspq_dbell_ready(rspq);
  383. }
  384. }
  385. static void
  386. bfa_msgq_rspq_pi_update(struct bfa_msgq_rspq *rspq, struct bfi_mbmsg *mb)
  387. {
  388. struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
  389. struct bfi_msgq_mhdr *msghdr;
  390. int num_entries;
  391. int mc;
  392. u8 *rspq_qe;
  393. rspq->producer_index = ntohs(dbell->idx.rspq_pi);
  394. while (rspq->consumer_index != rspq->producer_index) {
  395. rspq_qe = (u8 *)rspq->addr.kva;
  396. rspq_qe += (rspq->consumer_index * BFI_MSGQ_RSP_ENTRY_SIZE);
  397. msghdr = (struct bfi_msgq_mhdr *)rspq_qe;
  398. mc = msghdr->msg_class;
  399. num_entries = ntohs(msghdr->num_entries);
  400. if ((mc >= BFI_MC_MAX) || (rspq->rsphdlr[mc].cbfn == NULL))
  401. break;
  402. (rspq->rsphdlr[mc].cbfn)(rspq->rsphdlr[mc].cbarg, msghdr);
  403. BFA_MSGQ_INDX_ADD(rspq->consumer_index, num_entries,
  404. rspq->depth);
  405. }
  406. bfa_fsm_send_event(rspq, RSPQ_E_RESP);
  407. }
  408. static void
  409. bfa_msgq_rspq_attach(struct bfa_msgq_rspq *rspq, struct bfa_msgq *msgq)
  410. {
  411. rspq->depth = BFA_MSGQ_RSPQ_NUM_ENTRY;
  412. rspq->msgq = msgq;
  413. bfa_fsm_set_state(rspq, rspq_sm_stopped);
  414. }
  415. static void
  416. bfa_msgq_init_rsp(struct bfa_msgq *msgq,
  417. struct bfi_mbmsg *mb)
  418. {
  419. bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_INIT_RESP);
  420. bfa_fsm_send_event(&msgq->rspq, RSPQ_E_INIT_RESP);
  421. }
  422. static void
  423. bfa_msgq_init(void *arg)
  424. {
  425. struct bfa_msgq *msgq = (struct bfa_msgq *)arg;
  426. struct bfi_msgq_cfg_req *msgq_cfg =
  427. (struct bfi_msgq_cfg_req *)&msgq->init_mb.msg[0];
  428. memset(msgq_cfg, 0, sizeof(struct bfi_msgq_cfg_req));
  429. bfi_h2i_set(msgq_cfg->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_INIT_REQ, 0);
  430. msgq_cfg->mh.mtag.i2htok = 0;
  431. bfa_dma_be_addr_set(msgq_cfg->cmdq.addr, msgq->cmdq.addr.pa);
  432. msgq_cfg->cmdq.q_depth = htons(msgq->cmdq.depth);
  433. bfa_dma_be_addr_set(msgq_cfg->rspq.addr, msgq->rspq.addr.pa);
  434. msgq_cfg->rspq.q_depth = htons(msgq->rspq.depth);
  435. bfa_nw_ioc_mbox_queue(msgq->ioc, &msgq->init_mb, NULL, NULL);
  436. }
  437. static void
  438. bfa_msgq_isr(void *cbarg, struct bfi_mbmsg *msg)
  439. {
  440. struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
  441. switch (msg->mh.msg_id) {
  442. case BFI_MSGQ_I2H_INIT_RSP:
  443. bfa_msgq_init_rsp(msgq, msg);
  444. break;
  445. case BFI_MSGQ_I2H_DOORBELL_PI:
  446. bfa_msgq_rspq_pi_update(&msgq->rspq, msg);
  447. break;
  448. case BFI_MSGQ_I2H_DOORBELL_CI:
  449. bfa_msgq_cmdq_ci_update(&msgq->cmdq, msg);
  450. break;
  451. case BFI_MSGQ_I2H_CMDQ_COPY_REQ:
  452. bfa_msgq_cmdq_copy_req(&msgq->cmdq, msg);
  453. break;
  454. default:
  455. BUG_ON(1);
  456. }
  457. }
  458. static void
  459. bfa_msgq_notify(void *cbarg, enum bfa_ioc_event event)
  460. {
  461. struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
  462. switch (event) {
  463. case BFA_IOC_E_ENABLED:
  464. bfa_wc_init(&msgq->init_wc, bfa_msgq_init, msgq);
  465. bfa_wc_up(&msgq->init_wc);
  466. bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_START);
  467. bfa_wc_up(&msgq->init_wc);
  468. bfa_fsm_send_event(&msgq->rspq, RSPQ_E_START);
  469. bfa_wc_wait(&msgq->init_wc);
  470. break;
  471. case BFA_IOC_E_DISABLED:
  472. bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_STOP);
  473. bfa_fsm_send_event(&msgq->rspq, RSPQ_E_STOP);
  474. break;
  475. case BFA_IOC_E_FAILED:
  476. bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_FAIL);
  477. bfa_fsm_send_event(&msgq->rspq, RSPQ_E_FAIL);
  478. break;
  479. default:
  480. break;
  481. }
  482. }
  483. u32
  484. bfa_msgq_meminfo(void)
  485. {
  486. return roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ) +
  487. roundup(BFA_MSGQ_RSPQ_SIZE, BFA_DMA_ALIGN_SZ);
  488. }
  489. void
  490. bfa_msgq_memclaim(struct bfa_msgq *msgq, u8 *kva, u64 pa)
  491. {
  492. msgq->cmdq.addr.kva = kva;
  493. msgq->cmdq.addr.pa = pa;
  494. kva += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
  495. pa += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
  496. msgq->rspq.addr.kva = kva;
  497. msgq->rspq.addr.pa = pa;
  498. }
  499. void
  500. bfa_msgq_attach(struct bfa_msgq *msgq, struct bfa_ioc *ioc)
  501. {
  502. msgq->ioc = ioc;
  503. bfa_msgq_cmdq_attach(&msgq->cmdq, msgq);
  504. bfa_msgq_rspq_attach(&msgq->rspq, msgq);
  505. bfa_nw_ioc_mbox_regisr(msgq->ioc, BFI_MC_MSGQ, bfa_msgq_isr, msgq);
  506. bfa_ioc_notify_init(&msgq->ioc_notify, bfa_msgq_notify, msgq);
  507. bfa_nw_ioc_notify_register(msgq->ioc, &msgq->ioc_notify);
  508. }
  509. void
  510. bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
  511. bfa_msgq_mcfunc_t cbfn, void *cbarg)
  512. {
  513. msgq->rspq.rsphdlr[mc].cbfn = cbfn;
  514. msgq->rspq.rsphdlr[mc].cbarg = cbarg;
  515. }
  516. void
  517. bfa_msgq_cmd_post(struct bfa_msgq *msgq, struct bfa_msgq_cmd_entry *cmd)
  518. {
  519. if (ntohs(cmd->msg_hdr->num_entries) <=
  520. BFA_MSGQ_FREE_CNT(&msgq->cmdq)) {
  521. __cmd_copy(&msgq->cmdq, cmd);
  522. call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
  523. bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_POST);
  524. } else {
  525. list_add_tail(&cmd->qe, &msgq->cmdq.pending_q);
  526. }
  527. }
  528. void
  529. bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len)
  530. {
  531. struct bfa_msgq_rspq *rspq = &msgq->rspq;
  532. size_t len = buf_len;
  533. size_t to_copy;
  534. int ci;
  535. u8 *src, *dst;
  536. ci = rspq->consumer_index;
  537. src = (u8 *)rspq->addr.kva;
  538. src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
  539. dst = buf;
  540. while (len) {
  541. to_copy = (len < BFI_MSGQ_RSP_ENTRY_SIZE) ?
  542. len : BFI_MSGQ_RSP_ENTRY_SIZE;
  543. memcpy(dst, src, to_copy);
  544. len -= to_copy;
  545. dst += BFI_MSGQ_RSP_ENTRY_SIZE;
  546. BFA_MSGQ_INDX_ADD(ci, 1, rspq->depth);
  547. src = (u8 *)rspq->addr.kva;
  548. src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
  549. }
  550. }