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