3452 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.4 * Copyright (c) 2014- QLogic Corporation.5 * All rights reserved6 * www.qlogic.com7 *8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.9 */10 11/*12 * rport.c Remote port implementation.13 */14 15#include "bfad_drv.h"16#include "bfad_im.h"17#include "bfa_fcs.h"18#include "bfa_fcbuild.h"19 20BFA_TRC_FILE(FCS, RPORT);21 22static u3223bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;24 /* In millisecs */25/*26 * bfa_fcs_rport_max_logins is max count of bfa_fcs_rports27 * whereas DEF_CFG_NUM_RPORTS is max count of bfa_rports28 */29static u32 bfa_fcs_rport_max_logins = BFA_FCS_MAX_RPORT_LOGINS;30 31/*32 * forward declarations33 */34static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(35 struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);36static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);37static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);38static void bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport);39static void bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport);40static void bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport);41static void bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport);42static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,43 struct fc_logi_s *plogi);44static void bfa_fcs_rport_timeout(void *arg);45static void bfa_fcs_rport_send_plogi(void *rport_cbarg,46 struct bfa_fcxp_s *fcxp_alloced);47static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg,48 struct bfa_fcxp_s *fcxp_alloced);49static void bfa_fcs_rport_plogi_response(void *fcsarg,50 struct bfa_fcxp_s *fcxp, void *cbarg,51 bfa_status_t req_status, u32 rsp_len,52 u32 resid_len, struct fchs_s *rsp_fchs);53static void bfa_fcs_rport_send_adisc(void *rport_cbarg,54 struct bfa_fcxp_s *fcxp_alloced);55static void bfa_fcs_rport_adisc_response(void *fcsarg,56 struct bfa_fcxp_s *fcxp, void *cbarg,57 bfa_status_t req_status, u32 rsp_len,58 u32 resid_len, struct fchs_s *rsp_fchs);59static void bfa_fcs_rport_send_nsdisc(void *rport_cbarg,60 struct bfa_fcxp_s *fcxp_alloced);61static void bfa_fcs_rport_gidpn_response(void *fcsarg,62 struct bfa_fcxp_s *fcxp, void *cbarg,63 bfa_status_t req_status, u32 rsp_len,64 u32 resid_len, struct fchs_s *rsp_fchs);65static void bfa_fcs_rport_gpnid_response(void *fcsarg,66 struct bfa_fcxp_s *fcxp, void *cbarg,67 bfa_status_t req_status, u32 rsp_len,68 u32 resid_len, struct fchs_s *rsp_fchs);69static void bfa_fcs_rport_send_logo(void *rport_cbarg,70 struct bfa_fcxp_s *fcxp_alloced);71static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg);72static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,73 struct fchs_s *rx_fchs, u16 len);74static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,75 struct fchs_s *rx_fchs, u8 reason_code,76 u8 reason_code_expl);77static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,78 struct fchs_s *rx_fchs, u16 len);79static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);80static void bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport);81 82static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,83 enum rport_event event);84static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,85 enum rport_event event);86static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,87 enum rport_event event);88static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,89 enum rport_event event);90static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,91 enum rport_event event);92static void bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,93 enum rport_event event);94static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,95 enum rport_event event);96static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,97 enum rport_event event);98static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,99 enum rport_event event);100static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,101 enum rport_event event);102static void bfa_fcs_rport_sm_adisc_online_sending(103 struct bfa_fcs_rport_s *rport, enum rport_event event);104static void bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,105 enum rport_event event);106static void bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s107 *rport, enum rport_event event);108static void bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,109 enum rport_event event);110static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,111 enum rport_event event);112static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,113 enum rport_event event);114static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,115 enum rport_event event);116static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,117 enum rport_event event);118static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,119 enum rport_event event);120static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,121 enum rport_event event);122static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,123 enum rport_event event);124static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,125 enum rport_event event);126static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,127 enum rport_event event);128static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,129 enum rport_event event);130static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,131 enum rport_event event);132static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,133 enum rport_event event);134static void bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,135 enum rport_event event);136static void bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,137 enum rport_event event);138 139struct bfa_fcs_rport_sm_table_s {140 bfa_fcs_rport_sm_t sm; /* state machine function */141 enum bfa_rport_state state; /* state machine encoding */142 char *name; /* state name for display */143};144 145static inline enum bfa_rport_state146bfa_rport_sm_to_state(struct bfa_fcs_rport_sm_table_s *smt, bfa_fcs_rport_sm_t sm)147{148 int i = 0;149 150 while (smt[i].sm && smt[i].sm != sm)151 i++;152 return smt[i].state;153}154 155static struct bfa_fcs_rport_sm_table_s rport_sm_table[] = {156 {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},157 {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},158 {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},159 {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},160 {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},161 {BFA_SM(bfa_fcs_rport_sm_fc4_fcs_online), BFA_RPORT_ONLINE},162 {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},163 {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},164 {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},165 {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},166 {BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC},167 {BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC},168 {BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC},169 {BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},170 {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},171 {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},172 {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},173 {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},174 {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},175 {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},176 {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},177 {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},178 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},179 {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},180 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},181};182 183/*184 * Beginning state.185 */186static void187bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)188{189 bfa_trc(rport->fcs, rport->pwwn);190 bfa_trc(rport->fcs, rport->pid);191 bfa_trc(rport->fcs, event);192 193 switch (event) {194 case RPSM_EVENT_PLOGI_SEND:195 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);196 rport->plogi_retries = 0;197 bfa_fcs_rport_send_plogi(rport, NULL);198 break;199 200 case RPSM_EVENT_PLOGI_RCVD:201 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);202 bfa_fcs_rport_send_plogiacc(rport, NULL);203 break;204 205 case RPSM_EVENT_PLOGI_COMP:206 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);207 bfa_fcs_rport_hal_online(rport);208 break;209 210 case RPSM_EVENT_ADDRESS_CHANGE:211 case RPSM_EVENT_ADDRESS_DISC:212 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);213 rport->ns_retries = 0;214 bfa_fcs_rport_send_nsdisc(rport, NULL);215 break;216 default:217 bfa_sm_fault(rport->fcs, event);218 }219}220 221/*222 * PLOGI is being sent.223 */224static void225bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,226 enum rport_event event)227{228 bfa_trc(rport->fcs, rport->pwwn);229 bfa_trc(rport->fcs, rport->pid);230 bfa_trc(rport->fcs, event);231 232 switch (event) {233 case RPSM_EVENT_FCXP_SENT:234 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);235 break;236 237 case RPSM_EVENT_DELETE:238 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);239 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);240 bfa_fcs_rport_free(rport);241 break;242 243 case RPSM_EVENT_PLOGI_RCVD:244 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);245 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);246 bfa_fcs_rport_send_plogiacc(rport, NULL);247 break;248 249 case RPSM_EVENT_SCN_OFFLINE:250 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);251 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);252 bfa_timer_start(rport->fcs->bfa, &rport->timer,253 bfa_fcs_rport_timeout, rport,254 bfa_fcs_rport_del_timeout);255 break;256 case RPSM_EVENT_ADDRESS_CHANGE:257 case RPSM_EVENT_FAB_SCN:258 /* query the NS */259 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);260 WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=261 BFA_PORT_TOPOLOGY_LOOP));262 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);263 rport->ns_retries = 0;264 bfa_fcs_rport_send_nsdisc(rport, NULL);265 break;266 267 case RPSM_EVENT_LOGO_IMP:268 rport->pid = 0;269 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);270 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);271 bfa_timer_start(rport->fcs->bfa, &rport->timer,272 bfa_fcs_rport_timeout, rport,273 bfa_fcs_rport_del_timeout);274 break;275 276 277 default:278 bfa_sm_fault(rport->fcs, event);279 }280}281 282/*283 * PLOGI is being sent.284 */285static void286bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,287 enum rport_event event)288{289 bfa_trc(rport->fcs, rport->pwwn);290 bfa_trc(rport->fcs, rport->pid);291 bfa_trc(rport->fcs, event);292 293 switch (event) {294 case RPSM_EVENT_FCXP_SENT:295 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);296 bfa_fcs_rport_fcs_online_action(rport);297 break;298 299 case RPSM_EVENT_DELETE:300 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);301 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);302 bfa_fcs_rport_free(rport);303 break;304 305 case RPSM_EVENT_PLOGI_RCVD:306 case RPSM_EVENT_PLOGI_COMP:307 case RPSM_EVENT_FAB_SCN:308 /*309 * Ignore, SCN is possibly online notification.310 */311 break;312 313 case RPSM_EVENT_SCN_OFFLINE:314 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);315 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);316 bfa_timer_start(rport->fcs->bfa, &rport->timer,317 bfa_fcs_rport_timeout, rport,318 bfa_fcs_rport_del_timeout);319 break;320 321 case RPSM_EVENT_ADDRESS_CHANGE:322 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);323 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);324 rport->ns_retries = 0;325 bfa_fcs_rport_send_nsdisc(rport, NULL);326 break;327 328 case RPSM_EVENT_LOGO_IMP:329 rport->pid = 0;330 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);331 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);332 bfa_timer_start(rport->fcs->bfa, &rport->timer,333 bfa_fcs_rport_timeout, rport,334 bfa_fcs_rport_del_timeout);335 break;336 337 case RPSM_EVENT_HCB_OFFLINE:338 /*339 * Ignore BFA callback, on a PLOGI receive we call bfa offline.340 */341 break;342 343 default:344 bfa_sm_fault(rport->fcs, event);345 }346}347 348/*349 * PLOGI is sent.350 */351static void352bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,353 enum rport_event event)354{355 bfa_trc(rport->fcs, rport->pwwn);356 bfa_trc(rport->fcs, rport->pid);357 bfa_trc(rport->fcs, event);358 359 switch (event) {360 case RPSM_EVENT_TIMEOUT:361 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);362 bfa_fcs_rport_send_plogi(rport, NULL);363 break;364 365 case RPSM_EVENT_DELETE:366 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);367 bfa_timer_stop(&rport->timer);368 bfa_fcs_rport_free(rport);369 break;370 371 case RPSM_EVENT_PRLO_RCVD:372 case RPSM_EVENT_LOGO_RCVD:373 break;374 375 case RPSM_EVENT_PLOGI_RCVD:376 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);377 bfa_timer_stop(&rport->timer);378 bfa_fcs_rport_send_plogiacc(rport, NULL);379 break;380 381 case RPSM_EVENT_SCN_OFFLINE:382 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);383 bfa_timer_stop(&rport->timer);384 bfa_timer_start(rport->fcs->bfa, &rport->timer,385 bfa_fcs_rport_timeout, rport,386 bfa_fcs_rport_del_timeout);387 break;388 389 case RPSM_EVENT_ADDRESS_CHANGE:390 case RPSM_EVENT_FAB_SCN:391 bfa_timer_stop(&rport->timer);392 WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=393 BFA_PORT_TOPOLOGY_LOOP));394 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);395 rport->ns_retries = 0;396 bfa_fcs_rport_send_nsdisc(rport, NULL);397 break;398 399 case RPSM_EVENT_LOGO_IMP:400 rport->pid = 0;401 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);402 bfa_timer_stop(&rport->timer);403 bfa_timer_start(rport->fcs->bfa, &rport->timer,404 bfa_fcs_rport_timeout, rport,405 bfa_fcs_rport_del_timeout);406 break;407 408 case RPSM_EVENT_PLOGI_COMP:409 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);410 bfa_timer_stop(&rport->timer);411 bfa_fcs_rport_fcs_online_action(rport);412 break;413 414 default:415 bfa_sm_fault(rport->fcs, event);416 }417}418 419/*420 * PLOGI is sent.421 */422static void423bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)424{425 bfa_trc(rport->fcs, rport->pwwn);426 bfa_trc(rport->fcs, rport->pid);427 bfa_trc(rport->fcs, event);428 429 switch (event) {430 case RPSM_EVENT_ACCEPTED:431 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);432 rport->plogi_retries = 0;433 bfa_fcs_rport_fcs_online_action(rport);434 break;435 436 case RPSM_EVENT_LOGO_RCVD:437 bfa_fcs_rport_send_logo_acc(rport);438 fallthrough;439 case RPSM_EVENT_PRLO_RCVD:440 if (rport->prlo == BFA_TRUE)441 bfa_fcs_rport_send_prlo_acc(rport);442 443 bfa_fcxp_discard(rport->fcxp);444 fallthrough;445 case RPSM_EVENT_FAILED:446 if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {447 rport->plogi_retries++;448 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);449 bfa_timer_start(rport->fcs->bfa, &rport->timer,450 bfa_fcs_rport_timeout, rport,451 BFA_FCS_RETRY_TIMEOUT);452 } else {453 bfa_stats(rport->port, rport_del_max_plogi_retry);454 rport->old_pid = rport->pid;455 rport->pid = 0;456 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);457 bfa_timer_start(rport->fcs->bfa, &rport->timer,458 bfa_fcs_rport_timeout, rport,459 bfa_fcs_rport_del_timeout);460 }461 break;462 463 case RPSM_EVENT_SCN_ONLINE:464 break;465 466 case RPSM_EVENT_SCN_OFFLINE:467 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);468 bfa_fcxp_discard(rport->fcxp);469 bfa_timer_start(rport->fcs->bfa, &rport->timer,470 bfa_fcs_rport_timeout, rport,471 bfa_fcs_rport_del_timeout);472 break;473 474 case RPSM_EVENT_PLOGI_RETRY:475 rport->plogi_retries = 0;476 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);477 bfa_timer_start(rport->fcs->bfa, &rport->timer,478 bfa_fcs_rport_timeout, rport,479 (FC_RA_TOV * 1000));480 break;481 482 case RPSM_EVENT_LOGO_IMP:483 rport->pid = 0;484 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);485 bfa_fcxp_discard(rport->fcxp);486 bfa_timer_start(rport->fcs->bfa, &rport->timer,487 bfa_fcs_rport_timeout, rport,488 bfa_fcs_rport_del_timeout);489 break;490 491 case RPSM_EVENT_ADDRESS_CHANGE:492 case RPSM_EVENT_FAB_SCN:493 bfa_fcxp_discard(rport->fcxp);494 WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=495 BFA_PORT_TOPOLOGY_LOOP));496 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);497 rport->ns_retries = 0;498 bfa_fcs_rport_send_nsdisc(rport, NULL);499 break;500 501 case RPSM_EVENT_PLOGI_RCVD:502 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);503 bfa_fcxp_discard(rport->fcxp);504 bfa_fcs_rport_send_plogiacc(rport, NULL);505 break;506 507 case RPSM_EVENT_DELETE:508 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);509 bfa_fcxp_discard(rport->fcxp);510 bfa_fcs_rport_free(rport);511 break;512 513 case RPSM_EVENT_PLOGI_COMP:514 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);515 bfa_fcxp_discard(rport->fcxp);516 bfa_fcs_rport_fcs_online_action(rport);517 break;518 519 default:520 bfa_sm_fault(rport->fcs, event);521 }522}523 524/*525 * PLOGI is done. Await bfa_fcs_itnim to ascertain the scsi function526 */527static void528bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,529 enum rport_event event)530{531 bfa_trc(rport->fcs, rport->pwwn);532 bfa_trc(rport->fcs, rport->pid);533 bfa_trc(rport->fcs, event);534 535 switch (event) {536 case RPSM_EVENT_FC4_FCS_ONLINE:537 if (rport->scsi_function == BFA_RPORT_INITIATOR) {538 if (!BFA_FCS_PID_IS_WKA(rport->pid))539 bfa_fcs_rpf_rport_online(rport);540 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);541 break;542 }543 544 if (!rport->bfa_rport)545 rport->bfa_rport =546 bfa_rport_create(rport->fcs->bfa, rport);547 548 if (rport->bfa_rport) {549 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);550 bfa_fcs_rport_hal_online(rport);551 } else {552 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);553 bfa_fcs_rport_fcs_offline_action(rport);554 }555 break;556 557 case RPSM_EVENT_PLOGI_RCVD:558 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);559 rport->plogi_pending = BFA_TRUE;560 bfa_fcs_rport_fcs_offline_action(rport);561 break;562 563 case RPSM_EVENT_PLOGI_COMP:564 case RPSM_EVENT_LOGO_IMP:565 case RPSM_EVENT_ADDRESS_CHANGE:566 case RPSM_EVENT_FAB_SCN:567 case RPSM_EVENT_SCN_OFFLINE:568 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);569 bfa_fcs_rport_fcs_offline_action(rport);570 break;571 572 case RPSM_EVENT_LOGO_RCVD:573 case RPSM_EVENT_PRLO_RCVD:574 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);575 bfa_fcs_rport_fcs_offline_action(rport);576 break;577 578 case RPSM_EVENT_DELETE:579 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);580 bfa_fcs_rport_fcs_offline_action(rport);581 break;582 583 default:584 bfa_sm_fault(rport->fcs, event);585 break;586 }587}588 589/*590 * PLOGI is complete. Awaiting BFA rport online callback. FC-4s591 * are offline.592 */593static void594bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,595 enum rport_event event)596{597 bfa_trc(rport->fcs, rport->pwwn);598 bfa_trc(rport->fcs, rport->pid);599 bfa_trc(rport->fcs, event);600 601 switch (event) {602 case RPSM_EVENT_HCB_ONLINE:603 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);604 bfa_fcs_rport_hal_online_action(rport);605 break;606 607 case RPSM_EVENT_PLOGI_COMP:608 break;609 610 case RPSM_EVENT_PRLO_RCVD:611 case RPSM_EVENT_LOGO_RCVD:612 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);613 bfa_fcs_rport_fcs_offline_action(rport);614 break;615 616 case RPSM_EVENT_FAB_SCN:617 case RPSM_EVENT_LOGO_IMP:618 case RPSM_EVENT_ADDRESS_CHANGE:619 case RPSM_EVENT_SCN_OFFLINE:620 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);621 bfa_fcs_rport_fcs_offline_action(rport);622 break;623 624 case RPSM_EVENT_PLOGI_RCVD:625 rport->plogi_pending = BFA_TRUE;626 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);627 bfa_fcs_rport_fcs_offline_action(rport);628 break;629 630 case RPSM_EVENT_DELETE:631 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);632 bfa_fcs_rport_fcs_offline_action(rport);633 break;634 635 default:636 bfa_sm_fault(rport->fcs, event);637 }638}639 640/*641 * Rport is ONLINE. FC-4s active.642 */643static void644bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)645{646 bfa_trc(rport->fcs, rport->pwwn);647 bfa_trc(rport->fcs, rport->pid);648 bfa_trc(rport->fcs, event);649 650 switch (event) {651 case RPSM_EVENT_FAB_SCN:652 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {653 bfa_sm_set_state(rport,654 bfa_fcs_rport_sm_nsquery_sending);655 rport->ns_retries = 0;656 bfa_fcs_rport_send_nsdisc(rport, NULL);657 } else {658 bfa_sm_set_state(rport,659 bfa_fcs_rport_sm_adisc_online_sending);660 bfa_fcs_rport_send_adisc(rport, NULL);661 }662 break;663 664 case RPSM_EVENT_PLOGI_RCVD:665 case RPSM_EVENT_LOGO_IMP:666 case RPSM_EVENT_ADDRESS_CHANGE:667 case RPSM_EVENT_SCN_OFFLINE:668 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);669 bfa_fcs_rport_hal_offline_action(rport);670 break;671 672 case RPSM_EVENT_DELETE:673 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);674 bfa_fcs_rport_hal_offline_action(rport);675 break;676 677 case RPSM_EVENT_LOGO_RCVD:678 case RPSM_EVENT_PRLO_RCVD:679 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);680 bfa_fcs_rport_hal_offline_action(rport);681 break;682 683 case RPSM_EVENT_SCN_ONLINE:684 case RPSM_EVENT_PLOGI_COMP:685 break;686 687 default:688 bfa_sm_fault(rport->fcs, event);689 }690}691 692/*693 * An SCN event is received in ONLINE state. NS query is being sent694 * prior to ADISC authentication with rport. FC-4s are paused.695 */696static void697bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,698 enum rport_event event)699{700 bfa_trc(rport->fcs, rport->pwwn);701 bfa_trc(rport->fcs, rport->pid);702 bfa_trc(rport->fcs, event);703 704 switch (event) {705 case RPSM_EVENT_FCXP_SENT:706 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);707 break;708 709 case RPSM_EVENT_DELETE:710 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);711 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);712 bfa_fcs_rport_hal_offline_action(rport);713 break;714 715 case RPSM_EVENT_FAB_SCN:716 /*717 * ignore SCN, wait for response to query itself718 */719 break;720 721 case RPSM_EVENT_LOGO_RCVD:722 case RPSM_EVENT_PRLO_RCVD:723 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);724 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);725 bfa_fcs_rport_hal_offline_action(rport);726 break;727 728 case RPSM_EVENT_LOGO_IMP:729 case RPSM_EVENT_PLOGI_RCVD:730 case RPSM_EVENT_ADDRESS_CHANGE:731 case RPSM_EVENT_PLOGI_COMP:732 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);733 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);734 bfa_fcs_rport_hal_offline_action(rport);735 break;736 737 default:738 bfa_sm_fault(rport->fcs, event);739 }740}741 742/*743 * An SCN event is received in ONLINE state. NS query is sent to rport.744 * FC-4s are paused.745 */746static void747bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)748{749 bfa_trc(rport->fcs, rport->pwwn);750 bfa_trc(rport->fcs, rport->pid);751 bfa_trc(rport->fcs, event);752 753 switch (event) {754 case RPSM_EVENT_ACCEPTED:755 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);756 bfa_fcs_rport_send_adisc(rport, NULL);757 break;758 759 case RPSM_EVENT_FAILED:760 rport->ns_retries++;761 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {762 bfa_sm_set_state(rport,763 bfa_fcs_rport_sm_nsquery_sending);764 bfa_fcs_rport_send_nsdisc(rport, NULL);765 } else {766 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);767 bfa_fcs_rport_hal_offline_action(rport);768 }769 break;770 771 case RPSM_EVENT_DELETE:772 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);773 bfa_fcxp_discard(rport->fcxp);774 bfa_fcs_rport_hal_offline_action(rport);775 break;776 777 case RPSM_EVENT_FAB_SCN:778 break;779 780 case RPSM_EVENT_LOGO_RCVD:781 case RPSM_EVENT_PRLO_RCVD:782 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);783 bfa_fcxp_discard(rport->fcxp);784 bfa_fcs_rport_hal_offline_action(rport);785 break;786 787 case RPSM_EVENT_PLOGI_COMP:788 case RPSM_EVENT_ADDRESS_CHANGE:789 case RPSM_EVENT_PLOGI_RCVD:790 case RPSM_EVENT_LOGO_IMP:791 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);792 bfa_fcxp_discard(rport->fcxp);793 bfa_fcs_rport_hal_offline_action(rport);794 break;795 796 default:797 bfa_sm_fault(rport->fcs, event);798 }799}800 801/*802 * An SCN event is received in ONLINE state. ADISC is being sent for803 * authenticating with rport. FC-4s are paused.804 */805static void806bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,807 enum rport_event event)808{809 bfa_trc(rport->fcs, rport->pwwn);810 bfa_trc(rport->fcs, rport->pid);811 bfa_trc(rport->fcs, event);812 813 switch (event) {814 case RPSM_EVENT_FCXP_SENT:815 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);816 break;817 818 case RPSM_EVENT_DELETE:819 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);820 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);821 bfa_fcs_rport_hal_offline_action(rport);822 break;823 824 case RPSM_EVENT_LOGO_IMP:825 case RPSM_EVENT_ADDRESS_CHANGE:826 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);827 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);828 bfa_fcs_rport_hal_offline_action(rport);829 break;830 831 case RPSM_EVENT_LOGO_RCVD:832 case RPSM_EVENT_PRLO_RCVD:833 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);834 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);835 bfa_fcs_rport_hal_offline_action(rport);836 break;837 838 case RPSM_EVENT_FAB_SCN:839 break;840 841 case RPSM_EVENT_PLOGI_RCVD:842 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);843 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);844 bfa_fcs_rport_hal_offline_action(rport);845 break;846 847 default:848 bfa_sm_fault(rport->fcs, event);849 }850}851 852/*853 * An SCN event is received in ONLINE state. ADISC is to rport.854 * FC-4s are paused.855 */856static void857bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,858 enum rport_event event)859{860 bfa_trc(rport->fcs, rport->pwwn);861 bfa_trc(rport->fcs, rport->pid);862 bfa_trc(rport->fcs, event);863 864 switch (event) {865 case RPSM_EVENT_ACCEPTED:866 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);867 break;868 869 case RPSM_EVENT_PLOGI_RCVD:870 /*871 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.872 * At least go offline when a PLOGI is received.873 */874 bfa_fcxp_discard(rport->fcxp);875 fallthrough;876 877 case RPSM_EVENT_FAILED:878 case RPSM_EVENT_ADDRESS_CHANGE:879 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);880 bfa_fcs_rport_hal_offline_action(rport);881 break;882 883 case RPSM_EVENT_DELETE:884 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);885 bfa_fcxp_discard(rport->fcxp);886 bfa_fcs_rport_hal_offline_action(rport);887 break;888 889 case RPSM_EVENT_FAB_SCN:890 /*891 * already processing RSCN892 */893 break;894 895 case RPSM_EVENT_LOGO_IMP:896 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);897 bfa_fcxp_discard(rport->fcxp);898 bfa_fcs_rport_hal_offline_action(rport);899 break;900 901 case RPSM_EVENT_LOGO_RCVD:902 case RPSM_EVENT_PRLO_RCVD:903 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);904 bfa_fcxp_discard(rport->fcxp);905 bfa_fcs_rport_hal_offline_action(rport);906 break;907 908 default:909 bfa_sm_fault(rport->fcs, event);910 }911}912 913/*914 * ADISC is being sent for authenticating with rport915 * Already did offline actions.916 */917static void918bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport,919 enum rport_event event)920{921 bfa_trc(rport->fcs, rport->pwwn);922 bfa_trc(rport->fcs, rport->pid);923 bfa_trc(rport->fcs, event);924 925 switch (event) {926 case RPSM_EVENT_FCXP_SENT:927 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline);928 break;929 930 case RPSM_EVENT_DELETE:931 case RPSM_EVENT_SCN_OFFLINE:932 case RPSM_EVENT_LOGO_IMP:933 case RPSM_EVENT_LOGO_RCVD:934 case RPSM_EVENT_PRLO_RCVD:935 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);936 bfa_fcxp_walloc_cancel(rport->fcs->bfa,937 &rport->fcxp_wqe);938 bfa_timer_start(rport->fcs->bfa, &rport->timer,939 bfa_fcs_rport_timeout, rport,940 bfa_fcs_rport_del_timeout);941 break;942 943 case RPSM_EVENT_PLOGI_RCVD:944 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);945 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);946 bfa_fcs_rport_send_plogiacc(rport, NULL);947 break;948 949 default:950 bfa_sm_fault(rport->fcs, event);951 }952}953 954/*955 * ADISC to rport956 * Already did offline actions957 */958static void959bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,960 enum rport_event event)961{962 bfa_trc(rport->fcs, rport->pwwn);963 bfa_trc(rport->fcs, rport->pid);964 bfa_trc(rport->fcs, event);965 966 switch (event) {967 case RPSM_EVENT_ACCEPTED:968 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);969 bfa_fcs_rport_hal_online(rport);970 break;971 972 case RPSM_EVENT_PLOGI_RCVD:973 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);974 bfa_fcxp_discard(rport->fcxp);975 bfa_fcs_rport_send_plogiacc(rport, NULL);976 break;977 978 case RPSM_EVENT_FAILED:979 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);980 bfa_timer_start(rport->fcs->bfa, &rport->timer,981 bfa_fcs_rport_timeout, rport,982 bfa_fcs_rport_del_timeout);983 break;984 985 case RPSM_EVENT_DELETE:986 case RPSM_EVENT_SCN_OFFLINE:987 case RPSM_EVENT_LOGO_IMP:988 case RPSM_EVENT_LOGO_RCVD:989 case RPSM_EVENT_PRLO_RCVD:990 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);991 bfa_fcxp_discard(rport->fcxp);992 bfa_timer_start(rport->fcs->bfa, &rport->timer,993 bfa_fcs_rport_timeout, rport,994 bfa_fcs_rport_del_timeout);995 break;996 997 default:998 bfa_sm_fault(rport->fcs, event);999 }1000}1001 1002/*1003 * Rport has sent LOGO. Awaiting FC-4 offline completion callback.1004 */1005static void1006bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,1007 enum rport_event event)1008{1009 bfa_trc(rport->fcs, rport->pwwn);1010 bfa_trc(rport->fcs, rport->pid);1011 bfa_trc(rport->fcs, event);1012 1013 switch (event) {1014 case RPSM_EVENT_FC4_OFFLINE:1015 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);1016 bfa_fcs_rport_hal_offline(rport);1017 break;1018 1019 case RPSM_EVENT_DELETE:1020 if (rport->pid && (rport->prlo == BFA_TRUE))1021 bfa_fcs_rport_send_prlo_acc(rport);1022 if (rport->pid && (rport->prlo == BFA_FALSE))1023 bfa_fcs_rport_send_logo_acc(rport);1024 1025 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);1026 break;1027 1028 case RPSM_EVENT_SCN_ONLINE:1029 case RPSM_EVENT_SCN_OFFLINE:1030 case RPSM_EVENT_HCB_ONLINE:1031 case RPSM_EVENT_LOGO_RCVD:1032 case RPSM_EVENT_PRLO_RCVD:1033 case RPSM_EVENT_ADDRESS_CHANGE:1034 break;1035 1036 default:1037 bfa_sm_fault(rport->fcs, event);1038 }1039}1040 1041/*1042 * LOGO needs to be sent to rport. Awaiting FC-4 offline completion1043 * callback.1044 */1045static void1046bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,1047 enum rport_event event)1048{1049 bfa_trc(rport->fcs, rport->pwwn);1050 bfa_trc(rport->fcs, rport->pid);1051 bfa_trc(rport->fcs, event);1052 1053 switch (event) {1054 case RPSM_EVENT_FC4_OFFLINE:1055 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);1056 bfa_fcs_rport_hal_offline(rport);1057 break;1058 1059 case RPSM_EVENT_LOGO_RCVD:1060 bfa_fcs_rport_send_logo_acc(rport);1061 fallthrough;1062 case RPSM_EVENT_PRLO_RCVD:1063 if (rport->prlo == BFA_TRUE)1064 bfa_fcs_rport_send_prlo_acc(rport);1065 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);1066 break;1067 1068 case RPSM_EVENT_HCB_ONLINE:1069 case RPSM_EVENT_DELETE:1070 /* Rport is being deleted */1071 break;1072 1073 default:1074 bfa_sm_fault(rport->fcs, event);1075 }1076}1077 1078/*1079 * Rport is going offline. Awaiting FC-4 offline completion callback.1080 */1081static void1082bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,1083 enum rport_event event)1084{1085 bfa_trc(rport->fcs, rport->pwwn);1086 bfa_trc(rport->fcs, rport->pid);1087 bfa_trc(rport->fcs, event);1088 1089 switch (event) {1090 case RPSM_EVENT_FC4_OFFLINE:1091 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);1092 bfa_fcs_rport_hal_offline(rport);1093 break;1094 1095 case RPSM_EVENT_SCN_ONLINE:1096 break;1097 case RPSM_EVENT_LOGO_RCVD:1098 /*1099 * Rport is going offline. Just ack the logo1100 */1101 bfa_fcs_rport_send_logo_acc(rport);1102 break;1103 1104 case RPSM_EVENT_PRLO_RCVD:1105 bfa_fcs_rport_send_prlo_acc(rport);1106 break;1107 1108 case RPSM_EVENT_SCN_OFFLINE:1109 case RPSM_EVENT_HCB_ONLINE:1110 case RPSM_EVENT_FAB_SCN:1111 case RPSM_EVENT_LOGO_IMP:1112 case RPSM_EVENT_ADDRESS_CHANGE:1113 /*1114 * rport is already going offline.1115 * SCN - ignore and wait till transitioning to offline state1116 */1117 break;1118 1119 case RPSM_EVENT_DELETE:1120 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);1121 break;1122 1123 default:1124 bfa_sm_fault(rport->fcs, event);1125 }1126}1127 1128/*1129 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline1130 * callback.1131 */1132static void1133bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,1134 enum rport_event event)1135{1136 bfa_trc(rport->fcs, rport->pwwn);1137 bfa_trc(rport->fcs, rport->pid);1138 bfa_trc(rport->fcs, event);1139 1140 switch (event) {1141 case RPSM_EVENT_HCB_OFFLINE:1142 if (bfa_fcs_lport_is_online(rport->port) &&1143 (rport->plogi_pending)) {1144 rport->plogi_pending = BFA_FALSE;1145 bfa_sm_set_state(rport,1146 bfa_fcs_rport_sm_plogiacc_sending);1147 bfa_fcs_rport_send_plogiacc(rport, NULL);1148 break;1149 }1150 fallthrough;1151 1152 case RPSM_EVENT_ADDRESS_CHANGE:1153 if (!bfa_fcs_lport_is_online(rport->port)) {1154 rport->pid = 0;1155 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1156 bfa_timer_start(rport->fcs->bfa, &rport->timer,1157 bfa_fcs_rport_timeout, rport,1158 bfa_fcs_rport_del_timeout);1159 break;1160 }1161 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {1162 bfa_sm_set_state(rport,1163 bfa_fcs_rport_sm_nsdisc_sending);1164 rport->ns_retries = 0;1165 bfa_fcs_rport_send_nsdisc(rport, NULL);1166 } else if (bfa_fcport_get_topology(rport->port->fcs->bfa) ==1167 BFA_PORT_TOPOLOGY_LOOP) {1168 if (rport->scn_online) {1169 bfa_sm_set_state(rport,1170 bfa_fcs_rport_sm_adisc_offline_sending);1171 bfa_fcs_rport_send_adisc(rport, NULL);1172 } else {1173 bfa_sm_set_state(rport,1174 bfa_fcs_rport_sm_offline);1175 bfa_timer_start(rport->fcs->bfa, &rport->timer,1176 bfa_fcs_rport_timeout, rport,1177 bfa_fcs_rport_del_timeout);1178 }1179 } else {1180 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);1181 rport->plogi_retries = 0;1182 bfa_fcs_rport_send_plogi(rport, NULL);1183 }1184 break;1185 1186 case RPSM_EVENT_DELETE:1187 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1188 bfa_fcs_rport_free(rport);1189 break;1190 1191 case RPSM_EVENT_SCN_ONLINE:1192 case RPSM_EVENT_SCN_OFFLINE:1193 case RPSM_EVENT_FAB_SCN:1194 case RPSM_EVENT_LOGO_RCVD:1195 case RPSM_EVENT_PRLO_RCVD:1196 case RPSM_EVENT_PLOGI_RCVD:1197 case RPSM_EVENT_LOGO_IMP:1198 /*1199 * Ignore, already offline.1200 */1201 break;1202 1203 default:1204 bfa_sm_fault(rport->fcs, event);1205 }1206}1207 1208/*1209 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline1210 * callback to send LOGO accept.1211 */1212static void1213bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,1214 enum rport_event event)1215{1216 bfa_trc(rport->fcs, rport->pwwn);1217 bfa_trc(rport->fcs, rport->pid);1218 bfa_trc(rport->fcs, event);1219 1220 switch (event) {1221 case RPSM_EVENT_HCB_OFFLINE:1222 case RPSM_EVENT_ADDRESS_CHANGE:1223 if (rport->pid && (rport->prlo == BFA_TRUE))1224 bfa_fcs_rport_send_prlo_acc(rport);1225 if (rport->pid && (rport->prlo == BFA_FALSE))1226 bfa_fcs_rport_send_logo_acc(rport);1227 /*1228 * If the lport is online and if the rport is not a well1229 * known address port,1230 * we try to re-discover the r-port.1231 */1232 if (bfa_fcs_lport_is_online(rport->port) &&1233 (!BFA_FCS_PID_IS_WKA(rport->pid))) {1234 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {1235 bfa_sm_set_state(rport,1236 bfa_fcs_rport_sm_nsdisc_sending);1237 rport->ns_retries = 0;1238 bfa_fcs_rport_send_nsdisc(rport, NULL);1239 } else {1240 /* For N2N Direct Attach, try to re-login */1241 bfa_sm_set_state(rport,1242 bfa_fcs_rport_sm_plogi_sending);1243 rport->plogi_retries = 0;1244 bfa_fcs_rport_send_plogi(rport, NULL);1245 }1246 } else {1247 /*1248 * if it is not a well known address, reset the1249 * pid to 0.1250 */1251 if (!BFA_FCS_PID_IS_WKA(rport->pid))1252 rport->pid = 0;1253 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1254 bfa_timer_start(rport->fcs->bfa, &rport->timer,1255 bfa_fcs_rport_timeout, rport,1256 bfa_fcs_rport_del_timeout);1257 }1258 break;1259 1260 case RPSM_EVENT_DELETE:1261 bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);1262 if (rport->pid && (rport->prlo == BFA_TRUE))1263 bfa_fcs_rport_send_prlo_acc(rport);1264 if (rport->pid && (rport->prlo == BFA_FALSE))1265 bfa_fcs_rport_send_logo_acc(rport);1266 break;1267 1268 case RPSM_EVENT_LOGO_IMP:1269 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);1270 break;1271 1272 case RPSM_EVENT_SCN_ONLINE:1273 case RPSM_EVENT_SCN_OFFLINE:1274 case RPSM_EVENT_LOGO_RCVD:1275 case RPSM_EVENT_PRLO_RCVD:1276 /*1277 * Ignore - already processing a LOGO.1278 */1279 break;1280 1281 default:1282 bfa_sm_fault(rport->fcs, event);1283 }1284}1285 1286/*1287 * Rport is being deleted. FC-4s are offline.1288 * Awaiting BFA rport offline1289 * callback to send LOGO.1290 */1291static void1292bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,1293 enum rport_event event)1294{1295 bfa_trc(rport->fcs, rport->pwwn);1296 bfa_trc(rport->fcs, rport->pid);1297 bfa_trc(rport->fcs, event);1298 1299 switch (event) {1300 case RPSM_EVENT_HCB_OFFLINE:1301 bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);1302 bfa_fcs_rport_send_logo(rport, NULL);1303 break;1304 1305 case RPSM_EVENT_LOGO_RCVD:1306 bfa_fcs_rport_send_logo_acc(rport);1307 fallthrough;1308 case RPSM_EVENT_PRLO_RCVD:1309 if (rport->prlo == BFA_TRUE)1310 bfa_fcs_rport_send_prlo_acc(rport);1311 1312 bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);1313 break;1314 1315 case RPSM_EVENT_SCN_ONLINE:1316 case RPSM_EVENT_SCN_OFFLINE:1317 case RPSM_EVENT_ADDRESS_CHANGE:1318 break;1319 1320 default:1321 bfa_sm_fault(rport->fcs, event);1322 }1323}1324 1325/*1326 * Rport is being deleted. FC-4s are offline. LOGO is being sent.1327 */1328static void1329bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,1330 enum rport_event event)1331{1332 bfa_trc(rport->fcs, rport->pwwn);1333 bfa_trc(rport->fcs, rport->pid);1334 bfa_trc(rport->fcs, event);1335 1336 switch (event) {1337 case RPSM_EVENT_FCXP_SENT:1338 /* Once LOGO is sent, we donot wait for the response */1339 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1340 bfa_fcs_rport_free(rport);1341 break;1342 1343 case RPSM_EVENT_SCN_ONLINE:1344 case RPSM_EVENT_SCN_OFFLINE:1345 case RPSM_EVENT_FAB_SCN:1346 case RPSM_EVENT_ADDRESS_CHANGE:1347 break;1348 1349 case RPSM_EVENT_LOGO_RCVD:1350 bfa_fcs_rport_send_logo_acc(rport);1351 fallthrough;1352 case RPSM_EVENT_PRLO_RCVD:1353 if (rport->prlo == BFA_TRUE)1354 bfa_fcs_rport_send_prlo_acc(rport);1355 1356 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1357 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1358 bfa_fcs_rport_free(rport);1359 break;1360 1361 default:1362 bfa_sm_fault(rport->fcs, event);1363 }1364}1365 1366/*1367 * Rport is offline. FC-4s are offline. BFA rport is offline.1368 * Timer active to delete stale rport.1369 */1370static void1371bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)1372{1373 bfa_trc(rport->fcs, rport->pwwn);1374 bfa_trc(rport->fcs, rport->pid);1375 bfa_trc(rport->fcs, event);1376 1377 switch (event) {1378 case RPSM_EVENT_TIMEOUT:1379 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1380 bfa_fcs_rport_free(rport);1381 break;1382 1383 case RPSM_EVENT_FAB_SCN:1384 case RPSM_EVENT_ADDRESS_CHANGE:1385 bfa_timer_stop(&rport->timer);1386 WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=1387 BFA_PORT_TOPOLOGY_LOOP));1388 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);1389 rport->ns_retries = 0;1390 bfa_fcs_rport_send_nsdisc(rport, NULL);1391 break;1392 1393 case RPSM_EVENT_DELETE:1394 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1395 bfa_timer_stop(&rport->timer);1396 bfa_fcs_rport_free(rport);1397 break;1398 1399 case RPSM_EVENT_PLOGI_RCVD:1400 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);1401 bfa_timer_stop(&rport->timer);1402 bfa_fcs_rport_send_plogiacc(rport, NULL);1403 break;1404 1405 case RPSM_EVENT_LOGO_RCVD:1406 case RPSM_EVENT_PRLO_RCVD:1407 case RPSM_EVENT_LOGO_IMP:1408 case RPSM_EVENT_SCN_OFFLINE:1409 break;1410 1411 case RPSM_EVENT_PLOGI_COMP:1412 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);1413 bfa_timer_stop(&rport->timer);1414 bfa_fcs_rport_fcs_online_action(rport);1415 break;1416 1417 case RPSM_EVENT_SCN_ONLINE:1418 bfa_timer_stop(&rport->timer);1419 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);1420 bfa_fcs_rport_send_plogi(rport, NULL);1421 break;1422 1423 case RPSM_EVENT_PLOGI_SEND:1424 bfa_timer_stop(&rport->timer);1425 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);1426 rport->plogi_retries = 0;1427 bfa_fcs_rport_send_plogi(rport, NULL);1428 break;1429 1430 default:1431 bfa_sm_fault(rport->fcs, event);1432 }1433}1434 1435/*1436 * Rport address has changed. Nameserver discovery request is being sent.1437 */1438static void1439bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,1440 enum rport_event event)1441{1442 bfa_trc(rport->fcs, rport->pwwn);1443 bfa_trc(rport->fcs, rport->pid);1444 bfa_trc(rport->fcs, event);1445 1446 switch (event) {1447 case RPSM_EVENT_FCXP_SENT:1448 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);1449 break;1450 1451 case RPSM_EVENT_DELETE:1452 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1453 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1454 bfa_fcs_rport_free(rport);1455 break;1456 1457 case RPSM_EVENT_PLOGI_RCVD:1458 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);1459 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1460 bfa_fcs_rport_send_plogiacc(rport, NULL);1461 break;1462 1463 case RPSM_EVENT_FAB_SCN:1464 case RPSM_EVENT_LOGO_RCVD:1465 case RPSM_EVENT_PRLO_RCVD:1466 case RPSM_EVENT_PLOGI_SEND:1467 break;1468 1469 case RPSM_EVENT_ADDRESS_CHANGE:1470 rport->ns_retries = 0; /* reset the retry count */1471 break;1472 1473 case RPSM_EVENT_LOGO_IMP:1474 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1475 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1476 bfa_timer_start(rport->fcs->bfa, &rport->timer,1477 bfa_fcs_rport_timeout, rport,1478 bfa_fcs_rport_del_timeout);1479 break;1480 1481 case RPSM_EVENT_PLOGI_COMP:1482 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);1483 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);1484 bfa_fcs_rport_fcs_online_action(rport);1485 break;1486 1487 default:1488 bfa_sm_fault(rport->fcs, event);1489 }1490}1491 1492/*1493 * Nameserver discovery failed. Waiting for timeout to retry.1494 */1495static void1496bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,1497 enum rport_event event)1498{1499 bfa_trc(rport->fcs, rport->pwwn);1500 bfa_trc(rport->fcs, rport->pid);1501 bfa_trc(rport->fcs, event);1502 1503 switch (event) {1504 case RPSM_EVENT_TIMEOUT:1505 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);1506 bfa_fcs_rport_send_nsdisc(rport, NULL);1507 break;1508 1509 case RPSM_EVENT_FAB_SCN:1510 case RPSM_EVENT_ADDRESS_CHANGE:1511 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);1512 bfa_timer_stop(&rport->timer);1513 rport->ns_retries = 0;1514 bfa_fcs_rport_send_nsdisc(rport, NULL);1515 break;1516 1517 case RPSM_EVENT_DELETE:1518 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1519 bfa_timer_stop(&rport->timer);1520 bfa_fcs_rport_free(rport);1521 break;1522 1523 case RPSM_EVENT_PLOGI_RCVD:1524 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);1525 bfa_timer_stop(&rport->timer);1526 bfa_fcs_rport_send_plogiacc(rport, NULL);1527 break;1528 1529 case RPSM_EVENT_LOGO_IMP:1530 rport->pid = 0;1531 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1532 bfa_timer_stop(&rport->timer);1533 bfa_timer_start(rport->fcs->bfa, &rport->timer,1534 bfa_fcs_rport_timeout, rport,1535 bfa_fcs_rport_del_timeout);1536 break;1537 1538 case RPSM_EVENT_LOGO_RCVD:1539 bfa_fcs_rport_send_logo_acc(rport);1540 break;1541 case RPSM_EVENT_PRLO_RCVD:1542 bfa_fcs_rport_send_prlo_acc(rport);1543 break;1544 1545 case RPSM_EVENT_PLOGI_COMP:1546 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);1547 bfa_timer_stop(&rport->timer);1548 bfa_fcs_rport_fcs_online_action(rport);1549 break;1550 1551 default:1552 bfa_sm_fault(rport->fcs, event);1553 }1554}1555 1556/*1557 * Rport address has changed. Nameserver discovery request is sent.1558 */1559static void1560bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,1561 enum rport_event event)1562{1563 bfa_trc(rport->fcs, rport->pwwn);1564 bfa_trc(rport->fcs, rport->pid);1565 bfa_trc(rport->fcs, event);1566 1567 switch (event) {1568 case RPSM_EVENT_ACCEPTED:1569 case RPSM_EVENT_ADDRESS_CHANGE:1570 if (rport->pid) {1571 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);1572 bfa_fcs_rport_send_plogi(rport, NULL);1573 } else {1574 bfa_sm_set_state(rport,1575 bfa_fcs_rport_sm_nsdisc_sending);1576 rport->ns_retries = 0;1577 bfa_fcs_rport_send_nsdisc(rport, NULL);1578 }1579 break;1580 1581 case RPSM_EVENT_FAILED:1582 rport->ns_retries++;1583 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {1584 bfa_sm_set_state(rport,1585 bfa_fcs_rport_sm_nsdisc_sending);1586 bfa_fcs_rport_send_nsdisc(rport, NULL);1587 } else {1588 rport->old_pid = rport->pid;1589 rport->pid = 0;1590 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1591 bfa_timer_start(rport->fcs->bfa, &rport->timer,1592 bfa_fcs_rport_timeout, rport,1593 bfa_fcs_rport_del_timeout);1594 }1595 break;1596 1597 case RPSM_EVENT_DELETE:1598 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1599 bfa_fcxp_discard(rport->fcxp);1600 bfa_fcs_rport_free(rport);1601 break;1602 1603 case RPSM_EVENT_PLOGI_RCVD:1604 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);1605 bfa_fcxp_discard(rport->fcxp);1606 bfa_fcs_rport_send_plogiacc(rport, NULL);1607 break;1608 1609 case RPSM_EVENT_LOGO_IMP:1610 rport->pid = 0;1611 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);1612 bfa_fcxp_discard(rport->fcxp);1613 bfa_timer_start(rport->fcs->bfa, &rport->timer,1614 bfa_fcs_rport_timeout, rport,1615 bfa_fcs_rport_del_timeout);1616 break;1617 1618 1619 case RPSM_EVENT_PRLO_RCVD:1620 bfa_fcs_rport_send_prlo_acc(rport);1621 break;1622 case RPSM_EVENT_FAB_SCN:1623 /*1624 * ignore, wait for NS query response1625 */1626 break;1627 1628 case RPSM_EVENT_LOGO_RCVD:1629 /*1630 * Not logged-in yet. Accept LOGO.1631 */1632 bfa_fcs_rport_send_logo_acc(rport);1633 break;1634 1635 case RPSM_EVENT_PLOGI_COMP:1636 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);1637 bfa_fcxp_discard(rport->fcxp);1638 bfa_fcs_rport_fcs_online_action(rport);1639 break;1640 1641 default:1642 bfa_sm_fault(rport->fcs, event);1643 }1644}1645 1646/*1647 * Rport needs to be deleted1648 * waiting for ITNIM clean up to finish1649 */1650static void1651bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,1652 enum rport_event event)1653{1654 bfa_trc(rport->fcs, rport->pwwn);1655 bfa_trc(rport->fcs, rport->pid);1656 bfa_trc(rport->fcs, event);1657 1658 switch (event) {1659 case RPSM_EVENT_FC4_OFFLINE:1660 bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);1661 bfa_fcs_rport_hal_offline(rport);1662 break;1663 1664 case RPSM_EVENT_DELETE:1665 case RPSM_EVENT_PLOGI_RCVD:1666 /* Ignore these events */1667 break;1668 1669 default:1670 bfa_sm_fault(rport->fcs, event);1671 break;1672 }1673}1674 1675/*1676 * RPort needs to be deleted1677 * waiting for BFA/FW to finish current processing1678 */1679static void1680bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,1681 enum rport_event event)1682{1683 bfa_trc(rport->fcs, rport->pwwn);1684 bfa_trc(rport->fcs, rport->pid);1685 bfa_trc(rport->fcs, event);1686 1687 switch (event) {1688 case RPSM_EVENT_HCB_OFFLINE:1689 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);1690 bfa_fcs_rport_free(rport);1691 break;1692 1693 case RPSM_EVENT_DELETE:1694 case RPSM_EVENT_LOGO_IMP:1695 case RPSM_EVENT_PLOGI_RCVD:1696 /* Ignore these events */1697 break;1698 1699 default:1700 bfa_sm_fault(rport->fcs, event);1701 }1702}1703 1704/*1705 * fcs_rport_private FCS RPORT provate functions1706 */1707 1708static void1709bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)1710{1711 struct bfa_fcs_rport_s *rport = rport_cbarg;1712 struct bfa_fcs_lport_s *port = rport->port;1713 struct fchs_s fchs;1714 int len;1715 struct bfa_fcxp_s *fcxp;1716 1717 bfa_trc(rport->fcs, rport->pwwn);1718 1719 fcxp = fcxp_alloced ? fcxp_alloced :1720 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);1721 if (!fcxp) {1722 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,1723 bfa_fcs_rport_send_plogi, rport, BFA_TRUE);1724 return;1725 }1726 rport->fcxp = fcxp;1727 1728 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,1729 bfa_fcs_lport_get_fcid(port), 0,1730 port->port_cfg.pwwn, port->port_cfg.nwwn,1731 bfa_fcport_get_maxfrsize(port->fcs->bfa),1732 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));1733 1734 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,1735 FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,1736 (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);1737 1738 rport->stats.plogis++;1739 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);1740}1741 1742static void1743bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,1744 bfa_status_t req_status, u32 rsp_len,1745 u32 resid_len, struct fchs_s *rsp_fchs)1746{1747 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;1748 struct fc_logi_s *plogi_rsp;1749 struct fc_ls_rjt_s *ls_rjt;1750 struct bfa_fcs_rport_s *twin;1751 struct list_head *qe;1752 1753 bfa_trc(rport->fcs, rport->pwwn);1754 1755 /*1756 * Sanity Checks1757 */1758 if (req_status != BFA_STATUS_OK) {1759 bfa_trc(rport->fcs, req_status);1760 rport->stats.plogi_failed++;1761 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);1762 return;1763 }1764 1765 plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);1766 1767 /*1768 * Check for failure first.1769 */1770 if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {1771 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);1772 1773 bfa_trc(rport->fcs, ls_rjt->reason_code);1774 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);1775 1776 if ((ls_rjt->reason_code == FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD) &&1777 (ls_rjt->reason_code_expl == FC_LS_RJT_EXP_INSUFF_RES)) {1778 rport->stats.rjt_insuff_res++;1779 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RETRY);1780 return;1781 }1782 1783 rport->stats.plogi_rejects++;1784 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);1785 return;1786 }1787 1788 /*1789 * PLOGI is complete. Make sure this device is not one of the known1790 * device with a new FC port address.1791 */1792 list_for_each(qe, &rport->port->rport_q) {1793 twin = (struct bfa_fcs_rport_s *) qe;1794 if (twin == rport)1795 continue;1796 if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {1797 bfa_trc(rport->fcs, twin->pid);1798 bfa_trc(rport->fcs, rport->pid);1799 1800 /* Update plogi stats in twin */1801 twin->stats.plogis += rport->stats.plogis;1802 twin->stats.plogi_rejects +=1803 rport->stats.plogi_rejects;1804 twin->stats.plogi_timeouts +=1805 rport->stats.plogi_timeouts;1806 twin->stats.plogi_failed +=1807 rport->stats.plogi_failed;1808 twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;1809 twin->stats.plogi_accs++;1810 1811 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);1812 1813 bfa_fcs_rport_update(twin, plogi_rsp);1814 twin->pid = rsp_fchs->s_id;1815 bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);1816 return;1817 }1818 }1819 1820 /*1821 * Normal login path -- no evil twins.1822 */1823 rport->stats.plogi_accs++;1824 bfa_fcs_rport_update(rport, plogi_rsp);1825 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);1826}1827 1828static void1829bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)1830{1831 struct bfa_fcs_rport_s *rport = rport_cbarg;1832 struct bfa_fcs_lport_s *port = rport->port;1833 struct fchs_s fchs;1834 int len;1835 struct bfa_fcxp_s *fcxp;1836 1837 bfa_trc(rport->fcs, rport->pwwn);1838 bfa_trc(rport->fcs, rport->reply_oxid);1839 1840 fcxp = fcxp_alloced ? fcxp_alloced :1841 bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);1842 if (!fcxp) {1843 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,1844 bfa_fcs_rport_send_plogiacc, rport, BFA_FALSE);1845 return;1846 }1847 rport->fcxp = fcxp;1848 1849 len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),1850 rport->pid, bfa_fcs_lport_get_fcid(port),1851 rport->reply_oxid, port->port_cfg.pwwn,1852 port->port_cfg.nwwn,1853 bfa_fcport_get_maxfrsize(port->fcs->bfa),1854 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));1855 1856 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,1857 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);1858 1859 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);1860}1861 1862static void1863bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)1864{1865 struct bfa_fcs_rport_s *rport = rport_cbarg;1866 struct bfa_fcs_lport_s *port = rport->port;1867 struct fchs_s fchs;1868 int len;1869 struct bfa_fcxp_s *fcxp;1870 1871 bfa_trc(rport->fcs, rport->pwwn);1872 1873 fcxp = fcxp_alloced ? fcxp_alloced :1874 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);1875 if (!fcxp) {1876 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,1877 bfa_fcs_rport_send_adisc, rport, BFA_TRUE);1878 return;1879 }1880 rport->fcxp = fcxp;1881 1882 len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,1883 bfa_fcs_lport_get_fcid(port), 0,1884 port->port_cfg.pwwn, port->port_cfg.nwwn);1885 1886 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,1887 FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,1888 rport, FC_MAX_PDUSZ, FC_ELS_TOV);1889 1890 rport->stats.adisc_sent++;1891 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);1892}1893 1894static void1895bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,1896 bfa_status_t req_status, u32 rsp_len,1897 u32 resid_len, struct fchs_s *rsp_fchs)1898{1899 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;1900 void *pld = bfa_fcxp_get_rspbuf(fcxp);1901 struct fc_ls_rjt_s *ls_rjt;1902 1903 if (req_status != BFA_STATUS_OK) {1904 bfa_trc(rport->fcs, req_status);1905 rport->stats.adisc_failed++;1906 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);1907 return;1908 }1909 1910 if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,1911 rport->nwwn) == FC_PARSE_OK) {1912 rport->stats.adisc_accs++;1913 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);1914 return;1915 }1916 1917 rport->stats.adisc_rejects++;1918 ls_rjt = pld;1919 bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);1920 bfa_trc(rport->fcs, ls_rjt->reason_code);1921 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);1922 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);1923}1924 1925static void1926bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)1927{1928 struct bfa_fcs_rport_s *rport = rport_cbarg;1929 struct bfa_fcs_lport_s *port = rport->port;1930 struct fchs_s fchs;1931 struct bfa_fcxp_s *fcxp;1932 int len;1933 bfa_cb_fcxp_send_t cbfn;1934 1935 bfa_trc(rport->fcs, rport->pid);1936 1937 fcxp = fcxp_alloced ? fcxp_alloced :1938 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);1939 if (!fcxp) {1940 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,1941 bfa_fcs_rport_send_nsdisc, rport, BFA_TRUE);1942 return;1943 }1944 rport->fcxp = fcxp;1945 1946 if (rport->pwwn) {1947 len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),1948 bfa_fcs_lport_get_fcid(port), 0, rport->pwwn);1949 cbfn = bfa_fcs_rport_gidpn_response;1950 } else {1951 len = fc_gpnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),1952 bfa_fcs_lport_get_fcid(port), 0, rport->pid);1953 cbfn = bfa_fcs_rport_gpnid_response;1954 }1955 1956 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,1957 FC_CLASS_3, len, &fchs, cbfn,1958 (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);1959 1960 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);1961}1962 1963static void1964bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,1965 bfa_status_t req_status, u32 rsp_len,1966 u32 resid_len, struct fchs_s *rsp_fchs)1967{1968 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;1969 struct ct_hdr_s *cthdr;1970 struct fcgs_gidpn_resp_s *gidpn_rsp;1971 struct bfa_fcs_rport_s *twin;1972 struct list_head *qe;1973 1974 bfa_trc(rport->fcs, rport->pwwn);1975 1976 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);1977 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);1978 1979 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {1980 /* Check if the pid is the same as before. */1981 gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);1982 1983 if (gidpn_rsp->dap == rport->pid) {1984 /* Device is online */1985 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);1986 } else {1987 /*1988 * Device's PID has changed. We need to cleanup1989 * and re-login. If there is another device with1990 * the the newly discovered pid, send an scn notice1991 * so that its new pid can be discovered.1992 */1993 list_for_each(qe, &rport->port->rport_q) {1994 twin = (struct bfa_fcs_rport_s *) qe;1995 if (twin == rport)1996 continue;1997 if (gidpn_rsp->dap == twin->pid) {1998 bfa_trc(rport->fcs, twin->pid);1999 bfa_trc(rport->fcs, rport->pid);2000 2001 twin->pid = 0;2002 bfa_sm_send_event(twin,2003 RPSM_EVENT_ADDRESS_CHANGE);2004 }2005 }2006 rport->pid = gidpn_rsp->dap;2007 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);2008 }2009 return;2010 }2011 2012 /*2013 * Reject Response2014 */2015 switch (cthdr->reason_code) {2016 case CT_RSN_LOGICAL_BUSY:2017 /*2018 * Need to retry2019 */2020 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);2021 break;2022 2023 case CT_RSN_UNABLE_TO_PERF:2024 /*2025 * device doesn't exist : Start timer to cleanup this later.2026 */2027 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);2028 break;2029 2030 default:2031 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);2032 break;2033 }2034}2035 2036static void2037bfa_fcs_rport_gpnid_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,2038 bfa_status_t req_status, u32 rsp_len,2039 u32 resid_len, struct fchs_s *rsp_fchs)2040{2041 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2042 struct ct_hdr_s *cthdr;2043 2044 bfa_trc(rport->fcs, rport->pwwn);2045 2046 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);2047 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);2048 2049 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {2050 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);2051 return;2052 }2053 2054 /*2055 * Reject Response2056 */2057 switch (cthdr->reason_code) {2058 case CT_RSN_LOGICAL_BUSY:2059 /*2060 * Need to retry2061 */2062 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);2063 break;2064 2065 case CT_RSN_UNABLE_TO_PERF:2066 /*2067 * device doesn't exist : Start timer to cleanup this later.2068 */2069 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);2070 break;2071 2072 default:2073 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);2074 break;2075 }2076}2077 2078/*2079 * Called to send a logout to the rport.2080 */2081static void2082bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)2083{2084 struct bfa_fcs_rport_s *rport = rport_cbarg;2085 struct bfa_fcs_lport_s *port;2086 struct fchs_s fchs;2087 struct bfa_fcxp_s *fcxp;2088 u16 len;2089 2090 bfa_trc(rport->fcs, rport->pid);2091 2092 port = rport->port;2093 2094 fcxp = fcxp_alloced ? fcxp_alloced :2095 bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2096 if (!fcxp) {2097 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,2098 bfa_fcs_rport_send_logo, rport, BFA_FALSE);2099 return;2100 }2101 rport->fcxp = fcxp;2102 2103 len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,2104 bfa_fcs_lport_get_fcid(port), 0,2105 bfa_fcs_lport_get_pwwn(port));2106 2107 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,2108 FC_CLASS_3, len, &fchs, NULL,2109 rport, FC_MAX_PDUSZ, FC_ELS_TOV);2110 2111 rport->stats.logos++;2112 bfa_fcxp_discard(rport->fcxp);2113 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);2114}2115 2116/*2117 * Send ACC for a LOGO received.2118 */2119static void2120bfa_fcs_rport_send_logo_acc(void *rport_cbarg)2121{2122 struct bfa_fcs_rport_s *rport = rport_cbarg;2123 struct bfa_fcs_lport_s *port;2124 struct fchs_s fchs;2125 struct bfa_fcxp_s *fcxp;2126 u16 len;2127 2128 bfa_trc(rport->fcs, rport->pid);2129 2130 port = rport->port;2131 2132 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2133 if (!fcxp)2134 return;2135 2136 rport->stats.logo_rcvd++;2137 len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2138 rport->pid, bfa_fcs_lport_get_fcid(port),2139 rport->reply_oxid);2140 2141 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,2142 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);2143}2144 2145/*2146 * brief2147 * This routine will be called by bfa_timer on timer timeouts.2148 *2149 * param[in] rport - pointer to bfa_fcs_lport_ns_t.2150 * param[out] rport_status - pointer to return vport status in2151 *2152 * return2153 * void2154 *2155 * Special Considerations:2156 *2157 * note2158 */2159static void2160bfa_fcs_rport_timeout(void *arg)2161{2162 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) arg;2163 2164 rport->stats.plogi_timeouts++;2165 bfa_stats(rport->port, rport_plogi_timeouts);2166 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);2167}2168 2169static void2170bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,2171 struct fchs_s *rx_fchs, u16 len)2172{2173 struct bfa_fcxp_s *fcxp;2174 struct fchs_s fchs;2175 struct bfa_fcs_lport_s *port = rport->port;2176 struct fc_prli_s *prli;2177 2178 bfa_trc(port->fcs, rx_fchs->s_id);2179 bfa_trc(port->fcs, rx_fchs->d_id);2180 2181 rport->stats.prli_rcvd++;2182 2183 /*2184 * We are in Initiator Mode2185 */2186 prli = (struct fc_prli_s *) (rx_fchs + 1);2187 2188 if (prli->parampage.servparams.target) {2189 /*2190 * PRLI from a target ?2191 * Send the Acc.2192 * PRLI sent by us will be used to transition the IT nexus,2193 * once the response is received from the target.2194 */2195 bfa_trc(port->fcs, rx_fchs->s_id);2196 rport->scsi_function = BFA_RPORT_TARGET;2197 } else {2198 bfa_trc(rport->fcs, prli->parampage.type);2199 rport->scsi_function = BFA_RPORT_INITIATOR;2200 bfa_fcs_itnim_is_initiator(rport->itnim);2201 }2202 2203 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2204 if (!fcxp)2205 return;2206 2207 len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2208 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),2209 rx_fchs->ox_id, port->port_cfg.roles);2210 2211 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,2212 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);2213}2214 2215static void2216bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,2217 struct fchs_s *rx_fchs, u16 len)2218{2219 struct bfa_fcxp_s *fcxp;2220 struct fchs_s fchs;2221 struct bfa_fcs_lport_s *port = rport->port;2222 struct fc_rpsc_speed_info_s speeds;2223 struct bfa_port_attr_s pport_attr;2224 2225 bfa_trc(port->fcs, rx_fchs->s_id);2226 bfa_trc(port->fcs, rx_fchs->d_id);2227 2228 rport->stats.rpsc_rcvd++;2229 speeds.port_speed_cap =2230 RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |2231 RPSC_SPEED_CAP_8G;2232 2233 /*2234 * get curent speed from pport attributes from BFA2235 */2236 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);2237 2238 speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);2239 2240 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2241 if (!fcxp)2242 return;2243 2244 len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2245 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),2246 rx_fchs->ox_id, &speeds);2247 2248 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,2249 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);2250}2251 2252static void2253bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,2254 struct fchs_s *rx_fchs, u16 len)2255{2256 struct bfa_fcxp_s *fcxp;2257 struct fchs_s fchs;2258 struct bfa_fcs_lport_s *port = rport->port;2259 2260 bfa_trc(port->fcs, rx_fchs->s_id);2261 bfa_trc(port->fcs, rx_fchs->d_id);2262 2263 rport->stats.adisc_rcvd++;2264 2265 /*2266 * Accept if the itnim for this rport is online.2267 * Else reject the ADISC.2268 */2269 if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {2270 2271 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2272 if (!fcxp)2273 return;2274 2275 len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2276 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),2277 rx_fchs->ox_id, port->port_cfg.pwwn,2278 port->port_cfg.nwwn);2279 2280 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,2281 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,2282 FC_MAX_PDUSZ, 0);2283 } else {2284 rport->stats.adisc_rejected++;2285 bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,2286 FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,2287 FC_LS_RJT_EXP_LOGIN_REQUIRED);2288 }2289}2290 2291static void2292bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)2293{2294 struct bfa_fcs_lport_s *port = rport->port;2295 struct bfa_rport_info_s rport_info;2296 2297 rport_info.pid = rport->pid;2298 rport_info.local_pid = port->pid;2299 rport_info.lp_tag = port->lp_tag;2300 rport_info.vf_id = port->fabric->vf_id;2301 rport_info.vf_en = port->fabric->is_vf;2302 rport_info.fc_class = rport->fc_cos;2303 rport_info.cisc = rport->cisc;2304 rport_info.max_frmsz = rport->maxfrsize;2305 bfa_rport_online(rport->bfa_rport, &rport_info);2306}2307 2308static void2309bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport)2310{2311 if (rport->bfa_rport)2312 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);2313 else2314 bfa_cb_rport_offline(rport);2315}2316 2317static struct bfa_fcs_rport_s *2318bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)2319{2320 struct bfa_fcs_s *fcs = port->fcs;2321 struct bfa_fcs_rport_s *rport;2322 struct bfad_rport_s *rport_drv;2323 2324 /*2325 * allocate rport2326 */2327 if (fcs->num_rport_logins >= bfa_fcs_rport_max_logins) {2328 bfa_trc(fcs, rpid);2329 return NULL;2330 }2331 2332 if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)2333 != BFA_STATUS_OK) {2334 bfa_trc(fcs, rpid);2335 return NULL;2336 }2337 2338 /*2339 * Initialize r-port2340 */2341 rport->port = port;2342 rport->fcs = fcs;2343 rport->rp_drv = rport_drv;2344 rport->pid = rpid;2345 rport->pwwn = pwwn;2346 rport->old_pid = 0;2347 2348 rport->bfa_rport = NULL;2349 2350 /*2351 * allocate FC-4s2352 */2353 WARN_ON(!bfa_fcs_lport_is_initiator(port));2354 2355 if (bfa_fcs_lport_is_initiator(port)) {2356 rport->itnim = bfa_fcs_itnim_create(rport);2357 if (!rport->itnim) {2358 bfa_trc(fcs, rpid);2359 kfree(rport_drv);2360 return NULL;2361 }2362 }2363 2364 bfa_fcs_lport_add_rport(port, rport);2365 fcs->num_rport_logins++;2366 2367 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);2368 2369 /* Initialize the Rport Features(RPF) Sub Module */2370 if (!BFA_FCS_PID_IS_WKA(rport->pid))2371 bfa_fcs_rpf_init(rport);2372 2373 return rport;2374}2375 2376 2377static void2378bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)2379{2380 struct bfa_fcs_lport_s *port = rport->port;2381 struct bfa_fcs_s *fcs = port->fcs;2382 2383 /*2384 * - delete FC-4s2385 * - delete BFA rport2386 * - remove from queue of rports2387 */2388 rport->plogi_pending = BFA_FALSE;2389 2390 if (bfa_fcs_lport_is_initiator(port)) {2391 bfa_fcs_itnim_delete(rport->itnim);2392 if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))2393 bfa_fcs_rpf_rport_offline(rport);2394 }2395 2396 if (rport->bfa_rport) {2397 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);2398 rport->bfa_rport = NULL;2399 }2400 2401 bfa_fcs_lport_del_rport(port, rport);2402 fcs->num_rport_logins--;2403 kfree(rport->rp_drv);2404}2405 2406static void2407bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,2408 enum bfa_rport_aen_event event,2409 struct bfa_rport_aen_data_s *data)2410{2411 struct bfa_fcs_lport_s *port = rport->port;2412 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;2413 struct bfa_aen_entry_s *aen_entry;2414 2415 bfad_get_aen_entry(bfad, aen_entry);2416 if (!aen_entry)2417 return;2418 2419 if (event == BFA_RPORT_AEN_QOS_PRIO)2420 aen_entry->aen_data.rport.priv.qos = data->priv.qos;2421 else if (event == BFA_RPORT_AEN_QOS_FLOWID)2422 aen_entry->aen_data.rport.priv.qos = data->priv.qos;2423 2424 aen_entry->aen_data.rport.vf_id = rport->port->fabric->vf_id;2425 aen_entry->aen_data.rport.ppwwn = bfa_fcs_lport_get_pwwn(2426 bfa_fcs_get_base_port(rport->fcs));2427 aen_entry->aen_data.rport.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);2428 aen_entry->aen_data.rport.rpwwn = rport->pwwn;2429 2430 /* Send the AEN notification */2431 bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,2432 BFA_AEN_CAT_RPORT, event);2433}2434 2435static void2436bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport)2437{2438 if ((!rport->pid) || (!rport->pwwn)) {2439 bfa_trc(rport->fcs, rport->pid);2440 bfa_sm_fault(rport->fcs, rport->pid);2441 }2442 2443 bfa_sm_send_event(rport->itnim, BFA_FCS_ITNIM_SM_FCS_ONLINE);2444}2445 2446static void2447bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport)2448{2449 struct bfa_fcs_lport_s *port = rport->port;2450 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;2451 char lpwwn_buf[BFA_STRING_32];2452 char rpwwn_buf[BFA_STRING_32];2453 2454 rport->stats.onlines++;2455 2456 if ((!rport->pid) || (!rport->pwwn)) {2457 bfa_trc(rport->fcs, rport->pid);2458 bfa_sm_fault(rport->fcs, rport->pid);2459 }2460 2461 if (bfa_fcs_lport_is_initiator(port)) {2462 bfa_fcs_itnim_brp_online(rport->itnim);2463 if (!BFA_FCS_PID_IS_WKA(rport->pid))2464 bfa_fcs_rpf_rport_online(rport);2465 }2466 2467 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));2468 wwn2str(rpwwn_buf, rport->pwwn);2469 if (!BFA_FCS_PID_IS_WKA(rport->pid)) {2470 BFA_LOG(KERN_INFO, bfad, bfa_log_level,2471 "Remote port (WWN = %s) online for logical port (WWN = %s)\n",2472 rpwwn_buf, lpwwn_buf);2473 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);2474 }2475}2476 2477static void2478bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport)2479{2480 if (!BFA_FCS_PID_IS_WKA(rport->pid))2481 bfa_fcs_rpf_rport_offline(rport);2482 2483 bfa_fcs_itnim_rport_offline(rport->itnim);2484}2485 2486static void2487bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport)2488{2489 struct bfa_fcs_lport_s *port = rport->port;2490 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;2491 char lpwwn_buf[BFA_STRING_32];2492 char rpwwn_buf[BFA_STRING_32];2493 2494 if (!rport->bfa_rport) {2495 bfa_fcs_rport_fcs_offline_action(rport);2496 return;2497 }2498 2499 rport->stats.offlines++;2500 2501 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));2502 wwn2str(rpwwn_buf, rport->pwwn);2503 if (!BFA_FCS_PID_IS_WKA(rport->pid)) {2504 if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE) {2505 BFA_LOG(KERN_ERR, bfad, bfa_log_level,2506 "Remote port (WWN = %s) connectivity lost for "2507 "logical port (WWN = %s)\n",2508 rpwwn_buf, lpwwn_buf);2509 bfa_fcs_rport_aen_post(rport,2510 BFA_RPORT_AEN_DISCONNECT, NULL);2511 } else {2512 BFA_LOG(KERN_INFO, bfad, bfa_log_level,2513 "Remote port (WWN = %s) offlined by "2514 "logical port (WWN = %s)\n",2515 rpwwn_buf, lpwwn_buf);2516 bfa_fcs_rport_aen_post(rport,2517 BFA_RPORT_AEN_OFFLINE, NULL);2518 }2519 }2520 2521 if (bfa_fcs_lport_is_initiator(port)) {2522 bfa_fcs_itnim_rport_offline(rport->itnim);2523 if (!BFA_FCS_PID_IS_WKA(rport->pid))2524 bfa_fcs_rpf_rport_offline(rport);2525 }2526}2527 2528/*2529 * Update rport parameters from PLOGI or PLOGI accept.2530 */2531static void2532bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)2533{2534 bfa_fcs_lport_t *port = rport->port;2535 2536 /*2537 * - port name2538 * - node name2539 */2540 rport->pwwn = plogi->port_name;2541 rport->nwwn = plogi->node_name;2542 2543 /*2544 * - class of service2545 */2546 rport->fc_cos = 0;2547 if (plogi->class3.class_valid)2548 rport->fc_cos = FC_CLASS_3;2549 2550 if (plogi->class2.class_valid)2551 rport->fc_cos |= FC_CLASS_2;2552 2553 /*2554 * - CISC2555 * - MAX receive frame size2556 */2557 rport->cisc = plogi->csp.cisc;2558 if (be16_to_cpu(plogi->class3.rxsz) < be16_to_cpu(plogi->csp.rxsz))2559 rport->maxfrsize = be16_to_cpu(plogi->class3.rxsz);2560 else2561 rport->maxfrsize = be16_to_cpu(plogi->csp.rxsz);2562 2563 bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));2564 bfa_trc(port->fcs, port->fabric->bb_credit);2565 /*2566 * Direct Attach P2P mode :2567 * This is to handle a bug (233476) in IBM targets in Direct Attach2568 * Mode. Basically, in FLOGI Accept the target would have2569 * erroneously set the BB Credit to the value used in the FLOGI2570 * sent by the HBA. It uses the correct value (its own BB credit)2571 * in PLOGI.2572 */2573 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&2574 (be16_to_cpu(plogi->csp.bbcred) < port->fabric->bb_credit)) {2575 2576 bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));2577 bfa_trc(port->fcs, port->fabric->bb_credit);2578 2579 port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);2580 bfa_fcport_set_tx_bbcredit(port->fcs->bfa,2581 port->fabric->bb_credit);2582 }2583 2584}2585 2586/*2587 * Called to handle LOGO received from an existing remote port.2588 */2589static void2590bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)2591{2592 rport->reply_oxid = fchs->ox_id;2593 bfa_trc(rport->fcs, rport->reply_oxid);2594 2595 rport->prlo = BFA_FALSE;2596 rport->stats.logo_rcvd++;2597 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);2598}2599 2600 2601 2602/*2603 * fcs_rport_public FCS rport public interfaces2604 */2605 2606/*2607 * Called by bport/vport to create a remote port instance for a discovered2608 * remote device.2609 *2610 * @param[in] port - base port or vport2611 * @param[in] rpid - remote port ID2612 *2613 * @return None2614 */2615struct bfa_fcs_rport_s *2616bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 rpid)2617{2618 struct bfa_fcs_rport_s *rport;2619 2620 bfa_trc(port->fcs, rpid);2621 rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);2622 if (!rport)2623 return NULL;2624 2625 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);2626 return rport;2627}2628 2629/*2630 * Called to create a rport for which only the wwn is known.2631 *2632 * @param[in] port - base port2633 * @param[in] rpwwn - remote port wwn2634 *2635 * @return None2636 */2637struct bfa_fcs_rport_s *2638bfa_fcs_rport_create_by_wwn(struct bfa_fcs_lport_s *port, wwn_t rpwwn)2639{2640 struct bfa_fcs_rport_s *rport;2641 bfa_trc(port->fcs, rpwwn);2642 rport = bfa_fcs_rport_alloc(port, rpwwn, 0);2643 if (!rport)2644 return NULL;2645 2646 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);2647 return rport;2648}2649/*2650 * Called by bport in private loop topology to indicate that a2651 * rport has been discovered and plogi has been completed.2652 *2653 * @param[in] port - base port or vport2654 * @param[in] rpid - remote port ID2655 */2656void2657bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,2658 struct fc_logi_s *plogi)2659{2660 struct bfa_fcs_rport_s *rport;2661 2662 rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);2663 if (!rport)2664 return;2665 2666 bfa_fcs_rport_update(rport, plogi);2667 2668 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);2669}2670 2671/*2672 * Called by bport/vport to handle PLOGI received from a new remote port.2673 * If an existing rport does a plogi, it will be handled separately.2674 */2675void2676bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,2677 struct fc_logi_s *plogi)2678{2679 struct bfa_fcs_rport_s *rport;2680 2681 rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);2682 if (!rport)2683 return;2684 2685 bfa_fcs_rport_update(rport, plogi);2686 2687 rport->reply_oxid = fchs->ox_id;2688 bfa_trc(rport->fcs, rport->reply_oxid);2689 2690 rport->stats.plogi_rcvd++;2691 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);2692}2693 2694/*2695 * Called by bport/vport to handle PLOGI received from an existing2696 * remote port.2697 */2698void2699bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,2700 struct fc_logi_s *plogi)2701{2702 /*2703 * @todo Handle P2P and initiator-initiator.2704 */2705 2706 bfa_fcs_rport_update(rport, plogi);2707 2708 rport->reply_oxid = rx_fchs->ox_id;2709 bfa_trc(rport->fcs, rport->reply_oxid);2710 2711 rport->pid = rx_fchs->s_id;2712 bfa_trc(rport->fcs, rport->pid);2713 2714 rport->stats.plogi_rcvd++;2715 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);2716}2717 2718 2719/*2720 * Called by bport/vport to notify SCN for the remote port2721 */2722void2723bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)2724{2725 rport->stats.rscns++;2726 bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);2727}2728 2729/*2730 * brief2731 * This routine BFA callback for bfa_rport_online() call.2732 *2733 * param[in] cb_arg - rport struct.2734 *2735 * return2736 * void2737 *2738 * Special Considerations:2739 *2740 * note2741 */2742void2743bfa_cb_rport_online(void *cbarg)2744{2745 2746 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2747 2748 bfa_trc(rport->fcs, rport->pwwn);2749 bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);2750}2751 2752/*2753 * brief2754 * This routine BFA callback for bfa_rport_offline() call.2755 *2756 * param[in] rport -2757 *2758 * return2759 * void2760 *2761 * Special Considerations:2762 *2763 * note2764 */2765void2766bfa_cb_rport_offline(void *cbarg)2767{2768 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2769 2770 bfa_trc(rport->fcs, rport->pwwn);2771 bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);2772}2773 2774/*2775 * brief2776 * This routine is a static BFA callback when there is a QoS flow_id2777 * change notification2778 *2779 * param[in] rport -2780 *2781 * return2782 * void2783 *2784 * Special Considerations:2785 *2786 * note2787 */2788void2789bfa_cb_rport_qos_scn_flowid(void *cbarg,2790 struct bfa_rport_qos_attr_s old_qos_attr,2791 struct bfa_rport_qos_attr_s new_qos_attr)2792{2793 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2794 struct bfa_rport_aen_data_s aen_data;2795 2796 bfa_trc(rport->fcs, rport->pwwn);2797 aen_data.priv.qos = new_qos_attr;2798 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);2799}2800 2801void2802bfa_cb_rport_scn_online(struct bfa_s *bfa)2803{2804 struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;2805 struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);2806 struct bfa_fcs_rport_s *rp;2807 struct list_head *qe;2808 2809 list_for_each(qe, &port->rport_q) {2810 rp = (struct bfa_fcs_rport_s *) qe;2811 bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE);2812 rp->scn_online = BFA_TRUE;2813 }2814 2815 if (bfa_fcs_lport_is_online(port))2816 bfa_fcs_lport_lip_scn_online(port);2817}2818 2819void2820bfa_cb_rport_scn_no_dev(void *rport)2821{2822 struct bfa_fcs_rport_s *rp = rport;2823 2824 bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);2825 rp->scn_online = BFA_FALSE;2826}2827 2828void2829bfa_cb_rport_scn_offline(struct bfa_s *bfa)2830{2831 struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;2832 struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);2833 struct bfa_fcs_rport_s *rp;2834 struct list_head *qe;2835 2836 list_for_each(qe, &port->rport_q) {2837 rp = (struct bfa_fcs_rport_s *) qe;2838 bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);2839 rp->scn_online = BFA_FALSE;2840 }2841}2842 2843/*2844 * brief2845 * This routine is a static BFA callback when there is a QoS priority2846 * change notification2847 *2848 * param[in] rport -2849 *2850 * return2851 * void2852 *2853 * Special Considerations:2854 *2855 * note2856 */2857void2858bfa_cb_rport_qos_scn_prio(void *cbarg,2859 struct bfa_rport_qos_attr_s old_qos_attr,2860 struct bfa_rport_qos_attr_s new_qos_attr)2861{2862 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;2863 struct bfa_rport_aen_data_s aen_data;2864 2865 bfa_trc(rport->fcs, rport->pwwn);2866 aen_data.priv.qos = new_qos_attr;2867 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);2868}2869 2870/*2871 * Called to process any unsolicted frames from this remote port2872 */2873void2874bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,2875 struct fchs_s *fchs, u16 len)2876{2877 struct bfa_fcs_lport_s *port = rport->port;2878 struct fc_els_cmd_s *els_cmd;2879 2880 bfa_trc(rport->fcs, fchs->s_id);2881 bfa_trc(rport->fcs, fchs->d_id);2882 bfa_trc(rport->fcs, fchs->type);2883 2884 if (fchs->type != FC_TYPE_ELS)2885 return;2886 2887 els_cmd = (struct fc_els_cmd_s *) (fchs + 1);2888 2889 bfa_trc(rport->fcs, els_cmd->els_code);2890 2891 switch (els_cmd->els_code) {2892 case FC_ELS_LOGO:2893 bfa_stats(port, plogi_rcvd);2894 bfa_fcs_rport_process_logo(rport, fchs);2895 break;2896 2897 case FC_ELS_ADISC:2898 bfa_stats(port, adisc_rcvd);2899 bfa_fcs_rport_process_adisc(rport, fchs, len);2900 break;2901 2902 case FC_ELS_PRLO:2903 bfa_stats(port, prlo_rcvd);2904 if (bfa_fcs_lport_is_initiator(port))2905 bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);2906 break;2907 2908 case FC_ELS_PRLI:2909 bfa_stats(port, prli_rcvd);2910 bfa_fcs_rport_process_prli(rport, fchs, len);2911 break;2912 2913 case FC_ELS_RPSC:2914 bfa_stats(port, rpsc_rcvd);2915 bfa_fcs_rport_process_rpsc(rport, fchs, len);2916 break;2917 2918 default:2919 bfa_stats(port, un_handled_els_rcvd);2920 bfa_fcs_rport_send_ls_rjt(rport, fchs,2921 FC_LS_RJT_RSN_CMD_NOT_SUPP,2922 FC_LS_RJT_EXP_NO_ADDL_INFO);2923 break;2924 }2925}2926 2927/* send best case acc to prlo */2928static void2929bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)2930{2931 struct bfa_fcs_lport_s *port = rport->port;2932 struct fchs_s fchs;2933 struct bfa_fcxp_s *fcxp;2934 int len;2935 2936 bfa_trc(rport->fcs, rport->pid);2937 2938 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);2939 if (!fcxp)2940 return;2941 len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2942 rport->pid, bfa_fcs_lport_get_fcid(port),2943 rport->reply_oxid, 0);2944 2945 bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,2946 port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,2947 NULL, NULL, FC_MAX_PDUSZ, 0);2948}2949 2950/*2951 * Send a LS reject2952 */2953static void2954bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,2955 u8 reason_code, u8 reason_code_expl)2956{2957 struct bfa_fcs_lport_s *port = rport->port;2958 struct fchs_s fchs;2959 struct bfa_fcxp_s *fcxp;2960 int len;2961 2962 bfa_trc(rport->fcs, rx_fchs->s_id);2963 2964 fcxp = bfa_fcs_fcxp_alloc(rport->fcs, BFA_FALSE);2965 if (!fcxp)2966 return;2967 2968 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),2969 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),2970 rx_fchs->ox_id, reason_code, reason_code_expl);2971 2972 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,2973 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,2974 FC_MAX_PDUSZ, 0);2975}2976 2977/*2978 * Return state of rport.2979 */2980int2981bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)2982{2983 return bfa_rport_sm_to_state(rport_sm_table, rport->sm);2984}2985 2986 2987/*2988 * brief2989 * Called by the Driver to set rport delete/ageout timeout2990 *2991 * param[in] rport timeout value in seconds.2992 *2993 * return None2994 */2995void2996bfa_fcs_rport_set_del_timeout(u8 rport_tmo)2997{2998 /* convert to Millisecs */2999 if (rport_tmo > 0)3000 bfa_fcs_rport_del_timeout = rport_tmo * 1000;3001}3002void3003bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)3004{3005 bfa_trc(rport->fcs, rport->pid);3006 3007 rport->prlo = BFA_TRUE;3008 rport->reply_oxid = ox_id;3009 bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);3010}3011 3012/*3013 * Called by BFAD to set the max limit on number of bfa_fcs_rport allocation3014 * which limits number of concurrent logins to remote ports3015 */3016void3017bfa_fcs_rport_set_max_logins(u32 max_logins)3018{3019 if (max_logins > 0)3020 bfa_fcs_rport_max_logins = max_logins;3021}3022 3023void3024bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,3025 struct bfa_rport_attr_s *rport_attr)3026{3027 struct bfa_rport_qos_attr_s qos_attr;3028 struct bfa_fcs_lport_s *port = rport->port;3029 bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;3030 struct bfa_port_attr_s port_attr;3031 3032 bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);3033 3034 memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));3035 memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));3036 3037 rport_attr->pid = rport->pid;3038 rport_attr->pwwn = rport->pwwn;3039 rport_attr->nwwn = rport->nwwn;3040 rport_attr->cos_supported = rport->fc_cos;3041 rport_attr->df_sz = rport->maxfrsize;3042 rport_attr->state = bfa_fcs_rport_get_state(rport);3043 rport_attr->fc_cos = rport->fc_cos;3044 rport_attr->cisc = rport->cisc;3045 rport_attr->scsi_function = rport->scsi_function;3046 rport_attr->curr_speed = rport->rpf.rpsc_speed;3047 rport_attr->assigned_speed = rport->rpf.assigned_speed;3048 3049 if (rport->bfa_rport) {3050 qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;3051 qos_attr.qos_flow_id =3052 cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);3053 }3054 rport_attr->qos_attr = qos_attr;3055 3056 rport_attr->trl_enforced = BFA_FALSE;3057 if (bfa_fcport_is_ratelim(port->fcs->bfa) &&3058 (rport->scsi_function == BFA_RPORT_TARGET)) {3059 if (rport_speed == BFA_PORT_SPEED_UNKNOWN)3060 rport_speed =3061 bfa_fcport_get_ratelim_speed(rport->fcs->bfa);3062 3063 if ((bfa_fcs_lport_get_rport_max_speed(port) !=3064 BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))3065 rport_attr->trl_enforced = BFA_TRUE;3066 }3067}3068 3069/*3070 * Remote port implementation.3071 */3072 3073/*3074 * fcs_rport_api FCS rport API.3075 */3076 3077struct bfa_fcs_rport_s *3078bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)3079{3080 struct bfa_fcs_rport_s *rport;3081 3082 rport = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);3083 if (rport == NULL) {3084 /*3085 * TBD Error handling3086 */3087 }3088 3089 return rport;3090}3091 3092struct bfa_fcs_rport_s *3093bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)3094{3095 struct bfa_fcs_rport_s *rport;3096 3097 rport = bfa_fcs_lport_get_rport_by_nwwn(port, rnwwn);3098 if (rport == NULL) {3099 /*3100 * TBD Error handling3101 */3102 }3103 3104 return rport;3105}3106 3107/*3108 * Remote port features (RPF) implementation.3109 */3110 3111#define BFA_FCS_RPF_RETRIES (3)3112#define BFA_FCS_RPF_RETRY_TIMEOUT (1000) /* 1 sec (In millisecs) */3113 3114static void bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,3115 struct bfa_fcxp_s *fcxp_alloced);3116static void bfa_fcs_rpf_rpsc2_response(void *fcsarg,3117 struct bfa_fcxp_s *fcxp,3118 void *cbarg,3119 bfa_status_t req_status,3120 u32 rsp_len,3121 u32 resid_len,3122 struct fchs_s *rsp_fchs);3123 3124static void bfa_fcs_rpf_timeout(void *arg);3125 3126static void bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,3127 enum rpf_event event);3128static void bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,3129 enum rpf_event event);3130static void bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,3131 enum rpf_event event);3132static void bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,3133 enum rpf_event event);3134static void bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,3135 enum rpf_event event);3136static void bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,3137 enum rpf_event event);3138 3139static void3140bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3141{3142 struct bfa_fcs_rport_s *rport = rpf->rport;3143 struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;3144 3145 bfa_trc(rport->fcs, rport->pwwn);3146 bfa_trc(rport->fcs, rport->pid);3147 bfa_trc(rport->fcs, event);3148 3149 switch (event) {3150 case RPFSM_EVENT_RPORT_ONLINE:3151 /* Send RPSC2 to a Brocade fabric only. */3152 if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&3153 ((rport->port->fabric->lps->brcd_switch) ||3154 (bfa_fcs_fabric_get_switch_oui(fabric) ==3155 BFA_FCS_BRCD_SWITCH_OUI))) {3156 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);3157 rpf->rpsc_retries = 0;3158 bfa_fcs_rpf_send_rpsc2(rpf, NULL);3159 }3160 break;3161 3162 case RPFSM_EVENT_RPORT_OFFLINE:3163 break;3164 3165 default:3166 bfa_sm_fault(rport->fcs, event);3167 }3168}3169 3170static void3171bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3172{3173 struct bfa_fcs_rport_s *rport = rpf->rport;3174 3175 bfa_trc(rport->fcs, event);3176 3177 switch (event) {3178 case RPFSM_EVENT_FCXP_SENT:3179 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);3180 break;3181 3182 case RPFSM_EVENT_RPORT_OFFLINE:3183 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);3184 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);3185 rpf->rpsc_retries = 0;3186 break;3187 3188 default:3189 bfa_sm_fault(rport->fcs, event);3190 }3191}3192 3193static void3194bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3195{3196 struct bfa_fcs_rport_s *rport = rpf->rport;3197 3198 bfa_trc(rport->fcs, rport->pid);3199 bfa_trc(rport->fcs, event);3200 3201 switch (event) {3202 case RPFSM_EVENT_RPSC_COMP:3203 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);3204 /* Update speed info in f/w via BFA */3205 if (rpf->rpsc_speed != BFA_PORT_SPEED_UNKNOWN)3206 bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);3207 else if (rpf->assigned_speed != BFA_PORT_SPEED_UNKNOWN)3208 bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);3209 break;3210 3211 case RPFSM_EVENT_RPSC_FAIL:3212 /* RPSC not supported by rport */3213 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);3214 break;3215 3216 case RPFSM_EVENT_RPSC_ERROR:3217 /* need to retry...delayed a bit. */3218 if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {3219 bfa_timer_start(rport->fcs->bfa, &rpf->timer,3220 bfa_fcs_rpf_timeout, rpf,3221 BFA_FCS_RPF_RETRY_TIMEOUT);3222 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);3223 } else {3224 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);3225 }3226 break;3227 3228 case RPFSM_EVENT_RPORT_OFFLINE:3229 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);3230 bfa_fcxp_discard(rpf->fcxp);3231 rpf->rpsc_retries = 0;3232 break;3233 3234 default:3235 bfa_sm_fault(rport->fcs, event);3236 }3237}3238 3239static void3240bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3241{3242 struct bfa_fcs_rport_s *rport = rpf->rport;3243 3244 bfa_trc(rport->fcs, rport->pid);3245 bfa_trc(rport->fcs, event);3246 3247 switch (event) {3248 case RPFSM_EVENT_TIMEOUT:3249 /* re-send the RPSC */3250 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);3251 bfa_fcs_rpf_send_rpsc2(rpf, NULL);3252 break;3253 3254 case RPFSM_EVENT_RPORT_OFFLINE:3255 bfa_timer_stop(&rpf->timer);3256 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);3257 rpf->rpsc_retries = 0;3258 break;3259 3260 default:3261 bfa_sm_fault(rport->fcs, event);3262 }3263}3264 3265static void3266bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3267{3268 struct bfa_fcs_rport_s *rport = rpf->rport;3269 3270 bfa_trc(rport->fcs, rport->pwwn);3271 bfa_trc(rport->fcs, rport->pid);3272 bfa_trc(rport->fcs, event);3273 3274 switch (event) {3275 case RPFSM_EVENT_RPORT_OFFLINE:3276 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);3277 rpf->rpsc_retries = 0;3278 break;3279 3280 default:3281 bfa_sm_fault(rport->fcs, event);3282 }3283}3284 3285static void3286bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)3287{3288 struct bfa_fcs_rport_s *rport = rpf->rport;3289 3290 bfa_trc(rport->fcs, rport->pwwn);3291 bfa_trc(rport->fcs, rport->pid);3292 bfa_trc(rport->fcs, event);3293 3294 switch (event) {3295 case RPFSM_EVENT_RPORT_ONLINE:3296 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);3297 bfa_fcs_rpf_send_rpsc2(rpf, NULL);3298 break;3299 3300 case RPFSM_EVENT_RPORT_OFFLINE:3301 break;3302 3303 default:3304 bfa_sm_fault(rport->fcs, event);3305 }3306}3307/*3308 * Called when Rport is created.3309 */3310void3311bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)3312{3313 struct bfa_fcs_rpf_s *rpf = &rport->rpf;3314 3315 bfa_trc(rport->fcs, rport->pid);3316 rpf->rport = rport;3317 3318 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);3319}3320 3321/*3322 * Called when Rport becomes online3323 */3324void3325bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)3326{3327 bfa_trc(rport->fcs, rport->pid);3328 3329 if (__fcs_min_cfg(rport->port->fcs))3330 return;3331 3332 if (bfa_fcs_fabric_is_switched(rport->port->fabric))3333 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);3334}3335 3336/*3337 * Called when Rport becomes offline3338 */3339void3340bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)3341{3342 bfa_trc(rport->fcs, rport->pid);3343 3344 if (__fcs_min_cfg(rport->port->fcs))3345 return;3346 3347 rport->rpf.rpsc_speed = 0;3348 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);3349}3350 3351static void3352bfa_fcs_rpf_timeout(void *arg)3353{3354 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;3355 struct bfa_fcs_rport_s *rport = rpf->rport;3356 3357 bfa_trc(rport->fcs, rport->pid);3358 bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);3359}3360 3361static void3362bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)3363{3364 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;3365 struct bfa_fcs_rport_s *rport = rpf->rport;3366 struct bfa_fcs_lport_s *port = rport->port;3367 struct fchs_s fchs;3368 int len;3369 struct bfa_fcxp_s *fcxp;3370 3371 bfa_trc(rport->fcs, rport->pwwn);3372 3373 fcxp = fcxp_alloced ? fcxp_alloced :3374 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);3375 if (!fcxp) {3376 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,3377 bfa_fcs_rpf_send_rpsc2, rpf, BFA_TRUE);3378 return;3379 }3380 rpf->fcxp = fcxp;3381 3382 len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,3383 bfa_fcs_lport_get_fcid(port), &rport->pid, 1);3384 3385 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,3386 FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,3387 rpf, FC_MAX_PDUSZ, FC_ELS_TOV);3388 rport->stats.rpsc_sent++;3389 bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);3390 3391}3392 3393static void3394bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,3395 bfa_status_t req_status, u32 rsp_len,3396 u32 resid_len, struct fchs_s *rsp_fchs)3397{3398 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;3399 struct bfa_fcs_rport_s *rport = rpf->rport;3400 struct fc_ls_rjt_s *ls_rjt;3401 struct fc_rpsc2_acc_s *rpsc2_acc;3402 u16 num_ents;3403 3404 bfa_trc(rport->fcs, req_status);3405 3406 if (req_status != BFA_STATUS_OK) {3407 bfa_trc(rport->fcs, req_status);3408 if (req_status == BFA_STATUS_ETIMER)3409 rport->stats.rpsc_failed++;3410 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);3411 return;3412 }3413 3414 rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);3415 if (rpsc2_acc->els_cmd == FC_ELS_ACC) {3416 rport->stats.rpsc_accs++;3417 num_ents = be16_to_cpu(rpsc2_acc->num_pids);3418 bfa_trc(rport->fcs, num_ents);3419 if (num_ents > 0) {3420 WARN_ON(be32_to_cpu(rpsc2_acc->port_info[0].pid) !=3421 bfa_ntoh3b(rport->pid));3422 bfa_trc(rport->fcs,3423 be32_to_cpu(rpsc2_acc->port_info[0].pid));3424 bfa_trc(rport->fcs,3425 be16_to_cpu(rpsc2_acc->port_info[0].speed));3426 bfa_trc(rport->fcs,3427 be16_to_cpu(rpsc2_acc->port_info[0].index));3428 bfa_trc(rport->fcs,3429 rpsc2_acc->port_info[0].type);3430 3431 if (rpsc2_acc->port_info[0].speed == 0) {3432 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);3433 return;3434 }3435 3436 rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(3437 be16_to_cpu(rpsc2_acc->port_info[0].speed));3438 3439 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);3440 }3441 } else {3442 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);3443 bfa_trc(rport->fcs, ls_rjt->reason_code);3444 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);3445 rport->stats.rpsc_rejects++;3446 if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)3447 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);3448 else3449 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);3450 }3451}3452