brintos

brintos / linux-shallow public Read only

0
0
Text · 20.8 KiB · 200e500 Raw
806 lines · c
1/*2 * This file is part of the Chelsio FCoE driver for Linux.3 *4 * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.5 *6 * This software is available to you under a choice of one of two7 * licenses.  You may choose to be licensed under the terms of the GNU8 * General Public License (GPL) Version 2, available from the file9 * COPYING in the main directory of this source tree, or the10 * OpenIB.org BSD license below:11 *12 *     Redistribution and use in source and binary forms, with or13 *     without modification, are permitted provided that the following14 *     conditions are met:15 *16 *      - Redistributions of source code must retain the above17 *        copyright notice, this list of conditions and the following18 *        disclaimer.19 *20 *      - Redistributions in binary form must reproduce the above21 *        copyright notice, this list of conditions and the following22 *        disclaimer in the documentation and/or other materials23 *        provided with the distribution.24 *25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE32 * SOFTWARE.33 */34 35#include <linux/kernel.h>36#include <linux/string.h>37#include <linux/delay.h>38#include <linux/module.h>39#include <linux/init.h>40#include <linux/pci.h>41#include <linux/mm.h>42#include <linux/jiffies.h>43#include <scsi/fc/fc_fs.h>44 45#include "csio_init.h"46 47static void48csio_vport_set_state(struct csio_lnode *ln);49 50/*51 * csio_reg_rnode - Register a remote port with FC transport.52 * @rn: Rnode representing remote port.53 *54 * Call fc_remote_port_add() to register this remote port with FC transport.55 * If remote port is Initiator OR Target OR both, change the role appropriately.56 *57 */58void59csio_reg_rnode(struct csio_rnode *rn)60{61	struct csio_lnode *ln		= csio_rnode_to_lnode(rn);62	struct Scsi_Host *shost		= csio_ln_to_shost(ln);63	struct fc_rport_identifiers ids;64	struct fc_rport  *rport;65	struct csio_service_parms *sp;66 67	ids.node_name	= wwn_to_u64(csio_rn_wwnn(rn));68	ids.port_name	= wwn_to_u64(csio_rn_wwpn(rn));69	ids.port_id	= rn->nport_id;70	ids.roles	= FC_RPORT_ROLE_UNKNOWN;71 72	if (rn->role & CSIO_RNFR_INITIATOR || rn->role & CSIO_RNFR_TARGET) {73		rport = rn->rport;74		CSIO_ASSERT(rport != NULL);75		goto update_role;76	}77 78	rn->rport = fc_remote_port_add(shost, 0, &ids);79	if (!rn->rport) {80		csio_ln_err(ln, "Failed to register rport = 0x%x.\n",81					rn->nport_id);82		return;83	}84 85	ln->num_reg_rnodes++;86	rport = rn->rport;87	spin_lock_irq(shost->host_lock);88	*((struct csio_rnode **)rport->dd_data) = rn;89	spin_unlock_irq(shost->host_lock);90 91	sp = &rn->rn_sparm;92	rport->maxframe_size = ntohs(sp->csp.sp_bb_data);93	if (ntohs(sp->clsp[2].cp_class) & FC_CPC_VALID)94		rport->supported_classes = FC_COS_CLASS3;95	else96		rport->supported_classes = FC_COS_UNSPECIFIED;97update_role:98	if (rn->role & CSIO_RNFR_INITIATOR)99		ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;100	if (rn->role & CSIO_RNFR_TARGET)101		ids.roles |= FC_RPORT_ROLE_FCP_TARGET;102 103	if (ids.roles != FC_RPORT_ROLE_UNKNOWN)104		fc_remote_port_rolechg(rport, ids.roles);105 106	rn->scsi_id = rport->scsi_target_id;107 108	csio_ln_dbg(ln, "Remote port x%x role 0x%x registered\n",109		rn->nport_id, ids.roles);110}111 112/*113 * csio_unreg_rnode - Unregister a remote port with FC transport.114 * @rn: Rnode representing remote port.115 *116 * Call fc_remote_port_delete() to unregister this remote port with FC117 * transport.118 *119 */120void121csio_unreg_rnode(struct csio_rnode *rn)122{123	struct csio_lnode *ln = csio_rnode_to_lnode(rn);124	struct fc_rport *rport = rn->rport;125 126	rn->role &= ~(CSIO_RNFR_INITIATOR | CSIO_RNFR_TARGET);127	fc_remote_port_delete(rport);128	ln->num_reg_rnodes--;129 130	csio_ln_dbg(ln, "Remote port x%x un-registered\n", rn->nport_id);131}132 133/*134 * csio_lnode_async_event - Async events from local port.135 * @ln: lnode representing local port.136 *137 * Async events from local node that FC transport/SCSI ML138 * should be made aware of (Eg: RSCN).139 */140void141csio_lnode_async_event(struct csio_lnode *ln, enum csio_ln_fc_evt fc_evt)142{143	switch (fc_evt) {144	case CSIO_LN_FC_RSCN:145		/* Get payload of rscn from ln */146		/* For each RSCN entry */147			/*148			 * fc_host_post_event(shost,149			 *		      fc_get_event_number(),150			 *		      FCH_EVT_RSCN,151			 *		      rscn_entry);152			 */153		break;154	case CSIO_LN_FC_LINKUP:155		/* send fc_host_post_event */156		/* set vport state */157		if (csio_is_npiv_ln(ln))158			csio_vport_set_state(ln);159 160		break;161	case CSIO_LN_FC_LINKDOWN:162		/* send fc_host_post_event */163		/* set vport state */164		if (csio_is_npiv_ln(ln))165			csio_vport_set_state(ln);166 167		break;168	case CSIO_LN_FC_ATTRIB_UPDATE:169		csio_fchost_attr_init(ln);170		break;171	default:172		break;173	}174}175 176/*177 * csio_fchost_attr_init - Initialize FC transport attributes178 * @ln: Lnode.179 *180 */181void182csio_fchost_attr_init(struct csio_lnode *ln)183{184	struct Scsi_Host  *shost = csio_ln_to_shost(ln);185 186	fc_host_node_name(shost) = wwn_to_u64(csio_ln_wwnn(ln));187	fc_host_port_name(shost) = wwn_to_u64(csio_ln_wwpn(ln));188 189	fc_host_supported_classes(shost) = FC_COS_CLASS3;190	fc_host_max_npiv_vports(shost) =191			(csio_lnode_to_hw(ln))->fres_info.max_vnps;192	fc_host_supported_speeds(shost) = FC_PORTSPEED_10GBIT |193		FC_PORTSPEED_1GBIT;194 195	fc_host_maxframe_size(shost) = ntohs(ln->ln_sparm.csp.sp_bb_data);196	memset(fc_host_supported_fc4s(shost), 0,197		sizeof(fc_host_supported_fc4s(shost)));198	fc_host_supported_fc4s(shost)[7] = 1;199 200	memset(fc_host_active_fc4s(shost), 0,201		sizeof(fc_host_active_fc4s(shost)));202	fc_host_active_fc4s(shost)[7] = 1;203}204 205/*206 * csio_get_host_port_id - sysfs entries for nport_id is207 * populated/cached from this function208 */209static void210csio_get_host_port_id(struct Scsi_Host *shost)211{212	struct csio_lnode *ln	= shost_priv(shost);213	struct csio_hw *hw = csio_lnode_to_hw(ln);214 215	spin_lock_irq(&hw->lock);216	fc_host_port_id(shost) = ln->nport_id;217	spin_unlock_irq(&hw->lock);218}219 220/*221 * csio_get_port_type - Return FC local port type.222 * @shost: scsi host.223 *224 */225static void226csio_get_host_port_type(struct Scsi_Host *shost)227{228	struct csio_lnode *ln = shost_priv(shost);229	struct csio_hw *hw = csio_lnode_to_hw(ln);230 231	spin_lock_irq(&hw->lock);232	if (csio_is_npiv_ln(ln))233		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;234	else235		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;236	spin_unlock_irq(&hw->lock);237}238 239/*240 * csio_get_port_state - Return FC local port state.241 * @shost: scsi host.242 *243 */244static void245csio_get_host_port_state(struct Scsi_Host *shost)246{247	struct csio_lnode *ln = shost_priv(shost);248	struct csio_hw *hw = csio_lnode_to_hw(ln);249	char state[16];250 251	spin_lock_irq(&hw->lock);252 253	csio_lnode_state_to_str(ln, state);254	if (!strcmp(state, "READY"))255		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;256	else if (!strcmp(state, "OFFLINE"))257		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;258	else259		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;260 261	spin_unlock_irq(&hw->lock);262}263 264/*265 * csio_get_host_speed - Return link speed to FC transport.266 * @shost: scsi host.267 *268 */269static void270csio_get_host_speed(struct Scsi_Host *shost)271{272	struct csio_lnode *ln = shost_priv(shost);273	struct csio_hw *hw = csio_lnode_to_hw(ln);274 275	spin_lock_irq(&hw->lock);276	switch (hw->pport[ln->portid].link_speed) {277	case FW_PORT_CAP32_SPEED_1G:278		fc_host_speed(shost) = FC_PORTSPEED_1GBIT;279		break;280	case FW_PORT_CAP32_SPEED_10G:281		fc_host_speed(shost) = FC_PORTSPEED_10GBIT;282		break;283	case FW_PORT_CAP32_SPEED_25G:284		fc_host_speed(shost) = FC_PORTSPEED_25GBIT;285		break;286	case FW_PORT_CAP32_SPEED_40G:287		fc_host_speed(shost) = FC_PORTSPEED_40GBIT;288		break;289	case FW_PORT_CAP32_SPEED_50G:290		fc_host_speed(shost) = FC_PORTSPEED_50GBIT;291		break;292	case FW_PORT_CAP32_SPEED_100G:293		fc_host_speed(shost) = FC_PORTSPEED_100GBIT;294		break;295	default:296		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;297		break;298	}299	spin_unlock_irq(&hw->lock);300}301 302/*303 * csio_get_host_fabric_name - Return fabric name304 * @shost: scsi host.305 *306 */307static void308csio_get_host_fabric_name(struct Scsi_Host *shost)309{310	struct csio_lnode *ln = shost_priv(shost);311	struct csio_rnode *rn = NULL;312	struct csio_hw *hw = csio_lnode_to_hw(ln);313 314	spin_lock_irq(&hw->lock);315	rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI);316	if (rn)317		fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn));318	else319		fc_host_fabric_name(shost) = 0;320	spin_unlock_irq(&hw->lock);321}322 323/*324 * csio_get_host_speed - Return FC transport statistics.325 * @ln: Lnode.326 *327 */328static struct fc_host_statistics *329csio_get_stats(struct Scsi_Host *shost)330{331	struct csio_lnode *ln = shost_priv(shost);332	struct csio_hw *hw = csio_lnode_to_hw(ln);333	struct fc_host_statistics *fhs = &ln->fch_stats;334	struct fw_fcoe_port_stats fcoe_port_stats;335	uint64_t seconds;336 337	memset(&fcoe_port_stats, 0, sizeof(struct fw_fcoe_port_stats));338	csio_get_phy_port_stats(hw, ln->portid, &fcoe_port_stats);339 340	fhs->tx_frames  += (be64_to_cpu(fcoe_port_stats.tx_bcast_frames) +341			    be64_to_cpu(fcoe_port_stats.tx_mcast_frames) +342			    be64_to_cpu(fcoe_port_stats.tx_ucast_frames) +343			    be64_to_cpu(fcoe_port_stats.tx_offload_frames));344	fhs->tx_words  += (be64_to_cpu(fcoe_port_stats.tx_bcast_bytes) +345			   be64_to_cpu(fcoe_port_stats.tx_mcast_bytes) +346			   be64_to_cpu(fcoe_port_stats.tx_ucast_bytes) +347			   be64_to_cpu(fcoe_port_stats.tx_offload_bytes)) /348							CSIO_WORD_TO_BYTE;349	fhs->rx_frames += (be64_to_cpu(fcoe_port_stats.rx_bcast_frames) +350			   be64_to_cpu(fcoe_port_stats.rx_mcast_frames) +351			   be64_to_cpu(fcoe_port_stats.rx_ucast_frames));352	fhs->rx_words += (be64_to_cpu(fcoe_port_stats.rx_bcast_bytes) +353			  be64_to_cpu(fcoe_port_stats.rx_mcast_bytes) +354			  be64_to_cpu(fcoe_port_stats.rx_ucast_bytes)) /355							CSIO_WORD_TO_BYTE;356	fhs->error_frames += be64_to_cpu(fcoe_port_stats.rx_err_frames);357	fhs->fcp_input_requests +=  ln->stats.n_input_requests;358	fhs->fcp_output_requests +=  ln->stats.n_output_requests;359	fhs->fcp_control_requests +=  ln->stats.n_control_requests;360	fhs->fcp_input_megabytes +=  ln->stats.n_input_bytes >> 20;361	fhs->fcp_output_megabytes +=  ln->stats.n_output_bytes >> 20;362	fhs->link_failure_count = ln->stats.n_link_down;363	/* Reset stats for the device */364	seconds = jiffies_to_msecs(jiffies) - hw->stats.n_reset_start;365	do_div(seconds, 1000);366	fhs->seconds_since_last_reset = seconds;367 368	return fhs;369}370 371/*372 * csio_set_rport_loss_tmo - Set the rport dev loss timeout373 * @rport: fc rport.374 * @timeout: new value for dev loss tmo.375 *376 * If timeout is non zero set the dev_loss_tmo to timeout, else set377 * dev_loss_tmo to one.378 */379static void380csio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)381{382	if (timeout)383		rport->dev_loss_tmo = timeout;384	else385		rport->dev_loss_tmo = 1;386}387 388static void389csio_vport_set_state(struct csio_lnode *ln)390{391	struct fc_vport *fc_vport = ln->fc_vport;392	struct csio_lnode  *pln = ln->pln;393	char state[16];394 395	/* Set fc vport state based on phyiscal lnode */396	csio_lnode_state_to_str(pln, state);397	if (strcmp(state, "READY")) {398		fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);399		return;400	}401 402	if (!(pln->flags & CSIO_LNF_NPIVSUPP)) {403		fc_vport_set_state(fc_vport, FC_VPORT_NO_FABRIC_SUPP);404		return;405	}406 407	/* Set fc vport state based on virtual lnode */408	csio_lnode_state_to_str(ln, state);409	if (strcmp(state, "READY")) {410		fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);411		return;412	}413	fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);414}415 416static int417csio_fcoe_alloc_vnp(struct csio_hw *hw, struct csio_lnode *ln)418{419	struct csio_lnode *pln;420	struct csio_mb  *mbp;421	struct fw_fcoe_vnp_cmd *rsp;422	int ret = 0;423	int retry = 0;424 425	/* Issue VNP cmd to alloc vport */426	/* Allocate Mbox request */427	spin_lock_irq(&hw->lock);428	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);429	if (!mbp) {430		CSIO_INC_STATS(hw, n_err_nomem);431		ret = -ENOMEM;432		goto out;433	}434 435	pln = ln->pln;436	ln->fcf_flowid = pln->fcf_flowid;437	ln->portid = pln->portid;438 439	csio_fcoe_vnp_alloc_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,440				    pln->fcf_flowid, pln->vnp_flowid, 0,441				    csio_ln_wwnn(ln), csio_ln_wwpn(ln), NULL);442 443	for (retry = 0; retry < 3; retry++) {444		/* FW is expected to complete vnp cmd in immediate mode445		 * without much delay.446		 * Otherwise, there will be increase in IO latency since HW447		 * lock is held till completion of vnp mbox cmd.448		 */449		ret = csio_mb_issue(hw, mbp);450		if (ret != -EBUSY)451			break;452 453		/* Retry if mbox returns busy */454		spin_unlock_irq(&hw->lock);455		msleep(2000);456		spin_lock_irq(&hw->lock);457	}458 459	if (ret) {460		csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");461		goto out_free;462	}463 464	/* Process Mbox response of VNP command */465	rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);466	if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {467		csio_ln_err(ln, "FCOE VNP ALLOC cmd returned 0x%x!\n",468			    FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));469		ret = -EINVAL;470		goto out_free;471	}472 473	ln->vnp_flowid = FW_FCOE_VNP_CMD_VNPI_GET(474				ntohl(rsp->gen_wwn_to_vnpi));475	memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);476	memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);477 478	csio_ln_dbg(ln, "FCOE VNPI: 0x%x\n", ln->vnp_flowid);479	csio_ln_dbg(ln, "\tWWNN: %x%x%x%x%x%x%x%x\n",480		    ln->ln_sparm.wwnn[0], ln->ln_sparm.wwnn[1],481		    ln->ln_sparm.wwnn[2], ln->ln_sparm.wwnn[3],482		    ln->ln_sparm.wwnn[4], ln->ln_sparm.wwnn[5],483		    ln->ln_sparm.wwnn[6], ln->ln_sparm.wwnn[7]);484	csio_ln_dbg(ln, "\tWWPN: %x%x%x%x%x%x%x%x\n",485		    ln->ln_sparm.wwpn[0], ln->ln_sparm.wwpn[1],486		    ln->ln_sparm.wwpn[2], ln->ln_sparm.wwpn[3],487		    ln->ln_sparm.wwpn[4], ln->ln_sparm.wwpn[5],488		    ln->ln_sparm.wwpn[6], ln->ln_sparm.wwpn[7]);489 490out_free:491	mempool_free(mbp, hw->mb_mempool);492out:493	spin_unlock_irq(&hw->lock);494	return ret;495}496 497static int498csio_fcoe_free_vnp(struct csio_hw *hw, struct csio_lnode *ln)499{500	struct csio_mb  *mbp;501	struct fw_fcoe_vnp_cmd *rsp;502	int ret = 0;503	int retry = 0;504 505	/* Issue VNP cmd to free vport */506	/* Allocate Mbox request */507 508	spin_lock_irq(&hw->lock);509	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);510	if (!mbp) {511		CSIO_INC_STATS(hw, n_err_nomem);512		ret = -ENOMEM;513		goto out;514	}515 516	csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,517				   ln->fcf_flowid, ln->vnp_flowid,518				   NULL);519 520	for (retry = 0; retry < 3; retry++) {521		ret = csio_mb_issue(hw, mbp);522		if (ret != -EBUSY)523			break;524 525		/* Retry if mbox returns busy */526		spin_unlock_irq(&hw->lock);527		msleep(2000);528		spin_lock_irq(&hw->lock);529	}530 531	if (ret) {532		csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");533		goto out_free;534	}535 536	/* Process Mbox response of VNP command */537	rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);538	if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {539		csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n",540			    FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));541		ret = -EINVAL;542	}543 544out_free:545	mempool_free(mbp, hw->mb_mempool);546out:547	spin_unlock_irq(&hw->lock);548	return ret;549}550 551static int552csio_vport_create(struct fc_vport *fc_vport, bool disable)553{554	struct Scsi_Host *shost = fc_vport->shost;555	struct csio_lnode *pln = shost_priv(shost);556	struct csio_lnode *ln = NULL;557	struct csio_hw *hw = csio_lnode_to_hw(pln);558	uint8_t wwn[8];559	int ret = -1;560 561	ln = csio_shost_init(hw, &fc_vport->dev, false, pln);562	if (!ln)563		goto error;564 565	if (fc_vport->node_name != 0) {566		u64_to_wwn(fc_vport->node_name, wwn);567 568		if (!CSIO_VALID_WWN(wwn)) {569			csio_ln_err(ln,570				    "vport create failed. Invalid wwnn\n");571			goto error;572		}573		memcpy(csio_ln_wwnn(ln), wwn, 8);574	}575 576	if (fc_vport->port_name != 0) {577		u64_to_wwn(fc_vport->port_name, wwn);578 579		if (!CSIO_VALID_WWN(wwn)) {580			csio_ln_err(ln,581				    "vport create failed. Invalid wwpn\n");582			goto error;583		}584 585		if (csio_lnode_lookup_by_wwpn(hw, wwn)) {586			csio_ln_err(ln,587			    "vport create failed. wwpn already exists\n");588			goto error;589		}590		memcpy(csio_ln_wwpn(ln), wwn, 8);591	}592 593	fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);594	ln->fc_vport = fc_vport;595 596	if (csio_fcoe_alloc_vnp(hw, ln))597		goto error;598 599	*(struct csio_lnode **)fc_vport->dd_data = ln;600	if (!fc_vport->node_name)601		fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));602	if (!fc_vport->port_name)603		fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln));604	csio_fchost_attr_init(ln);605	return 0;606error:607	if (ln)608		csio_shost_exit(ln);609 610	return ret;611}612 613static int614csio_vport_delete(struct fc_vport *fc_vport)615{616	struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;617	struct Scsi_Host *shost = csio_ln_to_shost(ln);618	struct csio_hw *hw = csio_lnode_to_hw(ln);619	int rmv;620 621	spin_lock_irq(&hw->lock);622	rmv = csio_is_hw_removing(hw);623	spin_unlock_irq(&hw->lock);624 625	if (rmv) {626		csio_shost_exit(ln);627		return 0;628	}629 630	/* Quiesce ios and send remove event to lnode */631	scsi_block_requests(shost);632	spin_lock_irq(&hw->lock);633	csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);634	csio_lnode_close(ln);635	spin_unlock_irq(&hw->lock);636	scsi_unblock_requests(shost);637 638	/* Free vnp */639	if (fc_vport->vport_state !=  FC_VPORT_DISABLED)640		csio_fcoe_free_vnp(hw, ln);641 642	csio_shost_exit(ln);643	return 0;644}645 646static int647csio_vport_disable(struct fc_vport *fc_vport, bool disable)648{649	struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;650	struct Scsi_Host *shost = csio_ln_to_shost(ln);651	struct csio_hw *hw = csio_lnode_to_hw(ln);652 653	/* disable vport */654	if (disable) {655		/* Quiesce ios and send stop event to lnode */656		scsi_block_requests(shost);657		spin_lock_irq(&hw->lock);658		csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);659		csio_lnode_stop(ln);660		spin_unlock_irq(&hw->lock);661		scsi_unblock_requests(shost);662 663		/* Free vnp */664		csio_fcoe_free_vnp(hw, ln);665		fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);666		csio_ln_err(ln, "vport disabled\n");667		return 0;668	} else {669		/* enable vport */670		fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);671		if (csio_fcoe_alloc_vnp(hw, ln)) {672			csio_ln_err(ln, "vport enabled failed.\n");673			return -1;674		}675		csio_ln_err(ln, "vport enabled\n");676		return 0;677	}678}679 680static void681csio_dev_loss_tmo_callbk(struct fc_rport *rport)682{683	struct csio_rnode *rn;684	struct csio_hw *hw;685	struct csio_lnode *ln;686 687	rn = *((struct csio_rnode **)rport->dd_data);688	ln = csio_rnode_to_lnode(rn);689	hw = csio_lnode_to_hw(ln);690 691	spin_lock_irq(&hw->lock);692 693	/* return if driver is being removed or same rnode comes back online */694	if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn))695		goto out;696 697	csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n",698		    rn, rn->nport_id, csio_rn_flowid(rn));699 700	CSIO_INC_STATS(ln, n_dev_loss_tmo);701 702	/*703	 * enqueue devloss event to event worker thread to serialize all704	 * rnode events.705	 */706	if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) {707		CSIO_INC_STATS(hw, n_evt_drop);708		goto out;709	}710 711	if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) {712		hw->flags |= CSIO_HWF_FWEVT_PENDING;713		spin_unlock_irq(&hw->lock);714		schedule_work(&hw->evtq_work);715		return;716	}717 718out:719	spin_unlock_irq(&hw->lock);720}721 722/* FC transport functions template - Physical port */723struct fc_function_template csio_fc_transport_funcs = {724	.show_host_node_name = 1,725	.show_host_port_name = 1,726	.show_host_supported_classes = 1,727	.show_host_supported_fc4s = 1,728	.show_host_maxframe_size = 1,729 730	.get_host_port_id = csio_get_host_port_id,731	.show_host_port_id = 1,732 733	.get_host_port_type = csio_get_host_port_type,734	.show_host_port_type = 1,735 736	.get_host_port_state = csio_get_host_port_state,737	.show_host_port_state = 1,738 739	.show_host_active_fc4s = 1,740	.get_host_speed = csio_get_host_speed,741	.show_host_speed = 1,742	.get_host_fabric_name = csio_get_host_fabric_name,743	.show_host_fabric_name = 1,744 745	.get_fc_host_stats = csio_get_stats,746 747	.dd_fcrport_size = sizeof(struct csio_rnode *),748	.show_rport_maxframe_size = 1,749	.show_rport_supported_classes = 1,750 751	.set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,752	.show_rport_dev_loss_tmo = 1,753 754	.show_starget_port_id = 1,755	.show_starget_node_name = 1,756	.show_starget_port_name = 1,757 758	.dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,759	.dd_fcvport_size = sizeof(struct csio_lnode *),760 761	.vport_create = csio_vport_create,762	.vport_disable = csio_vport_disable,763	.vport_delete = csio_vport_delete,764};765 766/* FC transport functions template - Virtual  port */767struct fc_function_template csio_fc_transport_vport_funcs = {768	.show_host_node_name = 1,769	.show_host_port_name = 1,770	.show_host_supported_classes = 1,771	.show_host_supported_fc4s = 1,772	.show_host_maxframe_size = 1,773 774	.get_host_port_id = csio_get_host_port_id,775	.show_host_port_id = 1,776 777	.get_host_port_type = csio_get_host_port_type,778	.show_host_port_type = 1,779 780	.get_host_port_state = csio_get_host_port_state,781	.show_host_port_state = 1,782	.show_host_active_fc4s = 1,783 784	.get_host_speed = csio_get_host_speed,785	.show_host_speed = 1,786 787	.get_host_fabric_name = csio_get_host_fabric_name,788	.show_host_fabric_name = 1,789 790	.get_fc_host_stats = csio_get_stats,791 792	.dd_fcrport_size = sizeof(struct csio_rnode *),793	.show_rport_maxframe_size = 1,794	.show_rport_supported_classes = 1,795 796	.set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,797	.show_rport_dev_loss_tmo = 1,798 799	.show_starget_port_id = 1,800	.show_starget_node_name = 1,801	.show_starget_port_name = 1,802 803	.dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,804 805};806