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