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        struct bfa_plog_rec_s  lp;
 373        u32     *tmp_int = (u32 *) fchdr;
 374        u32     ints[BFA_PL_INT_LOG_SZ];
 375
 376        if (plog->plog_enabled) {
 377                memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
 378
 379                ints[0] = tmp_int[0];
 380                ints[1] = tmp_int[1];
 381                ints[2] = tmp_int[4];
 382
 383                bfa_plog_intarr(plog, mid, event, misc, ints, 3);
 384        }
 385}
 386
 387void
 388bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
 389                      enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
 390                      u32 pld_w0)
 391{
 392        struct bfa_plog_rec_s  lp;
 393        u32     *tmp_int = (u32 *) fchdr;
 394        u32     ints[BFA_PL_INT_LOG_SZ];
 395
 396        if (plog->plog_enabled) {
 397                memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
 398
 399                ints[0] = tmp_int[0];
 400                ints[1] = tmp_int[1];
 401                ints[2] = tmp_int[4];
 402                ints[3] = pld_w0;
 403
 404                bfa_plog_intarr(plog, mid, event, misc, ints, 4);
 405        }
 406}
 407
 408
 409/*
 410 *  fcxp_pvt BFA FCXP private functions
 411 */
 412
 413static void
 414claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
 415{
 416        u16     i;
 417        struct bfa_fcxp_s *fcxp;
 418
 419        fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
 420        memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
 421
 422        INIT_LIST_HEAD(&mod->fcxp_req_free_q);
 423        INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);
 424        INIT_LIST_HEAD(&mod->fcxp_active_q);
 425        INIT_LIST_HEAD(&mod->fcxp_req_unused_q);
 426        INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);
 427
 428        mod->fcxp_list = fcxp;
 429
 430        for (i = 0; i < mod->num_fcxps; i++) {
 431                fcxp->fcxp_mod = mod;
 432                fcxp->fcxp_tag = i;
 433
 434                if (i < (mod->num_fcxps / 2)) {
 435                        list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
 436                        fcxp->req_rsp = BFA_TRUE;
 437                } else {
 438                        list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
 439                        fcxp->req_rsp = BFA_FALSE;
 440                }
 441
 442                bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
 443                fcxp->reqq_waiting = BFA_FALSE;
 444
 445                fcxp = fcxp + 1;
 446        }
 447
 448        bfa_mem_kva_curp(mod) = (void *)fcxp;
 449}
 450
 451void
 452bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
 453                struct bfa_s *bfa)
 454{
 455        struct bfa_fcxp_mod_s *fcxp_mod = BFA_FCXP_MOD(bfa);
 456        struct bfa_mem_kva_s *fcxp_kva = BFA_MEM_FCXP_KVA(bfa);
 457        struct bfa_mem_dma_s *seg_ptr;
 458        u16     nsegs, idx, per_seg_fcxp;
 459        u16     num_fcxps = cfg->fwcfg.num_fcxp_reqs;
 460        u32     per_fcxp_sz;
 461
 462        if (num_fcxps == 0)
 463                return;
 464
 465        if (cfg->drvcfg.min_cfg)
 466                per_fcxp_sz = 2 * BFA_FCXP_MAX_IBUF_SZ;
 467        else
 468                per_fcxp_sz = BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ;
 469
 470        /* dma memory */
 471        nsegs = BFI_MEM_DMA_NSEGS(num_fcxps, per_fcxp_sz);
 472        per_seg_fcxp = BFI_MEM_NREQS_SEG(per_fcxp_sz);
 473
 474        bfa_mem_dma_seg_iter(fcxp_mod, seg_ptr, nsegs, idx) {
 475                if (num_fcxps >= per_seg_fcxp) {
 476                        num_fcxps -= per_seg_fcxp;
 477                        bfa_mem_dma_setup(minfo, seg_ptr,
 478                                per_seg_fcxp * per_fcxp_sz);
 479                } else
 480                        bfa_mem_dma_setup(minfo, seg_ptr,
 481                                num_fcxps * per_fcxp_sz);
 482        }
 483
 484        /* kva memory */
 485        bfa_mem_kva_setup(minfo, fcxp_kva,
 486                cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));
 487}
 488
 489void
 490bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 491                struct bfa_pcidev_s *pcidev)
 492{
 493        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 494
 495        mod->bfa = bfa;
 496        mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
 497
 498        /*
 499         * Initialize FCXP request and response payload sizes.
 500         */
 501        mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
 502        if (!cfg->drvcfg.min_cfg)
 503                mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
 504
 505        INIT_LIST_HEAD(&mod->req_wait_q);
 506        INIT_LIST_HEAD(&mod->rsp_wait_q);
 507
 508        claim_fcxps_mem(mod);
 509}
 510
 511void
 512bfa_fcxp_iocdisable(struct bfa_s *bfa)
 513{
 514        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 515        struct bfa_fcxp_s *fcxp;
 516        struct list_head              *qe, *qen;
 517
 518        /* Enqueue unused fcxp resources to free_q */
 519        list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q);
 520        list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q);
 521
 522        list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
 523                fcxp = (struct bfa_fcxp_s *) qe;
 524                if (fcxp->caller == NULL) {
 525                        fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
 526                                        BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
 527                        bfa_fcxp_free(fcxp);
 528                } else {
 529                        fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
 530                        bfa_cb_queue(bfa, &fcxp->hcb_qe,
 531                                     __bfa_fcxp_send_cbfn, fcxp);
 532                }
 533        }
 534}
 535
 536static struct bfa_fcxp_s *
 537bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)
 538{
 539        struct bfa_fcxp_s *fcxp;
 540
 541        if (req)
 542                bfa_q_deq(&fm->fcxp_req_free_q, &fcxp);
 543        else
 544                bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);
 545
 546        if (fcxp)
 547                list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
 548
 549        return fcxp;
 550}
 551
 552static void
 553bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
 554               struct bfa_s *bfa,
 555               u8 *use_ibuf,
 556               u32 *nr_sgles,
 557               bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
 558               bfa_fcxp_get_sglen_t *r_sglen_cbfn,
 559               struct list_head *r_sgpg_q,
 560               int n_sgles,
 561               bfa_fcxp_get_sgaddr_t sga_cbfn,
 562               bfa_fcxp_get_sglen_t sglen_cbfn)
 563{
 564
 565        WARN_ON(bfa == NULL);
 566
 567        bfa_trc(bfa, fcxp->fcxp_tag);
 568
 569        if (n_sgles == 0) {
 570                *use_ibuf = 1;
 571        } else {
 572                WARN_ON(*sga_cbfn == NULL);
 573                WARN_ON(*sglen_cbfn == NULL);
 574
 575                *use_ibuf = 0;
 576                *r_sga_cbfn = sga_cbfn;
 577                *r_sglen_cbfn = sglen_cbfn;
 578
 579                *nr_sgles = n_sgles;
 580
 581                /*
 582                 * alloc required sgpgs
 583                 */
 584                if (n_sgles > BFI_SGE_INLINE)
 585                        WARN_ON(1);
 586        }
 587
 588}
 589
 590static void
 591bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
 592               void *caller, struct bfa_s *bfa, int nreq_sgles,
 593               int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
 594               bfa_fcxp_get_sglen_t req_sglen_cbfn,
 595               bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
 596               bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
 597{
 598
 599        WARN_ON(bfa == NULL);
 600
 601        bfa_trc(bfa, fcxp->fcxp_tag);
 602
 603        fcxp->caller = caller;
 604
 605        bfa_fcxp_init_reqrsp(fcxp, bfa,
 606                &fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
 607                &fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
 608                nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
 609
 610        bfa_fcxp_init_reqrsp(fcxp, bfa,
 611                &fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
 612                &fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
 613                nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
 614
 615}
 616
 617static void
 618bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
 619{
 620        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 621        struct bfa_fcxp_wqe_s *wqe;
 622
 623        if (fcxp->req_rsp)
 624                bfa_q_deq(&mod->req_wait_q, &wqe);
 625        else
 626                bfa_q_deq(&mod->rsp_wait_q, &wqe);
 627
 628        if (wqe) {
 629                bfa_trc(mod->bfa, fcxp->fcxp_tag);
 630
 631                bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
 632                        wqe->nrsp_sgles, wqe->req_sga_cbfn,
 633                        wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
 634                        wqe->rsp_sglen_cbfn);
 635
 636                wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
 637                return;
 638        }
 639
 640        WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
 641        list_del(&fcxp->qe);
 642
 643        if (fcxp->req_rsp)
 644                list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
 645        else
 646                list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
 647}
 648
 649static void
 650bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
 651                   bfa_status_t req_status, u32 rsp_len,
 652                   u32 resid_len, struct fchs_s *rsp_fchs)
 653{
 654        /* discarded fcxp completion */
 655}
 656
 657static void
 658__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
 659{
 660        struct bfa_fcxp_s *fcxp = cbarg;
 661
 662        if (complete) {
 663                fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
 664                                fcxp->rsp_status, fcxp->rsp_len,
 665                                fcxp->residue_len, &fcxp->rsp_fchs);
 666        } else {
 667                bfa_fcxp_free(fcxp);
 668        }
 669}
 670
 671static void
 672hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
 673{
 674        struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
 675        struct bfa_fcxp_s       *fcxp;
 676        u16             fcxp_tag = be16_to_cpu(fcxp_rsp->fcxp_tag);
 677
 678        bfa_trc(bfa, fcxp_tag);
 679
 680        fcxp_rsp->rsp_len = be32_to_cpu(fcxp_rsp->rsp_len);
 681
 682        /*
 683         * @todo f/w should not set residue to non-0 when everything
 684         *       is received.
 685         */
 686        if (fcxp_rsp->req_status == BFA_STATUS_OK)
 687                fcxp_rsp->residue_len = 0;
 688        else
 689                fcxp_rsp->residue_len = be32_to_cpu(fcxp_rsp->residue_len);
 690
 691        fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
 692
 693        WARN_ON(fcxp->send_cbfn == NULL);
 694
 695        hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
 696
 697        if (fcxp->send_cbfn != NULL) {
 698                bfa_trc(mod->bfa, (NULL == fcxp->caller));
 699                if (fcxp->caller == NULL) {
 700                        fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
 701                                        fcxp_rsp->req_status, fcxp_rsp->rsp_len,
 702                                        fcxp_rsp->residue_len, &fcxp_rsp->fchs);
 703                        /*
 704                         * fcxp automatically freed on return from the callback
 705                         */
 706                        bfa_fcxp_free(fcxp);
 707                } else {
 708                        fcxp->rsp_status = fcxp_rsp->req_status;
 709                        fcxp->rsp_len = fcxp_rsp->rsp_len;
 710                        fcxp->residue_len = fcxp_rsp->residue_len;
 711                        fcxp->rsp_fchs = fcxp_rsp->fchs;
 712
 713                        bfa_cb_queue(bfa, &fcxp->hcb_qe,
 714                                        __bfa_fcxp_send_cbfn, fcxp);
 715                }
 716        } else {
 717                bfa_trc(bfa, (NULL == fcxp->send_cbfn));
 718        }
 719}
 720
 721static void
 722hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
 723                 struct fchs_s *fchs)
 724{
 725        /*
 726         * TODO: TX ox_id
 727         */
 728        if (reqlen > 0) {
 729                if (fcxp->use_ireqbuf) {
 730                        u32     pld_w0 =
 731                                *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
 732
 733                        bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
 734                                        BFA_PL_EID_TX,
 735                                        reqlen + sizeof(struct fchs_s), fchs,
 736                                        pld_w0);
 737                } else {
 738                        bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
 739                                        BFA_PL_EID_TX,
 740                                        reqlen + sizeof(struct fchs_s),
 741                                        fchs);
 742                }
 743        } else {
 744                bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
 745                               reqlen + sizeof(struct fchs_s), fchs);
 746        }
 747}
 748
 749static void
 750hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
 751                 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
 752{
 753        if (fcxp_rsp->rsp_len > 0) {
 754                if (fcxp->use_irspbuf) {
 755                        u32     pld_w0 =
 756                                *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
 757
 758                        bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
 759                                              BFA_PL_EID_RX,
 760                                              (u16) fcxp_rsp->rsp_len,
 761                                              &fcxp_rsp->fchs, pld_w0);
 762                } else {
 763                        bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
 764                                       BFA_PL_EID_RX,
 765                                       (u16) fcxp_rsp->rsp_len,
 766                                       &fcxp_rsp->fchs);
 767                }
 768        } else {
 769                bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
 770                               (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
 771        }
 772}
 773
 774/*
 775 * Handler to resume sending fcxp when space in available in cpe queue.
 776 */
 777static void
 778bfa_fcxp_qresume(void *cbarg)
 779{
 780        struct bfa_fcxp_s               *fcxp = cbarg;
 781        struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
 782        struct bfi_fcxp_send_req_s      *send_req;
 783
 784        fcxp->reqq_waiting = BFA_FALSE;
 785        send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
 786        bfa_fcxp_queue(fcxp, send_req);
 787}
 788
 789/*
 790 * Queue fcxp send request to foimrware.
 791 */
 792static void
 793bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
 794{
 795        struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
 796        struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
 797        struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
 798        struct bfa_rport_s              *rport = reqi->bfa_rport;
 799
 800        bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
 801                    bfa_fn_lpu(bfa));
 802
 803        send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);
 804        if (rport) {
 805                send_req->rport_fw_hndl = rport->fw_handle;
 806                send_req->max_frmsz = cpu_to_be16(rport->rport_info.max_frmsz);
 807                if (send_req->max_frmsz == 0)
 808                        send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
 809        } else {
 810                send_req->rport_fw_hndl = 0;
 811                send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
 812        }
 813
 814        send_req->vf_id = cpu_to_be16(reqi->vf_id);
 815        send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);
 816        send_req->class = reqi->class;
 817        send_req->rsp_timeout = rspi->rsp_timeout;
 818        send_req->cts = reqi->cts;
 819        send_req->fchs = reqi->fchs;
 820
 821        send_req->req_len = cpu_to_be32(reqi->req_tot_len);
 822        send_req->rsp_maxlen = cpu_to_be32(rspi->rsp_maxlen);
 823
 824        /*
 825         * setup req sgles
 826         */
 827        if (fcxp->use_ireqbuf == 1) {
 828                bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
 829                                        BFA_FCXP_REQ_PLD_PA(fcxp));
 830        } else {
 831                if (fcxp->nreq_sgles > 0) {
 832                        WARN_ON(fcxp->nreq_sgles != 1);
 833                        bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
 834                                fcxp->req_sga_cbfn(fcxp->caller, 0));
 835                } else {
 836                        WARN_ON(reqi->req_tot_len != 0);
 837                        bfa_alen_set(&send_req->rsp_alen, 0, 0);
 838                }
 839        }
 840
 841        /*
 842         * setup rsp sgles
 843         */
 844        if (fcxp->use_irspbuf == 1) {
 845                WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
 846
 847                bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
 848                                        BFA_FCXP_RSP_PLD_PA(fcxp));
 849        } else {
 850                if (fcxp->nrsp_sgles > 0) {
 851                        WARN_ON(fcxp->nrsp_sgles != 1);
 852                        bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
 853                                fcxp->rsp_sga_cbfn(fcxp->caller, 0));
 854
 855                } else {
 856                        WARN_ON(rspi->rsp_maxlen != 0);
 857                        bfa_alen_set(&send_req->rsp_alen, 0, 0);
 858                }
 859        }
 860
 861        hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
 862
 863        bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);
 864
 865        bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
 866        bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
 867}
 868
 869/*
 870 * Allocate an FCXP instance to send a response or to send a request
 871 * that has a response. Request/response buffers are allocated by caller.
 872 *
 873 * @param[in]   bfa             BFA bfa instance
 874 * @param[in]   nreq_sgles      Number of SG elements required for request
 875 *                              buffer. 0, if fcxp internal buffers are used.
 876 *                              Use bfa_fcxp_get_reqbuf() to get the
 877 *                              internal req buffer.
 878 * @param[in]   req_sgles       SG elements describing request buffer. Will be
 879 *                              copied in by BFA and hence can be freed on
 880 *                              return from this function.
 881 * @param[in]   get_req_sga     function ptr to be called to get a request SG
 882 *                              Address (given the sge index).
 883 * @param[in]   get_req_sglen   function ptr to be called to get a request SG
 884 *                              len (given the sge index).
 885 * @param[in]   get_rsp_sga     function ptr to be called to get a response SG
 886 *                              Address (given the sge index).
 887 * @param[in]   get_rsp_sglen   function ptr to be called to get a response SG
 888 *                              len (given the sge index).
 889 * @param[in]   req             Allocated FCXP is used to send req or rsp?
 890 *                              request - BFA_TRUE, response - BFA_FALSE
 891 *
 892 * @return FCXP instance. NULL on failure.
 893 */
 894struct bfa_fcxp_s *
 895bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
 896                int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
 897                bfa_fcxp_get_sglen_t req_sglen_cbfn,
 898                bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
 899                bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
 900{
 901        struct bfa_fcxp_s *fcxp = NULL;
 902
 903        WARN_ON(bfa == NULL);
 904
 905        fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);
 906        if (fcxp == NULL)
 907                return NULL;
 908
 909        bfa_trc(bfa, fcxp->fcxp_tag);
 910
 911        bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
 912                        req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
 913
 914        return fcxp;
 915}
 916
 917/*
 918 * Get the internal request buffer pointer
 919 *
 920 * @param[in]   fcxp    BFA fcxp pointer
 921 *
 922 * @return              pointer to the internal request buffer
 923 */
 924void *
 925bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
 926{
 927        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 928        void    *reqbuf;
 929
 930        WARN_ON(fcxp->use_ireqbuf != 1);
 931        reqbuf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
 932                                mod->req_pld_sz + mod->rsp_pld_sz);
 933        return reqbuf;
 934}
 935
 936u32
 937bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
 938{
 939        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 940
 941        return mod->req_pld_sz;
 942}
 943
 944/*
 945 * Get the internal response buffer pointer
 946 *
 947 * @param[in]   fcxp    BFA fcxp pointer
 948 *
 949 * @return              pointer to the internal request buffer
 950 */
 951void *
 952bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
 953{
 954        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 955        void    *fcxp_buf;
 956
 957        WARN_ON(fcxp->use_irspbuf != 1);
 958
 959        fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
 960                                mod->req_pld_sz + mod->rsp_pld_sz);
 961
 962        /* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
 963        return ((u8 *) fcxp_buf) + mod->req_pld_sz;
 964}
 965
 966/*
 967 * Free the BFA FCXP
 968 *
 969 * @param[in]   fcxp                    BFA fcxp pointer
 970 *
 971 * @return              void
 972 */
 973void
 974bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
 975{
 976        struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 977
 978        WARN_ON(fcxp == NULL);
 979        bfa_trc(mod->bfa, fcxp->fcxp_tag);
 980        bfa_fcxp_put(fcxp);
 981}
 982
 983/*
 984 * Send a FCXP request
 985 *
 986 * @param[in]   fcxp    BFA fcxp pointer
 987 * @param[in]   rport   BFA rport pointer. Could be left NULL for WKA rports
 988 * @param[in]   vf_id   virtual Fabric ID
 989 * @param[in]   lp_tag  lport tag
 990 * @param[in]   cts     use Continuous sequence
 991 * @param[in]   cos     fc Class of Service
 992 * @param[in]   reqlen  request length, does not include FCHS length
 993 * @param[in]   fchs    fc Header Pointer. The header content will be copied
 994 *                      in by BFA.
 995 *
 996 * @param[in]   cbfn    call back function to be called on receiving
 997 *                                                              the response
 998 * @param[in]   cbarg   arg for cbfn
 999 * @param[in]   rsp_timeout
1000 *                      response timeout
1001 *
1002 * @return              bfa_status_t
1003 */
1004void
1005bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
1006              u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
1007              u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
1008              void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
1009{
1010        struct bfa_s                    *bfa  = fcxp->fcxp_mod->bfa;
1011        struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
1012        struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
1013        struct bfi_fcxp_send_req_s      *send_req;
1014
1015        bfa_trc(bfa, fcxp->fcxp_tag);
1016
1017        /*
1018         * setup request/response info
1019         */
1020        reqi->bfa_rport = rport;
1021        reqi->vf_id = vf_id;
1022        reqi->lp_tag = lp_tag;
1023        reqi->class = cos;
1024        rspi->rsp_timeout = rsp_timeout;
1025        reqi->cts = cts;
1026        reqi->fchs = *fchs;
1027        reqi->req_tot_len = reqlen;
1028        rspi->rsp_maxlen = rsp_maxlen;
1029        fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
1030        fcxp->send_cbarg = cbarg;
1031
1032        /*
1033         * If no room in CPE queue, wait for space in request queue
1034         */
1035        send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
1036        if (!send_req) {
1037                bfa_trc(bfa, fcxp->fcxp_tag);
1038                fcxp->reqq_waiting = BFA_TRUE;
1039                bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
1040                return;
1041        }
1042
1043        bfa_fcxp_queue(fcxp, send_req);
1044}
1045
1046/*
1047 * Abort a BFA FCXP
1048 *
1049 * @param[in]   fcxp    BFA fcxp pointer
1050 *
1051 * @return              void
1052 */
1053bfa_status_t
1054bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
1055{
1056        bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
1057        WARN_ON(1);
1058        return BFA_STATUS_OK;
1059}
1060
1061void
1062bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1063               bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
1064               void *caller, int nreq_sgles,
1065               int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
1066               bfa_fcxp_get_sglen_t req_sglen_cbfn,
1067               bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
1068               bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
1069{
1070        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1071
1072        if (req)
1073                WARN_ON(!list_empty(&mod->fcxp_req_free_q));
1074        else
1075                WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));
1076
1077        wqe->alloc_cbfn = alloc_cbfn;
1078        wqe->alloc_cbarg = alloc_cbarg;
1079        wqe->caller = caller;
1080        wqe->bfa = bfa;
1081        wqe->nreq_sgles = nreq_sgles;
1082        wqe->nrsp_sgles = nrsp_sgles;
1083        wqe->req_sga_cbfn = req_sga_cbfn;
1084        wqe->req_sglen_cbfn = req_sglen_cbfn;
1085        wqe->rsp_sga_cbfn = rsp_sga_cbfn;
1086        wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
1087
1088        if (req)
1089                list_add_tail(&wqe->qe, &mod->req_wait_q);
1090        else
1091                list_add_tail(&wqe->qe, &mod->rsp_wait_q);
1092}
1093
1094void
1095bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
1096{
1097        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1098
1099        WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||
1100                !bfa_q_is_on_q(&mod->rsp_wait_q, wqe));
1101        list_del(&wqe->qe);
1102}
1103
1104void
1105bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
1106{
1107        /*
1108         * If waiting for room in request queue, cancel reqq wait
1109         * and free fcxp.
1110         */
1111        if (fcxp->reqq_waiting) {
1112                fcxp->reqq_waiting = BFA_FALSE;
1113                bfa_reqq_wcancel(&fcxp->reqq_wqe);
1114                bfa_fcxp_free(fcxp);
1115                return;
1116        }
1117
1118        fcxp->send_cbfn = bfa_fcxp_null_comp;
1119}
1120
1121void
1122bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
1123{
1124        switch (msg->mhdr.msg_id) {
1125        case BFI_FCXP_I2H_SEND_RSP:
1126                hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
1127                break;
1128
1129        default:
1130                bfa_trc(bfa, msg->mhdr.msg_id);
1131                WARN_ON(1);
1132        }
1133}
1134
1135u32
1136bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
1137{
1138        struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1139
1140        return mod->rsp_pld_sz;
1141}
1142
1143void
1144bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
1145{
1146        struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
1147        struct list_head        *qe;
1148        int     i;
1149
1150        for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
1151                if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {
1152                        bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);
1153                        list_add_tail(qe, &mod->fcxp_req_unused_q);
1154                } else {
1155                        bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);
1156                        list_add_tail(qe, &mod->fcxp_rsp_unused_q);
1157                }
1158        }
1159}
1160
1161/*
1162 *  BFA LPS state machine functions
1163 */
1164
1165/*
1166 * Init state -- no login
1167 */
1168static void
1169bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
1170{
1171        bfa_trc(lps->bfa, lps->bfa_tag);
1172        bfa_trc(lps->bfa, event);
1173
1174        switch (event) {
1175        case BFA_LPS_SM_LOGIN:
1176                if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1177                        bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
1178                        bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1179                } else {
1180                        bfa_sm_set_state(lps, bfa_lps_sm_login);
1181                        bfa_lps_send_login(lps);
1182                }
1183
1184                if (lps->fdisc)
1185                        bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1186                                BFA_PL_EID_LOGIN, 0, "FDISC Request");
1187                else
1188                        bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1189                                BFA_PL_EID_LOGIN, 0, "FLOGI Request");
1190                break;
1191
1192        case BFA_LPS_SM_LOGOUT:
1193                bfa_lps_logout_comp(lps);
1194                break;
1195
1196        case BFA_LPS_SM_DELETE:
1197                bfa_lps_free(lps);
1198                break;
1199
1200        case BFA_LPS_SM_RX_CVL:
1201        case BFA_LPS_SM_OFFLINE:
1202                break;
1203
1204        case BFA_LPS_SM_FWRSP:
1205                /*
1206                 * Could happen when fabric detects loopback and discards
1207                 * the lps request. Fw will eventually sent out the timeout
1208                 * Just ignore
1209                 */
1210                break;
1211        case BFA_LPS_SM_SET_N2N_PID:
1212                /*
1213                 * When topology is set to loop, bfa_lps_set_n2n_pid() sends
1214                 * this event. Ignore this event.
1215                 */
1216                break;
1217
1218        default:
1219                bfa_sm_fault(lps->bfa, event);
1220        }
1221}
1222
1223/*
1224 * login is in progress -- awaiting response from firmware
1225 */
1226static void
1227bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
1228{
1229        bfa_trc(lps->bfa, lps->bfa_tag);
1230        bfa_trc(lps->bfa, event);
1231
1232        switch (event) {
1233        case BFA_LPS_SM_FWRSP:
1234                if (lps->status == BFA_STATUS_OK) {
1235                        bfa_sm_set_state(lps, bfa_lps_sm_online);
1236                        if (lps->fdisc)
1237                                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1238                                        BFA_PL_EID_LOGIN, 0, "FDISC Accept");
1239                        else
1240                                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1241                                        BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
1242                        /* If N2N, send the assigned PID to FW */
1243                        bfa_trc(lps->bfa, lps->fport);
1244                        bfa_trc(lps->bfa, lps->lp_pid);
1245
1246                        if (!lps->fport && lps->lp_pid)
1247                                bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1248                } else {
1249                        bfa_sm_set_state(lps, bfa_lps_sm_init);
1250                        if (lps->fdisc)
1251                                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1252                                        BFA_PL_EID_LOGIN, 0,
1253                                        "FDISC Fail (RJT or timeout)");
1254                        else
1255                                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1256                                        BFA_PL_EID_LOGIN, 0,
1257                                        "FLOGI Fail (RJT or timeout)");
1258                }
1259                bfa_lps_login_comp(lps);
1260                break;
1261
1262        case BFA_LPS_SM_OFFLINE:
1263        case BFA_LPS_SM_DELETE:
1264                bfa_sm_set_state(lps, bfa_lps_sm_init);
1265                break;
1266
1267        case BFA_LPS_SM_SET_N2N_PID:
1268                bfa_trc(lps->bfa, lps->fport);
1269                bfa_trc(lps->bfa, lps->lp_pid);
1270                break;
1271
1272        default:
1273                bfa_sm_fault(lps->bfa, event);
1274        }
1275}
1276
1277/*
1278 * login pending - awaiting space in request queue
1279 */
1280static void
1281bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1282{
1283        bfa_trc(lps->bfa, lps->bfa_tag);
1284        bfa_trc(lps->bfa, event);
1285
1286        switch (event) {
1287        case BFA_LPS_SM_RESUME:
1288                bfa_sm_set_state(lps, bfa_lps_sm_login);
1289                bfa_lps_send_login(lps);
1290                break;
1291
1292        case BFA_LPS_SM_OFFLINE:
1293        case BFA_LPS_SM_DELETE:
1294                bfa_sm_set_state(lps, bfa_lps_sm_init);
1295                bfa_reqq_wcancel(&lps->wqe);
1296                break;
1297
1298        case BFA_LPS_SM_RX_CVL:
1299                /*
1300                 * Login was not even sent out; so when getting out
1301                 * of this state, it will appear like a login retry
1302                 * after Clear virtual link
1303                 */
1304                break;
1305
1306        default:
1307                bfa_sm_fault(lps->bfa, event);
1308        }
1309}
1310
1311/*
1312 * login complete
1313 */
1314static void
1315bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
1316{
1317        bfa_trc(lps->bfa, lps->bfa_tag);
1318        bfa_trc(lps->bfa, event);
1319
1320        switch (event) {
1321        case BFA_LPS_SM_LOGOUT:
1322                if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1323                        bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1324                        bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1325                } else {
1326                        bfa_sm_set_state(lps, bfa_lps_sm_logout);
1327                        bfa_lps_send_logout(lps);
1328                }
1329                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1330                        BFA_PL_EID_LOGO, 0, "Logout");
1331                break;
1332
1333        case BFA_LPS_SM_RX_CVL:
1334                bfa_sm_set_state(lps, bfa_lps_sm_init);
1335
1336                /* Let the vport module know about this event */
1337                bfa_lps_cvl_event(lps);
1338                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1339                        BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1340                break;
1341
1342        case BFA_LPS_SM_SET_N2N_PID:
1343                if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1344                        bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
1345                        bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1346                } else
1347                        bfa_lps_send_set_n2n_pid(lps);
1348                break;
1349
1350        case BFA_LPS_SM_OFFLINE:
1351        case BFA_LPS_SM_DELETE:
1352                bfa_sm_set_state(lps, bfa_lps_sm_init);
1353                break;
1354
1355        default:
1356                bfa_sm_fault(lps->bfa, event);
1357        }
1358}
1359
1360/*
1361 * login complete
1362 */
1363static void
1364bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1365{
1366        bfa_trc(lps->bfa, lps->bfa_tag);
1367        bfa_trc(lps->bfa, event);
1368
1369        switch (event) {
1370        case BFA_LPS_SM_RESUME:
1371                bfa_sm_set_state(lps, bfa_lps_sm_online);
1372                bfa_lps_send_set_n2n_pid(lps);
1373                break;
1374
1375        case BFA_LPS_SM_LOGOUT:
1376                bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1377                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1378                        BFA_PL_EID_LOGO, 0, "Logout");
1379                break;
1380
1381        case BFA_LPS_SM_RX_CVL:
1382                bfa_sm_set_state(lps, bfa_lps_sm_init);
1383                bfa_reqq_wcancel(&lps->wqe);
1384
1385                /* Let the vport module know about this event */
1386                bfa_lps_cvl_event(lps);
1387                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1388                        BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1389                break;
1390
1391        case BFA_LPS_SM_OFFLINE:
1392        case BFA_LPS_SM_DELETE:
1393                bfa_sm_set_state(lps, bfa_lps_sm_init);
1394                bfa_reqq_wcancel(&lps->wqe);
1395                break;
1396
1397        default:
1398                bfa_sm_fault(lps->bfa, event);
1399        }
1400}
1401
1402/*
1403 * logout in progress - awaiting firmware response
1404 */
1405static void
1406bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1407{
1408        bfa_trc(lps->bfa, lps->bfa_tag);
1409        bfa_trc(lps->bfa, event);
1410
1411        switch (event) {
1412        case BFA_LPS_SM_FWRSP:
1413        case BFA_LPS_SM_OFFLINE:
1414                bfa_sm_set_state(lps, bfa_lps_sm_init);
1415                bfa_lps_logout_comp(lps);
1416                break;
1417
1418        case BFA_LPS_SM_DELETE:
1419                bfa_sm_set_state(lps, bfa_lps_sm_init);
1420                break;
1421
1422        default:
1423                bfa_sm_fault(lps->bfa, event);
1424        }
1425}
1426
1427/*
1428 * logout pending -- awaiting space in request queue
1429 */
1430static void
1431bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1432{
1433        bfa_trc(lps->bfa, lps->bfa_tag);
1434        bfa_trc(lps->bfa, event);
1435
1436        switch (event) {
1437        case BFA_LPS_SM_RESUME:
1438                bfa_sm_set_state(lps, bfa_lps_sm_logout);
1439                bfa_lps_send_logout(lps);
1440                break;
1441
1442        case BFA_LPS_SM_OFFLINE:
1443        case BFA_LPS_SM_DELETE:
1444                bfa_sm_set_state(lps, bfa_lps_sm_init);
1445                bfa_reqq_wcancel(&lps->wqe);
1446                break;
1447
1448        default:
1449                bfa_sm_fault(lps->bfa, event);
1450        }
1451}
1452
1453
1454
1455/*
1456 *  lps_pvt BFA LPS private functions
1457 */
1458
1459/*
1460 * return memory requirement
1461 */
1462void
1463bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
1464                struct bfa_s *bfa)
1465{
1466        struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa);
1467
1468        if (cfg->drvcfg.min_cfg)
1469                bfa_mem_kva_setup(minfo, lps_kva,
1470                        sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);
1471        else
1472                bfa_mem_kva_setup(minfo, lps_kva,
1473                        sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);
1474}
1475
1476/*
1477 * bfa module attach at initialization time
1478 */
1479void
1480bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1481        struct bfa_pcidev_s *pcidev)
1482{
1483        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1484        struct bfa_lps_s        *lps;
1485        int                     i;
1486
1487        mod->num_lps = BFA_LPS_MAX_LPORTS;
1488        if (cfg->drvcfg.min_cfg)
1489                mod->num_lps = BFA_LPS_MIN_LPORTS;
1490        else
1491                mod->num_lps = BFA_LPS_MAX_LPORTS;
1492        mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod);
1493
1494        bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);
1495
1496        INIT_LIST_HEAD(&mod->lps_free_q);
1497        INIT_LIST_HEAD(&mod->lps_active_q);
1498        INIT_LIST_HEAD(&mod->lps_login_q);
1499
1500        for (i = 0; i < mod->num_lps; i++, lps++) {
1501                lps->bfa        = bfa;
1502                lps->bfa_tag    = (u8) i;
1503                lps->reqq       = BFA_REQQ_LPS;
1504                bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
1505                list_add_tail(&lps->qe, &mod->lps_free_q);
1506        }
1507}
1508
1509/*
1510 * IOC in disabled state -- consider all lps offline
1511 */
1512void
1513bfa_lps_iocdisable(struct bfa_s *bfa)
1514{
1515        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1516        struct bfa_lps_s        *lps;
1517        struct list_head                *qe, *qen;
1518
1519        list_for_each_safe(qe, qen, &mod->lps_active_q) {
1520                lps = (struct bfa_lps_s *) qe;
1521                bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1522        }
1523        list_for_each_safe(qe, qen, &mod->lps_login_q) {
1524                lps = (struct bfa_lps_s *) qe;
1525                bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1526        }
1527        list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);
1528}
1529
1530/*
1531 * Firmware login response
1532 */
1533static void
1534bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
1535{
1536        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1537        struct bfa_lps_s        *lps;
1538
1539        WARN_ON(rsp->bfa_tag >= mod->num_lps);
1540        lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1541
1542        lps->status = rsp->status;
1543        switch (rsp->status) {
1544        case BFA_STATUS_OK:
1545                lps->fw_tag     = rsp->fw_tag;
1546                lps->fport      = rsp->f_port;
1547                if (lps->fport)
1548                        lps->lp_pid = rsp->lp_pid;
1549                lps->npiv_en    = rsp->npiv_en;
1550                lps->pr_bbcred  = be16_to_cpu(rsp->bb_credit);
1551                lps->pr_pwwn    = rsp->port_name;
1552                lps->pr_nwwn    = rsp->node_name;
1553                lps->auth_req   = rsp->auth_req;
1554                lps->lp_mac     = rsp->lp_mac;
1555                lps->brcd_switch = rsp->brcd_switch;
1556                lps->fcf_mac    = rsp->fcf_mac;
1557
1558                break;
1559
1560        case BFA_STATUS_FABRIC_RJT:
1561                lps->lsrjt_rsn = rsp->lsrjt_rsn;
1562                lps->lsrjt_expl = rsp->lsrjt_expl;
1563
1564                break;
1565
1566        case BFA_STATUS_EPROTOCOL:
1567                lps->ext_status = rsp->ext_status;
1568
1569                break;
1570
1571        case BFA_STATUS_VPORT_MAX:
1572                if (rsp->ext_status)
1573                        bfa_lps_no_res(lps, rsp->ext_status);
1574                break;
1575
1576        default:
1577                /* Nothing to do with other status */
1578                break;
1579        }
1580
1581        list_del(&lps->qe);
1582        list_add_tail(&lps->qe, &mod->lps_active_q);
1583        bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1584}
1585
1586static void
1587bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)
1588{
1589        struct bfa_s            *bfa = first_lps->bfa;
1590        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1591        struct list_head        *qe, *qe_next;
1592        struct bfa_lps_s        *lps;
1593
1594        bfa_trc(bfa, count);
1595
1596        qe = bfa_q_next(first_lps);
1597
1598        while (count && qe) {
1599                qe_next = bfa_q_next(qe);
1600                lps = (struct bfa_lps_s *)qe;
1601                bfa_trc(bfa, lps->bfa_tag);
1602                lps->status = first_lps->status;
1603                list_del(&lps->qe);
1604                list_add_tail(&lps->qe, &mod->lps_active_q);
1605                bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1606                qe = qe_next;
1607                count--;
1608        }
1609}
1610
1611/*
1612 * Firmware logout response
1613 */
1614static void
1615bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
1616{
1617        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1618        struct bfa_lps_s        *lps;
1619
1620        WARN_ON(rsp->bfa_tag >= mod->num_lps);
1621        lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1622
1623        bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1624}
1625
1626/*
1627 * Firmware received a Clear virtual link request (for FCoE)
1628 */
1629static void
1630bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
1631{
1632        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1633        struct bfa_lps_s        *lps;
1634
1635        lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);
1636
1637        bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
1638}
1639
1640/*
1641 * Space is available in request queue, resume queueing request to firmware.
1642 */
1643static void
1644bfa_lps_reqq_resume(void *lps_arg)
1645{
1646        struct bfa_lps_s        *lps = lps_arg;
1647
1648        bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
1649}
1650
1651/*
1652 * lps is freed -- triggered by vport delete
1653 */
1654static void
1655bfa_lps_free(struct bfa_lps_s *lps)
1656{
1657        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(lps->bfa);
1658
1659        lps->lp_pid = 0;
1660        list_del(&lps->qe);
1661        list_add_tail(&lps->qe, &mod->lps_free_q);
1662}
1663
1664/*
1665 * send login request to firmware
1666 */
1667static void
1668bfa_lps_send_login(struct bfa_lps_s *lps)
1669{
1670        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(lps->bfa);
1671        struct bfi_lps_login_req_s      *m;
1672
1673        m = bfa_reqq_next(lps->bfa, lps->reqq);
1674        WARN_ON(!m);
1675
1676        bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
1677                bfa_fn_lpu(lps->bfa));
1678
1679        m->bfa_tag      = lps->bfa_tag;
1680        m->alpa         = lps->alpa;
1681        m->pdu_size     = cpu_to_be16(lps->pdusz);
1682        m->pwwn         = lps->pwwn;
1683        m->nwwn         = lps->nwwn;
1684        m->fdisc        = lps->fdisc;
1685        m->auth_en      = lps->auth_en;
1686
1687        bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1688        list_del(&lps->qe);
1689        list_add_tail(&lps->qe, &mod->lps_login_q);
1690}
1691
1692/*
1693 * send logout request to firmware
1694 */
1695static void
1696bfa_lps_send_logout(struct bfa_lps_s *lps)
1697{
1698        struct bfi_lps_logout_req_s *m;
1699
1700        m = bfa_reqq_next(lps->bfa, lps->reqq);
1701        WARN_ON(!m);
1702
1703        bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
1704                bfa_fn_lpu(lps->bfa));
1705
1706        m->fw_tag = lps->fw_tag;
1707        m->port_name = lps->pwwn;
1708        bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1709}
1710
1711/*
1712 * send n2n pid set request to firmware
1713 */
1714static void
1715bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
1716{
1717        struct bfi_lps_n2n_pid_req_s *m;
1718
1719        m = bfa_reqq_next(lps->bfa, lps->reqq);
1720        WARN_ON(!m);
1721
1722        bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
1723                bfa_fn_lpu(lps->bfa));
1724
1725        m->fw_tag = lps->fw_tag;
1726        m->lp_pid = lps->lp_pid;
1727        bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1728}
1729
1730/*
1731 * Indirect login completion handler for non-fcs
1732 */
1733static void
1734bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
1735{
1736        struct bfa_lps_s *lps   = arg;
1737
1738        if (!complete)
1739                return;
1740
1741        if (lps->fdisc)
1742                bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1743        else
1744                bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1745}
1746
1747/*
1748 * Login completion handler -- direct call for fcs, queue for others
1749 */
1750static void
1751bfa_lps_login_comp(struct bfa_lps_s *lps)
1752{
1753        if (!lps->bfa->fcs) {
1754                bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
1755                        lps);
1756                return;
1757        }
1758
1759        if (lps->fdisc)
1760                bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1761        else
1762                bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1763}
1764
1765/*
1766 * Indirect logout completion handler for non-fcs
1767 */
1768static void
1769bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
1770{
1771        struct bfa_lps_s *lps   = arg;
1772
1773        if (!complete)
1774                return;
1775
1776        if (lps->fdisc)
1777                bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1778        else
1779                bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
1780}
1781
1782/*
1783 * Logout completion handler -- direct call for fcs, queue for others
1784 */
1785static void
1786bfa_lps_logout_comp(struct bfa_lps_s *lps)
1787{
1788        if (!lps->bfa->fcs) {
1789                bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
1790                        lps);
1791                return;
1792        }
1793        if (lps->fdisc)
1794                bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1795}
1796
1797/*
1798 * Clear virtual link completion handler for non-fcs
1799 */
1800static void
1801bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
1802{
1803        struct bfa_lps_s *lps   = arg;
1804
1805        if (!complete)
1806                return;
1807
1808        /* Clear virtual link to base port will result in link down */
1809        if (lps->fdisc)
1810                bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1811}
1812
1813/*
1814 * Received Clear virtual link event --direct call for fcs,
1815 * queue for others
1816 */
1817static void
1818bfa_lps_cvl_event(struct bfa_lps_s *lps)
1819{
1820        if (!lps->bfa->fcs) {
1821                bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
1822                        lps);
1823                return;
1824        }
1825
1826        /* Clear virtual link to base port will result in link down */
1827        if (lps->fdisc)
1828                bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1829}
1830
1831
1832
1833/*
1834 *  lps_public BFA LPS public functions
1835 */
1836
1837u32
1838bfa_lps_get_max_vport(struct bfa_s *bfa)
1839{
1840        if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
1841                return BFA_LPS_MAX_VPORTS_SUPP_CT;
1842        else
1843                return BFA_LPS_MAX_VPORTS_SUPP_CB;
1844}
1845
1846/*
1847 * Allocate a lport srvice tag.
1848 */
1849struct bfa_lps_s  *
1850bfa_lps_alloc(struct bfa_s *bfa)
1851{
1852        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1853        struct bfa_lps_s        *lps = NULL;
1854
1855        bfa_q_deq(&mod->lps_free_q, &lps);
1856
1857        if (lps == NULL)
1858                return NULL;
1859
1860        list_add_tail(&lps->qe, &mod->lps_active_q);
1861
1862        bfa_sm_set_state(lps, bfa_lps_sm_init);
1863        return lps;
1864}
1865
1866/*
1867 * Free lport service tag. This can be called anytime after an alloc.
1868 * No need to wait for any pending login/logout completions.
1869 */
1870void
1871bfa_lps_delete(struct bfa_lps_s *lps)
1872{
1873        bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
1874}
1875
1876/*
1877 * Initiate a lport login.
1878 */
1879void
1880bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
1881        wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
1882{
1883        lps->uarg       = uarg;
1884        lps->alpa       = alpa;
1885        lps->pdusz      = pdusz;
1886        lps->pwwn       = pwwn;
1887        lps->nwwn       = nwwn;
1888        lps->fdisc      = BFA_FALSE;
1889        lps->auth_en    = auth_en;
1890        bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1891}
1892
1893/*
1894 * Initiate a lport fdisc login.
1895 */
1896void
1897bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
1898        wwn_t nwwn)
1899{
1900        lps->uarg       = uarg;
1901        lps->alpa       = 0;
1902        lps->pdusz      = pdusz;
1903        lps->pwwn       = pwwn;
1904        lps->nwwn       = nwwn;
1905        lps->fdisc      = BFA_TRUE;
1906        lps->auth_en    = BFA_FALSE;
1907        bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1908}
1909
1910
1911/*
1912 * Initiate a lport FDSIC logout.
1913 */
1914void
1915bfa_lps_fdisclogo(struct bfa_lps_s *lps)
1916{
1917        bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
1918}
1919
1920u8
1921bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)
1922{
1923        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1924
1925        return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;
1926}
1927
1928/*
1929 * Return lport services tag given the pid
1930 */
1931u8
1932bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
1933{
1934        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1935        struct bfa_lps_s        *lps;
1936        int                     i;
1937
1938        for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
1939                if (lps->lp_pid == pid)
1940                        return lps->bfa_tag;
1941        }
1942
1943        /* Return base port tag anyway */
1944        return 0;
1945}
1946
1947
1948/*
1949 * return port id assigned to the base lport
1950 */
1951u32
1952bfa_lps_get_base_pid(struct bfa_s *bfa)
1953{
1954        struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1955
1956        return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
1957}
1958
1959/*
1960 * Set PID in case of n2n (which is assigned during PLOGI)
1961 */
1962void
1963bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
1964{
1965        bfa_trc(lps->bfa, lps->bfa_tag);
1966        bfa_trc(lps->bfa, n2n_pid);
1967
1968        lps->lp_pid = n2n_pid;
1969        bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1970}
1971
1972/*
1973 * LPS firmware message class handler.
1974 */
1975void
1976bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1977{
1978        union bfi_lps_i2h_msg_u msg;
1979
1980        bfa_trc(bfa, m->mhdr.msg_id);
1981        msg.msg = m;
1982
1983        switch (m->mhdr.msg_id) {
1984        case BFI_LPS_I2H_LOGIN_RSP:
1985                bfa_lps_login_rsp(bfa, msg.login_rsp);
1986                break;
1987
1988        case BFI_LPS_I2H_LOGOUT_RSP:
1989                bfa_lps_logout_rsp(bfa, msg.logout_rsp);
1990                break;
1991
1992        case BFI_LPS_I2H_CVL_EVENT:
1993                bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
1994                break;
1995
1996        default:
1997                bfa_trc(bfa, m->mhdr.msg_id);
1998                WARN_ON(1);
1999        }
2000}
2001
2002static void
2003bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
2004{
2005        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2006        struct bfa_aen_entry_s  *aen_entry;
2007
2008        bfad_get_aen_entry(bfad, aen_entry);
2009        if (!aen_entry)
2010                return;
2011
2012        aen_entry->aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
2013        aen_entry->aen_data.port.pwwn = fcport->pwwn;
2014
2015        /* Send the AEN notification */
2016        bfad_im_post_vendor_event(aen_entry, bfad, ++fcport->bfa->bfa_aen_seq,
2017                                  BFA_AEN_CAT_PORT, event);
2018}
2019
2020/*
2021 * FC PORT state machine functions
2022 */
2023static void
2024bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
2025                        enum bfa_fcport_sm_event event)
2026{
2027        bfa_trc(fcport->bfa, event);
2028
2029        switch (event) {
2030        case BFA_FCPORT_SM_START:
2031                /*
2032                 * Start event after IOC is configured and BFA is started.
2033                 */
2034                fcport->use_flash_cfg = BFA_TRUE;
2035
2036                if (bfa_fcport_send_enable(fcport)) {
2037                        bfa_trc(fcport->bfa, BFA_TRUE);
2038                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2039                } else {
2040                        bfa_trc(fcport->bfa, BFA_FALSE);
2041                        bfa_sm_set_state(fcport,
2042                                        bfa_fcport_sm_enabling_qwait);
2043                }
2044                break;
2045
2046        case BFA_FCPORT_SM_ENABLE:
2047                /*
2048                 * Port is persistently configured to be in enabled state. Do
2049                 * not change state. Port enabling is done when START event is
2050                 * received.
2051                 */
2052                break;
2053
2054        case BFA_FCPORT_SM_DISABLE:
2055                /*
2056                 * If a port is persistently configured to be disabled, the
2057                 * first event will a port disable request.
2058                 */
2059                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2060                break;
2061
2062        case BFA_FCPORT_SM_HWFAIL:
2063                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2064                break;
2065
2066        default:
2067                bfa_sm_fault(fcport->bfa, event);
2068        }
2069}
2070
2071static void
2072bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
2073                                enum bfa_fcport_sm_event event)
2074{
2075        char pwwn_buf[BFA_STRING_32];
2076        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2077        bfa_trc(fcport->bfa, event);
2078
2079        switch (event) {
2080        case BFA_FCPORT_SM_QRESUME:
2081                bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2082                bfa_fcport_send_enable(fcport);
2083                break;
2084
2085        case BFA_FCPORT_SM_STOP:
2086                bfa_reqq_wcancel(&fcport->reqq_wait);
2087                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2088                break;
2089
2090        case BFA_FCPORT_SM_ENABLE:
2091                /*
2092                 * Already enable is in progress.
2093                 */
2094                break;
2095
2096        case BFA_FCPORT_SM_DISABLE:
2097                /*
2098                 * Just send disable request to firmware when room becomes
2099                 * available in request queue.
2100                 */
2101                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2102                bfa_reqq_wcancel(&fcport->reqq_wait);
2103                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2104                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2105                wwn2str(pwwn_buf, fcport->pwwn);
2106                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2107                        "Base port disabled: WWN = %s\n", pwwn_buf);
2108                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2109                break;
2110
2111        case BFA_FCPORT_SM_LINKUP:
2112        case BFA_FCPORT_SM_LINKDOWN:
2113                /*
2114                 * Possible to get link events when doing back-to-back
2115                 * enable/disables.
2116                 */
2117                break;
2118
2119        case BFA_FCPORT_SM_HWFAIL:
2120                bfa_reqq_wcancel(&fcport->reqq_wait);
2121                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2122                break;
2123
2124        case BFA_FCPORT_SM_FAA_MISCONFIG:
2125                bfa_fcport_reset_linkinfo(fcport);
2126                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2127                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2128                break;
2129
2130        default:
2131                bfa_sm_fault(fcport->bfa, event);
2132        }
2133}
2134
2135static void
2136bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
2137                                                enum bfa_fcport_sm_event event)
2138{
2139        char pwwn_buf[BFA_STRING_32];
2140        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2141        bfa_trc(fcport->bfa, event);
2142
2143        switch (event) {
2144        case BFA_FCPORT_SM_FWRSP:
2145        case BFA_FCPORT_SM_LINKDOWN:
2146                bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2147                break;
2148
2149        case BFA_FCPORT_SM_LINKUP:
2150                bfa_fcport_update_linkinfo(fcport);
2151                bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2152
2153                WARN_ON(!fcport->event_cbfn);
2154                bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2155                break;
2156
2157        case BFA_FCPORT_SM_ENABLE:
2158                /*
2159                 * Already being enabled.
2160                 */
2161                break;
2162
2163        case BFA_FCPORT_SM_DISABLE:
2164                if (bfa_fcport_send_disable(fcport))
2165                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2166                else
2167                        bfa_sm_set_state(fcport,
2168                                         bfa_fcport_sm_disabling_qwait);
2169
2170                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2171                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2172                wwn2str(pwwn_buf, fcport->pwwn);
2173                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2174                        "Base port disabled: WWN = %s\n", pwwn_buf);
2175                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2176                break;
2177
2178        case BFA_FCPORT_SM_STOP:
2179                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2180                break;
2181
2182        case BFA_FCPORT_SM_HWFAIL:
2183                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2184                break;
2185
2186        case BFA_FCPORT_SM_FAA_MISCONFIG:
2187                bfa_fcport_reset_linkinfo(fcport);
2188                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2189                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2190                break;
2191
2192        default:
2193                bfa_sm_fault(fcport->bfa, event);
2194        }
2195}
2196
2197static void
2198bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
2199                                                enum bfa_fcport_sm_event event)
2200{
2201        struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2202        char pwwn_buf[BFA_STRING_32];
2203        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2204
2205        bfa_trc(fcport->bfa, event);
2206
2207        switch (event) {
2208        case BFA_FCPORT_SM_LINKUP:
2209                bfa_fcport_update_linkinfo(fcport);
2210                bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2211                WARN_ON(!fcport->event_cbfn);
2212                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2213                                BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
2214                if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
2215
2216                        bfa_trc(fcport->bfa,
2217                                pevent->link_state.attr.vc_fcf.fcf.fipenabled);
2218                        bfa_trc(fcport->bfa,
2219                                pevent->link_state.attr.vc_fcf.fcf.fipfailed);
2220
2221                        if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
2222                                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2223                                        BFA_PL_EID_FIP_FCF_DISC, 0,
2224                                        "FIP FCF Discovery Failed");
2225                        else
2226                                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2227                                        BFA_PL_EID_FIP_FCF_DISC, 0,
2228                                        "FIP FCF Discovered");
2229                }
2230
2231                bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2232                wwn2str(pwwn_buf, fcport->pwwn);
2233                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2234                        "Base port online: WWN = %s\n", pwwn_buf);
2235                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
2236
2237                /* If QoS is enabled and it is not online, send AEN */
2238                if (fcport->cfg.qos_enabled &&
2239                    fcport->qos_attr.state != BFA_QOS_ONLINE)
2240                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
2241                break;
2242
2243        case BFA_FCPORT_SM_LINKDOWN:
2244                /*
2245                 * Possible to get link down event.
2246                 */
2247                break;
2248
2249        case BFA_FCPORT_SM_ENABLE:
2250                /*
2251                 * Already enabled.
2252                 */
2253                break;
2254
2255        case BFA_FCPORT_SM_DISABLE:
2256                if (bfa_fcport_send_disable(fcport))
2257                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2258                else
2259                        bfa_sm_set_state(fcport,
2260                                         bfa_fcport_sm_disabling_qwait);
2261
2262                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2263                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2264                wwn2str(pwwn_buf, fcport->pwwn);
2265                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2266                        "Base port disabled: WWN = %s\n", pwwn_buf);
2267                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2268                break;
2269
2270        case BFA_FCPORT_SM_STOP:
2271                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2272                break;
2273
2274        case BFA_FCPORT_SM_HWFAIL:
2275                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2276                break;
2277
2278        case BFA_FCPORT_SM_FAA_MISCONFIG:
2279                bfa_fcport_reset_linkinfo(fcport);
2280                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2281                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2282                break;
2283
2284        default:
2285                bfa_sm_fault(fcport->bfa, event);
2286        }
2287}
2288
2289static void
2290bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
2291        enum bfa_fcport_sm_event event)
2292{
2293        char pwwn_buf[BFA_STRING_32];
2294        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2295
2296        bfa_trc(fcport->bfa, event);
2297
2298        switch (event) {
2299        case BFA_FCPORT_SM_ENABLE:
2300                /*
2301                 * Already enabled.
2302                 */
2303                break;
2304
2305        case BFA_FCPORT_SM_DISABLE:
2306                if (bfa_fcport_send_disable(fcport))
2307                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2308                else
2309                        bfa_sm_set_state(fcport,
2310                                         bfa_fcport_sm_disabling_qwait);
2311
2312                bfa_fcport_reset_linkinfo(fcport);
2313                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2314                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2315                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2316                wwn2str(pwwn_buf, fcport->pwwn);
2317                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2318                        "Base port offline: WWN = %s\n", pwwn_buf);
2319                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2320                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2321                        "Base port disabled: WWN = %s\n", pwwn_buf);
2322                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2323                break;
2324
2325        case BFA_FCPORT_SM_LINKDOWN:
2326                bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2327                bfa_fcport_reset_linkinfo(fcport);
2328                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2329                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2330                                BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
2331                wwn2str(pwwn_buf, fcport->pwwn);
2332                if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2333                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2334                                "Base port offline: WWN = %s\n", pwwn_buf);
2335                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2336                } else {
2337                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2338                                "Base port (WWN = %s) "
2339                                "lost fabric connectivity\n", pwwn_buf);
2340                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2341                }
2342                break;
2343
2344        case BFA_FCPORT_SM_STOP:
2345                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2346                bfa_fcport_reset_linkinfo(fcport);
2347                wwn2str(pwwn_buf, fcport->pwwn);
2348                if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2349                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2350                                "Base port offline: WWN = %s\n", pwwn_buf);
2351                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2352                } else {
2353                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2354                                "Base port (WWN = %s) "
2355                                "lost fabric connectivity\n", pwwn_buf);
2356                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2357                }
2358                break;
2359
2360        case BFA_FCPORT_SM_HWFAIL:
2361                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2362                bfa_fcport_reset_linkinfo(fcport);
2363                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2364                wwn2str(pwwn_buf, fcport->pwwn);
2365                if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2366                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2367                                "Base port offline: WWN = %s\n", pwwn_buf);
2368                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2369                } else {
2370                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2371                                "Base port (WWN = %s) "
2372                                "lost fabric connectivity\n", pwwn_buf);
2373                        bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2374                }
2375                break;
2376
2377        case BFA_FCPORT_SM_FAA_MISCONFIG:
2378                bfa_fcport_reset_linkinfo(fcport);
2379                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2380                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2381                break;
2382
2383        default:
2384                bfa_sm_fault(fcport->bfa, event);
2385        }
2386}
2387
2388static void
2389bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
2390                                 enum bfa_fcport_sm_event event)
2391{
2392        bfa_trc(fcport->bfa, event);
2393
2394        switch (event) {
2395        case BFA_FCPORT_SM_QRESUME:
2396                bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2397                bfa_fcport_send_disable(fcport);
2398                break;
2399
2400        case BFA_FCPORT_SM_STOP:
2401                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2402                bfa_reqq_wcancel(&fcport->reqq_wait);
2403                break;
2404
2405        case BFA_FCPORT_SM_ENABLE:
2406                bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
2407                break;
2408
2409        case BFA_FCPORT_SM_DISABLE:
2410                /*
2411                 * Already being disabled.
2412                 */
2413                break;
2414
2415        case BFA_FCPORT_SM_LINKUP:
2416        case BFA_FCPORT_SM_LINKDOWN:
2417                /*
2418                 * Possible to get link events when doing back-to-back
2419                 * enable/disables.
2420                 */
2421                break;
2422
2423        case BFA_FCPORT_SM_HWFAIL:
2424                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2425                bfa_reqq_wcancel(&fcport->reqq_wait);
2426                break;
2427
2428        case BFA_FCPORT_SM_FAA_MISCONFIG:
2429                bfa_fcport_reset_linkinfo(fcport);
2430                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2431                bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2432                break;
2433
2434        default:
2435                bfa_sm_fault(fcport->bfa, event);
2436        }
2437}
2438
2439static void
2440bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
2441                                 enum bfa_fcport_sm_event event)
2442{
2443        bfa_trc(fcport->bfa, event);
2444
2445        switch (event) {
2446        case BFA_FCPORT_SM_QRESUME:
2447                bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2448                bfa_fcport_send_disable(fcport);
2449                if (bfa_fcport_send_enable(fcport))
2450                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2451                else
2452                        bfa_sm_set_state(fcport,
2453                                         bfa_fcport_sm_enabling_qwait);
2454                break;
2455
2456        case BFA_FCPORT_SM_STOP:
2457                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2458                bfa_reqq_wcancel(&fcport->reqq_wait);
2459                break;
2460
2461        case BFA_FCPORT_SM_ENABLE:
2462                break;
2463
2464        case BFA_FCPORT_SM_DISABLE:
2465                bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2466                break;
2467
2468        case BFA_FCPORT_SM_LINKUP:
2469        case BFA_FCPORT_SM_LINKDOWN:
2470                /*
2471                 * Possible to get link events when doing back-to-back
2472                 * enable/disables.
2473                 */
2474                break;
2475
2476        case BFA_FCPORT_SM_HWFAIL:
2477                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2478                bfa_reqq_wcancel(&fcport->reqq_wait);
2479                break;
2480
2481        default:
2482                bfa_sm_fault(fcport->bfa, event);
2483        }
2484}
2485
2486static void
2487bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
2488                                                enum bfa_fcport_sm_event event)
2489{
2490        char pwwn_buf[BFA_STRING_32];
2491        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2492        bfa_trc(fcport->bfa, event);
2493
2494        switch (event) {
2495        case BFA_FCPORT_SM_FWRSP:
2496                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2497                break;
2498
2499        case BFA_FCPORT_SM_DISABLE:
2500                /*
2501                 * Already being disabled.
2502                 */
2503                break;
2504
2505        case BFA_FCPORT_SM_ENABLE:
2506                if (bfa_fcport_send_enable(fcport))
2507                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2508                else
2509                        bfa_sm_set_state(fcport,
2510                                         bfa_fcport_sm_enabling_qwait);
2511
2512                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2513                                BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2514                wwn2str(pwwn_buf, fcport->pwwn);
2515                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2516                        "Base port enabled: WWN = %s\n", pwwn_buf);
2517                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2518                break;
2519
2520        case BFA_FCPORT_SM_STOP:
2521                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2522                break;
2523
2524        case BFA_FCPORT_SM_LINKUP:
2525        case BFA_FCPORT_SM_LINKDOWN:
2526                /*
2527                 * Possible to get link events when doing back-to-back
2528                 * enable/disables.
2529                 */
2530                break;
2531
2532        case BFA_FCPORT_SM_HWFAIL:
2533                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2534                break;
2535
2536        default:
2537                bfa_sm_fault(fcport->bfa, event);
2538        }
2539}
2540
2541static void
2542bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
2543                                                enum bfa_fcport_sm_event event)
2544{
2545        char pwwn_buf[BFA_STRING_32];
2546        struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2547        bfa_trc(fcport->bfa, event);
2548
2549        switch (event) {
2550        case BFA_FCPORT_SM_START:
2551                /*
2552                 * Ignore start event for a port that is disabled.
2553                 */
2554                break;
2555
2556        case BFA_FCPORT_SM_STOP:
2557                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2558                break;
2559
2560        case BFA_FCPORT_SM_ENABLE:
2561                if (bfa_fcport_send_enable(fcport))
2562                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2563                else
2564                        bfa_sm_set_state(fcport,
2565                                         bfa_fcport_sm_enabling_qwait);
2566
2567                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2568                                BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2569                wwn2str(pwwn_buf, fcport->pwwn);
2570                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2571                        "Base port enabled: WWN = %s\n", pwwn_buf);
2572                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2573                break;
2574
2575        case BFA_FCPORT_SM_DISABLE:
2576                /*
2577                 * Already disabled.
2578                 */
2579                break;
2580
2581        case BFA_FCPORT_SM_HWFAIL:
2582                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2583                break;
2584
2585        case BFA_FCPORT_SM_DPORTENABLE:
2586                bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
2587                break;
2588
2589        case BFA_FCPORT_SM_DDPORTENABLE:
2590                bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);
2591                break;
2592
2593        default:
2594                bfa_sm_fault(fcport->bfa, event);
2595        }
2596}
2597
2598static void
2599bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
2600                         enum bfa_fcport_sm_event event)
2601{
2602        bfa_trc(fcport->bfa, event);
2603
2604        switch (event) {
2605        case BFA_FCPORT_SM_START:
2606                if (bfa_fcport_send_enable(fcport))
2607                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2608                else
2609                        bfa_sm_set_state(fcport,
2610                                         bfa_fcport_sm_enabling_qwait);
2611                break;
2612
2613        default:
2614                /*
2615                 * Ignore all other events.
2616                 */
2617                ;
2618        }
2619}
2620
2621/*
2622 * Port is enabled. IOC is down/failed.
2623 */
2624static void
2625bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
2626                         enum bfa_fcport_sm_event event)
2627{
2628        bfa_trc(fcport->bfa, event);
2629
2630        switch (event) {
2631        case BFA_FCPORT_SM_START:
2632                if (bfa_fcport_send_enable(fcport))
2633                        bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2634                else
2635                        bfa_sm_set_state(fcport,
2636                                         bfa_fcport_sm_enabling_qwait);
2637                break;
2638
2639        default:
2640                /*
2641                 * Ignore all events.
2642                 */
2643                ;
2644        }
2645}
2646
2647/*
2648 * Port is disabled. IOC is down/failed.
2649 */
2650static void
2651bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
2652                         enum bfa_fcport_sm_event event)
2653{
2654        bfa_trc(fcport->bfa, event);
2655
2656        switch (event) {
2657        case BFA_FCPORT_SM_START:
2658                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2659                break;
2660
2661        case BFA_FCPORT_SM_ENABLE:
2662                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2663                break;
2664
2665        default:
2666                /*
2667                 * Ignore all events.
2668                 */
2669                ;
2670        }
2671}
2672
2673static void
2674bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
2675{
2676        bfa_trc(fcport->bfa, event);
2677
2678        switch (event) {
2679        case BFA_FCPORT_SM_DPORTENABLE:
2680        case BFA_FCPORT_SM_DISABLE:
2681        case BFA_FCPORT_SM_ENABLE:
2682        case BFA_FCPORT_SM_START:
2683                /*
2684                 * Ignore event for a port that is dport
2685                 */
2686                break;
2687
2688        case BFA_FCPORT_SM_STOP:
2689                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2690                break;
2691
2692        case BFA_FCPORT_SM_HWFAIL:
2693                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2694                break;
2695
2696        case BFA_FCPORT_SM_DPORTDISABLE:
2697                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2698                break;
2699
2700        default:
2701                bfa_sm_fault(fcport->bfa, event);
2702        }
2703}
2704
2705static void
2706bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
2707                        enum bfa_fcport_sm_event event)
2708{
2709        bfa_trc(fcport->bfa, event);
2710
2711        switch (event) {
2712        case BFA_FCPORT_SM_DISABLE:
2713        case BFA_FCPORT_SM_DDPORTDISABLE:
2714                bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2715                break;
2716
2717        case BFA_FCPORT_SM_DPORTENABLE:
2718        case BFA_FCPORT_SM_DPORTDISABLE:
2719        case BFA_FCPORT_SM_ENABLE:
2720        case BFA_FCPORT_SM_START:
2721                /*
2722                 * Ignore event for a port that is ddport
2723                 */
2724                break;
2725
2726        case BFA_FCPORT_SM_STOP:
2727                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2728                break;
2729
2730        case BFA_FCPORT_SM_HWFAIL:
2731                bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2732                break;
2733
2734        default:
2735                bfa_sm_fault(fcport->bfa, event);
2736        }
2737}
2738
2739static void
2740bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
2741                            enum bfa_fcport_sm_event event)
2742{
2743        bfa_trc(fcport->bfa, event);
2744
2745        switch (event) {
2746        case BFA_FCPORT_SM_DPORTENABLE:
2747        case BFA_FCPORT_SM_ENABLE:
2748        case BFA_FCPORT_SM_START:
2749                /*
2750                 * Ignore event for a port as there is FAA misconfig
2751                 */
2752                break;
2753
2754        case BFA_FCPORT_SM_DISABLE:
2755                if (bfa_fcport_send_disable(fcport))
2756                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2757                else
2758                        bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2759
2760                bfa_fcport_reset_linkinfo(fcport);
2761                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2762                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2763                             BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2764                bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2765                break;
2766
2767        case BFA_FCPORT_SM_STOP:
2768                bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2769                break;
2770
2771        case BFA_FCPORT_SM_HWFAIL:
2772                bfa_fcport_reset_linkinfo(fcport);
2773                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2774                bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2775                break;
2776
2777        default:
2778                bfa_sm_fault(fcport->bfa, event);
2779        }
2780}
2781
2782/*
2783 * Link state is down
2784 */
2785static void
2786bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
2787                enum bfa_fcport_ln_sm_event event)
2788{
2789        bfa_trc(ln->fcport->bfa, event);
2790
2791        switch (event) {
2792        case BFA_FCPORT_LN_SM_LINKUP:
2793                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2794                bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2795                break;
2796
2797        default:
2798                bfa_sm_fault(ln->fcport->bfa, event);
2799        }
2800}
2801
2802/*
2803 * Link state is waiting for down notification
2804 */
2805static void
2806bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
2807                enum bfa_fcport_ln_sm_event event)
2808{
2809        bfa_trc(ln->fcport->bfa, event);
2810
2811        switch (event) {
2812        case BFA_FCPORT_LN_SM_LINKUP:
2813                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2814                break;
2815
2816        case BFA_FCPORT_LN_SM_NOTIFICATION:
2817                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2818                break;
2819
2820        default:
2821                bfa_sm_fault(ln->fcport->bfa, event);
2822        }
2823}
2824
2825/*
2826 * Link state is waiting for down notification and there is a pending up
2827 */
2828static void
2829bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
2830                enum bfa_fcport_ln_sm_event event)
2831{
2832        bfa_trc(ln->fcport->bfa, event);
2833
2834        switch (event) {
2835        case BFA_FCPORT_LN_SM_LINKDOWN:
2836                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2837                break;
2838
2839        case BFA_FCPORT_LN_SM_NOTIFICATION:
2840                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2841                bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2842                break;
2843
2844        default:
2845                bfa_sm_fault(ln->fcport->bfa, event);
2846        }
2847}
2848
2849/*
2850 * Link state is up
2851 */
2852static void
2853bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
2854                enum bfa_fcport_ln_sm_event event)
2855{
2856        bfa_trc(ln->fcport->bfa, event);
2857
2858        switch (event) {
2859        case BFA_FCPORT_LN_SM_LINKDOWN:
2860                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2861                bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2862                break;
2863
2864        default:
2865                bfa_sm_fault(ln->fcport->bfa, event);
2866        }
2867}
2868
2869/*
2870 * Link state is waiting for up notification
2871 */
2872static void
2873bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
2874                enum bfa_fcport_ln_sm_event event)
2875{
2876        bfa_trc(ln->fcport->bfa, event);
2877
2878        switch (event) {
2879        case BFA_FCPORT_LN_SM_LINKDOWN:
2880                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2881                break;
2882
2883        case BFA_FCPORT_LN_SM_NOTIFICATION:
2884                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
2885                break;
2886
2887        default:
2888                bfa_sm_fault(ln->fcport->bfa, event);
2889        }
2890}
2891
2892/*
2893 * Link state is waiting for up notification and there is a pending down
2894 */
2895static void
2896bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
2897                enum bfa_fcport_ln_sm_event event)
2898{
2899        bfa_trc(ln->fcport->bfa, event);
2900
2901        switch (event) {
2902        case BFA_FCPORT_LN_SM_LINKUP:
2903                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
2904                break;
2905
2906        case BFA_FCPORT_LN_SM_NOTIFICATION:
2907                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2908                bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2909                break;
2910
2911        default:
2912                bfa_sm_fault(ln->fcport->bfa, event);
2913        }
2914}
2915
2916/*
2917 * Link state is waiting for up notification and there are pending down and up
2918 */
2919static void
2920bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
2921                        enum bfa_fcport_ln_sm_event event)
2922{
2923        bfa_trc(ln->fcport->bfa, event);
2924
2925        switch (event) {
2926        case BFA_FCPORT_LN_SM_LINKDOWN:
2927                bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2928                break;
2929
2930        case BFA_FCPORT_LN_SM_NOTIFICATION:
2931                bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2932                bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2933                break;
2934
2935        default:
2936                bfa_sm_fault(ln->fcport->bfa, event);
2937        }
2938}
2939
2940static void
2941__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
2942{
2943        struct bfa_fcport_ln_s *ln = cbarg;
2944
2945        if (complete)
2946                ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
2947        else
2948                bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2949}
2950
2951/*
2952 * Send SCN notification to upper layers.
2953 * trunk - false if caller is fcport to ignore fcport event in trunked mode
2954 */
2955static void
2956bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
2957        bfa_boolean_t trunk)
2958{
2959        if (fcport->cfg.trunked && !trunk)
2960                return;
2961
2962        switch (event) {
2963        case BFA_PORT_LINKUP:
2964                bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
2965                break;
2966        case BFA_PORT_LINKDOWN:
2967                bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
2968                break;
2969        default:
2970                WARN_ON(1);
2971        }
2972}
2973
2974static void
2975bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
2976{
2977        struct bfa_fcport_s *fcport = ln->fcport;
2978
2979        if (fcport->bfa->fcs) {
2980                fcport->event_cbfn(fcport->event_cbarg, event);
2981                bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2982        } else {
2983                ln->ln_event = event;
2984                bfa_cb_queue(fcport->bfa, &ln->ln_qe,
2985                        __bfa_cb_fcport_event, ln);
2986        }
2987}
2988
2989#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
2990                                                        BFA_CACHELINE_SZ))
2991
2992void
2993bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
2994                   struct bfa_s *bfa)
2995{
2996        struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa);
2997
2998        bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);
2999}
3000
3001static void
3002bfa_fcport_qresume(void *cbarg)
3003{
3004        struct bfa_fcport_s *fcport = cbarg;
3005
3006        bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
3007}
3008
3009static void
3010bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)
3011{
3012        struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma;
3013
3014        fcport->stats_kva = bfa_mem_dma_virt(fcport_dma);
3015        fcport->stats_pa  = bfa_mem_dma_phys(fcport_dma);
3016        fcport->stats = (union bfa_fcport_stats_u *)
3017                                bfa_mem_dma_virt(fcport_dma);
3018}
3019
3020/*
3021 * Memory initialization.
3022 */
3023void
3024bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
3025                struct bfa_pcidev_s *pcidev)
3026{
3027        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3028        struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
3029        struct bfa_fcport_ln_s *ln = &fcport->ln;
3030
3031        fcport->bfa = bfa;
3032        ln->fcport = fcport;
3033
3034        bfa_fcport_mem_claim(fcport);
3035
3036        bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
3037        bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
3038
3039        /*
3040         * initialize time stamp for stats reset
3041         */
3042        fcport->stats_reset_time = ktime_get_seconds();
3043        fcport->stats_dma_ready = BFA_FALSE;
3044
3045        /*
3046         * initialize and set default configuration
3047         */
3048        port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
3049        port_cfg->speed = BFA_PORT_SPEED_AUTO;
3050        port_cfg->trunked = BFA_FALSE;
3051        port_cfg->maxfrsize = 0;
3052
3053        port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
3054        port_cfg->qos_bw.high = BFA_QOS_BW_HIGH;
3055        port_cfg->qos_bw.med = BFA_QOS_BW_MED;
3056        port_cfg->qos_bw.low = BFA_QOS_BW_LOW;
3057
3058        fcport->fec_state = BFA_FEC_OFFLINE;
3059
3060        INIT_LIST_HEAD(&fcport->stats_pending_q);
3061        INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3062
3063        bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
3064}
3065
3066void
3067bfa_fcport_start(struct bfa_s *bfa)
3068{
3069        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
3070}
3071
3072/*
3073 * Called when IOC failure is detected.
3074 */
3075void
3076bfa_fcport_iocdisable(struct bfa_s *bfa)
3077{
3078        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3079
3080        bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
3081        bfa_trunk_iocdisable(bfa);
3082}
3083
3084/*
3085 * Update loop info in fcport for SCN online
3086 */
3087static void
3088bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
3089                        struct bfa_fcport_loop_info_s *loop_info)
3090{
3091        fcport->myalpa = loop_info->myalpa;
3092        fcport->alpabm_valid =
3093                        loop_info->alpabm_val;
3094        memcpy(fcport->alpabm.alpa_bm,
3095                        loop_info->alpabm.alpa_bm,
3096                        sizeof(struct fc_alpabm_s));
3097}
3098
3099static void
3100bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
3101{
3102        struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
3103        struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3104
3105        fcport->speed = pevent->link_state.speed;
3106        fcport->topology = pevent->link_state.topology;
3107
3108        if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
3109                bfa_fcport_update_loop_info(fcport,
3110                                &pevent->link_state.attr.loop_info);
3111                return;
3112        }
3113
3114        /* QoS Details */
3115        fcport->qos_attr = pevent->link_state.qos_attr;
3116        fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
3117
3118        if (fcport->cfg.bb_cr_enabled)
3119                fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr;
3120
3121        fcport->fec_state = pevent->link_state.fec_state;
3122
3123        /*
3124         * update trunk state if applicable
3125         */
3126        if (!fcport->cfg.trunked)
3127                trunk->attr.state = BFA_TRUNK_DISABLED;
3128
3129        /* update FCoE specific */
3130        fcport->fcoe_vlan =
3131                be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
3132
3133        bfa_trc(fcport->bfa, fcport->speed);
3134        bfa_trc(fcport->bfa, fcport->topology);
3135}
3136
3137static void
3138bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
3139{
3140        fcport->speed = BFA_PORT_SPEED_UNKNOWN;
3141        fcport->topology = BFA_PORT_TOPOLOGY_NONE;
3142        fcport->fec_state = BFA_FEC_OFFLINE;
3143}
3144
3145/*
3146 * Send port enable message to firmware.
3147 */
3148static bfa_boolean_t
3149bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
3150{
3151        struct bfi_fcport_enable_req_s *m;
3152
3153        /*
3154         * Increment message tag before queue check, so that responses to old
3155         * requests are discarded.
3156         */
3157        fcport->msgtag++;
3158
3159        /*
3160         * check for room in queue to send request now
3161         */
3162        m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3163        if (!m) {
3164                bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3165                                                        &fcport->reqq_wait);
3166                return BFA_FALSE;
3167        }
3168
3169        bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
3170                        bfa_fn_lpu(fcport->bfa));
3171        m->nwwn = fcport->nwwn;
3172        m->pwwn = fcport->pwwn;
3173        m->port_cfg = fcport->cfg;
3174        m->msgtag = fcport->msgtag;
3175        m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
3176         m->use_flash_cfg = fcport->use_flash_cfg;
3177        bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
3178        bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
3179        bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
3180
3181        /*
3182         * queue I/O message to firmware
3183         */
3184        bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3185        return BFA_TRUE;
3186}
3187
3188/*
3189 * Send port disable message to firmware.
3190 */
3191static  bfa_boolean_t
3192bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
3193{
3194        struct bfi_fcport_req_s *m;
3195
3196        /*
3197         * Increment message tag before queue check, so that responses to old
3198         * requests are discarded.
3199         */
3200        fcport->msgtag++;
3201
3202        /*
3203         * check for room in queue to send request now
3204         */
3205        m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3206        if (!m) {
3207                bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3208                                                        &fcport->reqq_wait);
3209                return BFA_FALSE;
3210        }
3211
3212        bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
3213                        bfa_fn_lpu(fcport->bfa));
3214        m->msgtag = fcport->msgtag;
3215
3216        /*
3217         * queue I/O message to firmware
3218         */
3219        bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3220
3221        return BFA_TRUE;
3222}
3223
3224static void
3225bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
3226{
3227        fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
3228        fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
3229
3230        bfa_trc(fcport->bfa, fcport->pwwn);
3231        bfa_trc(fcport->bfa, fcport->nwwn);
3232}
3233
3234static void
3235bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
3236        struct bfa_qos_stats_s *s)
3237{
3238        u32     *dip = (u32 *) d;
3239        __be32  *sip = (__be32 *) s;
3240        int             i;
3241
3242        /* Now swap the 32 bit fields */
3243        for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
3244                dip[i] = be32_to_cpu(sip[i]);
3245}
3246
3247static void
3248bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
3249        struct bfa_fcoe_stats_s *s)
3250{
3251        u32     *dip = (u32 *) d;
3252        __be32  *sip = (__be32 *) s;
3253        int             i;
3254
3255        for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
3256             i = i + 2) {
3257#ifdef __BIG_ENDIAN
3258                dip[i] = be32_to_cpu(sip[i]);
3259                dip[i + 1] = be32_to_cpu(sip[i + 1]);
3260#else
3261                dip[i] = be32_to_cpu(sip[i + 1]);
3262                dip[i + 1] = be32_to_cpu(sip[i]);
3263#endif
3264        }
3265}
3266
3267static void
3268__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
3269{
3270        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;
3271        struct bfa_cb_pending_q_s *cb;
3272        struct list_head *qe, *qen;
3273        union bfa_fcport_stats_u *ret;
3274
3275        if (complete) {
3276                time64_t time = ktime_get_seconds();
3277
3278                list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
3279                        bfa_q_deq(&fcport->stats_pending_q, &qe);
3280                        cb = (struct bfa_cb_pending_q_s *)qe;
3281                        if (fcport->stats_status == BFA_STATUS_OK) {
3282                                ret = (union bfa_fcport_stats_u *)cb->data;
3283                                /* Swap FC QoS or FCoE stats */
3284                                if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
3285                                        bfa_fcport_qos_stats_swap(&ret->fcqos,
3286                                                        &fcport->stats->fcqos);
3287                                else {
3288                                        bfa_fcport_fcoe_stats_swap(&ret->fcoe,
3289                                                        &fcport->stats->fcoe);
3290                                        ret->fcoe.secs_reset =
3291                                                time - fcport->stats_reset_time;
3292                                }
3293                        }
3294                        bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3295                                        fcport->stats_status);
3296                }
3297                fcport->stats_status = BFA_STATUS_OK;
3298        } else {
3299                INIT_LIST_HEAD(&fcport->stats_pending_q);
3300                fcport->stats_status = BFA_STATUS_OK;
3301        }
3302}
3303
3304static void
3305bfa_fcport_stats_get_timeout(void *cbarg)
3306{
3307        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3308
3309        bfa_trc(fcport->bfa, fcport->stats_qfull);
3310
3311        if (fcport->stats_qfull) {
3312                bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3313                fcport->stats_qfull = BFA_FALSE;
3314        }
3315
3316        fcport->stats_status = BFA_STATUS_ETIMER;
3317        __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3318}
3319
3320static void
3321bfa_fcport_send_stats_get(void *cbarg)
3322{
3323        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3324        struct bfi_fcport_req_s *msg;
3325
3326        msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3327
3328        if (!msg) {
3329                fcport->stats_qfull = BFA_TRUE;
3330                bfa_reqq_winit(&fcport->stats_reqq_wait,
3331                                bfa_fcport_send_stats_get, fcport);
3332                bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3333                                &fcport->stats_reqq_wait);
3334                return;
3335        }
3336        fcport->stats_qfull = BFA_FALSE;
3337
3338        memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3339        bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
3340                        bfa_fn_lpu(fcport->bfa));
3341        bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3342}
3343
3344static void
3345__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3346{
3347        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3348        struct bfa_cb_pending_q_s *cb;
3349        struct list_head *qe, *qen;
3350
3351        if (complete) {
3352                /*
3353                 * re-initialize time stamp for stats reset
3354                 */
3355                fcport->stats_reset_time = ktime_get_seconds();
3356                list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
3357                        bfa_q_deq(&fcport->statsclr_pending_q, &qe);
3358                        cb = (struct bfa_cb_pending_q_s *)qe;
3359                        bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3360                                                fcport->stats_status);
3361                }
3362                fcport->stats_status = BFA_STATUS_OK;
3363        } else {
3364                INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3365                fcport->stats_status = BFA_STATUS_OK;
3366        }
3367}
3368
3369static void
3370bfa_fcport_stats_clr_timeout(void *cbarg)
3371{
3372        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3373
3374        bfa_trc(fcport->bfa, fcport->stats_qfull);
3375
3376        if (fcport->stats_qfull) {
3377                bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3378                fcport->stats_qfull = BFA_FALSE;
3379        }
3380
3381        fcport->stats_status = BFA_STATUS_ETIMER;
3382        __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3383}
3384
3385static void
3386bfa_fcport_send_stats_clear(void *cbarg)
3387{
3388        struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3389        struct bfi_fcport_req_s *msg;
3390
3391        msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3392
3393        if (!msg) {
3394                fcport->stats_qfull = BFA_TRUE;
3395                bfa_reqq_winit(&fcport->stats_reqq_wait,
3396                                bfa_fcport_send_stats_clear, fcport);
3397                bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3398                                                &fcport->stats_reqq_wait);
3399                return;
3400        }
3401        fcport->stats_qfull = BFA_FALSE;
3402
3403        memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3404        bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
3405                        bfa_fn_lpu(fcport->bfa));
3406        bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3407}
3408
3409/*
3410 * Handle trunk SCN event from firmware.
3411 */
3412static void
3413bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
3414{
3415        struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3416        struct bfi_fcport_trunk_link_s *tlink;
3417        struct bfa_trunk_link_attr_s *lattr;
3418        enum bfa_trunk_state state_prev;
3419        int i;
3420        int link_bm = 0;
3421
3422        bfa_trc(fcport->bfa, fcport->cfg.trunked);
3423        WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
3424                   scn->trunk_state != BFA_TRUNK_OFFLINE);
3425
3426        bfa_trc(fcport->bfa, trunk->attr.state);
3427        bfa_trc(fcport->bfa, scn->trunk_state);
3428        bfa_trc(fcport->bfa, scn->trunk_speed);
3429
3430        /*
3431         * Save off new state for trunk attribute query
3432         */
3433        state_prev = trunk->attr.state;
3434        if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
3435                trunk->attr.state = scn->trunk_state;
3436        trunk->attr.speed = scn->trunk_speed;
3437        for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3438                lattr = &trunk->attr.link_attr[i];
3439                tlink = &scn->tlink[i];
3440
3441                lattr->link_state = tlink->state;
3442                lattr->trunk_wwn  = tlink->trunk_wwn;
3443                lattr->fctl       = tlink->fctl;
3444                lattr->speed      = tlink->speed;
3445                lattr->deskew     = be32_to_cpu(tlink->deskew);
3446
3447                if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
3448                        fcport->speed    = tlink->speed;
3449                        fcport->topology = BFA_PORT_TOPOLOGY_P2P;
3450                        link_bm |= 1 << i;
3451                }
3452
3453                bfa_trc(fcport->bfa, lattr->link_state);
3454                bfa_trc(fcport->bfa, lattr->trunk_wwn);
3455                bfa_trc(fcport->bfa, lattr->fctl);
3456                bfa_trc(fcport->bfa, lattr->speed);
3457                bfa_trc(fcport->bfa, lattr->deskew);
3458        }
3459
3460        switch (link_bm) {
3461        case 3:
3462                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3463                        BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
3464                break;
3465        case 2:
3466                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3467                        BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
3468                break;
3469        case 1:
3470                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3471                        BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
3472                break;
3473        default:
3474                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3475                        BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
3476        }
3477
3478        /*
3479         * Notify upper layers if trunk state changed.
3480         */
3481        if ((state_prev != trunk->attr.state) ||
3482                (scn->trunk_state == BFA_TRUNK_OFFLINE)) {
3483                bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
3484                        BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
3485        }
3486}
3487
3488static void
3489bfa_trunk_iocdisable(struct bfa_s *bfa)
3490{
3491        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3492        int i = 0;
3493
3494        /*
3495         * In trunked mode, notify upper layers that link is down
3496         */
3497        if (fcport->cfg.trunked) {
3498                if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
3499                        bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
3500
3501                fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
3502                fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
3503                for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3504                        fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
3505                        fcport->trunk.attr.link_attr[i].fctl =
3506                                                BFA_TRUNK_LINK_FCTL_NORMAL;
3507                        fcport->trunk.attr.link_attr[i].link_state =
3508                                                BFA_TRUNK_LINK_STATE_DN_LINKDN;
3509                        fcport->trunk.attr.link_attr[i].speed =
3510                                                BFA_PORT_SPEED_UNKNOWN;
3511                        fcport->trunk.attr.link_attr[i].deskew = 0;
3512                }
3513        }
3514}
3515
3516/*
3517 * Called to initialize port attributes
3518 */
3519void
3520bfa_fcport_init(struct bfa_s *bfa)
3521{
3522        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3523
3524        /*
3525         * Initialize port attributes from IOC hardware data.
3526         */
3527        bfa_fcport_set_wwns(fcport);
3528        if (fcport->cfg.maxfrsize == 0)
3529                fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
3530        fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
3531        fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
3532
3533        if (bfa_fcport_is_pbcdisabled(bfa))
3534                bfa->modules.port.pbc_disabled = BFA_TRUE;
3535
3536        WARN_ON(!fcport->cfg.maxfrsize);
3537        WARN_ON(!fcport->cfg.rx_bbcredit);
3538        WARN_ON(!fcport->speed_sup);
3539}
3540
3541/*
3542 * Firmware message handler.
3543 */
3544void
3545bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
3546{
3547        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3548        union bfi_fcport_i2h_msg_u i2hmsg;
3549
3550        i2hmsg.msg = msg;
3551        fcport->event_arg.i2hmsg = i2hmsg;
3552
3553        bfa_trc(bfa, msg->mhdr.msg_id);
3554        bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
3555
3556        switch (msg->mhdr.msg_id) {
3557        case BFI_FCPORT_I2H_ENABLE_RSP:
3558                if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
3559
3560                        fcport->stats_dma_ready = BFA_TRUE;
3561                        if (fcport->use_flash_cfg) {
3562                                fcport->cfg = i2hmsg.penable_rsp->port_cfg;
3563                                fcport->cfg.maxfrsize =
3564                                        cpu_to_be16(fcport->cfg.maxfrsize);
3565                                fcport->cfg.path_tov =
3566                                        cpu_to_be16(fcport->cfg.path_tov);
3567                                fcport->cfg.q_depth =
3568                                        cpu_to_be16(fcport->cfg.q_depth);
3569
3570                                if (fcport->cfg.trunked)
3571                                        fcport->trunk.attr.state =
3572                                                BFA_TRUNK_OFFLINE;
3573                                else
3574                                        fcport->trunk.attr.state =
3575                                                BFA_TRUNK_DISABLED;
3576                                fcport->qos_attr.qos_bw =
3577                                        i2hmsg.penable_rsp->port_cfg.qos_bw;
3578                                fcport->use_flash_cfg = BFA_FALSE;
3579                        }
3580
3581                        if (fcport->cfg.qos_enabled)
3582                                fcport->qos_attr.state = BFA_QOS_OFFLINE;
3583                        else
3584                                fcport->qos_attr.state = BFA_QOS_DISABLED;
3585
3586                        fcport->qos_attr.qos_bw_op =
3587                                        i2hmsg.penable_rsp->port_cfg.qos_bw;
3588
3589                        if (fcport->cfg.bb_cr_enabled)
3590                                fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3591                        else
3592                                fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3593
3594                        bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3595                }
3596                break;
3597
3598        case BFI_FCPORT_I2H_DISABLE_RSP:
3599                if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
3600                        bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3601                break;
3602
3603        case BFI_FCPORT_I2H_EVENT:
3604                if (fcport->cfg.bb_cr_enabled)
3605                        fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3606                else
3607                        fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3608
3609                if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
3610                        bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
3611                else {
3612                        if (i2hmsg.event->link_state.linkstate_rsn ==
3613                            BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG)
3614                                bfa_sm_send_event(fcport,
3615                                                  BFA_FCPORT_SM_FAA_MISCONFIG);
3616                        else
3617                                bfa_sm_send_event(fcport,
3618                                                  BFA_FCPORT_SM_LINKDOWN);
3619                }
3620                fcport->qos_attr.qos_bw_op =
3621                                i2hmsg.event->link_state.qos_attr.qos_bw_op;
3622                break;
3623
3624        case BFI_FCPORT_I2H_TRUNK_SCN:
3625                bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
3626                break;
3627
3628        case BFI_FCPORT_I2H_STATS_GET_RSP:
3629                /*
3630                 * check for timer pop before processing the rsp
3631                 */
3632                if (list_empty(&fcport->stats_pending_q) ||
3633                    (fcport->stats_status == BFA_STATUS_ETIMER))
3634                        break;
3635
3636                bfa_timer_stop(&fcport->timer);
3637                fcport->stats_status = i2hmsg.pstatsget_rsp->status;
3638                __bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3639                break;
3640
3641        case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
3642                /*
3643                 * check for timer pop before processing the rsp
3644                 */
3645                if (list_empty(&fcport->statsclr_pending_q) ||
3646                    (fcport->stats_status == BFA_STATUS_ETIMER))
3647                        break;
3648
3649                bfa_timer_stop(&fcport->timer);
3650                fcport->stats_status = BFA_STATUS_OK;
3651                __bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3652                break;
3653
3654        case BFI_FCPORT_I2H_ENABLE_AEN:
3655                bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
3656                break;
3657
3658        case BFI_FCPORT_I2H_DISABLE_AEN:
3659                bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
3660                break;
3661
3662        default:
3663                WARN_ON(1);
3664        break;
3665        }
3666}
3667
3668/*
3669 * Registered callback for port events.
3670 */
3671void
3672bfa_fcport_event_register(struct bfa_s *bfa,
3673                                void (*cbfn) (void *cbarg,
3674                                enum bfa_port_linkstate event),
3675                                void *cbarg)
3676{
3677        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3678
3679        fcport->event_cbfn = cbfn;
3680        fcport->event_cbarg = cbarg;
3681}
3682
3683bfa_status_t
3684bfa_fcport_enable(struct bfa_s *bfa)
3685{
3686        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3687
3688        if (bfa_fcport_is_pbcdisabled(bfa))
3689                return BFA_STATUS_PBC;
3690
3691        if (bfa_ioc_is_disabled(&bfa->ioc))
3692                return BFA_STATUS_IOC_DISABLED;
3693
3694        if (fcport->diag_busy)
3695                return BFA_STATUS_DIAG_BUSY;
3696
3697        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
3698        return BFA_STATUS_OK;
3699}
3700
3701bfa_status_t
3702bfa_fcport_disable(struct bfa_s *bfa)
3703{
3704        if (bfa_fcport_is_pbcdisabled(bfa))
3705                return BFA_STATUS_PBC;
3706
3707        if (bfa_ioc_is_disabled(&bfa->ioc))
3708                return BFA_STATUS_IOC_DISABLED;
3709
3710        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
3711        return BFA_STATUS_OK;
3712}
3713
3714/* If PBC is disabled on port, return error */
3715bfa_status_t
3716bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)
3717{
3718        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3719        struct bfa_iocfc_s *iocfc = &bfa->iocfc;
3720        struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
3721
3722        if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
3723                bfa_trc(bfa, fcport->pwwn);
3724                return BFA_STATUS_PBC;
3725        }
3726        return BFA_STATUS_OK;
3727}
3728
3729/*
3730 * Configure port speed.
3731 */
3732bfa_status_t
3733bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
3734{
3735        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3736
3737        bfa_trc(bfa, speed);
3738
3739        if (fcport->cfg.trunked == BFA_TRUE)
3740                return BFA_STATUS_TRUNK_ENABLED;
3741        if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
3742                        (speed == BFA_PORT_SPEED_16GBPS))
3743                return BFA_STATUS_UNSUPP_SPEED;
3744        if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
3745                bfa_trc(bfa, fcport->speed_sup);
3746                return BFA_STATUS_UNSUPP_SPEED;
3747        }
3748
3749        /* Port speed entered needs to be checked */
3750        if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {
3751                /* For CT2, 1G is not supported */
3752                if ((speed == BFA_PORT_SPEED_1GBPS) &&
3753                    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
3754                        return BFA_STATUS_UNSUPP_SPEED;
3755
3756                /* Already checked for Auto Speed and Max Speed supp */
3757                if (!(speed == BFA_PORT_SPEED_1GBPS ||
3758                      speed == BFA_PORT_SPEED_2GBPS ||
3759                      speed == BFA_PORT_SPEED_4GBPS ||
3760                      speed == BFA_PORT_SPEED_8GBPS ||
3761                      speed == BFA_PORT_SPEED_16GBPS ||
3762                      speed == BFA_PORT_SPEED_AUTO))
3763                        return BFA_STATUS_UNSUPP_SPEED;
3764        } else {
3765                if (speed != BFA_PORT_SPEED_10GBPS)
3766                        return BFA_STATUS_UNSUPP_SPEED;
3767        }
3768
3769        fcport->cfg.speed = speed;
3770
3771        return BFA_STATUS_OK;
3772}
3773
3774/*
3775 * Get current speed.
3776 */
3777enum bfa_port_speed
3778bfa_fcport_get_speed(struct bfa_s *bfa)
3779{
3780        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3781
3782        return fcport->speed;
3783}
3784
3785/*
3786 * Configure port topology.
3787 */
3788bfa_status_t
3789bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
3790{
3791        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3792
3793        bfa_trc(bfa, topology);
3794        bfa_trc(bfa, fcport->cfg.topology);
3795
3796        switch (topology) {
3797        case BFA_PORT_TOPOLOGY_P2P:
3798                break;
3799
3800        case BFA_PORT_TOPOLOGY_LOOP:
3801                if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
3802                        (fcport->qos_attr.state != BFA_QOS_DISABLED))
3803                        return BFA_STATUS_ERROR_QOS_ENABLED;
3804                if (fcport->cfg.ratelimit != BFA_FALSE)
3805                        return BFA_STATUS_ERROR_TRL_ENABLED;
3806                if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
3807                        (fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
3808                        return BFA_STATUS_ERROR_TRUNK_ENABLED;
3809                if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
3810                        (fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
3811                        return BFA_STATUS_UNSUPP_SPEED;
3812                if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
3813                        return BFA_STATUS_LOOP_UNSUPP_MEZZ;
3814                if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
3815                        return BFA_STATUS_DPORT_ERR;
3816                if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)
3817                        return BFA_STATUS_DPORT_ERR;
3818                break;
3819
3820        case BFA_PORT_TOPOLOGY_AUTO:
3821                break;
3822
3823        default:
3824                return BFA_STATUS_EINVAL;
3825        }
3826
3827        fcport->cfg.topology = topology;
3828        return BFA_STATUS_OK;
3829}
3830
3831/*
3832 * Get current topology.
3833 */
3834enum bfa_port_topology
3835bfa_fcport_get_topology(struct bfa_s *bfa)
3836{
3837        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3838
3839        return fcport->topology;
3840}
3841
3842/*
3843 * Get config topology.
3844 */
3845enum bfa_port_topology
3846bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
3847{
3848        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3849
3850        return fcport->cfg.topology;
3851}
3852
3853bfa_status_t
3854bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
3855{
3856        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3857
3858        bfa_trc(bfa, alpa);
3859        bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3860        bfa_trc(bfa, fcport->cfg.hardalpa);
3861
3862        fcport->cfg.cfg_hardalpa = BFA_TRUE;
3863        fcport->cfg.hardalpa = alpa;
3864
3865        return BFA_STATUS_OK;
3866}
3867
3868bfa_status_t
3869bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
3870{
3871        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3872
3873        bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3874        bfa_trc(bfa, fcport->cfg.hardalpa);
3875
3876        fcport->cfg.cfg_hardalpa = BFA_FALSE;
3877        return BFA_STATUS_OK;
3878}
3879
3880bfa_boolean_t
3881bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
3882{
3883        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3884
3885        *alpa = fcport->cfg.hardalpa;
3886        return fcport->cfg.cfg_hardalpa;
3887}
3888
3889u8
3890bfa_fcport_get_myalpa(struct bfa_s *bfa)
3891{
3892        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3893
3894        return fcport->myalpa;
3895}
3896
3897bfa_status_t
3898bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
3899{
3900        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3901
3902        bfa_trc(bfa, maxfrsize);
3903        bfa_trc(bfa, fcport->cfg.maxfrsize);
3904
3905        /* with in range */
3906        if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
3907                return BFA_STATUS_INVLD_DFSZ;
3908
3909        /* power of 2, if not the max frame size of 2112 */
3910        if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
3911                return BFA_STATUS_INVLD_DFSZ;
3912
3913        fcport->cfg.maxfrsize = maxfrsize;
3914        return BFA_STATUS_OK;
3915}
3916
3917u16
3918bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
3919{
3920        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3921
3922        return fcport->cfg.maxfrsize;
3923}
3924
3925u8
3926bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
3927{
3928        if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
3929                return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
3930
3931        else
3932                return 0;
3933}
3934
3935void
3936bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
3937{
3938        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3939
3940        fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
3941}
3942
3943/*
3944 * Get port attributes.
3945 */
3946
3947wwn_t
3948bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
3949{
3950        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3951        if (node)
3952                return fcport->nwwn;
3953        else
3954                return fcport->pwwn;
3955}
3956
3957void
3958bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
3959{
3960        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3961
3962        memset(attr, 0, sizeof(struct bfa_port_attr_s));
3963
3964        attr->nwwn = fcport->nwwn;
3965        attr->pwwn = fcport->pwwn;
3966
3967        attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn;
3968        attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;
3969
3970        memcpy(&attr->pport_cfg, &fcport->cfg,
3971                sizeof(struct bfa_port_cfg_s));
3972        /* speed attributes */
3973        attr->pport_cfg.speed = fcport->cfg.speed;
3974        attr->speed_supported = fcport->speed_sup;
3975        attr->speed = fcport->speed;
3976        attr->cos_supported = FC_CLASS_3;
3977
3978        /* topology attributes */
3979        attr->pport_cfg.topology = fcport->cfg.topology;
3980        attr->topology = fcport->topology;
3981        attr->pport_cfg.trunked = fcport->cfg.trunked;
3982
3983        /* beacon attributes */
3984        attr->beacon = fcport->beacon;
3985        attr->link_e2e_beacon = fcport->link_e2e_beacon;
3986
3987        attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
3988        attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
3989        attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
3990
3991        attr->fec_state = fcport->fec_state;
3992
3993        /* PBC Disabled State */
3994        if (bfa_fcport_is_pbcdisabled(bfa))
3995                attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;
3996        else {
3997                if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
3998                        attr->port_state = BFA_PORT_ST_IOCDIS;
3999                else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
4000                        attr->port_state = BFA_PORT_ST_FWMISMATCH;
4001        }
4002
4003        /* FCoE vlan */
4004        attr->fcoe_vlan = fcport->fcoe_vlan;
4005}
4006
4007#define BFA_FCPORT_STATS_TOV    1000
4008
4009/*
4010 * Fetch port statistics (FCQoS or FCoE).
4011 */
4012bfa_status_t
4013bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4014{
4015        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4016
4017        if (!bfa_iocfc_is_operational(bfa) ||
4018            !fcport->stats_dma_ready)
4019                return BFA_STATUS_IOC_NON_OP;
4020
4021        if (!list_empty(&fcport->statsclr_pending_q))
4022                return BFA_STATUS_DEVBUSY;
4023
4024        if (list_empty(&fcport->stats_pending_q)) {
4025                list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4026                bfa_fcport_send_stats_get(fcport);
4027                bfa_timer_start(bfa, &fcport->timer,
4028                                bfa_fcport_stats_get_timeout,
4029                                fcport, BFA_FCPORT_STATS_TOV);
4030        } else
4031                list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4032
4033        return BFA_STATUS_OK;
4034}
4035
4036/*
4037 * Reset port statistics (FCQoS or FCoE).
4038 */
4039bfa_status_t
4040bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4041{
4042        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4043
4044        if (!bfa_iocfc_is_operational(bfa) ||
4045            !fcport->stats_dma_ready)
4046                return BFA_STATUS_IOC_NON_OP;
4047
4048        if (!list_empty(&fcport->stats_pending_q))
4049                return BFA_STATUS_DEVBUSY;
4050
4051        if (list_empty(&fcport->statsclr_pending_q)) {
4052                list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4053                bfa_fcport_send_stats_clear(fcport);
4054                bfa_timer_start(bfa, &fcport->timer,
4055                                bfa_fcport_stats_clr_timeout,
4056                                fcport, BFA_FCPORT_STATS_TOV);
4057        } else
4058                list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4059
4060        return BFA_STATUS_OK;
4061}
4062
4063/*
4064 * Fetch port attributes.
4065 */
4066bfa_boolean_t
4067bfa_fcport_is_disabled(struct bfa_s *bfa)
4068{
4069        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4070
4071        return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4072                BFA_PORT_ST_DISABLED;
4073
4074}
4075
4076bfa_boolean_t
4077bfa_fcport_is_dport(struct bfa_s *bfa)
4078{
4079        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4080
4081        return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4082                BFA_PORT_ST_DPORT);
4083}
4084
4085bfa_boolean_t
4086bfa_fcport_is_ddport(struct bfa_s *bfa)
4087{
4088        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4089
4090        return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4091                BFA_PORT_ST_DDPORT);
4092}
4093
4094bfa_status_t
4095bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
4096{
4097        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4098        enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
4099
4100        bfa_trc(bfa, ioc_type);
4101
4102        if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0))
4103                return BFA_STATUS_QOS_BW_INVALID;
4104
4105        if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100)
4106                return BFA_STATUS_QOS_BW_INVALID;
4107
4108        if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) ||
4109            (qos_bw->low > qos_bw->high))
4110                return BFA_STATUS_QOS_BW_INVALID;
4111
4112        if ((ioc_type == BFA_IOC_TYPE_FC) &&
4113            (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP))
4114                fcport->cfg.qos_bw = *qos_bw;
4115
4116        return BFA_STATUS_OK;
4117}
4118
4119bfa_boolean_t
4120bfa_fcport_is_ratelim(struct bfa_s *bfa)
4121{
4122        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4123
4124        return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
4125
4126}
4127
4128/*
4129 *      Enable/Disable FAA feature in port config
4130 */
4131void
4132bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)
4133{
4134        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4135
4136        bfa_trc(bfa, state);
4137        fcport->cfg.faa_state = state;
4138}
4139
4140/*
4141 * Get default minimum ratelim speed
4142 */
4143enum bfa_port_speed
4144bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
4145{
4146        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4147
4148        bfa_trc(bfa, fcport->cfg.trl_def_speed);
4149        return fcport->cfg.trl_def_speed;
4150
4151}
4152
4153void
4154bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
4155                  bfa_boolean_t link_e2e_beacon)
4156{
4157        struct bfa_s *bfa = dev;
4158        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4159
4160        bfa_trc(bfa, beacon);
4161        bfa_trc(bfa, link_e2e_beacon);
4162        bfa_trc(bfa, fcport->beacon);
4163        bfa_trc(bfa, fcport->link_e2e_beacon);
4164
4165        fcport->beacon = beacon;
4166        fcport->link_e2e_beacon = link_e2e_beacon;
4167}
4168
4169bfa_boolean_t
4170bfa_fcport_is_linkup(struct bfa_s *bfa)
4171{
4172        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4173
4174        return  (!fcport->cfg.trunked &&
4175                 bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
4176                (fcport->cfg.trunked &&
4177                 fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
4178}
4179
4180bfa_boolean_t
4181bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
4182{
4183        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4184
4185        return fcport->cfg.qos_enabled;
4186}
4187
4188bfa_boolean_t
4189bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
4190{
4191        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4192
4193        return fcport->cfg.trunked;
4194}
4195
4196bfa_status_t
4197bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)
4198{
4199        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4200
4201        bfa_trc(bfa, on_off);
4202
4203        if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4204                return BFA_STATUS_BBCR_FC_ONLY;
4205
4206        if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) &&
4207                (bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK))
4208                return BFA_STATUS_CMD_NOTSUPP_MEZZ;
4209
4210        if (on_off) {
4211                if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4212                        return BFA_STATUS_TOPOLOGY_LOOP;
4213
4214                if (fcport->cfg.qos_enabled)
4215                        return BFA_STATUS_ERROR_QOS_ENABLED;
4216
4217                if (fcport->cfg.trunked)
4218                        return BFA_STATUS_TRUNK_ENABLED;
4219
4220                if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) &&
4221                        (fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc)))
4222                        return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT;
4223
4224                if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS)
4225                        return BFA_STATUS_FEATURE_NOT_SUPPORTED;
4226
4227                if (fcport->cfg.bb_cr_enabled) {
4228                        if (bb_scn != fcport->cfg.bb_scn)
4229                                return BFA_STATUS_BBCR_CFG_NO_CHANGE;
4230                        else
4231                                return BFA_STATUS_NO_CHANGE;
4232                }
4233
4234                if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX))
4235                        bb_scn = BFA_BB_SCN_DEF;
4236
4237                fcport->cfg.bb_cr_enabled = on_off;
4238                fcport->cfg.bb_scn = bb_scn;
4239        } else {
4240                if (!fcport->cfg.bb_cr_enabled)
4241                        return BFA_STATUS_NO_CHANGE;
4242
4243                fcport->cfg.bb_cr_enabled = on_off;
4244                fcport->cfg.bb_scn = 0;
4245        }
4246
4247        return BFA_STATUS_OK;
4248}
4249
4250bfa_status_t
4251bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
4252                struct bfa_bbcr_attr_s *bbcr_attr)
4253{
4254        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4255
4256        if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4257                return BFA_STATUS_BBCR_FC_ONLY;
4258
4259        if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4260                return BFA_STATUS_TOPOLOGY_LOOP;
4261
4262        *bbcr_attr = fcport->bbcr_attr;
4263
4264        return BFA_STATUS_OK;
4265}
4266
4267void
4268bfa_fcport_dportenable(struct bfa_s *bfa)
4269{
4270        /*
4271         * Assume caller check for port is in disable state
4272         */
4273        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);
4274        bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);
4275}
4276
4277void
4278bfa_fcport_dportdisable(struct bfa_s *bfa)
4279{
4280        /*
4281         * Assume caller check for port is in disable state
4282         */
4283        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);
4284        bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
4285}
4286
4287static void
4288bfa_fcport_ddportenable(struct bfa_s *bfa)
4289{
4290        /*
4291         * Assume caller check for port is in disable state
4292         */
4293        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
4294}
4295
4296static void
4297bfa_fcport_ddportdisable(struct bfa_s *bfa)
4298{
4299        /*
4300         * Assume caller check for port is in disable state
4301         */
4302        bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);
4303}
4304
4305/*
4306 * Rport State machine functions
4307 */
4308/*
4309 * Beginning state, only online event expected.
4310 */
4311static void
4312bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
4313{
4314        bfa_trc(rp->bfa, rp->rport_tag);
4315        bfa_trc(rp->bfa, event);
4316
4317        switch (event) {
4318        case BFA_RPORT_SM_CREATE:
4319                bfa_stats(rp, sm_un_cr);
4320                bfa_sm_set_state(rp, bfa_rport_sm_created);
4321                break;
4322
4323        default:
4324                bfa_stats(rp, sm_un_unexp);
4325                bfa_sm_fault(rp->bfa, event);
4326        }
4327}
4328
4329static void
4330bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
4331{
4332        bfa_trc(rp->bfa, rp->rport_tag);
4333        bfa_trc(rp->bfa, event);
4334
4335        switch (event) {
4336        case BFA_RPORT_SM_ONLINE:
4337                bfa_stats(rp, sm_cr_on);
4338                if (bfa_rport_send_fwcreate(rp))
4339                        bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4340                else
4341                        bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4342                break;
4343
4344        case BFA_RPORT_SM_DELETE:
4345                bfa_stats(rp, sm_cr_del);
4346                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4347                bfa_rport_free(rp);
4348                break;
4349
4350        case BFA_RPORT_SM_HWFAIL:
4351                bfa_stats(rp, sm_cr_hwf);
4352                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4353                break;
4354
4355        default:
4356                bfa_stats(rp, sm_cr_unexp);
4357                bfa_sm_fault(rp->bfa, event);
4358        }
4359}
4360
4361/*
4362 * Waiting for rport create response from firmware.
4363 */
4364static void
4365bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
4366{
4367        bfa_trc(rp->bfa, rp->rport_tag);
4368        bfa_trc(rp->bfa, event);
4369
4370        switch (event) {
4371        case BFA_RPORT_SM_FWRSP:
4372                bfa_stats(rp, sm_fwc_rsp);
4373                bfa_sm_set_state(rp, bfa_rport_sm_online);
4374                bfa_rport_online_cb(rp);
4375                break;
4376
4377        case BFA_RPORT_SM_DELETE:
4378                bfa_stats(rp, sm_fwc_del);
4379                bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4380                break;
4381
4382        case BFA_RPORT_SM_OFFLINE:
4383                bfa_stats(rp, sm_fwc_off);
4384                bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
4385                break;
4386
4387        case BFA_RPORT_SM_HWFAIL:
4388                bfa_stats(rp, sm_fwc_hwf);
4389                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4390                break;
4391
4392        default:
4393                bfa_stats(rp, sm_fwc_unexp);
4394                bfa_sm_fault(rp->bfa, event);
4395        }
4396}
4397
4398/*
4399 * Request queue is full, awaiting queue resume to send create request.
4400 */
4401static void
4402bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4403{
4404        bfa_trc(rp->bfa, rp->rport_tag);
4405        bfa_trc(rp->bfa, event);
4406
4407        switch (event) {
4408        case BFA_RPORT_SM_QRESUME:
4409                bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4410                bfa_rport_send_fwcreate(rp);
4411                break;
4412
4413        case BFA_RPORT_SM_DELETE:
4414                bfa_stats(rp, sm_fwc_del);
4415                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4416                bfa_reqq_wcancel(&rp->reqq_wait);
4417                bfa_rport_free(rp);
4418                break;
4419
4420        case BFA_RPORT_SM_OFFLINE:
4421                bfa_stats(rp, sm_fwc_off);
4422                bfa_sm_set_state(rp, bfa_rport_sm_offline);
4423                bfa_reqq_wcancel(&rp->reqq_wait);
4424                bfa_rport_offline_cb(rp);
4425                break;
4426
4427        case BFA_RPORT_SM_HWFAIL:
4428                bfa_stats(rp, sm_fwc_hwf);
4429                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4430                bfa_reqq_wcancel(&rp->reqq_wait);
4431                break;
4432
4433        default:
4434                bfa_stats(rp, sm_fwc_unexp);
4435                bfa_sm_fault(rp->bfa, event);
4436        }
4437}
4438
4439/*
4440 * Online state - normal parking state.
4441 */
4442static void
4443bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
4444{
4445        struct bfi_rport_qos_scn_s *qos_scn;
4446
4447        bfa_trc(rp->bfa, rp->rport_tag);
4448        bfa_trc(rp->bfa, event);
4449
4450        switch (event) {
4451        case BFA_RPORT_SM_OFFLINE:
4452                bfa_stats(rp, sm_on_off);
4453                if (bfa_rport_send_fwdelete(rp))
4454                        bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4455                else
4456                        bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4457                break;
4458
4459        case BFA_RPORT_SM_DELETE:
4460                bfa_stats(rp, sm_on_del);
4461                if (bfa_rport_send_fwdelete(rp))
4462                        bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4463                else
4464                        bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4465                break;
4466
4467        case BFA_RPORT_SM_HWFAIL:
4468                bfa_stats(rp, sm_on_hwf);
4469                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4470                break;
4471
4472        case BFA_RPORT_SM_SET_SPEED:
4473                bfa_rport_send_fwspeed(rp);
4474                break;
4475
4476        case BFA_RPORT_SM_QOS_SCN:
4477                qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
4478                rp->qos_attr = qos_scn->new_qos_attr;
4479                bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
4480                bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
4481                bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
4482                bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
4483
4484                qos_scn->old_qos_attr.qos_flow_id  =
4485                        be32_to_cpu(qos_scn->old_qos_attr.qos_flow_id);
4486                qos_scn->new_qos_attr.qos_flow_id  =
4487                        be32_to_cpu(qos_scn->new_qos_attr.qos_flow_id);
4488
4489                if (qos_scn->old_qos_attr.qos_flow_id !=
4490                        qos_scn->new_qos_attr.qos_flow_id)
4491                        bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
4492                                                    qos_scn->old_qos_attr,
4493                                                    qos_scn->new_qos_attr);
4494                if (qos_scn->old_qos_attr.qos_priority !=
4495                        qos_scn->new_qos_attr.qos_priority)
4496                        bfa_cb_rport_qos_scn_prio(rp->rport_drv,
4497                                                  qos_scn->old_qos_attr,
4498                                                  qos_scn->new_qos_attr);
4499                break;
4500
4501        default:
4502                bfa_stats(rp, sm_on_unexp);
4503                bfa_sm_fault(rp->bfa, event);
4504        }
4505}
4506
4507/*
4508 * Firmware rport is being deleted - awaiting f/w response.
4509 */
4510static void
4511bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
4512{
4513        bfa_trc(rp->bfa, rp->rport_tag);
4514        bfa_trc(rp->bfa, event);
4515
4516        switch (event) {
4517        case BFA_RPORT_SM_FWRSP:
4518                bfa_stats(rp, sm_fwd_rsp);
4519                bfa_sm_set_state(rp, bfa_rport_sm_offline);
4520                bfa_rport_offline_cb(rp);
4521                break;
4522
4523        case BFA_RPORT_SM_DELETE:
4524                bfa_stats(rp, sm_fwd_del);
4525                bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4526                break;
4527
4528        case BFA_RPORT_SM_HWFAIL:
4529                bfa_stats(rp, sm_fwd_hwf);
4530                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4531                bfa_rport_offline_cb(rp);
4532                break;
4533
4534        default:
4535                bfa_stats(rp, sm_fwd_unexp);
4536                bfa_sm_fault(rp->bfa, event);
4537        }
4538}
4539
4540static void
4541bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4542{
4543        bfa_trc(rp->bfa, rp->rport_tag);
4544        bfa_trc(rp->bfa, event);
4545
4546        switch (event) {
4547        case BFA_RPORT_SM_QRESUME:
4548                bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4549                bfa_rport_send_fwdelete(rp);
4550                break;
4551
4552        case BFA_RPORT_SM_DELETE:
4553                bfa_stats(rp, sm_fwd_del);
4554                bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4555                break;
4556
4557        case BFA_RPORT_SM_HWFAIL:
4558                bfa_stats(rp, sm_fwd_hwf);
4559                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4560                bfa_reqq_wcancel(&rp->reqq_wait);
4561                bfa_rport_offline_cb(rp);
4562                break;
4563
4564        default:
4565                bfa_stats(rp, sm_fwd_unexp);
4566                bfa_sm_fault(rp->bfa, event);
4567        }
4568}
4569
4570/*
4571 * Offline state.
4572 */
4573static void
4574bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
4575{
4576        bfa_trc(rp->bfa, rp->rport_tag);
4577        bfa_trc(rp->bfa, event);
4578
4579        switch (event) {
4580        case BFA_RPORT_SM_DELETE:
4581                bfa_stats(rp, sm_off_del);
4582                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4583                bfa_rport_free(rp);
4584                break;
4585
4586        case BFA_RPORT_SM_ONLINE:
4587                bfa_stats(rp, sm_off_on);
4588                if (bfa_rport_send_fwcreate(rp))
4589                        bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4590                else
4591                        bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4592                break;
4593
4594        case BFA_RPORT_SM_HWFAIL:
4595                bfa_stats(rp, sm_off_hwf);
4596                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4597                break;
4598
4599        case BFA_RPORT_SM_OFFLINE:
4600                bfa_rport_offline_cb(rp);
4601                break;
4602
4603        default:
4604                bfa_stats(rp, sm_off_unexp);
4605                bfa_sm_fault(rp->bfa, event);
4606        }
4607}
4608
4609/*
4610 * Rport is deleted, waiting for firmware response to delete.
4611 */
4612static void
4613bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
4614{
4615        bfa_trc(rp->bfa, rp->rport_tag);
4616        bfa_trc(rp->bfa, event);
4617
4618        switch (event) {
4619        case BFA_RPORT_SM_FWRSP:
4620                bfa_stats(rp, sm_del_fwrsp);
4621                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4622                bfa_rport_free(rp);
4623                break;
4624
4625        case BFA_RPORT_SM_HWFAIL:
4626                bfa_stats(rp, sm_del_hwf);
4627                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4628                bfa_rport_free(rp);
4629                break;
4630
4631        default:
4632                bfa_sm_fault(rp->bfa, event);
4633        }
4634}
4635
4636static void
4637bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4638{
4639        bfa_trc(rp->bfa, rp->rport_tag);
4640        bfa_trc(rp->bfa, event);
4641
4642        switch (event) {
4643        case BFA_RPORT_SM_QRESUME:
4644                bfa_stats(rp, sm_del_fwrsp);
4645                bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4646                bfa_rport_send_fwdelete(rp);
4647                break;
4648
4649        case BFA_RPORT_SM_HWFAIL:
4650                bfa_stats(rp, sm_del_hwf);
4651                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4652                bfa_reqq_wcancel(&rp->reqq_wait);
4653                bfa_rport_free(rp);
4654                break;
4655
4656        default:
4657                bfa_sm_fault(rp->bfa, event);
4658        }
4659}
4660
4661/*
4662 * Waiting for rport create response from firmware. A delete is pending.
4663 */
4664static void
4665bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
4666                                enum bfa_rport_event event)
4667{
4668        bfa_trc(rp->bfa, rp->rport_tag);
4669        bfa_trc(rp->bfa, event);
4670
4671        switch (event) {
4672        case BFA_RPORT_SM_FWRSP:
4673                bfa_stats(rp, sm_delp_fwrsp);
4674                if (bfa_rport_send_fwdelete(rp))
4675                        bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4676                else
4677                        bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4678                break;
4679
4680        case BFA_RPORT_SM_HWFAIL:
4681                bfa_stats(rp, sm_delp_hwf);
4682                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4683                bfa_rport_free(rp);
4684                break;
4685
4686        default:
4687                bfa_stats(rp, sm_delp_unexp);
4688                bfa_sm_fault(rp->bfa, event);
4689        }
4690}
4691
4692/*
4693 * Waiting for rport create response from firmware. Rport offline is pending.
4694 */
4695static void
4696bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
4697                                 enum bfa_rport_event event)
4698{
4699        bfa_trc(rp->bfa, rp->rport_tag);
4700        bfa_trc(rp->bfa, event);
4701
4702        switch (event) {
4703        case BFA_RPORT_SM_FWRSP:
4704                bfa_stats(rp, sm_offp_fwrsp);
4705                if (bfa_rport_send_fwdelete(rp))
4706                        bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4707                else
4708                        bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4709                break;
4710
4711        case BFA_RPORT_SM_DELETE:
4712                bfa_stats(rp, sm_offp_del);
4713                bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4714                break;
4715
4716        case BFA_RPORT_SM_HWFAIL:
4717                bfa_stats(rp, sm_offp_hwf);
4718                bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4719                bfa_rport_offline_cb(rp);
4720                break;
4721
4722        default:
4723                bfa_stats(rp, sm_offp_unexp);
4724                bfa_sm_fault(rp->bfa, event);
4725        }
4726}
4727
4728/*
4729 * IOC h/w failed.
4730 */
4731static void
4732bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
4733{
4734        bfa_trc(rp->bfa, rp->rport_tag);
4735        bfa_trc(rp->bfa, event);
4736
4737        switch (event) {
4738        case BFA_RPORT_SM_OFFLINE:
4739                bfa_stats(rp, sm_iocd_off);
4740                bfa_rport_offline_cb(rp);
4741                break;
4742
4743        case BFA_RPORT_SM_DELETE:
4744                bfa_stats(rp, sm_iocd_del);
4745                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4746                bfa_rport_free(rp);
4747                break;
4748
4749        case BFA_RPORT_SM_ONLINE:
4750                bfa_stats(rp, sm_iocd_on);
4751                if (bfa_rport_send_fwcreate(rp))
4752                        bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4753                else
4754                        bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4755                break;
4756
4757        case BFA_RPORT_SM_HWFAIL:
4758                break;
4759
4760        default:
4761                bfa_stats(rp, sm_iocd_unexp);
4762                bfa_sm_fault(rp->bfa, event);
4763        }
4764}
4765
4766
4767
4768/*
4769 *  bfa_rport_private BFA rport private functions
4770 */
4771
4772static void
4773__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
4774{
4775        struct bfa_rport_s *rp = cbarg;
4776
4777        if (complete)
4778                bfa_cb_rport_online(rp->rport_drv);
4779}
4780
4781static void
4782__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
4783{
4784        struct bfa_rport_s *rp = cbarg;
4785
4786        if (complete)
4787                bfa_cb_rport_offline(rp->rport_drv);
4788}
4789
4790static void
4791bfa_rport_qresume(void *cbarg)
4792{
4793        struct bfa_rport_s      *rp = cbarg;
4794
4795        bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
4796}
4797
4798void
4799bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
4800                struct bfa_s *bfa)
4801{
4802        struct bfa_mem_kva_s *rport_kva = BFA_MEM_RPORT_KVA(bfa);
4803
4804        if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
4805                cfg->fwcfg.num_rports = BFA_RPORT_MIN;
4806
4807        /* kva memory */
4808        bfa_mem_kva_setup(minfo, rport_kva,
4809                cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));
4810}
4811
4812void
4813bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4814                struct bfa_pcidev_s *pcidev)
4815{
4816        struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4817        struct bfa_rport_s *rp;
4818        u16 i;
4819
4820        INIT_LIST_HEAD(&mod->rp_free_q);
4821        INIT_LIST_HEAD(&mod->rp_active_q);
4822        INIT_LIST_HEAD(&mod->rp_unused_q);
4823
4824        rp = (struct bfa_rport_s *) bfa_mem_kva_curp(mod);
4825        mod->rps_list = rp;
4826        mod->num_rports = cfg->fwcfg.num_rports;
4827
4828        WARN_ON(!mod->num_rports ||
4829                   (mod->num_rports & (mod->num_rports - 1)));
4830
4831        for (i = 0; i < mod->num_rports; i++, rp++) {
4832                memset(rp, 0, sizeof(struct bfa_rport_s));
4833                rp->bfa = bfa;
4834                rp->rport_tag = i;
4835                bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4836
4837                /*
4838                 *  - is unused
4839                 */
4840                if (i)
4841                        list_add_tail(&rp->qe, &mod->rp_free_q);
4842
4843                bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
4844        }
4845
4846        /*
4847         * consume memory
4848         */
4849        bfa_mem_kva_curp(mod) = (u8 *) rp;
4850}
4851
4852void
4853bfa_rport_iocdisable(struct bfa_s *bfa)
4854{
4855        struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4856        struct bfa_rport_s *rport;
4857        struct list_head *qe, *qen;
4858
4859        /* Enqueue unused rport resources to free_q */
4860        list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q);
4861
4862        list_for_each_safe(qe, qen, &mod->rp_active_q) {
4863                rport = (struct bfa_rport_s *) qe;
4864                bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
4865        }
4866}
4867
4868static struct bfa_rport_s *
4869bfa_rport_alloc(struct bfa_rport_mod_s *mod)
4870{
4871        struct bfa_rport_s *rport;
4872
4873        bfa_q_deq(&mod->rp_free_q, &rport);
4874        if (rport)
4875                list_add_tail(&rport->qe, &mod->rp_active_q);
4876
4877        return rport;
4878}
4879
4880static void
4881bfa_rport_free(struct bfa_rport_s *rport)
4882{
4883        struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
4884
4885        WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));
4886        list_del(&rport->qe);
4887        list_add_tail(&rport->qe, &mod->rp_free_q);
4888}
4889
4890static bfa_boolean_t
4891bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
4892{
4893        struct bfi_rport_create_req_s *m;
4894
4895        /*
4896         * check for room in queue to send request now
4897         */
4898        m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4899        if (!m) {
4900                bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4901                return BFA_FALSE;
4902        }
4903
4904        bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
4905                        bfa_fn_lpu(rp->bfa));
4906        m->bfa_handle = rp->rport_tag;
4907        m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);
4908        m->pid = rp->rport_info.pid;
4909        m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);
4910        m->local_pid = rp->rport_info.local_pid;
4911        m->fc_class = rp->rport_info.fc_class;
4912        m->vf_en = rp->rport_info.vf_en;
4913        m->vf_id = rp->rport_info.vf_id;
4914        m->cisc = rp->rport_info.cisc;
4915
4916        /*
4917         * queue I/O message to firmware
4918         */
4919        bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4920        return BFA_TRUE;
4921}
4922
4923static bfa_boolean_t
4924bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
4925{
4926        struct bfi_rport_delete_req_s *m;
4927
4928        /*
4929         * check for room in queue to send request now
4930         */
4931        m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4932        if (!m) {
4933                bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4934                return BFA_FALSE;
4935        }
4936
4937        bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
4938                        bfa_fn_lpu(rp->bfa));
4939        m->fw_handle = rp->fw_handle;
4940
4941        /*
4942         * queue I/O message to firmware
4943         */
4944        bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4945        return BFA_TRUE;
4946}
4947
4948static bfa_boolean_t
4949bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
4950{
4951        struct bfa_rport_speed_req_s *m;
4952
4953        /*
4954         * check for room in queue to send request now
4955         */
4956        m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4957        if (!m) {
4958                bfa_trc(rp->bfa, rp->rport_info.speed);
4959                return BFA_FALSE;
4960        }
4961
4962        bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
4963                        bfa_fn_lpu(rp->bfa));
4964        m->fw_handle = rp->fw_handle;
4965        m->speed = (u8)rp->rport_info.speed;
4966
4967        /*
4968         * queue I/O message to firmware
4969         */
4970        bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4971        return BFA_TRUE;
4972}
4973
4974
4975
4976/*
4977 *  bfa_rport_public
4978 */
4979
4980/*
4981 * Rport interrupt processing.
4982 */
4983void
4984bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
4985{
4986        union bfi_rport_i2h_msg_u msg;
4987        struct bfa_rport_s *rp;
4988
4989        bfa_trc(bfa, m->mhdr.msg_id);
4990
4991        msg.msg = m;
4992
4993        switch (m->mhdr.msg_id) {
4994        case BFI_RPORT_I2H_CREATE_RSP:
4995                rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
4996                rp->fw_handle = msg.create_rsp->fw_handle;
4997                rp->qos_attr = msg.create_rsp->qos_attr;
4998                bfa_rport_set_lunmask(bfa, rp);
4999                WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
5000                bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
5001                break;
5002
5003        case BFI_RPORT_I2H_DELETE_RSP:
5004                rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
5005                WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
5006                bfa_rport_unset_lunmask(bfa, rp);
5007                bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
5008                break;
5009
5010        case BFI_RPORT_I2H_QOS_SCN:
5011                rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
5012                rp->event_arg.fw_msg = msg.qos_scn_evt;
5013                bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
5014                break;
5015
5016        case BFI_RPORT_I2H_LIP_SCN_ONLINE:
5017                bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),
5018                                &msg.lip_scn->loop_info);
5019                bfa_cb_rport_scn_online(bfa);
5020                break;
5021
5022        case BFI_RPORT_I2H_LIP_SCN_OFFLINE:
5023                bfa_cb_rport_scn_offline(bfa);
5024                break;
5025
5026        case BFI_RPORT_I2H_NO_DEV:
5027                rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);
5028                bfa_cb_rport_scn_no_dev(rp->rport_drv);
5029                break;
5030
5031        default:
5032                bfa_trc(bfa, m->mhdr.msg_id);
5033                WARN_ON(1);
5034        }
5035}
5036
5037void
5038bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw)
5039{
5040        struct bfa_rport_mod_s  *mod = BFA_RPORT_MOD(bfa);
5041        struct list_head        *qe;
5042        int     i;
5043
5044        for (i = 0; i < (mod->num_rports - num_rport_fw); i++) {
5045                bfa_q_deq_tail(&mod->rp_free_q, &qe);
5046                list_add_tail(qe, &mod->rp_unused_q);
5047        }
5048}
5049
5050/*
5051 *  bfa_rport_api
5052 */
5053
5054struct bfa_rport_s *
5055bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
5056{
5057        struct bfa_rport_s *rp;
5058
5059        rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
5060
5061        if (rp == NULL)
5062                return NULL;
5063
5064        rp->bfa = bfa;
5065        rp->rport_drv = rport_drv;
5066        memset(&rp->stats, 0, sizeof(rp->stats));
5067
5068        WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
5069        bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
5070
5071        return rp;
5072}
5073
5074void
5075bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
5076{
5077        WARN_ON(rport_info->max_frmsz == 0);
5078
5079        /*
5080         * Some JBODs are seen to be not setting PDU size correctly in PLOGI
5081         * responses. Default to minimum size.
5082         */
5083        if (rport_info->max_frmsz == 0) {
5084                bfa_trc(rport->bfa, rport->rport_tag);
5085                rport_info->max_frmsz = FC_MIN_PDUSZ;
5086        }
5087
5088        rport->rport_info = *rport_info;
5089        bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
5090}
5091
5092void
5093bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
5094{
5095        WARN_ON(speed == 0);
5096        WARN_ON(speed == BFA_PORT_SPEED_AUTO);
5097
5098        if (rport) {
5099                rport->rport_info.speed = speed;
5100                bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
5101        }
5102}
5103
5104/* Set Rport LUN Mask */
5105void
5106bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5107{
5108        struct bfa_lps_mod_s    *lps_mod = BFA_LPS_MOD(bfa);
5109        wwn_t   lp_wwn, rp_wwn;
5110        u8 lp_tag = (u8)rp->rport_info.lp_tag;
5111
5112        rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5113        lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5114
5115        BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5116                                        rp->lun_mask = BFA_TRUE;
5117        bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, rp->rport_tag, lp_tag);
5118}
5119
5120/* Unset Rport LUN mask */
5121void
5122bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5123{
5124        struct bfa_lps_mod_s    *lps_mod = BFA_LPS_MOD(bfa);
5125        wwn_t   lp_wwn, rp_wwn;
5126
5127        rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5128        lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5129
5130        BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5131                                rp->lun_mask = BFA_FALSE;
5132        bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn,
5133                        BFA_RPORT_TAG_INVALID, BFA_LP_TAG_INVALID);
5134}
5135
5136/*
5137 * SGPG related functions
5138 */
5139
5140/*
5141 * Compute and return memory needed by FCP(im) module.
5142 */
5143void
5144bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5145                struct bfa_s *bfa)
5146{
5147        struct bfa_sgpg_mod_s *sgpg_mod = BFA_SGPG_MOD(bfa);
5148        struct bfa_mem_kva_s *sgpg_kva = BFA_MEM_SGPG_KVA(bfa);
5149        struct bfa_mem_dma_s *seg_ptr;
5150        u16     nsegs, idx, per_seg_sgpg, num_sgpg;
5151        u32     sgpg_sz = sizeof(struct bfi_sgpg_s);
5152
5153        if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
5154                cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
5155        else if (cfg->drvcfg.num_sgpgs > BFA_SGPG_MAX)
5156                cfg->drvcfg.num_sgpgs = BFA_SGPG_MAX;
5157
5158        num_sgpg = cfg->drvcfg.num_sgpgs;
5159
5160        nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5161        per_seg_sgpg = BFI_MEM_NREQS_SEG(sgpg_sz);
5162
5163        bfa_mem_dma_seg_iter(sgpg_mod, seg_ptr, nsegs, idx) {
5164                if (num_sgpg >= per_seg_sgpg) {
5165                        num_sgpg -= per_seg_sgpg;
5166                        bfa_mem_dma_setup(minfo, seg_ptr,
5167                                        per_seg_sgpg * sgpg_sz);
5168                } else
5169                        bfa_mem_dma_setup(minfo, seg_ptr,
5170                                        num_sgpg * sgpg_sz);
5171        }
5172
5173        /* kva memory */
5174        bfa_mem_kva_setup(minfo, sgpg_kva,
5175                cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));
5176}
5177
5178void
5179bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5180                struct bfa_pcidev_s *pcidev)
5181{
5182        struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5183        struct bfa_sgpg_s *hsgpg;
5184        struct bfi_sgpg_s *sgpg;
5185        u64 align_len;
5186        struct bfa_mem_dma_s *seg_ptr;
5187        u32     sgpg_sz = sizeof(struct bfi_sgpg_s);
5188        u16     i, idx, nsegs, per_seg_sgpg, num_sgpg;
5189
5190        union {
5191                u64 pa;
5192                union bfi_addr_u addr;
5193        } sgpg_pa, sgpg_pa_tmp;
5194
5195        INIT_LIST_HEAD(&mod->sgpg_q);
5196        INIT_LIST_HEAD(&mod->sgpg_wait_q);
5197
5198        bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
5199
5200        mod->free_sgpgs = mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
5201
5202        num_sgpg = cfg->drvcfg.num_sgpgs;
5203        nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5204
5205        /* dma/kva mem claim */
5206        hsgpg = (struct bfa_sgpg_s *) bfa_mem_kva_curp(mod);
5207
5208        bfa_mem_dma_seg_iter(mod, seg_ptr, nsegs, idx) {
5209
5210                if (!bfa_mem_dma_virt(seg_ptr))
5211                        break;
5212
5213                align_len = BFA_SGPG_ROUNDUP(bfa_mem_dma_phys(seg_ptr)) -
5214                                             bfa_mem_dma_phys(seg_ptr);
5215
5216                sgpg = (struct bfi_sgpg_s *)
5217                        (((u8 *) bfa_mem_dma_virt(seg_ptr)) + align_len);
5218                sgpg_pa.pa = bfa_mem_dma_phys(seg_ptr) + align_len;
5219                WARN_ON(sgpg_pa.pa & (sgpg_sz - 1));
5220
5221                per_seg_sgpg = (seg_ptr->mem_len - (u32)align_len) / sgpg_sz;
5222
5223                for (i = 0; num_sgpg > 0 && i < per_seg_sgpg; i++, num_sgpg--) {
5224                        memset(hsgpg, 0, sizeof(*hsgpg));
5225                        memset(sgpg, 0, sizeof(*sgpg));
5226
5227                        hsgpg->sgpg = sgpg;
5228                        sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
5229                        hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
5230                        list_add_tail(&hsgpg->qe, &mod->sgpg_q);
5231
5232                        sgpg++;
5233                        hsgpg++;
5234                        sgpg_pa.pa += sgpg_sz;
5235                }
5236        }
5237
5238        bfa_mem_kva_curp(mod) = (u8 *) hsgpg;
5239}
5240
5241bfa_status_t
5242bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
5243{
5244        struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5245        struct bfa_sgpg_s *hsgpg;
5246        int i;
5247
5248        if (mod->free_sgpgs < nsgpgs)
5249                return BFA_STATUS_ENOMEM;
5250
5251        for (i = 0; i < nsgpgs; i++) {
5252                bfa_q_deq(&mod->sgpg_q, &hsgpg);
5253                WARN_ON(!hsgpg);
5254                list_add_tail(&hsgpg->qe, sgpg_q);
5255        }
5256
5257        mod->free_sgpgs -= nsgpgs;
5258        return BFA_STATUS_OK;
5259}
5260
5261void
5262bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
5263{
5264        struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5265        struct bfa_sgpg_wqe_s *wqe;
5266
5267        mod->free_sgpgs += nsgpg;
5268        WARN_ON(mod->free_sgpgs > mod->num_sgpgs);
5269
5270        list_splice_tail_init(sgpg_q, &mod->sgpg_q);
5271
5272        if (list_empty(&mod->sgpg_wait_q))
5273                return;
5274
5275        /*
5276         * satisfy as many waiting requests as possible
5277         */
5278        do {
5279                wqe = bfa_q_first(&mod->sgpg_wait_q);
5280                if (mod->free_sgpgs < wqe->nsgpg)
5281                        nsgpg = mod->free_sgpgs;
5282                else
5283                        nsgpg = wqe->nsgpg;
5284                bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
5285                wqe->nsgpg -= nsgpg;
5286                if (wqe->nsgpg == 0) {
5287                        list_del(&wqe->qe);
5288                        wqe->cbfn(wqe->cbarg);
5289                }
5290        } while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
5291}
5292
5293void
5294bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
5295{
5296        struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5297
5298        WARN_ON(nsgpg <= 0);
5299        WARN_ON(nsgpg <= mod->free_sgpgs);
5300
5301        wqe->nsgpg_total = wqe->nsgpg = nsgpg;
5302
5303        /*
5304         * allocate any left to this one first
5305         */
5306        if (mod->free_sgpgs) {
5307                /*
5308                 * no one else is waiting for SGPG
5309                 */
5310                WARN_ON(!list_empty(&mod->sgpg_wait_q));
5311                list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
5312                wqe->nsgpg -= mod->free_sgpgs;
5313                mod->free_sgpgs = 0;
5314        }
5315
5316        list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
5317}
5318
5319void
5320bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
5321{
5322        struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5323
5324        WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
5325        list_del(&wqe->qe);
5326
5327        if (wqe->nsgpg_total != wqe->nsgpg)
5328                bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
5329                                   wqe->nsgpg_total - wqe->nsgpg);
5330}
5331
5332void
5333bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
5334                   void *cbarg)
5335{
5336        INIT_LIST_HEAD(&wqe->sgpg_q);
5337        wqe->cbfn = cbfn;
5338        wqe->cbarg = cbarg;
5339}
5340
5341/*
5342 *  UF related functions
5343 */
5344/*
5345 *****************************************************************************
5346 * Internal functions
5347 *****************************************************************************
5348 */
5349static void
5350__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
5351{
5352        struct bfa_uf_s   *uf = cbarg;
5353        struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
5354
5355        if (complete)
5356                ufm->ufrecv(ufm->cbarg, uf);
5357}
5358
5359static void
5360claim_uf_post_msgs(struct bfa_uf_mod_s *ufm)
5361{
5362        struct bfi_uf_buf_post_s *uf_bp_msg;
5363        u16 i;
5364        u16 buf_len;
5365
5366        ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_mem_kva_curp(ufm);
5367        uf_bp_msg = ufm->uf_buf_posts;
5368
5369        for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
5370             i++, uf_bp_msg++) {
5371                memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
5372
5373                uf_bp_msg->buf_tag = i;
5374                buf_len = sizeof(struct bfa_uf_buf_s);
5375                uf_bp_msg->buf_len = cpu_to_be16(buf_len);
5376                bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
5377                            bfa_fn_lpu(ufm->bfa));
5378                bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));
5379        }
5380
5381        /*
5382         * advance pointer beyond consumed memory
5383         */
5384        bfa_mem_kva_curp(ufm) = (u8 *) uf_bp_msg;
5385}
5386
5387static void
5388claim_ufs(struct bfa_uf_mod_s *ufm)
5389{
5390        u16 i;
5391        struct bfa_uf_s   *uf;
5392
5393        /*
5394         * Claim block of memory for UF list
5395         */
5396        ufm->uf_list = (struct bfa_uf_s *) bfa_mem_kva_curp(ufm);
5397
5398        /*
5399         * Initialize UFs and queue it in UF free queue
5400         */
5401        for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
5402                memset(uf, 0, sizeof(struct bfa_uf_s));
5403                uf->bfa = ufm->bfa;
5404                uf->uf_tag = i;
5405                uf->pb_len = BFA_PER_UF_DMA_SZ;
5406                uf->buf_kva = bfa_mem_get_dmabuf_kva(ufm, i, BFA_PER_UF_DMA_SZ);
5407                uf->buf_pa = ufm_pbs_pa(ufm, i);
5408                list_add_tail(&uf->qe, &ufm->uf_free_q);
5409        }
5410
5411        /*
5412         * advance memory pointer
5413         */
5414        bfa_mem_kva_curp(ufm) = (u8 *) uf;
5415}
5416
5417static void
5418uf_mem_claim(struct bfa_uf_mod_s *ufm)
5419{
5420        claim_ufs(ufm);
5421        claim_uf_post_msgs(ufm);
5422}
5423
5424void
5425bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5426                struct bfa_s *bfa)
5427{
5428        struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5429        struct bfa_mem_kva_s *uf_kva = BFA_MEM_UF_KVA(bfa);
5430        u32     num_ufs = cfg->fwcfg.num_uf_bufs;
5431        struct bfa_mem_dma_s *seg_ptr;
5432        u16     nsegs, idx, per_seg_uf = 0;
5433
5434        nsegs = BFI_MEM_DMA_NSEGS(num_ufs, BFA_PER_UF_DMA_SZ);
5435        per_seg_uf = BFI_MEM_NREQS_SEG(BFA_PER_UF_DMA_SZ);
5436
5437        bfa_mem_dma_seg_iter(ufm, seg_ptr, nsegs, idx) {
5438                if (num_ufs >= per_seg_uf) {
5439                        num_ufs -= per_seg_uf;
5440                        bfa_mem_dma_setup(minfo, seg_ptr,
5441                                per_seg_uf * BFA_PER_UF_DMA_SZ);
5442                } else
5443                        bfa_mem_dma_setup(minfo, seg_ptr,
5444                                num_ufs * BFA_PER_UF_DMA_SZ);
5445        }
5446
5447        /* kva memory */
5448        bfa_mem_kva_setup(minfo, uf_kva, cfg->fwcfg.num_uf_bufs *
5449                (sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));
5450}
5451
5452void
5453bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5454                struct bfa_pcidev_s *pcidev)
5455{
5456        struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5457
5458        ufm->bfa = bfa;
5459        ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
5460        INIT_LIST_HEAD(&ufm->uf_free_q);
5461        INIT_LIST_HEAD(&ufm->uf_posted_q);
5462        INIT_LIST_HEAD(&ufm->uf_unused_q);
5463
5464        uf_mem_claim(ufm);
5465}
5466
5467static struct bfa_uf_s *
5468bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
5469{
5470        struct bfa_uf_s   *uf;
5471
5472        bfa_q_deq(&uf_mod->uf_free_q, &uf);
5473        return uf;
5474}
5475
5476static void
5477bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
5478{
5479        list_add_tail(&uf->qe, &uf_mod->uf_free_q);
5480}
5481
5482static bfa_status_t
5483bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
5484{
5485        struct bfi_uf_buf_post_s *uf_post_msg;
5486
5487        uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
5488        if (!uf_post_msg)
5489                return BFA_STATUS_FAILED;
5490
5491        memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
5492                      sizeof(struct bfi_uf_buf_post_s));
5493        bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);
5494
5495        bfa_trc(ufm->bfa, uf->uf_tag);
5496
5497        list_add_tail(&uf->qe, &ufm->uf_posted_q);
5498        return BFA_STATUS_OK;
5499}
5500
5501static void
5502bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
5503{
5504        struct bfa_uf_s   *uf;
5505
5506        while ((uf = bfa_uf_get(uf_mod)) != NULL) {
5507                if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
5508                        break;
5509        }
5510}
5511
5512static void
5513uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
5514{
5515        struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5516        u16 uf_tag = m->buf_tag;
5517        struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
5518        struct bfa_uf_buf_s *uf_buf;
5519        uint8_t *buf;
5520
5521        uf_buf = (struct bfa_uf_buf_s *)
5522                        bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len);
5523        buf = &uf_buf->d[0];
5524
5525        m->frm_len = be16_to_cpu(m->frm_len);
5526        m->xfr_len = be16_to_cpu(m->xfr_len);
5527
5528        list_del(&uf->qe);      /* dequeue from posted queue */
5529
5530        uf->data_ptr = buf;
5531        uf->data_len = m->xfr_len;
5532
5533        WARN_ON(uf->data_len < sizeof(struct fchs_s));
5534
5535        if (uf->data_len == sizeof(struct fchs_s)) {
5536                bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
5537                               uf->data_len, (struct fchs_s *)buf);
5538        } else {
5539                u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
5540                bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
5541                                      BFA_PL_EID_RX, uf->data_len,
5542                                      (struct fchs_s *)buf, pld_w0);
5543        }
5544
5545        if (bfa->fcs)
5546                __bfa_cb_uf_recv(uf, BFA_TRUE);
5547        else
5548                bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
5549}
5550
5551void
5552bfa_uf_iocdisable(struct bfa_s *bfa)
5553{
5554        struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5555        struct bfa_uf_s *uf;
5556        struct list_head *qe, *qen;
5557
5558        /* Enqueue unused uf resources to free_q */
5559        list_splice_tail_init(&ufm->uf_unused_q, &ufm->uf_free_q);
5560
5561        list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
5562                uf = (struct bfa_uf_s *) qe;
5563                list_del(&uf->qe);
5564                bfa_uf_put(ufm, uf);
5565        }
5566}
5567
5568void
5569bfa_uf_start(struct bfa_s *bfa)
5570{
5571        bfa_uf_post_all(BFA_UF_MOD(bfa));
5572}
5573
5574/*
5575 * Register handler for all unsolicted receive frames.
5576 *
5577 * @param[in]   bfa             BFA instance
5578 * @param[in]   ufrecv  receive handler function
5579 * @param[in]   cbarg   receive handler arg
5580 */
5581void
5582bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
5583{
5584        struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5585
5586        ufm->ufrecv = ufrecv;
5587        ufm->cbarg = cbarg;
5588}
5589
5590/*
5591 *      Free an unsolicited frame back to BFA.
5592 *
5593 * @param[in]           uf              unsolicited frame to be freed
5594 *
5595 * @return None
5596 */
5597void
5598bfa_uf_free(struct bfa_uf_s *uf)
5599{
5600        bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
5601        bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
5602}
5603
5604
5605
5606/*
5607 *  uf_pub BFA uf module public functions
5608 */
5609void
5610bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5611{
5612        bfa_trc(bfa, msg->mhdr.msg_id);
5613
5614        switch (msg->mhdr.msg_id) {
5615        case BFI_UF_I2H_FRM_RCVD:
5616                uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
5617                break;
5618
5619        default:
5620                bfa_trc(bfa, msg->mhdr.msg_id);
5621                WARN_ON(1);
5622        }
5623}
5624
5625void
5626bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
5627{
5628        struct bfa_uf_mod_s     *mod = BFA_UF_MOD(bfa);
5629        struct list_head        *qe;
5630        int     i;
5631
5632        for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) {
5633                bfa_q_deq_tail(&mod->uf_free_q, &qe);
5634                list_add_tail(qe, &mod->uf_unused_q);
5635        }
5636}
5637
5638/*
5639 *      Dport forward declaration
5640 */
5641
5642enum bfa_dport_test_state_e {
5643        BFA_DPORT_ST_DISABLED   = 0,    /*!< dport is disabled */
5644        BFA_DPORT_ST_INP        = 1,    /*!< test in progress */
5645        BFA_DPORT_ST_COMP       = 2,    /*!< test complete successfully */
5646        BFA_DPORT_ST_NO_SFP     = 3,    /*!< sfp is not present */
5647        BFA_DPORT_ST_NOTSTART   = 4,    /*!< test not start dport is enabled */
5648};
5649
5650/*
5651 * BFA DPORT state machine events
5652 */
5653enum bfa_dport_sm_event {
5654        BFA_DPORT_SM_ENABLE     = 1,    /* dport enable event         */
5655        BFA_DPORT_SM_DISABLE    = 2,    /* dport disable event        */
5656        BFA_DPORT_SM_FWRSP      = 3,    /* fw enable/disable rsp      */
5657        BFA_DPORT_SM_QRESUME    = 4,    /* CQ space available         */
5658        BFA_DPORT_SM_HWFAIL     = 5,    /* IOC h/w failure            */
5659        BFA_DPORT_SM_START      = 6,    /* re-start dport test        */
5660        BFA_DPORT_SM_REQFAIL    = 7,    /* request failure            */
5661        BFA_DPORT_SM_SCN        = 8,    /* state change notify frm fw */
5662};
5663
5664static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
5665                                  enum bfa_dport_sm_event event);
5666static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
5667                                  enum bfa_dport_sm_event event);
5668static void bfa_dport_sm_enabling(struct bfa_dport_s *dport,
5669                                  enum bfa_dport_sm_event event);
5670static void bfa_dport_sm_enabled(struct bfa_dport_s *dport,
5671                                 enum bfa_dport_sm_event event);
5672static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
5673                                 enum bfa_dport_sm_event event);
5674static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
5675                                   enum bfa_dport_sm_event event);
5676static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
5677                                        enum bfa_dport_sm_event event);
5678static void bfa_dport_sm_starting(struct bfa_dport_s *dport,
5679                                  enum bfa_dport_sm_event event);
5680static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
5681                                   enum bfa_dport_sm_event event);
5682static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
5683                                   enum bfa_dport_sm_event event);
5684static void bfa_dport_qresume(void *cbarg);
5685static void bfa_dport_req_comp(struct bfa_dport_s *dport,
5686                                struct bfi_diag_dport_rsp_s *msg);
5687static void bfa_dport_scn(struct bfa_dport_s *dport,
5688                                struct bfi_diag_dport_scn_s *msg);
5689
5690/*
5691 *      BFA fcdiag module
5692 */
5693#define BFA_DIAG_QTEST_TOV      1000    /* msec */
5694
5695/*
5696 *      Set port status to busy
5697 */
5698static void
5699bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)
5700{
5701        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa);
5702
5703        if (fcdiag->lb.lock)
5704                fcport->diag_busy = BFA_TRUE;
5705        else
5706                fcport->diag_busy = BFA_FALSE;
5707}
5708
5709void
5710bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5711                struct bfa_pcidev_s *pcidev)
5712{
5713        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5714        struct bfa_dport_s  *dport = &fcdiag->dport;
5715
5716        fcdiag->bfa             = bfa;
5717        fcdiag->trcmod  = bfa->trcmod;
5718        /* The common DIAG attach bfa_diag_attach() will do all memory claim */
5719        dport->bfa = bfa;
5720        bfa_sm_set_state(dport, bfa_dport_sm_disabled);
5721        bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
5722        dport->cbfn = NULL;
5723        dport->cbarg = NULL;
5724        dport->test_state = BFA_DPORT_ST_DISABLED;
5725        memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));
5726}
5727
5728void
5729bfa_fcdiag_iocdisable(struct bfa_s *bfa)
5730{
5731        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5732        struct bfa_dport_s *dport = &fcdiag->dport;
5733
5734        bfa_trc(fcdiag, fcdiag->lb.lock);
5735        if (fcdiag->lb.lock) {
5736                fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
5737                fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5738                fcdiag->lb.lock = 0;
5739                bfa_fcdiag_set_busy_status(fcdiag);
5740        }
5741
5742        bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);
5743}
5744
5745static void
5746bfa_fcdiag_queuetest_timeout(void *cbarg)
5747{
5748        struct bfa_fcdiag_s       *fcdiag = cbarg;
5749        struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5750
5751        bfa_trc(fcdiag, fcdiag->qtest.all);
5752        bfa_trc(fcdiag, fcdiag->qtest.count);
5753
5754        fcdiag->qtest.timer_active = 0;
5755
5756        res->status = BFA_STATUS_ETIMER;
5757        res->count  = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5758        if (fcdiag->qtest.all)
5759                res->queue  = fcdiag->qtest.all;
5760
5761        bfa_trc(fcdiag, BFA_STATUS_ETIMER);
5762        fcdiag->qtest.status = BFA_STATUS_ETIMER;
5763        fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5764        fcdiag->qtest.lock = 0;
5765}
5766
5767static bfa_status_t
5768bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag)
5769{
5770        u32     i;
5771        struct bfi_diag_qtest_req_s *req;
5772
5773        req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue);
5774        if (!req)
5775                return BFA_STATUS_DEVBUSY;
5776
5777        /* build host command */
5778        bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST,
5779                bfa_fn_lpu(fcdiag->bfa));
5780
5781        for (i = 0; i < BFI_LMSG_PL_WSZ; i++)
5782                req->data[i] = QTEST_PAT_DEFAULT;
5783
5784        bfa_trc(fcdiag, fcdiag->qtest.queue);
5785        /* ring door bell */
5786        bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh);
5787        return BFA_STATUS_OK;
5788}
5789
5790static void
5791bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag,
5792                        bfi_diag_qtest_rsp_t *rsp)
5793{
5794        struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5795        bfa_status_t status = BFA_STATUS_OK;
5796        int i;
5797
5798        /* Check timer, should still be active   */
5799        if (!fcdiag->qtest.timer_active) {
5800                bfa_trc(fcdiag, fcdiag->qtest.timer_active);
5801                return;
5802        }
5803
5804        /* update count */
5805        fcdiag->qtest.count--;
5806
5807        /* Check result */
5808        for (i = 0; i < BFI_LMSG_PL_WSZ; i++) {
5809                if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) {
5810                        res->status = BFA_STATUS_DATACORRUPTED;
5811                        break;
5812                }
5813        }
5814
5815        if (res->status == BFA_STATUS_OK) {
5816                if (fcdiag->qtest.count > 0) {
5817                        status = bfa_fcdiag_queuetest_send(fcdiag);
5818                        if (status == BFA_STATUS_OK)
5819                                return;
5820                        else
5821                                res->status = status;
5822                } else if (fcdiag->qtest.all > 0 &&
5823                        fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) {
5824                        fcdiag->qtest.count = QTEST_CNT_DEFAULT;
5825                        fcdiag->qtest.queue++;
5826                        status = bfa_fcdiag_queuetest_send(fcdiag);
5827                        if (status == BFA_STATUS_OK)
5828                                return;
5829                        else
5830                                res->status = status;
5831                }
5832        }
5833
5834        /* Stop timer when we comp all queue */
5835        if (fcdiag->qtest.timer_active) {
5836                bfa_timer_stop(&fcdiag->qtest.timer);
5837                fcdiag->qtest.timer_active = 0;
5838        }
5839        res->queue = fcdiag->qtest.queue;
5840        res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5841        bfa_trc(fcdiag, res->count);
5842        bfa_trc(fcdiag, res->status);
5843        fcdiag->qtest.status = res->status;
5844        fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5845        fcdiag->qtest.lock = 0;
5846}
5847
5848static void
5849bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag,
5850                        struct bfi_diag_lb_rsp_s *rsp)
5851{
5852        struct bfa_diag_loopback_result_s *res = fcdiag->lb.result;
5853
5854        res->numtxmfrm  = be32_to_cpu(rsp->res.numtxmfrm);
5855        res->numosffrm  = be32_to_cpu(rsp->res.numosffrm);
5856        res->numrcvfrm  = be32_to_cpu(rsp->res.numrcvfrm);
5857        res->badfrminf  = be32_to_cpu(rsp->res.badfrminf);
5858        res->badfrmnum  = be32_to_cpu(rsp->res.badfrmnum);
5859        res->status     = rsp->res.status;
5860        fcdiag->lb.status = rsp->res.status;
5861        bfa_trc(fcdiag, fcdiag->lb.status);
5862        fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5863        fcdiag->lb.lock = 0;
5864        bfa_fcdiag_set_busy_status(fcdiag);
5865}
5866
5867static bfa_status_t
5868bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag,
5869                        struct bfa_diag_loopback_s *loopback)
5870{
5871        struct bfi_diag_lb_req_s *lb_req;
5872
5873        lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG);
5874        if (!lb_req)
5875                return BFA_STATUS_DEVBUSY;
5876
5877        /* build host command */
5878        bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK,
5879                bfa_fn_lpu(fcdiag->bfa));
5880
5881        lb_req->lb_mode = loopback->lb_mode;
5882        lb_req->speed = loopback->speed;
5883        lb_req->loopcnt = loopback->loopcnt;
5884        lb_req->pattern = loopback->pattern;
5885
5886        /* ring door bell */
5887        bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh);
5888
5889        bfa_trc(fcdiag, loopback->lb_mode);
5890        bfa_trc(fcdiag, loopback->speed);
5891        bfa_trc(fcdiag, loopback->loopcnt);
5892        bfa_trc(fcdiag, loopback->pattern);
5893        return BFA_STATUS_OK;
5894}
5895
5896/*
5897 *      cpe/rme intr handler
5898 */
5899void
5900bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5901{
5902        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5903
5904        switch (msg->mhdr.msg_id) {
5905        case BFI_DIAG_I2H_LOOPBACK:
5906                bfa_fcdiag_loopback_comp(fcdiag,
5907                                (struct bfi_diag_lb_rsp_s *) msg);
5908                break;
5909        case BFI_DIAG_I2H_QTEST:
5910                bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
5911                break;
5912        case BFI_DIAG_I2H_DPORT:
5913                bfa_dport_req_comp(&fcdiag->dport,
5914                                (struct bfi_diag_dport_rsp_s *)msg);
5915                break;
5916        case BFI_DIAG_I2H_DPORT_SCN:
5917                bfa_dport_scn(&fcdiag->dport,
5918                                (struct bfi_diag_dport_scn_s *)msg);
5919                break;
5920        default:
5921                bfa_trc(fcdiag, msg->mhdr.msg_id);
5922                WARN_ON(1);
5923        }
5924}
5925
5926/*
5927 *      Loopback test
5928 *
5929 *   @param[in] *bfa            - bfa data struct
5930 *   @param[in] opmode          - port operation mode
5931 *   @param[in] speed           - port speed
5932 *   @param[in] lpcnt           - loop count
5933 *   @param[in] pat                     - pattern to build packet
5934 *   @param[in] *result         - pt to bfa_diag_loopback_result_t data struct
5935 *   @param[in] cbfn            - callback function
5936 *   @param[in] cbarg           - callback functioin arg
5937 *
5938 *   @param[out]
5939 */
5940bfa_status_t
5941bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
5942                enum bfa_port_speed speed, u32 lpcnt, u32 pat,
5943                struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn,
5944                void *cbarg)
5945{
5946        struct  bfa_diag_loopback_s loopback;
5947        struct bfa_port_attr_s attr;
5948        bfa_status_t status;
5949        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5950
5951        if (!bfa_iocfc_is_operational(bfa))
5952                return BFA_STATUS_IOC_NON_OP;
5953
5954        /* if port is PBC disabled, return error */
5955        if (bfa_fcport_is_pbcdisabled(bfa)) {
5956                bfa_trc(fcdiag, BFA_STATUS_PBC);
5957                return BFA_STATUS_PBC;
5958        }
5959
5960        if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) {
5961                bfa_trc(fcdiag, opmode);
5962                return BFA_STATUS_PORT_NOT_DISABLED;
5963        }
5964
5965        /*
5966         * Check if input speed is supported by the port mode
5967         */
5968        if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
5969                if (!(speed == BFA_PORT_SPEED_1GBPS ||
5970                      speed == BFA_PORT_SPEED_2GBPS ||
5971                      speed == BFA_PORT_SPEED_4GBPS ||
5972                      speed == BFA_PORT_SPEED_8GBPS ||
5973                      speed == BFA_PORT_SPEED_16GBPS ||
5974                      speed == BFA_PORT_SPEED_AUTO)) {
5975                        bfa_trc(fcdiag, speed);
5976                        return BFA_STATUS_UNSUPP_SPEED;
5977                }
5978                bfa_fcport_get_attr(bfa, &attr);
5979                bfa_trc(fcdiag, attr.speed_supported);
5980                if (speed > attr.speed_supported)
5981                        return BFA_STATUS_UNSUPP_SPEED;
5982        } else {
5983                if (speed != BFA_PORT_SPEED_10GBPS) {
5984                        bfa_trc(fcdiag, speed);
5985                        return BFA_STATUS_UNSUPP_SPEED;
5986                }
5987        }
5988
5989        /*
5990         * For CT2, 1G is not supported
5991         */
5992        if ((speed == BFA_PORT_SPEED_1GBPS) &&
5993            (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) {
5994                bfa_trc(fcdiag, speed);
5995                return BFA_STATUS_UNSUPP_SPEED;
5996        }
5997
5998        /* For Mezz card, port speed entered needs to be checked */
5999        if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
6000                if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
6001                        if (!(speed == BFA_PORT_SPEED_1GBPS ||
6002                              speed == BFA_PORT_SPEED_2GBPS ||
6003                              speed == BFA_PORT_SPEED_4GBPS ||
6004                              speed == BFA_PORT_SPEED_8GBPS ||
6005                              speed == BFA_PORT_SPEED_16GBPS ||
6006                              speed == BFA_PORT_SPEED_AUTO))
6007                                return BFA_STATUS_UNSUPP_SPEED;
6008                } else {
6009                        if (speed != BFA_PORT_SPEED_10GBPS)
6010                                return BFA_STATUS_UNSUPP_SPEED;
6011                }
6012        }
6013        /* check to see if fcport is dport */
6014        if (bfa_fcport_is_dport(bfa)) {
6015                bfa_trc(fcdiag, fcdiag->lb.lock);
6016                return BFA_STATUS_DPORT_ENABLED;
6017        }
6018        /* check to see if there is another destructive diag cmd running */
6019        if (fcdiag->lb.lock) {
6020                bfa_trc(fcdiag, fcdiag->lb.lock);
6021                return BFA_STATUS_DEVBUSY;
6022        }
6023
6024        fcdiag->lb.lock = 1;
6025        loopback.lb_mode = opmode;
6026        loopback.speed = speed;
6027        loopback.loopcnt = lpcnt;
6028        loopback.pattern = pat;
6029        fcdiag->lb.result = result;
6030        fcdiag->lb.cbfn = cbfn;
6031        fcdiag->lb.cbarg = cbarg;
6032        memset(result, 0, sizeof(struct bfa_diag_loopback_result_s));
6033        bfa_fcdiag_set_busy_status(fcdiag);
6034
6035        /* Send msg to fw */
6036        status = bfa_fcdiag_loopback_send(fcdiag, &loopback);
6037        return status;
6038}
6039
6040/*
6041 *      DIAG queue test command
6042 *
6043 *   @param[in] *bfa            - bfa data struct
6044 *   @param[in] force           - 1: don't do ioc op checking
6045 *   @param[in] queue           - queue no. to test
6046 *   @param[in] *result         - pt to bfa_diag_qtest_result_t data struct
6047 *   @param[in] cbfn            - callback function
6048 *   @param[in] *cbarg          - callback functioin arg
6049 *
6050 *   @param[out]
6051 */
6052bfa_status_t
6053bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue,
6054                struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn,
6055                void *cbarg)
6056{
6057        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6058        bfa_status_t status;
6059        bfa_trc(fcdiag, force);
6060        bfa_trc(fcdiag, queue);
6061
6062        if (!force && !bfa_iocfc_is_operational(bfa))
6063                return BFA_STATUS_IOC_NON_OP;
6064
6065        /* check to see if there is another destructive diag cmd running */
6066        if (fcdiag->qtest.lock) {
6067                bfa_trc(fcdiag, fcdiag->qtest.lock);
6068                return BFA_STATUS_DEVBUSY;
6069        }
6070
6071        /* Initialization */
6072        fcdiag->qtest.lock = 1;
6073        fcdiag->qtest.cbfn = cbfn;
6074        fcdiag->qtest.cbarg = cbarg;
6075        fcdiag->qtest.result = result;
6076        fcdiag->qtest.count = QTEST_CNT_DEFAULT;
6077
6078        /* Init test results */
6079        fcdiag->qtest.result->status = BFA_STATUS_OK;
6080        fcdiag->qtest.result->count  = 0;
6081
6082        /* send */
6083        if (queue < BFI_IOC_MAX_CQS) {
6084                fcdiag->qtest.result->queue  = (u8)queue;
6085                fcdiag->qtest.queue = (u8)queue;
6086                fcdiag->qtest.all   = 0;
6087        } else {
6088                fcdiag->qtest.result->queue  = 0;
6089                fcdiag->qtest.queue = 0;
6090                fcdiag->qtest.all   = 1;
6091        }
6092        status = bfa_fcdiag_queuetest_send(fcdiag);
6093
6094        /* Start a timer */
6095        if (status == BFA_STATUS_OK) {
6096                bfa_timer_start(bfa, &fcdiag->qtest.timer,
6097                                bfa_fcdiag_queuetest_timeout, fcdiag,
6098                                BFA_DIAG_QTEST_TOV);
6099                fcdiag->qtest.timer_active = 1;
6100        }
6101        return status;
6102}
6103
6104/*
6105 * DIAG PLB is running
6106 *
6107 *   @param[in] *bfa    - bfa data struct
6108 *
6109 *   @param[out]
6110 */
6111bfa_status_t
6112bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
6113{
6114        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6115        return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
6116}
6117
6118/*
6119 *      D-port
6120 */
6121#define bfa_dport_result_start(__dport, __mode) do {                            \
6122                (__dport)->result.start_time = ktime_get_real_seconds();        \
6123                (__dport)->result.status = DPORT_TEST_ST_INPRG;                 \
6124                (__dport)->result.mode = (__mode);                              \
6125                (__dport)->result.rp_pwwn = (__dport)->rp_pwwn;                 \
6126                (__dport)->result.rp_nwwn = (__dport)->rp_nwwn;                 \
6127                (__dport)->result.lpcnt = (__dport)->lpcnt;                     \
6128} while (0)
6129
6130static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
6131                                        enum bfi_dport_req req);
6132static void
6133bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status)
6134{
6135        if (dport->cbfn != NULL) {
6136                dport->cbfn(dport->cbarg, bfa_status);
6137                dport->cbfn = NULL;
6138                dport->cbarg = NULL;
6139        }
6140}
6141
6142static void
6143bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6144{
6145        bfa_trc(dport->bfa, event);
6146
6147        switch (event) {
6148        case BFA_DPORT_SM_ENABLE:
6149                bfa_fcport_dportenable(dport->bfa);
6150                if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE))
6151                        bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6152                else
6153                        bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait);
6154                break;
6155
6156        case BFA_DPORT_SM_DISABLE:
6157                /* Already disabled */
6158                break;
6159
6160        case BFA_DPORT_SM_HWFAIL:
6161                /* ignore */
6162                break;
6163
6164        case BFA_DPORT_SM_SCN:
6165                if (dport->i2hmsg.scn.state ==  BFI_DPORT_SCN_DDPORT_ENABLE) {
6166                        bfa_fcport_ddportenable(dport->bfa);
6167                        dport->dynamic = BFA_TRUE;
6168                        dport->test_state = BFA_DPORT_ST_NOTSTART;
6169                        bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6170                } else {
6171                        bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6172                        WARN_ON(1);
6173                }
6174                break;
6175
6176        default:
6177                bfa_sm_fault(dport->bfa, event);
6178        }
6179}
6180
6181static void
6182bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
6183                            enum bfa_dport_sm_event event)
6184{
6185        bfa_trc(dport->bfa, event);
6186
6187        switch (event) {
6188        case BFA_DPORT_SM_QRESUME:
6189                bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6190                bfa_dport_send_req(dport, BFI_DPORT_ENABLE);
6191                break;
6192
6193        case BFA_DPORT_SM_HWFAIL:
6194                bfa_reqq_wcancel(&dport->reqq_wait);
6195                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6196                bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6197                break;
6198
6199        default:
6200                bfa_sm_fault(dport->bfa, event);
6201        }
6202}
6203
6204static void
6205bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6206{
6207        bfa_trc(dport->bfa, event);
6208
6209        switch (event) {
6210        case BFA_DPORT_SM_FWRSP:
6211                memset(&dport->result, 0,
6212                                sizeof(struct bfa_diag_dport_result_s));
6213                if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6214                        dport->test_state = BFA_DPORT_ST_NO_SFP;
6215                } else {
6216                        dport->test_state = BFA_DPORT_ST_INP;
6217                        bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
6218                }
6219                bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6220                break;
6221
6222        case BFA_DPORT_SM_REQFAIL:
6223                dport->test_state = BFA_DPORT_ST_DISABLED;
6224                bfa_fcport_dportdisable(dport->bfa);
6225                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6226                break;
6227
6228        case BFA_DPORT_SM_HWFAIL:
6229                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6230                bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6231                break;
6232
6233        default:
6234                bfa_sm_fault(dport->bfa, event);
6235        }
6236}
6237
6238static void
6239bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6240{
6241        bfa_trc(dport->bfa, event);
6242
6243        switch (event) {
6244        case BFA_DPORT_SM_START:
6245                if (bfa_dport_send_req(dport, BFI_DPORT_START))
6246                        bfa_sm_set_state(dport, bfa_dport_sm_starting);
6247                else
6248                        bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait);
6249                break;
6250
6251        case BFA_DPORT_SM_DISABLE:
6252                bfa_fcport_dportdisable(dport->bfa);
6253                if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE))
6254                        bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6255                else
6256                        bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait);
6257                break;
6258
6259        case BFA_DPORT_SM_HWFAIL:
6260                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6261                break;
6262
6263        case BFA_DPORT_SM_SCN:
6264                switch (dport->i2hmsg.scn.state) {
6265                case BFI_DPORT_SCN_TESTCOMP:
6266                        dport->test_state = BFA_DPORT_ST_COMP;
6267                        break;
6268
6269                case BFI_DPORT_SCN_TESTSTART:
6270                        dport->test_state = BFA_DPORT_ST_INP;
6271                        break;
6272
6273                case BFI_DPORT_SCN_TESTSKIP:
6274                case BFI_DPORT_SCN_SUBTESTSTART:
6275                        /* no state change */
6276                        break;
6277
6278                case BFI_DPORT_SCN_SFP_REMOVED:
6279                        dport->test_state = BFA_DPORT_ST_NO_SFP;
6280                        break;
6281
6282                case BFI_DPORT_SCN_DDPORT_DISABLE:
6283                        bfa_fcport_ddportdisable(dport->bfa);
6284
6285                        if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE))
6286                                bfa_sm_set_state(dport,
6287                                         bfa_dport_sm_dynamic_disabling);
6288                        else
6289                                bfa_sm_set_state(dport,
6290                                         bfa_dport_sm_dynamic_disabling_qwait);
6291                        break;
6292
6293                case BFI_DPORT_SCN_FCPORT_DISABLE:
6294                        bfa_fcport_ddportdisable(dport->bfa);
6295
6296                        bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6297                        dport->dynamic = BFA_FALSE;
6298                        break;
6299
6300                default:
6301                        bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6302                        bfa_sm_fault(dport->bfa, event);
6303                }
6304                break;
6305        default:
6306                bfa_sm_fault(dport->bfa, event);
6307        }
6308}
6309
6310static void
6311bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
6312                             enum bfa_dport_sm_event event)
6313{
6314        bfa_trc(dport->bfa, event);
6315
6316        switch (event) {
6317        case BFA_DPORT_SM_QRESUME:
6318                bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6319                bfa_dport_send_req(dport, BFI_DPORT_DISABLE);
6320                break;
6321
6322        case BFA_DPORT_SM_HWFAIL:
6323                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6324                bfa_reqq_wcancel(&dport->reqq_wait);
6325                bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6326                break;
6327
6328        case BFA_DPORT_SM_SCN:
6329                /* ignore */
6330                break;
6331
6332        default:
6333                bfa_sm_fault(dport->bfa, event);
6334        }
6335}
6336
6337static void
6338bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6339{
6340        bfa_trc(dport->bfa, event);
6341
6342        switch (event) {
6343        case BFA_DPORT_SM_FWRSP:
6344                dport->test_state = BFA_DPORT_ST_DISABLED;
6345                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6346                break;
6347
6348        case BFA_DPORT_SM_HWFAIL:
6349                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6350                bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6351                break;
6352
6353        case BFA_DPORT_SM_SCN:
6354                /* no state change */
6355                break;
6356
6357        default:
6358                bfa_sm_fault(dport->bfa, event);
6359        }
6360}
6361
6362static void
6363bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
6364                            enum bfa_dport_sm_event event)
6365{
6366        bfa_trc(dport->bfa, event);
6367
6368        switch (event) {
6369        case BFA_DPORT_SM_QRESUME:
6370                bfa_sm_set_state(dport, bfa_dport_sm_starting);
6371                bfa_dport_send_req(dport, BFI_DPORT_START);
6372                break;
6373
6374        case BFA_DPORT_SM_HWFAIL:
6375                bfa_reqq_wcancel(&dport->reqq_wait);
6376                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6377                bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6378                break;
6379
6380        default:
6381                bfa_sm_fault(dport->bfa, event);
6382        }
6383}
6384
6385static void
6386bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6387{
6388        bfa_trc(dport->bfa, event);
6389
6390        switch (event) {
6391        case BFA_DPORT_SM_FWRSP:
6392                memset(&dport->result, 0,
6393                                sizeof(struct bfa_diag_dport_result_s));
6394                if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6395                        dport->test_state = BFA_DPORT_ST_NO_SFP;
6396                } else {
6397                        dport->test_state = BFA_DPORT_ST_INP;
6398                        bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);
6399                }
6400                fallthrough;
6401
6402        case BFA_DPORT_SM_REQFAIL:
6403                bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6404                break;
6405
6406        case BFA_DPORT_SM_HWFAIL:
6407                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6408                bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6409                break;
6410
6411        default:
6412                bfa_sm_fault(dport->bfa, event);
6413        }
6414}
6415
6416static void
6417bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
6418                               enum bfa_dport_sm_event event)
6419{
6420        bfa_trc(dport->bfa, event);
6421
6422        switch (event) {
6423        case BFA_DPORT_SM_SCN:
6424                switch (dport->i2hmsg.scn.state) {
6425                case BFI_DPORT_SCN_DDPORT_DISABLED:
6426                        bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6427                        dport->dynamic = BFA_FALSE;
6428                        bfa_fcport_enable(dport->bfa);
6429                        break;
6430
6431                default:
6432                        bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6433                        bfa_sm_fault(dport->bfa, event);
6434
6435                }
6436                break;
6437
6438        case BFA_DPORT_SM_HWFAIL:
6439                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6440                bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6441                break;
6442
6443        default:
6444                bfa_sm_fault(dport->bfa, event);
6445        }
6446}
6447
6448static void
6449bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
6450                            enum bfa_dport_sm_event event)
6451{
6452        bfa_trc(dport->bfa, event);
6453
6454        switch (event) {
6455        case BFA_DPORT_SM_QRESUME:
6456                bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling);
6457                bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE);
6458                break;
6459
6460        case BFA_DPORT_SM_HWFAIL:
6461                bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6462                bfa_reqq_wcancel(&dport->reqq_wait);
6463                bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6464                break;
6465
6466        case BFA_DPORT_SM_SCN:
6467                /* ignore */
6468                break;
6469
6470        default:
6471                bfa_sm_fault(dport->bfa, event);
6472        }
6473}
6474
6475static bfa_boolean_t
6476bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
6477{
6478        struct bfi_diag_dport_req_s *m;
6479
6480        /*
6481         * check for room in queue to send request now
6482         */
6483        m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);
6484        if (!m) {
6485                bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait);
6486                return BFA_FALSE;
6487        }
6488
6489        bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
6490                    bfa_fn_lpu(dport->bfa));
6491        m->req  = req;
6492        if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) {
6493                m->lpcnt = cpu_to_be32(dport->lpcnt);
6494                m->payload = cpu_to_be32(dport->payload);
6495        }
6496
6497        /*
6498         * queue I/O message to firmware
6499         */
6500        bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh);
6501
6502        return BFA_TRUE;
6503}
6504
6505static void
6506bfa_dport_qresume(void *cbarg)
6507{
6508        struct bfa_dport_s *dport = cbarg;
6509
6510        bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME);
6511}
6512
6513static void
6514bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg)
6515{
6516        msg->status = cpu_to_be32(msg->status);
6517        dport->i2hmsg.rsp.status = msg->status;
6518        dport->rp_pwwn = msg->pwwn;
6519        dport->rp_nwwn = msg->nwwn;
6520
6521        if ((msg->status == BFA_STATUS_OK) ||
6522            (msg->status == BFA_STATUS_DPORT_NO_SFP)) {
6523                bfa_trc(dport->bfa, msg->status);
6524                bfa_trc(dport->bfa, dport->rp_pwwn);
6525                bfa_trc(dport->bfa, dport->rp_nwwn);
6526                bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
6527
6528        } else {
6529                bfa_trc(dport->bfa, msg->status);
6530                bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL);
6531        }
6532        bfa_cb_fcdiag_dport(dport, msg->status);
6533}
6534
6535static bfa_boolean_t
6536bfa_dport_is_sending_req(struct bfa_dport_s *dport)
6537{
6538        if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling)      ||
6539            bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
6540            bfa_sm_cmp_state(dport, bfa_dport_sm_disabling)     ||
6541            bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) ||
6542            bfa_sm_cmp_state(dport, bfa_dport_sm_starting)      ||
6543            bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) {
6544                return BFA_TRUE;
6545        } else {
6546                return BFA_FALSE;
6547        }
6548}
6549
6550static void
6551bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg)
6552{
6553        int i;
6554        uint8_t subtesttype;
6555
6556        bfa_trc(dport->bfa, msg->state);
6557        dport->i2hmsg.scn.state = msg->state;
6558
6559        switch (dport->i2hmsg.scn.state) {
6560        case BFI_DPORT_SCN_TESTCOMP:
6561                dport->result.end_time = ktime_get_real_seconds();
6562                bfa_trc(dport->bfa, dport->result.end_time);
6563
6564                dport->result.status = msg->info.testcomp.status;
6565                bfa_trc(dport->bfa, dport->result.status);
6566
6567                dport->result.roundtrip_latency =
6568                        cpu_to_be32(msg->info.testcomp.latency);
6569                dport->result.est_cable_distance =
6570                        cpu_to_be32(msg->info.testcomp.distance);
6571                dport->result.buffer_required =
6572                        be16_to_cpu(msg->info.testcomp.numbuffer);
6573
6574                dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz);
6575                dport->result.speed = msg->info.testcomp.speed;
6576
6577                bfa_trc(dport->bfa, dport->result.roundtrip_latency);
6578                bfa_trc(dport->bfa, dport->result.est_cable_distance);
6579                bfa_trc(dport->bfa, dport->result.buffer_required);
6580                bfa_trc(dport->bfa, dport->result.frmsz);
6581                bfa_trc(dport->bfa, dport->result.speed);
6582
6583                for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) {
6584                        dport->result.subtest[i].status =
6585                                msg->info.testcomp.subtest_status[i];
6586                        bfa_trc(dport->bfa, dport->result.subtest[i].status);
6587                }
6588                break;
6589
6590        case BFI_DPORT_SCN_TESTSKIP:
6591        case BFI_DPORT_SCN_DDPORT_ENABLE:
6592                memset(&dport->result, 0,
6593                                sizeof(struct bfa_diag_dport_result_s));
6594                break;
6595
6596        case BFI_DPORT_SCN_TESTSTART:
6597                memset(&dport->result, 0,
6598                                sizeof(struct bfa_diag_dport_result_s));
6599                dport->rp_pwwn = msg->info.teststart.pwwn;
6600                dport->rp_nwwn = msg->info.teststart.nwwn;
6601                dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm);
6602                bfa_dport_result_start(dport, msg->info.teststart.mode);
6603                break;
6604
6605        case BFI_DPORT_SCN_SUBTESTSTART:
6606                subtesttype = msg->info.teststart.type;
6607                dport->result.subtest[subtesttype].start_time =
6608                        ktime_get_real_seconds();
6609                dport->result.subtest[subtesttype].status =
6610                        DPORT_TEST_ST_INPRG;
6611
6612                bfa_trc(dport->bfa, subtesttype);
6613                bfa_trc(dport->bfa,
6614                        dport->result.subtest[subtesttype].start_time);
6615                break;
6616
6617        case BFI_DPORT_SCN_SFP_REMOVED:
6618        case BFI_DPORT_SCN_DDPORT_DISABLED:
6619        case BFI_DPORT_SCN_DDPORT_DISABLE:
6620        case BFI_DPORT_SCN_FCPORT_DISABLE:
6621                dport->result.status = DPORT_TEST_ST_IDLE;
6622                break;
6623
6624        default:
6625                bfa_sm_fault(dport->bfa, msg->state);
6626        }
6627
6628        bfa_sm_send_event(dport, BFA_DPORT_SM_SCN);
6629}
6630
6631/*
6632 * Dport enable
6633 *
6634 * @param[in] *bfa            - bfa data struct
6635 */
6636bfa_status_t
6637bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6638                                bfa_cb_diag_t cbfn, void *cbarg)
6639{
6640        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6641        struct bfa_dport_s  *dport = &fcdiag->dport;
6642
6643        /*
6644         * Dport is not support in MEZZ card
6645         */
6646        if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) {
6647                bfa_trc(dport->bfa, BFA_STATUS_PBC);
6648                return BFA_STATUS_CMD_NOTSUPP_MEZZ;
6649        }
6650
6651        /*
6652         * Dport is supported in CT2 or above
6653         */
6654        if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) {
6655                bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id);
6656                return BFA_STATUS_FEATURE_NOT_SUPPORTED;
6657        }
6658
6659        /*
6660         * Check to see if IOC is down
6661        */
6662        if (!bfa_iocfc_is_operational(bfa))
6663                return BFA_STATUS_IOC_NON_OP;
6664
6665        /* if port is PBC disabled, return error */
6666        if (bfa_fcport_is_pbcdisabled(bfa)) {
6667                bfa_trc(dport->bfa, BFA_STATUS_PBC);
6668                return BFA_STATUS_PBC;
6669        }
6670
6671        /*
6672         * Check if port mode is FC port
6673         */
6674        if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) {
6675                bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc));
6676                return BFA_STATUS_CMD_NOTSUPP_CNA;
6677        }
6678
6679        /*
6680         * Check if port is in LOOP mode
6681         */
6682        if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) ||
6683            (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) {
6684                bfa_trc(dport->bfa, 0);
6685                return BFA_STATUS_TOPOLOGY_LOOP;
6686        }
6687
6688        /*
6689         * Check if port is TRUNK mode
6690         */
6691        if (bfa_fcport_is_trunk_enabled(bfa)) {
6692                bfa_trc(dport->bfa, 0);
6693                return BFA_STATUS_ERROR_TRUNK_ENABLED;
6694        }
6695
6696        /*
6697         * Check if diag loopback is running
6698         */
6699        if (bfa_fcdiag_lb_is_running(bfa)) {
6700                bfa_trc(dport->bfa, 0);
6701                return BFA_STATUS_DIAG_BUSY;
6702        }
6703
6704        /*
6705         * Check to see if port is disable or in dport state
6706         */
6707        if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6708            (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6709                bfa_trc(dport->bfa, 0);
6710                return BFA_STATUS_PORT_NOT_DISABLED;
6711        }
6712
6713        /*
6714         * Check if dport is in dynamic mode
6715         */
6716        if (dport->dynamic)
6717                return BFA_STATUS_DDPORT_ERR;
6718
6719        /*
6720         * Check if dport is busy
6721         */
6722        if (bfa_dport_is_sending_req(dport))
6723                return BFA_STATUS_DEVBUSY;
6724
6725        /*
6726         * Check if dport is already enabled
6727         */
6728        if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6729                bfa_trc(dport->bfa, 0);
6730                return BFA_STATUS_DPORT_ENABLED;
6731        }
6732
6733        bfa_trc(dport->bfa, lpcnt);
6734        bfa_trc(dport->bfa, pat);
6735        dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6736        dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6737        dport->cbfn = cbfn;
6738        dport->cbarg = cbarg;
6739
6740        bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE);
6741        return BFA_STATUS_OK;
6742}
6743
6744/*
6745 *      Dport disable
6746 *
6747 *      @param[in] *bfa            - bfa data struct
6748 */
6749bfa_status_t
6750bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
6751{
6752        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6753        struct bfa_dport_s *dport = &fcdiag->dport;
6754
6755        if (bfa_ioc_is_disabled(&bfa->ioc))
6756                return BFA_STATUS_IOC_DISABLED;
6757
6758        /* if port is PBC disabled, return error */
6759        if (bfa_fcport_is_pbcdisabled(bfa)) {
6760                bfa_trc(dport->bfa, BFA_STATUS_PBC);
6761                return BFA_STATUS_PBC;
6762        }
6763
6764        /*
6765         * Check if dport is in dynamic mode
6766         */
6767        if (dport->dynamic) {
6768                return BFA_STATUS_DDPORT_ERR;
6769        }
6770
6771        /*
6772         * Check to see if port is disable or in dport state
6773         */
6774        if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6775            (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6776                bfa_trc(dport->bfa, 0);
6777                return BFA_STATUS_PORT_NOT_DISABLED;
6778        }
6779
6780        /*
6781         * Check if dport is busy
6782         */
6783        if (bfa_dport_is_sending_req(dport))
6784                return BFA_STATUS_DEVBUSY;
6785
6786        /*
6787         * Check if dport is already disabled
6788         */
6789        if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) {
6790                bfa_trc(dport->bfa, 0);
6791                return BFA_STATUS_DPORT_DISABLED;
6792        }
6793
6794        dport->cbfn = cbfn;
6795        dport->cbarg = cbarg;
6796
6797        bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE);
6798        return BFA_STATUS_OK;
6799}
6800
6801/*
6802 * Dport start -- restart dport test
6803 *
6804 *   @param[in] *bfa            - bfa data struct
6805 */
6806bfa_status_t
6807bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6808                        bfa_cb_diag_t cbfn, void *cbarg)
6809{
6810        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6811        struct bfa_dport_s *dport = &fcdiag->dport;
6812
6813        /*
6814         * Check to see if IOC is down
6815         */
6816        if (!bfa_iocfc_is_operational(bfa))
6817                return BFA_STATUS_IOC_NON_OP;
6818
6819        /*
6820         * Check if dport is in dynamic mode
6821         */
6822        if (dport->dynamic)
6823                return BFA_STATUS_DDPORT_ERR;
6824
6825        /*
6826         * Check if dport is busy
6827         */
6828        if (bfa_dport_is_sending_req(dport))
6829                return BFA_STATUS_DEVBUSY;
6830
6831        /*
6832         * Check if dport is in enabled state.
6833         * Test can only be restart when previous test has completed
6834         */
6835        if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6836                bfa_trc(dport->bfa, 0);
6837                return BFA_STATUS_DPORT_DISABLED;
6838
6839        } else {
6840                if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6841                        return BFA_STATUS_DPORT_INV_SFP;
6842
6843                if (dport->test_state == BFA_DPORT_ST_INP)
6844                        return BFA_STATUS_DEVBUSY;
6845
6846                WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);
6847        }
6848
6849        bfa_trc(dport->bfa, lpcnt);
6850        bfa_trc(dport->bfa, pat);
6851
6852        dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6853        dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6854
6855        dport->cbfn = cbfn;
6856        dport->cbarg = cbarg;
6857
6858        bfa_sm_send_event(dport, BFA_DPORT_SM_START);
6859        return BFA_STATUS_OK;
6860}
6861
6862/*
6863 * Dport show -- return dport test result
6864 *
6865 *   @param[in] *bfa            - bfa data struct
6866 */
6867bfa_status_t
6868bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result)
6869{
6870        struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6871        struct bfa_dport_s *dport = &fcdiag->dport;
6872
6873        /*
6874         * Check to see if IOC is down
6875         */
6876        if (!bfa_iocfc_is_operational(bfa))
6877                return BFA_STATUS_IOC_NON_OP;
6878
6879        /*
6880         * Check if dport is busy
6881         */
6882        if (bfa_dport_is_sending_req(dport))
6883                return BFA_STATUS_DEVBUSY;
6884
6885        /*
6886         * Check if dport is in enabled state.
6887         */
6888        if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6889                bfa_trc(dport->bfa, 0);
6890                return BFA_STATUS_DPORT_DISABLED;
6891
6892        }
6893
6894        /*
6895         * Check if there is SFP
6896         */
6897        if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6898                return BFA_STATUS_DPORT_INV_SFP;
6899
6900        memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s));
6901
6902        return BFA_STATUS_OK;
6903}
6904