linux/drivers/scsi/bfa/bfa_fcs_lport.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
   4 * Copyright (c) 2014- QLogic Corporation.
   5 * All rights reserved
   6 * www.qlogic.com
   7 *
   8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
   9 */
  10
  11#include "bfad_drv.h"
  12#include "bfad_im.h"
  13#include "bfa_fcs.h"
  14#include "bfa_fcbuild.h"
  15#include "bfa_fc.h"
  16
  17BFA_TRC_FILE(FCS, PORT);
  18
  19/*
  20 * ALPA to LIXA bitmap mapping
  21 *
  22 * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
  23 * is for L_bit (login required) and is filled as ALPA 0x00 here.
  24 */
  25static const u8 loop_alpa_map[] = {
  26        0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, /* Word 0 Bits 31..24 */
  27        0x17, 0x18, 0x1B, 0x1D, 0x1E, 0x1F, 0x23, 0x25, /* Word 0 Bits 23..16 */
  28        0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, /* Word 0 Bits 15..08 */
  29        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, /* Word 0 Bits 07..00 */
  30
  31        0x3C, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, /* Word 1 Bits 31..24 */
  32        0x4C, 0x4D, 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, /* Word 1 Bits 23..16 */
  33        0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x67, /* Word 1 Bits 15..08 */
  34        0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, /* Word 1 Bits 07..00 */
  35
  36        0x73, 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, /* Word 2 Bits 31..24 */
  37        0x81, 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, /* Word 2 Bits 23..16 */
  38        0x9B, 0x9D, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, /* Word 2 Bits 15..08 */
  39        0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, /* Word 2 Bits 07..00 */
  40
  41        0xB3, 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xC3, /* Word 3 Bits 31..24 */
  42        0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, /* Word 3 Bits 23..16 */
  43        0xCE, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, /* Word 3 Bits 15..08 */
  44        0xDA, 0xDC, 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF, /* Word 3 Bits 07..00 */
  45};
  46
  47static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
  48                                         struct fchs_s *rx_fchs, u8 reason_code,
  49                                         u8 reason_code_expl);
  50static void     bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
  51                        struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
  52static void     bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
  53static void     bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
  54static void     bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
  55static void     bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
  56static void     bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
  57static void     bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
  58static void     bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
  59                        struct fchs_s *rx_fchs,
  60                        struct fc_echo_s *echo, u16 len);
  61static void     bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
  62                        struct fchs_s *rx_fchs,
  63                        struct fc_rnid_cmd_s *rnid, u16 len);
  64static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
  65                        struct fc_rnid_general_topology_data_s *gen_topo_data);
  66
  67static void     bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
  68static void     bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
  69static void     bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
  70
  71static void     bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
  72static void     bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
  73static void     bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
  74
  75static void     bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port);
  76static void     bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port);
  77static void     bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port);
  78
  79static struct {
  80        void            (*init) (struct bfa_fcs_lport_s *port);
  81        void            (*online) (struct bfa_fcs_lport_s *port);
  82        void            (*offline) (struct bfa_fcs_lport_s *port);
  83} __port_action[] = {
  84        [BFA_FCS_FABRIC_UNKNOWN] = {
  85                .init = bfa_fcs_lport_unknown_init,
  86                .online = bfa_fcs_lport_unknown_online,
  87                .offline = bfa_fcs_lport_unknown_offline
  88        },
  89        [BFA_FCS_FABRIC_SWITCHED] = {
  90                .init = bfa_fcs_lport_fab_init,
  91                .online = bfa_fcs_lport_fab_online,
  92                .offline = bfa_fcs_lport_fab_offline
  93        },
  94        [BFA_FCS_FABRIC_N2N] = {
  95                .init = bfa_fcs_lport_n2n_init,
  96                .online = bfa_fcs_lport_n2n_online,
  97                .offline = bfa_fcs_lport_n2n_offline
  98        },
  99        [BFA_FCS_FABRIC_LOOP] = {
 100                .init = bfa_fcs_lport_loop_init,
 101                .online = bfa_fcs_lport_loop_online,
 102                .offline = bfa_fcs_lport_loop_offline
 103        },
 104};
 105
 106/*
 107 *  fcs_port_sm FCS logical port state machine
 108 */
 109
 110enum bfa_fcs_lport_event {
 111        BFA_FCS_PORT_SM_CREATE = 1,
 112        BFA_FCS_PORT_SM_ONLINE = 2,
 113        BFA_FCS_PORT_SM_OFFLINE = 3,
 114        BFA_FCS_PORT_SM_DELETE = 4,
 115        BFA_FCS_PORT_SM_DELRPORT = 5,
 116        BFA_FCS_PORT_SM_STOP = 6,
 117};
 118
 119static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
 120                                        enum bfa_fcs_lport_event event);
 121static void     bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
 122                                        enum bfa_fcs_lport_event event);
 123static void     bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
 124                                        enum bfa_fcs_lport_event event);
 125static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
 126                                        enum bfa_fcs_lport_event event);
 127static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
 128                                        enum bfa_fcs_lport_event event);
 129static void     bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
 130                                        enum bfa_fcs_lport_event event);
 131
 132static void
 133bfa_fcs_lport_sm_uninit(
 134        struct bfa_fcs_lport_s *port,
 135        enum bfa_fcs_lport_event event)
 136{
 137        bfa_trc(port->fcs, port->port_cfg.pwwn);
 138        bfa_trc(port->fcs, event);
 139
 140        switch (event) {
 141        case BFA_FCS_PORT_SM_CREATE:
 142                bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
 143                break;
 144
 145        default:
 146                bfa_sm_fault(port->fcs, event);
 147        }
 148}
 149
 150static void
 151bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
 152                        enum bfa_fcs_lport_event event)
 153{
 154        bfa_trc(port->fcs, port->port_cfg.pwwn);
 155        bfa_trc(port->fcs, event);
 156
 157        switch (event) {
 158        case BFA_FCS_PORT_SM_ONLINE:
 159                bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
 160                bfa_fcs_lport_online_actions(port);
 161                break;
 162
 163        case BFA_FCS_PORT_SM_DELETE:
 164                bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
 165                bfa_fcs_lport_deleted(port);
 166                break;
 167
 168        case BFA_FCS_PORT_SM_STOP:
 169                /* If vport - send completion call back */
 170                if (port->vport)
 171                        bfa_fcs_vport_stop_comp(port->vport);
 172                else
 173                        bfa_wc_down(&(port->fabric->stop_wc));
 174                break;
 175
 176        case BFA_FCS_PORT_SM_OFFLINE:
 177                break;
 178
 179        default:
 180                bfa_sm_fault(port->fcs, event);
 181        }
 182}
 183
 184static void
 185bfa_fcs_lport_sm_online(
 186        struct bfa_fcs_lport_s *port,
 187        enum bfa_fcs_lport_event event)
 188{
 189        struct bfa_fcs_rport_s *rport;
 190        struct list_head                *qe, *qen;
 191
 192        bfa_trc(port->fcs, port->port_cfg.pwwn);
 193        bfa_trc(port->fcs, event);
 194
 195        switch (event) {
 196        case BFA_FCS_PORT_SM_OFFLINE:
 197                bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
 198                bfa_fcs_lport_offline_actions(port);
 199                break;
 200
 201        case BFA_FCS_PORT_SM_STOP:
 202                __port_action[port->fabric->fab_type].offline(port);
 203
 204                if (port->num_rports == 0) {
 205                        bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
 206                        /* If vport - send completion call back */
 207                        if (port->vport)
 208                                bfa_fcs_vport_stop_comp(port->vport);
 209                        else
 210                                bfa_wc_down(&(port->fabric->stop_wc));
 211                } else {
 212                        bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
 213                        list_for_each_safe(qe, qen, &port->rport_q) {
 214                                rport = (struct bfa_fcs_rport_s *) qe;
 215                                bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
 216                        }
 217                }
 218                break;
 219
 220        case BFA_FCS_PORT_SM_DELETE:
 221
 222                __port_action[port->fabric->fab_type].offline(port);
 223
 224                if (port->num_rports == 0) {
 225                        bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
 226                        bfa_fcs_lport_deleted(port);
 227                } else {
 228                        bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
 229                        list_for_each_safe(qe, qen, &port->rport_q) {
 230                                rport = (struct bfa_fcs_rport_s *) qe;
 231                                bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
 232                        }
 233                }
 234                break;
 235
 236        case BFA_FCS_PORT_SM_DELRPORT:
 237                break;
 238
 239        default:
 240                bfa_sm_fault(port->fcs, event);
 241        }
 242}
 243
 244static void
 245bfa_fcs_lport_sm_offline(
 246        struct bfa_fcs_lport_s *port,
 247        enum bfa_fcs_lport_event event)
 248{
 249        struct bfa_fcs_rport_s *rport;
 250        struct list_head                *qe, *qen;
 251
 252        bfa_trc(port->fcs, port->port_cfg.pwwn);
 253        bfa_trc(port->fcs, event);
 254
 255        switch (event) {
 256        case BFA_FCS_PORT_SM_ONLINE:
 257                bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
 258                bfa_fcs_lport_online_actions(port);
 259                break;
 260
 261        case BFA_FCS_PORT_SM_STOP:
 262                if (port->num_rports == 0) {
 263                        bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
 264                        /* If vport - send completion call back */
 265                        if (port->vport)
 266                                bfa_fcs_vport_stop_comp(port->vport);
 267                        else
 268                                bfa_wc_down(&(port->fabric->stop_wc));
 269                } else {
 270                        bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
 271                        list_for_each_safe(qe, qen, &port->rport_q) {
 272                                rport = (struct bfa_fcs_rport_s *) qe;
 273                                bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
 274                        }
 275                }
 276                break;
 277
 278        case BFA_FCS_PORT_SM_DELETE:
 279                if (port->num_rports == 0) {
 280                        bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
 281                        bfa_fcs_lport_deleted(port);
 282                } else {
 283                        bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
 284                        list_for_each_safe(qe, qen, &port->rport_q) {
 285                                rport = (struct bfa_fcs_rport_s *) qe;
 286                                bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
 287                        }
 288                }
 289                break;
 290
 291        case BFA_FCS_PORT_SM_DELRPORT:
 292        case BFA_FCS_PORT_SM_OFFLINE:
 293                break;
 294
 295        default:
 296                bfa_sm_fault(port->fcs, event);
 297        }
 298}
 299
 300static void
 301bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
 302                          enum bfa_fcs_lport_event event)
 303{
 304        bfa_trc(port->fcs, port->port_cfg.pwwn);
 305        bfa_trc(port->fcs, event);
 306
 307        switch (event) {
 308        case BFA_FCS_PORT_SM_DELRPORT:
 309                if (port->num_rports == 0) {
 310                        bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
 311                        /* If vport - send completion call back */
 312                        if (port->vport)
 313                                bfa_fcs_vport_stop_comp(port->vport);
 314                        else
 315                                bfa_wc_down(&(port->fabric->stop_wc));
 316                }
 317                break;
 318
 319        default:
 320                bfa_sm_fault(port->fcs, event);
 321        }
 322}
 323
 324static void
 325bfa_fcs_lport_sm_deleting(
 326        struct bfa_fcs_lport_s *port,
 327        enum bfa_fcs_lport_event event)
 328{
 329        bfa_trc(port->fcs, port->port_cfg.pwwn);
 330        bfa_trc(port->fcs, event);
 331
 332        switch (event) {
 333        case BFA_FCS_PORT_SM_DELRPORT:
 334                if (port->num_rports == 0) {
 335                        bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
 336                        bfa_fcs_lport_deleted(port);
 337                }
 338                break;
 339
 340        default:
 341                bfa_sm_fault(port->fcs, event);
 342        }
 343}
 344
 345/*
 346 *  fcs_port_pvt
 347 */
 348
 349/*
 350 * Send AEN notification
 351 */
 352static void
 353bfa_fcs_lport_aen_post(struct bfa_fcs_lport_s *port,
 354                        enum bfa_lport_aen_event event)
 355{
 356        struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
 357        struct bfa_aen_entry_s  *aen_entry;
 358
 359        bfad_get_aen_entry(bfad, aen_entry);
 360        if (!aen_entry)
 361                return;
 362
 363        aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
 364        aen_entry->aen_data.lport.roles = port->port_cfg.roles;
 365        aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
 366                                        bfa_fcs_get_base_port(port->fcs));
 367        aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
 368
 369        /* Send the AEN notification */
 370        bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
 371                                  BFA_AEN_CAT_LPORT, event);
 372}
 373
 374/*
 375 * Send a LS reject
 376 */
 377static void
 378bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
 379                         u8 reason_code, u8 reason_code_expl)
 380{
 381        struct fchs_s   fchs;
 382        struct bfa_fcxp_s *fcxp;
 383        struct bfa_rport_s *bfa_rport = NULL;
 384        int             len;
 385
 386        bfa_trc(port->fcs, rx_fchs->d_id);
 387        bfa_trc(port->fcs, rx_fchs->s_id);
 388
 389        fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 390        if (!fcxp)
 391                return;
 392
 393        len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
 394                              rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
 395                              rx_fchs->ox_id, reason_code, reason_code_expl);
 396
 397        bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
 398                          BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
 399                          FC_MAX_PDUSZ, 0);
 400}
 401
 402/*
 403 * Send a FCCT Reject
 404 */
 405static void
 406bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
 407        struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl)
 408{
 409        struct fchs_s   fchs;
 410        struct bfa_fcxp_s *fcxp;
 411        struct bfa_rport_s *bfa_rport = NULL;
 412        int             len;
 413        struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1);
 414        struct ct_hdr_s *ct_hdr;
 415
 416        bfa_trc(port->fcs, rx_fchs->d_id);
 417        bfa_trc(port->fcs, rx_fchs->s_id);
 418
 419        fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 420        if (!fcxp)
 421                return;
 422
 423        ct_hdr = bfa_fcxp_get_reqbuf(fcxp);
 424        ct_hdr->gs_type = rx_cthdr->gs_type;
 425        ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type;
 426
 427        len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id,
 428                        bfa_fcs_lport_get_fcid(port),
 429                        rx_fchs->ox_id, reason_code, reason_code_expl);
 430
 431        bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
 432                        BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
 433                        FC_MAX_PDUSZ, 0);
 434}
 435
 436/*
 437 * Process incoming plogi from a remote port.
 438 */
 439static void
 440bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
 441                struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
 442{
 443        struct bfa_fcs_rport_s *rport;
 444
 445        bfa_trc(port->fcs, rx_fchs->d_id);
 446        bfa_trc(port->fcs, rx_fchs->s_id);
 447
 448        /*
 449         * If min cfg mode is enabled, drop any incoming PLOGIs
 450         */
 451        if (__fcs_min_cfg(port->fcs)) {
 452                bfa_trc(port->fcs, rx_fchs->s_id);
 453                return;
 454        }
 455
 456        if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
 457                bfa_trc(port->fcs, rx_fchs->s_id);
 458                /*
 459                 * send a LS reject
 460                 */
 461                bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
 462                                        FC_LS_RJT_RSN_PROTOCOL_ERROR,
 463                                        FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
 464                return;
 465        }
 466
 467        /*
 468         * Direct Attach P2P mode : verify address assigned by the r-port.
 469         */
 470        if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
 471                (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
 472                           (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
 473                if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
 474                        /* Address assigned to us cannot be a WKA */
 475                        bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
 476                                        FC_LS_RJT_RSN_PROTOCOL_ERROR,
 477                                        FC_LS_RJT_EXP_INVALID_NPORT_ID);
 478                        return;
 479                }
 480                port->pid  = rx_fchs->d_id;
 481                bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
 482        }
 483
 484        /*
 485         * First, check if we know the device by pwwn.
 486         */
 487        rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
 488        if (rport) {
 489                /*
 490                 * Direct Attach P2P mode : handle address assigned by r-port.
 491                 */
 492                if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
 493                        (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
 494                        (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
 495                        port->pid  = rx_fchs->d_id;
 496                        bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
 497                        rport->pid = rx_fchs->s_id;
 498                }
 499                bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
 500                return;
 501        }
 502
 503        /*
 504         * Next, lookup rport by PID.
 505         */
 506        rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
 507        if (!rport) {
 508                /*
 509                 * Inbound PLOGI from a new device.
 510                 */
 511                bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
 512                return;
 513        }
 514
 515        /*
 516         * Rport is known only by PID.
 517         */
 518        if (rport->pwwn) {
 519                /*
 520                 * This is a different device with the same pid. Old device
 521                 * disappeared. Send implicit LOGO to old device.
 522                 */
 523                WARN_ON(rport->pwwn == plogi->port_name);
 524                bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
 525
 526                /*
 527                 * Inbound PLOGI from a new device (with old PID).
 528                 */
 529                bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
 530                return;
 531        }
 532
 533        /*
 534         * PLOGI crossing each other.
 535         */
 536        WARN_ON(rport->pwwn != WWN_NULL);
 537        bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
 538}
 539
 540/*
 541 * Process incoming ECHO.
 542 * Since it does not require a login, it is processed here.
 543 */
 544static void
 545bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
 546                struct fc_echo_s *echo, u16 rx_len)
 547{
 548        struct fchs_s           fchs;
 549        struct bfa_fcxp_s       *fcxp;
 550        struct bfa_rport_s      *bfa_rport = NULL;
 551        int                     len, pyld_len;
 552
 553        bfa_trc(port->fcs, rx_fchs->s_id);
 554        bfa_trc(port->fcs, rx_fchs->d_id);
 555
 556        fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 557        if (!fcxp)
 558                return;
 559
 560        len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
 561                                rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
 562                                rx_fchs->ox_id);
 563
 564        /*
 565         * Copy the payload (if any) from the echo frame
 566         */
 567        pyld_len = rx_len - sizeof(struct fchs_s);
 568        bfa_trc(port->fcs, rx_len);
 569        bfa_trc(port->fcs, pyld_len);
 570
 571        if (pyld_len > len)
 572                memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
 573                        sizeof(struct fc_echo_s), (echo + 1),
 574                        (pyld_len - sizeof(struct fc_echo_s)));
 575
 576        bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
 577                        BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
 578                        FC_MAX_PDUSZ, 0);
 579}
 580
 581/*
 582 * Process incoming RNID.
 583 * Since it does not require a login, it is processed here.
 584 */
 585static void
 586bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
 587                struct fc_rnid_cmd_s *rnid, u16 rx_len)
 588{
 589        struct fc_rnid_common_id_data_s common_id_data;
 590        struct fc_rnid_general_topology_data_s gen_topo_data;
 591        struct fchs_s   fchs;
 592        struct bfa_fcxp_s *fcxp;
 593        struct bfa_rport_s *bfa_rport = NULL;
 594        u16     len;
 595        u32     data_format;
 596
 597        bfa_trc(port->fcs, rx_fchs->s_id);
 598        bfa_trc(port->fcs, rx_fchs->d_id);
 599        bfa_trc(port->fcs, rx_len);
 600
 601        fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 602        if (!fcxp)
 603                return;
 604
 605        /*
 606         * Check Node Indentification Data Format
 607         * We only support General Topology Discovery Format.
 608         * For any other requested Data Formats, we return Common Node Id Data
 609         * only, as per FC-LS.
 610         */
 611        bfa_trc(port->fcs, rnid->node_id_data_format);
 612        if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
 613                data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
 614                /*
 615                 * Get General topology data for this port
 616                 */
 617                bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
 618        } else {
 619                data_format = RNID_NODEID_DATA_FORMAT_COMMON;
 620        }
 621
 622        /*
 623         * Copy the Node Id Info
 624         */
 625        common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
 626        common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
 627
 628        len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
 629                                rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
 630                                rx_fchs->ox_id, data_format, &common_id_data,
 631                                &gen_topo_data);
 632
 633        bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
 634                        BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
 635                        FC_MAX_PDUSZ, 0);
 636}
 637
 638/*
 639 *  Fill out General Topolpgy Discovery Data for RNID ELS.
 640 */
 641static void
 642bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
 643                        struct fc_rnid_general_topology_data_s *gen_topo_data)
 644{
 645        memset(gen_topo_data, 0,
 646                      sizeof(struct fc_rnid_general_topology_data_s));
 647
 648        gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
 649        gen_topo_data->phy_port_num = 0;        /* @todo */
 650        gen_topo_data->num_attached_nodes = cpu_to_be32(1);
 651}
 652
 653static void
 654bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
 655{
 656        struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
 657        char    lpwwn_buf[BFA_STRING_32];
 658
 659        bfa_trc(port->fcs, port->fabric->oper_type);
 660
 661        __port_action[port->fabric->fab_type].init(port);
 662        __port_action[port->fabric->fab_type].online(port);
 663
 664        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
 665        BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
 666                "Logical port online: WWN = %s Role = %s\n",
 667                lpwwn_buf, "Initiator");
 668        bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_ONLINE);
 669
 670        bfad->bfad_flags |= BFAD_PORT_ONLINE;
 671}
 672
 673static void
 674bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
 675{
 676        struct list_head        *qe, *qen;
 677        struct bfa_fcs_rport_s *rport;
 678        struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
 679        char    lpwwn_buf[BFA_STRING_32];
 680
 681        bfa_trc(port->fcs, port->fabric->oper_type);
 682
 683        __port_action[port->fabric->fab_type].offline(port);
 684
 685        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
 686        if (bfa_sm_cmp_state(port->fabric,
 687                        bfa_fcs_fabric_sm_online) == BFA_TRUE) {
 688                BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
 689                "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
 690                lpwwn_buf, "Initiator");
 691                bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
 692        } else {
 693                BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
 694                "Logical port taken offline: WWN = %s Role = %s\n",
 695                lpwwn_buf, "Initiator");
 696                bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_OFFLINE);
 697        }
 698
 699        list_for_each_safe(qe, qen, &port->rport_q) {
 700                rport = (struct bfa_fcs_rport_s *) qe;
 701                bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
 702        }
 703}
 704
 705static void
 706bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
 707{
 708        WARN_ON(1);
 709}
 710
 711static void
 712bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
 713{
 714        WARN_ON(1);
 715}
 716
 717static void
 718bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
 719{
 720        WARN_ON(1);
 721}
 722
 723static void
 724bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
 725{
 726        struct fchs_s fchs;
 727        struct bfa_fcxp_s *fcxp;
 728        int             len;
 729
 730        bfa_trc(port->fcs, rx_fchs->d_id);
 731        bfa_trc(port->fcs, rx_fchs->s_id);
 732
 733        fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
 734        if (!fcxp)
 735                return;
 736
 737        len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
 738                        rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
 739                        rx_fchs->ox_id, 0);
 740
 741        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
 742                          BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
 743                          FC_MAX_PDUSZ, 0);
 744}
 745static void
 746bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
 747{
 748        struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
 749        char    lpwwn_buf[BFA_STRING_32];
 750
 751        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
 752        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
 753                "Logical port deleted: WWN = %s Role = %s\n",
 754                lpwwn_buf, "Initiator");
 755        bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DELETE);
 756
 757        /* Base port will be deleted by the OS driver */
 758        if (port->vport)
 759                bfa_fcs_vport_delete_comp(port->vport);
 760        else
 761                bfa_wc_down(&port->fabric->wc);
 762}
 763
 764
 765/*
 766 * Unsolicited frame receive handling.
 767 */
 768void
 769bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
 770                        struct fchs_s *fchs, u16 len)
 771{
 772        u32     pid = fchs->s_id;
 773        struct bfa_fcs_rport_s *rport = NULL;
 774        struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
 775
 776        bfa_stats(lport, uf_recvs);
 777        bfa_trc(lport->fcs, fchs->type);
 778
 779        if (!bfa_fcs_lport_is_online(lport)) {
 780                /*
 781                 * In direct attach topology, it is possible to get a PLOGI
 782                 * before the lport is online due to port feature
 783                 * (QoS/Trunk/FEC/CR), so send a rjt
 784                 */
 785                if ((fchs->type == FC_TYPE_ELS) &&
 786                        (els_cmd->els_code == FC_ELS_PLOGI)) {
 787                        bfa_fcs_lport_send_ls_rjt(lport, fchs,
 788                                FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
 789                                FC_LS_RJT_EXP_NO_ADDL_INFO);
 790                        bfa_stats(lport, plogi_rcvd);
 791                } else
 792                        bfa_stats(lport, uf_recv_drops);
 793
 794                return;
 795        }
 796
 797        /*
 798         * First, handle ELSs that donot require a login.
 799         */
 800        /*
 801         * Handle PLOGI first
 802         */
 803        if ((fchs->type == FC_TYPE_ELS) &&
 804                (els_cmd->els_code == FC_ELS_PLOGI)) {
 805                bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
 806                return;
 807        }
 808
 809        /*
 810         * Handle ECHO separately.
 811         */
 812        if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
 813                bfa_fcs_lport_echo(lport, fchs,
 814                                (struct fc_echo_s *)els_cmd, len);
 815                return;
 816        }
 817
 818        /*
 819         * Handle RNID separately.
 820         */
 821        if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
 822                bfa_fcs_lport_rnid(lport, fchs,
 823                        (struct fc_rnid_cmd_s *) els_cmd, len);
 824                return;
 825        }
 826
 827        if (fchs->type == FC_TYPE_BLS) {
 828                if ((fchs->routing == FC_RTG_BASIC_LINK) &&
 829                                (fchs->cat_info == FC_CAT_ABTS))
 830                        bfa_fcs_lport_abts_acc(lport, fchs);
 831                return;
 832        }
 833
 834        if (fchs->type == FC_TYPE_SERVICES) {
 835                /*
 836                 * Unhandled FC-GS frames. Send a FC-CT Reject
 837                 */
 838                bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP,
 839                                CT_NS_EXP_NOADDITIONAL);
 840                return;
 841        }
 842
 843        /*
 844         * look for a matching remote port ID
 845         */
 846        rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
 847        if (rport) {
 848                bfa_trc(rport->fcs, fchs->s_id);
 849                bfa_trc(rport->fcs, fchs->d_id);
 850                bfa_trc(rport->fcs, fchs->type);
 851
 852                bfa_fcs_rport_uf_recv(rport, fchs, len);
 853                return;
 854        }
 855
 856        /*
 857         * Only handles ELS frames for now.
 858         */
 859        if (fchs->type != FC_TYPE_ELS) {
 860                bfa_trc(lport->fcs, fchs->s_id);
 861                bfa_trc(lport->fcs, fchs->d_id);
 862                /* ignore type FC_TYPE_FC_FSS */
 863                if (fchs->type != FC_TYPE_FC_FSS)
 864                        bfa_sm_fault(lport->fcs, fchs->type);
 865                return;
 866        }
 867
 868        bfa_trc(lport->fcs, els_cmd->els_code);
 869        if (els_cmd->els_code == FC_ELS_RSCN) {
 870                bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
 871                return;
 872        }
 873
 874        if (els_cmd->els_code == FC_ELS_LOGO) {
 875                /*
 876                 * @todo Handle LOGO frames received.
 877                 */
 878                return;
 879        }
 880
 881        if (els_cmd->els_code == FC_ELS_PRLI) {
 882                /*
 883                 * @todo Handle PRLI frames received.
 884                 */
 885                return;
 886        }
 887
 888        /*
 889         * Unhandled ELS frames. Send a LS_RJT.
 890         */
 891        bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
 892                                 FC_LS_RJT_EXP_NO_ADDL_INFO);
 893
 894}
 895
 896/*
 897 *   PID based Lookup for a R-Port in the Port R-Port Queue
 898 */
 899struct bfa_fcs_rport_s *
 900bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
 901{
 902        struct bfa_fcs_rport_s *rport;
 903        struct list_head        *qe;
 904
 905        list_for_each(qe, &port->rport_q) {
 906                rport = (struct bfa_fcs_rport_s *) qe;
 907                if (rport->pid == pid)
 908                        return rport;
 909        }
 910
 911        bfa_trc(port->fcs, pid);
 912        return NULL;
 913}
 914
 915/*
 916 * OLD_PID based Lookup for a R-Port in the Port R-Port Queue
 917 */
 918struct bfa_fcs_rport_s *
 919bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid)
 920{
 921        struct bfa_fcs_rport_s *rport;
 922        struct list_head        *qe;
 923
 924        list_for_each(qe, &port->rport_q) {
 925                rport = (struct bfa_fcs_rport_s *) qe;
 926                if (rport->old_pid == pid)
 927                        return rport;
 928        }
 929
 930        bfa_trc(port->fcs, pid);
 931        return NULL;
 932}
 933
 934/*
 935 *   PWWN based Lookup for a R-Port in the Port R-Port Queue
 936 */
 937struct bfa_fcs_rport_s *
 938bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
 939{
 940        struct bfa_fcs_rport_s *rport;
 941        struct list_head        *qe;
 942
 943        list_for_each(qe, &port->rport_q) {
 944                rport = (struct bfa_fcs_rport_s *) qe;
 945                if (wwn_is_equal(rport->pwwn, pwwn))
 946                        return rport;
 947        }
 948
 949        bfa_trc(port->fcs, pwwn);
 950        return NULL;
 951}
 952
 953/*
 954 *   NWWN based Lookup for a R-Port in the Port R-Port Queue
 955 */
 956struct bfa_fcs_rport_s *
 957bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
 958{
 959        struct bfa_fcs_rport_s *rport;
 960        struct list_head        *qe;
 961
 962        list_for_each(qe, &port->rport_q) {
 963                rport = (struct bfa_fcs_rport_s *) qe;
 964                if (wwn_is_equal(rport->nwwn, nwwn))
 965                        return rport;
 966        }
 967
 968        bfa_trc(port->fcs, nwwn);
 969        return NULL;
 970}
 971
 972/*
 973 * PWWN & PID based Lookup for a R-Port in the Port R-Port Queue
 974 */
 975struct bfa_fcs_rport_s *
 976bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port,
 977                                     wwn_t pwwn, u32 pid)
 978{
 979        struct bfa_fcs_rport_s *rport;
 980        struct list_head        *qe;
 981
 982        list_for_each(qe, &port->rport_q) {
 983                rport = (struct bfa_fcs_rport_s *) qe;
 984                if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid)
 985                        return rport;
 986        }
 987
 988        bfa_trc(port->fcs, pwwn);
 989        return NULL;
 990}
 991
 992/*
 993 * Called by rport module when new rports are discovered.
 994 */
 995void
 996bfa_fcs_lport_add_rport(
 997        struct bfa_fcs_lport_s *port,
 998        struct bfa_fcs_rport_s *rport)
 999{
1000        list_add_tail(&rport->qe, &port->rport_q);
1001        port->num_rports++;
1002}
1003
1004/*
1005 * Called by rport module to when rports are deleted.
1006 */
1007void
1008bfa_fcs_lport_del_rport(
1009        struct bfa_fcs_lport_s *port,
1010        struct bfa_fcs_rport_s *rport)
1011{
1012        WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
1013        list_del(&rport->qe);
1014        port->num_rports--;
1015
1016        bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
1017}
1018
1019/*
1020 * Called by fabric for base port when fabric login is complete.
1021 * Called by vport for virtual ports when FDISC is complete.
1022 */
1023void
1024bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
1025{
1026        bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
1027}
1028
1029/*
1030 * Called by fabric for base port when fabric goes offline.
1031 * Called by vport for virtual ports when virtual port becomes offline.
1032 */
1033void
1034bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
1035{
1036        bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
1037}
1038
1039/*
1040 * Called by fabric for base port and by vport for virtual ports
1041 * when target mode driver is unloaded.
1042 */
1043void
1044bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port)
1045{
1046        bfa_sm_send_event(port, BFA_FCS_PORT_SM_STOP);
1047}
1048
1049/*
1050 * Called by fabric to delete base lport and associated resources.
1051 *
1052 * Called by vport to delete lport and associated resources. Should call
1053 * bfa_fcs_vport_delete_comp() for vports on completion.
1054 */
1055void
1056bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
1057{
1058        bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
1059}
1060
1061/*
1062 * Return TRUE if port is online, else return FALSE
1063 */
1064bfa_boolean_t
1065bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
1066{
1067        return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
1068}
1069
1070/*
1071  * Attach time initialization of logical ports.
1072 */
1073void
1074bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
1075                   u16 vf_id, struct bfa_fcs_vport_s *vport)
1076{
1077        lport->fcs = fcs;
1078        lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
1079        lport->vport = vport;
1080        lport->lp_tag = (vport) ? vport->lps->bfa_tag :
1081                                  lport->fabric->lps->bfa_tag;
1082
1083        INIT_LIST_HEAD(&lport->rport_q);
1084        lport->num_rports = 0;
1085}
1086
1087/*
1088 * Logical port initialization of base or virtual port.
1089 * Called by fabric for base port or by vport for virtual ports.
1090 */
1091
1092void
1093bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
1094        struct bfa_lport_cfg_s *port_cfg)
1095{
1096        struct bfa_fcs_vport_s *vport = lport->vport;
1097        struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
1098        char    lpwwn_buf[BFA_STRING_32];
1099
1100        lport->port_cfg = *port_cfg;
1101
1102        lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
1103                                        lport->port_cfg.roles,
1104                                        lport->fabric->vf_drv,
1105                                        vport ? vport->vport_drv : NULL);
1106
1107        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
1108        BFA_LOG(KERN_INFO, bfad, bfa_log_level,
1109                "New logical port created: WWN = %s Role = %s\n",
1110                lpwwn_buf, "Initiator");
1111        bfa_fcs_lport_aen_post(lport, BFA_LPORT_AEN_NEW);
1112
1113        bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
1114        bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
1115}
1116
1117void
1118bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port,
1119                                char *symname)
1120{
1121        strcpy(port->port_cfg.sym_name.symname, symname);
1122
1123        if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
1124                bfa_fcs_lport_ns_util_send_rspn_id(
1125                        BFA_FCS_GET_NS_FROM_PORT(port), NULL);
1126}
1127
1128/*
1129 *  fcs_lport_api
1130 */
1131
1132void
1133bfa_fcs_lport_get_attr(
1134        struct bfa_fcs_lport_s *port,
1135        struct bfa_lport_attr_s *port_attr)
1136{
1137        if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
1138                port_attr->pid = port->pid;
1139        else
1140                port_attr->pid = 0;
1141
1142        port_attr->port_cfg = port->port_cfg;
1143
1144        if (port->fabric) {
1145                port_attr->port_type = port->fabric->oper_type;
1146                port_attr->loopback = bfa_sm_cmp_state(port->fabric,
1147                                bfa_fcs_fabric_sm_loopback);
1148                port_attr->authfail =
1149                        bfa_sm_cmp_state(port->fabric,
1150                                bfa_fcs_fabric_sm_auth_failed);
1151                port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);
1152                memcpy(port_attr->fabric_ip_addr,
1153                        bfa_fcs_lport_get_fabric_ipaddr(port),
1154                        BFA_FCS_FABRIC_IPADDR_SZ);
1155
1156                if (port->vport != NULL) {
1157                        port_attr->port_type = BFA_PORT_TYPE_VPORT;
1158                        port_attr->fpma_mac =
1159                                port->vport->lps->lp_mac;
1160                } else {
1161                        port_attr->fpma_mac =
1162                                port->fabric->lps->lp_mac;
1163                }
1164        } else {
1165                port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
1166                port_attr->state = BFA_LPORT_UNINIT;
1167        }
1168}
1169
1170/*
1171 *  bfa_fcs_lport_fab port fab functions
1172 */
1173
1174/*
1175 *   Called by port to initialize fabric services of the base port.
1176 */
1177static void
1178bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
1179{
1180        bfa_fcs_lport_ns_init(port);
1181        bfa_fcs_lport_scn_init(port);
1182        bfa_fcs_lport_ms_init(port);
1183}
1184
1185/*
1186 *   Called by port to notify transition to online state.
1187 */
1188static void
1189bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
1190{
1191        bfa_fcs_lport_ns_online(port);
1192        bfa_fcs_lport_fab_scn_online(port);
1193}
1194
1195/*
1196 *   Called by port to notify transition to offline state.
1197 */
1198static void
1199bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
1200{
1201        bfa_fcs_lport_ns_offline(port);
1202        bfa_fcs_lport_scn_offline(port);
1203        bfa_fcs_lport_ms_offline(port);
1204}
1205
1206/*
1207 *  bfa_fcs_lport_n2n  functions
1208 */
1209
1210/*
1211 *   Called by fcs/port to initialize N2N topology.
1212 */
1213static void
1214bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
1215{
1216}
1217
1218/*
1219 *   Called by fcs/port to notify transition to online state.
1220 */
1221static void
1222bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
1223{
1224        struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1225        struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
1226        struct bfa_fcs_rport_s *rport;
1227
1228        bfa_trc(port->fcs, pcfg->pwwn);
1229
1230        /*
1231         * If our PWWN is > than that of the r-port, we have to initiate PLOGI
1232         * and assign an Address. if not, we need to wait for its PLOGI.
1233         *
1234         * If our PWWN is < than that of the remote port, it will send a PLOGI
1235         * with the PIDs assigned. The rport state machine take care of this
1236         * incoming PLOGI.
1237         */
1238        if (memcmp
1239            ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
1240             sizeof(wwn_t)) > 0) {
1241                port->pid = N2N_LOCAL_PID;
1242                bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
1243                /*
1244                 * First, check if we know the device by pwwn.
1245                 */
1246                rport = bfa_fcs_lport_get_rport_by_pwwn(port,
1247                                                        n2n_port->rem_port_wwn);
1248                if (rport) {
1249                        bfa_trc(port->fcs, rport->pid);
1250                        bfa_trc(port->fcs, rport->pwwn);
1251                        rport->pid = N2N_REMOTE_PID;
1252                        bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
1253                        return;
1254                }
1255
1256                /*
1257                 * In n2n there can be only one rport. Delete the old one
1258                 * whose pid should be zero, because it is offline.
1259                 */
1260                if (port->num_rports > 0) {
1261                        rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
1262                        WARN_ON(rport == NULL);
1263                        if (rport) {
1264                                bfa_trc(port->fcs, rport->pwwn);
1265                                bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
1266                        }
1267                }
1268                bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1269        }
1270}
1271
1272/*
1273 *   Called by fcs/port to notify transition to offline state.
1274 */
1275static void
1276bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1277{
1278        struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1279
1280        bfa_trc(port->fcs, port->pid);
1281        port->pid = 0;
1282        n2n_port->rem_port_wwn = 0;
1283        n2n_port->reply_oxid = 0;
1284}
1285
1286static void
1287bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s *port)
1288{
1289        int i = 0, j = 0, bit = 0, alpa_bit = 0;
1290        u8 k = 0;
1291        struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(port->fcs->bfa);
1292
1293        port->port_topo.ploop.alpabm_valid = fcport->alpabm_valid;
1294        port->pid = fcport->myalpa;
1295        port->pid = bfa_hton3b(port->pid);
1296
1297        for (i = 0; i < (FC_ALPA_MAX / 8); i++) {
1298                for (j = 0, alpa_bit = 0; j < 8; j++, alpa_bit++) {
1299                        bfa_trc(port->fcs->bfa, fcport->alpabm.alpa_bm[i]);
1300                        bit = (fcport->alpabm.alpa_bm[i] & (1 << (7 - j)));
1301                        if (bit) {
1302                                port->port_topo.ploop.alpa_pos_map[k] =
1303                                        loop_alpa_map[(i * 8) + alpa_bit];
1304                                k++;
1305                                bfa_trc(port->fcs->bfa, k);
1306                                bfa_trc(port->fcs->bfa,
1307                                         port->port_topo.ploop.alpa_pos_map[k]);
1308                        }
1309                }
1310        }
1311        port->port_topo.ploop.num_alpa = k;
1312}
1313
1314/*
1315 * Called by fcs/port to initialize Loop topology.
1316 */
1317static void
1318bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port)
1319{
1320}
1321
1322/*
1323 * Called by fcs/port to notify transition to online state.
1324 */
1325static void
1326bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port)
1327{
1328        u8 num_alpa = 0, alpabm_valid = 0;
1329        struct bfa_fcs_rport_s *rport;
1330        u8 *alpa_map = NULL;
1331        int i = 0;
1332        u32 pid;
1333
1334        bfa_fcport_get_loop_attr(port);
1335
1336        num_alpa = port->port_topo.ploop.num_alpa;
1337        alpabm_valid = port->port_topo.ploop.alpabm_valid;
1338        alpa_map = port->port_topo.ploop.alpa_pos_map;
1339
1340        bfa_trc(port->fcs->bfa, port->pid);
1341        bfa_trc(port->fcs->bfa, num_alpa);
1342        if (alpabm_valid == 1) {
1343                for (i = 0; i < num_alpa; i++) {
1344                        bfa_trc(port->fcs->bfa, alpa_map[i]);
1345                        if (alpa_map[i] != bfa_hton3b(port->pid)) {
1346                                pid = alpa_map[i];
1347                                bfa_trc(port->fcs->bfa, pid);
1348                                rport = bfa_fcs_lport_get_rport_by_pid(port,
1349                                                bfa_hton3b(pid));
1350                                if (!rport)
1351                                        rport = bfa_fcs_rport_create(port,
1352                                                bfa_hton3b(pid));
1353                        }
1354                }
1355        } else {
1356                for (i = 0; i < MAX_ALPA_COUNT; i++) {
1357                        if (alpa_map[i] != port->pid) {
1358                                pid = loop_alpa_map[i];
1359                                bfa_trc(port->fcs->bfa, pid);
1360                                rport = bfa_fcs_lport_get_rport_by_pid(port,
1361                                                bfa_hton3b(pid));
1362                                if (!rport)
1363                                        rport = bfa_fcs_rport_create(port,
1364                                                bfa_hton3b(pid));
1365                        }
1366                }
1367        }
1368}
1369
1370/*
1371 * Called by fcs/port to notify transition to offline state.
1372 */
1373static void
1374bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port)
1375{
1376}
1377
1378#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1379
1380/*
1381 * forward declarations
1382 */
1383static void     bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1384                                            struct bfa_fcxp_s *fcxp_alloced);
1385static void     bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1386                                            struct bfa_fcxp_s *fcxp_alloced);
1387static void     bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1388                                           struct bfa_fcxp_s *fcxp_alloced);
1389static void     bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1390                                                struct bfa_fcxp_s *fcxp,
1391                                                void *cbarg,
1392                                                bfa_status_t req_status,
1393                                                u32 rsp_len,
1394                                                u32 resid_len,
1395                                                struct fchs_s *rsp_fchs);
1396static void     bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1397                                                struct bfa_fcxp_s *fcxp,
1398                                                void *cbarg,
1399                                                bfa_status_t req_status,
1400                                                u32 rsp_len,
1401                                                u32 resid_len,
1402                                                struct fchs_s *rsp_fchs);
1403static void     bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1404                                               struct bfa_fcxp_s *fcxp,
1405                                               void *cbarg,
1406                                               bfa_status_t req_status,
1407                                               u32 rsp_len,
1408                                               u32 resid_len,
1409                                               struct fchs_s *rsp_fchs);
1410static void     bfa_fcs_lport_fdmi_timeout(void *arg);
1411static int bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1412                                                  u8 *pyld);
1413static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1414                                                  u8 *pyld);
1415static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1416                                                 u8 *pyld);
1417static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1418                                                       fdmi, u8 *pyld);
1419static void     bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1420                                 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1421static void     bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1422                                  struct bfa_fcs_fdmi_port_attr_s *port_attr);
1423u32     bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed);
1424
1425/*
1426 *  fcs_fdmi_sm FCS FDMI state machine
1427 */
1428
1429/*
1430 *  FDMI State Machine events
1431 */
1432enum port_fdmi_event {
1433        FDMISM_EVENT_PORT_ONLINE = 1,
1434        FDMISM_EVENT_PORT_OFFLINE = 2,
1435        FDMISM_EVENT_RSP_OK = 4,
1436        FDMISM_EVENT_RSP_ERROR = 5,
1437        FDMISM_EVENT_TIMEOUT = 6,
1438        FDMISM_EVENT_RHBA_SENT = 7,
1439        FDMISM_EVENT_RPRT_SENT = 8,
1440        FDMISM_EVENT_RPA_SENT = 9,
1441};
1442
1443static void     bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1444                                             enum port_fdmi_event event);
1445static void     bfa_fcs_lport_fdmi_sm_sending_rhba(
1446                                struct bfa_fcs_lport_fdmi_s *fdmi,
1447                                enum port_fdmi_event event);
1448static void     bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1449                                          enum port_fdmi_event event);
1450static void     bfa_fcs_lport_fdmi_sm_rhba_retry(
1451                                struct bfa_fcs_lport_fdmi_s *fdmi,
1452                                enum port_fdmi_event event);
1453static void     bfa_fcs_lport_fdmi_sm_sending_rprt(
1454                                struct bfa_fcs_lport_fdmi_s *fdmi,
1455                                enum port_fdmi_event event);
1456static void     bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1457                                          enum port_fdmi_event event);
1458static void     bfa_fcs_lport_fdmi_sm_rprt_retry(
1459                                struct bfa_fcs_lport_fdmi_s *fdmi,
1460                                enum port_fdmi_event event);
1461static void     bfa_fcs_lport_fdmi_sm_sending_rpa(
1462                                struct bfa_fcs_lport_fdmi_s *fdmi,
1463                                enum port_fdmi_event event);
1464static void     bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1465                                         enum port_fdmi_event event);
1466static void     bfa_fcs_lport_fdmi_sm_rpa_retry(
1467                                struct bfa_fcs_lport_fdmi_s *fdmi,
1468                                enum port_fdmi_event event);
1469static void     bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1470                                            enum port_fdmi_event event);
1471static void     bfa_fcs_lport_fdmi_sm_disabled(
1472                                struct bfa_fcs_lport_fdmi_s *fdmi,
1473                                enum port_fdmi_event event);
1474/*
1475 *      Start in offline state - awaiting MS to send start.
1476 */
1477static void
1478bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1479                             enum port_fdmi_event event)
1480{
1481        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1482
1483        bfa_trc(port->fcs, port->port_cfg.pwwn);
1484        bfa_trc(port->fcs, event);
1485
1486        fdmi->retry_cnt = 0;
1487
1488        switch (event) {
1489        case FDMISM_EVENT_PORT_ONLINE:
1490                if (port->vport) {
1491                        /*
1492                         * For Vports, register a new port.
1493                         */
1494                        bfa_sm_set_state(fdmi,
1495                                         bfa_fcs_lport_fdmi_sm_sending_rprt);
1496                        bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1497                } else {
1498                        /*
1499                         * For a base port, we should first register the HBA
1500                         * attribute. The HBA attribute also contains the base
1501                         *  port registration.
1502                         */
1503                        bfa_sm_set_state(fdmi,
1504                                         bfa_fcs_lport_fdmi_sm_sending_rhba);
1505                        bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1506                }
1507                break;
1508
1509        case FDMISM_EVENT_PORT_OFFLINE:
1510                break;
1511
1512        default:
1513                bfa_sm_fault(port->fcs, event);
1514        }
1515}
1516
1517static void
1518bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1519                                  enum port_fdmi_event event)
1520{
1521        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1522
1523        bfa_trc(port->fcs, port->port_cfg.pwwn);
1524        bfa_trc(port->fcs, event);
1525
1526        switch (event) {
1527        case FDMISM_EVENT_RHBA_SENT:
1528                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1529                break;
1530
1531        case FDMISM_EVENT_PORT_OFFLINE:
1532                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1533                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1534                                           &fdmi->fcxp_wqe);
1535                break;
1536
1537        default:
1538                bfa_sm_fault(port->fcs, event);
1539        }
1540}
1541
1542static void
1543bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1544                        enum port_fdmi_event event)
1545{
1546        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1547
1548        bfa_trc(port->fcs, port->port_cfg.pwwn);
1549        bfa_trc(port->fcs, event);
1550
1551        switch (event) {
1552        case FDMISM_EVENT_RSP_ERROR:
1553                /*
1554                 * if max retries have not been reached, start timer for a
1555                 * delayed retry
1556                 */
1557                if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1558                        bfa_sm_set_state(fdmi,
1559                                        bfa_fcs_lport_fdmi_sm_rhba_retry);
1560                        bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1561                                            &fdmi->timer,
1562                                            bfa_fcs_lport_fdmi_timeout, fdmi,
1563                                            BFA_FCS_RETRY_TIMEOUT);
1564                } else {
1565                        /*
1566                         * set state to offline
1567                         */
1568                        bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1569                }
1570                break;
1571
1572        case FDMISM_EVENT_RSP_OK:
1573                /*
1574                 * Initiate Register Port Attributes
1575                 */
1576                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1577                fdmi->retry_cnt = 0;
1578                bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1579                break;
1580
1581        case FDMISM_EVENT_PORT_OFFLINE:
1582                bfa_fcxp_discard(fdmi->fcxp);
1583                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1584                break;
1585
1586        default:
1587                bfa_sm_fault(port->fcs, event);
1588        }
1589}
1590
1591static void
1592bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1593                                enum port_fdmi_event event)
1594{
1595        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1596
1597        bfa_trc(port->fcs, port->port_cfg.pwwn);
1598        bfa_trc(port->fcs, event);
1599
1600        switch (event) {
1601        case FDMISM_EVENT_TIMEOUT:
1602                /*
1603                 * Retry Timer Expired. Re-send
1604                 */
1605                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1606                bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1607                break;
1608
1609        case FDMISM_EVENT_PORT_OFFLINE:
1610                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1611                bfa_timer_stop(&fdmi->timer);
1612                break;
1613
1614        default:
1615                bfa_sm_fault(port->fcs, event);
1616        }
1617}
1618
1619/*
1620* RPRT : Register Port
1621 */
1622static void
1623bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1624                                  enum port_fdmi_event event)
1625{
1626        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1627
1628        bfa_trc(port->fcs, port->port_cfg.pwwn);
1629        bfa_trc(port->fcs, event);
1630
1631        switch (event) {
1632        case FDMISM_EVENT_RPRT_SENT:
1633                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1634                break;
1635
1636        case FDMISM_EVENT_PORT_OFFLINE:
1637                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1638                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1639                                           &fdmi->fcxp_wqe);
1640                break;
1641
1642        default:
1643                bfa_sm_fault(port->fcs, event);
1644        }
1645}
1646
1647static void
1648bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1649                        enum port_fdmi_event event)
1650{
1651        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1652
1653        bfa_trc(port->fcs, port->port_cfg.pwwn);
1654        bfa_trc(port->fcs, event);
1655
1656        switch (event) {
1657        case FDMISM_EVENT_RSP_ERROR:
1658                /*
1659                 * if max retries have not been reached, start timer for a
1660                 * delayed retry
1661                 */
1662                if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1663                        bfa_sm_set_state(fdmi,
1664                                        bfa_fcs_lport_fdmi_sm_rprt_retry);
1665                        bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1666                                            &fdmi->timer,
1667                                            bfa_fcs_lport_fdmi_timeout, fdmi,
1668                                            BFA_FCS_RETRY_TIMEOUT);
1669
1670                } else {
1671                        /*
1672                         * set state to offline
1673                         */
1674                        bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1675                        fdmi->retry_cnt = 0;
1676                }
1677                break;
1678
1679        case FDMISM_EVENT_RSP_OK:
1680                fdmi->retry_cnt = 0;
1681                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1682                break;
1683
1684        case FDMISM_EVENT_PORT_OFFLINE:
1685                bfa_fcxp_discard(fdmi->fcxp);
1686                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1687                break;
1688
1689        default:
1690                bfa_sm_fault(port->fcs, event);
1691        }
1692}
1693
1694static void
1695bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1696                                enum port_fdmi_event event)
1697{
1698        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1699
1700        bfa_trc(port->fcs, port->port_cfg.pwwn);
1701        bfa_trc(port->fcs, event);
1702
1703        switch (event) {
1704        case FDMISM_EVENT_TIMEOUT:
1705                /*
1706                 * Retry Timer Expired. Re-send
1707                 */
1708                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1709                bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1710                break;
1711
1712        case FDMISM_EVENT_PORT_OFFLINE:
1713                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1714                bfa_timer_stop(&fdmi->timer);
1715                break;
1716
1717        default:
1718                bfa_sm_fault(port->fcs, event);
1719        }
1720}
1721
1722/*
1723 * Register Port Attributes
1724 */
1725static void
1726bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1727                                 enum port_fdmi_event event)
1728{
1729        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1730
1731        bfa_trc(port->fcs, port->port_cfg.pwwn);
1732        bfa_trc(port->fcs, event);
1733
1734        switch (event) {
1735        case FDMISM_EVENT_RPA_SENT:
1736                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1737                break;
1738
1739        case FDMISM_EVENT_PORT_OFFLINE:
1740                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1741                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1742                                           &fdmi->fcxp_wqe);
1743                break;
1744
1745        default:
1746                bfa_sm_fault(port->fcs, event);
1747        }
1748}
1749
1750static void
1751bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1752                        enum port_fdmi_event event)
1753{
1754        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1755
1756        bfa_trc(port->fcs, port->port_cfg.pwwn);
1757        bfa_trc(port->fcs, event);
1758
1759        switch (event) {
1760        case FDMISM_EVENT_RSP_ERROR:
1761                /*
1762                 * if max retries have not been reached, start timer for a
1763                 * delayed retry
1764                 */
1765                if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1766                        bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1767                        bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1768                                            &fdmi->timer,
1769                                            bfa_fcs_lport_fdmi_timeout, fdmi,
1770                                            BFA_FCS_RETRY_TIMEOUT);
1771                } else {
1772                        /*
1773                         * set state to offline
1774                         */
1775                        bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1776                        fdmi->retry_cnt = 0;
1777                }
1778                break;
1779
1780        case FDMISM_EVENT_RSP_OK:
1781                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1782                fdmi->retry_cnt = 0;
1783                break;
1784
1785        case FDMISM_EVENT_PORT_OFFLINE:
1786                bfa_fcxp_discard(fdmi->fcxp);
1787                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1788                break;
1789
1790        default:
1791                bfa_sm_fault(port->fcs, event);
1792        }
1793}
1794
1795static void
1796bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1797                               enum port_fdmi_event event)
1798{
1799        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1800
1801        bfa_trc(port->fcs, port->port_cfg.pwwn);
1802        bfa_trc(port->fcs, event);
1803
1804        switch (event) {
1805        case FDMISM_EVENT_TIMEOUT:
1806                /*
1807                 * Retry Timer Expired. Re-send
1808                 */
1809                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1810                bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1811                break;
1812
1813        case FDMISM_EVENT_PORT_OFFLINE:
1814                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1815                bfa_timer_stop(&fdmi->timer);
1816                break;
1817
1818        default:
1819                bfa_sm_fault(port->fcs, event);
1820        }
1821}
1822
1823static void
1824bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1825                                enum port_fdmi_event event)
1826{
1827        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1828
1829        bfa_trc(port->fcs, port->port_cfg.pwwn);
1830        bfa_trc(port->fcs, event);
1831
1832        switch (event) {
1833        case FDMISM_EVENT_PORT_OFFLINE:
1834                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1835                break;
1836
1837        default:
1838                bfa_sm_fault(port->fcs, event);
1839        }
1840}
1841/*
1842 *  FDMI is disabled state.
1843 */
1844static void
1845bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1846                             enum port_fdmi_event event)
1847{
1848        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1849
1850        bfa_trc(port->fcs, port->port_cfg.pwwn);
1851        bfa_trc(port->fcs, event);
1852
1853        /* No op State. It can only be enabled at Driver Init. */
1854}
1855
1856/*
1857*  RHBA : Register HBA Attributes.
1858 */
1859static void
1860bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1861{
1862        struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1863        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1864        struct fchs_s fchs;
1865        int             len, attr_len;
1866        struct bfa_fcxp_s *fcxp;
1867        u8        *pyld;
1868
1869        bfa_trc(port->fcs, port->port_cfg.pwwn);
1870
1871        fcxp = fcxp_alloced ? fcxp_alloced :
1872               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1873        if (!fcxp) {
1874                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1875                                bfa_fcs_lport_fdmi_send_rhba, fdmi, BFA_TRUE);
1876                return;
1877        }
1878        fdmi->fcxp = fcxp;
1879
1880        pyld = bfa_fcxp_get_reqbuf(fcxp);
1881        memset(pyld, 0, FC_MAX_PDUSZ);
1882
1883        len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1884                                   FDMI_RHBA);
1885
1886        attr_len =
1887                bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1888                                          (u8 *) ((struct ct_hdr_s *) pyld
1889                                                       + 1));
1890        if (attr_len < 0)
1891                return;
1892
1893        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1894                          FC_CLASS_3, (len + attr_len), &fchs,
1895                          bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1896                          FC_MAX_PDUSZ, FC_FCCT_TOV);
1897
1898        bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1899}
1900
1901static int
1902bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1903{
1904        struct bfa_fcs_lport_s *port = fdmi->ms->port;
1905        struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr;
1906        struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1907        struct fdmi_attr_s *attr;
1908        int        len;
1909        u8        *curr_ptr;
1910        u16     templen, count;
1911
1912        fcs_hba_attr = kzalloc(sizeof(*fcs_hba_attr), GFP_KERNEL);
1913        if (!fcs_hba_attr)
1914                return -ENOMEM;
1915
1916        /*
1917         * get hba attributes
1918         */
1919        bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1920
1921        rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1922        rhba->port_list.num_ports = cpu_to_be32(1);
1923        rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1924
1925        len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1926
1927        count = 0;
1928        len += sizeof(rhba->hba_attr_blk.attr_count);
1929
1930        /*
1931         * fill out the invididual entries of the HBA attrib Block
1932         */
1933        curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1934
1935        /*
1936         * Node Name
1937         */
1938        attr = (struct fdmi_attr_s *) curr_ptr;
1939        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
1940        templen = sizeof(wwn_t);
1941        memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1942        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1943        len += templen;
1944        count++;
1945        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1946                             sizeof(templen));
1947
1948        /*
1949         * Manufacturer
1950         */
1951        attr = (struct fdmi_attr_s *) curr_ptr;
1952        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
1953        templen = (u16) strlen(fcs_hba_attr->manufacturer);
1954        memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1955        templen = fc_roundup(templen, sizeof(u32));
1956        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1957        len += templen;
1958        count++;
1959        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1960                             sizeof(templen));
1961
1962        /*
1963         * Serial Number
1964         */
1965        attr = (struct fdmi_attr_s *) curr_ptr;
1966        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
1967        templen = (u16) strlen(fcs_hba_attr->serial_num);
1968        memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1969        templen = fc_roundup(templen, sizeof(u32));
1970        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1971        len += templen;
1972        count++;
1973        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1974                             sizeof(templen));
1975
1976        /*
1977         * Model
1978         */
1979        attr = (struct fdmi_attr_s *) curr_ptr;
1980        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
1981        templen = (u16) strlen(fcs_hba_attr->model);
1982        memcpy(attr->value, fcs_hba_attr->model, templen);
1983        templen = fc_roundup(templen, sizeof(u32));
1984        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1985        len += templen;
1986        count++;
1987        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1988                             sizeof(templen));
1989
1990        /*
1991         * Model Desc
1992         */
1993        attr = (struct fdmi_attr_s *) curr_ptr;
1994        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
1995        templen = (u16) strlen(fcs_hba_attr->model_desc);
1996        memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1997        templen = fc_roundup(templen, sizeof(u32));
1998        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1999        len += templen;
2000        count++;
2001        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2002                             sizeof(templen));
2003
2004        /*
2005         * H/W Version
2006         */
2007        if (fcs_hba_attr->hw_version[0] != '\0') {
2008                attr = (struct fdmi_attr_s *) curr_ptr;
2009                attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
2010                templen = (u16) strlen(fcs_hba_attr->hw_version);
2011                memcpy(attr->value, fcs_hba_attr->hw_version, templen);
2012                templen = fc_roundup(templen, sizeof(u32));
2013                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2014                len += templen;
2015                count++;
2016                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2017                                         sizeof(templen));
2018        }
2019
2020        /*
2021         * Driver Version
2022         */
2023        attr = (struct fdmi_attr_s *) curr_ptr;
2024        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
2025        templen = (u16) strlen(fcs_hba_attr->driver_version);
2026        memcpy(attr->value, fcs_hba_attr->driver_version, templen);
2027        templen = fc_roundup(templen, sizeof(u32));
2028        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2029        len += templen;
2030        count++;
2031        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2032                             sizeof(templen));
2033
2034        /*
2035         * Option Rom Version
2036         */
2037        if (fcs_hba_attr->option_rom_ver[0] != '\0') {
2038                attr = (struct fdmi_attr_s *) curr_ptr;
2039                attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
2040                templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
2041                memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
2042                templen = fc_roundup(templen, sizeof(u32));
2043                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2044                len += templen;
2045                count++;
2046                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2047                                         sizeof(templen));
2048        }
2049
2050        attr = (struct fdmi_attr_s *) curr_ptr;
2051        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
2052        templen = (u16) strlen(fcs_hba_attr->fw_version);
2053        memcpy(attr->value, fcs_hba_attr->fw_version, templen);
2054        templen = fc_roundup(templen, sizeof(u32));
2055        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2056        len += templen;
2057        count++;
2058        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2059                             sizeof(templen));
2060
2061        /*
2062         * OS Name
2063         */
2064        if (fcs_hba_attr->os_name[0] != '\0') {
2065                attr = (struct fdmi_attr_s *) curr_ptr;
2066                attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
2067                templen = (u16) strlen(fcs_hba_attr->os_name);
2068                memcpy(attr->value, fcs_hba_attr->os_name, templen);
2069                templen = fc_roundup(templen, sizeof(u32));
2070                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2071                len += templen;
2072                count++;
2073                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2074                                        sizeof(templen));
2075        }
2076
2077        /*
2078         * MAX_CT_PAYLOAD
2079         */
2080        attr = (struct fdmi_attr_s *) curr_ptr;
2081        attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
2082        templen = sizeof(fcs_hba_attr->max_ct_pyld);
2083        memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
2084        templen = fc_roundup(templen, sizeof(u32));
2085        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2086        len += templen;
2087        count++;
2088        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2089                             sizeof(templen));
2090        /*
2091         * Send extended attributes ( FOS 7.1 support )
2092         */
2093        if (fdmi->retry_cnt == 0) {
2094                attr = (struct fdmi_attr_s *) curr_ptr;
2095                attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODE_SYM_NAME);
2096                templen = sizeof(fcs_hba_attr->node_sym_name);
2097                memcpy(attr->value, &fcs_hba_attr->node_sym_name, templen);
2098                templen = fc_roundup(templen, sizeof(u32));
2099                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2100                len += templen;
2101                count++;
2102                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2103                                        sizeof(templen));
2104
2105                attr = (struct fdmi_attr_s *) curr_ptr;
2106                attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_VENDOR_ID);
2107                templen = sizeof(fcs_hba_attr->vendor_info);
2108                memcpy(attr->value, &fcs_hba_attr->vendor_info, templen);
2109                templen = fc_roundup(templen, sizeof(u32));
2110                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2111                len += templen;
2112                count++;
2113                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2114                                        sizeof(templen));
2115
2116                attr = (struct fdmi_attr_s *) curr_ptr;
2117                attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NUM_PORTS);
2118                templen = sizeof(fcs_hba_attr->num_ports);
2119                memcpy(attr->value, &fcs_hba_attr->num_ports, templen);
2120                templen = fc_roundup(templen, sizeof(u32));
2121                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2122                len += templen;
2123                count++;
2124                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2125                                        sizeof(templen));
2126
2127                attr = (struct fdmi_attr_s *) curr_ptr;
2128                attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FABRIC_NAME);
2129                templen = sizeof(fcs_hba_attr->fabric_name);
2130                memcpy(attr->value, &fcs_hba_attr->fabric_name, templen);
2131                templen = fc_roundup(templen, sizeof(u32));
2132                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2133                len += templen;
2134                count++;
2135                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2136                                        sizeof(templen));
2137
2138                attr = (struct fdmi_attr_s *) curr_ptr;
2139                attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_BIOS_VER);
2140                templen = sizeof(fcs_hba_attr->bios_ver);
2141                memcpy(attr->value, &fcs_hba_attr->bios_ver, templen);
2142                templen = fc_roundup(attr->len, sizeof(u32));
2143                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2144                len += templen;
2145                count++;
2146                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2147                                        sizeof(templen));
2148        }
2149
2150        /*
2151         * Update size of payload
2152         */
2153        len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
2154
2155        rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
2156
2157        kfree(fcs_hba_attr);
2158
2159        return len;
2160}
2161
2162static void
2163bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2164                                void *cbarg, bfa_status_t req_status,
2165                                u32 rsp_len, u32 resid_len,
2166                                struct fchs_s *rsp_fchs)
2167{
2168        struct bfa_fcs_lport_fdmi_s *fdmi =
2169                                (struct bfa_fcs_lport_fdmi_s *) cbarg;
2170        struct bfa_fcs_lport_s *port = fdmi->ms->port;
2171        struct ct_hdr_s *cthdr = NULL;
2172
2173        bfa_trc(port->fcs, port->port_cfg.pwwn);
2174
2175        /*
2176         * Sanity Checks
2177         */
2178        if (req_status != BFA_STATUS_OK) {
2179                bfa_trc(port->fcs, req_status);
2180                bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2181                return;
2182        }
2183
2184        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2185        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2186
2187        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2188                bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2189                return;
2190        }
2191
2192        bfa_trc(port->fcs, cthdr->reason_code);
2193        bfa_trc(port->fcs, cthdr->exp_code);
2194        bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2195}
2196
2197/*
2198*  RPRT : Register Port
2199 */
2200static void
2201bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2202{
2203        struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2204        struct bfa_fcs_lport_s *port = fdmi->ms->port;
2205        struct fchs_s fchs;
2206        u16        len, attr_len;
2207        struct bfa_fcxp_s *fcxp;
2208        u8        *pyld;
2209
2210        bfa_trc(port->fcs, port->port_cfg.pwwn);
2211
2212        fcxp = fcxp_alloced ? fcxp_alloced :
2213               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2214        if (!fcxp) {
2215                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2216                                bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE);
2217                return;
2218        }
2219        fdmi->fcxp = fcxp;
2220
2221        pyld = bfa_fcxp_get_reqbuf(fcxp);
2222        memset(pyld, 0, FC_MAX_PDUSZ);
2223
2224        len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2225                                   FDMI_RPRT);
2226
2227        attr_len =
2228                bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
2229                                          (u8 *) ((struct ct_hdr_s *) pyld
2230                                                       + 1));
2231
2232        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2233                          FC_CLASS_3, len + attr_len, &fchs,
2234                          bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
2235                          FC_MAX_PDUSZ, FC_FCCT_TOV);
2236
2237        bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
2238}
2239
2240/*
2241 * This routine builds Port Attribute Block that used in RPA, RPRT commands.
2242 */
2243static          u16
2244bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
2245                                       u8 *pyld)
2246{
2247        struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
2248        struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
2249        struct fdmi_attr_s *attr;
2250        u8        *curr_ptr;
2251        u16        len;
2252        u8      count = 0;
2253        u16     templen;
2254
2255        /*
2256         * get port attributes
2257         */
2258        bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
2259
2260        len = sizeof(port_attrib->attr_count);
2261
2262        /*
2263         * fill out the invididual entries
2264         */
2265        curr_ptr = (u8 *) &port_attrib->port_attr;
2266
2267        /*
2268         * FC4 Types
2269         */
2270        attr = (struct fdmi_attr_s *) curr_ptr;
2271        attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
2272        templen = sizeof(fcs_port_attr.supp_fc4_types);
2273        memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
2274        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2275        len += templen;
2276        ++count;
2277        attr->len =
2278                cpu_to_be16(templen + sizeof(attr->type) +
2279                             sizeof(templen));
2280
2281        /*
2282         * Supported Speed
2283         */
2284        attr = (struct fdmi_attr_s *) curr_ptr;
2285        attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
2286        templen = sizeof(fcs_port_attr.supp_speed);
2287        memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
2288        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2289        len += templen;
2290        ++count;
2291        attr->len =
2292                cpu_to_be16(templen + sizeof(attr->type) +
2293                             sizeof(templen));
2294
2295        /*
2296         * current Port Speed
2297         */
2298        attr = (struct fdmi_attr_s *) curr_ptr;
2299        attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
2300        templen = sizeof(fcs_port_attr.curr_speed);
2301        memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
2302        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2303        len += templen;
2304        ++count;
2305        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2306                             sizeof(templen));
2307
2308        /*
2309         * max frame size
2310         */
2311        attr = (struct fdmi_attr_s *) curr_ptr;
2312        attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
2313        templen = sizeof(fcs_port_attr.max_frm_size);
2314        memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
2315        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2316        len += templen;
2317        ++count;
2318        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2319                             sizeof(templen));
2320
2321        /*
2322         * OS Device Name
2323         */
2324        if (fcs_port_attr.os_device_name[0] != '\0') {
2325                attr = (struct fdmi_attr_s *) curr_ptr;
2326                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
2327                templen = (u16) strlen(fcs_port_attr.os_device_name);
2328                memcpy(attr->value, fcs_port_attr.os_device_name, templen);
2329                templen = fc_roundup(templen, sizeof(u32));
2330                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2331                len += templen;
2332                ++count;
2333                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2334                                        sizeof(templen));
2335        }
2336        /*
2337         * Host Name
2338         */
2339        if (fcs_port_attr.host_name[0] != '\0') {
2340                attr = (struct fdmi_attr_s *) curr_ptr;
2341                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
2342                templen = (u16) strlen(fcs_port_attr.host_name);
2343                memcpy(attr->value, fcs_port_attr.host_name, templen);
2344                templen = fc_roundup(templen, sizeof(u32));
2345                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2346                len += templen;
2347                ++count;
2348                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2349                                sizeof(templen));
2350        }
2351
2352        if (fdmi->retry_cnt == 0) {
2353                attr = (struct fdmi_attr_s *) curr_ptr;
2354                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_NODE_NAME);
2355                templen = sizeof(fcs_port_attr.node_name);
2356                memcpy(attr->value, &fcs_port_attr.node_name, templen);
2357                templen = fc_roundup(templen, sizeof(u32));
2358                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2359                len += templen;
2360                ++count;
2361                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2362                                 sizeof(templen));
2363
2364                attr = (struct fdmi_attr_s *) curr_ptr;
2365                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NAME);
2366                templen = sizeof(fcs_port_attr.port_name);
2367                memcpy(attr->value, &fcs_port_attr.port_name, templen);
2368                templen = fc_roundup(templen, sizeof(u32));
2369                curr_ptr += sizeof(attr->type) + sizeof(attr->len) + templen;
2370                len += templen;
2371                ++count;
2372                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2373                                 sizeof(templen));
2374
2375                if (fcs_port_attr.port_sym_name.symname[0] != '\0') {
2376                        attr = (struct fdmi_attr_s *) curr_ptr;
2377                        attr->type =
2378                                cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SYM_NAME);
2379                        templen = sizeof(fcs_port_attr.port_sym_name);
2380                        memcpy(attr->value,
2381                                &fcs_port_attr.port_sym_name, templen);
2382                        templen = fc_roundup(templen, sizeof(u32));
2383                        curr_ptr += sizeof(attr->type) +
2384                                        sizeof(templen) + templen;
2385                        len += templen;
2386                        ++count;
2387                        attr->len = cpu_to_be16(templen +
2388                                sizeof(attr->type) + sizeof(templen));
2389                }
2390
2391                attr = (struct fdmi_attr_s *) curr_ptr;
2392                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_TYPE);
2393                templen = sizeof(fcs_port_attr.port_type);
2394                memcpy(attr->value, &fcs_port_attr.port_type, templen);
2395                templen = fc_roundup(templen, sizeof(u32));
2396                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2397                len += templen;
2398                ++count;
2399                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2400                                 sizeof(templen));
2401
2402                attr = (struct fdmi_attr_s *) curr_ptr;
2403                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_COS);
2404                templen = sizeof(fcs_port_attr.scos);
2405                memcpy(attr->value, &fcs_port_attr.scos, templen);
2406                templen = fc_roundup(templen, sizeof(u32));
2407                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2408                len += templen;
2409                ++count;
2410                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2411                                 sizeof(templen));
2412
2413                attr = (struct fdmi_attr_s *) curr_ptr;
2414                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FAB_NAME);
2415                templen = sizeof(fcs_port_attr.port_fabric_name);
2416                memcpy(attr->value, &fcs_port_attr.port_fabric_name, templen);
2417                templen = fc_roundup(templen, sizeof(u32));
2418                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2419                len += templen;
2420                ++count;
2421                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2422                                 sizeof(templen));
2423
2424                attr = (struct fdmi_attr_s *) curr_ptr;
2425                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FC4_TYPE);
2426                templen = sizeof(fcs_port_attr.port_act_fc4_type);
2427                memcpy(attr->value, fcs_port_attr.port_act_fc4_type,
2428                                templen);
2429                templen = fc_roundup(templen, sizeof(u32));
2430                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2431                len += templen;
2432                ++count;
2433                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2434                                 sizeof(templen));
2435
2436                attr = (struct fdmi_attr_s *) curr_ptr;
2437                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_STATE);
2438                templen = sizeof(fcs_port_attr.port_state);
2439                memcpy(attr->value, &fcs_port_attr.port_state, templen);
2440                templen = fc_roundup(templen, sizeof(u32));
2441                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2442                len += templen;
2443                ++count;
2444                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2445                                 sizeof(templen));
2446
2447                attr = (struct fdmi_attr_s *) curr_ptr;
2448                attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NUM_RPRT);
2449                templen = sizeof(fcs_port_attr.num_ports);
2450                memcpy(attr->value, &fcs_port_attr.num_ports, templen);
2451                templen = fc_roundup(templen, sizeof(u32));
2452                curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2453                len += templen;
2454                ++count;
2455                attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2456                                sizeof(templen));
2457        }
2458
2459        /*
2460         * Update size of payload
2461         */
2462        port_attrib->attr_count = cpu_to_be32(count);
2463        len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
2464        return len;
2465}
2466
2467static          u16
2468bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2469{
2470        struct bfa_fcs_lport_s *port = fdmi->ms->port;
2471        struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
2472        u16        len;
2473
2474        rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
2475        rprt->port_name = bfa_fcs_lport_get_pwwn(port);
2476
2477        len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2478                                (u8 *) &rprt->port_attr_blk);
2479
2480        len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
2481
2482        return len;
2483}
2484
2485static void
2486bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2487                                void *cbarg, bfa_status_t req_status,
2488                                u32 rsp_len, u32 resid_len,
2489                                struct fchs_s *rsp_fchs)
2490{
2491        struct bfa_fcs_lport_fdmi_s *fdmi =
2492                        (struct bfa_fcs_lport_fdmi_s *) cbarg;
2493        struct bfa_fcs_lport_s *port = fdmi->ms->port;
2494        struct ct_hdr_s *cthdr = NULL;
2495
2496        bfa_trc(port->fcs, port->port_cfg.pwwn);
2497
2498        /*
2499         * Sanity Checks
2500         */
2501        if (req_status != BFA_STATUS_OK) {
2502                bfa_trc(port->fcs, req_status);
2503                bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2504                return;
2505        }
2506
2507        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2508        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2509
2510        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2511                bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2512                return;
2513        }
2514
2515        bfa_trc(port->fcs, cthdr->reason_code);
2516        bfa_trc(port->fcs, cthdr->exp_code);
2517        bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2518}
2519
2520/*
2521*  RPA : Register Port Attributes.
2522 */
2523static void
2524bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2525{
2526        struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2527        struct bfa_fcs_lport_s *port = fdmi->ms->port;
2528        struct fchs_s fchs;
2529        u16        len, attr_len;
2530        struct bfa_fcxp_s *fcxp;
2531        u8        *pyld;
2532
2533        bfa_trc(port->fcs, port->port_cfg.pwwn);
2534
2535        fcxp = fcxp_alloced ? fcxp_alloced :
2536               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2537        if (!fcxp) {
2538                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2539                                bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE);
2540                return;
2541        }
2542        fdmi->fcxp = fcxp;
2543
2544        pyld = bfa_fcxp_get_reqbuf(fcxp);
2545        memset(pyld, 0, FC_MAX_PDUSZ);
2546
2547        len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2548                                   FDMI_RPA);
2549
2550        attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2551                                (u8 *) ((struct ct_hdr_s *) pyld + 1));
2552
2553        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2554                          FC_CLASS_3, len + attr_len, &fchs,
2555                          bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2556                          FC_MAX_PDUSZ, FC_FCCT_TOV);
2557
2558        bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2559}
2560
2561static          u16
2562bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2563{
2564        struct bfa_fcs_lport_s *port = fdmi->ms->port;
2565        struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2566        u16        len;
2567
2568        rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2569
2570        len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2571                                (u8 *) &rpa->port_attr_blk);
2572
2573        len += sizeof(rpa->port_name);
2574
2575        return len;
2576}
2577
2578static void
2579bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2580                        void *cbarg, bfa_status_t req_status, u32 rsp_len,
2581                        u32 resid_len, struct fchs_s *rsp_fchs)
2582{
2583        struct bfa_fcs_lport_fdmi_s *fdmi =
2584                                (struct bfa_fcs_lport_fdmi_s *) cbarg;
2585        struct bfa_fcs_lport_s *port = fdmi->ms->port;
2586        struct ct_hdr_s *cthdr = NULL;
2587
2588        bfa_trc(port->fcs, port->port_cfg.pwwn);
2589
2590        /*
2591         * Sanity Checks
2592         */
2593        if (req_status != BFA_STATUS_OK) {
2594                bfa_trc(port->fcs, req_status);
2595                bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2596                return;
2597        }
2598
2599        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2600        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2601
2602        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2603                bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2604                return;
2605        }
2606
2607        bfa_trc(port->fcs, cthdr->reason_code);
2608        bfa_trc(port->fcs, cthdr->exp_code);
2609        bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2610}
2611
2612static void
2613bfa_fcs_lport_fdmi_timeout(void *arg)
2614{
2615        struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2616
2617        bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2618}
2619
2620static void
2621bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2622                         struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2623{
2624        struct bfa_fcs_lport_s *port = fdmi->ms->port;
2625        struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2626        struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
2627
2628        memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2629
2630        bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2631                                        hba_attr->manufacturer);
2632        bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2633                                        hba_attr->serial_num);
2634        bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2635                                        hba_attr->model);
2636        bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2637                                        hba_attr->model_desc);
2638        bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2639                                        hba_attr->hw_version);
2640        bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2641                                        hba_attr->option_rom_ver);
2642        bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2643                                        hba_attr->fw_version);
2644
2645        strlcpy(hba_attr->driver_version, (char *)driver_info->version,
2646                sizeof(hba_attr->driver_version));
2647
2648        strlcpy(hba_attr->os_name, driver_info->host_os_name,
2649                sizeof(hba_attr->os_name));
2650
2651        /*
2652         * If there is a patch level, append it
2653         * to the os name along with a separator
2654         */
2655        if (driver_info->host_os_patch[0] != '\0') {
2656                strlcat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2657                        sizeof(hba_attr->os_name));
2658                strlcat(hba_attr->os_name, driver_info->host_os_patch,
2659                                sizeof(hba_attr->os_name));
2660        }
2661
2662        /* Retrieve the max frame size from the port attr */
2663        bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
2664        hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size;
2665
2666        strlcpy(hba_attr->node_sym_name.symname,
2667                port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN);
2668        strcpy(hba_attr->vendor_info, "QLogic");
2669        hba_attr->num_ports =
2670                cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc));
2671        hba_attr->fabric_name = port->fabric->lps->pr_nwwn;
2672        strlcpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN);
2673
2674}
2675
2676static void
2677bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2678                          struct bfa_fcs_fdmi_port_attr_s *port_attr)
2679{
2680        struct bfa_fcs_lport_s *port = fdmi->ms->port;
2681        struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2682        struct bfa_port_attr_s pport_attr;
2683        struct bfa_lport_attr_s lport_attr;
2684
2685        memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2686
2687        /*
2688         * get pport attributes from hal
2689         */
2690        bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2691
2692        /*
2693         * get FC4 type Bitmask
2694         */
2695        fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2696
2697        /*
2698         * Supported Speeds
2699         */
2700        switch (pport_attr.speed_supported) {
2701        case BFA_PORT_SPEED_16GBPS:
2702                port_attr->supp_speed =
2703                        cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G);
2704                break;
2705
2706        case BFA_PORT_SPEED_10GBPS:
2707                port_attr->supp_speed =
2708                        cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G);
2709                break;
2710
2711        case BFA_PORT_SPEED_8GBPS:
2712                port_attr->supp_speed =
2713                        cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G);
2714                break;
2715
2716        case BFA_PORT_SPEED_4GBPS:
2717                port_attr->supp_speed =
2718                        cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G);
2719                break;
2720
2721        default:
2722                bfa_sm_fault(port->fcs, pport_attr.speed_supported);
2723        }
2724
2725        /*
2726         * Current Speed
2727         */
2728        port_attr->curr_speed = cpu_to_be32(
2729                                bfa_fcs_fdmi_convert_speed(pport_attr.speed));
2730
2731        /*
2732         * Max PDU Size.
2733         */
2734        port_attr->max_frm_size = cpu_to_be32(pport_attr.pport_cfg.maxfrsize);
2735
2736        /*
2737         * OS device Name
2738         */
2739        strlcpy(port_attr->os_device_name, driver_info->os_device_name,
2740                sizeof(port_attr->os_device_name));
2741
2742        /*
2743         * Host name
2744         */
2745        strlcpy(port_attr->host_name, driver_info->host_machine_name,
2746                sizeof(port_attr->host_name));
2747
2748        port_attr->node_name = bfa_fcs_lport_get_nwwn(port);
2749        port_attr->port_name = bfa_fcs_lport_get_pwwn(port);
2750
2751        strlcpy(port_attr->port_sym_name.symname,
2752                bfa_fcs_lport_get_psym_name(port).symname, BFA_SYMNAME_MAXLEN);
2753        bfa_fcs_lport_get_attr(port, &lport_attr);
2754        port_attr->port_type = cpu_to_be32(lport_attr.port_type);
2755        port_attr->scos = pport_attr.cos_supported;
2756        port_attr->port_fabric_name = port->fabric->lps->pr_nwwn;
2757        fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->port_act_fc4_type);
2758        port_attr->port_state = cpu_to_be32(pport_attr.port_state);
2759        port_attr->num_ports = cpu_to_be32(port->num_rports);
2760}
2761
2762/*
2763 * Convert BFA speed to FDMI format.
2764 */
2765u32
2766bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)
2767{
2768        u32     ret;
2769
2770        switch (pport_speed) {
2771        case BFA_PORT_SPEED_1GBPS:
2772        case BFA_PORT_SPEED_2GBPS:
2773                ret = pport_speed;
2774                break;
2775
2776        case BFA_PORT_SPEED_4GBPS:
2777                ret = FDMI_TRANS_SPEED_4G;
2778                break;
2779
2780        case BFA_PORT_SPEED_8GBPS:
2781                ret = FDMI_TRANS_SPEED_8G;
2782                break;
2783
2784        case BFA_PORT_SPEED_10GBPS:
2785                ret = FDMI_TRANS_SPEED_10G;
2786                break;
2787
2788        case BFA_PORT_SPEED_16GBPS:
2789                ret = FDMI_TRANS_SPEED_16G;
2790                break;
2791
2792        default:
2793                ret = FDMI_TRANS_SPEED_UNKNOWN;
2794        }
2795        return ret;
2796}
2797
2798void
2799bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2800{
2801        struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2802
2803        fdmi->ms = ms;
2804        if (ms->port->fcs->fdmi_enabled)
2805                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2806        else
2807                bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2808}
2809
2810void
2811bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2812{
2813        struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2814
2815        fdmi->ms = ms;
2816        bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2817}
2818
2819void
2820bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2821{
2822        struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2823
2824        fdmi->ms = ms;
2825        bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2826}
2827
2828#define BFA_FCS_MS_CMD_MAX_RETRIES  2
2829
2830/*
2831 * forward declarations
2832 */
2833static void     bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2834                                           struct bfa_fcxp_s *fcxp_alloced);
2835static void     bfa_fcs_lport_ms_timeout(void *arg);
2836static void     bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2837                                               struct bfa_fcxp_s *fcxp,
2838                                               void *cbarg,
2839                                               bfa_status_t req_status,
2840                                               u32 rsp_len,
2841                                               u32 resid_len,
2842                                               struct fchs_s *rsp_fchs);
2843
2844static void     bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2845                                        struct bfa_fcxp_s *fcxp_alloced);
2846static void     bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2847                                               struct bfa_fcxp_s *fcxp,
2848                                               void *cbarg,
2849                                               bfa_status_t req_status,
2850                                               u32 rsp_len,
2851                                               u32 resid_len,
2852                                               struct fchs_s *rsp_fchs);
2853static void     bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2854                                        struct bfa_fcxp_s *fcxp_alloced);
2855static void     bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2856                                               struct bfa_fcxp_s *fcxp,
2857                                               void *cbarg,
2858                                               bfa_status_t req_status,
2859                                               u32 rsp_len,
2860                                               u32 resid_len,
2861                                               struct fchs_s *rsp_fchs);
2862/*
2863 *  fcs_ms_sm FCS MS state machine
2864 */
2865
2866/*
2867 *  MS State Machine events
2868 */
2869enum port_ms_event {
2870        MSSM_EVENT_PORT_ONLINE = 1,
2871        MSSM_EVENT_PORT_OFFLINE = 2,
2872        MSSM_EVENT_RSP_OK = 3,
2873        MSSM_EVENT_RSP_ERROR = 4,
2874        MSSM_EVENT_TIMEOUT = 5,
2875        MSSM_EVENT_FCXP_SENT = 6,
2876        MSSM_EVENT_PORT_FABRIC_RSCN = 7
2877};
2878
2879static void     bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2880                                           enum port_ms_event event);
2881static void     bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2882                                                 enum port_ms_event event);
2883static void     bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2884                                         enum port_ms_event event);
2885static void     bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2886                                               enum port_ms_event event);
2887static void     bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2888                                                 enum port_ms_event event);
2889static void     bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2890                                         enum port_ms_event event);
2891static void     bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2892                                               enum port_ms_event event);
2893static void     bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2894                                                 enum port_ms_event event);
2895static void     bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2896                                         enum port_ms_event event);
2897static void     bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2898                                               enum port_ms_event event);
2899static void     bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2900                                          enum port_ms_event event);
2901/*
2902 *      Start in offline state - awaiting NS to send start.
2903 */
2904static void
2905bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2906                                enum port_ms_event event)
2907{
2908        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2909        bfa_trc(ms->port->fcs, event);
2910
2911        switch (event) {
2912        case MSSM_EVENT_PORT_ONLINE:
2913                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2914                bfa_fcs_lport_ms_send_plogi(ms, NULL);
2915                break;
2916
2917        case MSSM_EVENT_PORT_OFFLINE:
2918                break;
2919
2920        default:
2921                bfa_sm_fault(ms->port->fcs, event);
2922        }
2923}
2924
2925static void
2926bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2927                                enum port_ms_event event)
2928{
2929        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2930        bfa_trc(ms->port->fcs, event);
2931
2932        switch (event) {
2933        case MSSM_EVENT_FCXP_SENT:
2934                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2935                break;
2936
2937        case MSSM_EVENT_PORT_OFFLINE:
2938                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2939                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2940                                           &ms->fcxp_wqe);
2941                break;
2942
2943        default:
2944                bfa_sm_fault(ms->port->fcs, event);
2945        }
2946}
2947
2948static void
2949bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2950                        enum port_ms_event event)
2951{
2952        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2953        bfa_trc(ms->port->fcs, event);
2954
2955        switch (event) {
2956        case MSSM_EVENT_RSP_ERROR:
2957                /*
2958                 * Start timer for a delayed retry
2959                 */
2960                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2961                ms->port->stats.ms_retries++;
2962                bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2963                                    &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2964                                    BFA_FCS_RETRY_TIMEOUT);
2965                break;
2966
2967        case MSSM_EVENT_RSP_OK:
2968                /*
2969                 * since plogi is done, now invoke MS related sub-modules
2970                 */
2971                bfa_fcs_lport_fdmi_online(ms);
2972
2973                /*
2974                 * if this is a Vport, go to online state.
2975                 */
2976                if (ms->port->vport) {
2977                        bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2978                        break;
2979                }
2980
2981                /*
2982                 * For a base port we need to get the
2983                 * switch's IP address.
2984                 */
2985                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2986                bfa_fcs_lport_ms_send_gmal(ms, NULL);
2987                break;
2988
2989        case MSSM_EVENT_PORT_OFFLINE:
2990                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2991                bfa_fcxp_discard(ms->fcxp);
2992                break;
2993
2994        default:
2995                bfa_sm_fault(ms->port->fcs, event);
2996        }
2997}
2998
2999static void
3000bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
3001                        enum port_ms_event event)
3002{
3003        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3004        bfa_trc(ms->port->fcs, event);
3005
3006        switch (event) {
3007        case MSSM_EVENT_TIMEOUT:
3008                /*
3009                 * Retry Timer Expired. Re-send
3010                 */
3011                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
3012                bfa_fcs_lport_ms_send_plogi(ms, NULL);
3013                break;
3014
3015        case MSSM_EVENT_PORT_OFFLINE:
3016                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3017                bfa_timer_stop(&ms->timer);
3018                break;
3019
3020        default:
3021                bfa_sm_fault(ms->port->fcs, event);
3022        }
3023}
3024
3025static void
3026bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
3027                        enum port_ms_event event)
3028{
3029        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3030        bfa_trc(ms->port->fcs, event);
3031
3032        switch (event) {
3033        case MSSM_EVENT_PORT_OFFLINE:
3034                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3035                break;
3036
3037        case MSSM_EVENT_PORT_FABRIC_RSCN:
3038                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3039                ms->retry_cnt = 0;
3040                bfa_fcs_lport_ms_send_gfn(ms, NULL);
3041                break;
3042
3043        default:
3044                bfa_sm_fault(ms->port->fcs, event);
3045        }
3046}
3047
3048static void
3049bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
3050                                enum port_ms_event event)
3051{
3052        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3053        bfa_trc(ms->port->fcs, event);
3054
3055        switch (event) {
3056        case MSSM_EVENT_FCXP_SENT:
3057                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
3058                break;
3059
3060        case MSSM_EVENT_PORT_OFFLINE:
3061                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3062                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3063                                           &ms->fcxp_wqe);
3064                break;
3065
3066        default:
3067                bfa_sm_fault(ms->port->fcs, event);
3068        }
3069}
3070
3071static void
3072bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
3073                                enum port_ms_event event)
3074{
3075        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3076        bfa_trc(ms->port->fcs, event);
3077
3078        switch (event) {
3079        case MSSM_EVENT_RSP_ERROR:
3080                /*
3081                 * Start timer for a delayed retry
3082                 */
3083                if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
3084                        bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
3085                        ms->port->stats.ms_retries++;
3086                        bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3087                                &ms->timer, bfa_fcs_lport_ms_timeout, ms,
3088                                BFA_FCS_RETRY_TIMEOUT);
3089                } else {
3090                        bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3091                        bfa_fcs_lport_ms_send_gfn(ms, NULL);
3092                        ms->retry_cnt = 0;
3093                }
3094                break;
3095
3096        case MSSM_EVENT_RSP_OK:
3097                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3098                bfa_fcs_lport_ms_send_gfn(ms, NULL);
3099                break;
3100
3101        case MSSM_EVENT_PORT_OFFLINE:
3102                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3103                bfa_fcxp_discard(ms->fcxp);
3104                break;
3105
3106        default:
3107                bfa_sm_fault(ms->port->fcs, event);
3108        }
3109}
3110
3111static void
3112bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
3113                                enum port_ms_event event)
3114{
3115        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3116        bfa_trc(ms->port->fcs, event);
3117
3118        switch (event) {
3119        case MSSM_EVENT_TIMEOUT:
3120                /*
3121                 * Retry Timer Expired. Re-send
3122                 */
3123                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
3124                bfa_fcs_lport_ms_send_gmal(ms, NULL);
3125                break;
3126
3127        case MSSM_EVENT_PORT_OFFLINE:
3128                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3129                bfa_timer_stop(&ms->timer);
3130                break;
3131
3132        default:
3133                bfa_sm_fault(ms->port->fcs, event);
3134        }
3135}
3136/*
3137 *  ms_pvt MS local functions
3138 */
3139
3140static void
3141bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3142{
3143        struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3144        bfa_fcs_lport_t *port = ms->port;
3145        struct fchs_s   fchs;
3146        int             len;
3147        struct bfa_fcxp_s *fcxp;
3148
3149        bfa_trc(port->fcs, port->pid);
3150
3151        fcxp = fcxp_alloced ? fcxp_alloced :
3152               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3153        if (!fcxp) {
3154                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3155                                bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE);
3156                return;
3157        }
3158        ms->fcxp = fcxp;
3159
3160        len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3161                             bfa_fcs_lport_get_fcid(port),
3162                                 port->fabric->lps->pr_nwwn);
3163
3164        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3165                          FC_CLASS_3, len, &fchs,
3166                          bfa_fcs_lport_ms_gmal_response, (void *)ms,
3167                          FC_MAX_PDUSZ, FC_FCCT_TOV);
3168
3169        bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3170}
3171
3172static void
3173bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3174                                void *cbarg, bfa_status_t req_status,
3175                                u32 rsp_len, u32 resid_len,
3176                                struct fchs_s *rsp_fchs)
3177{
3178        struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3179        bfa_fcs_lport_t *port = ms->port;
3180        struct ct_hdr_s         *cthdr = NULL;
3181        struct fcgs_gmal_resp_s *gmal_resp;
3182        struct fcgs_gmal_entry_s *gmal_entry;
3183        u32             num_entries;
3184        u8                      *rsp_str;
3185
3186        bfa_trc(port->fcs, req_status);
3187        bfa_trc(port->fcs, port->port_cfg.pwwn);
3188
3189        /*
3190         * Sanity Checks
3191         */
3192        if (req_status != BFA_STATUS_OK) {
3193                bfa_trc(port->fcs, req_status);
3194                bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3195                return;
3196        }
3197
3198        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3199        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3200
3201        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3202                gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
3203
3204                num_entries = be32_to_cpu(gmal_resp->ms_len);
3205                if (num_entries == 0) {
3206                        bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3207                        return;
3208                }
3209                /*
3210                * The response could contain multiple Entries.
3211                * Entries for SNMP interface, etc.
3212                * We look for the entry with a telnet prefix.
3213                * First "http://" entry refers to IP addr
3214                */
3215
3216                gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
3217                while (num_entries > 0) {
3218                        if (strncmp(gmal_entry->prefix,
3219                                CT_GMAL_RESP_PREFIX_HTTP,
3220                                sizeof(gmal_entry->prefix)) == 0) {
3221
3222                                /*
3223                                * if the IP address is terminating with a '/',
3224                                * remove it.
3225                                * Byte 0 consists of the length of the string.
3226                                */
3227                                rsp_str = &(gmal_entry->prefix[0]);
3228                                if (rsp_str[gmal_entry->len-1] == '/')
3229                                        rsp_str[gmal_entry->len-1] = 0;
3230
3231                                /* copy IP Address to fabric */
3232                                strlcpy(bfa_fcs_lport_get_fabric_ipaddr(port),
3233                                        gmal_entry->ip_addr,
3234                                        BFA_FCS_FABRIC_IPADDR_SZ);
3235                                break;
3236                        } else {
3237                                --num_entries;
3238                                ++gmal_entry;
3239                        }
3240                }
3241
3242                bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3243                return;
3244        }
3245
3246        bfa_trc(port->fcs, cthdr->reason_code);
3247        bfa_trc(port->fcs, cthdr->exp_code);
3248        bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3249}
3250
3251static void
3252bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
3253                        enum port_ms_event event)
3254{
3255        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3256        bfa_trc(ms->port->fcs, event);
3257
3258        switch (event) {
3259        case MSSM_EVENT_FCXP_SENT:
3260                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
3261                break;
3262
3263        case MSSM_EVENT_PORT_OFFLINE:
3264                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3265                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3266                                           &ms->fcxp_wqe);
3267                break;
3268
3269        default:
3270                bfa_sm_fault(ms->port->fcs, event);
3271        }
3272}
3273
3274static void
3275bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
3276                        enum port_ms_event event)
3277{
3278        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3279        bfa_trc(ms->port->fcs, event);
3280
3281        switch (event) {
3282        case MSSM_EVENT_RSP_ERROR:
3283                /*
3284                 * Start timer for a delayed retry
3285                 */
3286                if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
3287                        bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
3288                        ms->port->stats.ms_retries++;
3289                        bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
3290                                &ms->timer, bfa_fcs_lport_ms_timeout, ms,
3291                                BFA_FCS_RETRY_TIMEOUT);
3292                } else {
3293                        bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
3294                        ms->retry_cnt = 0;
3295                }
3296                break;
3297
3298        case MSSM_EVENT_RSP_OK:
3299                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
3300                break;
3301
3302        case MSSM_EVENT_PORT_OFFLINE:
3303                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3304                bfa_fcxp_discard(ms->fcxp);
3305                break;
3306
3307        default:
3308                bfa_sm_fault(ms->port->fcs, event);
3309        }
3310}
3311
3312static void
3313bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
3314                                enum port_ms_event event)
3315{
3316        bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
3317        bfa_trc(ms->port->fcs, event);
3318
3319        switch (event) {
3320        case MSSM_EVENT_TIMEOUT:
3321                /*
3322                 * Retry Timer Expired. Re-send
3323                 */
3324                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
3325                bfa_fcs_lport_ms_send_gfn(ms, NULL);
3326                break;
3327
3328        case MSSM_EVENT_PORT_OFFLINE:
3329                bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3330                bfa_timer_stop(&ms->timer);
3331                break;
3332
3333        default:
3334                bfa_sm_fault(ms->port->fcs, event);
3335        }
3336}
3337/*
3338 *  ms_pvt MS local functions
3339 */
3340
3341static void
3342bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3343{
3344        struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3345        bfa_fcs_lport_t *port = ms->port;
3346        struct fchs_s           fchs;
3347        int                     len;
3348        struct bfa_fcxp_s *fcxp;
3349
3350        bfa_trc(port->fcs, port->pid);
3351
3352        fcxp = fcxp_alloced ? fcxp_alloced :
3353               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3354        if (!fcxp) {
3355                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3356                                bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE);
3357                return;
3358        }
3359        ms->fcxp = fcxp;
3360
3361        len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3362                             bfa_fcs_lport_get_fcid(port),
3363                                 port->fabric->lps->pr_nwwn);
3364
3365        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3366                          FC_CLASS_3, len, &fchs,
3367                          bfa_fcs_lport_ms_gfn_response, (void *)ms,
3368                          FC_MAX_PDUSZ, FC_FCCT_TOV);
3369
3370        bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3371}
3372
3373static void
3374bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3375                        void *cbarg, bfa_status_t req_status, u32 rsp_len,
3376                        u32 resid_len, struct fchs_s *rsp_fchs)
3377{
3378        struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3379        bfa_fcs_lport_t *port = ms->port;
3380        struct ct_hdr_s *cthdr = NULL;
3381        wwn_t          *gfn_resp;
3382
3383        bfa_trc(port->fcs, req_status);
3384        bfa_trc(port->fcs, port->port_cfg.pwwn);
3385
3386        /*
3387         * Sanity Checks
3388         */
3389        if (req_status != BFA_STATUS_OK) {
3390                bfa_trc(port->fcs, req_status);
3391                bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3392                return;
3393        }
3394
3395        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3396        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3397
3398        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3399                gfn_resp = (wwn_t *)(cthdr + 1);
3400                /* check if it has actually changed */
3401                if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
3402                                gfn_resp, sizeof(wwn_t)) != 0)) {
3403                        bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
3404                }
3405                bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3406                return;
3407        }
3408
3409        bfa_trc(port->fcs, cthdr->reason_code);
3410        bfa_trc(port->fcs, cthdr->exp_code);
3411        bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3412}
3413
3414/*
3415 *  ms_pvt MS local functions
3416 */
3417
3418static void
3419bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3420{
3421        struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3422        struct bfa_fcs_lport_s *port = ms->port;
3423        struct fchs_s   fchs;
3424        int     len;
3425        struct bfa_fcxp_s *fcxp;
3426
3427        bfa_trc(port->fcs, port->pid);
3428
3429        fcxp = fcxp_alloced ? fcxp_alloced :
3430               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3431        if (!fcxp) {
3432                port->stats.ms_plogi_alloc_wait++;
3433                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3434                                bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE);
3435                return;
3436        }
3437        ms->fcxp = fcxp;
3438
3439        len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3440                             bfa_hton3b(FC_MGMT_SERVER),
3441                             bfa_fcs_lport_get_fcid(port), 0,
3442                             port->port_cfg.pwwn, port->port_cfg.nwwn,
3443                             bfa_fcport_get_maxfrsize(port->fcs->bfa),
3444                             bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
3445
3446        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3447                          FC_CLASS_3, len, &fchs,
3448                          bfa_fcs_lport_ms_plogi_response, (void *)ms,
3449                          FC_MAX_PDUSZ, FC_ELS_TOV);
3450
3451        port->stats.ms_plogi_sent++;
3452        bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3453}
3454
3455static void
3456bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3457                        void *cbarg, bfa_status_t req_status,
3458                        u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
3459{
3460        struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3461        struct bfa_fcs_lport_s *port = ms->port;
3462        struct fc_els_cmd_s *els_cmd;
3463        struct fc_ls_rjt_s *ls_rjt;
3464
3465        bfa_trc(port->fcs, req_status);
3466        bfa_trc(port->fcs, port->port_cfg.pwwn);
3467
3468        /*
3469         * Sanity Checks
3470         */
3471        if (req_status != BFA_STATUS_OK) {
3472                port->stats.ms_plogi_rsp_err++;
3473                bfa_trc(port->fcs, req_status);
3474                bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3475                return;
3476        }
3477
3478        els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3479
3480        switch (els_cmd->els_code) {
3481
3482        case FC_ELS_ACC:
3483                if (rsp_len < sizeof(struct fc_logi_s)) {
3484                        bfa_trc(port->fcs, rsp_len);
3485                        port->stats.ms_plogi_acc_err++;
3486                        bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3487                        break;
3488                }
3489                port->stats.ms_plogi_accepts++;
3490                bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3491                break;
3492
3493        case FC_ELS_LS_RJT:
3494                ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3495
3496                bfa_trc(port->fcs, ls_rjt->reason_code);
3497                bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3498
3499                port->stats.ms_rejects++;
3500                bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3501                break;
3502
3503        default:
3504                port->stats.ms_plogi_unknown_rsp++;
3505                bfa_trc(port->fcs, els_cmd->els_code);
3506                bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3507        }
3508}
3509
3510static void
3511bfa_fcs_lport_ms_timeout(void *arg)
3512{
3513        struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
3514
3515        ms->port->stats.ms_timeouts++;
3516        bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
3517}
3518
3519
3520void
3521bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
3522{
3523        struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3524
3525        ms->port = port;
3526        bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3527
3528        /*
3529         * Invoke init routines of sub modules.
3530         */
3531        bfa_fcs_lport_fdmi_init(ms);
3532}
3533
3534void
3535bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
3536{
3537        struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3538
3539        ms->port = port;
3540        bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
3541        bfa_fcs_lport_fdmi_offline(ms);
3542}
3543
3544void
3545bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
3546{
3547        struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3548
3549        ms->port = port;
3550        bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
3551}
3552void
3553bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
3554{
3555        struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3556
3557        /* todo.  Handle this only  when in Online state */
3558        if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
3559                bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
3560}
3561
3562/*
3563 * @page ns_sm_info VPORT NS State Machine
3564 *
3565 * @section ns_sm_interactions VPORT NS State Machine Interactions
3566 *
3567 * @section ns_sm VPORT NS State Machine
3568 * img ns_sm.jpg
3569 */
3570
3571/*
3572 * forward declarations
3573 */
3574static void     bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
3575                                           struct bfa_fcxp_s *fcxp_alloced);
3576static void     bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
3577                                             struct bfa_fcxp_s *fcxp_alloced);
3578static void     bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
3579                                            struct bfa_fcxp_s *fcxp_alloced);
3580static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
3581                                            struct bfa_fcxp_s *fcxp_alloced);
3582static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
3583                                            struct bfa_fcxp_s *fcxp_alloced);
3584static void     bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg,
3585                                        struct bfa_fcxp_s *fcxp_alloced);
3586static void     bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg,
3587                                        struct bfa_fcxp_s *fcxp_alloced);
3588static void     bfa_fcs_lport_ns_timeout(void *arg);
3589static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
3590                                               struct bfa_fcxp_s *fcxp,
3591                                               void *cbarg,
3592                                               bfa_status_t req_status,
3593                                               u32 rsp_len,
3594                                               u32 resid_len,
3595                                               struct fchs_s *rsp_fchs);
3596static void     bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
3597                                                 struct bfa_fcxp_s *fcxp,
3598                                                 void *cbarg,
3599                                                 bfa_status_t req_status,
3600                                                 u32 rsp_len,
3601                                                 u32 resid_len,
3602                                                 struct fchs_s *rsp_fchs);
3603static void     bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
3604                                                struct bfa_fcxp_s *fcxp,
3605                                                void *cbarg,
3606                                                bfa_status_t req_status,
3607                                                u32 rsp_len,
3608                                                u32 resid_len,
3609                                                struct fchs_s *rsp_fchs);
3610static void     bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
3611                                                struct bfa_fcxp_s *fcxp,
3612                                                void *cbarg,
3613                                                bfa_status_t req_status,
3614                                                u32 rsp_len,
3615                                                u32 resid_len,
3616                                                struct fchs_s *rsp_fchs);
3617static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3618                                                struct bfa_fcxp_s *fcxp,
3619                                                void *cbarg,
3620                                                bfa_status_t req_status,
3621                                                u32 rsp_len,
3622                                                u32 resid_len,
3623                                                struct fchs_s *rsp_fchs);
3624static void     bfa_fcs_lport_ns_rnn_id_response(void *fcsarg,
3625                                                struct bfa_fcxp_s *fcxp,
3626                                                void *cbarg,
3627                                                bfa_status_t req_status,
3628                                                u32 rsp_len,
3629                                                u32 resid_len,
3630                                                struct fchs_s *rsp_fchs);
3631static void     bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg,
3632                                                struct bfa_fcxp_s *fcxp,
3633                                                void *cbarg,
3634                                                bfa_status_t req_status,
3635                                                u32 rsp_len,
3636                                                u32 resid_len,
3637                                                struct fchs_s *rsp_fchs);
3638static void     bfa_fcs_lport_ns_process_gidft_pids(
3639                                struct bfa_fcs_lport_s *port,
3640                                u32 *pid_buf, u32 n_pids);
3641
3642static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3643/*
3644 *  fcs_ns_sm FCS nameserver interface state machine
3645 */
3646
3647/*
3648 * VPort NS State Machine events
3649 */
3650enum vport_ns_event {
3651        NSSM_EVENT_PORT_ONLINE = 1,
3652        NSSM_EVENT_PORT_OFFLINE = 2,
3653        NSSM_EVENT_PLOGI_SENT = 3,
3654        NSSM_EVENT_RSP_OK = 4,
3655        NSSM_EVENT_RSP_ERROR = 5,
3656        NSSM_EVENT_TIMEOUT = 6,
3657        NSSM_EVENT_NS_QUERY = 7,
3658        NSSM_EVENT_RSPNID_SENT = 8,
3659        NSSM_EVENT_RFTID_SENT = 9,
3660        NSSM_EVENT_RFFID_SENT = 10,
3661        NSSM_EVENT_GIDFT_SENT = 11,
3662        NSSM_EVENT_RNNID_SENT = 12,
3663        NSSM_EVENT_RSNN_NN_SENT = 13,
3664};
3665
3666static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3667                                           enum vport_ns_event event);
3668static void     bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3669                                                 enum vport_ns_event event);
3670static void     bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3671                                         enum vport_ns_event event);
3672static void     bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3673                                               enum vport_ns_event event);
3674static void     bfa_fcs_lport_ns_sm_sending_rspn_id(
3675                                        struct bfa_fcs_lport_ns_s *ns,
3676                                        enum vport_ns_event event);
3677static void     bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3678                                           enum vport_ns_event event);
3679static void     bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3680                                                 enum vport_ns_event event);
3681static void     bfa_fcs_lport_ns_sm_sending_rft_id(
3682                                        struct bfa_fcs_lport_ns_s *ns,
3683                                        enum vport_ns_event event);
3684static void     bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3685                                                enum vport_ns_event event);
3686static void     bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3687                                          enum vport_ns_event event);
3688static void     bfa_fcs_lport_ns_sm_sending_rff_id(
3689                                        struct bfa_fcs_lport_ns_s *ns,
3690                                        enum vport_ns_event event);
3691static void     bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3692                                                enum vport_ns_event event);
3693static void     bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3694                                          enum vport_ns_event event);
3695static void     bfa_fcs_lport_ns_sm_sending_gid_ft(
3696                                        struct bfa_fcs_lport_ns_s *ns,
3697                                        enum vport_ns_event event);
3698static void     bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3699                                          enum vport_ns_event event);
3700static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3701                                                enum vport_ns_event event);
3702static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3703                                          enum vport_ns_event event);
3704static void     bfa_fcs_lport_ns_sm_sending_rnn_id(
3705                                        struct bfa_fcs_lport_ns_s *ns,
3706                                        enum vport_ns_event event);
3707static void     bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3708                                        enum vport_ns_event event);
3709static void     bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3710                                                enum vport_ns_event event);
3711static void     bfa_fcs_lport_ns_sm_sending_rsnn_nn(
3712                                        struct bfa_fcs_lport_ns_s *ns,
3713                                        enum vport_ns_event event);
3714static void     bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3715                                                enum vport_ns_event event);
3716static void     bfa_fcs_lport_ns_sm_rsnn_nn_retry(
3717                                        struct bfa_fcs_lport_ns_s *ns,
3718                                        enum vport_ns_event event);
3719/*
3720 *      Start in offline state - awaiting linkup
3721 */
3722static void
3723bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3724                        enum vport_ns_event event)
3725{
3726        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3727        bfa_trc(ns->port->fcs, event);
3728
3729        switch (event) {
3730        case NSSM_EVENT_PORT_ONLINE:
3731                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3732                bfa_fcs_lport_ns_send_plogi(ns, NULL);
3733                break;
3734
3735        case NSSM_EVENT_PORT_OFFLINE:
3736                break;
3737
3738        default:
3739                bfa_sm_fault(ns->port->fcs, event);
3740        }
3741}
3742
3743static void
3744bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3745                        enum vport_ns_event event)
3746{
3747        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3748        bfa_trc(ns->port->fcs, event);
3749
3750        switch (event) {
3751        case NSSM_EVENT_PLOGI_SENT:
3752                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3753                break;
3754
3755        case NSSM_EVENT_PORT_OFFLINE:
3756                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3757                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3758                                           &ns->fcxp_wqe);
3759                break;
3760
3761        default:
3762                bfa_sm_fault(ns->port->fcs, event);
3763        }
3764}
3765
3766static void
3767bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3768                        enum vport_ns_event event)
3769{
3770        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3771        bfa_trc(ns->port->fcs, event);
3772
3773        switch (event) {
3774        case NSSM_EVENT_RSP_ERROR:
3775                /*
3776                 * Start timer for a delayed retry
3777                 */
3778                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3779                ns->port->stats.ns_retries++;
3780                bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3781                                    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3782                                    BFA_FCS_RETRY_TIMEOUT);
3783                break;
3784
3785        case NSSM_EVENT_RSP_OK:
3786                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3787                ns->num_rnnid_retries = 0;
3788                bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3789                break;
3790
3791        case NSSM_EVENT_PORT_OFFLINE:
3792                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3793                bfa_fcxp_discard(ns->fcxp);
3794                break;
3795
3796        default:
3797                bfa_sm_fault(ns->port->fcs, event);
3798        }
3799}
3800
3801static void
3802bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3803                                enum vport_ns_event event)
3804{
3805        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3806        bfa_trc(ns->port->fcs, event);
3807
3808        switch (event) {
3809        case NSSM_EVENT_TIMEOUT:
3810                /*
3811                 * Retry Timer Expired. Re-send
3812                 */
3813                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3814                bfa_fcs_lport_ns_send_plogi(ns, NULL);
3815                break;
3816
3817        case NSSM_EVENT_PORT_OFFLINE:
3818                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3819                bfa_timer_stop(&ns->timer);
3820                break;
3821
3822        default:
3823                bfa_sm_fault(ns->port->fcs, event);
3824        }
3825}
3826
3827static void
3828bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3829                                        enum vport_ns_event event)
3830{
3831        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3832        bfa_trc(ns->port->fcs, event);
3833
3834        switch (event) {
3835        case NSSM_EVENT_RNNID_SENT:
3836                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id);
3837                break;
3838
3839        case NSSM_EVENT_PORT_OFFLINE:
3840                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3841                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3842                                                &ns->fcxp_wqe);
3843                break;
3844        default:
3845                bfa_sm_fault(ns->port->fcs, event);
3846        }
3847}
3848
3849static void
3850bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3851                                enum vport_ns_event event)
3852{
3853        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3854        bfa_trc(ns->port->fcs, event);
3855
3856        switch (event) {
3857        case NSSM_EVENT_RSP_OK:
3858                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3859                ns->num_rnnid_retries = 0;
3860                ns->num_rsnn_nn_retries = 0;
3861                bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3862                break;
3863
3864        case NSSM_EVENT_RSP_ERROR:
3865                if (ns->num_rnnid_retries < BFA_FCS_MAX_NS_RETRIES) {
3866                        bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id_retry);
3867                        ns->port->stats.ns_retries++;
3868                        ns->num_rnnid_retries++;
3869                        bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3870                                &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3871                                BFA_FCS_RETRY_TIMEOUT);
3872                } else {
3873                        bfa_sm_set_state(ns,
3874                                bfa_fcs_lport_ns_sm_sending_rspn_id);
3875                        bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3876                }
3877                break;
3878
3879        case NSSM_EVENT_PORT_OFFLINE:
3880                bfa_fcxp_discard(ns->fcxp);
3881                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3882                break;
3883
3884        default:
3885                bfa_sm_fault(ns->port->fcs, event);
3886        }
3887}
3888
3889static void
3890bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3891                                enum vport_ns_event event)
3892{
3893        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3894        bfa_trc(ns->port->fcs, event);
3895
3896        switch (event) {
3897        case NSSM_EVENT_TIMEOUT:
3898                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3899                bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3900                break;
3901
3902        case NSSM_EVENT_PORT_OFFLINE:
3903                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3904                bfa_timer_stop(&ns->timer);
3905                break;
3906
3907        default:
3908                bfa_sm_fault(ns->port->fcs, event);
3909        }
3910}
3911
3912static void
3913bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3914                                        enum vport_ns_event event)
3915{
3916        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3917        bfa_trc(ns->port->fcs, event);
3918
3919        switch (event) {
3920        case NSSM_EVENT_RSNN_NN_SENT:
3921                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn);
3922                break;
3923
3924        case NSSM_EVENT_PORT_OFFLINE:
3925                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3926                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3927                        &ns->fcxp_wqe);
3928                break;
3929
3930        default:
3931                bfa_sm_fault(ns->port->fcs, event);
3932        }
3933}
3934
3935static void
3936bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3937                                enum vport_ns_event event)
3938{
3939        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3940        bfa_trc(ns->port->fcs, event);
3941
3942        switch (event) {
3943        case NSSM_EVENT_RSP_OK:
3944                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3945                ns->num_rsnn_nn_retries = 0;
3946                bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3947                break;
3948
3949        case NSSM_EVENT_RSP_ERROR:
3950                if (ns->num_rsnn_nn_retries < BFA_FCS_MAX_NS_RETRIES) {
3951                        bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn_retry);
3952                        ns->port->stats.ns_retries++;
3953                        ns->num_rsnn_nn_retries++;
3954                        bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3955                                        &ns->timer, bfa_fcs_lport_ns_timeout,
3956                                        ns, BFA_FCS_RETRY_TIMEOUT);
3957                } else {
3958                        bfa_sm_set_state(ns,
3959                                bfa_fcs_lport_ns_sm_sending_rspn_id);
3960                        bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3961                }
3962                break;
3963
3964        case NSSM_EVENT_PORT_OFFLINE:
3965                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3966                bfa_fcxp_discard(ns->fcxp);
3967                break;
3968
3969        default:
3970                bfa_sm_fault(ns->port->fcs, event);
3971        }
3972}
3973
3974static void
3975bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s *ns,
3976                                        enum vport_ns_event event)
3977{
3978        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3979        bfa_trc(ns->port->fcs, event);
3980
3981        switch (event) {
3982        case NSSM_EVENT_TIMEOUT:
3983                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3984                bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3985                break;
3986
3987        case NSSM_EVENT_PORT_OFFLINE:
3988                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3989                bfa_timer_stop(&ns->timer);
3990                break;
3991
3992        default:
3993                bfa_sm_fault(ns->port->fcs, event);
3994        }
3995}
3996
3997static void
3998bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3999                                   enum vport_ns_event event)
4000{
4001        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4002        bfa_trc(ns->port->fcs, event);
4003
4004        switch (event) {
4005        case NSSM_EVENT_RSPNID_SENT:
4006                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
4007                break;
4008
4009        case NSSM_EVENT_PORT_OFFLINE:
4010                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4011                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4012                                           &ns->fcxp_wqe);
4013                break;
4014
4015        default:
4016                bfa_sm_fault(ns->port->fcs, event);
4017        }
4018}
4019
4020static void
4021bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
4022                        enum vport_ns_event event)
4023{
4024        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4025        bfa_trc(ns->port->fcs, event);
4026
4027        switch (event) {
4028        case NSSM_EVENT_RSP_ERROR:
4029                /*
4030                 * Start timer for a delayed retry
4031                 */
4032                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
4033                ns->port->stats.ns_retries++;
4034                bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4035                                    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4036                                    BFA_FCS_RETRY_TIMEOUT);
4037                break;
4038
4039        case NSSM_EVENT_RSP_OK:
4040                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
4041                bfa_fcs_lport_ns_send_rft_id(ns, NULL);
4042                break;
4043
4044        case NSSM_EVENT_PORT_OFFLINE:
4045                bfa_fcxp_discard(ns->fcxp);
4046                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4047                break;
4048
4049        default:
4050                bfa_sm_fault(ns->port->fcs, event);
4051        }
4052}
4053
4054static void
4055bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
4056                                enum vport_ns_event event)
4057{
4058        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4059        bfa_trc(ns->port->fcs, event);
4060
4061        switch (event) {
4062        case NSSM_EVENT_TIMEOUT:
4063                /*
4064                 * Retry Timer Expired. Re-send
4065                 */
4066                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
4067                bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
4068                break;
4069
4070        case NSSM_EVENT_PORT_OFFLINE:
4071                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4072                bfa_timer_stop(&ns->timer);
4073                break;
4074
4075        default:
4076                bfa_sm_fault(ns->port->fcs, event);
4077        }
4078}
4079
4080static void
4081bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
4082                                  enum vport_ns_event event)
4083{
4084        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4085        bfa_trc(ns->port->fcs, event);
4086
4087        switch (event) {
4088        case NSSM_EVENT_RFTID_SENT:
4089                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
4090                break;
4091
4092        case NSSM_EVENT_PORT_OFFLINE:
4093                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4094                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4095                                           &ns->fcxp_wqe);
4096                break;
4097
4098        default:
4099                bfa_sm_fault(ns->port->fcs, event);
4100        }
4101}
4102
4103static void
4104bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
4105                        enum vport_ns_event event)
4106{
4107        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4108        bfa_trc(ns->port->fcs, event);
4109
4110        switch (event) {
4111        case NSSM_EVENT_RSP_OK:
4112                /* Now move to register FC4 Features */
4113                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
4114                bfa_fcs_lport_ns_send_rff_id(ns, NULL);
4115                break;
4116
4117        case NSSM_EVENT_RSP_ERROR:
4118                /*
4119                 * Start timer for a delayed retry
4120                 */
4121                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
4122                ns->port->stats.ns_retries++;
4123                bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4124                                    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4125                                    BFA_FCS_RETRY_TIMEOUT);
4126                break;
4127
4128        case NSSM_EVENT_PORT_OFFLINE:
4129                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4130                bfa_fcxp_discard(ns->fcxp);
4131                break;
4132
4133        default:
4134                bfa_sm_fault(ns->port->fcs, event);
4135        }
4136}
4137
4138static void
4139bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
4140                                enum vport_ns_event event)
4141{
4142        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4143        bfa_trc(ns->port->fcs, event);
4144
4145        switch (event) {
4146        case NSSM_EVENT_TIMEOUT:
4147                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
4148                bfa_fcs_lport_ns_send_rft_id(ns, NULL);
4149                break;
4150
4151        case NSSM_EVENT_PORT_OFFLINE:
4152                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4153                bfa_timer_stop(&ns->timer);
4154                break;
4155
4156        default:
4157                bfa_sm_fault(ns->port->fcs, event);
4158        }
4159}
4160
4161static void
4162bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
4163                                  enum vport_ns_event event)
4164{
4165        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4166        bfa_trc(ns->port->fcs, event);
4167
4168        switch (event) {
4169        case NSSM_EVENT_RFFID_SENT:
4170                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
4171                break;
4172
4173        case NSSM_EVENT_PORT_OFFLINE:
4174                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4175                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4176                                           &ns->fcxp_wqe);
4177                break;
4178
4179        default:
4180                bfa_sm_fault(ns->port->fcs, event);
4181        }
4182}
4183
4184static void
4185bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
4186                        enum vport_ns_event event)
4187{
4188        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4189        bfa_trc(ns->port->fcs, event);
4190
4191        switch (event) {
4192        case NSSM_EVENT_RSP_OK:
4193
4194                /*
4195                 * If min cfg mode is enabled, we donot initiate rport
4196                 * discovery with the fabric. Instead, we will retrieve the
4197                 * boot targets from HAL/FW.
4198                 */
4199                if (__fcs_min_cfg(ns->port->fcs)) {
4200                        bfa_fcs_lport_ns_boot_target_disc(ns->port);
4201                        bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
4202                        return;
4203                }
4204
4205                /*
4206                 * If the port role is Initiator Mode issue NS query.
4207                 * If it is Target Mode, skip this and go to online.
4208                 */
4209                if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
4210                        bfa_sm_set_state(ns,
4211                                bfa_fcs_lport_ns_sm_sending_gid_ft);
4212                        bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4213                }
4214                /*
4215                 * kick off mgmt srvr state machine
4216                 */
4217                bfa_fcs_lport_ms_online(ns->port);
4218                break;
4219
4220        case NSSM_EVENT_RSP_ERROR:
4221                /*
4222                 * Start timer for a delayed retry
4223                 */
4224                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
4225                ns->port->stats.ns_retries++;
4226                bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4227                                    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4228                                    BFA_FCS_RETRY_TIMEOUT);
4229                break;
4230
4231        case NSSM_EVENT_PORT_OFFLINE:
4232                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4233                bfa_fcxp_discard(ns->fcxp);
4234                break;
4235
4236        default:
4237                bfa_sm_fault(ns->port->fcs, event);
4238        }
4239}
4240
4241static void
4242bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
4243                                enum vport_ns_event event)
4244{
4245        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4246        bfa_trc(ns->port->fcs, event);
4247
4248        switch (event) {
4249        case NSSM_EVENT_TIMEOUT:
4250                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
4251                bfa_fcs_lport_ns_send_rff_id(ns, NULL);
4252                break;
4253
4254        case NSSM_EVENT_PORT_OFFLINE:
4255                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4256                bfa_timer_stop(&ns->timer);
4257                break;
4258
4259        default:
4260                bfa_sm_fault(ns->port->fcs, event);
4261        }
4262}
4263static void
4264bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
4265                                  enum vport_ns_event event)
4266{
4267        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4268        bfa_trc(ns->port->fcs, event);
4269
4270        switch (event) {
4271        case NSSM_EVENT_GIDFT_SENT:
4272                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
4273                break;
4274
4275        case NSSM_EVENT_PORT_OFFLINE:
4276                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4277                bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4278                                           &ns->fcxp_wqe);
4279                break;
4280
4281        default:
4282                bfa_sm_fault(ns->port->fcs, event);
4283        }
4284}
4285
4286static void
4287bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
4288                        enum vport_ns_event event)
4289{
4290        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4291        bfa_trc(ns->port->fcs, event);
4292
4293        switch (event) {
4294        case NSSM_EVENT_RSP_OK:
4295                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
4296                break;
4297
4298        case NSSM_EVENT_RSP_ERROR:
4299                /*
4300                 * TBD: for certain reject codes, we don't need to retry
4301                 */
4302                /*
4303                 * Start timer for a delayed retry
4304                 */
4305                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
4306                ns->port->stats.ns_retries++;
4307                bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
4308                                    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
4309                                    BFA_FCS_RETRY_TIMEOUT);
4310                break;
4311
4312        case NSSM_EVENT_PORT_OFFLINE:
4313                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4314                bfa_fcxp_discard(ns->fcxp);
4315                break;
4316
4317        case  NSSM_EVENT_NS_QUERY:
4318                break;
4319
4320        default:
4321                bfa_sm_fault(ns->port->fcs, event);
4322        }
4323}
4324
4325static void
4326bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
4327                                enum vport_ns_event event)
4328{
4329        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4330        bfa_trc(ns->port->fcs, event);
4331
4332        switch (event) {
4333        case NSSM_EVENT_TIMEOUT:
4334                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
4335                bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4336                break;
4337
4338        case NSSM_EVENT_PORT_OFFLINE:
4339                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4340                bfa_timer_stop(&ns->timer);
4341                break;
4342
4343        default:
4344                bfa_sm_fault(ns->port->fcs, event);
4345        }
4346}
4347
4348static void
4349bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
4350                        enum vport_ns_event event)
4351{
4352        bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4353        bfa_trc(ns->port->fcs, event);
4354
4355        switch (event) {
4356        case NSSM_EVENT_PORT_OFFLINE:
4357                bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4358                break;
4359
4360        case NSSM_EVENT_NS_QUERY:
4361                /*
4362                 * If the port role is Initiator Mode issue NS query.
4363                 * If it is Target Mode, skip this and go to online.
4364                 */
4365                if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
4366                        bfa_sm_set_state(ns,
4367                                bfa_fcs_lport_ns_sm_sending_gid_ft);
4368                        bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4369                }
4370                break;
4371
4372        default:
4373                bfa_sm_fault(ns->port->fcs, event);
4374        }
4375}
4376
4377
4378
4379/*
4380 *  ns_pvt Nameserver local functions
4381 */
4382
4383static void
4384bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4385{
4386        struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4387        struct bfa_fcs_lport_s *port = ns->port;
4388        struct fchs_s fchs;
4389        int             len;
4390        struct bfa_fcxp_s *fcxp;
4391
4392        bfa_trc(port->fcs, port->pid);
4393
4394        fcxp = fcxp_alloced ? fcxp_alloced :
4395               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4396        if (!fcxp) {
4397                port->stats.ns_plogi_alloc_wait++;
4398                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4399                                bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE);
4400                return;
4401        }
4402        ns->fcxp = fcxp;
4403
4404        len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4405                             bfa_hton3b(FC_NAME_SERVER),
4406                             bfa_fcs_lport_get_fcid(port), 0,
4407                             port->port_cfg.pwwn, port->port_cfg.nwwn,
4408                             bfa_fcport_get_maxfrsize(port->fcs->bfa),
4409                             bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
4410
4411        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4412                          FC_CLASS_3, len, &fchs,
4413                          bfa_fcs_lport_ns_plogi_response, (void *)ns,
4414                          FC_MAX_PDUSZ, FC_ELS_TOV);
4415        port->stats.ns_plogi_sent++;
4416
4417        bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
4418}
4419
4420static void
4421bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4422                        void *cbarg, bfa_status_t req_status, u32 rsp_len,
4423                       u32 resid_len, struct fchs_s *rsp_fchs)
4424{
4425        struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4426        struct bfa_fcs_lport_s *port = ns->port;
4427        /* struct fc_logi_s *plogi_resp; */
4428        struct fc_els_cmd_s *els_cmd;
4429        struct fc_ls_rjt_s *ls_rjt;
4430
4431        bfa_trc(port->fcs, req_status);
4432        bfa_trc(port->fcs, port->port_cfg.pwwn);
4433
4434        /*
4435         * Sanity Checks
4436         */
4437        if (req_status != BFA_STATUS_OK) {
4438                bfa_trc(port->fcs, req_status);
4439                port->stats.ns_plogi_rsp_err++;
4440                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4441                return;
4442        }
4443
4444        els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4445
4446        switch (els_cmd->els_code) {
4447
4448        case FC_ELS_ACC:
4449                if (rsp_len < sizeof(struct fc_logi_s)) {
4450                        bfa_trc(port->fcs, rsp_len);
4451                        port->stats.ns_plogi_acc_err++;
4452                        bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4453                        break;
4454                }
4455                port->stats.ns_plogi_accepts++;
4456                bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4457                break;
4458
4459        case FC_ELS_LS_RJT:
4460                ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4461
4462                bfa_trc(port->fcs, ls_rjt->reason_code);
4463                bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4464
4465                port->stats.ns_rejects++;
4466
4467                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4468                break;
4469
4470        default:
4471                port->stats.ns_plogi_unknown_rsp++;
4472                bfa_trc(port->fcs, els_cmd->els_code);
4473                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4474        }
4475}
4476
4477/*
4478 * Register node name for port_id
4479 */
4480static void
4481bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4482{
4483        struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4484        struct bfa_fcs_lport_s *port = ns->port;
4485        struct fchs_s  fchs;
4486        int     len;
4487        struct bfa_fcxp_s *fcxp;
4488
4489        bfa_trc(port->fcs, port->port_cfg.pwwn);
4490
4491        fcxp = fcxp_alloced ? fcxp_alloced :
4492                        bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4493        if (!fcxp) {
4494                port->stats.ns_rnnid_alloc_wait++;
4495                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4496                                bfa_fcs_lport_ns_send_rnn_id, ns, BFA_TRUE);
4497                return;
4498        }
4499
4500        ns->fcxp = fcxp;
4501
4502        len = fc_rnnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4503                                bfa_fcs_lport_get_fcid(port),
4504                                bfa_fcs_lport_get_fcid(port),
4505                                bfa_fcs_lport_get_nwwn(port));
4506
4507        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4508                          FC_CLASS_3, len, &fchs,
4509                          bfa_fcs_lport_ns_rnn_id_response, (void *)ns,
4510                          FC_MAX_PDUSZ, FC_FCCT_TOV);
4511
4512        port->stats.ns_rnnid_sent++;
4513        bfa_sm_send_event(ns, NSSM_EVENT_RNNID_SENT);
4514}
4515
4516static void
4517bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4518                                void *cbarg, bfa_status_t req_status,
4519                                u32 rsp_len, u32 resid_len,
4520                                struct fchs_s *rsp_fchs)
4521
4522{
4523        struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4524        struct bfa_fcs_lport_s *port = ns->port;
4525        struct ct_hdr_s *cthdr = NULL;
4526
4527        bfa_trc(port->fcs, port->port_cfg.pwwn);
4528
4529        /*
4530         * Sanity Checks
4531         */
4532        if (req_status != BFA_STATUS_OK) {
4533                bfa_trc(port->fcs, req_status);
4534                port->stats.ns_rnnid_rsp_err++;
4535                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4536                return;
4537        }
4538
4539        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4540        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4541
4542        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4543                port->stats.ns_rnnid_accepts++;
4544                bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4545                return;
4546        }
4547
4548        port->stats.ns_rnnid_rejects++;
4549        bfa_trc(port->fcs, cthdr->reason_code);
4550        bfa_trc(port->fcs, cthdr->exp_code);
4551        bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4552}
4553
4554/*
4555 * Register the symbolic node name for a given node name.
4556 */
4557static void
4558bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4559{
4560        struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4561        struct bfa_fcs_lport_s *port = ns->port;
4562        struct fchs_s  fchs;
4563        int     len;
4564        struct bfa_fcxp_s *fcxp;
4565        u8 *nsymbl;
4566
4567        bfa_trc(port->fcs, port->port_cfg.pwwn);
4568
4569        fcxp = fcxp_alloced ? fcxp_alloced :
4570                        bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4571        if (!fcxp) {
4572                port->stats.ns_rsnn_nn_alloc_wait++;
4573                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4574                                bfa_fcs_lport_ns_send_rsnn_nn, ns, BFA_TRUE);
4575                return;
4576        }
4577        ns->fcxp = fcxp;
4578
4579        nsymbl = (u8 *) &(bfa_fcs_lport_get_nsym_name(
4580                                        bfa_fcs_get_base_port(port->fcs)));
4581
4582        len = fc_rsnn_nn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4583                                bfa_fcs_lport_get_fcid(port),
4584                                bfa_fcs_lport_get_nwwn(port), nsymbl);
4585
4586        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4587                          FC_CLASS_3, len, &fchs,
4588                          bfa_fcs_lport_ns_rsnn_nn_response, (void *)ns,
4589                          FC_MAX_PDUSZ, FC_FCCT_TOV);
4590
4591        port->stats.ns_rsnn_nn_sent++;
4592
4593        bfa_sm_send_event(ns, NSSM_EVENT_RSNN_NN_SENT);
4594}
4595
4596static void
4597bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4598                                void *cbarg, bfa_status_t req_status,
4599                                u32 rsp_len, u32 resid_len,
4600                                struct fchs_s *rsp_fchs)
4601{
4602        struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4603        struct bfa_fcs_lport_s *port = ns->port;
4604        struct ct_hdr_s *cthdr = NULL;
4605
4606        bfa_trc(port->fcs, port->port_cfg.pwwn);
4607
4608        /*
4609         * Sanity Checks
4610         */
4611        if (req_status != BFA_STATUS_OK) {
4612                bfa_trc(port->fcs, req_status);
4613                port->stats.ns_rsnn_nn_rsp_err++;
4614                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4615                return;
4616        }
4617
4618        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4619        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4620
4621        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4622                port->stats.ns_rsnn_nn_accepts++;
4623                bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4624                return;
4625        }
4626
4627        port->stats.ns_rsnn_nn_rejects++;
4628        bfa_trc(port->fcs, cthdr->reason_code);
4629        bfa_trc(port->fcs, cthdr->exp_code);
4630        bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4631}
4632
4633/*
4634 * Register the symbolic port name.
4635 */
4636static void
4637bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4638{
4639        struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4640        struct bfa_fcs_lport_s *port = ns->port;
4641        struct fchs_s fchs;
4642        int             len;
4643        struct bfa_fcxp_s *fcxp;
4644        u8         symbl[256];
4645        u8         *psymbl = &symbl[0];
4646
4647        memset(symbl, 0, sizeof(symbl));
4648
4649        bfa_trc(port->fcs, port->port_cfg.pwwn);
4650
4651        fcxp = fcxp_alloced ? fcxp_alloced :
4652               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4653        if (!fcxp) {
4654                port->stats.ns_rspnid_alloc_wait++;
4655                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4656                                bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE);
4657                return;
4658        }
4659        ns->fcxp = fcxp;
4660
4661        /*
4662         * for V-Port, form a Port Symbolic Name
4663         */
4664        if (port->vport) {
4665                /*
4666                 * For Vports, we append the vport's port symbolic name
4667                 * to that of the base port.
4668                 */
4669
4670                strlcpy(symbl,
4671                        (char *)&(bfa_fcs_lport_get_psym_name
4672                         (bfa_fcs_get_base_port(port->fcs))),
4673                        sizeof(symbl));
4674
4675                strlcat(symbl, (char *)&(bfa_fcs_lport_get_psym_name(port)),
4676                        sizeof(symbl));
4677        } else {
4678                psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
4679        }
4680
4681        len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4682                              bfa_fcs_lport_get_fcid(port), 0, psymbl);
4683
4684        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4685                          FC_CLASS_3, len, &fchs,
4686                          bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
4687                          FC_MAX_PDUSZ, FC_FCCT_TOV);
4688
4689        port->stats.ns_rspnid_sent++;
4690
4691        bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
4692}
4693
4694static void
4695bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4696                                 void *cbarg, bfa_status_t req_status,
4697                                 u32 rsp_len, u32 resid_len,
4698                                 struct fchs_s *rsp_fchs)
4699{
4700        struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4701        struct bfa_fcs_lport_s *port = ns->port;
4702        struct ct_hdr_s *cthdr = NULL;
4703
4704        bfa_trc(port->fcs, port->port_cfg.pwwn);
4705
4706        /*
4707         * Sanity Checks
4708         */
4709        if (req_status != BFA_STATUS_OK) {
4710                bfa_trc(port->fcs, req_status);
4711                port->stats.ns_rspnid_rsp_err++;
4712                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4713                return;
4714        }
4715
4716        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4717        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4718
4719        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4720                port->stats.ns_rspnid_accepts++;
4721                bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4722                return;
4723        }
4724
4725        port->stats.ns_rspnid_rejects++;
4726        bfa_trc(port->fcs, cthdr->reason_code);
4727        bfa_trc(port->fcs, cthdr->exp_code);
4728        bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4729}
4730
4731/*
4732 * Register FC4-Types
4733 */
4734static void
4735bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4736{
4737        struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4738        struct bfa_fcs_lport_s *port = ns->port;
4739        struct fchs_s fchs;
4740        int             len;
4741        struct bfa_fcxp_s *fcxp;
4742
4743        bfa_trc(port->fcs, port->port_cfg.pwwn);
4744
4745        fcxp = fcxp_alloced ? fcxp_alloced :
4746               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4747        if (!fcxp) {
4748                port->stats.ns_rftid_alloc_wait++;
4749                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4750                                bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE);
4751                return;
4752        }
4753        ns->fcxp = fcxp;
4754
4755        len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4756                     bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
4757
4758        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4759                          FC_CLASS_3, len, &fchs,
4760                          bfa_fcs_lport_ns_rft_id_response, (void *)ns,
4761                          FC_MAX_PDUSZ, FC_FCCT_TOV);
4762
4763        port->stats.ns_rftid_sent++;
4764        bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
4765}
4766
4767static void
4768bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4769                                void *cbarg, bfa_status_t req_status,
4770                                u32 rsp_len, u32 resid_len,
4771                                struct fchs_s *rsp_fchs)
4772{
4773        struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4774        struct bfa_fcs_lport_s *port = ns->port;
4775        struct ct_hdr_s *cthdr = NULL;
4776
4777        bfa_trc(port->fcs, port->port_cfg.pwwn);
4778
4779        /*
4780         * Sanity Checks
4781         */
4782        if (req_status != BFA_STATUS_OK) {
4783                bfa_trc(port->fcs, req_status);
4784                port->stats.ns_rftid_rsp_err++;
4785                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4786                return;
4787        }
4788
4789        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4790        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4791
4792        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4793                port->stats.ns_rftid_accepts++;
4794                bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4795                return;
4796        }
4797
4798        port->stats.ns_rftid_rejects++;
4799        bfa_trc(port->fcs, cthdr->reason_code);
4800        bfa_trc(port->fcs, cthdr->exp_code);
4801        bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4802}
4803
4804/*
4805 * Register FC4-Features : Should be done after RFT_ID
4806 */
4807static void
4808bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4809{
4810        struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4811        struct bfa_fcs_lport_s *port = ns->port;
4812        struct fchs_s fchs;
4813        int             len;
4814        struct bfa_fcxp_s *fcxp;
4815        u8                      fc4_ftrs = 0;
4816
4817        bfa_trc(port->fcs, port->port_cfg.pwwn);
4818
4819        fcxp = fcxp_alloced ? fcxp_alloced :
4820               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4821        if (!fcxp) {
4822                port->stats.ns_rffid_alloc_wait++;
4823                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4824                                bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE);
4825                return;
4826        }
4827        ns->fcxp = fcxp;
4828
4829        if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
4830                fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
4831
4832        len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4833                             bfa_fcs_lport_get_fcid(port), 0,
4834                                 FC_TYPE_FCP, fc4_ftrs);
4835
4836        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4837                          FC_CLASS_3, len, &fchs,
4838                          bfa_fcs_lport_ns_rff_id_response, (void *)ns,
4839                          FC_MAX_PDUSZ, FC_FCCT_TOV);
4840
4841        port->stats.ns_rffid_sent++;
4842        bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
4843}
4844
4845static void
4846bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4847                                void *cbarg, bfa_status_t req_status,
4848                                u32 rsp_len, u32 resid_len,
4849                                struct fchs_s *rsp_fchs)
4850{
4851        struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4852        struct bfa_fcs_lport_s *port = ns->port;
4853        struct ct_hdr_s *cthdr = NULL;
4854
4855        bfa_trc(port->fcs, port->port_cfg.pwwn);
4856
4857        /*
4858         * Sanity Checks
4859         */
4860        if (req_status != BFA_STATUS_OK) {
4861                bfa_trc(port->fcs, req_status);
4862                port->stats.ns_rffid_rsp_err++;
4863                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4864                return;
4865        }
4866
4867        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4868        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4869
4870        if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4871                port->stats.ns_rffid_accepts++;
4872                bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4873                return;
4874        }
4875
4876        port->stats.ns_rffid_rejects++;
4877        bfa_trc(port->fcs, cthdr->reason_code);
4878        bfa_trc(port->fcs, cthdr->exp_code);
4879
4880        if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
4881                /* if this command is not supported, we don't retry */
4882                bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4883        } else
4884                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4885}
4886/*
4887 * Query Fabric for FC4-Types Devices.
4888 *
4889* TBD : Need to use a local (FCS private) response buffer, since the response
4890 * can be larger than 2K.
4891 */
4892static void
4893bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4894{
4895        struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4896        struct bfa_fcs_lport_s *port = ns->port;
4897        struct fchs_s fchs;
4898        int             len;
4899        struct bfa_fcxp_s *fcxp;
4900
4901        bfa_trc(port->fcs, port->pid);
4902
4903        fcxp = fcxp_alloced ? fcxp_alloced :
4904               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4905        if (!fcxp) {
4906                port->stats.ns_gidft_alloc_wait++;
4907                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4908                                bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE);
4909                return;
4910        }
4911        ns->fcxp = fcxp;
4912
4913        /*
4914         * This query is only initiated for FCP initiator mode.
4915         */
4916        len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4917                              ns->port->pid, FC_TYPE_FCP);
4918
4919        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4920                          FC_CLASS_3, len, &fchs,
4921                          bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
4922                          bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
4923
4924        port->stats.ns_gidft_sent++;
4925
4926        bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
4927}
4928
4929static void
4930bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4931                                void *cbarg, bfa_status_t req_status,
4932                                u32 rsp_len, u32 resid_len,
4933                                struct fchs_s *rsp_fchs)
4934{
4935        struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4936        struct bfa_fcs_lport_s *port = ns->port;
4937        struct ct_hdr_s *cthdr = NULL;
4938        u32        n_pids;
4939
4940        bfa_trc(port->fcs, port->port_cfg.pwwn);
4941
4942        /*
4943         * Sanity Checks
4944         */
4945        if (req_status != BFA_STATUS_OK) {
4946                bfa_trc(port->fcs, req_status);
4947                port->stats.ns_gidft_rsp_err++;
4948                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4949                return;
4950        }
4951
4952        if (resid_len != 0) {
4953                /*
4954                 * TBD : we will need to allocate a larger buffer & retry the
4955                 * command
4956                 */
4957                bfa_trc(port->fcs, rsp_len);
4958                bfa_trc(port->fcs, resid_len);
4959                return;
4960        }
4961
4962        cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4963        cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4964
4965        switch (cthdr->cmd_rsp_code) {
4966
4967        case CT_RSP_ACCEPT:
4968
4969                port->stats.ns_gidft_accepts++;
4970                n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
4971                bfa_trc(port->fcs, n_pids);
4972                bfa_fcs_lport_ns_process_gidft_pids(port,
4973                                                   (u32 *) (cthdr + 1),
4974                                                   n_pids);
4975                bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4976                break;
4977
4978        case CT_RSP_REJECT:
4979
4980                /*
4981                 * Check the reason code  & explanation.
4982                 * There may not have been any FC4 devices in the fabric
4983                 */
4984                port->stats.ns_gidft_rejects++;
4985                bfa_trc(port->fcs, cthdr->reason_code);
4986                bfa_trc(port->fcs, cthdr->exp_code);
4987
4988                if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4989                    && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4990
4991                        bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4992                } else {
4993                        /*
4994                         * for all other errors, retry
4995                         */
4996                        bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4997                }
4998                break;
4999
5000        default:
5001                port->stats.ns_gidft_unknown_rsp++;
5002                bfa_trc(port->fcs, cthdr->cmd_rsp_code);
5003                bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
5004        }
5005}
5006
5007/*
5008 *     This routine will be called by bfa_timer on timer timeouts.
5009 *
5010 *      param[in]       port - pointer to bfa_fcs_lport_t.
5011 *
5012 *      return
5013 *              void
5014 *
5015 *      Special Considerations:
5016 *
5017 *      note
5018 */
5019static void
5020bfa_fcs_lport_ns_timeout(void *arg)
5021{
5022        struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
5023
5024        ns->port->stats.ns_timeouts++;
5025        bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
5026}
5027
5028/*
5029 * Process the PID list in GID_FT response
5030 */
5031static void
5032bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
5033                                   u32 n_pids)
5034{
5035        struct fcgs_gidft_resp_s *gidft_entry;
5036        struct bfa_fcs_rport_s *rport;
5037        u32        ii;
5038        struct bfa_fcs_fabric_s *fabric = port->fabric;
5039        struct bfa_fcs_vport_s *vport;
5040        struct list_head *qe;
5041        u8 found = 0;
5042
5043        for (ii = 0; ii < n_pids; ii++) {
5044                gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
5045
5046                if (gidft_entry->pid == port->pid)
5047                        continue;
5048
5049                /*
5050                 * Ignore PID if it is of base port
5051                 * (Avoid vports discovering base port as remote port)
5052                 */
5053                if (gidft_entry->pid == fabric->bport.pid)
5054                        continue;
5055
5056                /*
5057                 * Ignore PID if it is of vport created on the same base port
5058                 * (Avoid vport discovering every other vport created on the
5059                 * same port as remote port)
5060                 */
5061                list_for_each(qe, &fabric->vport_q) {
5062                        vport = (struct bfa_fcs_vport_s *) qe;
5063                        if (vport->lport.pid == gidft_entry->pid)
5064                                found = 1;
5065                }
5066
5067                if (found) {
5068                        found = 0;
5069                        continue;
5070                }
5071
5072                /*
5073                 * Check if this rport already exists
5074                 */
5075                rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
5076                if (rport == NULL) {
5077                        /*
5078                         * this is a new device. create rport
5079                         */
5080                        rport = bfa_fcs_rport_create(port, gidft_entry->pid);
5081                } else {
5082                        /*
5083                         * this rport already exists
5084                         */
5085                        bfa_fcs_rport_scn(rport);
5086                }
5087
5088                bfa_trc(port->fcs, gidft_entry->pid);
5089
5090                /*
5091                 * if the last entry bit is set, bail out.
5092                 */
5093                if (gidft_entry->last)
5094                        return;
5095        }
5096}
5097
5098/*
5099 *  fcs_ns_public FCS nameserver public interfaces
5100 */
5101
5102/*
5103 * Functions called by port/fab.
5104 * These will send relevant Events to the ns state machine.
5105 */
5106void
5107bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
5108{
5109        struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5110
5111        ns->port = port;
5112        bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
5113}
5114
5115void
5116bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
5117{
5118        struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5119
5120        ns->port = port;
5121        bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
5122}
5123
5124void
5125bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
5126{
5127        struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5128
5129        ns->port = port;
5130        bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
5131}
5132
5133void
5134bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
5135{
5136        struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
5137
5138        bfa_trc(port->fcs, port->pid);
5139        if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online))
5140                bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
5141}
5142
5143static void
5144bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
5145{
5146
5147        struct bfa_fcs_rport_s *rport;
5148        u8 nwwns;
5149        wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
5150        int ii;
5151
5152        bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
5153
5154        for (ii = 0 ; ii < nwwns; ++ii) {
5155                rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
5156                WARN_ON(!rport);
5157        }
5158}
5159
5160void
5161bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
5162{
5163        struct bfa_fcs_lport_ns_s *ns = cbarg;
5164        struct bfa_fcs_lport_s *port = ns->port;
5165        struct fchs_s fchs;
5166        struct bfa_fcxp_s *fcxp;
5167        u8 symbl[256];
5168        int len;
5169
5170        /* Avoid sending RSPN in the following states. */
5171        if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
5172            bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
5173            bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) ||
5174            bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) ||
5175            bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry))
5176                return;
5177
5178        memset(symbl, 0, sizeof(symbl));
5179        bfa_trc(port->fcs, port->port_cfg.pwwn);
5180
5181        fcxp = fcxp_alloced ? fcxp_alloced :
5182               bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
5183        if (!fcxp) {
5184                port->stats.ns_rspnid_alloc_wait++;
5185                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
5186                        bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE);
5187                return;
5188        }
5189
5190        ns->fcxp = fcxp;
5191
5192        if (port->vport) {
5193                /*
5194                 * For Vports, we append the vport's port symbolic name
5195                 * to that of the base port.
5196                 */
5197                strlcpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name
5198                        (bfa_fcs_get_base_port(port->fcs))),
5199                        sizeof(symbl));
5200
5201                strlcat(symbl,
5202                        (char *)&(bfa_fcs_lport_get_psym_name(port)),
5203                        sizeof(symbl));
5204        }
5205
5206        len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5207                              bfa_fcs_lport_get_fcid(port), 0, symbl);
5208
5209        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
5210                      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
5211
5212        port->stats.ns_rspnid_sent++;
5213}
5214
5215/*
5216 * FCS SCN
5217 */
5218
5219#define FC_QOS_RSCN_EVENT               0x0c
5220#define FC_FABRIC_NAME_RSCN_EVENT       0x0d
5221
5222/*
5223 * forward declarations
5224 */
5225static void     bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
5226                                          struct bfa_fcxp_s *fcxp_alloced);
5227static void     bfa_fcs_lport_scn_scr_response(void *fcsarg,
5228                                              struct bfa_fcxp_s *fcxp,
5229                                              void *cbarg,
5230                                              bfa_status_t req_status,
5231                                              u32 rsp_len,
5232                                              u32 resid_len,
5233                                              struct fchs_s *rsp_fchs);
5234static void     bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
5235                                             struct fchs_s *rx_fchs);
5236static void     bfa_fcs_lport_scn_timeout(void *arg);
5237
5238/*
5239 *  fcs_scm_sm FCS SCN state machine
5240 */
5241
5242/*
5243 * VPort SCN State Machine events
5244 */
5245enum port_scn_event {
5246        SCNSM_EVENT_PORT_ONLINE = 1,
5247        SCNSM_EVENT_PORT_OFFLINE = 2,
5248        SCNSM_EVENT_RSP_OK = 3,
5249        SCNSM_EVENT_RSP_ERROR = 4,
5250        SCNSM_EVENT_TIMEOUT = 5,
5251        SCNSM_EVENT_SCR_SENT = 6,
5252};
5253
5254static void     bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
5255                                            enum port_scn_event event);
5256static void     bfa_fcs_lport_scn_sm_sending_scr(
5257                                        struct bfa_fcs_lport_scn_s *scn,
5258                                        enum port_scn_event event);
5259static void     bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
5260                                        enum port_scn_event event);
5261static void     bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
5262                                              enum port_scn_event event);
5263static void     bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
5264                                           enum port_scn_event event);
5265
5266/*
5267 *      Starting state - awaiting link up.
5268 */
5269static void
5270bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
5271                        enum port_scn_event event)
5272{
5273        switch (event) {
5274        case SCNSM_EVENT_PORT_ONLINE:
5275                bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
5276                bfa_fcs_lport_scn_send_scr(scn, NULL);
5277                break;
5278
5279        case SCNSM_EVENT_PORT_OFFLINE:
5280                break;
5281
5282        default:
5283                bfa_sm_fault(scn->port->fcs, event);
5284        }
5285}
5286
5287static void
5288bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
5289                                enum port_scn_event event)
5290{
5291        switch (event) {
5292        case SCNSM_EVENT_SCR_SENT:
5293                bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
5294                break;
5295
5296        case SCNSM_EVENT_PORT_OFFLINE:
5297                bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5298                bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
5299                break;
5300
5301        default:
5302                bfa_sm_fault(scn->port->fcs, event);
5303        }
5304}
5305
5306static void
5307bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
5308                        enum port_scn_event event)
5309{
5310        struct bfa_fcs_lport_s *port = scn->port;
5311
5312        switch (event) {
5313        case SCNSM_EVENT_RSP_OK:
5314                bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
5315                break;
5316
5317        case SCNSM_EVENT_RSP_ERROR:
5318                bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
5319                bfa_timer_start(port->fcs->bfa, &scn->timer,
5320                                    bfa_fcs_lport_scn_timeout, scn,
5321                                    BFA_FCS_RETRY_TIMEOUT);
5322                break;
5323
5324        case SCNSM_EVENT_PORT_OFFLINE:
5325                bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5326                bfa_fcxp_discard(scn->fcxp);
5327                break;
5328
5329        default:
5330                bfa_sm_fault(port->fcs, event);
5331        }
5332}
5333
5334static void
5335bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
5336                                enum port_scn_event event)
5337{
5338        switch (event) {
5339        case SCNSM_EVENT_TIMEOUT:
5340                bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
5341                bfa_fcs_lport_scn_send_scr(scn, NULL);
5342                break;
5343
5344        case SCNSM_EVENT_PORT_OFFLINE:
5345                bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5346                bfa_timer_stop(&scn->timer);
5347                break;
5348
5349        default:
5350                bfa_sm_fault(scn->port->fcs, event);
5351        }
5352}
5353
5354static void
5355bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
5356                        enum port_scn_event event)
5357{
5358        switch (event) {
5359        case SCNSM_EVENT_PORT_OFFLINE:
5360                bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5361                break;
5362
5363        default:
5364                bfa_sm_fault(scn->port->fcs, event);
5365        }
5366}
5367
5368
5369
5370/*
5371 *  fcs_scn_private FCS SCN private functions
5372 */
5373
5374/*
5375 * This routine will be called to send a SCR command.
5376 */
5377static void
5378bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
5379{
5380        struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
5381        struct bfa_fcs_lport_s *port = scn->port;
5382        struct fchs_s fchs;
5383        int             len;
5384        struct bfa_fcxp_s *fcxp;
5385
5386        bfa_trc(port->fcs, port->pid);
5387        bfa_trc(port->fcs, port->port_cfg.pwwn);
5388
5389        fcxp = fcxp_alloced ? fcxp_alloced :
5390               bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
5391        if (!fcxp) {
5392                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
5393                                bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE);
5394                return;
5395        }
5396        scn->fcxp = fcxp;
5397
5398        /* Handle VU registrations for Base port only */
5399        if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
5400                len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5401                                port->fabric->lps->brcd_switch,
5402                                port->pid, 0);
5403        } else {
5404            len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5405                                    BFA_FALSE,
5406                                    port->pid, 0);
5407        }
5408
5409        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
5410                          FC_CLASS_3, len, &fchs,
5411                          bfa_fcs_lport_scn_scr_response,
5412                          (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
5413
5414        bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
5415}
5416
5417static void
5418bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
5419                        void *cbarg, bfa_status_t req_status, u32 rsp_len,
5420                              u32 resid_len, struct fchs_s *rsp_fchs)
5421{
5422        struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
5423        struct bfa_fcs_lport_s *port = scn->port;
5424        struct fc_els_cmd_s *els_cmd;
5425        struct fc_ls_rjt_s *ls_rjt;
5426
5427        bfa_trc(port->fcs, port->port_cfg.pwwn);
5428
5429        /*
5430         * Sanity Checks
5431         */
5432        if (req_status != BFA_STATUS_OK) {
5433                bfa_trc(port->fcs, req_status);
5434                bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5435                return;
5436        }
5437
5438        els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
5439
5440        switch (els_cmd->els_code) {
5441
5442        case FC_ELS_ACC:
5443                bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
5444                break;
5445
5446        case FC_ELS_LS_RJT:
5447
5448                ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
5449
5450                bfa_trc(port->fcs, ls_rjt->reason_code);
5451                bfa_trc(port->fcs, ls_rjt->reason_code_expl);
5452
5453                bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5454                break;
5455
5456        default:
5457                bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5458        }
5459}
5460
5461/*
5462 * Send a LS Accept
5463 */
5464static void
5465bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
5466                                struct fchs_s *rx_fchs)
5467{
5468        struct fchs_s fchs;
5469        struct bfa_fcxp_s *fcxp;
5470        struct bfa_rport_s *bfa_rport = NULL;
5471        int             len;
5472
5473        bfa_trc(port->fcs, rx_fchs->s_id);
5474
5475        fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
5476        if (!fcxp)
5477                return;
5478
5479        len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5480                              rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
5481                              rx_fchs->ox_id);
5482
5483        bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
5484                          BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
5485                          FC_MAX_PDUSZ, 0);
5486}
5487
5488/*
5489 *     This routine will be called by bfa_timer on timer timeouts.
5490 *
5491 *      param[in]       vport           - pointer to bfa_fcs_lport_t.
5492 *      param[out]      vport_status    - pointer to return vport status in
5493 *
5494 *      return
5495 *              void
5496 *
5497 *      Special Considerations:
5498 *
5499 *      note
5500 */
5501static void
5502bfa_fcs_lport_scn_timeout(void *arg)
5503{
5504        struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
5505
5506        bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
5507}
5508
5509
5510
5511/*
5512 *  fcs_scn_public FCS state change notification public interfaces
5513 */
5514
5515/*
5516 * Functions called by port/fab
5517 */
5518void
5519bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
5520{
5521        struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5522
5523        scn->port = port;
5524        bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5525}
5526
5527void
5528bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
5529{
5530        struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5531
5532        scn->port = port;
5533        bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
5534}
5535
5536void
5537bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port)
5538{
5539        struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5540
5541        scn->port = port;
5542        bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
5543}
5544
5545static void
5546bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
5547{
5548        struct bfa_fcs_rport_s *rport;
5549        struct bfa_fcs_fabric_s *fabric = port->fabric;
5550        struct bfa_fcs_vport_s *vport;
5551        struct list_head *qe;
5552
5553        bfa_trc(port->fcs, rpid);
5554
5555        /*
5556         * Ignore PID if it is of base port or of vports created on the
5557         * same base port. It is to avoid vports discovering base port or
5558         * other vports created on same base port as remote port
5559         */
5560        if (rpid == fabric->bport.pid)
5561                return;
5562
5563        list_for_each(qe, &fabric->vport_q) {
5564                vport = (struct bfa_fcs_vport_s *) qe;
5565                if (vport->lport.pid == rpid)
5566                        return;
5567        }
5568        /*
5569         * If this is an unknown device, then it just came online.
5570         * Otherwise let rport handle the RSCN event.
5571         */
5572        rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
5573        if (!rport)
5574                rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid);
5575
5576        if (rport == NULL) {
5577                /*
5578                 * If min cfg mode is enabled, we donot need to
5579                 * discover any new rports.
5580                 */
5581                if (!__fcs_min_cfg(port->fcs))
5582                        rport = bfa_fcs_rport_create(port, rpid);
5583        } else
5584                bfa_fcs_rport_scn(rport);
5585}
5586
5587/*
5588 * rscn format based PID comparison
5589 */
5590#define __fc_pid_match(__c0, __c1, __fmt)               \
5591        (((__fmt) == FC_RSCN_FORMAT_FABRIC) ||          \
5592         (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&         \
5593          ((__c0)[0] == (__c1)[0])) ||                          \
5594         (((__fmt) == FC_RSCN_FORMAT_AREA) &&           \
5595          ((__c0)[0] == (__c1)[0]) &&                           \
5596          ((__c0)[1] == (__c1)[1])))
5597
5598static void
5599bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
5600                                enum fc_rscn_format format,
5601                                u32 rscn_pid)
5602{
5603        struct bfa_fcs_rport_s *rport;
5604        struct list_head        *qe, *qe_next;
5605        u8        *c0, *c1;
5606
5607        bfa_trc(port->fcs, format);
5608        bfa_trc(port->fcs, rscn_pid);
5609
5610        c0 = (u8 *) &rscn_pid;
5611
5612        list_for_each_safe(qe, qe_next, &port->rport_q) {
5613                rport = (struct bfa_fcs_rport_s *) qe;
5614                c1 = (u8 *) &rport->pid;
5615                if (__fc_pid_match(c0, c1, format))
5616                        bfa_fcs_rport_scn(rport);
5617        }
5618}
5619
5620
5621void
5622bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
5623                        struct fchs_s *fchs, u32 len)
5624{
5625        struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
5626        int             num_entries;
5627        u32        rscn_pid;
5628        bfa_boolean_t   nsquery = BFA_FALSE, found;
5629        int             i = 0, j;
5630
5631        num_entries =
5632                (be16_to_cpu(rscn->payldlen) -
5633                 sizeof(u32)) / sizeof(rscn->event[0]);
5634
5635        bfa_trc(port->fcs, num_entries);
5636
5637        port->stats.num_rscn++;
5638
5639        bfa_fcs_lport_scn_send_ls_acc(port, fchs);
5640
5641        for (i = 0; i < num_entries; i++) {
5642                rscn_pid = rscn->event[i].portid;
5643
5644                bfa_trc(port->fcs, rscn->event[i].format);
5645                bfa_trc(port->fcs, rscn_pid);
5646
5647                /* check for duplicate entries in the list */
5648                found = BFA_FALSE;
5649                for (j = 0; j < i; j++) {
5650                        if (rscn->event[j].portid == rscn_pid) {
5651                                found = BFA_TRUE;
5652                                break;
5653                        }
5654                }
5655
5656                /* if found in down the list, pid has been already processed */
5657                if (found) {
5658                        bfa_trc(port->fcs, rscn_pid);
5659                        continue;
5660                }
5661
5662                switch (rscn->event[i].format) {
5663                case FC_RSCN_FORMAT_PORTID:
5664                        if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
5665                                /*
5666                                 * Ignore this event.
5667                                 * f/w would have processed it
5668                                 */
5669                                bfa_trc(port->fcs, rscn_pid);
5670                        } else {
5671                                port->stats.num_portid_rscn++;
5672                                bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
5673                        }
5674                break;
5675
5676                case FC_RSCN_FORMAT_FABRIC:
5677                        if (rscn->event[i].qualifier ==
5678                                        FC_FABRIC_NAME_RSCN_EVENT) {
5679                                bfa_fcs_lport_ms_fabric_rscn(port);
5680                                break;
5681                        }
5682                        fallthrough;
5683
5684                case FC_RSCN_FORMAT_AREA:
5685                case FC_RSCN_FORMAT_DOMAIN:
5686                        nsquery = BFA_TRUE;
5687                        bfa_fcs_lport_scn_multiport_rscn(port,
5688                                                        rscn->event[i].format,
5689                                                        rscn_pid);
5690                        break;
5691
5692
5693                default:
5694                        WARN_ON(1);
5695                        nsquery = BFA_TRUE;
5696                }
5697        }
5698
5699        /*
5700         * If any of area, domain or fabric RSCN is received, do a fresh
5701         * discovery to find new devices.
5702         */
5703        if (nsquery)
5704                bfa_fcs_lport_ns_query(port);
5705}
5706
5707/*
5708 * BFA FCS port
5709 */
5710/*
5711 *  fcs_port_api BFA FCS port API
5712 */
5713struct bfa_fcs_lport_s *
5714bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
5715{
5716        return &fcs->fabric.bport;
5717}
5718
5719wwn_t
5720bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
5721                int nrports, bfa_boolean_t bwwn)
5722{
5723        struct list_head        *qh, *qe;
5724        struct bfa_fcs_rport_s *rport = NULL;
5725        int     i;
5726        struct bfa_fcs_s        *fcs;
5727
5728        if (port == NULL || nrports == 0)
5729                return (wwn_t) 0;
5730
5731        fcs = port->fcs;
5732        bfa_trc(fcs, (u32) nrports);
5733
5734        i = 0;
5735        qh = &port->rport_q;
5736        qe = bfa_q_first(qh);
5737
5738        while ((qe != qh) && (i < nrports)) {
5739                rport = (struct bfa_fcs_rport_s *) qe;
5740                if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
5741                        qe = bfa_q_next(qe);
5742                        bfa_trc(fcs, (u32) rport->pwwn);
5743                        bfa_trc(fcs, rport->pid);
5744                        bfa_trc(fcs, i);
5745                        continue;
5746                }
5747
5748                if (bwwn) {
5749                        if (!memcmp(&wwn, &rport->pwwn, 8))
5750                                break;
5751                } else {
5752                        if (i == index)
5753                                break;
5754                }
5755
5756                i++;
5757                qe = bfa_q_next(qe);
5758        }
5759
5760        bfa_trc(fcs, i);
5761        if (rport)
5762                return rport->pwwn;
5763        else
5764                return (wwn_t) 0;
5765}
5766
5767void
5768bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
5769                struct bfa_rport_qualifier_s rports[], int *nrports)
5770{
5771        struct list_head        *qh, *qe;
5772        struct bfa_fcs_rport_s *rport = NULL;
5773        int     i;
5774        struct bfa_fcs_s        *fcs;
5775
5776        if (port == NULL || rports == NULL || *nrports == 0)
5777                return;
5778
5779        fcs = port->fcs;
5780        bfa_trc(fcs, (u32) *nrports);
5781
5782        i = 0;
5783        qh = &port->rport_q;
5784        qe = bfa_q_first(qh);
5785
5786        while ((qe != qh) && (i < *nrports)) {
5787                rport = (struct bfa_fcs_rport_s *) qe;
5788                if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
5789                        qe = bfa_q_next(qe);
5790                        bfa_trc(fcs, (u32) rport->pwwn);
5791                        bfa_trc(fcs, rport->pid);
5792                        bfa_trc(fcs, i);
5793                        continue;
5794                }
5795
5796                if (!rport->pwwn && !rport->pid) {
5797                        qe = bfa_q_next(qe);
5798                        continue;
5799                }
5800
5801                rports[i].pwwn = rport->pwwn;
5802                rports[i].pid = rport->pid;
5803
5804                i++;
5805                qe = bfa_q_next(qe);
5806        }
5807
5808        bfa_trc(fcs, i);
5809        *nrports = i;
5810}
5811
5812/*
5813 * Iterate's through all the rport's in the given port to
5814 * determine the maximum operating speed.
5815 *
5816 * !!!! To be used in TRL Functionality only !!!!
5817 */
5818bfa_port_speed_t
5819bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
5820{
5821        struct list_head *qh, *qe;
5822        struct bfa_fcs_rport_s *rport = NULL;
5823        struct bfa_fcs_s        *fcs;
5824        bfa_port_speed_t max_speed = 0;
5825        struct bfa_port_attr_s port_attr;
5826        bfa_port_speed_t port_speed, rport_speed;
5827        bfa_boolean_t trl_enabled;
5828
5829        if (port == NULL)
5830                return 0;
5831
5832        fcs = port->fcs;
5833        trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
5834
5835        /* Get Physical port's current speed */
5836        bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
5837        port_speed = port_attr.speed;
5838        bfa_trc(fcs, port_speed);
5839
5840        qh = &port->rport_q;
5841        qe = bfa_q_first(qh);
5842
5843        while (qe != qh) {
5844                rport = (struct bfa_fcs_rport_s *) qe;
5845                if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
5846                        (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) ||
5847                        (rport->scsi_function != BFA_RPORT_TARGET)) {
5848                        qe = bfa_q_next(qe);
5849                        continue;
5850                }
5851
5852                rport_speed = rport->rpf.rpsc_speed;
5853                if ((trl_enabled) && (rport_speed ==
5854                        BFA_PORT_SPEED_UNKNOWN)) {
5855                        /* Use default ratelim speed setting */
5856                        rport_speed =
5857                                bfa_fcport_get_ratelim_speed(port->fcs->bfa);
5858                }
5859
5860                if (rport_speed > max_speed)
5861                        max_speed = rport_speed;
5862
5863                qe = bfa_q_next(qe);
5864        }
5865
5866        if (max_speed > port_speed)
5867                max_speed = port_speed;
5868
5869        bfa_trc(fcs, max_speed);
5870        return max_speed;
5871}
5872
5873struct bfa_fcs_lport_s *
5874bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
5875{
5876        struct bfa_fcs_vport_s *vport;
5877        bfa_fcs_vf_t   *vf;
5878
5879        WARN_ON(fcs == NULL);
5880
5881        vf = bfa_fcs_vf_lookup(fcs, vf_id);
5882        if (vf == NULL) {
5883                bfa_trc(fcs, vf_id);
5884                return NULL;
5885        }
5886
5887        if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
5888                return &vf->bport;
5889
5890        vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
5891        if (vport)
5892                return &vport->lport;
5893
5894        return NULL;
5895}
5896
5897/*
5898 *  API corresponding to NPIV_VPORT_GETINFO.
5899 */
5900void
5901bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
5902         struct bfa_lport_info_s *port_info)
5903{
5904
5905        bfa_trc(port->fcs, port->fabric->fabric_name);
5906
5907        if (port->vport == NULL) {
5908                /*
5909                 * This is a Physical port
5910                 */
5911                port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
5912
5913                /*
5914                 * @todo : need to fix the state & reason
5915                 */
5916                port_info->port_state = 0;
5917                port_info->offline_reason = 0;
5918
5919                port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5920                port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5921
5922                port_info->max_vports_supp =
5923                        bfa_lps_get_max_vport(port->fcs->bfa);
5924                port_info->num_vports_inuse =
5925                        port->fabric->num_vports;
5926                port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
5927                port_info->num_rports_inuse = port->num_rports;
5928        } else {
5929                /*
5930                 * This is a virtual port
5931                 */
5932                port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
5933
5934                /*
5935                 * @todo : need to fix the state & reason
5936                 */
5937                port_info->port_state = 0;
5938                port_info->offline_reason = 0;
5939
5940                port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5941                port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5942        }
5943}
5944
5945void
5946bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
5947         struct bfa_lport_stats_s *port_stats)
5948{
5949        *port_stats = fcs_port->stats;
5950}
5951
5952void
5953bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
5954{
5955        memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
5956}
5957
5958/*
5959 * Let new loop map create missing rports
5960 */
5961void
5962bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port)
5963{
5964        bfa_fcs_lport_loop_online(port);
5965}
5966
5967/*
5968 * FCS virtual port state machine
5969 */
5970
5971#define __vport_fcs(__vp)       ((__vp)->lport.fcs)
5972#define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
5973#define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
5974#define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
5975#define __vport_fcid(__vp)      ((__vp)->lport.pid)
5976#define __vport_fabric(__vp)    ((__vp)->lport.fabric)
5977#define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
5978
5979#define BFA_FCS_VPORT_MAX_RETRIES  5
5980/*
5981 * Forward declarations
5982 */
5983static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
5984static void     bfa_fcs_vport_timeout(void *vport_arg);
5985static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
5986static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
5987
5988/*
5989 *  fcs_vport_sm FCS virtual port state machine
5990 */
5991
5992/*
5993 * VPort State Machine events
5994 */
5995enum bfa_fcs_vport_event {
5996        BFA_FCS_VPORT_SM_CREATE = 1,    /*  vport create event */
5997        BFA_FCS_VPORT_SM_DELETE = 2,    /*  vport delete event */
5998        BFA_FCS_VPORT_SM_START = 3,     /*  vport start request */
5999        BFA_FCS_VPORT_SM_STOP = 4,      /*  stop: unsupported */
6000        BFA_FCS_VPORT_SM_ONLINE = 5,    /*  fabric online */
6001        BFA_FCS_VPORT_SM_OFFLINE = 6,   /*  fabric offline event */
6002        BFA_FCS_VPORT_SM_FRMSENT = 7,   /*  fdisc/logo sent events */
6003        BFA_FCS_VPORT_SM_RSP_OK = 8,    /*  good response */
6004        BFA_FCS_VPORT_SM_RSP_ERROR = 9, /*  error/bad response */
6005        BFA_FCS_VPORT_SM_TIMEOUT = 10,  /*  delay timer event */
6006        BFA_FCS_VPORT_SM_DELCOMP = 11,  /*  lport delete completion */
6007        BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,      /*  Dup wnn error*/
6008        BFA_FCS_VPORT_SM_RSP_FAILED = 13,       /*  non-retryable failure */
6009        BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */
6010        BFA_FCS_VPORT_SM_FABRIC_MAX = 15, /* max vports on fabric */
6011};
6012
6013static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
6014                                        enum bfa_fcs_vport_event event);
6015static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
6016                                         enum bfa_fcs_vport_event event);
6017static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
6018                                         enum bfa_fcs_vport_event event);
6019static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
6020                                       enum bfa_fcs_vport_event event);
6021static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
6022                                             enum bfa_fcs_vport_event event);
6023static void     bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
6024                                        enum bfa_fcs_vport_event event);
6025static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
6026                                        enum bfa_fcs_vport_event event);
6027static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
6028                                          enum bfa_fcs_vport_event event);
6029static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
6030                                         enum bfa_fcs_vport_event event);
6031static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
6032                                      enum bfa_fcs_vport_event event);
6033static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
6034                                      enum bfa_fcs_vport_event event);
6035static void     bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
6036                                        enum bfa_fcs_vport_event event);
6037static void     bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
6038                                        enum bfa_fcs_vport_event event);
6039
6040static struct bfa_sm_table_s  vport_sm_table[] = {
6041        {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
6042        {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
6043        {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
6044        {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
6045        {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
6046        {BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},
6047        {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
6048        {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
6049        {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
6050        {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
6051        {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
6052};
6053
6054/*
6055 * Beginning state.
6056 */
6057static void
6058bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
6059                        enum bfa_fcs_vport_event event)
6060{
6061        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6062        bfa_trc(__vport_fcs(vport), event);
6063
6064        switch (event) {
6065        case BFA_FCS_VPORT_SM_CREATE:
6066                bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6067                bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
6068                break;
6069
6070        default:
6071                bfa_sm_fault(__vport_fcs(vport), event);
6072        }
6073}
6074
6075/*
6076 * Created state - a start event is required to start up the state machine.
6077 */
6078static void
6079bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
6080                        enum bfa_fcs_vport_event event)
6081{
6082        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6083        bfa_trc(__vport_fcs(vport), event);
6084
6085        switch (event) {
6086        case BFA_FCS_VPORT_SM_START:
6087                if (bfa_sm_cmp_state(__vport_fabric(vport),
6088                                        bfa_fcs_fabric_sm_online)
6089                    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
6090                        bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
6091                        bfa_fcs_vport_do_fdisc(vport);
6092                } else {
6093                        /*
6094                         * Fabric is offline or not NPIV capable, stay in
6095                         * offline state.
6096                         */
6097                        vport->vport_stats.fab_no_npiv++;
6098                        bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6099                }
6100                break;
6101
6102        case BFA_FCS_VPORT_SM_DELETE:
6103                bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6104                bfa_fcs_lport_delete(&vport->lport);
6105                break;
6106
6107        case BFA_FCS_VPORT_SM_ONLINE:
6108        case BFA_FCS_VPORT_SM_OFFLINE:
6109                /*
6110                 * Ignore ONLINE/OFFLINE events from fabric
6111                 * till vport is started.
6112                 */
6113                break;
6114
6115        default:
6116                bfa_sm_fault(__vport_fcs(vport), event);
6117        }
6118}
6119
6120/*
6121 * Offline state - awaiting ONLINE event from fabric SM.
6122 */
6123static void
6124bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
6125                        enum bfa_fcs_vport_event event)
6126{
6127        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6128        bfa_trc(__vport_fcs(vport), event);
6129
6130        switch (event) {
6131        case BFA_FCS_VPORT_SM_DELETE:
6132                bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6133                bfa_fcs_lport_delete(&vport->lport);
6134                break;
6135
6136        case BFA_FCS_VPORT_SM_ONLINE:
6137                bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
6138                vport->fdisc_retries = 0;
6139                bfa_fcs_vport_do_fdisc(vport);
6140                break;
6141
6142        case BFA_FCS_VPORT_SM_STOP:
6143                bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6144                bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
6145                break;
6146
6147        case BFA_FCS_VPORT_SM_OFFLINE:
6148                /*
6149                 * This can happen if the vport couldn't be initialzied
6150                 * due the fact that the npiv was not enabled on the switch.
6151                 * In that case we will put the vport in offline state.
6152                 * However, the link can go down and cause the this event to
6153                 * be sent when we are already offline. Ignore it.
6154                 */
6155                break;
6156
6157        default:
6158                bfa_sm_fault(__vport_fcs(vport), event);
6159        }
6160}
6161
6162
6163/*
6164 * FDISC is sent and awaiting reply from fabric.
6165 */
6166static void
6167bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
6168                        enum bfa_fcs_vport_event event)
6169{
6170        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6171        bfa_trc(__vport_fcs(vport), event);
6172
6173        switch (event) {
6174        case BFA_FCS_VPORT_SM_DELETE:
6175                bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);
6176                break;
6177
6178        case BFA_FCS_VPORT_SM_OFFLINE:
6179                bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6180                bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6181                break;
6182
6183        case BFA_FCS_VPORT_SM_RSP_OK:
6184                bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
6185                bfa_fcs_lport_online(&vport->lport);
6186                break;
6187
6188        case BFA_FCS_VPORT_SM_RSP_ERROR:
6189                bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
6190                bfa_timer_start(__vport_bfa(vport), &vport->timer,
6191                                    bfa_fcs_vport_timeout, vport,
6192                                    BFA_FCS_RETRY_TIMEOUT);
6193                break;
6194
6195        case BFA_FCS_VPORT_SM_RSP_FAILED:
6196        case BFA_FCS_VPORT_SM_FABRIC_MAX:
6197                bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6198                break;
6199
6200        case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
6201                bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
6202                break;
6203
6204        default:
6205                bfa_sm_fault(__vport_fcs(vport), event);
6206        }
6207}
6208
6209/*
6210 * FDISC attempt failed - a timer is active to retry FDISC.
6211 */
6212static void
6213bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
6214                             enum bfa_fcs_vport_event event)
6215{
6216        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6217        bfa_trc(__vport_fcs(vport), event);
6218
6219        switch (event) {
6220        case BFA_FCS_VPORT_SM_DELETE:
6221                bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6222                bfa_timer_stop(&vport->timer);
6223                bfa_fcs_lport_delete(&vport->lport);
6224                break;
6225
6226        case BFA_FCS_VPORT_SM_OFFLINE:
6227                bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6228                bfa_timer_stop(&vport->timer);
6229                break;
6230
6231        case BFA_FCS_VPORT_SM_TIMEOUT:
6232                bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
6233                vport->vport_stats.fdisc_retries++;
6234                vport->fdisc_retries++;
6235                bfa_fcs_vport_do_fdisc(vport);
6236                break;
6237
6238        default:
6239                bfa_sm_fault(__vport_fcs(vport), event);
6240        }
6241}
6242
6243/*
6244 * FDISC is in progress and we got a vport delete request -
6245 * this is a wait state while we wait for fdisc response and
6246 * we will transition to the appropriate state - on rsp status.
6247 */
6248static void
6249bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
6250                                enum bfa_fcs_vport_event event)
6251{
6252        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6253        bfa_trc(__vport_fcs(vport), event);
6254
6255        switch (event) {
6256        case BFA_FCS_VPORT_SM_RSP_OK:
6257                bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
6258                bfa_fcs_lport_delete(&vport->lport);
6259                break;
6260
6261        case BFA_FCS_VPORT_SM_DELETE:
6262                break;
6263
6264        case BFA_FCS_VPORT_SM_OFFLINE:
6265        case BFA_FCS_VPORT_SM_RSP_ERROR:
6266        case BFA_FCS_VPORT_SM_RSP_FAILED:
6267        case BFA_FCS_VPORT_SM_FABRIC_MAX:
6268        case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
6269                bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6270                bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6271                bfa_fcs_lport_delete(&vport->lport);
6272                break;
6273
6274        default:
6275                bfa_sm_fault(__vport_fcs(vport), event);
6276        }
6277}
6278
6279/*
6280 * Vport is online (FDISC is complete).
6281 */
6282static void
6283bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
6284                        enum bfa_fcs_vport_event event)
6285{
6286        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6287        bfa_trc(__vport_fcs(vport), event);
6288
6289        switch (event) {
6290        case BFA_FCS_VPORT_SM_DELETE:
6291                bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
6292                bfa_fcs_lport_delete(&vport->lport);
6293                break;
6294
6295        case BFA_FCS_VPORT_SM_STOP:
6296                bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
6297                bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
6298                break;
6299
6300        case BFA_FCS_VPORT_SM_OFFLINE:
6301                bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
6302                bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6303                bfa_fcs_lport_offline(&vport->lport);
6304                break;
6305
6306        default:
6307                bfa_sm_fault(__vport_fcs(vport), event);
6308        }
6309}
6310
6311/*
6312 * Vport is being stopped - awaiting lport stop completion to send
6313 * LOGO to fabric.
6314 */
6315static void
6316bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
6317                          enum bfa_fcs_vport_event event)
6318{
6319        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6320        bfa_trc(__vport_fcs(vport), event);
6321
6322        switch (event) {
6323        case BFA_FCS_VPORT_SM_STOPCOMP:
6324                bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
6325                bfa_fcs_vport_do_logo(vport);
6326                break;
6327
6328        case BFA_FCS_VPORT_SM_OFFLINE:
6329                bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6330                break;
6331
6332        default:
6333                bfa_sm_fault(__vport_fcs(vport), event);
6334        }
6335}
6336
6337/*
6338 * Vport is being deleted - awaiting lport delete completion to send
6339 * LOGO to fabric.
6340 */
6341static void
6342bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
6343                        enum bfa_fcs_vport_event event)
6344{
6345        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6346        bfa_trc(__vport_fcs(vport), event);
6347
6348        switch (event) {
6349        case BFA_FCS_VPORT_SM_DELETE:
6350                break;
6351
6352        case BFA_FCS_VPORT_SM_DELCOMP:
6353                bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
6354                bfa_fcs_vport_do_logo(vport);
6355                break;
6356
6357        case BFA_FCS_VPORT_SM_OFFLINE:
6358                bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6359                break;
6360
6361        default:
6362                bfa_sm_fault(__vport_fcs(vport), event);
6363        }
6364}
6365
6366/*
6367 * Error State.
6368 * This state will be set when the Vport Creation fails due
6369 * to errors like Dup WWN. In this state only operation allowed
6370 * is a Vport Delete.
6371 */
6372static void
6373bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
6374                        enum bfa_fcs_vport_event event)
6375{
6376        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6377        bfa_trc(__vport_fcs(vport), event);
6378
6379        switch (event) {
6380        case BFA_FCS_VPORT_SM_DELETE:
6381                bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6382                bfa_fcs_lport_delete(&vport->lport);
6383                break;
6384
6385        default:
6386                bfa_trc(__vport_fcs(vport), event);
6387        }
6388}
6389
6390/*
6391 * Lport cleanup is in progress since vport is being deleted. Fabric is
6392 * offline, so no LOGO is needed to complete vport deletion.
6393 */
6394static void
6395bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
6396                        enum bfa_fcs_vport_event event)
6397{
6398        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6399        bfa_trc(__vport_fcs(vport), event);
6400
6401        switch (event) {
6402        case BFA_FCS_VPORT_SM_DELCOMP:
6403                bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6404                bfa_fcs_vport_free(vport);
6405                break;
6406
6407        case BFA_FCS_VPORT_SM_STOPCOMP:
6408                bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6409                break;
6410
6411        case BFA_FCS_VPORT_SM_DELETE:
6412                break;
6413
6414        default:
6415                bfa_sm_fault(__vport_fcs(vport), event);
6416        }
6417}
6418
6419/*
6420 * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
6421 * is done.
6422 */
6423static void
6424bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
6425                               enum bfa_fcs_vport_event event)
6426{
6427        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6428        bfa_trc(__vport_fcs(vport), event);
6429
6430        switch (event) {
6431        case BFA_FCS_VPORT_SM_OFFLINE:
6432                bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6433                fallthrough;
6434
6435        case BFA_FCS_VPORT_SM_RSP_OK:
6436        case BFA_FCS_VPORT_SM_RSP_ERROR:
6437                bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6438                break;
6439
6440        default:
6441                bfa_sm_fault(__vport_fcs(vport), event);
6442        }
6443}
6444
6445/*
6446 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
6447 * is done.
6448 */
6449static void
6450bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
6451                        enum bfa_fcs_vport_event event)
6452{
6453        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6454        bfa_trc(__vport_fcs(vport), event);
6455
6456        switch (event) {
6457        case BFA_FCS_VPORT_SM_OFFLINE:
6458                bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6459                fallthrough;
6460
6461        case BFA_FCS_VPORT_SM_RSP_OK:
6462        case BFA_FCS_VPORT_SM_RSP_ERROR:
6463                bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6464                bfa_fcs_vport_free(vport);
6465                break;
6466
6467        case BFA_FCS_VPORT_SM_DELETE:
6468                break;
6469
6470        default:
6471                bfa_sm_fault(__vport_fcs(vport), event);
6472        }
6473}
6474
6475
6476
6477/*
6478 *  fcs_vport_private FCS virtual port private functions
6479 */
6480/*
6481 * Send AEN notification
6482 */
6483static void
6484bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s *port,
6485                       enum bfa_lport_aen_event event)
6486{
6487        struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
6488        struct bfa_aen_entry_s  *aen_entry;
6489
6490        bfad_get_aen_entry(bfad, aen_entry);
6491        if (!aen_entry)
6492                return;
6493
6494        aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
6495        aen_entry->aen_data.lport.roles = port->port_cfg.roles;
6496        aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
6497                                        bfa_fcs_get_base_port(port->fcs));
6498        aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
6499
6500        /* Send the AEN notification */
6501        bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
6502                                  BFA_AEN_CAT_LPORT, event);
6503}
6504
6505/*
6506 * This routine will be called to send a FDISC command.
6507 */
6508static void
6509bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
6510{
6511        bfa_lps_fdisc(vport->lps, vport,
6512                bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
6513                __vport_pwwn(vport), __vport_nwwn(vport));
6514        vport->vport_stats.fdisc_sent++;
6515}
6516
6517static void
6518bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
6519{
6520        u8              lsrjt_rsn = vport->lps->lsrjt_rsn;
6521        u8              lsrjt_expl = vport->lps->lsrjt_expl;
6522
6523        bfa_trc(__vport_fcs(vport), lsrjt_rsn);
6524        bfa_trc(__vport_fcs(vport), lsrjt_expl);
6525
6526        /* For certain reason codes, we don't want to retry. */
6527        switch (vport->lps->lsrjt_expl) {
6528        case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
6529        case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
6530                if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6531                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6532                else {
6533                        bfa_fcs_vport_aen_post(&vport->lport,
6534                                        BFA_LPORT_AEN_NPIV_DUP_WWN);
6535                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
6536                }
6537                break;
6538
6539        case FC_LS_RJT_EXP_INSUFF_RES:
6540                /*
6541                 * This means max logins per port/switch setting on the
6542                 * switch was exceeded.
6543                 */
6544                if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6545                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6546                else {
6547                        bfa_fcs_vport_aen_post(&vport->lport,
6548                                        BFA_LPORT_AEN_NPIV_FABRIC_MAX);
6549                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_FABRIC_MAX);
6550                }
6551                break;
6552
6553        default:
6554                if (vport->fdisc_retries == 0)
6555                        bfa_fcs_vport_aen_post(&vport->lport,
6556                                        BFA_LPORT_AEN_NPIV_UNKNOWN);
6557                bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6558        }
6559}
6560
6561/*
6562 *      Called to send a logout to the fabric. Used when a V-Port is
6563 *      deleted/stopped.
6564 */
6565static void
6566bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
6567{
6568        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6569
6570        vport->vport_stats.logo_sent++;
6571        bfa_lps_fdisclogo(vport->lps);
6572}
6573
6574
6575/*
6576 *     This routine will be called by bfa_timer on timer timeouts.
6577 *
6578 *      param[in]       vport           - pointer to bfa_fcs_vport_t.
6579 *      param[out]      vport_status    - pointer to return vport status in
6580 *
6581 *      return
6582 *              void
6583 *
6584 *      Special Considerations:
6585 *
6586 *      note
6587 */
6588static void
6589bfa_fcs_vport_timeout(void *vport_arg)
6590{
6591        struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
6592
6593        vport->vport_stats.fdisc_timeouts++;
6594        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
6595}
6596
6597static void
6598bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
6599{
6600        struct bfad_vport_s *vport_drv =
6601                        (struct bfad_vport_s *)vport->vport_drv;
6602
6603        bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
6604        bfa_lps_delete(vport->lps);
6605
6606        if (vport_drv->comp_del) {
6607                complete(vport_drv->comp_del);
6608                return;
6609        }
6610
6611        /*
6612         * We queue the vport delete work to the IM work_q from here.
6613         * The memory for the bfad_vport_s is freed from the FC function
6614         * template vport_delete entry point.
6615         */
6616        bfad_im_port_delete(vport_drv->drv_port.bfad, &vport_drv->drv_port);
6617}
6618
6619/*
6620 *  fcs_vport_public FCS virtual port public interfaces
6621 */
6622
6623/*
6624 * Online notification from fabric SM.
6625 */
6626void
6627bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
6628{
6629        vport->vport_stats.fab_online++;
6630        if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport)))
6631                bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
6632        else
6633                vport->vport_stats.fab_no_npiv++;
6634}
6635
6636/*
6637 * Offline notification from fabric SM.
6638 */
6639void
6640bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
6641{
6642        vport->vport_stats.fab_offline++;
6643        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
6644}
6645
6646/*
6647 * Cleanup notification from fabric SM on link timer expiry.
6648 */
6649void
6650bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
6651{
6652        vport->vport_stats.fab_cleanup++;
6653}
6654
6655/*
6656 * Stop notification from fabric SM. To be invoked from within FCS.
6657 */
6658void
6659bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport)
6660{
6661        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
6662}
6663
6664/*
6665 * delete notification from fabric SM. To be invoked from within FCS.
6666 */
6667void
6668bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
6669{
6670        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
6671}
6672
6673/*
6674 * Stop completion callback from associated lport
6675 */
6676void
6677bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
6678{
6679        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
6680}
6681
6682/*
6683 * Delete completion callback from associated lport
6684 */
6685void
6686bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
6687{
6688        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
6689}
6690
6691
6692
6693/*
6694 *  fcs_vport_api Virtual port API
6695 */
6696
6697/*
6698 *      Use this function to instantiate a new FCS vport object. This
6699 *      function will not trigger any HW initialization process (which will be
6700 *      done in vport_start() call)
6701 *
6702 *      param[in] vport -               pointer to bfa_fcs_vport_t. This space
6703 *                                      needs to be allocated by the driver.
6704 *      param[in] fcs           -       FCS instance
6705 *      param[in] vport_cfg     -       vport configuration
6706 *      param[in] vf_id         -       VF_ID if vport is created within a VF.
6707 *                                      FC_VF_ID_NULL to specify base fabric.
6708 *      param[in] vport_drv     -       Opaque handle back to the driver's vport
6709 *                                      structure
6710 *
6711 *      retval BFA_STATUS_OK - on success.
6712 *      retval BFA_STATUS_FAILED - on failure.
6713 */
6714bfa_status_t
6715bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
6716                u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
6717                struct bfad_vport_s *vport_drv)
6718{
6719        if (vport_cfg->pwwn == 0)
6720                return BFA_STATUS_INVALID_WWN;
6721
6722        if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
6723                return BFA_STATUS_VPORT_WWN_BP;
6724
6725        if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
6726                return BFA_STATUS_VPORT_EXISTS;
6727
6728        if (fcs->fabric.num_vports ==
6729                        bfa_lps_get_max_vport(fcs->bfa))
6730                return BFA_STATUS_VPORT_MAX;
6731
6732        vport->lps = bfa_lps_alloc(fcs->bfa);
6733        if (!vport->lps)
6734                return BFA_STATUS_VPORT_MAX;
6735
6736        vport->vport_drv = vport_drv;
6737        vport_cfg->preboot_vp = BFA_FALSE;
6738
6739        bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6740        bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
6741        bfa_fcs_lport_init(&vport->lport, vport_cfg);
6742        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
6743
6744        return BFA_STATUS_OK;
6745}
6746
6747/*
6748 *      Use this function to instantiate a new FCS PBC vport object. This
6749 *      function will not trigger any HW initialization process (which will be
6750 *      done in vport_start() call)
6751 *
6752 *      param[in] vport -       pointer to bfa_fcs_vport_t. This space
6753 *                              needs to be allocated by the driver.
6754 *      param[in] fcs   -       FCS instance
6755 *      param[in] vport_cfg     -       vport configuration
6756 *      param[in] vf_id         -       VF_ID if vport is created within a VF.
6757 *                                      FC_VF_ID_NULL to specify base fabric.
6758 *      param[in] vport_drv     -       Opaque handle back to the driver's vport
6759 *                                      structure
6760 *
6761 *      retval BFA_STATUS_OK - on success.
6762 *      retval BFA_STATUS_FAILED - on failure.
6763 */
6764bfa_status_t
6765bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
6766                        u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
6767                        struct bfad_vport_s *vport_drv)
6768{
6769        bfa_status_t rc;
6770
6771        rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
6772        vport->lport.port_cfg.preboot_vp = BFA_TRUE;
6773
6774        return rc;
6775}
6776
6777/*
6778 *      Use this function to findout if this is a pbc vport or not.
6779 *
6780 * @param[in] vport - pointer to bfa_fcs_vport_t.
6781 *
6782 * @returns None
6783 */
6784bfa_boolean_t
6785bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
6786{
6787
6788        if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
6789                return BFA_TRUE;
6790        else
6791                return BFA_FALSE;
6792
6793}
6794
6795/*
6796 * Use this function initialize the vport.
6797 *
6798 * @param[in] vport - pointer to bfa_fcs_vport_t.
6799 *
6800 * @returns None
6801 */
6802bfa_status_t
6803bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
6804{
6805        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
6806
6807        return BFA_STATUS_OK;
6808}
6809
6810/*
6811 *      Use this function quiese the vport object. This function will return
6812 *      immediately, when the vport is actually stopped, the
6813 *      bfa_drv_vport_stop_cb() will be called.
6814 *
6815 *      param[in] vport - pointer to bfa_fcs_vport_t.
6816 *
6817 *      return None
6818 */
6819bfa_status_t
6820bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
6821{
6822        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
6823
6824        return BFA_STATUS_OK;
6825}
6826
6827/*
6828 *      Use this function to delete a vport object. Fabric object should
6829 *      be stopped before this function call.
6830 *
6831 *      !!!!!!! Donot invoke this from within FCS  !!!!!!!
6832 *
6833 *      param[in] vport - pointer to bfa_fcs_vport_t.
6834 *
6835 *      return     None
6836 */
6837bfa_status_t
6838bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
6839{
6840
6841        if (vport->lport.port_cfg.preboot_vp)
6842                return BFA_STATUS_PBC;
6843
6844        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
6845
6846        return BFA_STATUS_OK;
6847}
6848
6849/*
6850 *      Use this function to get vport's current status info.
6851 *
6852 *      param[in] vport         pointer to bfa_fcs_vport_t.
6853 *      param[out] attr         pointer to return vport attributes
6854 *
6855 *      return None
6856 */
6857void
6858bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
6859                        struct bfa_vport_attr_s *attr)
6860{
6861        if (vport == NULL || attr == NULL)
6862                return;
6863
6864        memset(attr, 0, sizeof(struct bfa_vport_attr_s));
6865
6866        bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
6867        attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
6868}
6869
6870
6871/*
6872 *      Lookup a virtual port. Excludes base port from lookup.
6873 */
6874struct bfa_fcs_vport_s *
6875bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
6876{
6877        struct bfa_fcs_vport_s *vport;
6878        struct bfa_fcs_fabric_s *fabric;
6879
6880        bfa_trc(fcs, vf_id);
6881        bfa_trc(fcs, vpwwn);
6882
6883        fabric = bfa_fcs_vf_lookup(fcs, vf_id);
6884        if (!fabric) {
6885                bfa_trc(fcs, vf_id);
6886                return NULL;
6887        }
6888
6889        vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
6890        return vport;
6891}
6892
6893/*
6894 * FDISC Response
6895 */
6896void
6897bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
6898{
6899        struct bfa_fcs_vport_s *vport = uarg;
6900
6901        bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6902        bfa_trc(__vport_fcs(vport), status);
6903
6904        switch (status) {
6905        case BFA_STATUS_OK:
6906                /*
6907                 * Initialize the V-Port fields
6908                 */
6909                __vport_fcid(vport) = vport->lps->lp_pid;
6910                vport->vport_stats.fdisc_accepts++;
6911                bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6912                break;
6913
6914        case BFA_STATUS_INVALID_MAC:
6915                /* Only for CNA */
6916                vport->vport_stats.fdisc_acc_bad++;
6917                bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6918
6919                break;
6920
6921        case BFA_STATUS_EPROTOCOL:
6922                switch (vport->lps->ext_status) {
6923                case BFA_EPROTO_BAD_ACCEPT:
6924                        vport->vport_stats.fdisc_acc_bad++;
6925                        break;
6926
6927                case BFA_EPROTO_UNKNOWN_RSP:
6928                        vport->vport_stats.fdisc_unknown_rsp++;
6929                        break;
6930
6931                default:
6932                        break;
6933                }
6934
6935                if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6936                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6937                else
6938                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
6939
6940                break;
6941
6942        case BFA_STATUS_ETIMER:
6943                vport->vport_stats.fdisc_timeouts++;
6944                if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6945                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6946                else
6947                        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
6948                break;
6949
6950        case BFA_STATUS_FABRIC_RJT:
6951                vport->vport_stats.fdisc_rejects++;
6952                bfa_fcs_vport_fdisc_rejected(vport);
6953                break;
6954
6955        default:
6956                vport->vport_stats.fdisc_rsp_err++;
6957                bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6958        }
6959}
6960
6961/*
6962 * LOGO response
6963 */
6964void
6965bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
6966{
6967        struct bfa_fcs_vport_s *vport = uarg;
6968        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6969}
6970
6971/*
6972 * Received clear virtual link
6973 */
6974void
6975bfa_cb_lps_cvl_event(void *bfad, void *uarg)
6976{
6977        struct bfa_fcs_vport_s *vport = uarg;
6978
6979        /* Send an Offline followed by an ONLINE */
6980        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
6981        bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
6982}
6983