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