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