0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "bfi.h"
0015 #include "bfa_msgq.h"
0016 #include "bfa_ioc.h"
0017
0018 #define call_cmdq_ent_cbfn(_cmdq_ent, _status) \
0019 { \
0020 bfa_msgq_cmdcbfn_t cbfn; \
0021 void *cbarg; \
0022 cbfn = (_cmdq_ent)->cbfn; \
0023 cbarg = (_cmdq_ent)->cbarg; \
0024 (_cmdq_ent)->cbfn = NULL; \
0025 (_cmdq_ent)->cbarg = NULL; \
0026 if (cbfn) { \
0027 cbfn(cbarg, (_status)); \
0028 } \
0029 }
0030
0031 static void bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq);
0032 static void bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq);
0033
0034 enum cmdq_event {
0035 CMDQ_E_START = 1,
0036 CMDQ_E_STOP = 2,
0037 CMDQ_E_FAIL = 3,
0038 CMDQ_E_POST = 4,
0039 CMDQ_E_INIT_RESP = 5,
0040 CMDQ_E_DB_READY = 6,
0041 };
0042
0043 bfa_fsm_state_decl(cmdq, stopped, struct bfa_msgq_cmdq, enum cmdq_event);
0044 bfa_fsm_state_decl(cmdq, init_wait, struct bfa_msgq_cmdq, enum cmdq_event);
0045 bfa_fsm_state_decl(cmdq, ready, struct bfa_msgq_cmdq, enum cmdq_event);
0046 bfa_fsm_state_decl(cmdq, dbell_wait, struct bfa_msgq_cmdq,
0047 enum cmdq_event);
0048
0049 static void
0050 cmdq_sm_stopped_entry(struct bfa_msgq_cmdq *cmdq)
0051 {
0052 struct bfa_msgq_cmd_entry *cmdq_ent;
0053
0054 cmdq->producer_index = 0;
0055 cmdq->consumer_index = 0;
0056 cmdq->flags = 0;
0057 cmdq->token = 0;
0058 cmdq->offset = 0;
0059 cmdq->bytes_to_copy = 0;
0060 while (!list_empty(&cmdq->pending_q)) {
0061 cmdq_ent = list_first_entry(&cmdq->pending_q,
0062 struct bfa_msgq_cmd_entry, qe);
0063 list_del(&cmdq_ent->qe);
0064 call_cmdq_ent_cbfn(cmdq_ent, BFA_STATUS_FAILED);
0065 }
0066 }
0067
0068 static void
0069 cmdq_sm_stopped(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
0070 {
0071 switch (event) {
0072 case CMDQ_E_START:
0073 bfa_fsm_set_state(cmdq, cmdq_sm_init_wait);
0074 break;
0075
0076 case CMDQ_E_STOP:
0077 case CMDQ_E_FAIL:
0078
0079 break;
0080
0081 case CMDQ_E_POST:
0082 cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
0083 break;
0084
0085 default:
0086 bfa_sm_fault(event);
0087 }
0088 }
0089
0090 static void
0091 cmdq_sm_init_wait_entry(struct bfa_msgq_cmdq *cmdq)
0092 {
0093 bfa_wc_down(&cmdq->msgq->init_wc);
0094 }
0095
0096 static void
0097 cmdq_sm_init_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
0098 {
0099 switch (event) {
0100 case CMDQ_E_STOP:
0101 case CMDQ_E_FAIL:
0102 bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
0103 break;
0104
0105 case CMDQ_E_POST:
0106 cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
0107 break;
0108
0109 case CMDQ_E_INIT_RESP:
0110 if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
0111 cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
0112 bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
0113 } else
0114 bfa_fsm_set_state(cmdq, cmdq_sm_ready);
0115 break;
0116
0117 default:
0118 bfa_sm_fault(event);
0119 }
0120 }
0121
0122 static void
0123 cmdq_sm_ready_entry(struct bfa_msgq_cmdq *cmdq)
0124 {
0125 }
0126
0127 static void
0128 cmdq_sm_ready(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
0129 {
0130 switch (event) {
0131 case CMDQ_E_STOP:
0132 case CMDQ_E_FAIL:
0133 bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
0134 break;
0135
0136 case CMDQ_E_POST:
0137 bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
0138 break;
0139
0140 default:
0141 bfa_sm_fault(event);
0142 }
0143 }
0144
0145 static void
0146 cmdq_sm_dbell_wait_entry(struct bfa_msgq_cmdq *cmdq)
0147 {
0148 bfa_msgq_cmdq_dbell(cmdq);
0149 }
0150
0151 static void
0152 cmdq_sm_dbell_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
0153 {
0154 switch (event) {
0155 case CMDQ_E_STOP:
0156 case CMDQ_E_FAIL:
0157 bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
0158 break;
0159
0160 case CMDQ_E_POST:
0161 cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
0162 break;
0163
0164 case CMDQ_E_DB_READY:
0165 if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
0166 cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
0167 bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
0168 } else
0169 bfa_fsm_set_state(cmdq, cmdq_sm_ready);
0170 break;
0171
0172 default:
0173 bfa_sm_fault(event);
0174 }
0175 }
0176
0177 static void
0178 bfa_msgq_cmdq_dbell_ready(void *arg)
0179 {
0180 struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
0181 bfa_fsm_send_event(cmdq, CMDQ_E_DB_READY);
0182 }
0183
0184 static void
0185 bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq)
0186 {
0187 struct bfi_msgq_h2i_db *dbell =
0188 (struct bfi_msgq_h2i_db *)(&cmdq->dbell_mb.msg[0]);
0189
0190 memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
0191 bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_PI, 0);
0192 dbell->mh.mtag.i2htok = 0;
0193 dbell->idx.cmdq_pi = htons(cmdq->producer_index);
0194
0195 if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->dbell_mb,
0196 bfa_msgq_cmdq_dbell_ready, cmdq)) {
0197 bfa_msgq_cmdq_dbell_ready(cmdq);
0198 }
0199 }
0200
0201 static void
0202 __cmd_copy(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq_cmd_entry *cmd)
0203 {
0204 size_t len = cmd->msg_size;
0205 int num_entries = 0;
0206 size_t to_copy;
0207 u8 *src, *dst;
0208
0209 src = (u8 *)cmd->msg_hdr;
0210 dst = (u8 *)cmdq->addr.kva;
0211 dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
0212
0213 while (len) {
0214 to_copy = (len < BFI_MSGQ_CMD_ENTRY_SIZE) ?
0215 len : BFI_MSGQ_CMD_ENTRY_SIZE;
0216 memcpy(dst, src, to_copy);
0217 len -= to_copy;
0218 src += BFI_MSGQ_CMD_ENTRY_SIZE;
0219 BFA_MSGQ_INDX_ADD(cmdq->producer_index, 1, cmdq->depth);
0220 dst = (u8 *)cmdq->addr.kva;
0221 dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
0222 num_entries++;
0223 }
0224
0225 }
0226
0227 static void
0228 bfa_msgq_cmdq_ci_update(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
0229 {
0230 struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
0231 struct bfa_msgq_cmd_entry *cmd;
0232 int posted = 0;
0233
0234 cmdq->consumer_index = ntohs(dbell->idx.cmdq_ci);
0235
0236
0237 while (!list_empty(&cmdq->pending_q)) {
0238 cmd = list_first_entry(&cmdq->pending_q,
0239 struct bfa_msgq_cmd_entry, qe);
0240 if (ntohs(cmd->msg_hdr->num_entries) <=
0241 BFA_MSGQ_FREE_CNT(cmdq)) {
0242 list_del(&cmd->qe);
0243 __cmd_copy(cmdq, cmd);
0244 posted = 1;
0245 call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
0246 } else {
0247 break;
0248 }
0249 }
0250
0251 if (posted)
0252 bfa_fsm_send_event(cmdq, CMDQ_E_POST);
0253 }
0254
0255 static void
0256 bfa_msgq_cmdq_copy_next(void *arg)
0257 {
0258 struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
0259
0260 if (cmdq->bytes_to_copy)
0261 bfa_msgq_cmdq_copy_rsp(cmdq);
0262 }
0263
0264 static void
0265 bfa_msgq_cmdq_copy_req(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
0266 {
0267 struct bfi_msgq_i2h_cmdq_copy_req *req =
0268 (struct bfi_msgq_i2h_cmdq_copy_req *)mb;
0269
0270 cmdq->token = 0;
0271 cmdq->offset = ntohs(req->offset);
0272 cmdq->bytes_to_copy = ntohs(req->len);
0273 bfa_msgq_cmdq_copy_rsp(cmdq);
0274 }
0275
0276 static void
0277 bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq)
0278 {
0279 struct bfi_msgq_h2i_cmdq_copy_rsp *rsp =
0280 (struct bfi_msgq_h2i_cmdq_copy_rsp *)&cmdq->copy_mb.msg[0];
0281 int copied;
0282 u8 *addr = (u8 *)cmdq->addr.kva;
0283
0284 memset(rsp, 0, sizeof(struct bfi_msgq_h2i_cmdq_copy_rsp));
0285 bfi_h2i_set(rsp->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_CMDQ_COPY_RSP, 0);
0286 rsp->mh.mtag.i2htok = htons(cmdq->token);
0287 copied = (cmdq->bytes_to_copy >= BFI_CMD_COPY_SZ) ? BFI_CMD_COPY_SZ :
0288 cmdq->bytes_to_copy;
0289 addr += cmdq->offset;
0290 memcpy(rsp->data, addr, copied);
0291
0292 cmdq->token++;
0293 cmdq->offset += copied;
0294 cmdq->bytes_to_copy -= copied;
0295
0296 if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->copy_mb,
0297 bfa_msgq_cmdq_copy_next, cmdq)) {
0298 bfa_msgq_cmdq_copy_next(cmdq);
0299 }
0300 }
0301
0302 static void
0303 bfa_msgq_cmdq_attach(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq *msgq)
0304 {
0305 cmdq->depth = BFA_MSGQ_CMDQ_NUM_ENTRY;
0306 INIT_LIST_HEAD(&cmdq->pending_q);
0307 cmdq->msgq = msgq;
0308 bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
0309 }
0310
0311 static void bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq);
0312
0313 enum rspq_event {
0314 RSPQ_E_START = 1,
0315 RSPQ_E_STOP = 2,
0316 RSPQ_E_FAIL = 3,
0317 RSPQ_E_RESP = 4,
0318 RSPQ_E_INIT_RESP = 5,
0319 RSPQ_E_DB_READY = 6,
0320 };
0321
0322 bfa_fsm_state_decl(rspq, stopped, struct bfa_msgq_rspq, enum rspq_event);
0323 bfa_fsm_state_decl(rspq, init_wait, struct bfa_msgq_rspq,
0324 enum rspq_event);
0325 bfa_fsm_state_decl(rspq, ready, struct bfa_msgq_rspq, enum rspq_event);
0326 bfa_fsm_state_decl(rspq, dbell_wait, struct bfa_msgq_rspq,
0327 enum rspq_event);
0328
0329 static void
0330 rspq_sm_stopped_entry(struct bfa_msgq_rspq *rspq)
0331 {
0332 rspq->producer_index = 0;
0333 rspq->consumer_index = 0;
0334 rspq->flags = 0;
0335 }
0336
0337 static void
0338 rspq_sm_stopped(struct bfa_msgq_rspq *rspq, enum rspq_event event)
0339 {
0340 switch (event) {
0341 case RSPQ_E_START:
0342 bfa_fsm_set_state(rspq, rspq_sm_init_wait);
0343 break;
0344
0345 case RSPQ_E_STOP:
0346 case RSPQ_E_FAIL:
0347
0348 break;
0349
0350 default:
0351 bfa_sm_fault(event);
0352 }
0353 }
0354
0355 static void
0356 rspq_sm_init_wait_entry(struct bfa_msgq_rspq *rspq)
0357 {
0358 bfa_wc_down(&rspq->msgq->init_wc);
0359 }
0360
0361 static void
0362 rspq_sm_init_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
0363 {
0364 switch (event) {
0365 case RSPQ_E_FAIL:
0366 case RSPQ_E_STOP:
0367 bfa_fsm_set_state(rspq, rspq_sm_stopped);
0368 break;
0369
0370 case RSPQ_E_INIT_RESP:
0371 bfa_fsm_set_state(rspq, rspq_sm_ready);
0372 break;
0373
0374 default:
0375 bfa_sm_fault(event);
0376 }
0377 }
0378
0379 static void
0380 rspq_sm_ready_entry(struct bfa_msgq_rspq *rspq)
0381 {
0382 }
0383
0384 static void
0385 rspq_sm_ready(struct bfa_msgq_rspq *rspq, enum rspq_event event)
0386 {
0387 switch (event) {
0388 case RSPQ_E_STOP:
0389 case RSPQ_E_FAIL:
0390 bfa_fsm_set_state(rspq, rspq_sm_stopped);
0391 break;
0392
0393 case RSPQ_E_RESP:
0394 bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
0395 break;
0396
0397 default:
0398 bfa_sm_fault(event);
0399 }
0400 }
0401
0402 static void
0403 rspq_sm_dbell_wait_entry(struct bfa_msgq_rspq *rspq)
0404 {
0405 if (!bfa_nw_ioc_is_disabled(rspq->msgq->ioc))
0406 bfa_msgq_rspq_dbell(rspq);
0407 }
0408
0409 static void
0410 rspq_sm_dbell_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
0411 {
0412 switch (event) {
0413 case RSPQ_E_STOP:
0414 case RSPQ_E_FAIL:
0415 bfa_fsm_set_state(rspq, rspq_sm_stopped);
0416 break;
0417
0418 case RSPQ_E_RESP:
0419 rspq->flags |= BFA_MSGQ_RSPQ_F_DB_UPDATE;
0420 break;
0421
0422 case RSPQ_E_DB_READY:
0423 if (rspq->flags & BFA_MSGQ_RSPQ_F_DB_UPDATE) {
0424 rspq->flags &= ~BFA_MSGQ_RSPQ_F_DB_UPDATE;
0425 bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
0426 } else
0427 bfa_fsm_set_state(rspq, rspq_sm_ready);
0428 break;
0429
0430 default:
0431 bfa_sm_fault(event);
0432 }
0433 }
0434
0435 static void
0436 bfa_msgq_rspq_dbell_ready(void *arg)
0437 {
0438 struct bfa_msgq_rspq *rspq = (struct bfa_msgq_rspq *)arg;
0439 bfa_fsm_send_event(rspq, RSPQ_E_DB_READY);
0440 }
0441
0442 static void
0443 bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq)
0444 {
0445 struct bfi_msgq_h2i_db *dbell =
0446 (struct bfi_msgq_h2i_db *)(&rspq->dbell_mb.msg[0]);
0447
0448 memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
0449 bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_CI, 0);
0450 dbell->mh.mtag.i2htok = 0;
0451 dbell->idx.rspq_ci = htons(rspq->consumer_index);
0452
0453 if (!bfa_nw_ioc_mbox_queue(rspq->msgq->ioc, &rspq->dbell_mb,
0454 bfa_msgq_rspq_dbell_ready, rspq)) {
0455 bfa_msgq_rspq_dbell_ready(rspq);
0456 }
0457 }
0458
0459 static void
0460 bfa_msgq_rspq_pi_update(struct bfa_msgq_rspq *rspq, struct bfi_mbmsg *mb)
0461 {
0462 struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
0463 struct bfi_msgq_mhdr *msghdr;
0464 int num_entries;
0465 int mc;
0466 u8 *rspq_qe;
0467
0468 rspq->producer_index = ntohs(dbell->idx.rspq_pi);
0469
0470 while (rspq->consumer_index != rspq->producer_index) {
0471 rspq_qe = (u8 *)rspq->addr.kva;
0472 rspq_qe += (rspq->consumer_index * BFI_MSGQ_RSP_ENTRY_SIZE);
0473 msghdr = (struct bfi_msgq_mhdr *)rspq_qe;
0474
0475 mc = msghdr->msg_class;
0476 num_entries = ntohs(msghdr->num_entries);
0477
0478 if ((mc >= BFI_MC_MAX) || (rspq->rsphdlr[mc].cbfn == NULL))
0479 break;
0480
0481 (rspq->rsphdlr[mc].cbfn)(rspq->rsphdlr[mc].cbarg, msghdr);
0482
0483 BFA_MSGQ_INDX_ADD(rspq->consumer_index, num_entries,
0484 rspq->depth);
0485 }
0486
0487 bfa_fsm_send_event(rspq, RSPQ_E_RESP);
0488 }
0489
0490 static void
0491 bfa_msgq_rspq_attach(struct bfa_msgq_rspq *rspq, struct bfa_msgq *msgq)
0492 {
0493 rspq->depth = BFA_MSGQ_RSPQ_NUM_ENTRY;
0494 rspq->msgq = msgq;
0495 bfa_fsm_set_state(rspq, rspq_sm_stopped);
0496 }
0497
0498 static void
0499 bfa_msgq_init_rsp(struct bfa_msgq *msgq,
0500 struct bfi_mbmsg *mb)
0501 {
0502 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_INIT_RESP);
0503 bfa_fsm_send_event(&msgq->rspq, RSPQ_E_INIT_RESP);
0504 }
0505
0506 static void
0507 bfa_msgq_init(void *arg)
0508 {
0509 struct bfa_msgq *msgq = (struct bfa_msgq *)arg;
0510 struct bfi_msgq_cfg_req *msgq_cfg =
0511 (struct bfi_msgq_cfg_req *)&msgq->init_mb.msg[0];
0512
0513 memset(msgq_cfg, 0, sizeof(struct bfi_msgq_cfg_req));
0514 bfi_h2i_set(msgq_cfg->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_INIT_REQ, 0);
0515 msgq_cfg->mh.mtag.i2htok = 0;
0516
0517 bfa_dma_be_addr_set(msgq_cfg->cmdq.addr, msgq->cmdq.addr.pa);
0518 msgq_cfg->cmdq.q_depth = htons(msgq->cmdq.depth);
0519 bfa_dma_be_addr_set(msgq_cfg->rspq.addr, msgq->rspq.addr.pa);
0520 msgq_cfg->rspq.q_depth = htons(msgq->rspq.depth);
0521
0522 bfa_nw_ioc_mbox_queue(msgq->ioc, &msgq->init_mb, NULL, NULL);
0523 }
0524
0525 static void
0526 bfa_msgq_isr(void *cbarg, struct bfi_mbmsg *msg)
0527 {
0528 struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
0529
0530 switch (msg->mh.msg_id) {
0531 case BFI_MSGQ_I2H_INIT_RSP:
0532 bfa_msgq_init_rsp(msgq, msg);
0533 break;
0534
0535 case BFI_MSGQ_I2H_DOORBELL_PI:
0536 bfa_msgq_rspq_pi_update(&msgq->rspq, msg);
0537 break;
0538
0539 case BFI_MSGQ_I2H_DOORBELL_CI:
0540 bfa_msgq_cmdq_ci_update(&msgq->cmdq, msg);
0541 break;
0542
0543 case BFI_MSGQ_I2H_CMDQ_COPY_REQ:
0544 bfa_msgq_cmdq_copy_req(&msgq->cmdq, msg);
0545 break;
0546
0547 default:
0548 BUG_ON(1);
0549 }
0550 }
0551
0552 static void
0553 bfa_msgq_notify(void *cbarg, enum bfa_ioc_event event)
0554 {
0555 struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
0556
0557 switch (event) {
0558 case BFA_IOC_E_ENABLED:
0559 bfa_wc_init(&msgq->init_wc, bfa_msgq_init, msgq);
0560 bfa_wc_up(&msgq->init_wc);
0561 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_START);
0562 bfa_wc_up(&msgq->init_wc);
0563 bfa_fsm_send_event(&msgq->rspq, RSPQ_E_START);
0564 bfa_wc_wait(&msgq->init_wc);
0565 break;
0566
0567 case BFA_IOC_E_DISABLED:
0568 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_STOP);
0569 bfa_fsm_send_event(&msgq->rspq, RSPQ_E_STOP);
0570 break;
0571
0572 case BFA_IOC_E_FAILED:
0573 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_FAIL);
0574 bfa_fsm_send_event(&msgq->rspq, RSPQ_E_FAIL);
0575 break;
0576
0577 default:
0578 break;
0579 }
0580 }
0581
0582 u32
0583 bfa_msgq_meminfo(void)
0584 {
0585 return roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ) +
0586 roundup(BFA_MSGQ_RSPQ_SIZE, BFA_DMA_ALIGN_SZ);
0587 }
0588
0589 void
0590 bfa_msgq_memclaim(struct bfa_msgq *msgq, u8 *kva, u64 pa)
0591 {
0592 msgq->cmdq.addr.kva = kva;
0593 msgq->cmdq.addr.pa = pa;
0594
0595 kva += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
0596 pa += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
0597
0598 msgq->rspq.addr.kva = kva;
0599 msgq->rspq.addr.pa = pa;
0600 }
0601
0602 void
0603 bfa_msgq_attach(struct bfa_msgq *msgq, struct bfa_ioc *ioc)
0604 {
0605 msgq->ioc = ioc;
0606
0607 bfa_msgq_cmdq_attach(&msgq->cmdq, msgq);
0608 bfa_msgq_rspq_attach(&msgq->rspq, msgq);
0609
0610 bfa_nw_ioc_mbox_regisr(msgq->ioc, BFI_MC_MSGQ, bfa_msgq_isr, msgq);
0611 bfa_ioc_notify_init(&msgq->ioc_notify, bfa_msgq_notify, msgq);
0612 bfa_nw_ioc_notify_register(msgq->ioc, &msgq->ioc_notify);
0613 }
0614
0615 void
0616 bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
0617 bfa_msgq_mcfunc_t cbfn, void *cbarg)
0618 {
0619 msgq->rspq.rsphdlr[mc].cbfn = cbfn;
0620 msgq->rspq.rsphdlr[mc].cbarg = cbarg;
0621 }
0622
0623 void
0624 bfa_msgq_cmd_post(struct bfa_msgq *msgq, struct bfa_msgq_cmd_entry *cmd)
0625 {
0626 if (ntohs(cmd->msg_hdr->num_entries) <=
0627 BFA_MSGQ_FREE_CNT(&msgq->cmdq)) {
0628 __cmd_copy(&msgq->cmdq, cmd);
0629 call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
0630 bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_POST);
0631 } else {
0632 list_add_tail(&cmd->qe, &msgq->cmdq.pending_q);
0633 }
0634 }
0635
0636 void
0637 bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len)
0638 {
0639 struct bfa_msgq_rspq *rspq = &msgq->rspq;
0640 size_t len = buf_len;
0641 size_t to_copy;
0642 int ci;
0643 u8 *src, *dst;
0644
0645 ci = rspq->consumer_index;
0646 src = (u8 *)rspq->addr.kva;
0647 src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
0648 dst = buf;
0649
0650 while (len) {
0651 to_copy = (len < BFI_MSGQ_RSP_ENTRY_SIZE) ?
0652 len : BFI_MSGQ_RSP_ENTRY_SIZE;
0653 memcpy(dst, src, to_copy);
0654 len -= to_copy;
0655 dst += BFI_MSGQ_RSP_ENTRY_SIZE;
0656 BFA_MSGQ_INDX_ADD(ci, 1, rspq->depth);
0657 src = (u8 *)rspq->addr.kva;
0658 src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
0659 }
0660 }