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