linux/drivers/scsi/bfa/bfa_fcxp.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
   3 * All rights reserved
   4 * www.brocade.com
   5 *
   6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms of the GNU General Public License (GPL) Version 2 as
  10 * published by the Free Software Foundation
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 */
  17
  18#include <bfa.h>
  19#include <bfi/bfi_uf.h>
  20#include <cs/bfa_debug.h>
  21
  22BFA_TRC_FILE(HAL, FCXP);
  23BFA_MODULE(fcxp);
  24
  25/**
  26 * forward declarations
  27 */
  28static void     __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
  29static void     hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
  30                                 struct bfi_fcxp_send_rsp_s *fcxp_rsp);
  31static void     hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
  32                                 struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
  33static void     bfa_fcxp_qresume(void *cbarg);
  34static void     bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
  35                               struct bfi_fcxp_send_req_s *send_req);
  36
  37/**
  38 *  fcxp_pvt BFA FCXP private functions
  39 */
  40
  41static void
  42claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
  43{
  44        u8        *dm_kva = NULL;
  45        u64        dm_pa;
  46        u32        buf_pool_sz;
  47
  48        dm_kva = bfa_meminfo_dma_virt(mi);
  49        dm_pa = bfa_meminfo_dma_phys(mi);
  50
  51        buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
  52
  53        /*
  54         * Initialize the fcxp req payload list
  55         */
  56        mod->req_pld_list_kva = dm_kva;
  57        mod->req_pld_list_pa = dm_pa;
  58        dm_kva += buf_pool_sz;
  59        dm_pa += buf_pool_sz;
  60        bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
  61
  62        /*
  63         * Initialize the fcxp rsp payload list
  64         */
  65        buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
  66        mod->rsp_pld_list_kva = dm_kva;
  67        mod->rsp_pld_list_pa = dm_pa;
  68        dm_kva += buf_pool_sz;
  69        dm_pa += buf_pool_sz;
  70        bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
  71
  72        bfa_meminfo_dma_virt(mi) = dm_kva;
  73        bfa_meminfo_dma_phys(mi) = dm_pa;
  74}
  75
  76static void
  77claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
  78{
  79        u16        i;
  80        struct bfa_fcxp_s *fcxp;
  81
  82        fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
  83        bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
  84
  85        INIT_LIST_HEAD(&mod->fcxp_free_q);
  86        INIT_LIST_HEAD(&mod->fcxp_active_q);
  87
  88        mod->fcxp_list = fcxp;
  89
  90        for (i = 0; i < mod->num_fcxps; i++) {
  91                fcxp->fcxp_mod = mod;
  92                fcxp->fcxp_tag = i;
  93
  94                list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
  95                bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
  96                fcxp->reqq_waiting = BFA_FALSE;
  97
  98                fcxp = fcxp + 1;
  99        }
 100
 101        bfa_meminfo_kva(mi) = (void *)fcxp;
 102}
 103
 104static void
 105bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
 106                u32 *dm_len)
 107{
 108        u16        num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
 109
 110        if (num_fcxp_reqs == 0)
 111                return;
 112
 113        /*
 114         * Account for req/rsp payload
 115         */
 116        *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
 117        if (cfg->drvcfg.min_cfg)
 118                *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
 119        else
 120                *dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
 121
 122        /*
 123         * Account for fcxp structs
 124         */
 125        *ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
 126}
 127
 128static void
 129bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 130                    struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
 131{
 132        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 133
 134        bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
 135        mod->bfa = bfa;
 136        mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
 137
 138        /**
 139         * Initialize FCXP request and response payload sizes.
 140         */
 141        mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
 142        if (!cfg->drvcfg.min_cfg)
 143                mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
 144
 145        INIT_LIST_HEAD(&mod->wait_q);
 146
 147        claim_fcxp_req_rsp_mem(mod, meminfo);
 148        claim_fcxps_mem(mod, meminfo);
 149}
 150
 151static void
 152bfa_fcxp_initdone(struct bfa_s *bfa)
 153{
 154}
 155
 156static void
 157bfa_fcxp_detach(struct bfa_s *bfa)
 158{
 159}
 160
 161static void
 162bfa_fcxp_start(struct bfa_s *bfa)
 163{
 164}
 165
 166static void
 167bfa_fcxp_stop(struct bfa_s *bfa)
 168{
 169}
 170
 171static void
 172bfa_fcxp_iocdisable(struct bfa_s *bfa)
 173{
 174        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 175        struct bfa_fcxp_s *fcxp;
 176        struct list_head        *qe, *qen;
 177
 178        list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
 179                fcxp = (struct bfa_fcxp_s *) qe;
 180                if (fcxp->caller == NULL) {
 181                        fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
 182                                        BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
 183                        bfa_fcxp_free(fcxp);
 184                } else {
 185                        fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
 186                        bfa_cb_queue(bfa, &fcxp->hcb_qe,
 187                                      __bfa_fcxp_send_cbfn, fcxp);
 188                }
 189        }
 190}
 191
 192static struct bfa_fcxp_s *
 193bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
 194{
 195        struct bfa_fcxp_s *fcxp;
 196
 197        bfa_q_deq(&fm->fcxp_free_q, &fcxp);
 198
 199        if (fcxp)
 200                list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
 201
 202        return (fcxp);
 203}
 204
 205static void
 206bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
 207{
 208        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 209        struct bfa_fcxp_wqe_s *wqe;
 210
 211        bfa_q_deq(&mod->wait_q, &wqe);
 212        if (wqe) {
 213                bfa_trc(mod->bfa, fcxp->fcxp_tag);
 214                wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
 215                return;
 216        }
 217
 218        bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
 219        list_del(&fcxp->qe);
 220        list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
 221}
 222
 223static void
 224bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
 225                       bfa_status_t req_status, u32 rsp_len,
 226                       u32 resid_len, struct fchs_s *rsp_fchs)
 227{
 228        /**discarded fcxp completion */
 229}
 230
 231static void
 232__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
 233{
 234        struct bfa_fcxp_s *fcxp = cbarg;
 235
 236        if (complete) {
 237                fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
 238                                fcxp->rsp_status, fcxp->rsp_len,
 239                                fcxp->residue_len, &fcxp->rsp_fchs);
 240        } else {
 241                bfa_fcxp_free(fcxp);
 242        }
 243}
 244
 245static void
 246hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
 247{
 248        struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
 249        struct bfa_fcxp_s       *fcxp;
 250        u16             fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
 251
 252        bfa_trc(bfa, fcxp_tag);
 253
 254        fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
 255
 256        /**
 257         * @todo f/w should not set residue to non-0 when everything
 258         *       is received.
 259         */
 260        if (fcxp_rsp->req_status == BFA_STATUS_OK)
 261                fcxp_rsp->residue_len = 0;
 262        else
 263                fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
 264
 265        fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
 266
 267        bfa_assert(fcxp->send_cbfn != NULL);
 268
 269        hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
 270
 271        if (fcxp->send_cbfn != NULL) {
 272                if (fcxp->caller == NULL) {
 273                        bfa_trc(mod->bfa, fcxp->fcxp_tag);
 274
 275                        fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
 276                                        fcxp_rsp->req_status, fcxp_rsp->rsp_len,
 277                                        fcxp_rsp->residue_len, &fcxp_rsp->fchs);
 278                        /*
 279                         * fcxp automatically freed on return from the callback
 280                         */
 281                        bfa_fcxp_free(fcxp);
 282                } else {
 283                        bfa_trc(mod->bfa, fcxp->fcxp_tag);
 284                        fcxp->rsp_status = fcxp_rsp->req_status;
 285                        fcxp->rsp_len = fcxp_rsp->rsp_len;
 286                        fcxp->residue_len = fcxp_rsp->residue_len;
 287                        fcxp->rsp_fchs = fcxp_rsp->fchs;
 288
 289                        bfa_cb_queue(bfa, &fcxp->hcb_qe,
 290                                      __bfa_fcxp_send_cbfn, fcxp);
 291                }
 292        } else {
 293                bfa_trc(bfa, fcxp_tag);
 294        }
 295}
 296
 297static void
 298hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
 299{
 300        union bfi_addr_u      sga_zero = { {0} };
 301
 302        sge->sg_len = reqlen;
 303        sge->flags = BFI_SGE_DATA_LAST;
 304        bfa_dma_addr_set(sge[0].sga, req_pa);
 305        bfa_sge_to_be(sge);
 306        sge++;
 307
 308        sge->sga = sga_zero;
 309        sge->sg_len = reqlen;
 310        sge->flags = BFI_SGE_PGDLEN;
 311        bfa_sge_to_be(sge);
 312}
 313
 314static void
 315hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
 316                 struct fchs_s *fchs)
 317{
 318        /*
 319         * TODO: TX ox_id
 320         */
 321        if (reqlen > 0) {
 322                if (fcxp->use_ireqbuf) {
 323                        u32        pld_w0 =
 324                                *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
 325
 326                        bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
 327                                BFA_PL_EID_TX,
 328                                reqlen + sizeof(struct fchs_s), fchs, pld_w0);
 329                } else {
 330                        bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
 331                                BFA_PL_EID_TX, reqlen + sizeof(struct fchs_s),
 332                                fchs);
 333                }
 334        } else {
 335                bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
 336                               reqlen + sizeof(struct fchs_s), fchs);
 337        }
 338}
 339
 340static void
 341hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
 342                 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
 343{
 344        if (fcxp_rsp->rsp_len > 0) {
 345                if (fcxp->use_irspbuf) {
 346                        u32        pld_w0 =
 347                                *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
 348
 349                        bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
 350                                              BFA_PL_EID_RX,
 351                                              (u16) fcxp_rsp->rsp_len,
 352                                              &fcxp_rsp->fchs, pld_w0);
 353                } else {
 354                        bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
 355                                       BFA_PL_EID_RX,
 356                                       (u16) fcxp_rsp->rsp_len,
 357                                       &fcxp_rsp->fchs);
 358                }
 359        } else {
 360                bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
 361                               (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
 362        }
 363}
 364
 365/**
 366 * Handler to resume sending fcxp when space in available in cpe queue.
 367 */
 368static void
 369bfa_fcxp_qresume(void *cbarg)
 370{
 371        struct bfa_fcxp_s               *fcxp = cbarg;
 372        struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
 373        struct bfi_fcxp_send_req_s      *send_req;
 374
 375        fcxp->reqq_waiting = BFA_FALSE;
 376        send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
 377        bfa_fcxp_queue(fcxp, send_req);
 378}
 379
 380/**
 381 * Queue fcxp send request to foimrware.
 382 */
 383static void
 384bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
 385{
 386        struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
 387        struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
 388        struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
 389        struct bfa_rport_s              *rport = reqi->bfa_rport;
 390
 391        bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
 392                        bfa_lpuid(bfa));
 393
 394        send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
 395        if (rport) {
 396                send_req->rport_fw_hndl = rport->fw_handle;
 397                send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
 398                if (send_req->max_frmsz == 0)
 399                        send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
 400        } else {
 401                send_req->rport_fw_hndl = 0;
 402                send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
 403        }
 404
 405        send_req->vf_id = bfa_os_htons(reqi->vf_id);
 406        send_req->lp_tag = reqi->lp_tag;
 407        send_req->class = reqi->class;
 408        send_req->rsp_timeout = rspi->rsp_timeout;
 409        send_req->cts = reqi->cts;
 410        send_req->fchs = reqi->fchs;
 411
 412        send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
 413        send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
 414
 415        /*
 416         * setup req sgles
 417         */
 418        if (fcxp->use_ireqbuf == 1) {
 419                hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
 420                                        BFA_FCXP_REQ_PLD_PA(fcxp));
 421        } else {
 422                if (fcxp->nreq_sgles > 0) {
 423                        bfa_assert(fcxp->nreq_sgles == 1);
 424                        hal_fcxp_set_local_sges(send_req->req_sge,
 425                                                reqi->req_tot_len,
 426                                                fcxp->req_sga_cbfn(fcxp->caller,
 427                                                                   0));
 428                } else {
 429                        bfa_assert(reqi->req_tot_len == 0);
 430                        hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
 431                }
 432        }
 433
 434        /*
 435         * setup rsp sgles
 436         */
 437        if (fcxp->use_irspbuf == 1) {
 438                bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
 439
 440                hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
 441                                        BFA_FCXP_RSP_PLD_PA(fcxp));
 442
 443        } else {
 444                if (fcxp->nrsp_sgles > 0) {
 445                        bfa_assert(fcxp->nrsp_sgles == 1);
 446                        hal_fcxp_set_local_sges(send_req->rsp_sge,
 447                                                rspi->rsp_maxlen,
 448                                                fcxp->rsp_sga_cbfn(fcxp->caller,
 449                                                                   0));
 450                } else {
 451                        bfa_assert(rspi->rsp_maxlen == 0);
 452                        hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
 453                }
 454        }
 455
 456        hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
 457
 458        bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
 459
 460        bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
 461        bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
 462}
 463
 464
 465/**
 466 *  hal_fcxp_api BFA FCXP API
 467 */
 468
 469/**
 470 * Allocate an FCXP instance to send a response or to send a request
 471 * that has a response. Request/response buffers are allocated by caller.
 472 *
 473 * @param[in]   bfa             BFA bfa instance
 474 * @param[in]   nreq_sgles      Number of SG elements required for request
 475 *                              buffer. 0, if fcxp internal buffers are used.
 476 *                              Use bfa_fcxp_get_reqbuf() to get the
 477 *                              internal req buffer.
 478 * @param[in]   req_sgles       SG elements describing request buffer. Will be
 479 *                              copied in by BFA and hence can be freed on
 480 *                              return from this function.
 481 * @param[in]   get_req_sga     function ptr to be called to get a request SG
 482 *                              Address (given the sge index).
 483 * @param[in]   get_req_sglen   function ptr to be called to get a request SG
 484 *                              len (given the sge index).
 485 * @param[in]   get_rsp_sga     function ptr to be called to get a response SG
 486 *                              Address (given the sge index).
 487 * @param[in]   get_rsp_sglen   function ptr to be called to get a response SG
 488 *                              len (given the sge index).
 489 *
 490 * @return FCXP instance. NULL on failure.
 491 */
 492struct bfa_fcxp_s *
 493bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
 494                        int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
 495                        bfa_fcxp_get_sglen_t req_sglen_cbfn,
 496                        bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
 497                        bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
 498{
 499        struct bfa_fcxp_s *fcxp = NULL;
 500        u32        nreq_sgpg, nrsp_sgpg;
 501
 502        bfa_assert(bfa != NULL);
 503
 504        fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
 505        if (fcxp == NULL)
 506                return (NULL);
 507
 508        bfa_trc(bfa, fcxp->fcxp_tag);
 509
 510        fcxp->caller = caller;
 511
 512        if (nreq_sgles == 0) {
 513                fcxp->use_ireqbuf = 1;
 514        } else {
 515                bfa_assert(req_sga_cbfn != NULL);
 516                bfa_assert(req_sglen_cbfn != NULL);
 517
 518                fcxp->use_ireqbuf = 0;
 519                fcxp->req_sga_cbfn = req_sga_cbfn;
 520                fcxp->req_sglen_cbfn = req_sglen_cbfn;
 521
 522                fcxp->nreq_sgles = nreq_sgles;
 523
 524                /*
 525                 * alloc required sgpgs
 526                 */
 527                if (nreq_sgles > BFI_SGE_INLINE) {
 528                        nreq_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
 529
 530                        if (bfa_sgpg_malloc
 531                            (bfa, &fcxp->req_sgpg_q, nreq_sgpg)
 532                            != BFA_STATUS_OK) {
 533                                /* bfa_sgpg_wait(bfa, &fcxp->req_sgpg_wqe,
 534                                nreq_sgpg); */
 535                                /*
 536                                 * TODO
 537                                 */
 538                        }
 539                }
 540        }
 541
 542        if (nrsp_sgles == 0) {
 543                fcxp->use_irspbuf = 1;
 544        } else {
 545                bfa_assert(rsp_sga_cbfn != NULL);
 546                bfa_assert(rsp_sglen_cbfn != NULL);
 547
 548                fcxp->use_irspbuf = 0;
 549                fcxp->rsp_sga_cbfn = rsp_sga_cbfn;
 550                fcxp->rsp_sglen_cbfn = rsp_sglen_cbfn;
 551
 552                fcxp->nrsp_sgles = nrsp_sgles;
 553                /*
 554                 * alloc required sgpgs
 555                 */
 556                if (nrsp_sgles > BFI_SGE_INLINE) {
 557                        nrsp_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
 558
 559                        if (bfa_sgpg_malloc
 560                            (bfa, &fcxp->rsp_sgpg_q, nrsp_sgpg)
 561                            != BFA_STATUS_OK) {
 562                                /* bfa_sgpg_wait(bfa, &fcxp->rsp_sgpg_wqe,
 563                                nrsp_sgpg); */
 564                                /*
 565                                 * TODO
 566                                 */
 567                        }
 568                }
 569        }
 570
 571        return (fcxp);
 572}
 573
 574/**
 575 * Get the internal request buffer pointer
 576 *
 577 * @param[in]   fcxp    BFA fcxp pointer
 578 *
 579 * @return              pointer to the internal request buffer
 580 */
 581void *
 582bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
 583{
 584        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 585        void    *reqbuf;
 586
 587        bfa_assert(fcxp->use_ireqbuf == 1);
 588        reqbuf = ((u8 *)mod->req_pld_list_kva) +
 589                        fcxp->fcxp_tag * mod->req_pld_sz;
 590        return reqbuf;
 591}
 592
 593u32
 594bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
 595{
 596        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 597
 598        return mod->req_pld_sz;
 599}
 600
 601/**
 602 * Get the internal response buffer pointer
 603 *
 604 * @param[in]   fcxp    BFA fcxp pointer
 605 *
 606 * @return              pointer to the internal request buffer
 607 */
 608void *
 609bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
 610{
 611        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 612        void    *rspbuf;
 613
 614        bfa_assert(fcxp->use_irspbuf == 1);
 615
 616        rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
 617                        fcxp->fcxp_tag * mod->rsp_pld_sz;
 618        return rspbuf;
 619}
 620
 621/**
 622 *              Free the BFA FCXP
 623 *
 624 * @param[in]   fcxp                    BFA fcxp pointer
 625 *
 626 * @return              void
 627 */
 628void
 629bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
 630{
 631        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 632
 633        bfa_assert(fcxp != NULL);
 634        bfa_trc(mod->bfa, fcxp->fcxp_tag);
 635        bfa_fcxp_put(fcxp);
 636}
 637
 638/**
 639 * Send a FCXP request
 640 *
 641 * @param[in]   fcxp    BFA fcxp pointer
 642 * @param[in]   rport   BFA rport pointer. Could be left NULL for WKA rports
 643 * @param[in]   vf_id   virtual Fabric ID
 644 * @param[in]   lp_tag  lport tag
 645 * @param[in]   cts     use Continous sequence
 646 * @param[in]   cos     fc Class of Service
 647 * @param[in]   reqlen  request length, does not include FCHS length
 648 * @param[in]   fchs    fc Header Pointer. The header content will be copied
 649 *                      in by BFA.
 650 *
 651 * @param[in]   cbfn    call back function to be called on receiving
 652 *                                                              the response
 653 * @param[in]   cbarg   arg for cbfn
 654 * @param[in]   rsp_timeout
 655 *                      response timeout
 656 *
 657 * @return              bfa_status_t
 658 */
 659void
 660bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
 661                u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
 662                u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
 663                void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
 664{
 665        struct bfa_s                    *bfa  = fcxp->fcxp_mod->bfa;
 666        struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
 667        struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
 668        struct bfi_fcxp_send_req_s      *send_req;
 669
 670        bfa_trc(bfa, fcxp->fcxp_tag);
 671
 672        /**
 673         * setup request/response info
 674         */
 675        reqi->bfa_rport = rport;
 676        reqi->vf_id = vf_id;
 677        reqi->lp_tag = lp_tag;
 678        reqi->class = cos;
 679        rspi->rsp_timeout = rsp_timeout;
 680        reqi->cts = cts;
 681        reqi->fchs = *fchs;
 682        reqi->req_tot_len = reqlen;
 683        rspi->rsp_maxlen = rsp_maxlen;
 684        fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
 685        fcxp->send_cbarg = cbarg;
 686
 687        /**
 688         * If no room in CPE queue, wait for
 689         */
 690        send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
 691        if (!send_req) {
 692                bfa_trc(bfa, fcxp->fcxp_tag);
 693                fcxp->reqq_waiting = BFA_TRUE;
 694                bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
 695                return;
 696        }
 697
 698        bfa_fcxp_queue(fcxp, send_req);
 699}
 700
 701/**
 702 * Abort a BFA FCXP
 703 *
 704 * @param[in]   fcxp    BFA fcxp pointer
 705 *
 706 * @return              void
 707 */
 708bfa_status_t
 709bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
 710{
 711        bfa_assert(0);
 712        return (BFA_STATUS_OK);
 713}
 714
 715void
 716bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
 717                        bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg)
 718{
 719        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 720
 721        bfa_assert(list_empty(&mod->fcxp_free_q));
 722
 723        wqe->alloc_cbfn = alloc_cbfn;
 724        wqe->alloc_cbarg = alloc_cbarg;
 725        list_add_tail(&wqe->qe, &mod->wait_q);
 726}
 727
 728void
 729bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
 730{
 731        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 732
 733        bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
 734        list_del(&wqe->qe);
 735}
 736
 737void
 738bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
 739{
 740        /**
 741         * If waiting for room in request queue, cancel reqq wait
 742         * and free fcxp.
 743         */
 744        if (fcxp->reqq_waiting) {
 745                fcxp->reqq_waiting = BFA_FALSE;
 746                bfa_reqq_wcancel(&fcxp->reqq_wqe);
 747                bfa_fcxp_free(fcxp);
 748                return;
 749        }
 750
 751        fcxp->send_cbfn = bfa_fcxp_null_comp;
 752}
 753
 754
 755
 756/**
 757 *  hal_fcxp_public BFA FCXP public functions
 758 */
 759
 760void
 761bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
 762{
 763        switch (msg->mhdr.msg_id) {
 764        case BFI_FCXP_I2H_SEND_RSP:
 765                hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
 766                break;
 767
 768        default:
 769                bfa_trc(bfa, msg->mhdr.msg_id);
 770                bfa_assert(0);
 771        }
 772}
 773
 774u32
 775bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
 776{
 777        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 778
 779        return mod->rsp_pld_sz;
 780}
 781
 782
 783