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