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