Back to home page

OSCL-LXR

 
 

    


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