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