1/* 2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. 3 * All rights reserved 4 * www.brocade.com 5 * 6 * Linux driver for Brocade Fibre Channel Host Bus Adapter. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License (GPL) Version 2 as 10 * published by the Free Software Foundation 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 */ 17 18/** 19 * rport.c Remote port implementation. 20 */ 21 22#include <linux/slab.h> 23#include <bfa.h> 24#include <bfa_svc.h> 25#include "fcbuild.h" 26#include "fcs_vport.h" 27#include "fcs_lport.h" 28#include "fcs_rport.h" 29#include "fcs_fcpim.h" 30#include "fcs_fcptm.h" 31#include "fcs_trcmod.h" 32#include "fcs_fcxp.h" 33#include "fcs.h" 34#include <fcb/bfa_fcb_rport.h> 35#include <aen/bfa_aen_rport.h> 36 37BFA_TRC_FILE(FCS, RPORT); 38 39/* In millisecs */ 40static u32 bfa_fcs_rport_del_timeout = 41 BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000; 42 43/* 44 * forward declarations 45 */ 46static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, 47 wwn_t pwwn, u32 rpid); 48static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport); 49static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport); 50static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport); 51static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport); 52static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, 53 struct fc_logi_s *plogi); 54static void bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport); 55static void bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport); 56static void bfa_fcs_rport_timeout(void *arg); 57static void bfa_fcs_rport_send_plogi(void *rport_cbarg, 58 struct bfa_fcxp_s *fcxp_alloced); 59static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg, 60 struct bfa_fcxp_s *fcxp_alloced); 61static void bfa_fcs_rport_plogi_response(void *fcsarg, 62 struct bfa_fcxp_s *fcxp, 63 void *cbarg, 64 bfa_status_t req_status, 65 u32 rsp_len, 66 u32 resid_len, 67 struct fchs_s *rsp_fchs); 68static void bfa_fcs_rport_send_adisc(void *rport_cbarg, 69 struct bfa_fcxp_s *fcxp_alloced); 70static void bfa_fcs_rport_adisc_response(void *fcsarg, 71 struct bfa_fcxp_s *fcxp, 72 void *cbarg, 73 bfa_status_t req_status, 74 u32 rsp_len, 75 u32 resid_len, 76 struct fchs_s *rsp_fchs); 77static void bfa_fcs_rport_send_gidpn(void *rport_cbarg, 78 struct bfa_fcxp_s *fcxp_alloced); 79static void bfa_fcs_rport_gidpn_response(void *fcsarg, 80 struct bfa_fcxp_s *fcxp, 81 void *cbarg, 82 bfa_status_t req_status, 83 u32 rsp_len, 84 u32 resid_len, 85 struct fchs_s *rsp_fchs); 86static void bfa_fcs_rport_send_logo(void *rport_cbarg, 87 struct bfa_fcxp_s *fcxp_alloced); 88static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg); 89static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport, 90 struct fchs_s *rx_fchs, u16 len); 91static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, 92 struct fchs_s *rx_fchs, u8 reason_code, 93 u8 reason_code_expl); 94static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport, 95 struct fchs_s *rx_fchs, u16 len); 96static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport); 97/** 98 * fcs_rport_sm FCS rport state machine events 99 */ 100 101enum rport_event { 102 RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */ 103 RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */ 104 RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */ 105 RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */ 106 RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */ 107 RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */ 108 RPSM_EVENT_DELETE = 7, /* RPORT delete request */ 109 RPSM_EVENT_SCN = 8, /* state change notification */ 110 RPSM_EVENT_ACCEPTED = 9,/* Good response from remote device */ 111 RPSM_EVENT_FAILED = 10, /* Request to rport failed. */ 112 RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */ 113 RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */ 114 RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */ 115 RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */ 116 RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */ 117 RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */ 118 RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */ 119}; 120 121static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, 122 enum rport_event event); 123static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport, 124 enum rport_event event); 125static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport, 126 enum rport_event event); 127static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport, 128 enum rport_event event); 129static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, 130 enum rport_event event); 131static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, 132 enum rport_event event); 133static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, 134 enum rport_event event); 135static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport, 136 enum rport_event event); 137static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, 138 enum rport_event event); 139static void bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport, 140 enum rport_event event); 141static void bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, 142 enum rport_event event); 143static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport, 144 enum rport_event event); 145static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport, 146 enum rport_event event); 147static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport, 148 enum rport_event event); 149static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, 150 enum rport_event event); 151static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, 152 enum rport_event event); 153static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport, 154 enum rport_event event); 155static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport, 156 enum rport_event event); 157static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, 158 enum rport_event event); 159static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport, 160 enum rport_event event); 161static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport, 162 enum rport_event event); 163static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, 164 enum rport_event event); 165static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, 166 enum rport_event event); 167 168static struct bfa_sm_table_s rport_sm_table[] = { 169 {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT}, 170 {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI}, 171 {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE}, 172 {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY}, 173 {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI}, 174 {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE}, 175 {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE}, 176 {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY}, 177 {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY}, 178 {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC}, 179 {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC}, 180 {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV}, 181 {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO}, 182 {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE}, 183 {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE}, 184 {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV}, 185 {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO}, 186 {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO}, 187 {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE}, 188 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC}, 189 {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC}, 190 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC}, 191}; 192 193/** 194 * Beginning state. 195 */ 196static void 197bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event) 198{ 199 bfa_trc(rport->fcs, rport->pwwn); 200 bfa_trc(rport->fcs, rport->pid); 201 bfa_trc(rport->fcs, event); 202 203 switch (event) { 204 case RPSM_EVENT_PLOGI_SEND: 205 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); 206 rport->plogi_retries = 0; 207 bfa_fcs_rport_send_plogi(rport, NULL); 208 break; 209 210 case RPSM_EVENT_PLOGI_RCVD: 211 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 212 bfa_fcs_rport_send_plogiacc(rport, NULL); 213 break; 214 215 case RPSM_EVENT_PLOGI_COMP: 216 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 217 bfa_fcs_rport_hal_online(rport); 218 break; 219 220 case RPSM_EVENT_ADDRESS_CHANGE: 221 case RPSM_EVENT_ADDRESS_DISC: 222 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); 223 rport->ns_retries = 0; 224 bfa_fcs_rport_send_gidpn(rport, NULL); 225 break; 226 227 default: 228 bfa_sm_fault(rport->fcs, event); 229 } 230} 231 232/** 233 * PLOGI is being sent. 234 */ 235static void 236bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport, 237 enum rport_event event) 238{ 239 bfa_trc(rport->fcs, rport->pwwn); 240 bfa_trc(rport->fcs, rport->pid); 241 bfa_trc(rport->fcs, event); 242 243 switch (event) { 244 case RPSM_EVENT_FCXP_SENT: 245 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi); 246 break; 247 248 case RPSM_EVENT_DELETE: 249 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 250 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 251 bfa_fcs_rport_free(rport); 252 break; 253 254 case RPSM_EVENT_PLOGI_RCVD: 255 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 256 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 257 bfa_fcs_rport_send_plogiacc(rport, NULL); 258 break; 259 260 case RPSM_EVENT_ADDRESS_CHANGE: 261 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 262 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); 263 rport->ns_retries = 0; 264 bfa_fcs_rport_send_gidpn(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 case RPSM_EVENT_SCN: 277 break; 278 279 default: 280 bfa_sm_fault(rport->fcs, event); 281 } 282} 283 284/** 285 * PLOGI is being sent. 286 */ 287static void 288bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport, 289 enum rport_event event) 290{ 291 bfa_trc(rport->fcs, rport->pwwn); 292 bfa_trc(rport->fcs, rport->pid); 293 bfa_trc(rport->fcs, event); 294 295 switch (event) { 296 case RPSM_EVENT_FCXP_SENT: 297 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 298 bfa_fcs_rport_hal_online(rport); 299 break; 300 301 case RPSM_EVENT_DELETE: 302 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 303 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 304 bfa_fcs_rport_free(rport); 305 break; 306 307 case RPSM_EVENT_SCN: 308 /** 309 * Ignore, SCN is possibly online notification. 310 */ 311 break; 312 313 case RPSM_EVENT_ADDRESS_CHANGE: 314 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 315 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); 316 rport->ns_retries = 0; 317 bfa_fcs_rport_send_gidpn(rport, NULL); 318 break; 319 320 case RPSM_EVENT_LOGO_IMP: 321 rport->pid = 0; 322 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 323 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 324 bfa_timer_start(rport->fcs->bfa, &rport->timer, 325 bfa_fcs_rport_timeout, rport, 326 bfa_fcs_rport_del_timeout); 327 break; 328 329 case RPSM_EVENT_HCB_OFFLINE: 330 /** 331 * Ignore BFA callback, on a PLOGI receive we call bfa offline. 332 */ 333 break; 334 335 default: 336 bfa_sm_fault(rport->fcs, event); 337 } 338} 339 340/** 341 * PLOGI is sent. 342 */ 343static void 344bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport, 345 enum rport_event event) 346{ 347 bfa_trc(rport->fcs, rport->pwwn); 348 bfa_trc(rport->fcs, rport->pid); 349 bfa_trc(rport->fcs, event); 350 351 switch (event) { 352 case RPSM_EVENT_SCN: 353 bfa_timer_stop(&rport->timer); 354 /* 355 * !! fall through !! 356 */ 357 358 case RPSM_EVENT_TIMEOUT: 359 if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) { 360 rport->plogi_retries++; 361 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); 362 bfa_fcs_rport_send_plogi(rport, NULL); 363 } else { 364 rport->pid = 0; 365 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 366 bfa_timer_start(rport->fcs->bfa, &rport->timer, 367 bfa_fcs_rport_timeout, rport, 368 bfa_fcs_rport_del_timeout); 369 } 370 break; 371 372 case RPSM_EVENT_DELETE: 373 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 374 bfa_timer_stop(&rport->timer); 375 bfa_fcs_rport_free(rport); 376 break; 377 378 case RPSM_EVENT_PRLO_RCVD: 379 case RPSM_EVENT_LOGO_RCVD: 380 break; 381 382 case RPSM_EVENT_PLOGI_RCVD: 383 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 384 bfa_timer_stop(&rport->timer); 385 bfa_fcs_rport_send_plogiacc(rport, NULL); 386 break; 387 388 case RPSM_EVENT_ADDRESS_CHANGE: 389 bfa_timer_stop(&rport->timer); 390 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); 391 rport->ns_retries = 0; 392 bfa_fcs_rport_send_gidpn(rport, NULL); 393 break; 394 395 case RPSM_EVENT_LOGO_IMP: 396 rport->pid = 0; 397 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 398 bfa_timer_stop(&rport->timer); 399 bfa_timer_start(rport->fcs->bfa, &rport->timer, 400 bfa_fcs_rport_timeout, rport, 401 bfa_fcs_rport_del_timeout); 402 break; 403 404 case RPSM_EVENT_PLOGI_COMP: 405 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 406 bfa_timer_stop(&rport->timer); 407 bfa_fcs_rport_hal_online(rport); 408 break; 409 410 default: 411 bfa_sm_fault(rport->fcs, event); 412 } 413} 414 415/** 416 * PLOGI is sent. 417 */ 418static void 419bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event) 420{ 421 bfa_trc(rport->fcs, rport->pwwn); 422 bfa_trc(rport->fcs, rport->pid); 423 bfa_trc(rport->fcs, event); 424 425 switch (event) { 426 case RPSM_EVENT_ACCEPTED: 427 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 428 rport->plogi_retries = 0; 429 bfa_fcs_rport_hal_online(rport); 430 break; 431 432 case RPSM_EVENT_LOGO_RCVD: 433 bfa_fcs_rport_send_logo_acc(rport); 434 /* 435 * !! fall through !! 436 */ 437 case RPSM_EVENT_PRLO_RCVD: 438 if (rport->prlo == BFA_TRUE) 439 bfa_fcs_rport_send_prlo_acc(rport); 440 441 bfa_fcxp_discard(rport->fcxp); 442 /* 443 * !! fall through !! 444 */ 445 case RPSM_EVENT_FAILED: 446 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry); 447 bfa_timer_start(rport->fcs->bfa, &rport->timer, 448 bfa_fcs_rport_timeout, rport, 449 BFA_FCS_RETRY_TIMEOUT); 450 break; 451 452 case RPSM_EVENT_LOGO_IMP: 453 rport->pid = 0; 454 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 455 bfa_fcxp_discard(rport->fcxp); 456 bfa_timer_start(rport->fcs->bfa, &rport->timer, 457 bfa_fcs_rport_timeout, rport, 458 bfa_fcs_rport_del_timeout); 459 break; 460 461 case RPSM_EVENT_ADDRESS_CHANGE: 462 bfa_fcxp_discard(rport->fcxp); 463 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); 464 rport->ns_retries = 0; 465 bfa_fcs_rport_send_gidpn(rport, NULL); 466 break; 467 468 case RPSM_EVENT_PLOGI_RCVD: 469 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 470 bfa_fcxp_discard(rport->fcxp); 471 bfa_fcs_rport_send_plogiacc(rport, NULL); 472 break; 473 474 case RPSM_EVENT_SCN: 475 /** 476 * Ignore SCN - wait for PLOGI response. 477 */ 478 break; 479 480 case RPSM_EVENT_DELETE: 481 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 482 bfa_fcxp_discard(rport->fcxp); 483 bfa_fcs_rport_free(rport); 484 break; 485 486 case RPSM_EVENT_PLOGI_COMP: 487 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 488 bfa_fcxp_discard(rport->fcxp); 489 bfa_fcs_rport_hal_online(rport); 490 break; 491 492 default: 493 bfa_sm_fault(rport->fcs, event); 494 } 495} 496 497/** 498 * PLOGI is complete. Awaiting BFA rport online callback. FC-4s 499 * are offline. 500 */ 501static void 502bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, 503 enum rport_event event) 504{ 505 bfa_trc(rport->fcs, rport->pwwn); 506 bfa_trc(rport->fcs, rport->pid); 507 bfa_trc(rport->fcs, event); 508 509 switch (event) { 510 case RPSM_EVENT_HCB_ONLINE: 511 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online); 512 bfa_fcs_rport_online_action(rport); 513 break; 514 515 case RPSM_EVENT_PRLO_RCVD: 516 break; 517 518 case RPSM_EVENT_LOGO_RCVD: 519 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); 520 bfa_rport_offline(rport->bfa_rport); 521 break; 522 523 case RPSM_EVENT_LOGO_IMP: 524 case RPSM_EVENT_ADDRESS_CHANGE: 525 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); 526 bfa_rport_offline(rport->bfa_rport); 527 break; 528 529 case RPSM_EVENT_PLOGI_RCVD: 530 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 531 bfa_rport_offline(rport->bfa_rport); 532 bfa_fcs_rport_send_plogiacc(rport, NULL); 533 break; 534 535 case RPSM_EVENT_DELETE: 536 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); 537 bfa_rport_offline(rport->bfa_rport); 538 break; 539 540 case RPSM_EVENT_SCN: 541 /** 542 * @todo 543 * Ignore SCN - PLOGI just completed, FC-4 login should detect 544 * device failures. 545 */ 546 break; 547 548 default: 549 bfa_sm_fault(rport->fcs, event); 550 } 551} 552 553/** 554 * Rport is ONLINE. FC-4s active. 555 */ 556static void 557bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event) 558{ 559 bfa_trc(rport->fcs, rport->pwwn); 560 bfa_trc(rport->fcs, rport->pid); 561 bfa_trc(rport->fcs, event); 562 563 switch (event) { 564 case RPSM_EVENT_SCN: 565 /** 566 * Pause FC-4 activity till rport is authenticated. 567 * In switched fabrics, check presence of device in nameserver 568 * first. 569 */ 570 bfa_fcs_rport_fc4_pause(rport); 571 572 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { 573 bfa_sm_set_state(rport, 574 bfa_fcs_rport_sm_nsquery_sending); 575 rport->ns_retries = 0; 576 bfa_fcs_rport_send_gidpn(rport, NULL); 577 } else { 578 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending); 579 bfa_fcs_rport_send_adisc(rport, NULL); 580 } 581 break; 582 583 case RPSM_EVENT_PLOGI_RCVD: 584 case RPSM_EVENT_LOGO_IMP: 585 case RPSM_EVENT_ADDRESS_CHANGE: 586 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 587 bfa_fcs_rport_offline_action(rport); 588 break; 589 590 case RPSM_EVENT_DELETE: 591 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 592 bfa_fcs_rport_offline_action(rport); 593 break; 594 595 case RPSM_EVENT_LOGO_RCVD: 596 case RPSM_EVENT_PRLO_RCVD: 597 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 598 bfa_fcs_rport_offline_action(rport); 599 break; 600 601 case RPSM_EVENT_PLOGI_COMP: 602 break; 603 604 default: 605 bfa_sm_fault(rport->fcs, event); 606 } 607} 608 609/** 610 * An SCN event is received in ONLINE state. NS query is being sent 611 * prior to ADISC authentication with rport. FC-4s are paused. 612 */ 613static void 614bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport, 615 enum rport_event event) 616{ 617 bfa_trc(rport->fcs, rport->pwwn); 618 bfa_trc(rport->fcs, rport->pid); 619 bfa_trc(rport->fcs, event); 620 621 switch (event) { 622 case RPSM_EVENT_FCXP_SENT: 623 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery); 624 break; 625 626 case RPSM_EVENT_DELETE: 627 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 628 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 629 bfa_fcs_rport_offline_action(rport); 630 break; 631 632 case RPSM_EVENT_SCN: 633 /** 634 * ignore SCN, wait for response to query itself 635 */ 636 break; 637 638 case RPSM_EVENT_LOGO_RCVD: 639 case RPSM_EVENT_PRLO_RCVD: 640 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 641 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 642 bfa_fcs_rport_offline_action(rport); 643 break; 644 645 case RPSM_EVENT_LOGO_IMP: 646 rport->pid = 0; 647 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 648 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 649 bfa_timer_start(rport->fcs->bfa, &rport->timer, 650 bfa_fcs_rport_timeout, rport, 651 bfa_fcs_rport_del_timeout); 652 break; 653 654 case RPSM_EVENT_PLOGI_RCVD: 655 case RPSM_EVENT_ADDRESS_CHANGE: 656 case RPSM_EVENT_PLOGI_COMP: 657 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 658 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 659 bfa_fcs_rport_offline_action(rport); 660 break; 661 662 default: 663 bfa_sm_fault(rport->fcs, event); 664 } 665} 666 667/** 668 * An SCN event is received in ONLINE state. NS query is sent to rport. 669 * FC-4s are paused. 670 */ 671static void 672bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event) 673{ 674 bfa_trc(rport->fcs, rport->pwwn); 675 bfa_trc(rport->fcs, rport->pid); 676 bfa_trc(rport->fcs, event); 677 678 switch (event) { 679 case RPSM_EVENT_ACCEPTED: 680 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending); 681 bfa_fcs_rport_send_adisc(rport, NULL); 682 break; 683 684 case RPSM_EVENT_FAILED: 685 rport->ns_retries++; 686 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) { 687 bfa_sm_set_state(rport, 688 bfa_fcs_rport_sm_nsquery_sending); 689 bfa_fcs_rport_send_gidpn(rport, NULL); 690 } else { 691 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 692 bfa_fcs_rport_offline_action(rport); 693 } 694 break; 695 696 case RPSM_EVENT_DELETE: 697 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 698 bfa_fcxp_discard(rport->fcxp); 699 bfa_fcs_rport_offline_action(rport); 700 break; 701 702 case RPSM_EVENT_SCN: 703 break; 704 705 case RPSM_EVENT_LOGO_RCVD: 706 case RPSM_EVENT_PRLO_RCVD: 707 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 708 bfa_fcxp_discard(rport->fcxp); 709 bfa_fcs_rport_offline_action(rport); 710 break; 711 712 case RPSM_EVENT_PLOGI_COMP: 713 case RPSM_EVENT_ADDRESS_CHANGE: 714 case RPSM_EVENT_PLOGI_RCVD: 715 case RPSM_EVENT_LOGO_IMP: 716 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 717 bfa_fcxp_discard(rport->fcxp); 718 bfa_fcs_rport_offline_action(rport); 719 break; 720 721 default: 722 bfa_sm_fault(rport->fcs, event); 723 } 724} 725 726/** 727 * An SCN event is received in ONLINE state. ADISC is being sent for 728 * authenticating with rport. FC-4s are paused. 729 */ 730static void 731bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport, 732 enum rport_event event) 733{ 734 bfa_trc(rport->fcs, rport->pwwn); 735 bfa_trc(rport->fcs, rport->pid); 736 bfa_trc(rport->fcs, event); 737 738 switch (event) { 739 case RPSM_EVENT_FCXP_SENT: 740 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc); 741 break; 742 743 case RPSM_EVENT_DELETE: 744 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 745 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 746 bfa_fcs_rport_offline_action(rport); 747 break; 748 749 case RPSM_EVENT_LOGO_IMP: 750 case RPSM_EVENT_ADDRESS_CHANGE: 751 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 752 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 753 bfa_fcs_rport_offline_action(rport); 754 break; 755 756 case RPSM_EVENT_LOGO_RCVD: 757 case RPSM_EVENT_PRLO_RCVD: 758 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 759 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 760 bfa_fcs_rport_offline_action(rport); 761 break; 762 763 case RPSM_EVENT_SCN: 764 break; 765 766 case RPSM_EVENT_PLOGI_RCVD: 767 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 768 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 769 bfa_fcs_rport_offline_action(rport); 770 break; 771 772 default: 773 bfa_sm_fault(rport->fcs, event); 774 } 775} 776 777/** 778 * An SCN event is received in ONLINE state. ADISC is to rport. 779 * FC-4s are paused. 780 */ 781static void 782bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event) 783{ 784 bfa_trc(rport->fcs, rport->pwwn); 785 bfa_trc(rport->fcs, rport->pid); 786 bfa_trc(rport->fcs, event); 787 788 switch (event) { 789 case RPSM_EVENT_ACCEPTED: 790 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online); 791 bfa_fcs_rport_fc4_resume(rport); 792 break; 793 794 case RPSM_EVENT_PLOGI_RCVD: 795 /** 796 * Too complex to cleanup FC-4 & rport and then acc to PLOGI. 797 * At least go offline when a PLOGI is received. 798 */ 799 bfa_fcxp_discard(rport->fcxp); 800 /* 801 * !!! fall through !!! 802 */ 803 804 case RPSM_EVENT_FAILED: 805 case RPSM_EVENT_ADDRESS_CHANGE: 806 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 807 bfa_fcs_rport_offline_action(rport); 808 break; 809 810 case RPSM_EVENT_DELETE: 811 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 812 bfa_fcxp_discard(rport->fcxp); 813 bfa_fcs_rport_offline_action(rport); 814 break; 815 816 case RPSM_EVENT_SCN: 817 /** 818 * already processing RSCN 819 */ 820 break; 821 822 case RPSM_EVENT_LOGO_IMP: 823 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); 824 bfa_fcxp_discard(rport->fcxp); 825 bfa_fcs_rport_offline_action(rport); 826 break; 827 828 case RPSM_EVENT_LOGO_RCVD: 829 case RPSM_EVENT_PRLO_RCVD: 830 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); 831 bfa_fcxp_discard(rport->fcxp); 832 bfa_fcs_rport_offline_action(rport); 833 break; 834 835 default: 836 bfa_sm_fault(rport->fcs, event); 837 } 838} 839 840/** 841 * Rport has sent LOGO. Awaiting FC-4 offline completion callback. 842 */ 843static void 844bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport, 845 enum rport_event event) 846{ 847 bfa_trc(rport->fcs, rport->pwwn); 848 bfa_trc(rport->fcs, rport->pid); 849 bfa_trc(rport->fcs, event); 850 851 switch (event) { 852 case RPSM_EVENT_FC4_OFFLINE: 853 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); 854 bfa_rport_offline(rport->bfa_rport); 855 break; 856 857 case RPSM_EVENT_DELETE: 858 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 859 break; 860 861 case RPSM_EVENT_LOGO_RCVD: 862 case RPSM_EVENT_PRLO_RCVD: 863 case RPSM_EVENT_ADDRESS_CHANGE: 864 break; 865 866 default: 867 bfa_sm_fault(rport->fcs, event); 868 } 869} 870 871/** 872 * LOGO needs to be sent to rport. Awaiting FC-4 offline completion 873 * callback. 874 */ 875static void 876bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport, 877 enum rport_event event) 878{ 879 bfa_trc(rport->fcs, rport->pwwn); 880 bfa_trc(rport->fcs, rport->pid); 881 bfa_trc(rport->fcs, event); 882 883 switch (event) { 884 case RPSM_EVENT_FC4_OFFLINE: 885 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); 886 bfa_rport_offline(rport->bfa_rport); 887 break; 888 889 default: 890 bfa_sm_fault(rport->fcs, event); 891 } 892} 893 894/** 895 * Rport is going offline. Awaiting FC-4 offline completion callback. 896 */ 897static void 898bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport, 899 enum rport_event event) 900{ 901 bfa_trc(rport->fcs, rport->pwwn); 902 bfa_trc(rport->fcs, rport->pid); 903 bfa_trc(rport->fcs, event); 904 905 switch (event) { 906 case RPSM_EVENT_FC4_OFFLINE: 907 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); 908 bfa_rport_offline(rport->bfa_rport); 909 break; 910 911 case RPSM_EVENT_SCN: 912 case RPSM_EVENT_LOGO_IMP: 913 case RPSM_EVENT_LOGO_RCVD: 914 case RPSM_EVENT_PRLO_RCVD: 915 case RPSM_EVENT_ADDRESS_CHANGE: 916 /** 917 * rport is already going offline. 918 * SCN - ignore and wait till transitioning to offline state 919 */ 920 break; 921 922 case RPSM_EVENT_DELETE: 923 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); 924 break; 925 926 default: 927 bfa_sm_fault(rport->fcs, event); 928 } 929} 930 931/** 932 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline 933 * callback. 934 */ 935static void 936bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, 937 enum rport_event event) 938{ 939 bfa_trc(rport->fcs, rport->pwwn); 940 bfa_trc(rport->fcs, rport->pid); 941 bfa_trc(rport->fcs, event); 942 943 switch (event) { 944 case RPSM_EVENT_HCB_OFFLINE: 945 case RPSM_EVENT_ADDRESS_CHANGE: 946 if (bfa_fcs_port_is_online(rport->port)) { 947 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { 948 bfa_sm_set_state(rport, 949 bfa_fcs_rport_sm_nsdisc_sending); 950 rport->ns_retries = 0; 951 bfa_fcs_rport_send_gidpn(rport, NULL); 952 } else { 953 bfa_sm_set_state(rport, 954 bfa_fcs_rport_sm_plogi_sending); 955 rport->plogi_retries = 0; 956 bfa_fcs_rport_send_plogi(rport, NULL); 957 } 958 } else { 959 rport->pid = 0; 960 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 961 bfa_timer_start(rport->fcs->bfa, &rport->timer, 962 bfa_fcs_rport_timeout, rport, 963 bfa_fcs_rport_del_timeout); 964 } 965 break; 966 967 case RPSM_EVENT_DELETE: 968 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 969 bfa_fcs_rport_free(rport); 970 break; 971 972 case RPSM_EVENT_SCN: 973 case RPSM_EVENT_LOGO_RCVD: 974 case RPSM_EVENT_PRLO_RCVD: 975 /** 976 * Ignore, already offline. 977 */ 978 break; 979 980 default: 981 bfa_sm_fault(rport->fcs, event); 982 } 983} 984 985/** 986 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline 987 * callback to send LOGO accept. 988 */ 989static void 990bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, 991 enum rport_event event) 992{ 993 bfa_trc(rport->fcs, rport->pwwn); 994 bfa_trc(rport->fcs, rport->pid); 995 bfa_trc(rport->fcs, event); 996 997 switch (event) { 998 case RPSM_EVENT_HCB_OFFLINE: 999 case RPSM_EVENT_ADDRESS_CHANGE: 1000 if (rport->pid && (rport->prlo == BFA_TRUE)) 1001 bfa_fcs_rport_send_prlo_acc(rport); 1002 if (rport->pid && (rport->prlo == BFA_FALSE)) 1003 bfa_fcs_rport_send_logo_acc(rport); 1004 1005 /* 1006 * If the lport is online and if the rport is not a well known 1007 * address port, we try to re-discover the r-port. 1008 */ 1009 if (bfa_fcs_port_is_online(rport->port) 1010 && (!BFA_FCS_PID_IS_WKA(rport->pid))) { 1011 bfa_sm_set_state(rport, 1012 bfa_fcs_rport_sm_nsdisc_sending); 1013 rport->ns_retries = 0; 1014 bfa_fcs_rport_send_gidpn(rport, NULL); 1015 } else { 1016 /* 1017 * if it is not a well known address, reset the pid to 1018 * 1019 */ 1020 if (!BFA_FCS_PID_IS_WKA(rport->pid)) 1021 rport->pid = 0; 1022 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 1023 bfa_timer_start(rport->fcs->bfa, &rport->timer, 1024 bfa_fcs_rport_timeout, rport, 1025 bfa_fcs_rport_del_timeout); 1026 } 1027 break; 1028 1029 case RPSM_EVENT_DELETE: 1030 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); 1031 break; 1032 1033 case RPSM_EVENT_LOGO_IMP: 1034 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); 1035 break; 1036 1037 case RPSM_EVENT_LOGO_RCVD: 1038 case RPSM_EVENT_PRLO_RCVD: 1039 /** 1040 * Ignore - already processing a LOGO. 1041 */ 1042 break; 1043 1044 default: 1045 bfa_sm_fault(rport->fcs, event); 1046 } 1047} 1048 1049/** 1050 * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline 1051 * callback to send LOGO. 1052 */ 1053static void 1054bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport, 1055 enum rport_event event) 1056{ 1057 bfa_trc(rport->fcs, rport->pwwn); 1058 bfa_trc(rport->fcs, rport->pid); 1059 bfa_trc(rport->fcs, event); 1060 1061 switch (event) { 1062 case RPSM_EVENT_HCB_OFFLINE: 1063 bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending); 1064 bfa_fcs_rport_send_logo(rport, NULL); 1065 break; 1066 1067 case RPSM_EVENT_LOGO_RCVD: 1068 case RPSM_EVENT_PRLO_RCVD: 1069 case RPSM_EVENT_ADDRESS_CHANGE: 1070 break; 1071 1072 default: 1073 bfa_sm_fault(rport->fcs, event); 1074 } 1075} 1076 1077/** 1078 * Rport is being deleted. FC-4s are offline. LOGO is being sent. 1079 */ 1080static void 1081bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport, 1082 enum rport_event event) 1083{ 1084 bfa_trc(rport->fcs, rport->pwwn); 1085 bfa_trc(rport->fcs, rport->pid); 1086 bfa_trc(rport->fcs, event); 1087 1088 switch (event) { 1089 case RPSM_EVENT_FCXP_SENT: 1090 /* 1091 * Once LOGO is sent, we donot wait for the response 1092 */ 1093 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 1094 bfa_fcs_rport_free(rport); 1095 break; 1096 1097 case RPSM_EVENT_SCN: 1098 case RPSM_EVENT_ADDRESS_CHANGE: 1099 break; 1100 1101 case RPSM_EVENT_LOGO_RCVD: 1102 case RPSM_EVENT_PRLO_RCVD: 1103 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 1104 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 1105 bfa_fcs_rport_free(rport); 1106 break; 1107 1108 default: 1109 bfa_sm_fault(rport->fcs, event); 1110 } 1111} 1112 1113/** 1114 * Rport is offline. FC-4s are offline. BFA rport is offline. 1115 * Timer active to delete stale rport. 1116 */ 1117static void 1118bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event) 1119{ 1120 bfa_trc(rport->fcs, rport->pwwn); 1121 bfa_trc(rport->fcs, rport->pid); 1122 bfa_trc(rport->fcs, event); 1123 1124 switch (event) { 1125 case RPSM_EVENT_TIMEOUT: 1126 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 1127 bfa_fcs_rport_free(rport); 1128 break; 1129 1130 case RPSM_EVENT_SCN: 1131 case RPSM_EVENT_ADDRESS_CHANGE: 1132 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); 1133 bfa_timer_stop(&rport->timer); 1134 rport->ns_retries = 0; 1135 bfa_fcs_rport_send_gidpn(rport, NULL); 1136 break; 1137 1138 case RPSM_EVENT_DELETE: 1139 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 1140 bfa_timer_stop(&rport->timer); 1141 bfa_fcs_rport_free(rport); 1142 break; 1143 1144 case RPSM_EVENT_PLOGI_RCVD: 1145 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 1146 bfa_timer_stop(&rport->timer); 1147 bfa_fcs_rport_send_plogiacc(rport, NULL); 1148 break; 1149 1150 case RPSM_EVENT_LOGO_RCVD: 1151 case RPSM_EVENT_PRLO_RCVD: 1152 case RPSM_EVENT_LOGO_IMP: 1153 break; 1154 1155 case RPSM_EVENT_PLOGI_COMP: 1156 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 1157 bfa_timer_stop(&rport->timer); 1158 bfa_fcs_rport_hal_online(rport); 1159 break; 1160 1161 case RPSM_EVENT_PLOGI_SEND: 1162 bfa_timer_stop(&rport->timer); 1163 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); 1164 rport->plogi_retries = 0; 1165 bfa_fcs_rport_send_plogi(rport, NULL); 1166 break; 1167 1168 default: 1169 bfa_sm_fault(rport->fcs, event); 1170 } 1171} 1172 1173/** 1174 * Rport address has changed. Nameserver discovery request is being sent. 1175 */ 1176static void 1177bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport, 1178 enum rport_event event) 1179{ 1180 bfa_trc(rport->fcs, rport->pwwn); 1181 bfa_trc(rport->fcs, rport->pid); 1182 bfa_trc(rport->fcs, event); 1183 1184 switch (event) { 1185 case RPSM_EVENT_FCXP_SENT: 1186 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent); 1187 break; 1188 1189 case RPSM_EVENT_DELETE: 1190 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 1191 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 1192 bfa_fcs_rport_free(rport); 1193 break; 1194 1195 case RPSM_EVENT_PLOGI_RCVD: 1196 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 1197 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 1198 bfa_fcs_rport_send_plogiacc(rport, NULL); 1199 break; 1200 1201 case RPSM_EVENT_SCN: 1202 case RPSM_EVENT_LOGO_RCVD: 1203 case RPSM_EVENT_PRLO_RCVD: 1204 case RPSM_EVENT_PLOGI_SEND: 1205 break; 1206 1207 case RPSM_EVENT_ADDRESS_CHANGE: 1208 rport->ns_retries = 0; /* reset the retry count */ 1209 break; 1210 1211 case RPSM_EVENT_LOGO_IMP: 1212 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 1213 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 1214 bfa_timer_start(rport->fcs->bfa, &rport->timer, 1215 bfa_fcs_rport_timeout, rport, 1216 bfa_fcs_rport_del_timeout); 1217 break; 1218 1219 case RPSM_EVENT_PLOGI_COMP: 1220 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 1221 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); 1222 bfa_fcs_rport_hal_online(rport); 1223 break; 1224 1225 default: 1226 bfa_sm_fault(rport->fcs, event); 1227 } 1228} 1229 1230/** 1231 * Nameserver discovery failed. Waiting for timeout to retry. 1232 */ 1233static void 1234bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport, 1235 enum rport_event event) 1236{ 1237 bfa_trc(rport->fcs, rport->pwwn); 1238 bfa_trc(rport->fcs, rport->pid); 1239 bfa_trc(rport->fcs, event); 1240 1241 switch (event) { 1242 case RPSM_EVENT_TIMEOUT: 1243 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); 1244 bfa_fcs_rport_send_gidpn(rport, NULL); 1245 break; 1246 1247 case RPSM_EVENT_SCN: 1248 case RPSM_EVENT_ADDRESS_CHANGE: 1249 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); 1250 bfa_timer_stop(&rport->timer); 1251 rport->ns_retries = 0; 1252 bfa_fcs_rport_send_gidpn(rport, NULL); 1253 break; 1254 1255 case RPSM_EVENT_DELETE: 1256 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 1257 bfa_timer_stop(&rport->timer); 1258 bfa_fcs_rport_free(rport); 1259 break; 1260 1261 case RPSM_EVENT_PLOGI_RCVD: 1262 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 1263 bfa_timer_stop(&rport->timer); 1264 bfa_fcs_rport_send_plogiacc(rport, NULL); 1265 break; 1266 1267 case RPSM_EVENT_LOGO_IMP: 1268 rport->pid = 0; 1269 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 1270 bfa_timer_stop(&rport->timer); 1271 bfa_timer_start(rport->fcs->bfa, &rport->timer, 1272 bfa_fcs_rport_timeout, rport, 1273 bfa_fcs_rport_del_timeout); 1274 break; 1275 1276 case RPSM_EVENT_LOGO_RCVD: 1277 bfa_fcs_rport_send_logo_acc(rport); 1278 break; 1279 1280 case RPSM_EVENT_PRLO_RCVD: 1281 bfa_fcs_rport_send_prlo_acc(rport); 1282 break; 1283 1284 case RPSM_EVENT_PLOGI_COMP: 1285 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 1286 bfa_timer_stop(&rport->timer); 1287 bfa_fcs_rport_hal_online(rport); 1288 break; 1289 1290 default: 1291 bfa_sm_fault(rport->fcs, event); 1292 } 1293} 1294 1295/** 1296 * Rport address has changed. Nameserver discovery request is sent. 1297 */ 1298static void 1299bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, 1300 enum rport_event event) 1301{ 1302 bfa_trc(rport->fcs, rport->pwwn); 1303 bfa_trc(rport->fcs, rport->pid); 1304 bfa_trc(rport->fcs, event); 1305 1306 switch (event) { 1307 case RPSM_EVENT_ACCEPTED: 1308 case RPSM_EVENT_ADDRESS_CHANGE: 1309 if (rport->pid) { 1310 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); 1311 bfa_fcs_rport_send_plogi(rport, NULL); 1312 } else { 1313 bfa_sm_set_state(rport, 1314 bfa_fcs_rport_sm_nsdisc_sending); 1315 rport->ns_retries = 0; 1316 bfa_fcs_rport_send_gidpn(rport, NULL); 1317 } 1318 break; 1319 1320 case RPSM_EVENT_FAILED: 1321 rport->ns_retries++; 1322 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) { 1323 bfa_sm_set_state(rport, 1324 bfa_fcs_rport_sm_nsdisc_sending); 1325 bfa_fcs_rport_send_gidpn(rport, NULL); 1326 } else { 1327 rport->pid = 0; 1328 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 1329 bfa_timer_start(rport->fcs->bfa, &rport->timer, 1330 bfa_fcs_rport_timeout, rport, 1331 bfa_fcs_rport_del_timeout); 1332 }; 1333 break; 1334 1335 case RPSM_EVENT_DELETE: 1336 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 1337 bfa_fcxp_discard(rport->fcxp); 1338 bfa_fcs_rport_free(rport); 1339 break; 1340 1341 case RPSM_EVENT_PLOGI_RCVD: 1342 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); 1343 bfa_fcxp_discard(rport->fcxp); 1344 bfa_fcs_rport_send_plogiacc(rport, NULL); 1345 break; 1346 1347 case RPSM_EVENT_LOGO_IMP: 1348 rport->pid = 0; 1349 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); 1350 bfa_fcxp_discard(rport->fcxp); 1351 bfa_timer_start(rport->fcs->bfa, &rport->timer, 1352 bfa_fcs_rport_timeout, rport, 1353 bfa_fcs_rport_del_timeout); 1354 break; 1355 1356 case RPSM_EVENT_PRLO_RCVD: 1357 bfa_fcs_rport_send_prlo_acc(rport); 1358 break; 1359 1360 case RPSM_EVENT_SCN: 1361 /** 1362 * ignore, wait for NS query response 1363 */ 1364 break; 1365 1366 case RPSM_EVENT_LOGO_RCVD: 1367 /** 1368 * Not logged-in yet. Accept LOGO. 1369 */ 1370 bfa_fcs_rport_send_logo_acc(rport); 1371 break; 1372 1373 case RPSM_EVENT_PLOGI_COMP: 1374 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); 1375 bfa_fcxp_discard(rport->fcxp); 1376 bfa_fcs_rport_hal_online(rport); 1377 break; 1378 1379 default: 1380 bfa_sm_fault(rport->fcs, event); 1381 } 1382} 1383 1384 1385 1386/** 1387 * fcs_rport_private FCS RPORT provate functions 1388 */ 1389 1390static void 1391bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) 1392{ 1393 struct bfa_fcs_rport_s *rport = rport_cbarg; 1394 struct bfa_fcs_port_s *port = rport->port; 1395 struct fchs_s fchs; 1396 int len; 1397 struct bfa_fcxp_s *fcxp; 1398 1399 bfa_trc(rport->fcs, rport->pwwn); 1400 1401 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1402 if (!fcxp) { 1403 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1404 bfa_fcs_rport_send_plogi, rport); 1405 return; 1406 } 1407 rport->fcxp = fcxp; 1408 1409 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, 1410 bfa_fcs_port_get_fcid(port), 0, 1411 port->port_cfg.pwwn, port->port_cfg.nwwn, 1412 bfa_fcport_get_maxfrsize(port->fcs->bfa)); 1413 1414 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1415 FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response, 1416 (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV); 1417 1418 rport->stats.plogis++; 1419 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); 1420} 1421 1422static void 1423bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, 1424 bfa_status_t req_status, u32 rsp_len, 1425 u32 resid_len, struct fchs_s *rsp_fchs) 1426{ 1427 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; 1428 struct fc_logi_s *plogi_rsp; 1429 struct fc_ls_rjt_s *ls_rjt; 1430 struct bfa_fcs_rport_s *twin; 1431 struct list_head *qe; 1432 1433 bfa_trc(rport->fcs, rport->pwwn); 1434 1435 /* 1436 * Sanity Checks 1437 */ 1438 if (req_status != BFA_STATUS_OK) { 1439 bfa_trc(rport->fcs, req_status); 1440 rport->stats.plogi_failed++; 1441 bfa_sm_send_event(rport, RPSM_EVENT_FAILED); 1442 return; 1443 } 1444 1445 plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp); 1446 1447 /** 1448 * Check for failure first. 1449 */ 1450 if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) { 1451 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); 1452 1453 bfa_trc(rport->fcs, ls_rjt->reason_code); 1454 bfa_trc(rport->fcs, ls_rjt->reason_code_expl); 1455 1456 rport->stats.plogi_rejects++; 1457 bfa_sm_send_event(rport, RPSM_EVENT_FAILED); 1458 return; 1459 } 1460 1461 /** 1462 * PLOGI is complete. Make sure this device is not one of the known 1463 * device with a new FC port address. 1464 */ 1465 list_for_each(qe, &rport->port->rport_q) { 1466 twin = (struct bfa_fcs_rport_s *)qe; 1467 if (twin == rport) 1468 continue; 1469 if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) { 1470 bfa_trc(rport->fcs, twin->pid); 1471 bfa_trc(rport->fcs, rport->pid); 1472 1473 /* 1474 * Update plogi stats in twin 1475 */ 1476 twin->stats.plogis += rport->stats.plogis; 1477 twin->stats.plogi_rejects += rport->stats.plogi_rejects; 1478 twin->stats.plogi_timeouts += 1479 rport->stats.plogi_timeouts; 1480 twin->stats.plogi_failed += rport->stats.plogi_failed; 1481 twin->stats.plogi_rcvd += rport->stats.plogi_rcvd; 1482 twin->stats.plogi_accs++; 1483 1484 bfa_fcs_rport_delete(rport); 1485 1486 bfa_fcs_rport_update(twin, plogi_rsp); 1487 twin->pid = rsp_fchs->s_id; 1488 bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP); 1489 return; 1490 } 1491 } 1492 1493 /** 1494 * Normal login path -- no evil twins. 1495 */ 1496 rport->stats.plogi_accs++; 1497 bfa_fcs_rport_update(rport, plogi_rsp); 1498 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED); 1499} 1500 1501static void 1502bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) 1503{ 1504 struct bfa_fcs_rport_s *rport = rport_cbarg; 1505 struct bfa_fcs_port_s *port = rport->port; 1506 struct fchs_s fchs; 1507 int len; 1508 struct bfa_fcxp_s *fcxp; 1509 1510 bfa_trc(rport->fcs, rport->pwwn); 1511 bfa_trc(rport->fcs, rport->reply_oxid); 1512 1513 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1514 if (!fcxp) { 1515 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1516 bfa_fcs_rport_send_plogiacc, rport); 1517 return; 1518 } 1519 rport->fcxp = fcxp; 1520 1521 len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, 1522 bfa_fcs_port_get_fcid(port), rport->reply_oxid, 1523 port->port_cfg.pwwn, port->port_cfg.nwwn, 1524 bfa_fcport_get_maxfrsize(port->fcs->bfa)); 1525 1526 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1527 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); 1528 1529 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); 1530} 1531 1532static void 1533bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) 1534{ 1535 struct bfa_fcs_rport_s *rport = rport_cbarg; 1536 struct bfa_fcs_port_s *port = rport->port; 1537 struct fchs_s fchs; 1538 int len; 1539 struct bfa_fcxp_s *fcxp; 1540 1541 bfa_trc(rport->fcs, rport->pwwn); 1542 1543 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1544 if (!fcxp) { 1545 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1546 bfa_fcs_rport_send_adisc, rport); 1547 return; 1548 } 1549 rport->fcxp = fcxp; 1550 1551 len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, 1552 bfa_fcs_port_get_fcid(port), 0, 1553 port->port_cfg.pwwn, port->port_cfg.nwwn); 1554 1555 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1556 FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response, 1557 rport, FC_MAX_PDUSZ, FC_ELS_TOV); 1558 1559 rport->stats.adisc_sent++; 1560 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); 1561} 1562 1563static void 1564bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, 1565 bfa_status_t req_status, u32 rsp_len, 1566 u32 resid_len, struct fchs_s *rsp_fchs) 1567{ 1568 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; 1569 void *pld = bfa_fcxp_get_rspbuf(fcxp); 1570 struct fc_ls_rjt_s *ls_rjt; 1571 1572 if (req_status != BFA_STATUS_OK) { 1573 bfa_trc(rport->fcs, req_status); 1574 rport->stats.adisc_failed++; 1575 bfa_sm_send_event(rport, RPSM_EVENT_FAILED); 1576 return; 1577 } 1578 1579 if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn, 1580 rport->nwwn) == FC_PARSE_OK) { 1581 rport->stats.adisc_accs++; 1582 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED); 1583 return; 1584 } 1585 1586 rport->stats.adisc_rejects++; 1587 ls_rjt = pld; 1588 bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code); 1589 bfa_trc(rport->fcs, ls_rjt->reason_code); 1590 bfa_trc(rport->fcs, ls_rjt->reason_code_expl); 1591 bfa_sm_send_event(rport, RPSM_EVENT_FAILED); 1592} 1593 1594static void 1595bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) 1596{ 1597 struct bfa_fcs_rport_s *rport = rport_cbarg; 1598 struct bfa_fcs_port_s *port = rport->port; 1599 struct fchs_s fchs; 1600 struct bfa_fcxp_s *fcxp; 1601 int len; 1602 1603 bfa_trc(rport->fcs, rport->pid); 1604 1605 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1606 if (!fcxp) { 1607 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1608 bfa_fcs_rport_send_gidpn, rport); 1609 return; 1610 } 1611 rport->fcxp = fcxp; 1612 1613 len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 1614 bfa_fcs_port_get_fcid(port), 0, rport->pwwn); 1615 1616 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1617 FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response, 1618 (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV); 1619 1620 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); 1621} 1622 1623static void 1624bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, 1625 bfa_status_t req_status, u32 rsp_len, 1626 u32 resid_len, struct fchs_s *rsp_fchs) 1627{ 1628 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; 1629 struct bfa_fcs_rport_s *twin; 1630 struct list_head *qe; 1631 struct ct_hdr_s *cthdr; 1632 struct fcgs_gidpn_resp_s *gidpn_rsp; 1633 1634 bfa_trc(rport->fcs, rport->pwwn); 1635 1636 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); 1637 cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); 1638 1639 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { 1640 /* 1641 * Check if the pid is the same as before. 1642 */ 1643 gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1); 1644 1645 if (gidpn_rsp->dap == rport->pid) { 1646 /* 1647 * Device is online 1648 */ 1649 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED); 1650 } else { 1651 /* 1652 * Device's PID has changed. We need to cleanup and 1653 * re-login. If there is another device with the the 1654 * newly discovered pid, send an scn notice so that its 1655 * new pid can be discovered. 1656 */ 1657 list_for_each(qe, &rport->port->rport_q) { 1658 twin = (struct bfa_fcs_rport_s *)qe; 1659 if (twin == rport) 1660 continue; 1661 if (gidpn_rsp->dap == twin->pid) { 1662 bfa_trc(rport->fcs, twin->pid); 1663 bfa_trc(rport->fcs, rport->pid); 1664 1665 twin->pid = 0; 1666 bfa_sm_send_event(twin, 1667 RPSM_EVENT_ADDRESS_CHANGE); 1668 } 1669 } 1670 rport->pid = gidpn_rsp->dap; 1671 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE); 1672 } 1673 return; 1674 } 1675 1676 /* 1677 * Reject Response 1678 */ 1679 switch (cthdr->reason_code) { 1680 case CT_RSN_LOGICAL_BUSY: 1681 /* 1682 * Need to retry 1683 */ 1684 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT); 1685 break; 1686 1687 case CT_RSN_UNABLE_TO_PERF: 1688 /* 1689 * device doesn't exist : Start timer to cleanup this later. 1690 */ 1691 bfa_sm_send_event(rport, RPSM_EVENT_FAILED); 1692 break; 1693 1694 default: 1695 bfa_sm_send_event(rport, RPSM_EVENT_FAILED); 1696 break; 1697 } 1698} 1699 1700/** 1701 * Called to send a logout to the rport. 1702 */ 1703static void 1704bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) 1705{ 1706 struct bfa_fcs_rport_s *rport = rport_cbarg; 1707 struct bfa_fcs_port_s *port; 1708 struct fchs_s fchs; 1709 struct bfa_fcxp_s *fcxp; 1710 u16 len; 1711 1712 bfa_trc(rport->fcs, rport->pid); 1713 1714 port = rport->port; 1715 1716 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 1717 if (!fcxp) { 1718 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, 1719 bfa_fcs_rport_send_logo, rport); 1720 return; 1721 } 1722 rport->fcxp = fcxp; 1723 1724 len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, 1725 bfa_fcs_port_get_fcid(port), 0, 1726 bfa_fcs_port_get_pwwn(port)); 1727 1728 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1729 FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ, 1730 FC_ELS_TOV); 1731 1732 rport->stats.logos++; 1733 bfa_fcxp_discard(rport->fcxp); 1734 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); 1735} 1736 1737/** 1738 * Send ACC for a LOGO received. 1739 */ 1740static void 1741bfa_fcs_rport_send_logo_acc(void *rport_cbarg) 1742{ 1743 struct bfa_fcs_rport_s *rport = rport_cbarg; 1744 struct bfa_fcs_port_s *port; 1745 struct fchs_s fchs; 1746 struct bfa_fcxp_s *fcxp; 1747 u16 len; 1748 1749 bfa_trc(rport->fcs, rport->pid); 1750 1751 port = rport->port; 1752 1753 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 1754 if (!fcxp) 1755 return; 1756 1757 rport->stats.logo_rcvd++; 1758 len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, 1759 bfa_fcs_port_get_fcid(port), rport->reply_oxid); 1760 1761 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1762 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); 1763} 1764 1765/** 1766 * This routine will be called by bfa_timer on timer timeouts. 1767 * 1768 * param[in] rport - pointer to bfa_fcs_port_ns_t. 1769 * param[out] rport_status - pointer to return vport status in 1770 * 1771 * return 1772 * void 1773 * 1774* Special Considerations: 1775 * 1776 * note 1777 */ 1778static void 1779bfa_fcs_rport_timeout(void *arg) 1780{ 1781 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg; 1782 1783 rport->stats.plogi_timeouts++; 1784 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT); 1785} 1786 1787static void 1788bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport, 1789 struct fchs_s *rx_fchs, u16 len) 1790{ 1791 struct bfa_fcxp_s *fcxp; 1792 struct fchs_s fchs; 1793 struct bfa_fcs_port_s *port = rport->port; 1794 struct fc_prli_s *prli; 1795 1796 bfa_trc(port->fcs, rx_fchs->s_id); 1797 bfa_trc(port->fcs, rx_fchs->d_id); 1798 1799 rport->stats.prli_rcvd++; 1800 1801 if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) { 1802 /* 1803 * Target Mode : Let the fcptm handle it 1804 */ 1805 bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len); 1806 return; 1807 } 1808 1809 /* 1810 * We are either in Initiator or ipfc Mode 1811 */ 1812 prli = (struct fc_prli_s *) (rx_fchs + 1); 1813 1814 if (prli->parampage.servparams.initiator) { 1815 bfa_trc(rport->fcs, prli->parampage.type); 1816 rport->scsi_function = BFA_RPORT_INITIATOR; 1817 bfa_fcs_itnim_is_initiator(rport->itnim); 1818 } else { 1819 /* 1820 * @todo: PRLI from a target ? 1821 */ 1822 bfa_trc(port->fcs, rx_fchs->s_id); 1823 rport->scsi_function = BFA_RPORT_TARGET; 1824 } 1825 1826 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 1827 if (!fcxp) 1828 return; 1829 1830 len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, 1831 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, 1832 port->port_cfg.roles); 1833 1834 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1835 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); 1836} 1837 1838static void 1839bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport, 1840 struct fchs_s *rx_fchs, u16 len) 1841{ 1842 struct bfa_fcxp_s *fcxp; 1843 struct fchs_s fchs; 1844 struct bfa_fcs_port_s *port = rport->port; 1845 struct fc_rpsc_speed_info_s speeds; 1846 struct bfa_pport_attr_s pport_attr; 1847 1848 bfa_trc(port->fcs, rx_fchs->s_id); 1849 bfa_trc(port->fcs, rx_fchs->d_id); 1850 1851 rport->stats.rpsc_rcvd++; 1852 speeds.port_speed_cap = 1853 RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G | 1854 RPSC_SPEED_CAP_8G; 1855 1856 /* 1857 * get curent speed from pport attributes from BFA 1858 */ 1859 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr); 1860 1861 speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed); 1862 1863 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 1864 if (!fcxp) 1865 return; 1866 1867 len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, 1868 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, 1869 &speeds); 1870 1871 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 1872 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); 1873} 1874 1875static void 1876bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport, 1877 struct fchs_s *rx_fchs, u16 len) 1878{ 1879 struct bfa_fcxp_s *fcxp; 1880 struct fchs_s fchs; 1881 struct bfa_fcs_port_s *port = rport->port; 1882 struct fc_adisc_s *adisc; 1883 1884 bfa_trc(port->fcs, rx_fchs->s_id); 1885 bfa_trc(port->fcs, rx_fchs->d_id); 1886 1887 rport->stats.adisc_rcvd++; 1888 1889 if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) { 1890 /* 1891 * @todo : Target Mode handling 1892 */ 1893 bfa_trc(port->fcs, rx_fchs->d_id); 1894 bfa_assert(0); 1895 return; 1896 } 1897 1898 adisc = (struct fc_adisc_s *) (rx_fchs + 1); 1899 1900 /* 1901 * Accept if the itnim for this rport is online. Else reject the ADISC 1902 */ 1903 if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) { 1904 1905 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 1906 if (!fcxp) 1907 return; 1908 1909 len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 1910 rx_fchs->s_id, 1911 bfa_fcs_port_get_fcid(port), 1912 rx_fchs->ox_id, port->port_cfg.pwwn, 1913 port->port_cfg.nwwn); 1914 1915 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, 1916 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, 1917 FC_MAX_PDUSZ, 0); 1918 } else { 1919 rport->stats.adisc_rejected++; 1920 bfa_fcs_rport_send_ls_rjt(rport, rx_fchs, 1921 FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD, 1922 FC_LS_RJT_EXP_LOGIN_REQUIRED); 1923 } 1924 1925} 1926 1927static void 1928bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport) 1929{ 1930 struct bfa_fcs_port_s *port = rport->port; 1931 struct bfa_rport_info_s rport_info; 1932 1933 rport_info.pid = rport->pid; 1934 rport_info.local_pid = port->pid; 1935 rport_info.lp_tag = port->lp_tag; 1936 rport_info.vf_id = port->fabric->vf_id; 1937 rport_info.vf_en = port->fabric->is_vf; 1938 rport_info.fc_class = rport->fc_cos; 1939 rport_info.cisc = rport->cisc; 1940 rport_info.max_frmsz = rport->maxfrsize; 1941 bfa_rport_online(rport->bfa_rport, &rport_info); 1942} 1943 1944static void 1945bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport) 1946{ 1947 if (bfa_fcs_port_is_initiator(rport->port)) 1948 bfa_fcs_itnim_pause(rport->itnim); 1949 1950 if (bfa_fcs_port_is_target(rport->port)) 1951 bfa_fcs_tin_pause(rport->tin); 1952} 1953 1954static void 1955bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport) 1956{ 1957 if (bfa_fcs_port_is_initiator(rport->port)) 1958 bfa_fcs_itnim_resume(rport->itnim); 1959 1960 if (bfa_fcs_port_is_target(rport->port)) 1961 bfa_fcs_tin_resume(rport->tin); 1962} 1963 1964static struct bfa_fcs_rport_s * 1965bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid) 1966{ 1967 struct bfa_fcs_s *fcs = port->fcs; 1968 struct bfa_fcs_rport_s *rport; 1969 struct bfad_rport_s *rport_drv; 1970 1971 /** 1972 * allocate rport 1973 */ 1974 if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv) 1975 != BFA_STATUS_OK) { 1976 bfa_trc(fcs, rpid); 1977 return NULL; 1978 } 1979 1980 /* 1981 * Initialize r-port 1982 */ 1983 rport->port = port; 1984 rport->fcs = fcs; 1985 rport->rp_drv = rport_drv; 1986 rport->pid = rpid; 1987 rport->pwwn = pwwn; 1988 1989 /** 1990 * allocate BFA rport 1991 */ 1992 rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport); 1993 if (!rport->bfa_rport) { 1994 bfa_trc(fcs, rpid); 1995 kfree(rport_drv); 1996 return NULL; 1997 } 1998 1999 /** 2000 * allocate FC-4s 2001 */ 2002 bfa_assert(bfa_fcs_port_is_initiator(port) ^ 2003 bfa_fcs_port_is_target(port)); 2004 2005 if (bfa_fcs_port_is_initiator(port)) { 2006 rport->itnim = bfa_fcs_itnim_create(rport); 2007 if (!rport->itnim) { 2008 bfa_trc(fcs, rpid); 2009 bfa_rport_delete(rport->bfa_rport); 2010 kfree(rport_drv); 2011 return NULL; 2012 } 2013 } 2014 2015 if (bfa_fcs_port_is_target(port)) { 2016 rport->tin = bfa_fcs_tin_create(rport); 2017 if (!rport->tin) { 2018 bfa_trc(fcs, rpid); 2019 bfa_rport_delete(rport->bfa_rport); 2020 kfree(rport_drv); 2021 return NULL; 2022 } 2023 } 2024 2025 bfa_fcs_port_add_rport(port, rport); 2026 2027 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); 2028 2029 /* 2030 * Initialize the Rport Features(RPF) Sub Module 2031 */ 2032 if (!BFA_FCS_PID_IS_WKA(rport->pid)) 2033 bfa_fcs_rpf_init(rport); 2034 2035 return rport; 2036} 2037 2038 2039static void 2040bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport) 2041{ 2042 struct bfa_fcs_port_s *port = rport->port; 2043 2044 /** 2045 * - delete FC-4s 2046 * - delete BFA rport 2047 * - remove from queue of rports 2048 */ 2049 if (bfa_fcs_port_is_initiator(port)) 2050 bfa_fcs_itnim_delete(rport->itnim); 2051 2052 if (bfa_fcs_port_is_target(port)) 2053 bfa_fcs_tin_delete(rport->tin); 2054 2055 bfa_rport_delete(rport->bfa_rport); 2056 bfa_fcs_port_del_rport(port, rport); 2057 kfree(rport->rp_drv); 2058} 2059 2060static void 2061bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport, 2062 enum bfa_rport_aen_event event, 2063 struct bfa_rport_aen_data_s *data) 2064{ 2065 union bfa_aen_data_u aen_data; 2066 struct bfa_log_mod_s *logmod = rport->fcs->logm; 2067 wwn_t lpwwn = bfa_fcs_port_get_pwwn(rport->port); 2068 wwn_t rpwwn = rport->pwwn; 2069 char lpwwn_ptr[BFA_STRING_32]; 2070 char rpwwn_ptr[BFA_STRING_32]; 2071 char *prio_str[] = { "unknown", "high", "medium", "low" }; 2072 2073 wwn2str(lpwwn_ptr, lpwwn); 2074 wwn2str(rpwwn_ptr, rpwwn); 2075 2076 switch (event) { 2077 case BFA_RPORT_AEN_ONLINE: 2078 case BFA_RPORT_AEN_OFFLINE: 2079 case BFA_RPORT_AEN_DISCONNECT: 2080 bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, event), 2081 rpwwn_ptr, lpwwn_ptr); 2082 break; 2083 case BFA_RPORT_AEN_QOS_PRIO: 2084 aen_data.rport.priv.qos = data->priv.qos; 2085 bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO, 2086 prio_str[aen_data.rport.priv.qos.qos_priority], 2087 rpwwn_ptr, lpwwn_ptr); 2088 break; 2089 case BFA_RPORT_AEN_QOS_FLOWID: 2090 aen_data.rport.priv.qos = data->priv.qos; 2091 bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID, 2092 aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr, 2093 lpwwn_ptr); 2094 break; 2095 default: 2096 break; 2097 } 2098 2099 aen_data.rport.vf_id = rport->port->fabric->vf_id; 2100 aen_data.rport.ppwwn = 2101 bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs)); 2102 aen_data.rport.lpwwn = lpwwn; 2103 aen_data.rport.rpwwn = rpwwn; 2104} 2105 2106static void 2107bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport) 2108{ 2109 struct bfa_fcs_port_s *port = rport->port; 2110 2111 rport->stats.onlines++; 2112 2113 if (bfa_fcs_port_is_initiator(port)) { 2114 bfa_fcs_itnim_rport_online(rport->itnim); 2115 if (!BFA_FCS_PID_IS_WKA(rport->pid)) 2116 bfa_fcs_rpf_rport_online(rport); 2117 }; 2118 2119 if (bfa_fcs_port_is_target(port)) 2120 bfa_fcs_tin_rport_online(rport->tin); 2121 2122 /* 2123 * Don't post events for well known addresses 2124 */ 2125 if (!BFA_FCS_PID_IS_WKA(rport->pid)) 2126 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL); 2127} 2128 2129static void 2130bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport) 2131{ 2132 struct bfa_fcs_port_s *port = rport->port; 2133 2134 rport->stats.offlines++; 2135 2136 /* 2137 * Don't post events for well known addresses 2138 */ 2139 if (!BFA_FCS_PID_IS_WKA(rport->pid)) { 2140 if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) { 2141 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT, 2142 NULL); 2143 } else { 2144 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE, 2145 NULL); 2146 } 2147 } 2148 2149 if (bfa_fcs_port_is_initiator(port)) { 2150 bfa_fcs_itnim_rport_offline(rport->itnim); 2151 if (!BFA_FCS_PID_IS_WKA(rport->pid)) 2152 bfa_fcs_rpf_rport_offline(rport); 2153 } 2154 2155 if (bfa_fcs_port_is_target(port)) 2156 bfa_fcs_tin_rport_offline(rport->tin); 2157} 2158 2159/** 2160 * Update rport parameters from PLOGI or PLOGI accept. 2161 */ 2162static void 2163bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi) 2164{ 2165 struct bfa_fcs_port_s *port = rport->port; 2166 2167 /** 2168 * - port name 2169 * - node name 2170 */ 2171 rport->pwwn = plogi->port_name; 2172 rport->nwwn = plogi->node_name; 2173 2174 /** 2175 * - class of service 2176 */ 2177 rport->fc_cos = 0; 2178 if (plogi->class3.class_valid) 2179 rport->fc_cos = FC_CLASS_3; 2180 2181 if (plogi->class2.class_valid) 2182 rport->fc_cos |= FC_CLASS_2; 2183 2184 /** 2185 * - CISC 2186 * - MAX receive frame size 2187 */ 2188 rport->cisc = plogi->csp.cisc; 2189 rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz); 2190 2191 bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred)); 2192 bfa_trc(port->fcs, port->fabric->bb_credit); 2193 /** 2194 * Direct Attach P2P mode : 2195 * This is to handle a bug (233476) in IBM targets in Direct Attach 2196 * Mode. Basically, in FLOGI Accept the target would have erroneously 2197 * set the BB Credit to the value used in the FLOGI sent by the HBA. 2198 * It uses the correct value (its own BB credit) in PLOGI. 2199 */ 2200 if ((!bfa_fcs_fabric_is_switched(port->fabric)) 2201 && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) { 2202 2203 bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred)); 2204 bfa_trc(port->fcs, port->fabric->bb_credit); 2205 2206 port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred); 2207 bfa_fcport_set_tx_bbcredit(port->fcs->bfa, 2208 port->fabric->bb_credit); 2209 } 2210 2211} 2212 2213/** 2214 * Called to handle LOGO received from an existing remote port. 2215 */ 2216static void 2217bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs) 2218{ 2219 rport->reply_oxid = fchs->ox_id; 2220 bfa_trc(rport->fcs, rport->reply_oxid); 2221 2222 rport->prlo = BFA_FALSE; 2223 rport->stats.logo_rcvd++; 2224 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD); 2225} 2226 2227 2228 2229/** 2230 * fcs_rport_public FCS rport public interfaces 2231 */ 2232 2233/** 2234 * Called by bport/vport to create a remote port instance for a discovered 2235 * remote device. 2236 * 2237 * @param[in] port - base port or vport 2238 * @param[in] rpid - remote port ID 2239 * 2240 * @return None 2241 */ 2242struct bfa_fcs_rport_s * 2243bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid) 2244{ 2245 struct bfa_fcs_rport_s *rport; 2246 2247 bfa_trc(port->fcs, rpid); 2248 rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid); 2249 if (!rport) 2250 return NULL; 2251 2252 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND); 2253 return rport; 2254} 2255 2256/** 2257 * Called to create a rport for which only the wwn is known. 2258 * 2259 * @param[in] port - base port 2260 * @param[in] rpwwn - remote port wwn 2261 * 2262 * @return None 2263 */ 2264struct bfa_fcs_rport_s * 2265bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn) 2266{ 2267 struct bfa_fcs_rport_s *rport; 2268 2269 bfa_trc(port->fcs, rpwwn); 2270 rport = bfa_fcs_rport_alloc(port, rpwwn, 0); 2271 if (!rport) 2272 return NULL; 2273 2274 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC); 2275 return rport; 2276} 2277 2278/** 2279 * Called by bport in private loop topology to indicate that a 2280 * rport has been discovered and plogi has been completed. 2281 * 2282 * @param[in] port - base port or vport 2283 * @param[in] rpid - remote port ID 2284 */ 2285void 2286bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs, 2287 struct fc_logi_s *plogi) 2288{ 2289 struct bfa_fcs_rport_s *rport; 2290 2291 rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id); 2292 if (!rport) 2293 return; 2294 2295 bfa_fcs_rport_update(rport, plogi); 2296 2297 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP); 2298} 2299 2300/** 2301 * Called by bport/vport to handle PLOGI received from a new remote port. 2302 * If an existing rport does a plogi, it will be handled separately. 2303 */ 2304void 2305bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs, 2306 struct fc_logi_s *plogi) 2307{ 2308 struct bfa_fcs_rport_s *rport; 2309 2310 rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id); 2311 if (!rport) 2312 return; 2313 2314 bfa_fcs_rport_update(rport, plogi); 2315 2316 rport->reply_oxid = fchs->ox_id; 2317 bfa_trc(rport->fcs, rport->reply_oxid); 2318 2319 rport->stats.plogi_rcvd++; 2320 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD); 2321} 2322 2323static int 2324wwn_compare(wwn_t wwn1, wwn_t wwn2) 2325{ 2326 u8 *b1 = (u8 *) &wwn1; 2327 u8 *b2 = (u8 *) &wwn2; 2328 int i; 2329 2330 for (i = 0; i < sizeof(wwn_t); i++) { 2331 if (b1[i] < b2[i]) 2332 return -1; 2333 if (b1[i] > b2[i]) 2334 return 1; 2335 } 2336 return 0; 2337} 2338 2339/** 2340 * Called by bport/vport to handle PLOGI received from an existing 2341 * remote port. 2342 */ 2343void 2344bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs, 2345 struct fc_logi_s *plogi) 2346{ 2347 /** 2348 * @todo Handle P2P and initiator-initiator. 2349 */ 2350 2351 bfa_fcs_rport_update(rport, plogi); 2352 2353 rport->reply_oxid = rx_fchs->ox_id; 2354 bfa_trc(rport->fcs, rport->reply_oxid); 2355 2356 /** 2357 * In Switched fabric topology, 2358 * PLOGI to each other. If our pwwn is smaller, ignore it, 2359 * if it is not a well known address. 2360 * If the link topology is N2N, 2361 * this Plogi should be accepted. 2362 */ 2363 if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) 2364 && (bfa_fcs_fabric_is_switched(rport->port->fabric)) 2365 && (!BFA_FCS_PID_IS_WKA(rport->pid))) { 2366 bfa_trc(rport->fcs, rport->pid); 2367 return; 2368 } 2369 2370 rport->stats.plogi_rcvd++; 2371 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD); 2372} 2373 2374/** 2375 * Called by bport/vport to delete a remote port instance. 2376 * 2377* Rport delete is called under the following conditions: 2378 * - vport is deleted 2379 * - vf is deleted 2380 * - explicit request from OS to delete rport (vmware) 2381 */ 2382void 2383bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport) 2384{ 2385 bfa_sm_send_event(rport, RPSM_EVENT_DELETE); 2386} 2387 2388/** 2389 * Called by bport/vport to when a target goes offline. 2390 * 2391 */ 2392void 2393bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport) 2394{ 2395 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); 2396} 2397 2398/** 2399 * Called by bport in n2n when a target (attached port) becomes online. 2400 * 2401 */ 2402void 2403bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport) 2404{ 2405 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND); 2406} 2407 2408/** 2409 * Called by bport/vport to notify SCN for the remote port 2410 */ 2411void 2412bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport) 2413{ 2414 2415 rport->stats.rscns++; 2416 bfa_sm_send_event(rport, RPSM_EVENT_SCN); 2417} 2418 2419/** 2420 * Called by fcpim to notify that the ITN cleanup is done. 2421 */ 2422void 2423bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport) 2424{ 2425 bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE); 2426} 2427 2428/** 2429 * Called by fcptm to notify that the ITN cleanup is done. 2430 */ 2431void 2432bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport) 2433{ 2434 bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE); 2435} 2436 2437/** 2438 * This routine BFA callback for bfa_rport_online() call. 2439 * 2440 * param[in] cb_arg - rport struct. 2441 * 2442 * return 2443 * void 2444 * 2445* Special Considerations: 2446 * 2447 * note 2448 */ 2449void 2450bfa_cb_rport_online(void *cbarg) 2451{ 2452 2453 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; 2454 2455 bfa_trc(rport->fcs, rport->pwwn); 2456 bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE); 2457} 2458 2459/** 2460 * This routine BFA callback for bfa_rport_offline() call. 2461 * 2462 * param[in] rport - 2463 * 2464 * return 2465 * void 2466 * 2467 * Special Considerations: 2468 * 2469 * note 2470 */ 2471void 2472bfa_cb_rport_offline(void *cbarg) 2473{ 2474 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; 2475 2476 bfa_trc(rport->fcs, rport->pwwn); 2477 bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE); 2478} 2479 2480/** 2481 * This routine is a static BFA callback when there is a QoS flow_id 2482 * change notification 2483 * 2484 * @param[in] rport - 2485 * 2486 * @return void 2487 * 2488 * Special Considerations: 2489 * 2490 * @note 2491 */ 2492void 2493bfa_cb_rport_qos_scn_flowid(void *cbarg, 2494 struct bfa_rport_qos_attr_s old_qos_attr, 2495 struct bfa_rport_qos_attr_s new_qos_attr) 2496{ 2497 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; 2498 struct bfa_rport_aen_data_s aen_data; 2499 2500 bfa_trc(rport->fcs, rport->pwwn); 2501 aen_data.priv.qos = new_qos_attr; 2502 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data); 2503} 2504 2505/** 2506 * This routine is a static BFA callback when there is a QoS priority 2507 * change notification 2508 * 2509 * @param[in] rport - 2510 * 2511 * @return void 2512 * 2513 * Special Considerations: 2514 * 2515 * @note 2516 */ 2517void 2518bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr, 2519 struct bfa_rport_qos_attr_s new_qos_attr) 2520{ 2521 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; 2522 struct bfa_rport_aen_data_s aen_data; 2523 2524 bfa_trc(rport->fcs, rport->pwwn); 2525 aen_data.priv.qos = new_qos_attr; 2526 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data); 2527} 2528 2529/** 2530 * Called to process any unsolicted frames from this remote port 2531 */ 2532void 2533bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport) 2534{ 2535 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); 2536} 2537 2538/** 2539 * Called to process any unsolicted frames from this remote port 2540 */ 2541void 2542bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, 2543 u16 len) 2544{ 2545 struct bfa_fcs_port_s *port = rport->port; 2546 struct fc_els_cmd_s *els_cmd; 2547 2548 bfa_trc(rport->fcs, fchs->s_id); 2549 bfa_trc(rport->fcs, fchs->d_id); 2550 bfa_trc(rport->fcs, fchs->type); 2551 2552 if (fchs->type != FC_TYPE_ELS) 2553 return; 2554 2555 els_cmd = (struct fc_els_cmd_s *) (fchs + 1); 2556 2557 bfa_trc(rport->fcs, els_cmd->els_code); 2558 2559 switch (els_cmd->els_code) { 2560 case FC_ELS_LOGO: 2561 bfa_fcs_rport_process_logo(rport, fchs); 2562 break; 2563 2564 case FC_ELS_ADISC: 2565 bfa_fcs_rport_process_adisc(rport, fchs, len); 2566 break; 2567 2568 case FC_ELS_PRLO: 2569 if (bfa_fcs_port_is_initiator(port)) 2570 bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len); 2571 2572 if (bfa_fcs_port_is_target(port)) 2573 bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len); 2574 break; 2575 2576 case FC_ELS_PRLI: 2577 bfa_fcs_rport_process_prli(rport, fchs, len); 2578 break; 2579 2580 case FC_ELS_RPSC: 2581 bfa_fcs_rport_process_rpsc(rport, fchs, len); 2582 break; 2583 2584 default: 2585 bfa_fcs_rport_send_ls_rjt(rport, fchs, 2586 FC_LS_RJT_RSN_CMD_NOT_SUPP, 2587 FC_LS_RJT_EXP_NO_ADDL_INFO); 2588 break; 2589 } 2590} 2591 2592/* Send best case acc to prlo */ 2593static void 2594bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport) 2595{ 2596 struct bfa_fcs_port_s *port = rport->port; 2597 struct fchs_s fchs; 2598 struct bfa_fcxp_s *fcxp; 2599 int len; 2600 2601 bfa_trc(rport->fcs, rport->pid); 2602 2603 fcxp = bfa_fcs_fcxp_alloc(port->fcs); 2604 if (!fcxp) 2605 return; 2606 2607 len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), 2608 rport->pid, bfa_fcs_port_get_fcid(port), 2609 rport->reply_oxid, 0); 2610 2611 bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, 2612 port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, 2613 NULL, NULL, FC_MAX_PDUSZ, 0); 2614} 2615 2616/* 2617 * Send a LS reject 2618 */ 2619static void 2620bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs, 2621 u8 reason_code, u8 reason_code_expl) 2622{ 2623 struct bfa_fcs_port_s *port = rport->port; 2624 struct fchs_s fchs; 2625 struct bfa_fcxp_s *fcxp; 2626 int len; 2627 2628 bfa_trc(rport->fcs, rx_fchs->s_id); 2629 2630 fcxp = bfa_fcs_fcxp_alloc(rport->fcs); 2631 if (!fcxp) 2632 return; 2633 2634 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, 2635 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, 2636 reason_code, reason_code_expl); 2637 2638 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 2639 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); 2640} 2641 2642/** 2643 * Return state of rport. 2644 */ 2645int 2646bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport) 2647{ 2648 return bfa_sm_to_state(rport_sm_table, rport->sm); 2649} 2650 2651/** 2652 * Called by the Driver to set rport delete/ageout timeout 2653 * 2654 * param[in] rport timeout value in seconds. 2655 * 2656 * return None 2657 */ 2658void 2659bfa_fcs_rport_set_del_timeout(u8 rport_tmo) 2660{ 2661 /* 2662 * convert to Millisecs 2663 */ 2664 if (rport_tmo > 0) 2665 bfa_fcs_rport_del_timeout = rport_tmo * 1000; 2666} 2667 2668void 2669bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id) 2670{ 2671 bfa_trc(rport->fcs, rport->pid); 2672 2673 rport->prlo = BFA_TRUE; 2674 rport->reply_oxid = ox_id; 2675 bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD); 2676} 2677