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                /* fall through */
 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                /* fall through */
 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                /* fall through */
 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                /* fall through */
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                /* fall through */
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                /* fall through */
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                /* fall through */
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        struct fc_adisc_s       *adisc;
2244
2245        bfa_trc(port->fcs, rx_fchs->s_id);
2246        bfa_trc(port->fcs, rx_fchs->d_id);
2247
2248        rport->stats.adisc_rcvd++;
2249
2250        adisc = (struct fc_adisc_s *) (rx_fchs + 1);
2251
2252        /*
2253         * Accept if the itnim for this rport is online.
2254         * Else reject the ADISC.
2255         */
2256        if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
2257
2258                fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
2259                if (!fcxp)
2260                        return;
2261
2262                len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2263                         rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2264                         rx_fchs->ox_id, port->port_cfg.pwwn,
2265                         port->port_cfg.nwwn);
2266
2267                bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
2268                                BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
2269                                FC_MAX_PDUSZ, 0);
2270        } else {
2271                rport->stats.adisc_rejected++;
2272                bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
2273                                          FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
2274                                          FC_LS_RJT_EXP_LOGIN_REQUIRED);
2275        }
2276}
2277
2278static void
2279bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
2280{
2281        struct bfa_fcs_lport_s *port = rport->port;
2282        struct bfa_rport_info_s rport_info;
2283
2284        rport_info.pid = rport->pid;
2285        rport_info.local_pid = port->pid;
2286        rport_info.lp_tag = port->lp_tag;
2287        rport_info.vf_id = port->fabric->vf_id;
2288        rport_info.vf_en = port->fabric->is_vf;
2289        rport_info.fc_class = rport->fc_cos;
2290        rport_info.cisc = rport->cisc;
2291        rport_info.max_frmsz = rport->maxfrsize;
2292        bfa_rport_online(rport->bfa_rport, &rport_info);
2293}
2294
2295static void
2296bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport)
2297{
2298        if (rport->bfa_rport)
2299                bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
2300        else
2301                bfa_cb_rport_offline(rport);
2302}
2303
2304static struct bfa_fcs_rport_s *
2305bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
2306{
2307        struct bfa_fcs_s        *fcs = port->fcs;
2308        struct bfa_fcs_rport_s *rport;
2309        struct bfad_rport_s     *rport_drv;
2310
2311        /*
2312         * allocate rport
2313         */
2314        if (fcs->num_rport_logins >= bfa_fcs_rport_max_logins) {
2315                bfa_trc(fcs, rpid);
2316                return NULL;
2317        }
2318
2319        if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
2320                != BFA_STATUS_OK) {
2321                bfa_trc(fcs, rpid);
2322                return NULL;
2323        }
2324
2325        /*
2326         * Initialize r-port
2327         */
2328        rport->port = port;
2329        rport->fcs = fcs;
2330        rport->rp_drv = rport_drv;
2331        rport->pid = rpid;
2332        rport->pwwn = pwwn;
2333        rport->old_pid = 0;
2334
2335        rport->bfa_rport = NULL;
2336
2337        /*
2338         * allocate FC-4s
2339         */
2340        WARN_ON(!bfa_fcs_lport_is_initiator(port));
2341
2342        if (bfa_fcs_lport_is_initiator(port)) {
2343                rport->itnim = bfa_fcs_itnim_create(rport);
2344                if (!rport->itnim) {
2345                        bfa_trc(fcs, rpid);
2346                        kfree(rport_drv);
2347                        return NULL;
2348                }
2349        }
2350
2351        bfa_fcs_lport_add_rport(port, rport);
2352        fcs->num_rport_logins++;
2353
2354        bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
2355
2356        /* Initialize the Rport Features(RPF) Sub Module  */
2357        if (!BFA_FCS_PID_IS_WKA(rport->pid))
2358                bfa_fcs_rpf_init(rport);
2359
2360        return rport;
2361}
2362
2363
2364static void
2365bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
2366{
2367        struct bfa_fcs_lport_s *port = rport->port;
2368        struct bfa_fcs_s *fcs = port->fcs;
2369
2370        /*
2371         * - delete FC-4s
2372         * - delete BFA rport
2373         * - remove from queue of rports
2374         */
2375        rport->plogi_pending = BFA_FALSE;
2376
2377        if (bfa_fcs_lport_is_initiator(port)) {
2378                bfa_fcs_itnim_delete(rport->itnim);
2379                if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
2380                        bfa_fcs_rpf_rport_offline(rport);
2381        }
2382
2383        if (rport->bfa_rport) {
2384                bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
2385                rport->bfa_rport = NULL;
2386        }
2387
2388        bfa_fcs_lport_del_rport(port, rport);
2389        fcs->num_rport_logins--;
2390        kfree(rport->rp_drv);
2391}
2392
2393static void
2394bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
2395                        enum bfa_rport_aen_event event,
2396                        struct bfa_rport_aen_data_s *data)
2397{
2398        struct bfa_fcs_lport_s *port = rport->port;
2399        struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2400        struct bfa_aen_entry_s  *aen_entry;
2401
2402        bfad_get_aen_entry(bfad, aen_entry);
2403        if (!aen_entry)
2404                return;
2405
2406        if (event == BFA_RPORT_AEN_QOS_PRIO)
2407                aen_entry->aen_data.rport.priv.qos = data->priv.qos;
2408        else if (event == BFA_RPORT_AEN_QOS_FLOWID)
2409                aen_entry->aen_data.rport.priv.qos = data->priv.qos;
2410
2411        aen_entry->aen_data.rport.vf_id = rport->port->fabric->vf_id;
2412        aen_entry->aen_data.rport.ppwwn = bfa_fcs_lport_get_pwwn(
2413                                        bfa_fcs_get_base_port(rport->fcs));
2414        aen_entry->aen_data.rport.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);
2415        aen_entry->aen_data.rport.rpwwn = rport->pwwn;
2416
2417        /* Send the AEN notification */
2418        bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,
2419                                  BFA_AEN_CAT_RPORT, event);
2420}
2421
2422static void
2423bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport)
2424{
2425        if ((!rport->pid) || (!rport->pwwn)) {
2426                bfa_trc(rport->fcs, rport->pid);
2427                bfa_sm_fault(rport->fcs, rport->pid);
2428        }
2429
2430        bfa_sm_send_event(rport->itnim, BFA_FCS_ITNIM_SM_FCS_ONLINE);
2431}
2432
2433static void
2434bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport)
2435{
2436        struct bfa_fcs_lport_s *port = rport->port;
2437        struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2438        char    lpwwn_buf[BFA_STRING_32];
2439        char    rpwwn_buf[BFA_STRING_32];
2440
2441        rport->stats.onlines++;
2442
2443        if ((!rport->pid) || (!rport->pwwn)) {
2444                bfa_trc(rport->fcs, rport->pid);
2445                bfa_sm_fault(rport->fcs, rport->pid);
2446        }
2447
2448        if (bfa_fcs_lport_is_initiator(port)) {
2449                bfa_fcs_itnim_brp_online(rport->itnim);
2450                if (!BFA_FCS_PID_IS_WKA(rport->pid))
2451                        bfa_fcs_rpf_rport_online(rport);
2452        };
2453
2454        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
2455        wwn2str(rpwwn_buf, rport->pwwn);
2456        if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
2457                BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2458                "Remote port (WWN = %s) online for logical port (WWN = %s)\n",
2459                rpwwn_buf, lpwwn_buf);
2460                bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
2461        }
2462}
2463
2464static void
2465bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport)
2466{
2467        if (!BFA_FCS_PID_IS_WKA(rport->pid))
2468                bfa_fcs_rpf_rport_offline(rport);
2469
2470        bfa_fcs_itnim_rport_offline(rport->itnim);
2471}
2472
2473static void
2474bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport)
2475{
2476        struct bfa_fcs_lport_s *port = rport->port;
2477        struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2478        char    lpwwn_buf[BFA_STRING_32];
2479        char    rpwwn_buf[BFA_STRING_32];
2480
2481        if (!rport->bfa_rport) {
2482                bfa_fcs_rport_fcs_offline_action(rport);
2483                return;
2484        }
2485
2486        rport->stats.offlines++;
2487
2488        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
2489        wwn2str(rpwwn_buf, rport->pwwn);
2490        if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
2491                if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE) {
2492                        BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2493                                "Remote port (WWN = %s) connectivity lost for "
2494                                "logical port (WWN = %s)\n",
2495                                rpwwn_buf, lpwwn_buf);
2496                        bfa_fcs_rport_aen_post(rport,
2497                                BFA_RPORT_AEN_DISCONNECT, NULL);
2498                } else {
2499                        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2500                                "Remote port (WWN = %s) offlined by "
2501                                "logical port (WWN = %s)\n",
2502                                rpwwn_buf, lpwwn_buf);
2503                        bfa_fcs_rport_aen_post(rport,
2504                                BFA_RPORT_AEN_OFFLINE, NULL);
2505                }
2506        }
2507
2508        if (bfa_fcs_lport_is_initiator(port)) {
2509                bfa_fcs_itnim_rport_offline(rport->itnim);
2510                if (!BFA_FCS_PID_IS_WKA(rport->pid))
2511                        bfa_fcs_rpf_rport_offline(rport);
2512        }
2513}
2514
2515/*
2516 * Update rport parameters from PLOGI or PLOGI accept.
2517 */
2518static void
2519bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
2520{
2521        bfa_fcs_lport_t *port = rport->port;
2522
2523        /*
2524         * - port name
2525         * - node name
2526         */
2527        rport->pwwn = plogi->port_name;
2528        rport->nwwn = plogi->node_name;
2529
2530        /*
2531         * - class of service
2532         */
2533        rport->fc_cos = 0;
2534        if (plogi->class3.class_valid)
2535                rport->fc_cos = FC_CLASS_3;
2536
2537        if (plogi->class2.class_valid)
2538                rport->fc_cos |= FC_CLASS_2;
2539
2540        /*
2541         * - CISC
2542         * - MAX receive frame size
2543         */
2544        rport->cisc = plogi->csp.cisc;
2545        if (be16_to_cpu(plogi->class3.rxsz) < be16_to_cpu(plogi->csp.rxsz))
2546                rport->maxfrsize = be16_to_cpu(plogi->class3.rxsz);
2547        else
2548                rport->maxfrsize = be16_to_cpu(plogi->csp.rxsz);
2549
2550        bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));
2551        bfa_trc(port->fcs, port->fabric->bb_credit);
2552        /*
2553         * Direct Attach P2P mode :
2554         * This is to handle a bug (233476) in IBM targets in Direct Attach
2555         *  Mode. Basically, in FLOGI Accept the target would have
2556         * erroneously set the BB Credit to the value used in the FLOGI
2557         * sent by the HBA. It uses the correct value (its own BB credit)
2558         * in PLOGI.
2559         */
2560        if ((!bfa_fcs_fabric_is_switched(port->fabric))  &&
2561                (be16_to_cpu(plogi->csp.bbcred) < port->fabric->bb_credit)) {
2562
2563                bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));
2564                bfa_trc(port->fcs, port->fabric->bb_credit);
2565
2566                port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
2567                bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
2568                                          port->fabric->bb_credit);
2569        }
2570
2571}
2572
2573/*
2574 *      Called to handle LOGO received from an existing remote port.
2575 */
2576static void
2577bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
2578{
2579        rport->reply_oxid = fchs->ox_id;
2580        bfa_trc(rport->fcs, rport->reply_oxid);
2581
2582        rport->prlo = BFA_FALSE;
2583        rport->stats.logo_rcvd++;
2584        bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
2585}
2586
2587
2588
2589/*
2590 *  fcs_rport_public FCS rport public interfaces
2591 */
2592
2593/*
2594 *      Called by bport/vport to create a remote port instance for a discovered
2595 *      remote device.
2596 *
2597 * @param[in] port      - base port or vport
2598 * @param[in] rpid      - remote port ID
2599 *
2600 * @return None
2601 */
2602struct bfa_fcs_rport_s *
2603bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 rpid)
2604{
2605        struct bfa_fcs_rport_s *rport;
2606
2607        bfa_trc(port->fcs, rpid);
2608        rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
2609        if (!rport)
2610                return NULL;
2611
2612        bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2613        return rport;
2614}
2615
2616/*
2617 * Called to create a rport for which only the wwn is known.
2618 *
2619 * @param[in] port      - base port
2620 * @param[in] rpwwn     - remote port wwn
2621 *
2622 * @return None
2623 */
2624struct bfa_fcs_rport_s *
2625bfa_fcs_rport_create_by_wwn(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
2626{
2627        struct bfa_fcs_rport_s *rport;
2628        bfa_trc(port->fcs, rpwwn);
2629        rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
2630        if (!rport)
2631                return NULL;
2632
2633        bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
2634        return rport;
2635}
2636/*
2637 * Called by bport in private loop topology to indicate that a
2638 * rport has been discovered and plogi has been completed.
2639 *
2640 * @param[in] port      - base port or vport
2641 * @param[in] rpid      - remote port ID
2642 */
2643void
2644bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
2645         struct fc_logi_s *plogi)
2646{
2647        struct bfa_fcs_rport_s *rport;
2648
2649        rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
2650        if (!rport)
2651                return;
2652
2653        bfa_fcs_rport_update(rport, plogi);
2654
2655        bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
2656}
2657
2658/*
2659 *      Called by bport/vport to handle PLOGI received from a new remote port.
2660 *      If an existing rport does a plogi, it will be handled separately.
2661 */
2662void
2663bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
2664                                struct fc_logi_s *plogi)
2665{
2666        struct bfa_fcs_rport_s *rport;
2667
2668        rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
2669        if (!rport)
2670                return;
2671
2672        bfa_fcs_rport_update(rport, plogi);
2673
2674        rport->reply_oxid = fchs->ox_id;
2675        bfa_trc(rport->fcs, rport->reply_oxid);
2676
2677        rport->stats.plogi_rcvd++;
2678        bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2679}
2680
2681/*
2682 *      Called by bport/vport to handle PLOGI received from an existing
2683 *       remote port.
2684 */
2685void
2686bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2687                        struct fc_logi_s *plogi)
2688{
2689        /*
2690         * @todo Handle P2P and initiator-initiator.
2691         */
2692
2693        bfa_fcs_rport_update(rport, plogi);
2694
2695        rport->reply_oxid = rx_fchs->ox_id;
2696        bfa_trc(rport->fcs, rport->reply_oxid);
2697
2698        rport->pid = rx_fchs->s_id;
2699        bfa_trc(rport->fcs, rport->pid);
2700
2701        rport->stats.plogi_rcvd++;
2702        bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2703}
2704
2705
2706/*
2707 *      Called by bport/vport to notify SCN for the remote port
2708 */
2709void
2710bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
2711{
2712        rport->stats.rscns++;
2713        bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);
2714}
2715
2716/*
2717 *      brief
2718 *      This routine BFA callback for bfa_rport_online() call.
2719 *
2720 *      param[in]       cb_arg  -  rport struct.
2721 *
2722 *      return
2723 *              void
2724 *
2725 *      Special Considerations:
2726 *
2727 *      note
2728 */
2729void
2730bfa_cb_rport_online(void *cbarg)
2731{
2732
2733        struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2734
2735        bfa_trc(rport->fcs, rport->pwwn);
2736        bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
2737}
2738
2739/*
2740 *      brief
2741 *      This routine BFA callback for bfa_rport_offline() call.
2742 *
2743 *      param[in]       rport   -
2744 *
2745 *      return
2746 *              void
2747 *
2748 *      Special Considerations:
2749 *
2750 *      note
2751 */
2752void
2753bfa_cb_rport_offline(void *cbarg)
2754{
2755        struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2756
2757        bfa_trc(rport->fcs, rport->pwwn);
2758        bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
2759}
2760
2761/*
2762 *      brief
2763 *      This routine is a static BFA callback when there is a QoS flow_id
2764 *      change notification
2765 *
2766 *      param[in]       rport   -
2767 *
2768 *      return
2769 *              void
2770 *
2771 *      Special Considerations:
2772 *
2773 *      note
2774 */
2775void
2776bfa_cb_rport_qos_scn_flowid(void *cbarg,
2777                struct bfa_rport_qos_attr_s old_qos_attr,
2778                struct bfa_rport_qos_attr_s new_qos_attr)
2779{
2780        struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2781        struct bfa_rport_aen_data_s aen_data;
2782
2783        bfa_trc(rport->fcs, rport->pwwn);
2784        aen_data.priv.qos = new_qos_attr;
2785        bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
2786}
2787
2788void
2789bfa_cb_rport_scn_online(struct bfa_s *bfa)
2790{
2791        struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
2792        struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
2793        struct bfa_fcs_rport_s *rp;
2794        struct list_head *qe;
2795
2796        list_for_each(qe, &port->rport_q) {
2797                rp = (struct bfa_fcs_rport_s *) qe;
2798                bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE);
2799                rp->scn_online = BFA_TRUE;
2800        }
2801
2802        if (bfa_fcs_lport_is_online(port))
2803                bfa_fcs_lport_lip_scn_online(port);
2804}
2805
2806void
2807bfa_cb_rport_scn_no_dev(void *rport)
2808{
2809        struct bfa_fcs_rport_s *rp = rport;
2810
2811        bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
2812        rp->scn_online = BFA_FALSE;
2813}
2814
2815void
2816bfa_cb_rport_scn_offline(struct bfa_s *bfa)
2817{
2818        struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
2819        struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
2820        struct bfa_fcs_rport_s *rp;
2821        struct list_head *qe;
2822
2823        list_for_each(qe, &port->rport_q) {
2824                rp = (struct bfa_fcs_rport_s *) qe;
2825                bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
2826                rp->scn_online = BFA_FALSE;
2827        }
2828}
2829
2830/*
2831 *      brief
2832 *      This routine is a static BFA callback when there is a QoS priority
2833 *      change notification
2834 *
2835 *      param[in]       rport   -
2836 *
2837 *      return
2838 *              void
2839 *
2840 *      Special Considerations:
2841 *
2842 *      note
2843 */
2844void
2845bfa_cb_rport_qos_scn_prio(void *cbarg,
2846                struct bfa_rport_qos_attr_s old_qos_attr,
2847                struct bfa_rport_qos_attr_s new_qos_attr)
2848{
2849        struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2850        struct bfa_rport_aen_data_s aen_data;
2851
2852        bfa_trc(rport->fcs, rport->pwwn);
2853        aen_data.priv.qos = new_qos_attr;
2854        bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
2855}
2856
2857/*
2858 *              Called to process any unsolicted frames from this remote port
2859 */
2860void
2861bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
2862                        struct fchs_s *fchs, u16 len)
2863{
2864        struct bfa_fcs_lport_s *port = rport->port;
2865        struct fc_els_cmd_s     *els_cmd;
2866
2867        bfa_trc(rport->fcs, fchs->s_id);
2868        bfa_trc(rport->fcs, fchs->d_id);
2869        bfa_trc(rport->fcs, fchs->type);
2870
2871        if (fchs->type != FC_TYPE_ELS)
2872                return;
2873
2874        els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
2875
2876        bfa_trc(rport->fcs, els_cmd->els_code);
2877
2878        switch (els_cmd->els_code) {
2879        case FC_ELS_LOGO:
2880                bfa_stats(port, plogi_rcvd);
2881                bfa_fcs_rport_process_logo(rport, fchs);
2882                break;
2883
2884        case FC_ELS_ADISC:
2885                bfa_stats(port, adisc_rcvd);
2886                bfa_fcs_rport_process_adisc(rport, fchs, len);
2887                break;
2888
2889        case FC_ELS_PRLO:
2890                bfa_stats(port, prlo_rcvd);
2891                if (bfa_fcs_lport_is_initiator(port))
2892                        bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
2893                break;
2894
2895        case FC_ELS_PRLI:
2896                bfa_stats(port, prli_rcvd);
2897                bfa_fcs_rport_process_prli(rport, fchs, len);
2898                break;
2899
2900        case FC_ELS_RPSC:
2901                bfa_stats(port, rpsc_rcvd);
2902                bfa_fcs_rport_process_rpsc(rport, fchs, len);
2903                break;
2904
2905        default:
2906                bfa_stats(port, un_handled_els_rcvd);
2907                bfa_fcs_rport_send_ls_rjt(rport, fchs,
2908                                          FC_LS_RJT_RSN_CMD_NOT_SUPP,
2909                                          FC_LS_RJT_EXP_NO_ADDL_INFO);
2910                break;
2911        }
2912}
2913
2914/* send best case  acc to prlo */
2915static void
2916bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
2917{
2918        struct bfa_fcs_lport_s *port = rport->port;
2919        struct fchs_s   fchs;
2920        struct bfa_fcxp_s *fcxp;
2921        int             len;
2922
2923        bfa_trc(rport->fcs, rport->pid);
2924
2925        fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
2926        if (!fcxp)
2927                return;
2928        len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2929                        rport->pid, bfa_fcs_lport_get_fcid(port),
2930                        rport->reply_oxid, 0);
2931
2932        bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
2933                port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
2934                NULL, NULL, FC_MAX_PDUSZ, 0);
2935}
2936
2937/*
2938 * Send a LS reject
2939 */
2940static void
2941bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2942                          u8 reason_code, u8 reason_code_expl)
2943{
2944        struct bfa_fcs_lport_s *port = rport->port;
2945        struct fchs_s   fchs;
2946        struct bfa_fcxp_s *fcxp;
2947        int             len;
2948
2949        bfa_trc(rport->fcs, rx_fchs->s_id);
2950
2951        fcxp = bfa_fcs_fcxp_alloc(rport->fcs, BFA_FALSE);
2952        if (!fcxp)
2953                return;
2954
2955        len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2956                                rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2957                                rx_fchs->ox_id, reason_code, reason_code_expl);
2958
2959        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
2960                        BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
2961                        FC_MAX_PDUSZ, 0);
2962}
2963
2964/*
2965 * Return state of rport.
2966 */
2967int
2968bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
2969{
2970        return bfa_sm_to_state(rport_sm_table, rport->sm);
2971}
2972
2973
2974/*
2975 *      brief
2976 *               Called by the Driver to set rport delete/ageout timeout
2977 *
2978 *      param[in]               rport timeout value in seconds.
2979 *
2980 *      return None
2981 */
2982void
2983bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
2984{
2985        /* convert to Millisecs */
2986        if (rport_tmo > 0)
2987                bfa_fcs_rport_del_timeout = rport_tmo * 1000;
2988}
2989void
2990bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
2991{
2992        bfa_trc(rport->fcs, rport->pid);
2993
2994        rport->prlo = BFA_TRUE;
2995        rport->reply_oxid = ox_id;
2996        bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
2997}
2998
2999/*
3000 * Called by BFAD to set the max limit on number of bfa_fcs_rport allocation
3001 * which limits number of concurrent logins to remote ports
3002 */
3003void
3004bfa_fcs_rport_set_max_logins(u32 max_logins)
3005{
3006        if (max_logins > 0)
3007                bfa_fcs_rport_max_logins = max_logins;
3008}
3009
3010void
3011bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
3012                struct bfa_rport_attr_s *rport_attr)
3013{
3014        struct bfa_rport_qos_attr_s qos_attr;
3015        struct bfa_fcs_lport_s *port = rport->port;
3016        bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
3017        struct bfa_port_attr_s port_attr;
3018
3019        bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);
3020
3021        memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
3022        memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
3023
3024        rport_attr->pid = rport->pid;
3025        rport_attr->pwwn = rport->pwwn;
3026        rport_attr->nwwn = rport->nwwn;
3027        rport_attr->cos_supported = rport->fc_cos;
3028        rport_attr->df_sz = rport->maxfrsize;
3029        rport_attr->state = bfa_fcs_rport_get_state(rport);
3030        rport_attr->fc_cos = rport->fc_cos;
3031        rport_attr->cisc = rport->cisc;
3032        rport_attr->scsi_function = rport->scsi_function;
3033        rport_attr->curr_speed  = rport->rpf.rpsc_speed;
3034        rport_attr->assigned_speed  = rport->rpf.assigned_speed;
3035
3036        if (rport->bfa_rport) {
3037                qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
3038                qos_attr.qos_flow_id =
3039                        cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
3040        }
3041        rport_attr->qos_attr = qos_attr;
3042
3043        rport_attr->trl_enforced = BFA_FALSE;
3044        if (bfa_fcport_is_ratelim(port->fcs->bfa) &&
3045            (rport->scsi_function == BFA_RPORT_TARGET)) {
3046                if (rport_speed == BFA_PORT_SPEED_UNKNOWN)
3047                        rport_speed =
3048                                bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
3049
3050                if ((bfa_fcs_lport_get_rport_max_speed(port) !=
3051                    BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))
3052                        rport_attr->trl_enforced = BFA_TRUE;
3053        }
3054}
3055
3056/*
3057 * Remote port implementation.
3058 */
3059
3060/*
3061 *  fcs_rport_api FCS rport API.
3062 */
3063
3064struct bfa_fcs_rport_s *
3065bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
3066{
3067        struct bfa_fcs_rport_s *rport;
3068
3069        rport = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
3070        if (rport == NULL) {
3071                /*
3072                 * TBD Error handling
3073                 */
3074        }
3075
3076        return rport;
3077}
3078
3079struct bfa_fcs_rport_s *
3080bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)
3081{
3082        struct bfa_fcs_rport_s *rport;
3083
3084        rport = bfa_fcs_lport_get_rport_by_nwwn(port, rnwwn);
3085        if (rport == NULL) {
3086                /*
3087                 * TBD Error handling
3088                 */
3089        }
3090
3091        return rport;
3092}
3093
3094/*
3095 * Remote port features (RPF) implementation.
3096 */
3097
3098#define BFA_FCS_RPF_RETRIES     (3)
3099#define BFA_FCS_RPF_RETRY_TIMEOUT  (1000) /* 1 sec (In millisecs) */
3100
3101static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
3102                                struct bfa_fcxp_s *fcxp_alloced);
3103static void     bfa_fcs_rpf_rpsc2_response(void *fcsarg,
3104                        struct bfa_fcxp_s *fcxp,
3105                        void *cbarg,
3106                        bfa_status_t req_status,
3107                        u32 rsp_len,
3108                        u32 resid_len,
3109                        struct fchs_s *rsp_fchs);
3110
3111static void     bfa_fcs_rpf_timeout(void *arg);
3112
3113/*
3114 *  fcs_rport_ftrs_sm FCS rport state machine events
3115 */
3116
3117enum rpf_event {
3118        RPFSM_EVENT_RPORT_OFFLINE  = 1, /* Rport offline                */
3119        RPFSM_EVENT_RPORT_ONLINE   = 2, /* Rport online                 */
3120        RPFSM_EVENT_FCXP_SENT      = 3, /* Frame from has been sent     */
3121        RPFSM_EVENT_TIMEOUT        = 4, /* Rport SM timeout event       */
3122        RPFSM_EVENT_RPSC_COMP      = 5,
3123        RPFSM_EVENT_RPSC_FAIL      = 6,
3124        RPFSM_EVENT_RPSC_ERROR     = 7,
3125};
3126
3127static void     bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
3128                                        enum rpf_event event);
3129static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
3130                                       enum rpf_event event);
3131static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
3132                                       enum rpf_event event);
3133static void     bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
3134                                        enum rpf_event event);
3135static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
3136                                        enum rpf_event event);
3137static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
3138                                        enum rpf_event event);
3139
3140static void
3141bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3142{
3143        struct bfa_fcs_rport_s *rport = rpf->rport;
3144        struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
3145
3146        bfa_trc(rport->fcs, rport->pwwn);
3147        bfa_trc(rport->fcs, rport->pid);
3148        bfa_trc(rport->fcs, event);
3149
3150        switch (event) {
3151        case RPFSM_EVENT_RPORT_ONLINE:
3152                /* Send RPSC2 to a Brocade fabric only. */
3153                if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
3154                        ((rport->port->fabric->lps->brcd_switch) ||
3155                        (bfa_fcs_fabric_get_switch_oui(fabric) ==
3156                                                BFA_FCS_BRCD_SWITCH_OUI))) {
3157                        bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
3158                        rpf->rpsc_retries = 0;
3159                        bfa_fcs_rpf_send_rpsc2(rpf, NULL);
3160                }
3161                break;
3162
3163        case RPFSM_EVENT_RPORT_OFFLINE:
3164                break;
3165
3166        default:
3167                bfa_sm_fault(rport->fcs, event);
3168        }
3169}
3170
3171static void
3172bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3173{
3174        struct bfa_fcs_rport_s *rport = rpf->rport;
3175
3176        bfa_trc(rport->fcs, event);
3177
3178        switch (event) {
3179        case RPFSM_EVENT_FCXP_SENT:
3180                bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
3181                break;
3182
3183        case RPFSM_EVENT_RPORT_OFFLINE:
3184                bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3185                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
3186                rpf->rpsc_retries = 0;
3187                break;
3188
3189        default:
3190                bfa_sm_fault(rport->fcs, event);
3191        }
3192}
3193
3194static void
3195bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3196{
3197        struct bfa_fcs_rport_s *rport = rpf->rport;
3198
3199        bfa_trc(rport->fcs, rport->pid);
3200        bfa_trc(rport->fcs, event);
3201
3202        switch (event) {
3203        case RPFSM_EVENT_RPSC_COMP:
3204                bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
3205                /* Update speed info in f/w via BFA */
3206                if (rpf->rpsc_speed != BFA_PORT_SPEED_UNKNOWN)
3207                        bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
3208                else if (rpf->assigned_speed != BFA_PORT_SPEED_UNKNOWN)
3209                        bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
3210                break;
3211
3212        case RPFSM_EVENT_RPSC_FAIL:
3213                /* RPSC not supported by rport */
3214                bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
3215                break;
3216
3217        case RPFSM_EVENT_RPSC_ERROR:
3218                /* need to retry...delayed a bit. */
3219                if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
3220                        bfa_timer_start(rport->fcs->bfa, &rpf->timer,
3221                                    bfa_fcs_rpf_timeout, rpf,
3222                                    BFA_FCS_RPF_RETRY_TIMEOUT);
3223                        bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
3224                } else {
3225                        bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
3226                }
3227                break;
3228
3229        case RPFSM_EVENT_RPORT_OFFLINE:
3230                bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3231                bfa_fcxp_discard(rpf->fcxp);
3232                rpf->rpsc_retries = 0;
3233                break;
3234
3235        default:
3236                bfa_sm_fault(rport->fcs, event);
3237        }
3238}
3239
3240static void
3241bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3242{
3243        struct bfa_fcs_rport_s *rport = rpf->rport;
3244
3245        bfa_trc(rport->fcs, rport->pid);
3246        bfa_trc(rport->fcs, event);
3247
3248        switch (event) {
3249        case RPFSM_EVENT_TIMEOUT:
3250                /* re-send the RPSC */
3251                bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
3252                bfa_fcs_rpf_send_rpsc2(rpf, NULL);
3253                break;
3254
3255        case RPFSM_EVENT_RPORT_OFFLINE:
3256                bfa_timer_stop(&rpf->timer);
3257                bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3258                rpf->rpsc_retries = 0;
3259                break;
3260
3261        default:
3262                bfa_sm_fault(rport->fcs, event);
3263        }
3264}
3265
3266static void
3267bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3268{
3269        struct bfa_fcs_rport_s *rport = rpf->rport;
3270
3271        bfa_trc(rport->fcs, rport->pwwn);
3272        bfa_trc(rport->fcs, rport->pid);
3273        bfa_trc(rport->fcs, event);
3274
3275        switch (event) {
3276        case RPFSM_EVENT_RPORT_OFFLINE:
3277                bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3278                rpf->rpsc_retries = 0;
3279                break;
3280
3281        default:
3282                bfa_sm_fault(rport->fcs, event);
3283        }
3284}
3285
3286static void
3287bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3288{
3289        struct bfa_fcs_rport_s *rport = rpf->rport;
3290
3291        bfa_trc(rport->fcs, rport->pwwn);
3292        bfa_trc(rport->fcs, rport->pid);
3293        bfa_trc(rport->fcs, event);
3294
3295        switch (event) {
3296        case RPFSM_EVENT_RPORT_ONLINE:
3297                bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
3298                bfa_fcs_rpf_send_rpsc2(rpf, NULL);
3299                break;
3300
3301        case RPFSM_EVENT_RPORT_OFFLINE:
3302                break;
3303
3304        default:
3305                bfa_sm_fault(rport->fcs, event);
3306        }
3307}
3308/*
3309 * Called when Rport is created.
3310 */
3311void
3312bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
3313{
3314        struct bfa_fcs_rpf_s *rpf = &rport->rpf;
3315
3316        bfa_trc(rport->fcs, rport->pid);
3317        rpf->rport = rport;
3318
3319        bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
3320}
3321
3322/*
3323 * Called when Rport becomes online
3324 */
3325void
3326bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
3327{
3328        bfa_trc(rport->fcs, rport->pid);
3329
3330        if (__fcs_min_cfg(rport->port->fcs))
3331                return;
3332
3333        if (bfa_fcs_fabric_is_switched(rport->port->fabric))
3334                bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
3335}
3336
3337/*
3338 * Called when Rport becomes offline
3339 */
3340void
3341bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
3342{
3343        bfa_trc(rport->fcs, rport->pid);
3344
3345        if (__fcs_min_cfg(rport->port->fcs))
3346                return;
3347
3348        rport->rpf.rpsc_speed = 0;
3349        bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
3350}
3351
3352static void
3353bfa_fcs_rpf_timeout(void *arg)
3354{
3355        struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
3356        struct bfa_fcs_rport_s *rport = rpf->rport;
3357
3358        bfa_trc(rport->fcs, rport->pid);
3359        bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
3360}
3361
3362static void
3363bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3364{
3365        struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;
3366        struct bfa_fcs_rport_s *rport = rpf->rport;
3367        struct bfa_fcs_lport_s *port = rport->port;
3368        struct fchs_s   fchs;
3369        int             len;
3370        struct bfa_fcxp_s *fcxp;
3371
3372        bfa_trc(rport->fcs, rport->pwwn);
3373
3374        fcxp = fcxp_alloced ? fcxp_alloced :
3375               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3376        if (!fcxp) {
3377                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
3378                                bfa_fcs_rpf_send_rpsc2, rpf, BFA_TRUE);
3379                return;
3380        }
3381        rpf->fcxp = fcxp;
3382
3383        len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
3384                            bfa_fcs_lport_get_fcid(port), &rport->pid, 1);
3385
3386        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3387                          FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
3388                          rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
3389        rport->stats.rpsc_sent++;
3390        bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
3391
3392}
3393
3394static void
3395bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
3396                            bfa_status_t req_status, u32 rsp_len,
3397                            u32 resid_len, struct fchs_s *rsp_fchs)
3398{
3399        struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
3400        struct bfa_fcs_rport_s *rport = rpf->rport;
3401        struct fc_ls_rjt_s *ls_rjt;
3402        struct fc_rpsc2_acc_s *rpsc2_acc;
3403        u16     num_ents;
3404
3405        bfa_trc(rport->fcs, req_status);
3406
3407        if (req_status != BFA_STATUS_OK) {
3408                bfa_trc(rport->fcs, req_status);
3409                if (req_status == BFA_STATUS_ETIMER)
3410                        rport->stats.rpsc_failed++;
3411                bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3412                return;
3413        }
3414
3415        rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
3416        if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
3417                rport->stats.rpsc_accs++;
3418                num_ents = be16_to_cpu(rpsc2_acc->num_pids);
3419                bfa_trc(rport->fcs, num_ents);
3420                if (num_ents > 0) {
3421                        WARN_ON(be32_to_cpu(rpsc2_acc->port_info[0].pid) !=
3422                                                bfa_ntoh3b(rport->pid));
3423                        bfa_trc(rport->fcs,
3424                                be32_to_cpu(rpsc2_acc->port_info[0].pid));
3425                        bfa_trc(rport->fcs,
3426                                be16_to_cpu(rpsc2_acc->port_info[0].speed));
3427                        bfa_trc(rport->fcs,
3428                                be16_to_cpu(rpsc2_acc->port_info[0].index));
3429                        bfa_trc(rport->fcs,
3430                                rpsc2_acc->port_info[0].type);
3431
3432                        if (rpsc2_acc->port_info[0].speed == 0) {
3433                                bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3434                                return;
3435                        }
3436
3437                        rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
3438                                be16_to_cpu(rpsc2_acc->port_info[0].speed));
3439
3440                        bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
3441                }
3442        } else {
3443                ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3444                bfa_trc(rport->fcs, ls_rjt->reason_code);
3445                bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
3446                rport->stats.rpsc_rejects++;
3447                if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
3448                        bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
3449                else
3450                        bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3451        }
3452}
3453