cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bfa_fcs_lport.c (180523B)


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