Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Linux network driver for QLogic BR-series Converged Network Adapter.
0004  */
0005 /*
0006  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
0007  * Copyright (c) 2014-2015 QLogic Corporation
0008  * All rights reserved
0009  * www.qlogic.com
0010  */
0011 
0012 /* MSGQ module source file. */
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         /* No-op */
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     /* Walk through pending list to see if the command can be posted */
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         /* No-op */
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 }