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