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