linux/drivers/scsi/bfa/bfa_svc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
   4 * Copyright (c) 2014- QLogic Corporation.
   5 * All rights reserved
   6 * www.qlogic.com
   7 *
   8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
   9 */
  10
  11#include "bfad_drv.h"
  12#include "bfad_im.h"
  13#include "bfa_plog.h"
  14#include "bfa_cs.h"
  15#include "bfa_modules.h"
  16
  17BFA_TRC_FILE(HAL, FCXP);
  18
  19/*
  20 * LPS related definitions
  21 */
  22#define BFA_LPS_MIN_LPORTS      (1)
  23#define BFA_LPS_MAX_LPORTS      (256)
  24
  25/*
  26 * Maximum Vports supported per physical port or vf.
  27 */
  28#define BFA_LPS_MAX_VPORTS_SUPP_CB  255
  29#define BFA_LPS_MAX_VPORTS_SUPP_CT  190
  30
  31
  32/*
  33 * FC PORT related definitions
  34 */
  35/*
  36 * The port is considered disabled if corresponding physical port or IOC are
  37 * disabled explicitly
  38 */
  39#define BFA_PORT_IS_DISABLED(bfa) \
  40        ((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
  41        (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
  42
  43/*
  44 * BFA port state machine events
  45 */
  46enum bfa_fcport_sm_event {
  47        BFA_FCPORT_SM_START     = 1,    /*  start port state machine    */
  48        BFA_FCPORT_SM_STOP      = 2,    /*  stop port state machine     */
  49        BFA_FCPORT_SM_ENABLE    = 3,    /*  enable port         */
  50        BFA_FCPORT_SM_DISABLE   = 4,    /*  disable port state machine */
  51        BFA_FCPORT_SM_FWRSP     = 5,    /*  firmware enable/disable rsp */
  52        BFA_FCPORT_SM_LINKUP    = 6,    /*  firmware linkup event       */
  53        BFA_FCPORT_SM_LINKDOWN  = 7,    /*  firmware linkup down        */
  54        BFA_FCPORT_SM_QRESUME   = 8,    /*  CQ space available  */
  55        BFA_FCPORT_SM_HWFAIL    = 9,    /*  IOC h/w failure             */
  56        BFA_FCPORT_SM_DPORTENABLE = 10, /*  enable dport      */
  57        BFA_FCPORT_SM_DPORTDISABLE = 11,/*  disable dport     */
  58        BFA_FCPORT_SM_FAA_MISCONFIG = 12,       /* FAA misconfiguratin */
  59        BFA_FCPORT_SM_DDPORTENABLE  = 13,       /* enable ddport        */
  60        BFA_FCPORT_SM_DDPORTDISABLE = 14,       /* disable ddport       */
  61};
  62
  63/*
  64 * BFA port link notification state machine events
  65 */
  66
  67enum bfa_fcport_ln_sm_event {
  68        BFA_FCPORT_LN_SM_LINKUP         = 1,    /*  linkup event        */
  69        BFA_FCPORT_LN_SM_LINKDOWN       = 2,    /*  linkdown event      */
  70        BFA_FCPORT_LN_SM_NOTIFICATION   = 3     /*  done notification   */
  71};
  72
  73/*
  74 * RPORT related definitions
  75 */
  76#define bfa_rport_offline_cb(__rp) do {                                 \
  77        if ((__rp)->bfa->fcs)                                           \
  78                bfa_cb_rport_offline((__rp)->rport_drv);      \
  79        else {                                                          \
  80                bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,              \
  81                                __bfa_cb_rport_offline, (__rp));      \
  82        }                                                               \
  83} while (0)
  84
  85#define bfa_rport_online_cb(__rp) do {                                  \
  86        if ((__rp)->bfa->fcs)                                           \
  87                bfa_cb_rport_online((__rp)->rport_drv);      \
  88        else {                                                          \
  89                bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,              \
  90                                  __bfa_cb_rport_online, (__rp));      \
  91                }                                                       \
  92} while (0)
  93
  94/*
  95 * forward declarations FCXP related functions
  96 */
  97static void     __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
  98static void     hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
  99                                struct bfi_fcxp_send_rsp_s *fcxp_rsp);
 100static void     hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
 101                                struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
 102static void     bfa_fcxp_qresume(void *cbarg);
 103static void     bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
 104                                struct bfi_fcxp_send_req_s *send_req);
 105
 106/*
 107 * forward declarations for LPS functions
 108 */
 109static void bfa_lps_login_rsp(struct bfa_s *bfa,
 110                                struct bfi_lps_login_rsp_s *rsp);
 111static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);
 112static void bfa_lps_logout_rsp(struct bfa_s *bfa,
 113                                struct bfi_lps_logout_rsp_s *rsp);
 114static void bfa_lps_reqq_resume(void *lps_arg);
 115static void bfa_lps_free(struct bfa_lps_s *lps);
 116static void bfa_lps_send_login(struct bfa_lps_s *lps);
 117static void bfa_lps_send_logout(struct bfa_lps_s *lps);
 118static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);
 119static void bfa_lps_login_comp(struct bfa_lps_s *lps);
 120static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
 121static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
 122
 123/*
 124 * forward declaration for LPS state machine
 125 */
 126static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
 127static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
 128static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
 129                                        event);
 130static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
 131static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,
 132                                        enum bfa_lps_event event);
 133static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
 134static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
 135                                        event);
 136
 137/*
 138 * forward declaration for FC Port functions
 139 */
 140static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
 141static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
 142static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
 143static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
 144static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
 145static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
 146static void bfa_fcport_scn(struct bfa_fcport_s *fcport,
 147                        enum bfa_port_linkstate event, bfa_boolean_t trunk);
 148static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
 149                                enum bfa_port_linkstate event);
 150static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
 151static void bfa_fcport_stats_get_timeout(void *cbarg);
 152static void bfa_fcport_stats_clr_timeout(void *cbarg);
 153static void bfa_trunk_iocdisable(struct bfa_s *bfa);
 154
 155/*
 156 * forward declaration for FC PORT state machine
 157 */
 158static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
 159                                        enum bfa_fcport_sm_event event);
 160static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
 161                                        enum bfa_fcport_sm_event event);
 162static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
 163                                        enum bfa_fcport_sm_event event);
 164static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
 165                                        enum bfa_fcport_sm_event event);
 166static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
 167                                        enum bfa_fcport_sm_event event);
 168static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
 169                                        enum bfa_fcport_sm_event event);
 170static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
 171                                        enum bfa_fcport_sm_event event);
 172static void     bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
 173                                        enum bfa_fcport_sm_event event);
 174static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
 175                                        enum bfa_fcport_sm_event event);
 176static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
 177                                        enum bfa_fcport_sm_event event);
 178static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
 179                                        enum bfa_fcport_sm_event event);
 180static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
 181                                        enum bfa_fcport_sm_event event);
 182static void     bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,
 183                                        enum bfa_fcport_sm_event event);
 184static void     bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
 185                                        enum bfa_fcport_sm_event event);
 186static void     bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
 187                                        enum bfa_fcport_sm_event event);
 188
 189static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
 190                                        enum bfa_fcport_ln_sm_event event);
 191static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
 192                                        enum bfa_fcport_ln_sm_event event);
 193static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
 194                                        enum bfa_fcport_ln_sm_event event);
 195static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
 196                                        enum bfa_fcport_ln_sm_event event);
 197static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
 198                                        enum bfa_fcport_ln_sm_event event);
 199static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
 200                                        enum bfa_fcport_ln_sm_event event);
 201static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
 202                                        enum bfa_fcport_ln_sm_event event);
 203
 204static struct bfa_sm_table_s hal_port_sm_table[] = {
 205        {BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},
 206        {BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},
 207        {BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},
 208        {BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},
 209        {BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},
 210        {BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},
 211        {BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},
 212        {BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},
 213        {BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},
 214        {BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
 215        {BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
 216        {BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
 217        {BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},
 218        {BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT},
 219        {BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},
 220};
 221
 222
 223/*
 224 * forward declaration for RPORT related functions
 225 */
 226static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
 227static void             bfa_rport_free(struct bfa_rport_s *rport);
 228static bfa_boolean_t    bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
 229static bfa_boolean_t    bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
 230static bfa_boolean_t    bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
 231static void             __bfa_cb_rport_online(void *cbarg,
 232                                                bfa_boolean_t complete);
 233static void             __bfa_cb_rport_offline(void *cbarg,
 234                                                bfa_boolean_t complete);
 235
 236/*
 237 * forward declaration for RPORT state machine
 238 */
 239static void     bfa_rport_sm_uninit(struct bfa_rport_s *rp,
 240                                        enum bfa_rport_event event);
 241static void     bfa_rport_sm_created(struct bfa_rport_s *rp,
 242                                        enum bfa_rport_event event);
 243static void     bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
 244                                        enum bfa_rport_event event);
 245static void     bfa_rport_sm_online(struct bfa_rport_s *rp,
 246                                        enum bfa_rport_event event);
 247static void     bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
 248                                        enum bfa_rport_event event);
 249static void     bfa_rport_sm_offline(struct bfa_rport_s *rp,
 250                                        enum bfa_rport_event event);
 251static void     bfa_rport_sm_deleting(struct bfa_rport_s *rp,
 252                                        enum bfa_rport_event event);
 253static void     bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
 254                                        enum bfa_rport_event event);
 255static void     bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
 256                                        enum bfa_rport_event event);
 257static void     bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
 258                                        enum bfa_rport_event event);
 259static void     bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
 260                                        enum bfa_rport_event event);
 261static void     bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
 262                                        enum bfa_rport_event event);
 263static void     bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
 264                                        enum bfa_rport_event event);
 265
 266/*
 267 * PLOG related definitions
 268 */
 269static int
 270plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
 271{
 272        if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
 273                (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
 274                return 1;
 275
 276        if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
 277                (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
 278                return 1;
 279
 280        return 0;
 281}
 282
 283static void
 284bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
 285{
 286        u16 tail;
 287        struct bfa_plog_rec_s *pl_recp;
 288
 289        if (plog->plog_enabled == 0)
 290                return;
 291
 292        if (plkd_validate_logrec(pl_rec)) {
 293                WARN_ON(1);
 294                return;
 295        }
 296
 297        tail = plog->tail;
 298
 299        pl_recp = &(plog->plog_recs[tail]);
 300
 301        memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
 302
 303        pl_recp->tv = ktime_get_real_seconds();
 304        BFA_PL_LOG_REC_INCR(plog->tail);
 305
 306        if (plog->head == plog->tail)
 307                BFA_PL_LOG_REC_INCR(plog->head);
 308}
 309
 310void
 311bfa_plog_init(struct bfa_plog_s *plog)
 312{
 313        memset((char *)plog, 0, sizeof(struct bfa_plog_s));
 314
 315        memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
 316        plog->head = plog->tail = 0;
 317        plog->plog_enabled = 1;
 318}
 319
 320void
 321bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
 322                enum bfa_plog_eid event,
 323                u16 misc, char *log_str)
 324{
 325        struct bfa_plog_rec_s  lp;
 326
 327        if (plog->plog_enabled) {
 328                memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
 329                lp.mid = mid;
 330                lp.eid = event;
 331                lp.log_type = BFA_PL_LOG_TYPE_STRING;
 332                lp.misc = misc;
 333                strlcpy(lp.log_entry.string_log, log_str,
 334                        BFA_PL_STRING_LOG_SZ);
 335                lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
 336                bfa_plog_add(plog, &lp);
 337        }
 338}
 339
 340void
 341bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
 342                enum bfa_plog_eid event,
 343                u16 misc, u32 *intarr, u32 num_ints)
 344{
 345        struct bfa_plog_rec_s  lp;
 346        u32 i;
 347
 348        if (num_ints > BFA_PL_INT_LOG_SZ)
 349                num_ints = BFA_PL_INT_LOG_SZ;
 350
 351        if (plog->plog_enabled) {
 352                memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
 353                lp.mid = mid;
 354                lp.eid = event;
 355                lp.log_type = BFA_PL_LOG_TYPE_INT;
 356                lp.misc = misc;
 357
 358                for (i = 0; i < num_ints; i++)
 359                        lp.log_entry.int_log[i] = intarr[i];
 360
 361                lp.log_num_ints = (u8) num_ints;
 362
 363                bfa_plog_add(plog, &lp);
 364        }
 365}
 366
 367void
 368bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
 369                        enum bfa_plog_eid event,
 370                        u16 misc, struct fchs_s *fchdr)
 371{
 372        u32     *tmp_int = (u32 *) fchdr;
 373        u32     ints[BFA_PL_INT_LOG_SZ];
 374
 375        if (plog->plog_enabled) {
 376                ints[0] = tmp_int[0];
 377                ints[1] = tmp_int[1];
 378                ints[2] = tmp_int[4];
 379
 380                bfa_plog_intarr(plog, mid, event, misc, ints, 3);
 381        }
 382}
 383
 384void
 385bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
 386                      enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
 387                      u32 pld_w0)
 388{
 389        u32     *tmp_int = (u32 *) fchdr;
 390        u32     ints[BFA_PL_INT_LOG_SZ];
 391
 392        if (plog->plog_enabled) {
 393                ints[0] = tmp_int[0];
 394                ints[1] = tmp_int[1];
 395                ints[2] = tmp_int[4];
 396                ints[3] = pld_w0;
 397
 398                bfa_plog_intarr(plog, mid, event, misc, ints, 4);
 399        }
 400}
 401
 402
 403/*
 404 *  fcxp_pvt BFA FCXP private functions
 405 */
 406
 407static void
 408claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
 409{
 410        u16     i;
 411        struct bfa_fcxp_s *fcxp;
 412
 413        fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
 414        memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
 415
 416        INIT_LIST_HEAD(&mod->fcxp_req_free_q);
 417        INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);
 418        INIT_LIST_HEAD(&mod->fcxp_active_q);
 419        INIT_LIST_HEAD(&mod->fcxp_req_unused_q);
 420        INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);
 421
 422        mod->fcxp_list = fcxp;
 423
 424        for (i = 0; i < mod->num_fcxps; i++) {
 425                fcxp->fcxp_mod = mod;
 426                fcxp->fcxp_tag = i;
 427
 428                if (i < (mod->num_fcxps / 2)) {
 429                        list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
 430                        fcxp->req_rsp = BFA_TRUE;
 431                } else {
 432                        list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
 433                        fcxp->req_rsp = BFA_FALSE;
 434                }
 435
 436                bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
 437                fcxp->reqq_waiting = BFA_FALSE;
 438
 439                fcxp = fcxp + 1;
 440        }
 441
 442        bfa_mem_kva_curp(mod) = (void *)fcxp;
 443}
 444
 445void
 446bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
 447                struct bfa_s *bfa)
 448{
 449        struct bfa_fcxp_mod_s *fcxp_mod = BFA_FCXP_MOD(bfa);
 450        struct bfa_mem_kva_s *fcxp_kva = BFA_MEM_FCXP_KVA(bfa);
 451        struct bfa_mem_dma_s *seg_ptr;
 452        u16     nsegs, idx, per_seg_fcxp;
 453        u16     num_fcxps = cfg->fwcfg.num_fcxp_reqs;
 454        u32     per_fcxp_sz;
 455
 456        if (num_fcxps == 0)
 457                return;
 458
 459        if (cfg->drvcfg.min_cfg)
 460                per_fcxp_sz = 2 * BFA_FCXP_MAX_IBUF_SZ;
 461        else
 462                per_fcxp_sz = BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ;
 463
 464        /* dma memory */
 465        nsegs = BFI_MEM_DMA_NSEGS(num_fcxps, per_fcxp_sz);
 466        per_seg_fcxp = BFI_MEM_NREQS_SEG(per_fcxp_sz);
 467
 468        bfa_mem_dma_seg_iter(fcxp_mod, seg_ptr, nsegs, idx) {
 469                if (num_fcxps >= per_seg_fcxp) {
 470                        num_fcxps -= per_seg_fcxp;
 471                        bfa_mem_dma_setup(minfo, seg_ptr,
 472                                per_seg_fcxp * per_fcxp_sz);
 473                } else
 474                        bfa_mem_dma_setup(minfo, seg_ptr,
 475                                num_fcxps * per_fcxp_sz);
 476        }
 477
 478        /* kva memory */
 479        bfa_mem_kva_setup(minfo, fcxp_kva,
 480                cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));
 481}
 482
 483void
 484bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 485                struct bfa_pcidev_s *pcidev)
 486{
 487        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 488
 489        mod->bfa = bfa;
 490        mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
 491
 492        /*
 493         * Initialize FCXP request and response payload sizes.
 494         */
 495        mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
 496        if (!cfg->drvcfg.min_cfg)
 497                mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
 498
 499        INIT_LIST_HEAD(&mod->req_wait_q);
 500        INIT_LIST_HEAD(&mod->rsp_wait_q);
 501
 502        claim_fcxps_mem(mod);
 503}
 504
 505void
 506bfa_fcxp_iocdisable(struct bfa_s *bfa)
 507{
 508        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 509        struct bfa_fcxp_s *fcxp;
 510        struct list_head              *qe, *qen;
 511
 512        /* Enqueue unused fcxp resources to free_q */
 513        list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q);
 514        list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q);
 515
 516        list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
 517                fcxp = (struct bfa_fcxp_s *) qe;
 518                if (fcxp->caller == NULL) {
 519                        fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
 520                                        BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
 521                        bfa_fcxp_free(fcxp);
 522                } else {
 523                        fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
 524                        bfa_cb_queue(bfa, &fcxp->hcb_qe,
 525                                     __bfa_fcxp_send_cbfn, fcxp);
 526                }
 527        }
 528}
 529
 530static struct bfa_fcxp_s *
 531bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)
 532{
 533        struct bfa_fcxp_s *fcxp;
 534
 535        if (req)
 536                bfa_q_deq(&fm->fcxp_req_free_q, &fcxp);
 537        else
 538                bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);
 539
 540        if (fcxp)
 541                list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
 542
 543        return fcxp;
 544}
 545
 546static void
 547bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
 548               struct bfa_s *bfa,
 549               u8 *use_ibuf,
 550               u32 *nr_sgles,
 551               bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
 552               bfa_fcxp_get_sglen_t *r_sglen_cbfn,
 553               struct list_head *r_sgpg_q,
 554               int n_sgles,
 555               bfa_fcxp_get_sgaddr_t sga_cbfn,
 556               bfa_fcxp_get_sglen_t sglen_cbfn)
 557{
 558
 559        WARN_ON(bfa == NULL);
 560
 561        bfa_trc(bfa, fcxp->fcxp_tag);
 562
 563        if (n_sgles == 0) {
 564                *use_ibuf = 1;
 565        } else {
 566                WARN_ON(*sga_cbfn == NULL);
 567                WARN_ON(*sglen_cbfn == NULL);
 568
 569                *use_ibuf = 0;
 570                *r_sga_cbfn = sga_cbfn;
 571                *r_sglen_cbfn = sglen_cbfn;
 572
 573                *nr_sgles = n_sgles;
 574
 575                /*
 576                 * alloc required sgpgs
 577                 */
 578                if (n_sgles > BFI_SGE_INLINE)
 579                        WARN_ON(1);
 580        }
 581
 582}
 583
 584static void
 585bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
 586               void *caller, struct bfa_s *bfa, int nreq_sgles,
 587               int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
 588               bfa_fcxp_get_sglen_t req_sglen_cbfn,
 589               bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
 590               bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
 591{
 592
 593        WARN_ON(bfa == NULL);
 594
 595        bfa_trc(bfa, fcxp->fcxp_tag);
 596
 597        fcxp->caller = caller;
 598
 599        bfa_fcxp_init_reqrsp(fcxp, bfa,
 600                &fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
 601                &fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
 602                nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
 603
 604        bfa_fcxp_init_reqrsp(fcxp, bfa,
 605                &fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
 606                &fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
 607                nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
 608
 609}
 610
 611static void
 612bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
 613{
 614        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 615        struct bfa_fcxp_wqe_s *wqe;
 616
 617        if (fcxp->req_rsp)
 618                bfa_q_deq(&mod->req_wait_q, &wqe);
 619        else
 620                bfa_q_deq(&mod->rsp_wait_q, &wqe);
 621
 622        if (wqe) {
 623                bfa_trc(mod->bfa, fcxp->fcxp_tag);
 624
 625                bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
 626                        wqe->nrsp_sgles, wqe->req_sga_cbfn,
 627                        wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
 628                        wqe->rsp_sglen_cbfn);
 629
 630                wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
 631                return;
 632        }
 633
 634        WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
 635        list_del(&fcxp->qe);
 636
 637        if (fcxp->req_rsp)
 638                list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
 639        else
 640                list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
 641}
 642
 643static void
 644bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
 645                   bfa_status_t req_status, u32 rsp_len,
 646                   u32 resid_len, struct fchs_s *rsp_fchs)
 647{
 648        /* discarded fcxp completion */
 649}
 650
 651static void
 652__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
 653{
 654        struct bfa_fcxp_s *fcxp = cbarg;
 655
 656        if (complete) {
 657                fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
 658                                fcxp->rsp_status, fcxp->rsp_len,
 659                                fcxp->residue_len, &fcxp->rsp_fchs);
 660        } else {
 661                bfa_fcxp_free(fcxp);
 662        }
 663}
 664
 665static void
 666hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
 667{
 668        struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
 669        struct bfa_fcxp_s       *fcxp;
 670        u16             fcxp_tag = be16_to_cpu(fcxp_rsp->fcxp_tag);
 671
 672        bfa_trc(bfa, fcxp_tag);
 673
 674        fcxp_rsp->rsp_len = be32_to_cpu(fcxp_rsp->rsp_len);
 675
 676        /*
 677         * @todo f/w should not set residue to non-0 when everything
 678         *       is received.
 679         */
 680        if (fcxp_rsp->req_status == BFA_STATUS_OK)
 681                fcxp_rsp->residue_len = 0;
 682        else
 683                fcxp_rsp->residue_len = be32_to_cpu(fcxp_rsp->residue_len);
 684
 685        fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
 686
 687        WARN_ON(fcxp->send_cbfn == NULL);
 688
 689        hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
 690
 691        if (fcxp->send_cbfn != NULL) {
 692                bfa_trc(mod->bfa, (NULL == fcxp->caller));
 693                if (fcxp->caller == NULL) {
 694                        fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
 695                                        fcxp_rsp->req_status, fcxp_rsp->rsp_len,
 696                                        fcxp_rsp->residue_len, &fcxp_rsp->fchs);
 697                        /*
 698                         * fcxp automatically freed on return from the callback
 699                         */
 700                        bfa_fcxp_free(fcxp);
 701                } else {
 702                        fcxp->rsp_status = fcxp_rsp->req_status;
 703                        fcxp->rsp_len = fcxp_rsp->rsp_len;
 704                        fcxp->residue_len = fcxp_rsp->residue_len;
 705                        fcxp->rsp_fchs = fcxp_rsp->fchs;
 706
 707                        bfa_cb_queue(bfa, &fcxp->hcb_qe,
 708                                        __bfa_fcxp_send_cbfn, fcxp);
 709                }
 710        } else {
 711                bfa_trc(bfa, (NULL == fcxp->send_cbfn));
 712        }
 713}
 714
 715static void
 716hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
 717                 struct fchs_s *fchs)
 718{
 719        /*
 720         * TODO: TX ox_id
 721         */
 722        if (reqlen > 0) {
 723                if (fcxp->use_ireqbuf) {
 724                        u32     pld_w0 =
 725                                *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
 726
 727                        bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
 728                                        BFA_PL_EID_TX,
 729                                        reqlen + sizeof(struct fchs_s), fchs,
 730                                        pld_w0);
 731                } else {
 732                        bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
 733                                        BFA_PL_EID_TX,
 734                                        reqlen + sizeof(struct fchs_s),
 735                                        fchs);
 736                }
 737        } else {
 738                bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
 739                               reqlen + sizeof(struct fchs_s), fchs);
 740        }
 741}
 742
 743static void
 744hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
 745                 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
 746{
 747        if (fcxp_rsp->rsp_len > 0) {
 748                if (fcxp->use_irspbuf) {
 749                        u32     pld_w0 =
 750                                *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
 751
 752                        bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
 753                                              BFA_PL_EID_RX,
 754                                              (u16) fcxp_rsp->rsp_len,
 755                                              &fcxp_rsp->fchs, pld_w0);
 756                } else {
 757                        bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
 758                                       BFA_PL_EID_RX,
 759                                       (u16) fcxp_rsp->rsp_len,
 760                                       &fcxp_rsp->fchs);
 761                }
 762        } else {
 763                bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
 764                               (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
 765        }
 766}
 767
 768/*
 769 * Handler to resume sending fcxp when space in available in cpe queue.
 770 */
 771static void
 772bfa_fcxp_qresume(void *cbarg)
 773{
 774        struct bfa_fcxp_s               *fcxp = cbarg;
 775        struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
 776        struct bfi_fcxp_send_req_s      *send_req;
 777
 778        fcxp->reqq_waiting = BFA_FALSE;
 779        send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
 780        bfa_fcxp_queue(fcxp, send_req);
 781}
 782
 783/*
 784 * Queue fcxp send request to foimrware.
 785 */
 786static void
 787bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
 788{
 789        struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
 790        struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
 791        struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
 792        struct bfa_rport_s              *rport = reqi->bfa_rport;
 793
 794        bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
 795                    bfa_fn_lpu(bfa));
 796
 797        send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);
 798        if (rport) {
 799                send_req->rport_fw_hndl = rport->fw_handle;
 800                send_req->max_frmsz = cpu_to_be16(rport->rport_info.max_frmsz);
 801                if (send_req->max_frmsz == 0)
 802                        send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
 803        } else {
 804                send_req->rport_fw_hndl = 0;
 805                send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
 806        }
 807
 808        send_req->vf_id = cpu_to_be16(reqi->vf_id);
 809        send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);
 810        send_req->class = reqi->class;
 811        send_req->rsp_timeout = rspi->rsp_timeout;
 812        send_req->cts = reqi->cts;
 813        send_req->fchs = reqi->fchs;
 814
 815        send_req->req_len = cpu_to_be32(reqi->req_tot_len);
 816        send_req->rsp_maxlen = cpu_to_be32(rspi->rsp_maxlen);
 817
 818        /*
 819         * setup req sgles
 820         */
 821        if (fcxp->use_ireqbuf == 1) {
 822                bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
 823                                        BFA_FCXP_REQ_PLD_PA(fcxp));
 824        } else {
 825                if (fcxp->nreq_sgles > 0) {
 826                        WARN_ON(fcxp->nreq_sgles != 1);
 827                        bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
 828                                fcxp->req_sga_cbfn(fcxp->caller, 0));
 829                } else {
 830                        WARN_ON(reqi->req_tot_len != 0);
 831                        bfa_alen_set(&send_req->rsp_alen, 0, 0);
 832                }
 833        }
 834
 835        /*
 836         * setup rsp sgles
 837         */
 838        if (fcxp->use_irspbuf == 1) {
 839                WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
 840
 841                bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
 842                                        BFA_FCXP_RSP_PLD_PA(fcxp));
 843        } else {
 844                if (fcxp->nrsp_sgles > 0) {
 845                        WARN_ON(fcxp->nrsp_sgles != 1);
 846                        bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
 847                                fcxp->rsp_sga_cbfn(fcxp->caller, 0));
 848
 849                } else {
 850                        WARN_ON(rspi->rsp_maxlen != 0);
 851                        bfa_alen_set(&send_req->rsp_alen, 0, 0);
 852                }
 853        }
 854
 855        hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
 856
 857        bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);
 858
 859        bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
 860        bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
 861}
 862
 863/*
 864 * Allocate an FCXP instance to send a response or to send a request
 865 * that has a response. Request/response buffers are allocated by caller.
 866 *
 867 * @param[in]   bfa             BFA bfa instance
 868 * @param[in]   nreq_sgles      Number of SG elements required for request
 869 *                              buffer. 0, if fcxp internal buffers are used.
 870 *                              Use bfa_fcxp_get_reqbuf() to get the
 871 *                              internal req buffer.
 872 * @param[in]   req_sgles       SG elements describing request buffer. Will be
 873 *                              copied in by BFA and hence can be freed on
 874 *                              return from this function.
 875 * @param[in]   get_req_sga     function ptr to be called to get a request SG
 876 *                              Address (given the sge index).
 877 * @param[in]   get_req_sglen   function ptr to be called to get a request SG
 878 *                              len (given the sge index).
 879 * @param[in]   get_rsp_sga     function ptr to be called to get a response SG
 880 *                              Address (given the sge index).
 881 * @param[in]   get_rsp_sglen   function ptr to be called to get a response SG
 882 *                              len (given the sge index).
 883 * @param[in]   req             Allocated FCXP is used to send req or rsp?
 884 *                              request - BFA_TRUE, response - BFA_FALSE
 885 *
 886 * @return FCXP instance. NULL on failure.
 887 */
 888struct bfa_fcxp_s *
 889bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
 890                int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
 891                bfa_fcxp_get_sglen_t req_sglen_cbfn,
 892                bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
 893                bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
 894{
 895        struct bfa_fcxp_s *fcxp = NULL;
 896
 897        WARN_ON(bfa == NULL);
 898
 899        fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);
 900        if (fcxp == NULL)
 901                return NULL;
 902
 903        bfa_trc(bfa, fcxp->fcxp_tag);
 904
 905        bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
 906                        req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
 907
 908        return fcxp;
 909}
 910
 911/*
 912 * Get the internal request buffer pointer
 913 *
 914 * @param[in]   fcxp    BFA fcxp pointer
 915 *
 916 * @return              pointer to the internal request buffer
 917 */
 918void *
 919bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
 920{
 921        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 922        void    *reqbuf;
 923
 924        WARN_ON(fcxp->use_ireqbuf != 1);
 925        reqbuf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
 926                                mod->req_pld_sz + mod->rsp_pld_sz);
 927        return reqbuf;
 928}
 929
 930u32
 931bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
 932{
 933        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 934
 935        return mod->req_pld_sz;
 936}
 937
 938/*
 939 * Get the internal response buffer pointer
 940 *
 941 * @param[in]   fcxp    BFA fcxp pointer
 942 *
 943 * @return              pointer to the internal request buffer
 944 */
 945void *
 946bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
 947{
 948        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 949        void    *fcxp_buf;
 950
 951        WARN_ON(fcxp->use_irspbuf != 1);
 952
 953        fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
 954                                mod->req_pld_sz + mod->rsp_pld_sz);
 955
 956        /* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
 957        return ((u8 *) fcxp_buf) + mod->req_pld_sz;
 958}
 959
 960/*
 961 * Free the BFA FCXP
 962 *
 963 * @param[in]   fcxp                    BFA fcxp pointer
 964 *
 965 * @return              void
 966 */
 967void
 968bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
 969{
 970        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 971
 972        WARN_ON(fcxp == NULL);
 973        bfa_trc(mod->bfa, fcxp->fcxp_tag);
 974        bfa_fcxp_put(fcxp);
 975}
 976
 977/*
 978 * Send a FCXP request
 979 *
 980 * @param[in]   fcxp    BFA fcxp pointer
 981 * @param[in]   rport   BFA rport pointer. Could be left NULL for WKA rports
 982 * @param[in]   vf_id   virtual Fabric ID
 983 * @param[in]   lp_tag  lport tag
 984 * @param[in]   cts     use Continuous sequence
 985 * @param[in]   cos     fc Class of Service
 986 * @param[in]   reqlen  request length, does not include FCHS length
 987 * @param[in]   fchs    fc Header Pointer. The header content will be copied
 988 *                      in by BFA.
 989 *
 990 * @param[in]   cbfn    call back function to be called on receiving
 991 *                                                              the response
 992 * @param[in]   cbarg   arg for cbfn
 993 * @param[in]   rsp_timeout
 994 *                      response timeout
 995 *
 996 * @return              bfa_status_t
 997 */
 998void
 999bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
1000              u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
1001              u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
1002              void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
1003{
1004        struct bfa_s                    *bfa  = fcxp->fcxp_mod->bfa;
1005        struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
1006        struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
1007        struct bfi_fcxp_send_req_s      *send_req;
1008
1009        bfa_trc(bfa, fcxp->fcxp_tag);
1010
1011        /*
1012         * setup request/response info
1013         */
1014        reqi->bfa_rport = rport;
1015        reqi->vf_id = vf_id;
1016        reqi->lp_tag = lp_tag;
1017        reqi->class = cos;
1018        rspi->rsp_timeout = rsp_timeout;
1019        reqi->cts = cts;
1020        reqi->fchs = *fchs;
1021        reqi->req_tot_len = reqlen;
1022        rspi->rsp_maxlen = rsp_maxlen;
1023        fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
1024        fcxp->send_cbarg = cbarg;
1025
1026        /*
1027         * If no room in CPE queue, wait for space in request queue
1028         */
1029        send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
1030        if (!send_req) {
1031                bfa_trc(bfa, fcxp->fcxp_tag);
1032                fcxp->reqq_waiting = BFA_TRUE;
1033                bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
1034                return;
1035        }
1036
1037        bfa_fcxp_queue(fcxp, send_req);
1038}
1039
1040/*
1041 * Abort a BFA FCXP
1042 *
1043 * @param[in]   fcxp    BFA fcxp pointer
1044 *
1045 * @return              void
1046 */
1047bfa_status_t
1048bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
1049{
1050        bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
1051        WARN_ON(1);
1052        return BFA_STATUS_OK;
1053}
1054
1055void
1056bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1057               bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
1058               void *caller, int nreq_sgles,
1059               int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
1060               bfa_fcxp_get_sglen_t req_sglen_cbfn,
1061               bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
1062               bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
1063{
1064        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1065
1066        if (req)
1067                WARN_ON(!list_empty(&mod->fcxp_req_free_q));
1068        else
1069                WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));
1070
1071        wqe->alloc_cbfn = alloc_cbfn;
1072        wqe->alloc_cbarg = alloc_cbarg;
1073        wqe->caller = caller;
1074        wqe->bfa = bfa;
1075        wqe->nreq_sgles = nreq_sgles;
1076        wqe->nrsp_sgles = nrsp_sgles;
1077        wqe->req_sga_cbfn = req_sga_cbfn;
1078        wqe->req_sglen_cbfn = req_sglen_cbfn;
1079        wqe->rsp_sga_cbfn = rsp_sga_cbfn;
1080        wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
1081
1082        if (req)
1083                list_add_tail(&wqe->qe, &mod->req_wait_q);
1084        else
1085                list_add_tail(&wqe->qe, &mod->rsp_wait_q);
1086}
1087
1088void
1089bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
1090{
1091        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1092
1093        WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||
1094                !bfa_q_is_on_q(&mod->rsp_wait_q, wqe));
1095        list_del(&wqe->qe);
1096}
1097
1098void
1099bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
1100{
1101        /*
1102         * If waiting for room in request queue, cancel reqq wait
1103         * and free fcxp.
1104         */
1105        if (fcxp->reqq_waiting) {
1106                fcxp->reqq_waiting = BFA_FALSE;
1107                bfa_reqq_wcancel(&fcxp->reqq_wqe);
1108                bfa_fcxp_free(fcxp);
1109                return;
1110        }
1111
1112        fcxp->send_cbfn = bfa_fcxp_null_comp;
1113}
1114
1115void
1116bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
1117{
1118        switch (msg->mhdr.msg_id) {
1119        case BFI_FCXP_I2H_SEND_RSP:
1120                hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
1121                break;
1122
1123        default:
1124                bfa_trc(bfa, msg->mhdr.msg_id);
1125                WARN_ON(1);
1126        }
1127}
1128
1129u32
1130bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
1131{
1132        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1133
1134        return mod->rsp_pld_sz;
1135}
1136
1137void
1138bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
1139{
1140        struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
1141        struct list_head        *qe;
1142        int     i;
1143
1144        for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
1145                if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {
1146                        bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);
1147                        list_add_tail(qe, &mod->fcxp_req_unused_q);
1148                } else {
1149                        bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);
1150                        list_add_tail(qe, &mod->fcxp_rsp_unused_q);
1151                }
1152        }
1153}
1154
1155/*
1156 *  BFA LPS state machine functions
1157 */
1158
1159/*
1160 * Init state -- no login
1161 */
1162static void
1163bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
1164{
1165        bfa_trc(lps->bfa, lps->bfa_tag);
1166        bfa_trc(lps->bfa, event);
1167
1168        switch (event) {
1169        case BFA_LPS_SM_LOGIN:
1170                if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1171                        bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
1172                        bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1173                } else {
1174                        bfa_sm_set_state(lps, bfa_lps_sm_login);
1175                        bfa_lps_send_login(lps);
1176                }
1177
1178                if (lps->fdisc)
1179                        bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1180                                BFA_PL_EID_LOGIN, 0, "FDISC Request");
1181                else
1182                        bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1183                                BFA_PL_EID_LOGIN, 0, "FLOGI Request");
1184                break;
1185
1186        case BFA_LPS_SM_LOGOUT:
1187                bfa_lps_logout_comp(lps);
1188                break;
1189
1190        case BFA_LPS_SM_DELETE:
1191                bfa_lps_free(lps);
1192                break;
1193
1194        case BFA_LPS_SM_RX_CVL:
1195        case BFA_LPS_SM_OFFLINE:
1196                break;
1197
1198        case BFA_LPS_SM_FWRSP:
1199                /*
1200                 * Could happen when fabric detects loopback and discards
1201                 * the lps request. Fw will eventually sent out the timeout
1202                 * Just ignore
1203                 */
1204                break;
1205        case BFA_LPS_SM_SET_N2N_PID:
1206                /*
1207                 * When topology is set to loop, bfa_lps_set_n2n_pid() sends
1208                 * this event. Ignore this event.
1209                 */
1210                break;
1211
1212        default:
1213                bfa_sm_fault(lps->bfa, event);
1214        }
1215}
1216
1217/*
1218 * login is in progress -- awaiting response from firmware
1219 */
1220static void
1221bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
1222{
1223        bfa_trc(lps->bfa, lps->bfa_tag);
1224        bfa_trc(lps->bfa, event);
1225
1226        switch (event) {
1227        case BFA_LPS_SM_FWRSP:
1228                if (lps->status == BFA_STATUS_OK) {
1229                        bfa_sm_set_state(lps, bfa_lps_sm_online);
1230                        if (lps->fdisc)
1231                                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1232                                        BFA_PL_EID_LOGIN, 0, "FDISC Accept");
1233                        else
1234                                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1235                                        BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
1236                        /* If N2N, send the assigned PID to FW */
1237                        bfa_trc(lps->bfa, lps->fport);
1238                        bfa_trc(lps->bfa, lps->lp_pid);
1239
1240                        if (!lps->fport && lps->lp_pid)
1241                                bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1242                } else {
1243                        bfa_sm_set_state(lps, bfa_lps_sm_init);
1244                        if (lps->fdisc)
1245                                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1246                                        BFA_PL_EID_LOGIN, 0,
1247                                        "FDISC Fail (RJT or timeout)");
1248                        else
1249                                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1250                                        BFA_PL_EID_LOGIN, 0,
1251                                        "FLOGI Fail (RJT or timeout)");
1252                }
1253                bfa_lps_login_comp(lps);
1254                break;
1255
1256        case BFA_LPS_SM_OFFLINE:
1257        case BFA_LPS_SM_DELETE:
1258                bfa_sm_set_state(lps, bfa_lps_sm_init);
1259                break;
1260
1261        case BFA_LPS_SM_SET_N2N_PID:
1262                bfa_trc(lps->bfa, lps->fport);
1263                bfa_trc(lps->bfa, lps->lp_pid);
1264                break;
1265
1266        default:
1267                bfa_sm_fault(lps->bfa, event);
1268        }
1269}
1270
1271/*
1272 * login pending - awaiting space in request queue
1273 */
1274static void
1275bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1276{
1277        bfa_trc(lps->bfa, lps->bfa_tag);
1278        bfa_trc(lps->bfa, event);
1279
1280        switch (event) {
1281        case BFA_LPS_SM_RESUME:
1282                bfa_sm_set_state(lps, bfa_lps_sm_login);
1283                bfa_lps_send_login(lps);
1284                break;
1285
1286        case BFA_LPS_SM_OFFLINE:
1287        case BFA_LPS_SM_DELETE:
1288                bfa_sm_set_state(lps, bfa_lps_sm_init);
1289                bfa_reqq_wcancel(&lps->wqe);
1290                break;
1291
1292        case BFA_LPS_SM_RX_CVL:
1293                /*
1294                 * Login was not even sent out; so when getting out
1295                 * of this state, it will appear like a login retry
1296                 * after Clear virtual link
1297                 */
1298                break;
1299
1300        default:
1301                bfa_sm_fault(lps->bfa, event);
1302        }
1303}
1304
1305/*
1306 * login complete
1307 */
1308static void
1309bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
1310{
1311        bfa_trc(lps->bfa, lps->bfa_tag);
1312        bfa_trc(lps->bfa, event);
1313
1314        switch (event) {
1315        case BFA_LPS_SM_LOGOUT:
1316                if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1317                        bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1318                        bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1319                } else {
1320                        bfa_sm_set_state(lps, bfa_lps_sm_logout);
1321                        bfa_lps_send_logout(lps);
1322                }
1323                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1324                        BFA_PL_EID_LOGO, 0, "Logout");
1325                break;
1326
1327        case BFA_LPS_SM_RX_CVL:
1328                bfa_sm_set_state(lps, bfa_lps_sm_init);
1329
1330                /* Let the vport module know about this event */
1331                bfa_lps_cvl_event(lps);
1332                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1333                        BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1334                break;
1335
1336        case BFA_LPS_SM_SET_N2N_PID:
1337                if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1338                        bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
1339                        bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1340                } else
1341                        bfa_lps_send_set_n2n_pid(lps);
1342                break;
1343
1344        case BFA_LPS_SM_OFFLINE:
1345        case BFA_LPS_SM_DELETE:
1346                bfa_sm_set_state(lps, bfa_lps_sm_init);
1347                break;
1348
1349        default:
1350                bfa_sm_fault(lps->bfa, event);
1351        }
1352}
1353
1354/*
1355 * login complete
1356 */
1357static void
1358bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1359{
1360        bfa_trc(lps->bfa, lps->bfa_tag);
1361        bfa_trc(lps->bfa, event);
1362
1363        switch (event) {
1364        case BFA_LPS_SM_RESUME:
1365                bfa_sm_set_state(lps, bfa_lps_sm_online);
1366                bfa_lps_send_set_n2n_pid(lps);
1367                break;
1368
1369        case BFA_LPS_SM_LOGOUT:
1370                bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1371                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1372                        BFA_PL_EID_LOGO, 0, "Logout");
1373                break;
1374
1375        case BFA_LPS_SM_RX_CVL:
1376                bfa_sm_set_state(lps, bfa_lps_sm_init);
1377                bfa_reqq_wcancel(&lps->wqe);
1378
1379                /* Let the vport module know about this event */
1380                bfa_lps_cvl_event(lps);
1381                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1382                        BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1383                break;
1384
1385        case BFA_LPS_SM_OFFLINE:
1386        case BFA_LPS_SM_DELETE:
1387                bfa_sm_set_state(lps, bfa_lps_sm_init);
1388                bfa_reqq_wcancel(&lps->wqe);
1389                break;
1390
1391        default:
1392                bfa_sm_fault(lps->bfa, event);
1393        }
1394}
1395
1396/*
1397 * logout in progress - awaiting firmware response
1398 */
1399static void
1400bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1401{
1402        bfa_trc(lps->bfa, lps->bfa_tag);
1403        bfa_trc(lps->bfa, event);
1404
1405        switch (event) {
1406        case BFA_LPS_SM_FWRSP:
1407        case BFA_LPS_SM_OFFLINE:
1408                bfa_sm_set_state(lps, bfa_lps_sm_init);
1409                bfa_lps_logout_comp(lps);
1410                break;
1411
1412        case BFA_LPS_SM_DELETE:
1413                bfa_sm_set_state(lps, bfa_lps_sm_init);
1414                break;
1415
1416        default:
1417                bfa_sm_fault(lps->bfa, event);
1418        }
1419}
1420
1421/*
1422 * logout pending -- awaiting space in request queue
1423 */
1424static void
1425bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1426{
1427        bfa_trc(lps->bfa, lps->bfa_tag);
1428        bfa_trc(lps->bfa, event);
1429
1430        switch (event) {
1431        case BFA_LPS_SM_RESUME:
1432                bfa_sm_set_state(lps, bfa_lps_sm_logout);
1433                bfa_lps_send_logout(lps);
1434                break;
1435
1436        case BFA_LPS_SM_OFFLINE:
1437        case BFA_LPS_SM_DELETE:
1438                bfa_sm_set_state(lps, bfa_lps_sm_init);
1439                bfa_reqq_wcancel(&lps->wqe);
1440                break;
1441
1442        default:
1443                bfa_sm_fault(lps->bfa, event);
1444        }
1445}
1446
1447
1448
1449/*
1450 *  lps_pvt BFA LPS private functions
1451 */
1452
1453/*
1454 * return memory requirement
1455 */
1456void
1457bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
1458                struct bfa_s *bfa)
1459{
1460        struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa);
1461
1462        if (cfg->drvcfg.min_cfg)
1463                bfa_mem_kva_setup(minfo, lps_kva,
1464                        sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);
1465        else
1466                bfa_mem_kva_setup(minfo, lps_kva,
1467                        sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);
1468}
1469
1470/*
1471 * bfa module attach at initialization time
1472 */
1473void
1474bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1475        struct bfa_pcidev_s *pcidev)
1476{
1477        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1478        struct bfa_lps_s        *lps;
1479        int                     i;
1480
1481        mod->num_lps = BFA_LPS_MAX_LPORTS;
1482        if (cfg->drvcfg.min_cfg)
1483                mod->num_lps = BFA_LPS_MIN_LPORTS;
1484        else
1485                mod->num_lps = BFA_LPS_MAX_LPORTS;
1486        mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod);
1487
1488        bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);
1489
1490        INIT_LIST_HEAD(&mod->lps_free_q);
1491        INIT_LIST_HEAD(&mod->lps_active_q);
1492        INIT_LIST_HEAD(&mod->lps_login_q);
1493
1494        for (i = 0; i < mod->num_lps; i++, lps++) {
1495                lps->bfa        = bfa;
1496                lps->bfa_tag    = (u8) i;
1497                lps->reqq       = BFA_REQQ_LPS;
1498                bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
1499                list_add_tail(&lps->qe, &mod->lps_free_q);
1500        }
1501}
1502
1503/*
1504 * IOC in disabled state -- consider all lps offline
1505 */
1506void
1507bfa_lps_iocdisable(struct bfa_s *bfa)
1508{
1509        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1510        struct bfa_lps_s        *lps;
1511        struct list_head                *qe, *qen;
1512
1513        list_for_each_safe(qe, qen, &mod->lps_active_q) {
1514                lps = (struct bfa_lps_s *) qe;
1515                bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1516        }
1517        list_for_each_safe(qe, qen, &mod->lps_login_q) {
1518                lps = (struct bfa_lps_s *) qe;
1519                bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1520        }
1521        list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);
1522}
1523
1524/*
1525 * Firmware login response
1526 */
1527static void
1528bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
1529{
1530        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1531        struct bfa_lps_s        *lps;
1532
1533        WARN_ON(rsp->bfa_tag >= mod->num_lps);
1534        lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1535
1536        lps->status = rsp->status;
1537        switch (rsp->status) {
1538        case BFA_STATUS_OK:
1539                lps->fw_tag     = rsp->fw_tag;
1540                lps->fport      = rsp->f_port;
1541                if (lps->fport)
1542                        lps->lp_pid = rsp->lp_pid;
1543                lps->npiv_en    = rsp->npiv_en;
1544                lps->pr_bbcred  = be16_to_cpu(rsp->bb_credit);
1545                lps->pr_pwwn    = rsp->port_name;
1546                lps->pr_nwwn    = rsp->node_name;
1547                lps->auth_req   = rsp->auth_req;
1548                lps->lp_mac     = rsp->lp_mac;
1549                lps->brcd_switch = rsp->brcd_switch;
1550                lps->fcf_mac    = rsp->fcf_mac;
1551
1552                break;
1553
1554        case BFA_STATUS_FABRIC_RJT:
1555                lps->lsrjt_rsn = rsp->lsrjt_rsn;
1556                lps->lsrjt_expl = rsp->lsrjt_expl;
1557
1558                break;
1559
1560        case BFA_STATUS_EPROTOCOL:
1561                lps->ext_status = rsp->ext_status;
1562
1563                break;
1564
1565        case BFA_STATUS_VPORT_MAX:
1566                if (rsp->ext_status)
1567                        bfa_lps_no_res(lps, rsp->ext_status);
1568                break;
1569
1570        default:
1571                /* Nothing to do with other status */
1572                break;
1573        }
1574
1575        list_del(&lps->qe);
1576        list_add_tail(&lps->qe, &mod->lps_active_q);
1577        bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1578}
1579
1580static void
1581bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)
1582{
1583        struct bfa_s            *bfa = first_lps->bfa;
1584        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1585        struct list_head        *qe, *qe_next;
1586        struct bfa_lps_s        *lps;
1587
1588        bfa_trc(bfa, count);
1589
1590        qe = bfa_q_next(first_lps);
1591
1592        while (count && qe) {
1593                qe_next = bfa_q_next(qe);
1594                lps = (struct bfa_lps_s *)qe;
1595                bfa_trc(bfa, lps->bfa_tag);
1596                lps->status = first_lps->status;
1597                list_del(&lps->qe);
1598                list_add_tail(&lps->qe, &mod->lps_active_q);
1599                bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1600                qe = qe_next;
1601                count--;
1602        }
1603}
1604
1605/*
1606 * Firmware logout response
1607 */
1608static void
1609bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
1610{
1611        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1612        struct bfa_lps_s        *lps;
1613
1614        WARN_ON(rsp->bfa_tag >= mod->num_lps);
1615        lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1616
1617        bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1618}
1619
1620/*
1621 * Firmware received a Clear virtual link request (for FCoE)
1622 */
1623static void
1624bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
1625{
1626        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1627        struct bfa_lps_s        *lps;
1628
1629        lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);
1630
1631        bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
1632}
1633
1634/*
1635 * Space is available in request queue, resume queueing request to firmware.
1636 */
1637static void
1638bfa_lps_reqq_resume(void *lps_arg)
1639{
1640        struct bfa_lps_s        *lps = lps_arg;
1641
1642        bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
1643}
1644
1645/*
1646 * lps is freed -- triggered by vport delete
1647 */
1648static void
1649bfa_lps_free(struct bfa_lps_s *lps)
1650{
1651        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(lps->bfa);
1652
1653        lps->lp_pid = 0;
1654        list_del(&lps->qe);
1655        list_add_tail(&lps->qe, &mod->lps_free_q);
1656}
1657
1658/*
1659 * send login request to firmware
1660 */
1661static void
1662bfa_lps_send_login(struct bfa_lps_s *lps)
1663{
1664        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(lps->bfa);
1665        struct bfi_lps_login_req_s      *m;
1666
1667        m = bfa_reqq_next(lps->bfa, lps->reqq);
1668        WARN_ON(!m);
1669
1670        bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
1671                bfa_fn_lpu(lps->bfa));
1672
1673        m->bfa_tag      = lps->bfa_tag;
1674        m->alpa         = lps->alpa;
1675        m->pdu_size     = cpu_to_be16(lps->pdusz);
1676        m->pwwn         = lps->pwwn;
1677        m->nwwn         = lps->nwwn;
1678        m->fdisc        = lps->fdisc;
1679        m->auth_en      = lps->auth_en;
1680
1681        bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1682        list_del(&lps->qe);
1683        list_add_tail(&lps->qe, &mod->lps_login_q);
1684}
1685
1686/*
1687 * send logout request to firmware
1688 */
1689static void
1690bfa_lps_send_logout(struct bfa_lps_s *lps)
1691{
1692        struct bfi_lps_logout_req_s *m;
1693
1694        m = bfa_reqq_next(lps->bfa, lps->reqq);
1695        WARN_ON(!m);
1696
1697        bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
1698                bfa_fn_lpu(lps->bfa));
1699
1700        m->fw_tag = lps->fw_tag;
1701        m->port_name = lps->pwwn;
1702        bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1703}
1704
1705/*
1706 * send n2n pid set request to firmware
1707 */
1708static void
1709bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
1710{
1711        struct bfi_lps_n2n_pid_req_s *m;
1712
1713        m = bfa_reqq_next(lps->bfa, lps->reqq);
1714        WARN_ON(!m);
1715
1716        bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
1717                bfa_fn_lpu(lps->bfa));
1718
1719        m->fw_tag = lps->fw_tag;
1720        m->lp_pid = lps->lp_pid;
1721        bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1722}
1723
1724/*
1725 * Indirect login completion handler for non-fcs
1726 */
1727static void
1728bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
1729{
1730        struct bfa_lps_s *lps   = arg;
1731
1732        if (!complete)
1733                return;
1734
1735        if (lps->fdisc)
1736                bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1737        else
1738                bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1739}
1740
1741/*
1742 * Login completion handler -- direct call for fcs, queue for others
1743 */
1744static void
1745bfa_lps_login_comp(struct bfa_lps_s *lps)
1746{
1747        if (!lps->bfa->fcs) {
1748                bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
1749                        lps);
1750                return;
1751        }
1752
1753        if (lps->fdisc)
1754                bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1755        else
1756                bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1757}
1758
1759/*
1760 * Indirect logout completion handler for non-fcs
1761 */
1762static void
1763bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
1764{
1765        struct bfa_lps_s *lps   = arg;
1766
1767        if (!complete)
1768                return;
1769
1770        if (lps->fdisc)
1771                bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1772        else
1773                bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
1774}
1775
1776/*
1777 * Logout completion handler -- direct call for fcs, queue for others
1778 */
1779static void
1780bfa_lps_logout_comp(struct bfa_lps_s *lps)
1781{
1782        if (!lps->bfa->fcs) {
1783                bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
1784                        lps);
1785                return;
1786        }
1787        if (lps->fdisc)
1788                bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1789}
1790
1791/*
1792 * Clear virtual link completion handler for non-fcs
1793 */
1794static void
1795bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
1796{
1797        struct bfa_lps_s *lps   = arg;
1798
1799        if (!complete)
1800                return;
1801
1802        /* Clear virtual link to base port will result in link down */
1803        if (lps->fdisc)
1804                bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1805}
1806
1807/*
1808 * Received Clear virtual link event --direct call for fcs,
1809 * queue for others
1810 */
1811static void
1812bfa_lps_cvl_event(struct bfa_lps_s *lps)
1813{
1814        if (!lps->bfa->fcs) {
1815                bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
1816                        lps);
1817                return;
1818        }
1819
1820        /* Clear virtual link to base port will result in link down */
1821        if (lps->fdisc)
1822                bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1823}
1824
1825
1826
1827/*
1828 *  lps_public BFA LPS public functions
1829 */
1830
1831u32
1832bfa_lps_get_max_vport(struct bfa_s *bfa)
1833{
1834        if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
1835                return BFA_LPS_MAX_VPORTS_SUPP_CT;
1836        else
1837                return BFA_LPS_MAX_VPORTS_SUPP_CB;
1838}
1839
1840/*
1841 * Allocate a lport srvice tag.
1842 */
1843struct bfa_lps_s  *
1844bfa_lps_alloc(struct bfa_s *bfa)
1845{
1846        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1847        struct bfa_lps_s        *lps = NULL;
1848
1849        bfa_q_deq(&mod->lps_free_q, &lps);
1850
1851        if (lps == NULL)
1852                return NULL;
1853
1854        list_add_tail(&lps->qe, &mod->lps_active_q);
1855
1856        bfa_sm_set_state(lps, bfa_lps_sm_init);
1857        return lps;
1858}
1859
1860/*
1861 * Free lport service tag. This can be called anytime after an alloc.
1862 * No need to wait for any pending login/logout completions.
1863 */
1864void
1865bfa_lps_delete(struct bfa_lps_s *lps)
1866{
1867        bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
1868}
1869
1870/*
1871 * Initiate a lport login.
1872 */
1873void
1874bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
1875        wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
1876{
1877        lps->uarg       = uarg;
1878        lps->alpa       = alpa;
1879        lps->pdusz      = pdusz;
1880        lps->pwwn       = pwwn;
1881        lps->nwwn       = nwwn;
1882        lps->fdisc      = BFA_FALSE;
1883        lps->auth_en    = auth_en;
1884        bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1885}
1886
1887/*
1888 * Initiate a lport fdisc login.
1889 */
1890void
1891bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
1892        wwn_t nwwn)
1893{
1894        lps->uarg       = uarg;
1895        lps->alpa       = 0;
1896        lps->pdusz      = pdusz;
1897        lps->pwwn       = pwwn;
1898        lps->nwwn       = nwwn;
1899        lps->fdisc      = BFA_TRUE;
1900        lps->auth_en    = BFA_FALSE;
1901        bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1902}
1903
1904
1905/*
1906 * Initiate a lport FDSIC logout.
1907 */
1908void
1909bfa_lps_fdisclogo(struct bfa_lps_s *lps)
1910{
1911        bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
1912}
1913
1914u8
1915bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)
1916{
1917        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1918
1919        return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;
1920}
1921
1922/*
1923 * Return lport services tag given the pid
1924 */
1925u8
1926bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
1927{
1928        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1929        struct bfa_lps_s        *lps;
1930        int                     i;
1931
1932        for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
1933                if (lps->lp_pid == pid)
1934                        return lps->bfa_tag;
1935        }
1936
1937        /* Return base port tag anyway */
1938        return 0;
1939}
1940
1941
1942/*
1943 * return port id assigned to the base lport
1944 */
1945u32
1946bfa_lps_get_base_pid(struct bfa_s *bfa)
1947{
1948        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1949
1950        return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
1951}
1952
1953/*
1954 * Set PID in case of n2n (which is assigned during PLOGI)
1955 */
1956void
1957bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
1958{
1959        bfa_trc(lps->bfa, lps->bfa_tag);
1960        bfa_trc(lps->bfa, n2n_pid);
1961
1962        lps->lp_pid = n2n_pid;
1963        bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1964}
1965
1966/*
1967 * LPS firmware message class handler.
1968 */
1969void
1970bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1971{
1972        union bfi_lps_i2h_msg_u msg;
1973
1974        bfa_trc(bfa, m->mhdr.msg_id);
1975        msg.msg = m;
1976
1977        switch (m->mhdr.msg_id) {
1978        case BFI_LPS_I2H_LOGIN_RSP:
1979                bfa_lps_login_rsp(bfa, msg.login_rsp);
1980                break;
1981
1982        case BFI_LPS_I2H_LOGOUT_RSP:
1983                bfa_lps_logout_rsp(bfa, msg.logout_rsp);
1984                break;
1985
1986        case BFI_LPS_I2H_CVL_EVENT:
1987                bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
1988                break;
1989
1990        default:
1991                bfa_trc(bfa, m->mhdr.msg_id);
1992                WARN_ON(1);
1993        }
1994}
1995
1996static void
1997bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
1998{
1999        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2000        struct bfa_aen_entry_s  *aen_entry;
2001
2002        bfad_get_aen_entry(bfad, aen_entry);
2003        if (!aen_entry)
2004                return;
2005
2006        aen_entry->aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
2007        aen_entry->aen_data.port.pwwn = fcport->pwwn;
2008
2009        /* Send the AEN notification */
2010        bfad_im_post_vendor_event(aen_entry, bfad, ++fcport->bfa->bfa_aen_seq,
2011                                  BFA_AEN_CAT_PORT, event);
2012}
2013
2014/*
2015 * FC PORT state machine functions
2016 */
2017static void
2018bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
2019                        enum bfa_fcport_sm_event event)
2020{
2021        bfa_trc(fcport->bfa, event);
2022
2023        switch (event) {
2024        case BFA_FCPORT_SM_START:
2025                /*
2026                 * Start event after IOC is configured and BFA is started.
2027                 */
2028                fcport->use_flash_cfg = BFA_TRUE;
2029
2030                if (bfa_fcport_send_enable(fcport)) {
2031                        bfa_trc(fcport->bfa, BFA_TRUE);
2032                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2033                } else {
2034                        bfa_trc(fcport->bfa, BFA_FALSE);
2035                        bfa_sm_set_state(fcport,
2036                                        bfa_fcport_sm_enabling_qwait);
2037                }
2038                break;
2039
2040        case BFA_FCPORT_SM_ENABLE:
2041                /*
2042                 * Port is persistently configured to be in enabled state. Do
2043                 * not change state. Port enabling is done when START event is
2044                 * received.
2045                 */
2046                break;
2047
2048        case BFA_FCPORT_SM_DISABLE:
2049                /*
2050                 * If a port is persistently configured to be disabled, the
2051                 * first event will a port disable request.
2052                 */
2053                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2054                break;
2055
2056        case BFA_FCPORT_SM_HWFAIL:
2057                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2058                break;
2059
2060        default:
2061                bfa_sm_fault(fcport->bfa, event);
2062        }
2063}
2064
2065static void
2066bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
2067                                enum bfa_fcport_sm_event event)
2068{
2069        char pwwn_buf[BFA_STRING_32];
2070        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2071        bfa_trc(fcport->bfa, event);
2072
2073        switch (event) {
2074        case BFA_FCPORT_SM_QRESUME:
2075                bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2076                bfa_fcport_send_enable(fcport);
2077                break;
2078
2079        case BFA_FCPORT_SM_STOP:
2080                bfa_reqq_wcancel(&fcport->reqq_wait);
2081                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2082                break;
2083
2084        case BFA_FCPORT_SM_ENABLE:
2085                /*
2086                 * Already enable is in progress.
2087                 */
2088                break;
2089
2090        case BFA_FCPORT_SM_DISABLE:
2091                /*
2092                 * Just send disable request to firmware when room becomes
2093                 * available in request queue.
2094                 */
2095                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2096                bfa_reqq_wcancel(&fcport->reqq_wait);
2097                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2098                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2099                wwn2str(pwwn_buf, fcport->pwwn);
2100                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2101                        "Base port disabled: WWN = %s\n", pwwn_buf);
2102                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2103                break;
2104
2105        case BFA_FCPORT_SM_LINKUP:
2106        case BFA_FCPORT_SM_LINKDOWN:
2107                /*
2108                 * Possible to get link events when doing back-to-back
2109                 * enable/disables.
2110                 */
2111                break;
2112
2113        case BFA_FCPORT_SM_HWFAIL:
2114                bfa_reqq_wcancel(&fcport->reqq_wait);
2115                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2116                break;
2117
2118        case BFA_FCPORT_SM_FAA_MISCONFIG:
2119                bfa_fcport_reset_linkinfo(fcport);
2120                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2121                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2122                break;
2123
2124        default:
2125                bfa_sm_fault(fcport->bfa, event);
2126        }
2127}
2128
2129static void
2130bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
2131                                                enum bfa_fcport_sm_event event)
2132{
2133        char pwwn_buf[BFA_STRING_32];
2134        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2135        bfa_trc(fcport->bfa, event);
2136
2137        switch (event) {
2138        case BFA_FCPORT_SM_FWRSP:
2139        case BFA_FCPORT_SM_LINKDOWN:
2140                bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2141                break;
2142
2143        case BFA_FCPORT_SM_LINKUP:
2144                bfa_fcport_update_linkinfo(fcport);
2145                bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2146
2147                WARN_ON(!fcport->event_cbfn);
2148                bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2149                break;
2150
2151        case BFA_FCPORT_SM_ENABLE:
2152                /*
2153                 * Already being enabled.
2154                 */
2155                break;
2156
2157        case BFA_FCPORT_SM_DISABLE:
2158                if (bfa_fcport_send_disable(fcport))
2159                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2160                else
2161                        bfa_sm_set_state(fcport,
2162                                         bfa_fcport_sm_disabling_qwait);
2163
2164                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2165                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2166                wwn2str(pwwn_buf, fcport->pwwn);
2167                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2168                        "Base port disabled: WWN = %s\n", pwwn_buf);
2169                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2170                break;
2171
2172        case BFA_FCPORT_SM_STOP:
2173                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2174                break;
2175
2176        case BFA_FCPORT_SM_HWFAIL:
2177                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2178                break;
2179
2180        case BFA_FCPORT_SM_FAA_MISCONFIG:
2181                bfa_fcport_reset_linkinfo(fcport);
2182                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2183                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2184                break;
2185
2186        default:
2187                bfa_sm_fault(fcport->bfa, event);
2188        }
2189}
2190
2191static void
2192bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
2193                                                enum bfa_fcport_sm_event event)
2194{
2195        struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2196        char pwwn_buf[BFA_STRING_32];
2197        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2198
2199        bfa_trc(fcport->bfa, event);
2200
2201        switch (event) {
2202        case BFA_FCPORT_SM_LINKUP:
2203                bfa_fcport_update_linkinfo(fcport);
2204                bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2205                WARN_ON(!fcport->event_cbfn);
2206                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2207                                BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
2208                if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
2209
2210                        bfa_trc(fcport->bfa,
2211                                pevent->link_state.attr.vc_fcf.fcf.fipenabled);
2212                        bfa_trc(fcport->bfa,
2213                                pevent->link_state.attr.vc_fcf.fcf.fipfailed);
2214
2215                        if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
2216                                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2217                                        BFA_PL_EID_FIP_FCF_DISC, 0,
2218                                        "FIP FCF Discovery Failed");
2219                        else
2220                                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2221                                        BFA_PL_EID_FIP_FCF_DISC, 0,
2222                                        "FIP FCF Discovered");
2223                }
2224
2225                bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2226                wwn2str(pwwn_buf, fcport->pwwn);
2227                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2228                        "Base port online: WWN = %s\n", pwwn_buf);
2229                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
2230
2231                /* If QoS is enabled and it is not online, send AEN */
2232                if (fcport->cfg.qos_enabled &&
2233                    fcport->qos_attr.state != BFA_QOS_ONLINE)
2234                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
2235                break;
2236
2237        case BFA_FCPORT_SM_LINKDOWN:
2238                /*
2239                 * Possible to get link down event.
2240                 */
2241                break;
2242
2243        case BFA_FCPORT_SM_ENABLE:
2244                /*
2245                 * Already enabled.
2246                 */
2247                break;
2248
2249        case BFA_FCPORT_SM_DISABLE:
2250                if (bfa_fcport_send_disable(fcport))
2251                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2252                else
2253                        bfa_sm_set_state(fcport,
2254                                         bfa_fcport_sm_disabling_qwait);
2255
2256                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2257                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2258                wwn2str(pwwn_buf, fcport->pwwn);
2259                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2260                        "Base port disabled: WWN = %s\n", pwwn_buf);
2261                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2262                break;
2263
2264        case BFA_FCPORT_SM_STOP:
2265                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2266                break;
2267
2268        case BFA_FCPORT_SM_HWFAIL:
2269                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2270                break;
2271
2272        case BFA_FCPORT_SM_FAA_MISCONFIG:
2273                bfa_fcport_reset_linkinfo(fcport);
2274                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2275                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2276                break;
2277
2278        default:
2279                bfa_sm_fault(fcport->bfa, event);
2280        }
2281}
2282
2283static void
2284bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
2285        enum bfa_fcport_sm_event event)
2286{
2287        char pwwn_buf[BFA_STRING_32];
2288        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2289
2290        bfa_trc(fcport->bfa, event);
2291
2292        switch (event) {
2293        case BFA_FCPORT_SM_ENABLE:
2294                /*
2295                 * Already enabled.
2296                 */
2297                break;
2298
2299        case BFA_FCPORT_SM_DISABLE:
2300                if (bfa_fcport_send_disable(fcport))
2301                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2302                else
2303                        bfa_sm_set_state(fcport,
2304                                         bfa_fcport_sm_disabling_qwait);
2305
2306                bfa_fcport_reset_linkinfo(fcport);
2307                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2308                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2309                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2310                wwn2str(pwwn_buf, fcport->pwwn);
2311                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2312                        "Base port offline: WWN = %s\n", pwwn_buf);
2313                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2314                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2315                        "Base port disabled: WWN = %s\n", pwwn_buf);
2316                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2317                break;
2318
2319        case BFA_FCPORT_SM_LINKDOWN:
2320                bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2321                bfa_fcport_reset_linkinfo(fcport);
2322                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2323                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2324                                BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
2325                wwn2str(pwwn_buf, fcport->pwwn);
2326                if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2327                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2328                                "Base port offline: WWN = %s\n", pwwn_buf);
2329                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2330                } else {
2331                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2332                                "Base port (WWN = %s) "
2333                                "lost fabric connectivity\n", pwwn_buf);
2334                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2335                }
2336                break;
2337
2338        case BFA_FCPORT_SM_STOP:
2339                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2340                bfa_fcport_reset_linkinfo(fcport);
2341                wwn2str(pwwn_buf, fcport->pwwn);
2342                if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2343                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2344                                "Base port offline: WWN = %s\n", pwwn_buf);
2345                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2346                } else {
2347                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2348                                "Base port (WWN = %s) "
2349                                "lost fabric connectivity\n", pwwn_buf);
2350                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2351                }
2352                break;
2353
2354        case BFA_FCPORT_SM_HWFAIL:
2355                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2356                bfa_fcport_reset_linkinfo(fcport);
2357                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2358                wwn2str(pwwn_buf, fcport->pwwn);
2359                if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2360                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2361                                "Base port offline: WWN = %s\n", pwwn_buf);
2362                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2363                } else {
2364                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2365                                "Base port (WWN = %s) "
2366                                "lost fabric connectivity\n", pwwn_buf);
2367                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2368                }
2369                break;
2370
2371        case BFA_FCPORT_SM_FAA_MISCONFIG:
2372                bfa_fcport_reset_linkinfo(fcport);
2373                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2374                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2375                break;
2376
2377        default:
2378                bfa_sm_fault(fcport->bfa, event);
2379        }
2380}
2381
2382static void
2383bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
2384                                 enum bfa_fcport_sm_event event)
2385{
2386        bfa_trc(fcport->bfa, event);
2387
2388        switch (event) {
2389        case BFA_FCPORT_SM_QRESUME:
2390                bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2391                bfa_fcport_send_disable(fcport);
2392                break;
2393
2394        case BFA_FCPORT_SM_STOP:
2395                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2396                bfa_reqq_wcancel(&fcport->reqq_wait);
2397                break;
2398
2399        case BFA_FCPORT_SM_ENABLE:
2400                bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
2401                break;
2402
2403        case BFA_FCPORT_SM_DISABLE:
2404                /*
2405                 * Already being disabled.
2406                 */
2407                break;
2408
2409        case BFA_FCPORT_SM_LINKUP:
2410        case BFA_FCPORT_SM_LINKDOWN:
2411                /*
2412                 * Possible to get link events when doing back-to-back
2413                 * enable/disables.
2414                 */
2415                break;
2416
2417        case BFA_FCPORT_SM_HWFAIL:
2418                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2419                bfa_reqq_wcancel(&fcport->reqq_wait);
2420                break;
2421
2422        case BFA_FCPORT_SM_FAA_MISCONFIG:
2423                bfa_fcport_reset_linkinfo(fcport);
2424                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2425                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2426                break;
2427
2428        default:
2429                bfa_sm_fault(fcport->bfa, event);
2430        }
2431}
2432
2433static void
2434bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
2435                                 enum bfa_fcport_sm_event event)
2436{
2437        bfa_trc(fcport->bfa, event);
2438
2439        switch (event) {
2440        case BFA_FCPORT_SM_QRESUME:
2441                bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2442                bfa_fcport_send_disable(fcport);
2443                if (bfa_fcport_send_enable(fcport))
2444                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2445                else
2446                        bfa_sm_set_state(fcport,
2447                                         bfa_fcport_sm_enabling_qwait);
2448                break;
2449
2450        case BFA_FCPORT_SM_STOP:
2451                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2452                bfa_reqq_wcancel(&fcport->reqq_wait);
2453                break;
2454
2455        case BFA_FCPORT_SM_ENABLE:
2456                break;
2457
2458        case BFA_FCPORT_SM_DISABLE:
2459                bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2460                break;
2461
2462        case BFA_FCPORT_SM_LINKUP:
2463        case BFA_FCPORT_SM_LINKDOWN:
2464                /*
2465                 * Possible to get link events when doing back-to-back
2466                 * enable/disables.
2467                 */
2468                break;
2469
2470        case BFA_FCPORT_SM_HWFAIL:
2471                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2472                bfa_reqq_wcancel(&fcport->reqq_wait);
2473                break;
2474
2475        default:
2476                bfa_sm_fault(fcport->bfa, event);
2477        }
2478}
2479
2480static void
2481bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
2482                                                enum bfa_fcport_sm_event event)
2483{
2484        char pwwn_buf[BFA_STRING_32];
2485        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2486        bfa_trc(fcport->bfa, event);
2487
2488        switch (event) {
2489        case BFA_FCPORT_SM_FWRSP:
2490                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2491                break;
2492
2493        case BFA_FCPORT_SM_DISABLE:
2494                /*
2495                 * Already being disabled.
2496                 */
2497                break;
2498
2499        case BFA_FCPORT_SM_ENABLE:
2500                if (bfa_fcport_send_enable(fcport))
2501                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2502                else
2503                        bfa_sm_set_state(fcport,
2504                                         bfa_fcport_sm_enabling_qwait);
2505
2506                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2507                                BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2508                wwn2str(pwwn_buf, fcport->pwwn);
2509                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2510                        "Base port enabled: WWN = %s\n", pwwn_buf);
2511                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2512                break;
2513
2514        case BFA_FCPORT_SM_STOP:
2515                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2516                break;
2517
2518        case BFA_FCPORT_SM_LINKUP:
2519        case BFA_FCPORT_SM_LINKDOWN:
2520                /*
2521                 * Possible to get link events when doing back-to-back
2522                 * enable/disables.
2523                 */
2524                break;
2525
2526        case BFA_FCPORT_SM_HWFAIL:
2527                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2528                break;
2529
2530        default:
2531                bfa_sm_fault(fcport->bfa, event);
2532        }
2533}
2534
2535static void
2536bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
2537                                                enum bfa_fcport_sm_event event)
2538{
2539        char pwwn_buf[BFA_STRING_32];
2540        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2541        bfa_trc(fcport->bfa, event);
2542
2543        switch (event) {
2544        case BFA_FCPORT_SM_START:
2545                /*
2546                 * Ignore start event for a port that is disabled.
2547                 */
2548                break;
2549
2550        case BFA_FCPORT_SM_STOP:
2551                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2552                break;
2553
2554        case BFA_FCPORT_SM_ENABLE:
2555                if (bfa_fcport_send_enable(fcport))
2556                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2557                else
2558                        bfa_sm_set_state(fcport,
2559                                         bfa_fcport_sm_enabling_qwait);
2560
2561                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2562                                BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2563                wwn2str(pwwn_buf, fcport->pwwn);
2564                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2565                        "Base port enabled: WWN = %s\n", pwwn_buf);
2566                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2567                break;
2568
2569        case BFA_FCPORT_SM_DISABLE:
2570                /*
2571                 * Already disabled.
2572                 */
2573                break;
2574
2575        case BFA_FCPORT_SM_HWFAIL:
2576                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2577                break;
2578
2579        case BFA_FCPORT_SM_DPORTENABLE:
2580                bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
2581                break;
2582
2583        case BFA_FCPORT_SM_DDPORTENABLE:
2584                bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);
2585                break;
2586
2587        default:
2588                bfa_sm_fault(fcport->bfa, event);
2589        }
2590}
2591
2592static void
2593bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
2594                         enum bfa_fcport_sm_event event)
2595{
2596        bfa_trc(fcport->bfa, event);
2597
2598        switch (event) {
2599        case BFA_FCPORT_SM_START:
2600                if (bfa_fcport_send_enable(fcport))
2601                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2602                else
2603                        bfa_sm_set_state(fcport,
2604                                         bfa_fcport_sm_enabling_qwait);
2605                break;
2606
2607        default:
2608                /*
2609                 * Ignore all other events.
2610                 */
2611                ;
2612        }
2613}
2614
2615/*
2616 * Port is enabled. IOC is down/failed.
2617 */
2618static void
2619bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
2620                         enum bfa_fcport_sm_event event)
2621{
2622        bfa_trc(fcport->bfa, event);
2623
2624        switch (event) {
2625        case BFA_FCPORT_SM_START:
2626                if (bfa_fcport_send_enable(fcport))
2627                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2628                else
2629                        bfa_sm_set_state(fcport,
2630                                         bfa_fcport_sm_enabling_qwait);
2631                break;
2632
2633        default:
2634                /*
2635                 * Ignore all events.
2636                 */
2637                ;
2638        }
2639}
2640
2641/*
2642 * Port is disabled. IOC is down/failed.
2643 */
2644static void
2645bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
2646                         enum bfa_fcport_sm_event event)
2647{
2648        bfa_trc(fcport->bfa, event);
2649
2650        switch (event) {
2651        case BFA_FCPORT_SM_START:
2652                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2653                break;
2654
2655        case BFA_FCPORT_SM_ENABLE:
2656                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2657                break;
2658
2659        default:
2660                /*
2661                 * Ignore all events.
2662                 */
2663                ;
2664        }
2665}
2666
2667static void
2668bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
2669{
2670        bfa_trc(fcport->bfa, event);
2671
2672        switch (event) {
2673        case BFA_FCPORT_SM_DPORTENABLE:
2674        case BFA_FCPORT_SM_DISABLE:
2675        case BFA_FCPORT_SM_ENABLE:
2676        case BFA_FCPORT_SM_START:
2677                /*
2678                 * Ignore event for a port that is dport
2679                 */
2680                break;
2681
2682        case BFA_FCPORT_SM_STOP:
2683                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2684                break;
2685
2686        case BFA_FCPORT_SM_HWFAIL:
2687                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2688                break;
2689
2690        case BFA_FCPORT_SM_DPORTDISABLE:
2691                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2692                break;
2693
2694        default:
2695                bfa_sm_fault(fcport->bfa, event);
2696        }
2697}
2698
2699static void
2700bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
2701                        enum bfa_fcport_sm_event event)
2702{
2703        bfa_trc(fcport->bfa, event);
2704
2705        switch (event) {
2706        case BFA_FCPORT_SM_DISABLE:
2707        case BFA_FCPORT_SM_DDPORTDISABLE:
2708                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2709                break;
2710
2711        case BFA_FCPORT_SM_DPORTENABLE:
2712        case BFA_FCPORT_SM_DPORTDISABLE:
2713        case BFA_FCPORT_SM_ENABLE:
2714        case BFA_FCPORT_SM_START:
2715                /*
2716                 * Ignore event for a port that is ddport
2717                 */
2718                break;
2719
2720        case BFA_FCPORT_SM_STOP:
2721                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2722                break;
2723
2724        case BFA_FCPORT_SM_HWFAIL:
2725                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2726                break;
2727
2728        default:
2729                bfa_sm_fault(fcport->bfa, event);
2730        }
2731}
2732
2733static void
2734bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
2735                            enum bfa_fcport_sm_event event)
2736{
2737        bfa_trc(fcport->bfa, event);
2738
2739        switch (event) {
2740        case BFA_FCPORT_SM_DPORTENABLE:
2741        case BFA_FCPORT_SM_ENABLE:
2742        case BFA_FCPORT_SM_START:
2743                /*
2744                 * Ignore event for a port as there is FAA misconfig
2745                 */
2746                break;
2747
2748        case BFA_FCPORT_SM_DISABLE:
2749                if (bfa_fcport_send_disable(fcport))
2750                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2751                else
2752                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2753
2754                bfa_fcport_reset_linkinfo(fcport);
2755                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2756                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2757                             BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2758                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2759                break;
2760
2761        case BFA_FCPORT_SM_STOP:
2762                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2763                break;
2764
2765        case BFA_FCPORT_SM_HWFAIL:
2766                bfa_fcport_reset_linkinfo(fcport);
2767                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2768                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2769                break;
2770
2771        default:
2772                bfa_sm_fault(fcport->bfa, event);
2773        }
2774}
2775
2776/*
2777 * Link state is down
2778 */
2779static void
2780bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
2781                enum bfa_fcport_ln_sm_event event)
2782{
2783        bfa_trc(ln->fcport->bfa, event);
2784
2785        switch (event) {
2786        case BFA_FCPORT_LN_SM_LINKUP:
2787                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2788                bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2789                break;
2790
2791        default:
2792                bfa_sm_fault(ln->fcport->bfa, event);
2793        }
2794}
2795
2796/*
2797 * Link state is waiting for down notification
2798 */
2799static void
2800bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
2801                enum bfa_fcport_ln_sm_event event)
2802{
2803        bfa_trc(ln->fcport->bfa, event);
2804
2805        switch (event) {
2806        case BFA_FCPORT_LN_SM_LINKUP:
2807                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2808                break;
2809
2810        case BFA_FCPORT_LN_SM_NOTIFICATION:
2811                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2812                break;
2813
2814        default:
2815                bfa_sm_fault(ln->fcport->bfa, event);
2816        }
2817}
2818
2819/*
2820 * Link state is waiting for down notification and there is a pending up
2821 */
2822static void
2823bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
2824                enum bfa_fcport_ln_sm_event event)
2825{
2826        bfa_trc(ln->fcport->bfa, event);
2827
2828        switch (event) {
2829        case BFA_FCPORT_LN_SM_LINKDOWN:
2830                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2831                break;
2832
2833        case BFA_FCPORT_LN_SM_NOTIFICATION:
2834                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2835                bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2836                break;
2837
2838        default:
2839                bfa_sm_fault(ln->fcport->bfa, event);
2840        }
2841}
2842
2843/*
2844 * Link state is up
2845 */
2846static void
2847bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
2848                enum bfa_fcport_ln_sm_event event)
2849{
2850        bfa_trc(ln->fcport->bfa, event);
2851
2852        switch (event) {
2853        case BFA_FCPORT_LN_SM_LINKDOWN:
2854                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2855                bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2856                break;
2857
2858        default:
2859                bfa_sm_fault(ln->fcport->bfa, event);
2860        }
2861}
2862
2863/*
2864 * Link state is waiting for up notification
2865 */
2866static void
2867bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
2868                enum bfa_fcport_ln_sm_event event)
2869{
2870        bfa_trc(ln->fcport->bfa, event);
2871
2872        switch (event) {
2873        case BFA_FCPORT_LN_SM_LINKDOWN:
2874                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2875                break;
2876
2877        case BFA_FCPORT_LN_SM_NOTIFICATION:
2878                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
2879                break;
2880
2881        default:
2882                bfa_sm_fault(ln->fcport->bfa, event);
2883        }
2884}
2885
2886/*
2887 * Link state is waiting for up notification and there is a pending down
2888 */
2889static void
2890bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
2891                enum bfa_fcport_ln_sm_event event)
2892{
2893        bfa_trc(ln->fcport->bfa, event);
2894
2895        switch (event) {
2896        case BFA_FCPORT_LN_SM_LINKUP:
2897                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
2898                break;
2899
2900        case BFA_FCPORT_LN_SM_NOTIFICATION:
2901                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2902                bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2903                break;
2904
2905        default:
2906                bfa_sm_fault(ln->fcport->bfa, event);
2907        }
2908}
2909
2910/*
2911 * Link state is waiting for up notification and there are pending down and up
2912 */
2913static void
2914bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
2915                        enum bfa_fcport_ln_sm_event event)
2916{
2917        bfa_trc(ln->fcport->bfa, event);
2918
2919        switch (event) {
2920        case BFA_FCPORT_LN_SM_LINKDOWN:
2921                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2922                break;
2923
2924        case BFA_FCPORT_LN_SM_NOTIFICATION:
2925                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2926                bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2927                break;
2928
2929        default:
2930                bfa_sm_fault(ln->fcport->bfa, event);
2931        }
2932}
2933
2934static void
2935__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
2936{
2937        struct bfa_fcport_ln_s *ln = cbarg;
2938
2939        if (complete)
2940                ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
2941        else
2942                bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2943}
2944
2945/*
2946 * Send SCN notification to upper layers.
2947 * trunk - false if caller is fcport to ignore fcport event in trunked mode
2948 */
2949static void
2950bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
2951        bfa_boolean_t trunk)
2952{
2953        if (fcport->cfg.trunked && !trunk)
2954                return;
2955
2956        switch (event) {
2957        case BFA_PORT_LINKUP:
2958                bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
2959                break;
2960        case BFA_PORT_LINKDOWN:
2961                bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
2962                break;
2963        default:
2964                WARN_ON(1);
2965        }
2966}
2967
2968static void
2969bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
2970{
2971        struct bfa_fcport_s *fcport = ln->fcport;
2972
2973        if (fcport->bfa->fcs) {
2974                fcport->event_cbfn(fcport->event_cbarg, event);
2975                bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2976        } else {
2977                ln->ln_event = event;
2978                bfa_cb_queue(fcport->bfa, &ln->ln_qe,
2979                        __bfa_cb_fcport_event, ln);
2980        }
2981}
2982
2983#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
2984                                                        BFA_CACHELINE_SZ))
2985
2986void
2987bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
2988                   struct bfa_s *bfa)
2989{
2990        struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa);
2991
2992        bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);
2993}
2994
2995static void
2996bfa_fcport_qresume(void *cbarg)
2997{
2998        struct bfa_fcport_s *fcport = cbarg;
2999
3000        bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
3001}
3002
3003static void
3004bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)
3005{
3006        struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma;
3007
3008        fcport->stats_kva = bfa_mem_dma_virt(fcport_dma);
3009        fcport->stats_pa  = bfa_mem_dma_phys(fcport_dma);
3010        fcport->stats = (union bfa_fcport_stats_u *)
3011                                bfa_mem_dma_virt(fcport_dma);
3012}
3013
3014/*
3015 * Memory initialization.
3016 */
3017void
3018bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
3019                struct bfa_pcidev_s *pcidev)
3020{
3021        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3022        struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
3023        struct bfa_fcport_ln_s *ln = &fcport->ln;
3024
3025        fcport->bfa = bfa;
3026        ln->fcport = fcport;
3027
3028        bfa_fcport_mem_claim(fcport);
3029
3030        bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
3031        bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
3032
3033        /*
3034         * initialize time stamp for stats reset
3035         */
3036        fcport->stats_reset_time = ktime_get_seconds();
3037        fcport->stats_dma_ready = BFA_FALSE;
3038
3039        /*
3040         * initialize and set default configuration
3041         */
3042        port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
3043        port_cfg->speed = BFA_PORT_SPEED_AUTO;
3044        port_cfg->trunked = BFA_FALSE;
3045        port_cfg->maxfrsize = 0;
3046
3047        port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
3048        port_cfg->qos_bw.high = BFA_QOS_BW_HIGH;
3049        port_cfg->qos_bw.med = BFA_QOS_BW_MED;
3050        port_cfg->qos_bw.low = BFA_QOS_BW_LOW;
3051
3052        fcport->fec_state = BFA_FEC_OFFLINE;
3053
3054        INIT_LIST_HEAD(&fcport->stats_pending_q);
3055        INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3056
3057        bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
3058}
3059
3060void
3061bfa_fcport_start(struct bfa_s *bfa)
3062{
3063        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
3064}
3065
3066/*
3067 * Called when IOC failure is detected.
3068 */
3069void
3070bfa_fcport_iocdisable(struct bfa_s *bfa)
3071{
3072        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3073
3074        bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
3075        bfa_trunk_iocdisable(bfa);
3076}
3077
3078/*
3079 * Update loop info in fcport for SCN online
3080 */
3081static void
3082bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
3083                        struct bfa_fcport_loop_info_s *loop_info)
3084{
3085        fcport->myalpa = loop_info->myalpa;
3086        fcport->alpabm_valid =
3087                        loop_info->alpabm_val;
3088        memcpy(fcport->alpabm.alpa_bm,
3089                        loop_info->alpabm.alpa_bm,
3090                        sizeof(struct fc_alpabm_s));
3091}
3092
3093static void
3094bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
3095{
3096        struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
3097        struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3098
3099        fcport->speed = pevent->link_state.speed;
3100        fcport->topology = pevent->link_state.topology;
3101
3102        if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
3103                bfa_fcport_update_loop_info(fcport,
3104                                &pevent->link_state.attr.loop_info);
3105                return;
3106        }
3107
3108        /* QoS Details */
3109        fcport->qos_attr = pevent->link_state.qos_attr;
3110        fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
3111
3112        if (fcport->cfg.bb_cr_enabled)
3113                fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr;
3114
3115        fcport->fec_state = pevent->link_state.fec_state;
3116
3117        /*
3118         * update trunk state if applicable
3119         */
3120        if (!fcport->cfg.trunked)
3121                trunk->attr.state = BFA_TRUNK_DISABLED;
3122
3123        /* update FCoE specific */
3124        fcport->fcoe_vlan =
3125                be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
3126
3127        bfa_trc(fcport->bfa, fcport->speed);
3128        bfa_trc(fcport->bfa, fcport->topology);
3129}
3130
3131static void
3132bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
3133{
3134        fcport->speed = BFA_PORT_SPEED_UNKNOWN;
3135        fcport->topology = BFA_PORT_TOPOLOGY_NONE;
3136        fcport->fec_state = BFA_FEC_OFFLINE;
3137}
3138
3139/*
3140 * Send port enable message to firmware.
3141 */
3142static bfa_boolean_t
3143bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
3144{
3145        struct bfi_fcport_enable_req_s *m;
3146
3147        /*
3148         * Increment message tag before queue check, so that responses to old
3149         * requests are discarded.
3150         */
3151        fcport->msgtag++;
3152
3153        /*
3154         * check for room in queue to send request now
3155         */
3156        m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3157        if (!m) {
3158                bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3159                                                        &fcport->reqq_wait);
3160                return BFA_FALSE;
3161        }
3162
3163        bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
3164                        bfa_fn_lpu(fcport->bfa));
3165        m->nwwn = fcport->nwwn;
3166        m->pwwn = fcport->pwwn;
3167        m->port_cfg = fcport->cfg;
3168        m->msgtag = fcport->msgtag;
3169        m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
3170        m->use_flash_cfg = fcport->use_flash_cfg;
3171        bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
3172        bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
3173        bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
3174
3175        /*
3176         * queue I/O message to firmware
3177         */
3178        bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3179        return BFA_TRUE;
3180}
3181
3182/*
3183 * Send port disable message to firmware.
3184 */
3185static  bfa_boolean_t
3186bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
3187{
3188        struct bfi_fcport_req_s *m;
3189
3190        /*
3191         * Increment message tag before queue check, so that responses to old
3192         * requests are discarded.
3193         */
3194        fcport->msgtag++;
3195
3196        /*
3197         * check for room in queue to send request now
3198         */
3199        m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3200        if (!m) {
3201                bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3202                                                        &fcport->reqq_wait);
3203                return BFA_FALSE;
3204        }
3205
3206        bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
3207                        bfa_fn_lpu(fcport->bfa));
3208        m->msgtag = fcport->msgtag;
3209
3210        /*
3211         * queue I/O message to firmware
3212         */
3213        bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3214
3215        return BFA_TRUE;
3216}
3217
3218static void
3219bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
3220{
3221        fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
3222        fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
3223
3224        bfa_trc(fcport->bfa, fcport->pwwn);
3225        bfa_trc(fcport->bfa, fcport->nwwn);
3226}
3227
3228static void
3229bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
3230        struct bfa_qos_stats_s *s)
3231{
3232        u32     *dip = (u32 *) d;
3233        __be32  *sip = (__be32 *) s;
3234        int             i;
3235
3236        /* Now swap the 32 bit fields */
3237        for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
3238                dip[i] = be32_to_cpu(sip[i]);
3239}
3240
3241static void
3242bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
3243        struct bfa_fcoe_stats_s *s)
3244{
3245        u32     *dip = (u32 *) d;
3246        __be32  *sip = (__be32 *) s;
3247        int             i;
3248
3249        for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
3250             i = i + 2) {
3251#ifdef __BIG_ENDIAN
3252                dip[i] = be32_to_cpu(sip[i]);
3253                dip[i + 1] = be32_to_cpu(sip[i + 1]);
3254#else
3255                dip[i] = be32_to_cpu(sip[i + 1]);
3256                dip[i + 1] = be32_to_cpu(sip[i]);
3257#endif
3258        }
3259}
3260
3261static void
3262__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
3263{
3264        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;
3265        struct bfa_cb_pending_q_s *cb;
3266        struct list_head *qe, *qen;
3267        union bfa_fcport_stats_u *ret;
3268
3269        if (complete) {
3270                time64_t time = ktime_get_seconds();
3271
3272                list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
3273                        bfa_q_deq(&fcport->stats_pending_q, &qe);
3274                        cb = (struct bfa_cb_pending_q_s *)qe;
3275                        if (fcport->stats_status == BFA_STATUS_OK) {
3276                                ret = (union bfa_fcport_stats_u *)cb->data;
3277                                /* Swap FC QoS or FCoE stats */
3278                                if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
3279                                        bfa_fcport_qos_stats_swap(&ret->fcqos,
3280                                                        &fcport->stats->fcqos);
3281                                else {
3282                                        bfa_fcport_fcoe_stats_swap(&ret->fcoe,
3283                                                        &fcport->stats->fcoe);
3284                                        ret->fcoe.secs_reset =
3285                                                time - fcport->stats_reset_time;
3286                                }
3287                        }
3288                        bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3289                                        fcport->stats_status);
3290                }
3291                fcport->stats_status = BFA_STATUS_OK;
3292        } else {
3293                INIT_LIST_HEAD(&fcport->stats_pending_q);
3294                fcport->stats_status = BFA_STATUS_OK;
3295        }
3296}
3297
3298static void
3299bfa_fcport_stats_get_timeout(void *cbarg)
3300{
3301        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3302
3303        bfa_trc(fcport->bfa, fcport->stats_qfull);
3304
3305        if (fcport->stats_qfull) {
3306                bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3307                fcport->stats_qfull = BFA_FALSE;
3308        }
3309
3310        fcport->stats_status = BFA_STATUS_ETIMER;
3311        __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3312}
3313
3314static void
3315bfa_fcport_send_stats_get(void *cbarg)
3316{
3317        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3318        struct bfi_fcport_req_s *msg;
3319
3320        msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3321
3322        if (!msg) {
3323                fcport->stats_qfull = BFA_TRUE;
3324                bfa_reqq_winit(&fcport->stats_reqq_wait,
3325                                bfa_fcport_send_stats_get, fcport);
3326                bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3327                                &fcport->stats_reqq_wait);
3328                return;
3329        }
3330        fcport->stats_qfull = BFA_FALSE;
3331
3332        memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3333        bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
3334                        bfa_fn_lpu(fcport->bfa));
3335        bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3336}
3337
3338static void
3339__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3340{
3341        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3342        struct bfa_cb_pending_q_s *cb;
3343        struct list_head *qe, *qen;
3344
3345        if (complete) {
3346                /*
3347                 * re-initialize time stamp for stats reset
3348                 */
3349                fcport->stats_reset_time = ktime_get_seconds();
3350                list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
3351                        bfa_q_deq(&fcport->statsclr_pending_q, &qe);
3352                        cb = (struct bfa_cb_pending_q_s *)qe;
3353                        bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3354                                                fcport->stats_status);
3355                }
3356                fcport->stats_status = BFA_STATUS_OK;
3357        } else {
3358                INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3359                fcport->stats_status = BFA_STATUS_OK;
3360        }
3361}
3362
3363static void
3364bfa_fcport_stats_clr_timeout(void *cbarg)
3365{
3366        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3367
3368        bfa_trc(fcport->bfa, fcport->stats_qfull);
3369
3370        if (fcport->stats_qfull) {
3371                bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3372                fcport->stats_qfull = BFA_FALSE;
3373        }
3374
3375        fcport->stats_status = BFA_STATUS_ETIMER;
3376        __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3377}
3378
3379static void
3380bfa_fcport_send_stats_clear(void *cbarg)
3381{
3382        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3383        struct bfi_fcport_req_s *msg;
3384
3385        msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3386
3387        if (!msg) {
3388                fcport->stats_qfull = BFA_TRUE;
3389                bfa_reqq_winit(&fcport->stats_reqq_wait,
3390                                bfa_fcport_send_stats_clear, fcport);
3391                bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3392                                                &fcport->stats_reqq_wait);
3393                return;
3394        }
3395        fcport->stats_qfull = BFA_FALSE;
3396
3397        memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3398        bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
3399                        bfa_fn_lpu(fcport->bfa));
3400        bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3401}
3402
3403/*
3404 * Handle trunk SCN event from firmware.
3405 */
3406static void
3407bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
3408{
3409        struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3410        struct bfi_fcport_trunk_link_s *tlink;
3411        struct bfa_trunk_link_attr_s *lattr;
3412        enum bfa_trunk_state state_prev;
3413        int i;
3414        int link_bm = 0;
3415
3416        bfa_trc(fcport->bfa, fcport->cfg.trunked);
3417        WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
3418                   scn->trunk_state != BFA_TRUNK_OFFLINE);
3419
3420        bfa_trc(fcport->bfa, trunk->attr.state);
3421        bfa_trc(fcport->bfa, scn->trunk_state);
3422        bfa_trc(fcport->bfa, scn->trunk_speed);
3423
3424        /*
3425         * Save off new state for trunk attribute query
3426         */
3427        state_prev = trunk->attr.state;
3428        if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
3429                trunk->attr.state = scn->trunk_state;
3430        trunk->attr.speed = scn->trunk_speed;
3431        for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3432                lattr = &trunk->attr.link_attr[i];
3433                tlink = &scn->tlink[i];
3434
3435                lattr->link_state = tlink->state;
3436                lattr->trunk_wwn  = tlink->trunk_wwn;
3437                lattr->fctl       = tlink->fctl;
3438                lattr->speed      = tlink->speed;
3439                lattr->deskew     = be32_to_cpu(tlink->deskew);
3440
3441                if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
3442                        fcport->speed    = tlink->speed;
3443                        fcport->topology = BFA_PORT_TOPOLOGY_P2P;
3444                        link_bm |= 1 << i;
3445                }
3446
3447                bfa_trc(fcport->bfa, lattr->link_state);
3448                bfa_trc(fcport->bfa, lattr->trunk_wwn);
3449                bfa_trc(fcport->bfa, lattr->fctl);
3450                bfa_trc(fcport->bfa, lattr->speed);
3451                bfa_trc(fcport->bfa, lattr->deskew);
3452        }
3453
3454        switch (link_bm) {
3455        case 3:
3456                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3457                        BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
3458                break;
3459        case 2:
3460                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3461                        BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
3462                break;
3463        case 1:
3464                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3465                        BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
3466                break;
3467        default:
3468                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3469                        BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
3470        }
3471
3472        /*
3473         * Notify upper layers if trunk state changed.
3474         */
3475        if ((state_prev != trunk->attr.state) ||
3476                (scn->trunk_state == BFA_TRUNK_OFFLINE)) {
3477                bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
3478                        BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
3479        }
3480}
3481
3482static void
3483bfa_trunk_iocdisable(struct bfa_s *bfa)
3484{
3485        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3486        int i = 0;
3487
3488        /*
3489         * In trunked mode, notify upper layers that link is down
3490         */
3491        if (fcport->cfg.trunked) {
3492                if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
3493                        bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
3494
3495                fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
3496                fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
3497                for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3498                        fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
3499                        fcport->trunk.attr.link_attr[i].fctl =
3500                                                BFA_TRUNK_LINK_FCTL_NORMAL;
3501                        fcport->trunk.attr.link_attr[i].link_state =
3502                                                BFA_TRUNK_LINK_STATE_DN_LINKDN;
3503                        fcport->trunk.attr.link_attr[i].speed =
3504                                                BFA_PORT_SPEED_UNKNOWN;
3505                        fcport->trunk.attr.link_attr[i].deskew = 0;
3506                }
3507        }
3508}
3509
3510/*
3511 * Called to initialize port attributes
3512 */
3513void
3514bfa_fcport_init(struct bfa_s *bfa)
3515{
3516        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3517
3518        /*
3519         * Initialize port attributes from IOC hardware data.
3520         */
3521        bfa_fcport_set_wwns(fcport);
3522        if (fcport->cfg.maxfrsize == 0)
3523                fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
3524        fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
3525        fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
3526
3527        if (bfa_fcport_is_pbcdisabled(bfa))
3528                bfa->modules.port.pbc_disabled = BFA_TRUE;
3529
3530        WARN_ON(!fcport->cfg.maxfrsize);
3531        WARN_ON(!fcport->cfg.rx_bbcredit);
3532        WARN_ON(!fcport->speed_sup);
3533}
3534
3535/*
3536 * Firmware message handler.
3537 */
3538void
3539bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
3540{
3541        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3542        union bfi_fcport_i2h_msg_u i2hmsg;
3543
3544        i2hmsg.msg = msg;
3545        fcport->event_arg.i2hmsg = i2hmsg;
3546
3547        bfa_trc(bfa, msg->mhdr.msg_id);
3548        bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
3549
3550        switch (msg->mhdr.msg_id) {
3551        case BFI_FCPORT_I2H_ENABLE_RSP:
3552                if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
3553
3554                        fcport->stats_dma_ready = BFA_TRUE;
3555                        if (fcport->use_flash_cfg) {
3556                                fcport->cfg = i2hmsg.penable_rsp->port_cfg;
3557                                fcport->cfg.maxfrsize =
3558                                        cpu_to_be16(fcport->cfg.maxfrsize);
3559                                fcport->cfg.path_tov =
3560                                        cpu_to_be16(fcport->cfg.path_tov);
3561                                fcport->cfg.q_depth =
3562                                        cpu_to_be16(fcport->cfg.q_depth);
3563
3564                                if (fcport->cfg.trunked)
3565                                        fcport->trunk.attr.state =
3566                                                BFA_TRUNK_OFFLINE;
3567                                else
3568                                        fcport->trunk.attr.state =
3569                                                BFA_TRUNK_DISABLED;
3570                                fcport->qos_attr.qos_bw =
3571                                        i2hmsg.penable_rsp->port_cfg.qos_bw;
3572                                fcport->use_flash_cfg = BFA_FALSE;
3573                        }
3574
3575                        if (fcport->cfg.qos_enabled)
3576                                fcport->qos_attr.state = BFA_QOS_OFFLINE;
3577                        else
3578                                fcport->qos_attr.state = BFA_QOS_DISABLED;
3579
3580                        fcport->qos_attr.qos_bw_op =
3581                                        i2hmsg.penable_rsp->port_cfg.qos_bw;
3582
3583                        if (fcport->cfg.bb_cr_enabled)
3584                                fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3585                        else
3586                                fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3587
3588                        bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3589                }
3590                break;
3591
3592        case BFI_FCPORT_I2H_DISABLE_RSP:
3593                if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
3594                        bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3595                break;
3596
3597        case BFI_FCPORT_I2H_EVENT:
3598                if (fcport->cfg.bb_cr_enabled)
3599                        fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3600                else
3601                        fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3602
3603                if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
3604                        bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
3605                else {
3606                        if (i2hmsg.event->link_state.linkstate_rsn ==
3607                            BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG)
3608                                bfa_sm_send_event(fcport,
3609                                                  BFA_FCPORT_SM_FAA_MISCONFIG);
3610                        else
3611                                bfa_sm_send_event(fcport,
3612                                                  BFA_FCPORT_SM_LINKDOWN);
3613                }
3614                fcport->qos_attr.qos_bw_op =
3615                                i2hmsg.event->link_state.qos_attr.qos_bw_op;
3616                break;
3617
3618        case BFI_FCPORT_I2H_TRUNK_SCN:
3619                bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
3620                break;
3621
3622        case BFI_FCPORT_I2H_STATS_GET_RSP:
3623                /*
3624                 * check for timer pop before processing the rsp
3625                 */
3626                if (list_empty(&fcport->stats_pending_q) ||
3627                    (fcport->stats_status == BFA_STATUS_ETIMER))
3628                        break;
3629
3630                bfa_timer_stop(&fcport->timer);
3631                fcport->stats_status = i2hmsg.pstatsget_rsp->status;
3632                __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3633                break;
3634
3635        case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
3636                /*
3637                 * check for timer pop before processing the rsp
3638                 */
3639                if (list_empty(&fcport->statsclr_pending_q) ||
3640                    (fcport->stats_status == BFA_STATUS_ETIMER))
3641                        break;
3642
3643                bfa_timer_stop(&fcport->timer);
3644                fcport->stats_status = BFA_STATUS_OK;
3645                __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3646                break;
3647
3648        case BFI_FCPORT_I2H_ENABLE_AEN:
3649                bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
3650                break;
3651
3652        case BFI_FCPORT_I2H_DISABLE_AEN:
3653                bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
3654                break;
3655
3656        default:
3657                WARN_ON(1);
3658        break;
3659        }
3660}
3661
3662/*
3663 * Registered callback for port events.
3664 */
3665void
3666bfa_fcport_event_register(struct bfa_s *bfa,
3667                                void (*cbfn) (void *cbarg,
3668                                enum bfa_port_linkstate event),
3669                                void *cbarg)
3670{
3671        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3672
3673        fcport->event_cbfn = cbfn;
3674        fcport->event_cbarg = cbarg;
3675}
3676
3677bfa_status_t
3678bfa_fcport_enable(struct bfa_s *bfa)
3679{
3680        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3681
3682        if (bfa_fcport_is_pbcdisabled(bfa))
3683                return BFA_STATUS_PBC;
3684
3685        if (bfa_ioc_is_disabled(&bfa->ioc))
3686                return BFA_STATUS_IOC_DISABLED;
3687
3688        if (fcport->diag_busy)
3689                return BFA_STATUS_DIAG_BUSY;
3690
3691        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
3692        return BFA_STATUS_OK;
3693}
3694
3695bfa_status_t
3696bfa_fcport_disable(struct bfa_s *bfa)
3697{
3698        if (bfa_fcport_is_pbcdisabled(bfa))
3699                return BFA_STATUS_PBC;
3700
3701        if (bfa_ioc_is_disabled(&bfa->ioc))
3702                return BFA_STATUS_IOC_DISABLED;
3703
3704        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
3705        return BFA_STATUS_OK;
3706}
3707
3708/* If PBC is disabled on port, return error */
3709bfa_status_t
3710bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)
3711{
3712        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3713        struct bfa_iocfc_s *iocfc = &bfa->iocfc;
3714        struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
3715
3716        if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
3717                bfa_trc(bfa, fcport->pwwn);
3718                return BFA_STATUS_PBC;
3719        }
3720        return BFA_STATUS_OK;
3721}
3722
3723/*
3724 * Configure port speed.
3725 */
3726bfa_status_t
3727bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
3728{
3729        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3730
3731        bfa_trc(bfa, speed);
3732
3733        if (fcport->cfg.trunked == BFA_TRUE)
3734                return BFA_STATUS_TRUNK_ENABLED;
3735        if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
3736                        (speed == BFA_PORT_SPEED_16GBPS))
3737                return BFA_STATUS_UNSUPP_SPEED;
3738        if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
3739                bfa_trc(bfa, fcport->speed_sup);
3740                return BFA_STATUS_UNSUPP_SPEED;
3741        }
3742
3743        /* Port speed entered needs to be checked */
3744        if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {
3745                /* For CT2, 1G is not supported */
3746                if ((speed == BFA_PORT_SPEED_1GBPS) &&
3747                    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
3748                        return BFA_STATUS_UNSUPP_SPEED;
3749
3750                /* Already checked for Auto Speed and Max Speed supp */
3751                if (!(speed == BFA_PORT_SPEED_1GBPS ||
3752                      speed == BFA_PORT_SPEED_2GBPS ||
3753                      speed == BFA_PORT_SPEED_4GBPS ||
3754                      speed == BFA_PORT_SPEED_8GBPS ||
3755                      speed == BFA_PORT_SPEED_16GBPS ||
3756                      speed == BFA_PORT_SPEED_AUTO))
3757                        return BFA_STATUS_UNSUPP_SPEED;
3758        } else {
3759                if (speed != BFA_PORT_SPEED_10GBPS)
3760                        return BFA_STATUS_UNSUPP_SPEED;
3761        }
3762
3763        fcport->cfg.speed = speed;
3764
3765        return BFA_STATUS_OK;
3766}
3767
3768/*
3769 * Get current speed.
3770 */
3771enum bfa_port_speed
3772bfa_fcport_get_speed(struct bfa_s *bfa)
3773{
3774        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3775
3776        return fcport->speed;
3777}
3778
3779/*
3780 * Configure port topology.
3781 */
3782bfa_status_t
3783bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
3784{
3785        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3786
3787        bfa_trc(bfa, topology);
3788        bfa_trc(bfa, fcport->cfg.topology);
3789
3790        switch (topology) {
3791        case BFA_PORT_TOPOLOGY_P2P:
3792                break;
3793
3794        case BFA_PORT_TOPOLOGY_LOOP:
3795                if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
3796                        (fcport->qos_attr.state != BFA_QOS_DISABLED))
3797                        return BFA_STATUS_ERROR_QOS_ENABLED;
3798                if (fcport->cfg.ratelimit != BFA_FALSE)
3799                        return BFA_STATUS_ERROR_TRL_ENABLED;
3800                if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
3801                        (fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
3802                        return BFA_STATUS_ERROR_TRUNK_ENABLED;
3803                if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
3804                        (fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
3805                        return BFA_STATUS_UNSUPP_SPEED;
3806                if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
3807                        return BFA_STATUS_LOOP_UNSUPP_MEZZ;
3808                if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
3809                        return BFA_STATUS_DPORT_ERR;
3810                if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)
3811                        return BFA_STATUS_DPORT_ERR;
3812                break;
3813
3814        case BFA_PORT_TOPOLOGY_AUTO:
3815                break;
3816
3817        default:
3818                return BFA_STATUS_EINVAL;
3819        }
3820
3821        fcport->cfg.topology = topology;
3822        return BFA_STATUS_OK;
3823}
3824
3825/*
3826 * Get current topology.
3827 */
3828enum bfa_port_topology
3829bfa_fcport_get_topology(struct bfa_s *bfa)
3830{
3831        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3832
3833        return fcport->topology;
3834}
3835
3836/*
3837 * Get config topology.
3838 */
3839enum bfa_port_topology
3840bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
3841{
3842        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3843
3844        return fcport->cfg.topology;
3845}
3846
3847bfa_status_t
3848bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
3849{
3850        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3851
3852        bfa_trc(bfa, alpa);
3853        bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3854        bfa_trc(bfa, fcport->cfg.hardalpa);
3855
3856        fcport->cfg.cfg_hardalpa = BFA_TRUE;
3857        fcport->cfg.hardalpa = alpa;
3858
3859        return BFA_STATUS_OK;
3860}
3861
3862bfa_status_t
3863bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
3864{
3865        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3866
3867        bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3868        bfa_trc(bfa, fcport->cfg.hardalpa);
3869
3870        fcport->cfg.cfg_hardalpa = BFA_FALSE;
3871        return BFA_STATUS_OK;
3872}
3873
3874bfa_boolean_t
3875bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
3876{
3877        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3878
3879        *alpa = fcport->cfg.hardalpa;
3880        return fcport->cfg.cfg_hardalpa;
3881}
3882
3883u8
3884bfa_fcport_get_myalpa(struct bfa_s *bfa)
3885{
3886        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3887
3888        return fcport->myalpa;
3889}
3890
3891bfa_status_t
3892bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
3893{
3894        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3895
3896        bfa_trc(bfa, maxfrsize);
3897        bfa_trc(bfa, fcport->cfg.maxfrsize);
3898
3899        /* with in range */
3900        if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
3901                return BFA_STATUS_INVLD_DFSZ;
3902
3903        /* power of 2, if not the max frame size of 2112 */
3904        if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
3905                return BFA_STATUS_INVLD_DFSZ;
3906
3907        fcport->cfg.maxfrsize = maxfrsize;
3908        return BFA_STATUS_OK;
3909}
3910
3911u16
3912bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
3913{
3914        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3915
3916        return fcport->cfg.maxfrsize;
3917}
3918
3919u8
3920bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
3921{
3922        if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
3923                return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
3924
3925        else
3926                return 0;
3927}
3928
3929void
3930bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
3931{
3932        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3933
3934        fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
3935}
3936
3937/*
3938 * Get port attributes.
3939 */
3940
3941wwn_t
3942bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
3943{
3944        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3945        if (node)
3946                return fcport->nwwn;
3947        else
3948                return fcport->pwwn;
3949}
3950
3951void
3952bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
3953{
3954        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3955
3956        memset(attr, 0, sizeof(struct bfa_port_attr_s));
3957
3958        attr->nwwn = fcport->nwwn;
3959        attr->pwwn = fcport->pwwn;
3960
3961        attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn;
3962        attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;
3963
3964        memcpy(&attr->pport_cfg, &fcport->cfg,
3965                sizeof(struct bfa_port_cfg_s));
3966        /* speed attributes */
3967        attr->pport_cfg.speed = fcport->cfg.speed;
3968        attr->speed_supported = fcport->speed_sup;
3969        attr->speed = fcport->speed;
3970        attr->cos_supported = FC_CLASS_3;
3971
3972        /* topology attributes */
3973        attr->pport_cfg.topology = fcport->cfg.topology;
3974        attr->topology = fcport->topology;
3975        attr->pport_cfg.trunked = fcport->cfg.trunked;
3976
3977        /* beacon attributes */
3978        attr->beacon = fcport->beacon;
3979        attr->link_e2e_beacon = fcport->link_e2e_beacon;
3980
3981        attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
3982        attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
3983        attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
3984
3985        attr->fec_state = fcport->fec_state;
3986
3987        /* PBC Disabled State */
3988        if (bfa_fcport_is_pbcdisabled(bfa))
3989                attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;
3990        else {
3991                if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
3992                        attr->port_state = BFA_PORT_ST_IOCDIS;
3993                else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
3994                        attr->port_state = BFA_PORT_ST_FWMISMATCH;
3995        }
3996
3997        /* FCoE vlan */
3998        attr->fcoe_vlan = fcport->fcoe_vlan;
3999}
4000
4001#define BFA_FCPORT_STATS_TOV    1000
4002
4003/*
4004 * Fetch port statistics (FCQoS or FCoE).
4005 */
4006bfa_status_t
4007bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4008{
4009        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4010
4011        if (!bfa_iocfc_is_operational(bfa) ||
4012            !fcport->stats_dma_ready)
4013                return BFA_STATUS_IOC_NON_OP;
4014
4015        if (!list_empty(&fcport->statsclr_pending_q))
4016                return BFA_STATUS_DEVBUSY;
4017
4018        if (list_empty(&fcport->stats_pending_q)) {
4019                list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4020                bfa_fcport_send_stats_get(fcport);
4021                bfa_timer_start(bfa, &fcport->timer,
4022                                bfa_fcport_stats_get_timeout,
4023                                fcport, BFA_FCPORT_STATS_TOV);
4024        } else
4025                list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4026
4027        return BFA_STATUS_OK;
4028}
4029
4030/*
4031 * Reset port statistics (FCQoS or FCoE).
4032 */
4033bfa_status_t
4034bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4035{
4036        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4037
4038        if (!bfa_iocfc_is_operational(bfa) ||
4039            !fcport->stats_dma_ready)
4040                return BFA_STATUS_IOC_NON_OP;
4041
4042        if (!list_empty(&fcport->stats_pending_q))
4043                return BFA_STATUS_DEVBUSY;
4044
4045        if (list_empty(&fcport->statsclr_pending_q)) {
4046                list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4047                bfa_fcport_send_stats_clear(fcport);
4048                bfa_timer_start(bfa, &fcport->timer,
4049                                bfa_fcport_stats_clr_timeout,
4050                                fcport, BFA_FCPORT_STATS_TOV);
4051        } else
4052                list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4053
4054        return BFA_STATUS_OK;
4055}
4056
4057/*
4058 * Fetch port attributes.
4059 */
4060bfa_boolean_t
4061bfa_fcport_is_disabled(struct bfa_s *bfa)
4062{
4063        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4064
4065        return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4066                BFA_PORT_ST_DISABLED;
4067
4068}
4069
4070bfa_boolean_t
4071bfa_fcport_is_dport(struct bfa_s *bfa)
4072{
4073        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4074
4075        return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4076                BFA_PORT_ST_DPORT);
4077}
4078
4079bfa_boolean_t
4080bfa_fcport_is_ddport(struct bfa_s *bfa)
4081{
4082        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4083
4084        return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4085                BFA_PORT_ST_DDPORT);
4086}
4087
4088bfa_status_t
4089bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
4090{
4091        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4092        enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
4093
4094        bfa_trc(bfa, ioc_type);
4095
4096        if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0))
4097                return BFA_STATUS_QOS_BW_INVALID;
4098
4099        if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100)
4100                return BFA_STATUS_QOS_BW_INVALID;
4101
4102        if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) ||
4103            (qos_bw->low > qos_bw->high))
4104                return BFA_STATUS_QOS_BW_INVALID;
4105
4106        if ((ioc_type == BFA_IOC_TYPE_FC) &&
4107            (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP))
4108                fcport->cfg.qos_bw = *qos_bw;
4109
4110        return BFA_STATUS_OK;
4111}
4112
4113bfa_boolean_t
4114bfa_fcport_is_ratelim(struct bfa_s *bfa)
4115{
4116        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4117
4118        return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
4119
4120}
4121
4122/*
4123 *      Enable/Disable FAA feature in port config
4124 */
4125void
4126bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)
4127{
4128        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4129
4130        bfa_trc(bfa, state);
4131        fcport->cfg.faa_state = state;
4132}
4133
4134/*
4135 * Get default minimum ratelim speed
4136 */
4137enum bfa_port_speed
4138bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
4139{
4140        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4141
4142        bfa_trc(bfa, fcport->cfg.trl_def_speed);
4143        return fcport->cfg.trl_def_speed;
4144
4145}
4146
4147void
4148bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
4149                  bfa_boolean_t link_e2e_beacon)
4150{
4151        struct bfa_s *bfa = dev;
4152        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4153
4154        bfa_trc(bfa, beacon);
4155        bfa_trc(bfa, link_e2e_beacon);
4156        bfa_trc(bfa, fcport->beacon);
4157        bfa_trc(bfa, fcport->link_e2e_beacon);
4158
4159        fcport->beacon = beacon;
4160        fcport->link_e2e_beacon = link_e2e_beacon;
4161}
4162
4163bfa_boolean_t
4164bfa_fcport_is_linkup(struct bfa_s *bfa)
4165{
4166        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4167
4168        return  (!fcport->cfg.trunked &&
4169                 bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
4170                (fcport->cfg.trunked &&
4171                 fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
4172}
4173
4174bfa_boolean_t
4175bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
4176{
4177        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4178
4179        return fcport->cfg.qos_enabled;
4180}
4181
4182bfa_boolean_t
4183bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
4184{
4185        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4186
4187        return fcport->cfg.trunked;
4188}
4189
4190bfa_status_t
4191bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)
4192{
4193        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4194
4195        bfa_trc(bfa, on_off);
4196
4197        if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4198                return BFA_STATUS_BBCR_FC_ONLY;
4199
4200        if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) &&
4201                (bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK))
4202                return BFA_STATUS_CMD_NOTSUPP_MEZZ;
4203
4204        if (on_off) {
4205                if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4206                        return BFA_STATUS_TOPOLOGY_LOOP;
4207
4208                if (fcport->cfg.qos_enabled)
4209                        return BFA_STATUS_ERROR_QOS_ENABLED;
4210
4211                if (fcport->cfg.trunked)
4212                        return BFA_STATUS_TRUNK_ENABLED;
4213
4214                if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) &&
4215                        (fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc)))
4216                        return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT;
4217
4218                if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS)
4219                        return BFA_STATUS_FEATURE_NOT_SUPPORTED;
4220
4221                if (fcport->cfg.bb_cr_enabled) {
4222                        if (bb_scn != fcport->cfg.bb_scn)
4223                                return BFA_STATUS_BBCR_CFG_NO_CHANGE;
4224                        else
4225                                return BFA_STATUS_NO_CHANGE;
4226                }
4227
4228                if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX))
4229                        bb_scn = BFA_BB_SCN_DEF;
4230
4231                fcport->cfg.bb_cr_enabled = on_off;
4232                fcport->cfg.bb_scn = bb_scn;
4233        } else {
4234                if (!fcport->cfg.bb_cr_enabled)
4235                        return BFA_STATUS_NO_CHANGE;
4236
4237                fcport->cfg.bb_cr_enabled = on_off;
4238                fcport->cfg.bb_scn = 0;
4239        }
4240
4241        return BFA_STATUS_OK;
4242}
4243
4244bfa_status_t
4245bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
4246                struct bfa_bbcr_attr_s *bbcr_attr)
4247{
4248        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4249
4250        if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4251                return BFA_STATUS_BBCR_FC_ONLY;
4252
4253        if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4254                return BFA_STATUS_TOPOLOGY_LOOP;
4255
4256        *bbcr_attr = fcport->bbcr_attr;
4257
4258        return BFA_STATUS_OK;
4259}
4260
4261void
4262bfa_fcport_dportenable(struct bfa_s *bfa)
4263{
4264        /*
4265         * Assume caller check for port is in disable state
4266         */
4267        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);
4268        bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);
4269}
4270
4271void
4272bfa_fcport_dportdisable(struct bfa_s *bfa)
4273{
4274        /*
4275         * Assume caller check for port is in disable state
4276         */
4277        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);
4278        bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
4279}
4280
4281static void
4282bfa_fcport_ddportenable(struct bfa_s *bfa)
4283{
4284        /*
4285         * Assume caller check for port is in disable state
4286         */
4287        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
4288}
4289
4290static void
4291bfa_fcport_ddportdisable(struct bfa_s *bfa)
4292{
4293        /*
4294         * Assume caller check for port is in disable state
4295         */
4296        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);
4297}
4298
4299/*
4300 * Rport State machine functions
4301 */
4302/*
4303 * Beginning state, only online event expected.
4304 */
4305static void
4306bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
4307{
4308        bfa_trc(rp->bfa, rp->rport_tag);
4309        bfa_trc(rp->bfa, event);
4310
4311        switch (event) {
4312        case BFA_RPORT_SM_CREATE:
4313                bfa_stats(rp, sm_un_cr);
4314                bfa_sm_set_state(rp, bfa_rport_sm_created);
4315                break;
4316
4317        default:
4318                bfa_stats(rp, sm_un_unexp);
4319                bfa_sm_fault(rp->bfa, event);
4320        }
4321}
4322
4323static void
4324bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
4325{
4326        bfa_trc(rp->bfa, rp->rport_tag);
4327        bfa_trc(rp->bfa, event);
4328
4329        switch (event) {
4330        case BFA_RPORT_SM_ONLINE:
4331                bfa_stats(rp, sm_cr_on);
4332                if (bfa_rport_send_fwcreate(rp))
4333                        bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4334                else
4335                        bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4336                break;
4337
4338        case BFA_RPORT_SM_DELETE:
4339                bfa_stats(rp, sm_cr_del);
4340                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4341                bfa_rport_free(rp);
4342                break;
4343
4344        case BFA_RPORT_SM_HWFAIL:
4345                bfa_stats(rp, sm_cr_hwf);
4346                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4347                break;
4348
4349        default:
4350                bfa_stats(rp, sm_cr_unexp);
4351                bfa_sm_fault(rp->bfa, event);
4352        }
4353}
4354
4355/*
4356 * Waiting for rport create response from firmware.
4357 */
4358static void
4359bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
4360{
4361        bfa_trc(rp->bfa, rp->rport_tag);
4362        bfa_trc(rp->bfa, event);
4363
4364        switch (event) {
4365        case BFA_RPORT_SM_FWRSP:
4366                bfa_stats(rp, sm_fwc_rsp);
4367                bfa_sm_set_state(rp, bfa_rport_sm_online);
4368                bfa_rport_online_cb(rp);
4369                break;
4370
4371        case BFA_RPORT_SM_DELETE:
4372                bfa_stats(rp, sm_fwc_del);
4373                bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4374                break;
4375
4376        case BFA_RPORT_SM_OFFLINE:
4377                bfa_stats(rp, sm_fwc_off);
4378                bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
4379                break;
4380
4381        case BFA_RPORT_SM_HWFAIL:
4382                bfa_stats(rp, sm_fwc_hwf);
4383                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4384                break;
4385
4386        default:
4387                bfa_stats(rp, sm_fwc_unexp);
4388                bfa_sm_fault(rp->bfa, event);
4389        }
4390}
4391
4392/*
4393 * Request queue is full, awaiting queue resume to send create request.
4394 */
4395static void
4396bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4397{
4398        bfa_trc(rp->bfa, rp->rport_tag);
4399        bfa_trc(rp->bfa, event);
4400
4401        switch (event) {
4402        case BFA_RPORT_SM_QRESUME:
4403                bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4404                bfa_rport_send_fwcreate(rp);
4405                break;
4406
4407        case BFA_RPORT_SM_DELETE:
4408                bfa_stats(rp, sm_fwc_del);
4409                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4410                bfa_reqq_wcancel(&rp->reqq_wait);
4411                bfa_rport_free(rp);
4412                break;
4413
4414        case BFA_RPORT_SM_OFFLINE:
4415                bfa_stats(rp, sm_fwc_off);
4416                bfa_sm_set_state(rp, bfa_rport_sm_offline);
4417                bfa_reqq_wcancel(&rp->reqq_wait);
4418                bfa_rport_offline_cb(rp);
4419                break;
4420
4421        case BFA_RPORT_SM_HWFAIL:
4422                bfa_stats(rp, sm_fwc_hwf);
4423                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4424                bfa_reqq_wcancel(&rp->reqq_wait);
4425                break;
4426
4427        default:
4428                bfa_stats(rp, sm_fwc_unexp);
4429                bfa_sm_fault(rp->bfa, event);
4430        }