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