18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * This file is part of the Chelsio FCoE driver for Linux.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
78c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
88c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
98c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the
108c2ecf20Sopenharmony_ci * OpenIB.org BSD license below:
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci *     Redistribution and use in source and binary forms, with or
138c2ecf20Sopenharmony_ci *     without modification, are permitted provided that the following
148c2ecf20Sopenharmony_ci *     conditions are met:
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci *      - Redistributions of source code must retain the above
178c2ecf20Sopenharmony_ci *        copyright notice, this list of conditions and the following
188c2ecf20Sopenharmony_ci *        disclaimer.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci *      - Redistributions in binary form must reproduce the above
218c2ecf20Sopenharmony_ci *        copyright notice, this list of conditions and the following
228c2ecf20Sopenharmony_ci *        disclaimer in the documentation and/or other materials
238c2ecf20Sopenharmony_ci *        provided with the distribution.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
268c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
278c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
288c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
298c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
308c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
318c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
328c2ecf20Sopenharmony_ci * SOFTWARE.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include <linux/kernel.h>
368c2ecf20Sopenharmony_ci#include <linux/string.h>
378c2ecf20Sopenharmony_ci#include <linux/delay.h>
388c2ecf20Sopenharmony_ci#include <linux/module.h>
398c2ecf20Sopenharmony_ci#include <linux/init.h>
408c2ecf20Sopenharmony_ci#include <linux/pci.h>
418c2ecf20Sopenharmony_ci#include <linux/mm.h>
428c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
438c2ecf20Sopenharmony_ci#include <scsi/fc/fc_fs.h>
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#include "csio_init.h"
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic void
488c2ecf20Sopenharmony_cicsio_vport_set_state(struct csio_lnode *ln);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/*
518c2ecf20Sopenharmony_ci * csio_reg_rnode - Register a remote port with FC transport.
528c2ecf20Sopenharmony_ci * @rn: Rnode representing remote port.
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * Call fc_remote_port_add() to register this remote port with FC transport.
558c2ecf20Sopenharmony_ci * If remote port is Initiator OR Target OR both, change the role appropriately.
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci */
588c2ecf20Sopenharmony_civoid
598c2ecf20Sopenharmony_cicsio_reg_rnode(struct csio_rnode *rn)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	struct csio_lnode *ln		= csio_rnode_to_lnode(rn);
628c2ecf20Sopenharmony_ci	struct Scsi_Host *shost		= csio_ln_to_shost(ln);
638c2ecf20Sopenharmony_ci	struct fc_rport_identifiers ids;
648c2ecf20Sopenharmony_ci	struct fc_rport  *rport;
658c2ecf20Sopenharmony_ci	struct csio_service_parms *sp;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	ids.node_name	= wwn_to_u64(csio_rn_wwnn(rn));
688c2ecf20Sopenharmony_ci	ids.port_name	= wwn_to_u64(csio_rn_wwpn(rn));
698c2ecf20Sopenharmony_ci	ids.port_id	= rn->nport_id;
708c2ecf20Sopenharmony_ci	ids.roles	= FC_RPORT_ROLE_UNKNOWN;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	if (rn->role & CSIO_RNFR_INITIATOR || rn->role & CSIO_RNFR_TARGET) {
738c2ecf20Sopenharmony_ci		rport = rn->rport;
748c2ecf20Sopenharmony_ci		CSIO_ASSERT(rport != NULL);
758c2ecf20Sopenharmony_ci		goto update_role;
768c2ecf20Sopenharmony_ci	}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	rn->rport = fc_remote_port_add(shost, 0, &ids);
798c2ecf20Sopenharmony_ci	if (!rn->rport) {
808c2ecf20Sopenharmony_ci		csio_ln_err(ln, "Failed to register rport = 0x%x.\n",
818c2ecf20Sopenharmony_ci					rn->nport_id);
828c2ecf20Sopenharmony_ci		return;
838c2ecf20Sopenharmony_ci	}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	ln->num_reg_rnodes++;
868c2ecf20Sopenharmony_ci	rport = rn->rport;
878c2ecf20Sopenharmony_ci	spin_lock_irq(shost->host_lock);
888c2ecf20Sopenharmony_ci	*((struct csio_rnode **)rport->dd_data) = rn;
898c2ecf20Sopenharmony_ci	spin_unlock_irq(shost->host_lock);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	sp = &rn->rn_sparm;
928c2ecf20Sopenharmony_ci	rport->maxframe_size = ntohs(sp->csp.sp_bb_data);
938c2ecf20Sopenharmony_ci	if (ntohs(sp->clsp[2].cp_class) & FC_CPC_VALID)
948c2ecf20Sopenharmony_ci		rport->supported_classes = FC_COS_CLASS3;
958c2ecf20Sopenharmony_ci	else
968c2ecf20Sopenharmony_ci		rport->supported_classes = FC_COS_UNSPECIFIED;
978c2ecf20Sopenharmony_ciupdate_role:
988c2ecf20Sopenharmony_ci	if (rn->role & CSIO_RNFR_INITIATOR)
998c2ecf20Sopenharmony_ci		ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
1008c2ecf20Sopenharmony_ci	if (rn->role & CSIO_RNFR_TARGET)
1018c2ecf20Sopenharmony_ci		ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	if (ids.roles != FC_RPORT_ROLE_UNKNOWN)
1048c2ecf20Sopenharmony_ci		fc_remote_port_rolechg(rport, ids.roles);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	rn->scsi_id = rport->scsi_target_id;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	csio_ln_dbg(ln, "Remote port x%x role 0x%x registered\n",
1098c2ecf20Sopenharmony_ci		rn->nport_id, ids.roles);
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/*
1138c2ecf20Sopenharmony_ci * csio_unreg_rnode - Unregister a remote port with FC transport.
1148c2ecf20Sopenharmony_ci * @rn: Rnode representing remote port.
1158c2ecf20Sopenharmony_ci *
1168c2ecf20Sopenharmony_ci * Call fc_remote_port_delete() to unregister this remote port with FC
1178c2ecf20Sopenharmony_ci * transport.
1188c2ecf20Sopenharmony_ci *
1198c2ecf20Sopenharmony_ci */
1208c2ecf20Sopenharmony_civoid
1218c2ecf20Sopenharmony_cicsio_unreg_rnode(struct csio_rnode *rn)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
1248c2ecf20Sopenharmony_ci	struct fc_rport *rport = rn->rport;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	rn->role &= ~(CSIO_RNFR_INITIATOR | CSIO_RNFR_TARGET);
1278c2ecf20Sopenharmony_ci	fc_remote_port_delete(rport);
1288c2ecf20Sopenharmony_ci	ln->num_reg_rnodes--;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	csio_ln_dbg(ln, "Remote port x%x un-registered\n", rn->nport_id);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci/*
1348c2ecf20Sopenharmony_ci * csio_lnode_async_event - Async events from local port.
1358c2ecf20Sopenharmony_ci * @ln: lnode representing local port.
1368c2ecf20Sopenharmony_ci *
1378c2ecf20Sopenharmony_ci * Async events from local node that FC transport/SCSI ML
1388c2ecf20Sopenharmony_ci * should be made aware of (Eg: RSCN).
1398c2ecf20Sopenharmony_ci */
1408c2ecf20Sopenharmony_civoid
1418c2ecf20Sopenharmony_cicsio_lnode_async_event(struct csio_lnode *ln, enum csio_ln_fc_evt fc_evt)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	switch (fc_evt) {
1448c2ecf20Sopenharmony_ci	case CSIO_LN_FC_RSCN:
1458c2ecf20Sopenharmony_ci		/* Get payload of rscn from ln */
1468c2ecf20Sopenharmony_ci		/* For each RSCN entry */
1478c2ecf20Sopenharmony_ci			/*
1488c2ecf20Sopenharmony_ci			 * fc_host_post_event(shost,
1498c2ecf20Sopenharmony_ci			 *		      fc_get_event_number(),
1508c2ecf20Sopenharmony_ci			 *		      FCH_EVT_RSCN,
1518c2ecf20Sopenharmony_ci			 *		      rscn_entry);
1528c2ecf20Sopenharmony_ci			 */
1538c2ecf20Sopenharmony_ci		break;
1548c2ecf20Sopenharmony_ci	case CSIO_LN_FC_LINKUP:
1558c2ecf20Sopenharmony_ci		/* send fc_host_post_event */
1568c2ecf20Sopenharmony_ci		/* set vport state */
1578c2ecf20Sopenharmony_ci		if (csio_is_npiv_ln(ln))
1588c2ecf20Sopenharmony_ci			csio_vport_set_state(ln);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci		break;
1618c2ecf20Sopenharmony_ci	case CSIO_LN_FC_LINKDOWN:
1628c2ecf20Sopenharmony_ci		/* send fc_host_post_event */
1638c2ecf20Sopenharmony_ci		/* set vport state */
1648c2ecf20Sopenharmony_ci		if (csio_is_npiv_ln(ln))
1658c2ecf20Sopenharmony_ci			csio_vport_set_state(ln);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci		break;
1688c2ecf20Sopenharmony_ci	case CSIO_LN_FC_ATTRIB_UPDATE:
1698c2ecf20Sopenharmony_ci		csio_fchost_attr_init(ln);
1708c2ecf20Sopenharmony_ci		break;
1718c2ecf20Sopenharmony_ci	default:
1728c2ecf20Sopenharmony_ci		break;
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/*
1778c2ecf20Sopenharmony_ci * csio_fchost_attr_init - Initialize FC transport attributes
1788c2ecf20Sopenharmony_ci * @ln: Lnode.
1798c2ecf20Sopenharmony_ci *
1808c2ecf20Sopenharmony_ci */
1818c2ecf20Sopenharmony_civoid
1828c2ecf20Sopenharmony_cicsio_fchost_attr_init(struct csio_lnode *ln)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	struct Scsi_Host  *shost = csio_ln_to_shost(ln);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	fc_host_node_name(shost) = wwn_to_u64(csio_ln_wwnn(ln));
1878c2ecf20Sopenharmony_ci	fc_host_port_name(shost) = wwn_to_u64(csio_ln_wwpn(ln));
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	fc_host_supported_classes(shost) = FC_COS_CLASS3;
1908c2ecf20Sopenharmony_ci	fc_host_max_npiv_vports(shost) =
1918c2ecf20Sopenharmony_ci			(csio_lnode_to_hw(ln))->fres_info.max_vnps;
1928c2ecf20Sopenharmony_ci	fc_host_supported_speeds(shost) = FC_PORTSPEED_10GBIT |
1938c2ecf20Sopenharmony_ci		FC_PORTSPEED_1GBIT;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	fc_host_maxframe_size(shost) = ntohs(ln->ln_sparm.csp.sp_bb_data);
1968c2ecf20Sopenharmony_ci	memset(fc_host_supported_fc4s(shost), 0,
1978c2ecf20Sopenharmony_ci		sizeof(fc_host_supported_fc4s(shost)));
1988c2ecf20Sopenharmony_ci	fc_host_supported_fc4s(shost)[7] = 1;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	memset(fc_host_active_fc4s(shost), 0,
2018c2ecf20Sopenharmony_ci		sizeof(fc_host_active_fc4s(shost)));
2028c2ecf20Sopenharmony_ci	fc_host_active_fc4s(shost)[7] = 1;
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci/*
2068c2ecf20Sopenharmony_ci * csio_get_host_port_id - sysfs entries for nport_id is
2078c2ecf20Sopenharmony_ci * populated/cached from this function
2088c2ecf20Sopenharmony_ci */
2098c2ecf20Sopenharmony_cistatic void
2108c2ecf20Sopenharmony_cicsio_get_host_port_id(struct Scsi_Host *shost)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	struct csio_lnode *ln	= shost_priv(shost);
2138c2ecf20Sopenharmony_ci	struct csio_hw *hw = csio_lnode_to_hw(ln);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
2168c2ecf20Sopenharmony_ci	fc_host_port_id(shost) = ln->nport_id;
2178c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci/*
2218c2ecf20Sopenharmony_ci * csio_get_port_type - Return FC local port type.
2228c2ecf20Sopenharmony_ci * @shost: scsi host.
2238c2ecf20Sopenharmony_ci *
2248c2ecf20Sopenharmony_ci */
2258c2ecf20Sopenharmony_cistatic void
2268c2ecf20Sopenharmony_cicsio_get_host_port_type(struct Scsi_Host *shost)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	struct csio_lnode *ln = shost_priv(shost);
2298c2ecf20Sopenharmony_ci	struct csio_hw *hw = csio_lnode_to_hw(ln);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
2328c2ecf20Sopenharmony_ci	if (csio_is_npiv_ln(ln))
2338c2ecf20Sopenharmony_ci		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
2348c2ecf20Sopenharmony_ci	else
2358c2ecf20Sopenharmony_ci		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
2368c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci/*
2408c2ecf20Sopenharmony_ci * csio_get_port_state - Return FC local port state.
2418c2ecf20Sopenharmony_ci * @shost: scsi host.
2428c2ecf20Sopenharmony_ci *
2438c2ecf20Sopenharmony_ci */
2448c2ecf20Sopenharmony_cistatic void
2458c2ecf20Sopenharmony_cicsio_get_host_port_state(struct Scsi_Host *shost)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	struct csio_lnode *ln = shost_priv(shost);
2488c2ecf20Sopenharmony_ci	struct csio_hw *hw = csio_lnode_to_hw(ln);
2498c2ecf20Sopenharmony_ci	char state[16];
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	csio_lnode_state_to_str(ln, state);
2548c2ecf20Sopenharmony_ci	if (!strcmp(state, "READY"))
2558c2ecf20Sopenharmony_ci		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
2568c2ecf20Sopenharmony_ci	else if (!strcmp(state, "OFFLINE"))
2578c2ecf20Sopenharmony_ci		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
2588c2ecf20Sopenharmony_ci	else
2598c2ecf20Sopenharmony_ci		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci/*
2658c2ecf20Sopenharmony_ci * csio_get_host_speed - Return link speed to FC transport.
2668c2ecf20Sopenharmony_ci * @shost: scsi host.
2678c2ecf20Sopenharmony_ci *
2688c2ecf20Sopenharmony_ci */
2698c2ecf20Sopenharmony_cistatic void
2708c2ecf20Sopenharmony_cicsio_get_host_speed(struct Scsi_Host *shost)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	struct csio_lnode *ln = shost_priv(shost);
2738c2ecf20Sopenharmony_ci	struct csio_hw *hw = csio_lnode_to_hw(ln);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
2768c2ecf20Sopenharmony_ci	switch (hw->pport[ln->portid].link_speed) {
2778c2ecf20Sopenharmony_ci	case FW_PORT_CAP32_SPEED_1G:
2788c2ecf20Sopenharmony_ci		fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
2798c2ecf20Sopenharmony_ci		break;
2808c2ecf20Sopenharmony_ci	case FW_PORT_CAP32_SPEED_10G:
2818c2ecf20Sopenharmony_ci		fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
2828c2ecf20Sopenharmony_ci		break;
2838c2ecf20Sopenharmony_ci	case FW_PORT_CAP32_SPEED_25G:
2848c2ecf20Sopenharmony_ci		fc_host_speed(shost) = FC_PORTSPEED_25GBIT;
2858c2ecf20Sopenharmony_ci		break;
2868c2ecf20Sopenharmony_ci	case FW_PORT_CAP32_SPEED_40G:
2878c2ecf20Sopenharmony_ci		fc_host_speed(shost) = FC_PORTSPEED_40GBIT;
2888c2ecf20Sopenharmony_ci		break;
2898c2ecf20Sopenharmony_ci	case FW_PORT_CAP32_SPEED_50G:
2908c2ecf20Sopenharmony_ci		fc_host_speed(shost) = FC_PORTSPEED_50GBIT;
2918c2ecf20Sopenharmony_ci		break;
2928c2ecf20Sopenharmony_ci	case FW_PORT_CAP32_SPEED_100G:
2938c2ecf20Sopenharmony_ci		fc_host_speed(shost) = FC_PORTSPEED_100GBIT;
2948c2ecf20Sopenharmony_ci		break;
2958c2ecf20Sopenharmony_ci	default:
2968c2ecf20Sopenharmony_ci		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
2978c2ecf20Sopenharmony_ci		break;
2988c2ecf20Sopenharmony_ci	}
2998c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
3008c2ecf20Sopenharmony_ci}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci/*
3038c2ecf20Sopenharmony_ci * csio_get_host_fabric_name - Return fabric name
3048c2ecf20Sopenharmony_ci * @shost: scsi host.
3058c2ecf20Sopenharmony_ci *
3068c2ecf20Sopenharmony_ci */
3078c2ecf20Sopenharmony_cistatic void
3088c2ecf20Sopenharmony_cicsio_get_host_fabric_name(struct Scsi_Host *shost)
3098c2ecf20Sopenharmony_ci{
3108c2ecf20Sopenharmony_ci	struct csio_lnode *ln = shost_priv(shost);
3118c2ecf20Sopenharmony_ci	struct csio_rnode *rn = NULL;
3128c2ecf20Sopenharmony_ci	struct csio_hw *hw = csio_lnode_to_hw(ln);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
3158c2ecf20Sopenharmony_ci	rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI);
3168c2ecf20Sopenharmony_ci	if (rn)
3178c2ecf20Sopenharmony_ci		fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn));
3188c2ecf20Sopenharmony_ci	else
3198c2ecf20Sopenharmony_ci		fc_host_fabric_name(shost) = 0;
3208c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci/*
3248c2ecf20Sopenharmony_ci * csio_get_host_speed - Return FC transport statistics.
3258c2ecf20Sopenharmony_ci * @ln: Lnode.
3268c2ecf20Sopenharmony_ci *
3278c2ecf20Sopenharmony_ci */
3288c2ecf20Sopenharmony_cistatic struct fc_host_statistics *
3298c2ecf20Sopenharmony_cicsio_get_stats(struct Scsi_Host *shost)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci	struct csio_lnode *ln = shost_priv(shost);
3328c2ecf20Sopenharmony_ci	struct csio_hw *hw = csio_lnode_to_hw(ln);
3338c2ecf20Sopenharmony_ci	struct fc_host_statistics *fhs = &ln->fch_stats;
3348c2ecf20Sopenharmony_ci	struct fw_fcoe_port_stats fcoe_port_stats;
3358c2ecf20Sopenharmony_ci	uint64_t seconds;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	memset(&fcoe_port_stats, 0, sizeof(struct fw_fcoe_port_stats));
3388c2ecf20Sopenharmony_ci	csio_get_phy_port_stats(hw, ln->portid, &fcoe_port_stats);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	fhs->tx_frames  += (be64_to_cpu(fcoe_port_stats.tx_bcast_frames) +
3418c2ecf20Sopenharmony_ci			    be64_to_cpu(fcoe_port_stats.tx_mcast_frames) +
3428c2ecf20Sopenharmony_ci			    be64_to_cpu(fcoe_port_stats.tx_ucast_frames) +
3438c2ecf20Sopenharmony_ci			    be64_to_cpu(fcoe_port_stats.tx_offload_frames));
3448c2ecf20Sopenharmony_ci	fhs->tx_words  += (be64_to_cpu(fcoe_port_stats.tx_bcast_bytes) +
3458c2ecf20Sopenharmony_ci			   be64_to_cpu(fcoe_port_stats.tx_mcast_bytes) +
3468c2ecf20Sopenharmony_ci			   be64_to_cpu(fcoe_port_stats.tx_ucast_bytes) +
3478c2ecf20Sopenharmony_ci			   be64_to_cpu(fcoe_port_stats.tx_offload_bytes)) /
3488c2ecf20Sopenharmony_ci							CSIO_WORD_TO_BYTE;
3498c2ecf20Sopenharmony_ci	fhs->rx_frames += (be64_to_cpu(fcoe_port_stats.rx_bcast_frames) +
3508c2ecf20Sopenharmony_ci			   be64_to_cpu(fcoe_port_stats.rx_mcast_frames) +
3518c2ecf20Sopenharmony_ci			   be64_to_cpu(fcoe_port_stats.rx_ucast_frames));
3528c2ecf20Sopenharmony_ci	fhs->rx_words += (be64_to_cpu(fcoe_port_stats.rx_bcast_bytes) +
3538c2ecf20Sopenharmony_ci			  be64_to_cpu(fcoe_port_stats.rx_mcast_bytes) +
3548c2ecf20Sopenharmony_ci			  be64_to_cpu(fcoe_port_stats.rx_ucast_bytes)) /
3558c2ecf20Sopenharmony_ci							CSIO_WORD_TO_BYTE;
3568c2ecf20Sopenharmony_ci	fhs->error_frames += be64_to_cpu(fcoe_port_stats.rx_err_frames);
3578c2ecf20Sopenharmony_ci	fhs->fcp_input_requests +=  ln->stats.n_input_requests;
3588c2ecf20Sopenharmony_ci	fhs->fcp_output_requests +=  ln->stats.n_output_requests;
3598c2ecf20Sopenharmony_ci	fhs->fcp_control_requests +=  ln->stats.n_control_requests;
3608c2ecf20Sopenharmony_ci	fhs->fcp_input_megabytes +=  ln->stats.n_input_bytes >> 20;
3618c2ecf20Sopenharmony_ci	fhs->fcp_output_megabytes +=  ln->stats.n_output_bytes >> 20;
3628c2ecf20Sopenharmony_ci	fhs->link_failure_count = ln->stats.n_link_down;
3638c2ecf20Sopenharmony_ci	/* Reset stats for the device */
3648c2ecf20Sopenharmony_ci	seconds = jiffies_to_msecs(jiffies) - hw->stats.n_reset_start;
3658c2ecf20Sopenharmony_ci	do_div(seconds, 1000);
3668c2ecf20Sopenharmony_ci	fhs->seconds_since_last_reset = seconds;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	return fhs;
3698c2ecf20Sopenharmony_ci}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci/*
3728c2ecf20Sopenharmony_ci * csio_set_rport_loss_tmo - Set the rport dev loss timeout
3738c2ecf20Sopenharmony_ci * @rport: fc rport.
3748c2ecf20Sopenharmony_ci * @timeout: new value for dev loss tmo.
3758c2ecf20Sopenharmony_ci *
3768c2ecf20Sopenharmony_ci * If timeout is non zero set the dev_loss_tmo to timeout, else set
3778c2ecf20Sopenharmony_ci * dev_loss_tmo to one.
3788c2ecf20Sopenharmony_ci */
3798c2ecf20Sopenharmony_cistatic void
3808c2ecf20Sopenharmony_cicsio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	if (timeout)
3838c2ecf20Sopenharmony_ci		rport->dev_loss_tmo = timeout;
3848c2ecf20Sopenharmony_ci	else
3858c2ecf20Sopenharmony_ci		rport->dev_loss_tmo = 1;
3868c2ecf20Sopenharmony_ci}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_cistatic void
3898c2ecf20Sopenharmony_cicsio_vport_set_state(struct csio_lnode *ln)
3908c2ecf20Sopenharmony_ci{
3918c2ecf20Sopenharmony_ci	struct fc_vport *fc_vport = ln->fc_vport;
3928c2ecf20Sopenharmony_ci	struct csio_lnode  *pln = ln->pln;
3938c2ecf20Sopenharmony_ci	char state[16];
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	/* Set fc vport state based on phyiscal lnode */
3968c2ecf20Sopenharmony_ci	csio_lnode_state_to_str(pln, state);
3978c2ecf20Sopenharmony_ci	if (strcmp(state, "READY")) {
3988c2ecf20Sopenharmony_ci		fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
3998c2ecf20Sopenharmony_ci		return;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	if (!(pln->flags & CSIO_LNF_NPIVSUPP)) {
4038c2ecf20Sopenharmony_ci		fc_vport_set_state(fc_vport, FC_VPORT_NO_FABRIC_SUPP);
4048c2ecf20Sopenharmony_ci		return;
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	/* Set fc vport state based on virtual lnode */
4088c2ecf20Sopenharmony_ci	csio_lnode_state_to_str(ln, state);
4098c2ecf20Sopenharmony_ci	if (strcmp(state, "READY")) {
4108c2ecf20Sopenharmony_ci		fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
4118c2ecf20Sopenharmony_ci		return;
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci	fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_cistatic int
4178c2ecf20Sopenharmony_cicsio_fcoe_alloc_vnp(struct csio_hw *hw, struct csio_lnode *ln)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	struct csio_lnode *pln;
4208c2ecf20Sopenharmony_ci	struct csio_mb  *mbp;
4218c2ecf20Sopenharmony_ci	struct fw_fcoe_vnp_cmd *rsp;
4228c2ecf20Sopenharmony_ci	int ret = 0;
4238c2ecf20Sopenharmony_ci	int retry = 0;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	/* Issue VNP cmd to alloc vport */
4268c2ecf20Sopenharmony_ci	/* Allocate Mbox request */
4278c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
4288c2ecf20Sopenharmony_ci	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
4298c2ecf20Sopenharmony_ci	if (!mbp) {
4308c2ecf20Sopenharmony_ci		CSIO_INC_STATS(hw, n_err_nomem);
4318c2ecf20Sopenharmony_ci		ret = -ENOMEM;
4328c2ecf20Sopenharmony_ci		goto out;
4338c2ecf20Sopenharmony_ci	}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	pln = ln->pln;
4368c2ecf20Sopenharmony_ci	ln->fcf_flowid = pln->fcf_flowid;
4378c2ecf20Sopenharmony_ci	ln->portid = pln->portid;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	csio_fcoe_vnp_alloc_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
4408c2ecf20Sopenharmony_ci				    pln->fcf_flowid, pln->vnp_flowid, 0,
4418c2ecf20Sopenharmony_ci				    csio_ln_wwnn(ln), csio_ln_wwpn(ln), NULL);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	for (retry = 0; retry < 3; retry++) {
4448c2ecf20Sopenharmony_ci		/* FW is expected to complete vnp cmd in immediate mode
4458c2ecf20Sopenharmony_ci		 * without much delay.
4468c2ecf20Sopenharmony_ci		 * Otherwise, there will be increase in IO latency since HW
4478c2ecf20Sopenharmony_ci		 * lock is held till completion of vnp mbox cmd.
4488c2ecf20Sopenharmony_ci		 */
4498c2ecf20Sopenharmony_ci		ret = csio_mb_issue(hw, mbp);
4508c2ecf20Sopenharmony_ci		if (ret != -EBUSY)
4518c2ecf20Sopenharmony_ci			break;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci		/* Retry if mbox returns busy */
4548c2ecf20Sopenharmony_ci		spin_unlock_irq(&hw->lock);
4558c2ecf20Sopenharmony_ci		msleep(2000);
4568c2ecf20Sopenharmony_ci		spin_lock_irq(&hw->lock);
4578c2ecf20Sopenharmony_ci	}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	if (ret) {
4608c2ecf20Sopenharmony_ci		csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
4618c2ecf20Sopenharmony_ci		goto out_free;
4628c2ecf20Sopenharmony_ci	}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	/* Process Mbox response of VNP command */
4658c2ecf20Sopenharmony_ci	rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
4668c2ecf20Sopenharmony_ci	if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
4678c2ecf20Sopenharmony_ci		csio_ln_err(ln, "FCOE VNP ALLOC cmd returned 0x%x!\n",
4688c2ecf20Sopenharmony_ci			    FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));
4698c2ecf20Sopenharmony_ci		ret = -EINVAL;
4708c2ecf20Sopenharmony_ci		goto out_free;
4718c2ecf20Sopenharmony_ci	}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	ln->vnp_flowid = FW_FCOE_VNP_CMD_VNPI_GET(
4748c2ecf20Sopenharmony_ci				ntohl(rsp->gen_wwn_to_vnpi));
4758c2ecf20Sopenharmony_ci	memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);
4768c2ecf20Sopenharmony_ci	memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	csio_ln_dbg(ln, "FCOE VNPI: 0x%x\n", ln->vnp_flowid);
4798c2ecf20Sopenharmony_ci	csio_ln_dbg(ln, "\tWWNN: %x%x%x%x%x%x%x%x\n",
4808c2ecf20Sopenharmony_ci		    ln->ln_sparm.wwnn[0], ln->ln_sparm.wwnn[1],
4818c2ecf20Sopenharmony_ci		    ln->ln_sparm.wwnn[2], ln->ln_sparm.wwnn[3],
4828c2ecf20Sopenharmony_ci		    ln->ln_sparm.wwnn[4], ln->ln_sparm.wwnn[5],
4838c2ecf20Sopenharmony_ci		    ln->ln_sparm.wwnn[6], ln->ln_sparm.wwnn[7]);
4848c2ecf20Sopenharmony_ci	csio_ln_dbg(ln, "\tWWPN: %x%x%x%x%x%x%x%x\n",
4858c2ecf20Sopenharmony_ci		    ln->ln_sparm.wwpn[0], ln->ln_sparm.wwpn[1],
4868c2ecf20Sopenharmony_ci		    ln->ln_sparm.wwpn[2], ln->ln_sparm.wwpn[3],
4878c2ecf20Sopenharmony_ci		    ln->ln_sparm.wwpn[4], ln->ln_sparm.wwpn[5],
4888c2ecf20Sopenharmony_ci		    ln->ln_sparm.wwpn[6], ln->ln_sparm.wwpn[7]);
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ciout_free:
4918c2ecf20Sopenharmony_ci	mempool_free(mbp, hw->mb_mempool);
4928c2ecf20Sopenharmony_ciout:
4938c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
4948c2ecf20Sopenharmony_ci	return ret;
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_cistatic int
4988c2ecf20Sopenharmony_cicsio_fcoe_free_vnp(struct csio_hw *hw, struct csio_lnode *ln)
4998c2ecf20Sopenharmony_ci{
5008c2ecf20Sopenharmony_ci	struct csio_mb  *mbp;
5018c2ecf20Sopenharmony_ci	struct fw_fcoe_vnp_cmd *rsp;
5028c2ecf20Sopenharmony_ci	int ret = 0;
5038c2ecf20Sopenharmony_ci	int retry = 0;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	/* Issue VNP cmd to free vport */
5068c2ecf20Sopenharmony_ci	/* Allocate Mbox request */
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
5098c2ecf20Sopenharmony_ci	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
5108c2ecf20Sopenharmony_ci	if (!mbp) {
5118c2ecf20Sopenharmony_ci		CSIO_INC_STATS(hw, n_err_nomem);
5128c2ecf20Sopenharmony_ci		ret = -ENOMEM;
5138c2ecf20Sopenharmony_ci		goto out;
5148c2ecf20Sopenharmony_ci	}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
5178c2ecf20Sopenharmony_ci				   ln->fcf_flowid, ln->vnp_flowid,
5188c2ecf20Sopenharmony_ci				   NULL);
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	for (retry = 0; retry < 3; retry++) {
5218c2ecf20Sopenharmony_ci		ret = csio_mb_issue(hw, mbp);
5228c2ecf20Sopenharmony_ci		if (ret != -EBUSY)
5238c2ecf20Sopenharmony_ci			break;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci		/* Retry if mbox returns busy */
5268c2ecf20Sopenharmony_ci		spin_unlock_irq(&hw->lock);
5278c2ecf20Sopenharmony_ci		msleep(2000);
5288c2ecf20Sopenharmony_ci		spin_lock_irq(&hw->lock);
5298c2ecf20Sopenharmony_ci	}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	if (ret) {
5328c2ecf20Sopenharmony_ci		csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
5338c2ecf20Sopenharmony_ci		goto out_free;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	/* Process Mbox response of VNP command */
5378c2ecf20Sopenharmony_ci	rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
5388c2ecf20Sopenharmony_ci	if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
5398c2ecf20Sopenharmony_ci		csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n",
5408c2ecf20Sopenharmony_ci			    FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));
5418c2ecf20Sopenharmony_ci		ret = -EINVAL;
5428c2ecf20Sopenharmony_ci	}
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ciout_free:
5458c2ecf20Sopenharmony_ci	mempool_free(mbp, hw->mb_mempool);
5468c2ecf20Sopenharmony_ciout:
5478c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
5488c2ecf20Sopenharmony_ci	return ret;
5498c2ecf20Sopenharmony_ci}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_cistatic int
5528c2ecf20Sopenharmony_cicsio_vport_create(struct fc_vport *fc_vport, bool disable)
5538c2ecf20Sopenharmony_ci{
5548c2ecf20Sopenharmony_ci	struct Scsi_Host *shost = fc_vport->shost;
5558c2ecf20Sopenharmony_ci	struct csio_lnode *pln = shost_priv(shost);
5568c2ecf20Sopenharmony_ci	struct csio_lnode *ln = NULL;
5578c2ecf20Sopenharmony_ci	struct csio_hw *hw = csio_lnode_to_hw(pln);
5588c2ecf20Sopenharmony_ci	uint8_t wwn[8];
5598c2ecf20Sopenharmony_ci	int ret = -1;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	ln = csio_shost_init(hw, &fc_vport->dev, false, pln);
5628c2ecf20Sopenharmony_ci	if (!ln)
5638c2ecf20Sopenharmony_ci		goto error;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	if (fc_vport->node_name != 0) {
5668c2ecf20Sopenharmony_ci		u64_to_wwn(fc_vport->node_name, wwn);
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci		if (!CSIO_VALID_WWN(wwn)) {
5698c2ecf20Sopenharmony_ci			csio_ln_err(ln,
5708c2ecf20Sopenharmony_ci				    "vport create failed. Invalid wwnn\n");
5718c2ecf20Sopenharmony_ci			goto error;
5728c2ecf20Sopenharmony_ci		}
5738c2ecf20Sopenharmony_ci		memcpy(csio_ln_wwnn(ln), wwn, 8);
5748c2ecf20Sopenharmony_ci	}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	if (fc_vport->port_name != 0) {
5778c2ecf20Sopenharmony_ci		u64_to_wwn(fc_vport->port_name, wwn);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci		if (!CSIO_VALID_WWN(wwn)) {
5808c2ecf20Sopenharmony_ci			csio_ln_err(ln,
5818c2ecf20Sopenharmony_ci				    "vport create failed. Invalid wwpn\n");
5828c2ecf20Sopenharmony_ci			goto error;
5838c2ecf20Sopenharmony_ci		}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci		if (csio_lnode_lookup_by_wwpn(hw, wwn)) {
5868c2ecf20Sopenharmony_ci			csio_ln_err(ln,
5878c2ecf20Sopenharmony_ci			    "vport create failed. wwpn already exists\n");
5888c2ecf20Sopenharmony_ci			goto error;
5898c2ecf20Sopenharmony_ci		}
5908c2ecf20Sopenharmony_ci		memcpy(csio_ln_wwpn(ln), wwn, 8);
5918c2ecf20Sopenharmony_ci	}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
5948c2ecf20Sopenharmony_ci	ln->fc_vport = fc_vport;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	if (csio_fcoe_alloc_vnp(hw, ln))
5978c2ecf20Sopenharmony_ci		goto error;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	*(struct csio_lnode **)fc_vport->dd_data = ln;
6008c2ecf20Sopenharmony_ci	if (!fc_vport->node_name)
6018c2ecf20Sopenharmony_ci		fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
6028c2ecf20Sopenharmony_ci	if (!fc_vport->port_name)
6038c2ecf20Sopenharmony_ci		fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln));
6048c2ecf20Sopenharmony_ci	csio_fchost_attr_init(ln);
6058c2ecf20Sopenharmony_ci	return 0;
6068c2ecf20Sopenharmony_cierror:
6078c2ecf20Sopenharmony_ci	if (ln)
6088c2ecf20Sopenharmony_ci		csio_shost_exit(ln);
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	return ret;
6118c2ecf20Sopenharmony_ci}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_cistatic int
6148c2ecf20Sopenharmony_cicsio_vport_delete(struct fc_vport *fc_vport)
6158c2ecf20Sopenharmony_ci{
6168c2ecf20Sopenharmony_ci	struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
6178c2ecf20Sopenharmony_ci	struct Scsi_Host *shost = csio_ln_to_shost(ln);
6188c2ecf20Sopenharmony_ci	struct csio_hw *hw = csio_lnode_to_hw(ln);
6198c2ecf20Sopenharmony_ci	int rmv;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
6228c2ecf20Sopenharmony_ci	rmv = csio_is_hw_removing(hw);
6238c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	if (rmv) {
6268c2ecf20Sopenharmony_ci		csio_shost_exit(ln);
6278c2ecf20Sopenharmony_ci		return 0;
6288c2ecf20Sopenharmony_ci	}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	/* Quiesce ios and send remove event to lnode */
6318c2ecf20Sopenharmony_ci	scsi_block_requests(shost);
6328c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
6338c2ecf20Sopenharmony_ci	csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
6348c2ecf20Sopenharmony_ci	csio_lnode_close(ln);
6358c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
6368c2ecf20Sopenharmony_ci	scsi_unblock_requests(shost);
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	/* Free vnp */
6398c2ecf20Sopenharmony_ci	if (fc_vport->vport_state !=  FC_VPORT_DISABLED)
6408c2ecf20Sopenharmony_ci		csio_fcoe_free_vnp(hw, ln);
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	csio_shost_exit(ln);
6438c2ecf20Sopenharmony_ci	return 0;
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_cistatic int
6478c2ecf20Sopenharmony_cicsio_vport_disable(struct fc_vport *fc_vport, bool disable)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
6508c2ecf20Sopenharmony_ci	struct Scsi_Host *shost = csio_ln_to_shost(ln);
6518c2ecf20Sopenharmony_ci	struct csio_hw *hw = csio_lnode_to_hw(ln);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	/* disable vport */
6548c2ecf20Sopenharmony_ci	if (disable) {
6558c2ecf20Sopenharmony_ci		/* Quiesce ios and send stop event to lnode */
6568c2ecf20Sopenharmony_ci		scsi_block_requests(shost);
6578c2ecf20Sopenharmony_ci		spin_lock_irq(&hw->lock);
6588c2ecf20Sopenharmony_ci		csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
6598c2ecf20Sopenharmony_ci		csio_lnode_stop(ln);
6608c2ecf20Sopenharmony_ci		spin_unlock_irq(&hw->lock);
6618c2ecf20Sopenharmony_ci		scsi_unblock_requests(shost);
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci		/* Free vnp */
6648c2ecf20Sopenharmony_ci		csio_fcoe_free_vnp(hw, ln);
6658c2ecf20Sopenharmony_ci		fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
6668c2ecf20Sopenharmony_ci		csio_ln_err(ln, "vport disabled\n");
6678c2ecf20Sopenharmony_ci		return 0;
6688c2ecf20Sopenharmony_ci	} else {
6698c2ecf20Sopenharmony_ci		/* enable vport */
6708c2ecf20Sopenharmony_ci		fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
6718c2ecf20Sopenharmony_ci		if (csio_fcoe_alloc_vnp(hw, ln)) {
6728c2ecf20Sopenharmony_ci			csio_ln_err(ln, "vport enabled failed.\n");
6738c2ecf20Sopenharmony_ci			return -1;
6748c2ecf20Sopenharmony_ci		}
6758c2ecf20Sopenharmony_ci		csio_ln_err(ln, "vport enabled\n");
6768c2ecf20Sopenharmony_ci		return 0;
6778c2ecf20Sopenharmony_ci	}
6788c2ecf20Sopenharmony_ci}
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_cistatic void
6818c2ecf20Sopenharmony_cicsio_dev_loss_tmo_callbk(struct fc_rport *rport)
6828c2ecf20Sopenharmony_ci{
6838c2ecf20Sopenharmony_ci	struct csio_rnode *rn;
6848c2ecf20Sopenharmony_ci	struct csio_hw *hw;
6858c2ecf20Sopenharmony_ci	struct csio_lnode *ln;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	rn = *((struct csio_rnode **)rport->dd_data);
6888c2ecf20Sopenharmony_ci	ln = csio_rnode_to_lnode(rn);
6898c2ecf20Sopenharmony_ci	hw = csio_lnode_to_hw(ln);
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	spin_lock_irq(&hw->lock);
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	/* return if driver is being removed or same rnode comes back online */
6948c2ecf20Sopenharmony_ci	if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn))
6958c2ecf20Sopenharmony_ci		goto out;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n",
6988c2ecf20Sopenharmony_ci		    rn, rn->nport_id, csio_rn_flowid(rn));
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	CSIO_INC_STATS(ln, n_dev_loss_tmo);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	/*
7038c2ecf20Sopenharmony_ci	 * enqueue devloss event to event worker thread to serialize all
7048c2ecf20Sopenharmony_ci	 * rnode events.
7058c2ecf20Sopenharmony_ci	 */
7068c2ecf20Sopenharmony_ci	if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) {
7078c2ecf20Sopenharmony_ci		CSIO_INC_STATS(hw, n_evt_drop);
7088c2ecf20Sopenharmony_ci		goto out;
7098c2ecf20Sopenharmony_ci	}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
7128c2ecf20Sopenharmony_ci		hw->flags |= CSIO_HWF_FWEVT_PENDING;
7138c2ecf20Sopenharmony_ci		spin_unlock_irq(&hw->lock);
7148c2ecf20Sopenharmony_ci		schedule_work(&hw->evtq_work);
7158c2ecf20Sopenharmony_ci		return;
7168c2ecf20Sopenharmony_ci	}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ciout:
7198c2ecf20Sopenharmony_ci	spin_unlock_irq(&hw->lock);
7208c2ecf20Sopenharmony_ci}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci/* FC transport functions template - Physical port */
7238c2ecf20Sopenharmony_cistruct fc_function_template csio_fc_transport_funcs = {
7248c2ecf20Sopenharmony_ci	.show_host_node_name = 1,
7258c2ecf20Sopenharmony_ci	.show_host_port_name = 1,
7268c2ecf20Sopenharmony_ci	.show_host_supported_classes = 1,
7278c2ecf20Sopenharmony_ci	.show_host_supported_fc4s = 1,
7288c2ecf20Sopenharmony_ci	.show_host_maxframe_size = 1,
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	.get_host_port_id = csio_get_host_port_id,
7318c2ecf20Sopenharmony_ci	.show_host_port_id = 1,
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	.get_host_port_type = csio_get_host_port_type,
7348c2ecf20Sopenharmony_ci	.show_host_port_type = 1,
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	.get_host_port_state = csio_get_host_port_state,
7378c2ecf20Sopenharmony_ci	.show_host_port_state = 1,
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	.show_host_active_fc4s = 1,
7408c2ecf20Sopenharmony_ci	.get_host_speed = csio_get_host_speed,
7418c2ecf20Sopenharmony_ci	.show_host_speed = 1,
7428c2ecf20Sopenharmony_ci	.get_host_fabric_name = csio_get_host_fabric_name,
7438c2ecf20Sopenharmony_ci	.show_host_fabric_name = 1,
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	.get_fc_host_stats = csio_get_stats,
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	.dd_fcrport_size = sizeof(struct csio_rnode *),
7488c2ecf20Sopenharmony_ci	.show_rport_maxframe_size = 1,
7498c2ecf20Sopenharmony_ci	.show_rport_supported_classes = 1,
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	.set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
7528c2ecf20Sopenharmony_ci	.show_rport_dev_loss_tmo = 1,
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	.show_starget_port_id = 1,
7558c2ecf20Sopenharmony_ci	.show_starget_node_name = 1,
7568c2ecf20Sopenharmony_ci	.show_starget_port_name = 1,
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	.dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
7598c2ecf20Sopenharmony_ci	.dd_fcvport_size = sizeof(struct csio_lnode *),
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	.vport_create = csio_vport_create,
7628c2ecf20Sopenharmony_ci	.vport_disable = csio_vport_disable,
7638c2ecf20Sopenharmony_ci	.vport_delete = csio_vport_delete,
7648c2ecf20Sopenharmony_ci};
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci/* FC transport functions template - Virtual  port */
7678c2ecf20Sopenharmony_cistruct fc_function_template csio_fc_transport_vport_funcs = {
7688c2ecf20Sopenharmony_ci	.show_host_node_name = 1,
7698c2ecf20Sopenharmony_ci	.show_host_port_name = 1,
7708c2ecf20Sopenharmony_ci	.show_host_supported_classes = 1,
7718c2ecf20Sopenharmony_ci	.show_host_supported_fc4s = 1,
7728c2ecf20Sopenharmony_ci	.show_host_maxframe_size = 1,
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	.get_host_port_id = csio_get_host_port_id,
7758c2ecf20Sopenharmony_ci	.show_host_port_id = 1,
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	.get_host_port_type = csio_get_host_port_type,
7788c2ecf20Sopenharmony_ci	.show_host_port_type = 1,
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	.get_host_port_state = csio_get_host_port_state,
7818c2ecf20Sopenharmony_ci	.show_host_port_state = 1,
7828c2ecf20Sopenharmony_ci	.show_host_active_fc4s = 1,
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	.get_host_speed = csio_get_host_speed,
7858c2ecf20Sopenharmony_ci	.show_host_speed = 1,
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	.get_host_fabric_name = csio_get_host_fabric_name,
7888c2ecf20Sopenharmony_ci	.show_host_fabric_name = 1,
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	.get_fc_host_stats = csio_get_stats,
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	.dd_fcrport_size = sizeof(struct csio_rnode *),
7938c2ecf20Sopenharmony_ci	.show_rport_maxframe_size = 1,
7948c2ecf20Sopenharmony_ci	.show_rport_supported_classes = 1,
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	.set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
7978c2ecf20Sopenharmony_ci	.show_rport_dev_loss_tmo = 1,
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	.show_starget_port_id = 1,
8008c2ecf20Sopenharmony_ci	.show_starget_node_name = 1,
8018c2ecf20Sopenharmony_ci	.show_starget_port_name = 1,
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	.dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci};
806