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