brintos

brintos / linux-shallow public Read only

0
0
Text · 128.7 KiB · 082f76e Raw
4355 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  FiberChannel transport specific attributes exported to sysfs.4 *5 *  Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.6 *  Copyright (C) 2004-2007   James Smart, Emulex Corporation7 *    Rewrite for host, target, device, and remote port attributes,8 *    statistics, and service functions...9 *    Add vports, etc10 */11#include <linux/module.h>12#include <linux/init.h>13#include <linux/slab.h>14#include <linux/delay.h>15#include <linux/kernel.h>16#include <linux/bsg-lib.h>17#include <scsi/scsi_device.h>18#include <scsi/scsi_host.h>19#include <scsi/scsi_transport.h>20#include <scsi/scsi_transport_fc.h>21#include <scsi/scsi_cmnd.h>22#include <net/netlink.h>23#include <scsi/scsi_netlink_fc.h>24#include <scsi/scsi_bsg_fc.h>25#include <uapi/scsi/fc/fc_els.h>26#include "scsi_priv.h"27 28static int fc_queue_work(struct Scsi_Host *, struct work_struct *);29static void fc_vport_sched_delete(struct work_struct *work);30static int fc_vport_setup(struct Scsi_Host *shost, int channel,31	struct device *pdev, struct fc_vport_identifiers  *ids,32	struct fc_vport **vport);33static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *);34static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *);35static void fc_bsg_remove(struct request_queue *);36static void fc_bsg_goose_queue(struct fc_rport *);37static void fc_li_stats_update(u16 event_type,38			       struct fc_fpin_stats *stats);39static void fc_delivery_stats_update(u32 reason_code,40				     struct fc_fpin_stats *stats);41static void fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats);42 43/*44 * Module Parameters45 */46 47/*48 * dev_loss_tmo: the default number of seconds that the FC transport49 *   should insulate the loss of a remote port.50 *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.51 */52static unsigned int fc_dev_loss_tmo = 60;		/* seconds */53 54module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);55MODULE_PARM_DESC(dev_loss_tmo,56		 "Maximum number of seconds that the FC transport should"57		 " insulate the loss of a remote port. Once this value is"58		 " exceeded, the scsi target is removed. Value should be"59		 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if"60		 " fast_io_fail_tmo is not set.");61 62/*63 * Redefine so that we can have same named attributes in the64 * sdev/starget/host objects.65 */66#define FC_DEVICE_ATTR(_prefix,_name,_mode,_show,_store)		\67struct device_attribute device_attr_##_prefix##_##_name = 	\68	__ATTR(_name,_mode,_show,_store)69 70#define fc_enum_name_search(title, table_type, table)			\71static const char *get_fc_##title##_name(enum table_type table_key)	\72{									\73	int i;								\74	char *name = NULL;						\75									\76	for (i = 0; i < ARRAY_SIZE(table); i++) {			\77		if (table[i].value == table_key) {			\78			name = table[i].name;				\79			break;						\80		}							\81	}								\82	return name;							\83}84 85#define fc_enum_name_match(title, table_type, table)			\86static int get_fc_##title##_match(const char *table_key,		\87		enum table_type *value)					\88{									\89	int i;								\90									\91	for (i = 0; i < ARRAY_SIZE(table); i++) {			\92		if (strncmp(table_key, table[i].name,			\93				table[i].matchlen) == 0) {		\94			*value = table[i].value;			\95			return 0; /* success */				\96		}							\97	}								\98	return 1; /* failure */						\99}100 101 102/* Convert fc_port_type values to ascii string name */103static struct {104	enum fc_port_type	value;105	char			*name;106} fc_port_type_names[] = {107	{ FC_PORTTYPE_UNKNOWN,		"Unknown" },108	{ FC_PORTTYPE_OTHER,		"Other" },109	{ FC_PORTTYPE_NOTPRESENT,	"Not Present" },110	{ FC_PORTTYPE_NPORT,	"NPort (fabric via point-to-point)" },111	{ FC_PORTTYPE_NLPORT,	"NLPort (fabric via loop)" },112	{ FC_PORTTYPE_LPORT,	"LPort (private loop)" },113	{ FC_PORTTYPE_PTP,	"Point-To-Point (direct nport connection)" },114	{ FC_PORTTYPE_NPIV,		"NPIV VPORT" },115};116fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)117#define FC_PORTTYPE_MAX_NAMELEN		50118 119/* Reuse fc_port_type enum function for vport_type */120#define get_fc_vport_type_name get_fc_port_type_name121 122 123/* Convert fc_host_event_code values to ascii string name */124static const struct {125	enum fc_host_event_code		value;126	char				*name;127} fc_host_event_code_names[] = {128	{ FCH_EVT_LIP,			"lip" },129	{ FCH_EVT_LINKUP,		"link_up" },130	{ FCH_EVT_LINKDOWN,		"link_down" },131	{ FCH_EVT_LIPRESET,		"lip_reset" },132	{ FCH_EVT_RSCN,			"rscn" },133	{ FCH_EVT_ADAPTER_CHANGE,	"adapter_chg" },134	{ FCH_EVT_PORT_UNKNOWN,		"port_unknown" },135	{ FCH_EVT_PORT_ONLINE,		"port_online" },136	{ FCH_EVT_PORT_OFFLINE,		"port_offline" },137	{ FCH_EVT_PORT_FABRIC,		"port_fabric" },138	{ FCH_EVT_LINK_UNKNOWN,		"link_unknown" },139	{ FCH_EVT_LINK_FPIN,		"link_FPIN" },140	{ FCH_EVT_LINK_FPIN_ACK,	"link_FPIN_ACK" },141	{ FCH_EVT_VENDOR_UNIQUE,	"vendor_unique" },142};143fc_enum_name_search(host_event_code, fc_host_event_code,144		fc_host_event_code_names)145#define FC_HOST_EVENT_CODE_MAX_NAMELEN	30146 147 148/* Convert fc_port_state values to ascii string name */149static struct {150	enum fc_port_state	value;151	char			*name;152	int			matchlen;153} fc_port_state_names[] = {154	{ FC_PORTSTATE_UNKNOWN,		"Unknown", 7},155	{ FC_PORTSTATE_NOTPRESENT,	"Not Present", 11 },156	{ FC_PORTSTATE_ONLINE,		"Online", 6 },157	{ FC_PORTSTATE_OFFLINE,		"Offline", 7 },158	{ FC_PORTSTATE_BLOCKED,		"Blocked", 7 },159	{ FC_PORTSTATE_BYPASSED,	"Bypassed", 8 },160	{ FC_PORTSTATE_DIAGNOSTICS,	"Diagnostics", 11 },161	{ FC_PORTSTATE_LINKDOWN,	"Linkdown", 8 },162	{ FC_PORTSTATE_ERROR,		"Error", 5 },163	{ FC_PORTSTATE_LOOPBACK,	"Loopback", 8 },164	{ FC_PORTSTATE_DELETED,		"Deleted", 7 },165	{ FC_PORTSTATE_MARGINAL,	"Marginal", 8 },166};167fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)168fc_enum_name_match(port_state, fc_port_state, fc_port_state_names)169#define FC_PORTSTATE_MAX_NAMELEN	20170 171 172/* Convert fc_vport_state values to ascii string name */173static struct {174	enum fc_vport_state	value;175	char			*name;176} fc_vport_state_names[] = {177	{ FC_VPORT_UNKNOWN,		"Unknown" },178	{ FC_VPORT_ACTIVE,		"Active" },179	{ FC_VPORT_DISABLED,		"Disabled" },180	{ FC_VPORT_LINKDOWN,		"Linkdown" },181	{ FC_VPORT_INITIALIZING,	"Initializing" },182	{ FC_VPORT_NO_FABRIC_SUPP,	"No Fabric Support" },183	{ FC_VPORT_NO_FABRIC_RSCS,	"No Fabric Resources" },184	{ FC_VPORT_FABRIC_LOGOUT,	"Fabric Logout" },185	{ FC_VPORT_FABRIC_REJ_WWN,	"Fabric Rejected WWN" },186	{ FC_VPORT_FAILED,		"VPort Failed" },187};188fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names)189#define FC_VPORTSTATE_MAX_NAMELEN	24190 191/* Reuse fc_vport_state enum function for vport_last_state */192#define get_fc_vport_last_state_name get_fc_vport_state_name193 194 195/* Convert fc_tgtid_binding_type values to ascii string name */196static const struct {197	enum fc_tgtid_binding_type	value;198	char				*name;199	int				matchlen;200} fc_tgtid_binding_type_names[] = {201	{ FC_TGTID_BIND_NONE, "none", 4 },202	{ FC_TGTID_BIND_BY_WWPN, "wwpn (World Wide Port Name)", 4 },203	{ FC_TGTID_BIND_BY_WWNN, "wwnn (World Wide Node Name)", 4 },204	{ FC_TGTID_BIND_BY_ID, "port_id (FC Address)", 7 },205};206fc_enum_name_search(tgtid_bind_type, fc_tgtid_binding_type,207		fc_tgtid_binding_type_names)208fc_enum_name_match(tgtid_bind_type, fc_tgtid_binding_type,209		fc_tgtid_binding_type_names)210#define FC_BINDTYPE_MAX_NAMELEN	30211 212 213#define fc_bitfield_name_search(title, table)			\214static ssize_t							\215get_fc_##title##_names(u32 table_key, char *buf)		\216{								\217	char *prefix = "";					\218	ssize_t len = 0;					\219	int i;							\220								\221	for (i = 0; i < ARRAY_SIZE(table); i++) {		\222		if (table[i].value & table_key) {		\223			len += sprintf(buf + len, "%s%s",	\224				prefix, table[i].name);		\225			prefix = ", ";				\226		}						\227	}							\228	len += sprintf(buf + len, "\n");			\229	return len;						\230}231 232 233/* Convert FC_COS bit values to ascii string name */234static const struct {235	u32 			value;236	char			*name;237} fc_cos_names[] = {238	{ FC_COS_CLASS1,	"Class 1" },239	{ FC_COS_CLASS2,	"Class 2" },240	{ FC_COS_CLASS3,	"Class 3" },241	{ FC_COS_CLASS4,	"Class 4" },242	{ FC_COS_CLASS6,	"Class 6" },243};244fc_bitfield_name_search(cos, fc_cos_names)245 246 247/* Convert FC_PORTSPEED bit values to ascii string name */248static const struct {249	u32 			value;250	char			*name;251} fc_port_speed_names[] = {252	{ FC_PORTSPEED_1GBIT,		"1 Gbit" },253	{ FC_PORTSPEED_2GBIT,		"2 Gbit" },254	{ FC_PORTSPEED_4GBIT,		"4 Gbit" },255	{ FC_PORTSPEED_10GBIT,		"10 Gbit" },256	{ FC_PORTSPEED_8GBIT,		"8 Gbit" },257	{ FC_PORTSPEED_16GBIT,		"16 Gbit" },258	{ FC_PORTSPEED_32GBIT,		"32 Gbit" },259	{ FC_PORTSPEED_20GBIT,		"20 Gbit" },260	{ FC_PORTSPEED_40GBIT,		"40 Gbit" },261	{ FC_PORTSPEED_50GBIT,		"50 Gbit" },262	{ FC_PORTSPEED_100GBIT,		"100 Gbit" },263	{ FC_PORTSPEED_25GBIT,		"25 Gbit" },264	{ FC_PORTSPEED_64GBIT,		"64 Gbit" },265	{ FC_PORTSPEED_128GBIT,		"128 Gbit" },266	{ FC_PORTSPEED_256GBIT,		"256 Gbit" },267	{ FC_PORTSPEED_NOT_NEGOTIATED,	"Not Negotiated" },268};269fc_bitfield_name_search(port_speed, fc_port_speed_names)270 271 272static int273show_fc_fc4s (char *buf, u8 *fc4_list)274{275	int i, len=0;276 277	for (i = 0; i < FC_FC4_LIST_SIZE; i++, fc4_list++)278		len += sprintf(buf + len , "0x%02x ", *fc4_list);279	len += sprintf(buf + len, "\n");280	return len;281}282 283 284/* Convert FC_PORT_ROLE bit values to ascii string name */285static const struct {286	u32 			value;287	char			*name;288} fc_port_role_names[] = {289	{ FC_PORT_ROLE_FCP_TARGET,		"FCP Target" },290	{ FC_PORT_ROLE_FCP_INITIATOR,		"FCP Initiator" },291	{ FC_PORT_ROLE_IP_PORT,			"IP Port" },292	{ FC_PORT_ROLE_FCP_DUMMY_INITIATOR,	"FCP Dummy Initiator" },293	{ FC_PORT_ROLE_NVME_INITIATOR,		"NVMe Initiator" },294	{ FC_PORT_ROLE_NVME_TARGET,		"NVMe Target" },295	{ FC_PORT_ROLE_NVME_DISCOVERY,		"NVMe Discovery" },296};297fc_bitfield_name_search(port_roles, fc_port_role_names)298 299/*300 * Define roles that are specific to port_id. Values are relative to ROLE_MASK.301 */302#define FC_WELLKNOWN_PORTID_MASK	0xfffff0303#define FC_WELLKNOWN_ROLE_MASK  	0x00000f304#define FC_FPORT_PORTID			0x00000e305#define FC_FABCTLR_PORTID		0x00000d306#define FC_DIRSRVR_PORTID		0x00000c307#define FC_TIMESRVR_PORTID		0x00000b308#define FC_MGMTSRVR_PORTID		0x00000a309 310 311static void fc_timeout_deleted_rport(struct work_struct *work);312static void fc_timeout_fail_rport_io(struct work_struct *work);313static void fc_scsi_scan_rport(struct work_struct *work);314 315/*316 * Attribute counts pre object type...317 * Increase these values if you add attributes318 */319#define FC_STARGET_NUM_ATTRS 	3320#define FC_RPORT_NUM_ATTRS	10321#define FC_VPORT_NUM_ATTRS	9322#define FC_HOST_NUM_ATTRS	29323 324struct fc_internal {325	struct scsi_transport_template t;326	struct fc_function_template *f;327 328	/*329	 * For attributes : each object has :330	 *   An array of the actual attributes structures331	 *   An array of null-terminated pointers to the attribute332	 *     structures - used for mid-layer interaction.333	 *334	 * The attribute containers for the starget and host are are335	 * part of the midlayer. As the remote port is specific to the336	 * fc transport, we must provide the attribute container.337	 */338	struct device_attribute private_starget_attrs[339							FC_STARGET_NUM_ATTRS];340	struct device_attribute *starget_attrs[FC_STARGET_NUM_ATTRS + 1];341 342	struct device_attribute private_host_attrs[FC_HOST_NUM_ATTRS];343	struct device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1];344 345	struct transport_container rport_attr_cont;346	struct device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];347	struct device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];348 349	struct transport_container vport_attr_cont;350	struct device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];351	struct device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];352};353 354#define to_fc_internal(tmpl)	container_of(tmpl, struct fc_internal, t)355 356static int fc_target_setup(struct transport_container *tc, struct device *dev,357			   struct device *cdev)358{359	struct scsi_target *starget = to_scsi_target(dev);360	struct fc_rport *rport = starget_to_rport(starget);361 362	/*363	 * if parent is remote port, use values from remote port.364	 * Otherwise, this host uses the fc_transport, but not the365	 * remote port interface. As such, initialize to known non-values.366	 */367	if (rport) {368		fc_starget_node_name(starget) = rport->node_name;369		fc_starget_port_name(starget) = rport->port_name;370		fc_starget_port_id(starget) = rport->port_id;371	} else {372		fc_starget_node_name(starget) = -1;373		fc_starget_port_name(starget) = -1;374		fc_starget_port_id(starget) = -1;375	}376 377	return 0;378}379 380static DECLARE_TRANSPORT_CLASS(fc_transport_class,381			       "fc_transport",382			       fc_target_setup,383			       NULL,384			       NULL);385 386static int fc_host_setup(struct transport_container *tc, struct device *dev,387			 struct device *cdev)388{389	struct Scsi_Host *shost = dev_to_shost(dev);390	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);391 392	/*393	 * Set default values easily detected by the midlayer as394	 * failure cases.  The scsi lldd is responsible for initializing395	 * all transport attributes to valid values per host.396	 */397	fc_host->node_name = -1;398	fc_host->port_name = -1;399	fc_host->permanent_port_name = -1;400	fc_host->supported_classes = FC_COS_UNSPECIFIED;401	memset(fc_host->supported_fc4s, 0,402		sizeof(fc_host->supported_fc4s));403	fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;404	fc_host->maxframe_size = -1;405	fc_host->max_npiv_vports = 0;406	memset(fc_host->serial_number, 0,407		sizeof(fc_host->serial_number));408	memset(fc_host->manufacturer, 0,409		sizeof(fc_host->manufacturer));410	memset(fc_host->model, 0,411		sizeof(fc_host->model));412	memset(fc_host->model_description, 0,413		sizeof(fc_host->model_description));414	memset(fc_host->hardware_version, 0,415		sizeof(fc_host->hardware_version));416	memset(fc_host->driver_version, 0,417		sizeof(fc_host->driver_version));418	memset(fc_host->firmware_version, 0,419		sizeof(fc_host->firmware_version));420	memset(fc_host->optionrom_version, 0,421		sizeof(fc_host->optionrom_version));422 423	fc_host->port_id = -1;424	fc_host->port_type = FC_PORTTYPE_UNKNOWN;425	fc_host->port_state = FC_PORTSTATE_UNKNOWN;426	memset(fc_host->active_fc4s, 0,427		sizeof(fc_host->active_fc4s));428	fc_host->speed = FC_PORTSPEED_UNKNOWN;429	fc_host->fabric_name = -1;430	memset(fc_host->symbolic_name, 0, sizeof(fc_host->symbolic_name));431	memset(fc_host->system_hostname, 0, sizeof(fc_host->system_hostname));432	memset(&fc_host->fpin_stats, 0, sizeof(fc_host->fpin_stats));433 434	fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN;435 436	INIT_LIST_HEAD(&fc_host->rports);437	INIT_LIST_HEAD(&fc_host->rport_bindings);438	INIT_LIST_HEAD(&fc_host->vports);439	fc_host->next_rport_number = 0;440	fc_host->next_target_id = 0;441	fc_host->next_vport_number = 0;442	fc_host->npiv_vports_inuse = 0;443 444	fc_host->work_q = alloc_workqueue("fc_wq_%d", 0, 0, shost->host_no);445	if (!fc_host->work_q)446		return -ENOMEM;447 448	fc_host->dev_loss_tmo = fc_dev_loss_tmo;449	fc_host->devloss_work_q = alloc_workqueue("fc_dl_%d", 0, 0,450					shost->host_no);451	if (!fc_host->devloss_work_q) {452		destroy_workqueue(fc_host->work_q);453		fc_host->work_q = NULL;454		return -ENOMEM;455	}456 457	fc_bsg_hostadd(shost, fc_host);458	/* ignore any bsg add error - we just can't do sgio */459 460	return 0;461}462 463static int fc_host_remove(struct transport_container *tc, struct device *dev,464			 struct device *cdev)465{466	struct Scsi_Host *shost = dev_to_shost(dev);467	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);468 469	fc_bsg_remove(fc_host->rqst_q);470	return 0;471}472 473static DECLARE_TRANSPORT_CLASS(fc_host_class,474			       "fc_host",475			       fc_host_setup,476			       fc_host_remove,477			       NULL);478 479/*480 * Setup and Remove actions for remote ports are handled481 * in the service functions below.482 */483static DECLARE_TRANSPORT_CLASS(fc_rport_class,484			       "fc_remote_ports",485			       NULL,486			       NULL,487			       NULL);488 489/*490 * Setup and Remove actions for virtual ports are handled491 * in the service functions below.492 */493static DECLARE_TRANSPORT_CLASS(fc_vport_class,494			       "fc_vports",495			       NULL,496			       NULL,497			       NULL);498 499/*500 * Netlink Infrastructure501 */502 503static atomic_t fc_event_seq;504 505/**506 * fc_get_event_number - Obtain the next sequential FC event number507 *508 * Notes:509 *   We could have inlined this, but it would have required fc_event_seq to510 *   be exposed. For now, live with the subroutine call.511 *   Atomic used to avoid lock/unlock...512 */513u32514fc_get_event_number(void)515{516	return atomic_add_return(1, &fc_event_seq);517}518EXPORT_SYMBOL(fc_get_event_number);519 520/**521 * fc_host_post_fc_event - routine to do the work of posting an event522 *                      on an fc_host.523 * @shost:		host the event occurred on524 * @event_number:	fc event number obtained from get_fc_event_number()525 * @event_code:		fc_host event being posted526 * @data_len:		amount, in bytes, of event data527 * @data_buf:		pointer to event data528 * @vendor_id:          value for Vendor id529 *530 * Notes:531 *	This routine assumes no locks are held on entry.532 */533void534fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number,535		enum fc_host_event_code event_code,536		u32 data_len, char *data_buf, u64 vendor_id)537{538	struct sk_buff *skb;539	struct nlmsghdr	*nlh;540	struct fc_nl_event *event;541	const char *name;542	size_t len, padding;543	int err;544 545	if (!data_buf || data_len < 4)546		data_len = 0;547 548	if (!scsi_nl_sock) {549		err = -ENOENT;550		goto send_fail;551	}552 553	len = FC_NL_MSGALIGN(sizeof(*event) - sizeof(event->event_data) + data_len);554 555	skb = nlmsg_new(len, GFP_KERNEL);556	if (!skb) {557		err = -ENOBUFS;558		goto send_fail;559	}560 561	nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, len, 0);562	if (!nlh) {563		err = -ENOBUFS;564		goto send_fail_skb;565	}566	event = nlmsg_data(nlh);567 568	INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,569				FC_NL_ASYNC_EVENT, len);570	event->seconds = ktime_get_real_seconds();571	event->vendor_id = vendor_id;572	event->host_no = shost->host_no;573	event->event_datalen = data_len;	/* bytes */574	event->event_num = event_number;575	event->event_code = event_code;576	if (data_len)577		memcpy(event->event_data_flex, data_buf, data_len);578	padding = len - offsetof(typeof(*event), event_data_flex) - data_len;579	memset(event->event_data_flex + data_len, 0, padding);580 581	nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,582			GFP_KERNEL);583	return;584 585send_fail_skb:586	kfree_skb(skb);587send_fail:588	name = get_fc_host_event_code_name(event_code);589	printk(KERN_WARNING590		"%s: Dropped Event : host %d %s data 0x%08x - err %d\n",591		__func__, shost->host_no,592		(name) ? name : "<unknown>",593		(data_len) ? *((u32 *)data_buf) : 0xFFFFFFFF, err);594	return;595}596EXPORT_SYMBOL(fc_host_post_fc_event);597 598/**599 * fc_host_post_event - called to post an even on an fc_host.600 * @shost:		host the event occurred on601 * @event_number:	fc event number obtained from get_fc_event_number()602 * @event_code:		fc_host event being posted603 * @event_data:		32bits of data for the event being posted604 *605 * Notes:606 *	This routine assumes no locks are held on entry.607 */608void609fc_host_post_event(struct Scsi_Host *shost, u32 event_number,610		enum fc_host_event_code event_code, u32 event_data)611{612	fc_host_post_fc_event(shost, event_number, event_code,613		(u32)sizeof(u32), (char *)&event_data, 0);614}615EXPORT_SYMBOL(fc_host_post_event);616 617 618/**619 * fc_host_post_vendor_event - called to post a vendor unique event620 *                      on an fc_host621 * @shost:		host the event occurred on622 * @event_number:	fc event number obtained from get_fc_event_number()623 * @data_len:		amount, in bytes, of vendor unique data624 * @data_buf:		pointer to vendor unique data625 * @vendor_id:          Vendor id626 *627 * Notes:628 *	This routine assumes no locks are held on entry.629 */630void631fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,632		u32 data_len, char * data_buf, u64 vendor_id)633{634	fc_host_post_fc_event(shost, event_number, FCH_EVT_VENDOR_UNIQUE,635		data_len, data_buf, vendor_id);636}637EXPORT_SYMBOL(fc_host_post_vendor_event);638 639/**640 * fc_find_rport_by_wwpn - find the fc_rport pointer for a given wwpn641 * @shost:		host the fc_rport is associated with642 * @wwpn:		wwpn of the fc_rport device643 *644 * Notes:645 *	This routine assumes no locks are held on entry.646 */647struct fc_rport *648fc_find_rport_by_wwpn(struct Scsi_Host *shost, u64 wwpn)649{650	struct fc_rport *rport;651	unsigned long flags;652 653	spin_lock_irqsave(shost->host_lock, flags);654 655	list_for_each_entry(rport, &fc_host_rports(shost), peers) {656		if (rport->port_state != FC_PORTSTATE_ONLINE)657			continue;658 659		if (rport->port_name == wwpn) {660			spin_unlock_irqrestore(shost->host_lock, flags);661			return rport;662		}663	}664 665	spin_unlock_irqrestore(shost->host_lock, flags);666	return NULL;667}668EXPORT_SYMBOL(fc_find_rport_by_wwpn);669 670static void671fc_li_stats_update(u16 event_type,672		   struct fc_fpin_stats *stats)673{674	stats->li++;675	switch (event_type) {676	case FPIN_LI_UNKNOWN:677		stats->li_failure_unknown++;678		break;679	case FPIN_LI_LINK_FAILURE:680		stats->li_link_failure_count++;681		break;682	case FPIN_LI_LOSS_OF_SYNC:683		stats->li_loss_of_sync_count++;684		break;685	case FPIN_LI_LOSS_OF_SIG:686		stats->li_loss_of_signals_count++;687		break;688	case FPIN_LI_PRIM_SEQ_ERR:689		stats->li_prim_seq_err_count++;690		break;691	case FPIN_LI_INVALID_TX_WD:692		stats->li_invalid_tx_word_count++;693		break;694	case FPIN_LI_INVALID_CRC:695		stats->li_invalid_crc_count++;696		break;697	case FPIN_LI_DEVICE_SPEC:698		stats->li_device_specific++;699		break;700	}701}702 703static void704fc_delivery_stats_update(u32 reason_code, struct fc_fpin_stats *stats)705{706	stats->dn++;707	switch (reason_code) {708	case FPIN_DELI_UNKNOWN:709		stats->dn_unknown++;710		break;711	case FPIN_DELI_TIMEOUT:712		stats->dn_timeout++;713		break;714	case FPIN_DELI_UNABLE_TO_ROUTE:715		stats->dn_unable_to_route++;716		break;717	case FPIN_DELI_DEVICE_SPEC:718		stats->dn_device_specific++;719		break;720	}721}722 723static void724fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats)725{726	stats->cn++;727	switch (event_type) {728	case FPIN_CONGN_CLEAR:729		stats->cn_clear++;730		break;731	case FPIN_CONGN_LOST_CREDIT:732		stats->cn_lost_credit++;733		break;734	case FPIN_CONGN_CREDIT_STALL:735		stats->cn_credit_stall++;736		break;737	case FPIN_CONGN_OVERSUBSCRIPTION:738		stats->cn_oversubscription++;739		break;740	case FPIN_CONGN_DEVICE_SPEC:741		stats->cn_device_specific++;742	}743}744 745/*746 * fc_fpin_li_stats_update - routine to update Link Integrity747 * event statistics.748 * @shost:		host the FPIN was received on749 * @tlv:		pointer to link integrity descriptor750 *751 */752static void753fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)754{755	u8 i;756	struct fc_rport *rport = NULL;757	struct fc_rport *attach_rport = NULL;758	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);759	struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv;760	u16 event_type = be16_to_cpu(li_desc->event_type);761	u64 wwpn;762 763	rport = fc_find_rport_by_wwpn(shost,764				      be64_to_cpu(li_desc->attached_wwpn));765	if (rport &&766	    (rport->roles & FC_PORT_ROLE_FCP_TARGET ||767	     rport->roles & FC_PORT_ROLE_NVME_TARGET)) {768		attach_rport = rport;769		fc_li_stats_update(event_type, &attach_rport->fpin_stats);770	}771 772	if (be32_to_cpu(li_desc->pname_count) > 0) {773		for (i = 0;774		    i < be32_to_cpu(li_desc->pname_count);775		    i++) {776			wwpn = be64_to_cpu(li_desc->pname_list[i]);777			rport = fc_find_rport_by_wwpn(shost, wwpn);778			if (rport &&779			    (rport->roles & FC_PORT_ROLE_FCP_TARGET ||780			    rport->roles & FC_PORT_ROLE_NVME_TARGET)) {781				if (rport == attach_rport)782					continue;783				fc_li_stats_update(event_type,784						   &rport->fpin_stats);785			}786		}787	}788 789	if (fc_host->port_name == be64_to_cpu(li_desc->attached_wwpn))790		fc_li_stats_update(event_type, &fc_host->fpin_stats);791}792 793/*794 * fc_fpin_delivery_stats_update - routine to update Delivery Notification795 * event statistics.796 * @shost:		host the FPIN was received on797 * @tlv:		pointer to delivery descriptor798 *799 */800static void801fc_fpin_delivery_stats_update(struct Scsi_Host *shost,802			      struct fc_tlv_desc *tlv)803{804	struct fc_rport *rport = NULL;805	struct fc_rport *attach_rport = NULL;806	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);807	struct fc_fn_deli_desc *dn_desc = (struct fc_fn_deli_desc *)tlv;808	u32 reason_code = be32_to_cpu(dn_desc->deli_reason_code);809 810	rport = fc_find_rport_by_wwpn(shost,811				      be64_to_cpu(dn_desc->attached_wwpn));812	if (rport &&813	    (rport->roles & FC_PORT_ROLE_FCP_TARGET ||814	     rport->roles & FC_PORT_ROLE_NVME_TARGET)) {815		attach_rport = rport;816		fc_delivery_stats_update(reason_code,817					 &attach_rport->fpin_stats);818	}819 820	if (fc_host->port_name == be64_to_cpu(dn_desc->attached_wwpn))821		fc_delivery_stats_update(reason_code, &fc_host->fpin_stats);822}823 824/*825 * fc_fpin_peer_congn_stats_update - routine to update Peer Congestion826 * event statistics.827 * @shost:		host the FPIN was received on828 * @tlv:		pointer to peer congestion descriptor829 *830 */831static void832fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost,833				struct fc_tlv_desc *tlv)834{835	u8 i;836	struct fc_rport *rport = NULL;837	struct fc_rport *attach_rport = NULL;838	struct fc_fn_peer_congn_desc *pc_desc =839	    (struct fc_fn_peer_congn_desc *)tlv;840	u16 event_type = be16_to_cpu(pc_desc->event_type);841	u64 wwpn;842 843	rport = fc_find_rport_by_wwpn(shost,844				      be64_to_cpu(pc_desc->attached_wwpn));845	if (rport &&846	    (rport->roles & FC_PORT_ROLE_FCP_TARGET ||847	     rport->roles & FC_PORT_ROLE_NVME_TARGET)) {848		attach_rport = rport;849		fc_cn_stats_update(event_type, &attach_rport->fpin_stats);850	}851 852	if (be32_to_cpu(pc_desc->pname_count) > 0) {853		for (i = 0;854		    i < be32_to_cpu(pc_desc->pname_count);855		    i++) {856			wwpn = be64_to_cpu(pc_desc->pname_list[i]);857			rport = fc_find_rport_by_wwpn(shost, wwpn);858			if (rport &&859			    (rport->roles & FC_PORT_ROLE_FCP_TARGET ||860			     rport->roles & FC_PORT_ROLE_NVME_TARGET)) {861				if (rport == attach_rport)862					continue;863				fc_cn_stats_update(event_type,864						   &rport->fpin_stats);865			}866		}867	}868}869 870/*871 * fc_fpin_congn_stats_update - routine to update Congestion872 * event statistics.873 * @shost:		host the FPIN was received on874 * @tlv:		pointer to congestion descriptor875 *876 */877static void878fc_fpin_congn_stats_update(struct Scsi_Host *shost,879			   struct fc_tlv_desc *tlv)880{881	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);882	struct fc_fn_congn_desc *congn = (struct fc_fn_congn_desc *)tlv;883 884	fc_cn_stats_update(be16_to_cpu(congn->event_type),885			   &fc_host->fpin_stats);886}887 888/**889 * fc_host_fpin_rcv - routine to process a received FPIN.890 * @shost:		host the FPIN was received on891 * @fpin_len:		length of FPIN payload, in bytes892 * @fpin_buf:		pointer to FPIN payload893 * @event_acknowledge:	1, if LLDD handles this event.894 * Notes:895 *	This routine assumes no locks are held on entry.896 */897void898fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf,899		u8 event_acknowledge)900{901	struct fc_els_fpin *fpin = (struct fc_els_fpin *)fpin_buf;902	struct fc_tlv_desc *tlv;903	u32 bytes_remain;904	u32 dtag;905	enum fc_host_event_code event_code =906		event_acknowledge ? FCH_EVT_LINK_FPIN_ACK : FCH_EVT_LINK_FPIN;907 908	/* Update Statistics */909	tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0];910	bytes_remain = fpin_len - offsetof(struct fc_els_fpin, fpin_desc);911	bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len));912 913	while (bytes_remain >= FC_TLV_DESC_HDR_SZ &&914	       bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) {915		dtag = be32_to_cpu(tlv->desc_tag);916		switch (dtag) {917		case ELS_DTAG_LNK_INTEGRITY:918			fc_fpin_li_stats_update(shost, tlv);919			break;920		case ELS_DTAG_DELIVERY:921			fc_fpin_delivery_stats_update(shost, tlv);922			break;923		case ELS_DTAG_PEER_CONGEST:924			fc_fpin_peer_congn_stats_update(shost, tlv);925			break;926		case ELS_DTAG_CONGESTION:927			fc_fpin_congn_stats_update(shost, tlv);928		}929 930		bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv);931		tlv = fc_tlv_next_desc(tlv);932	}933 934	fc_host_post_fc_event(shost, fc_get_event_number(),935				event_code, fpin_len, fpin_buf, 0);936}937EXPORT_SYMBOL(fc_host_fpin_rcv);938 939 940static __init int fc_transport_init(void)941{942	int error;943 944	atomic_set(&fc_event_seq, 0);945 946	error = transport_class_register(&fc_host_class);947	if (error)948		return error;949	error = transport_class_register(&fc_vport_class);950	if (error)951		goto unreg_host_class;952	error = transport_class_register(&fc_rport_class);953	if (error)954		goto unreg_vport_class;955	error = transport_class_register(&fc_transport_class);956	if (error)957		goto unreg_rport_class;958	return 0;959 960unreg_rport_class:961	transport_class_unregister(&fc_rport_class);962unreg_vport_class:963	transport_class_unregister(&fc_vport_class);964unreg_host_class:965	transport_class_unregister(&fc_host_class);966	return error;967}968 969static void __exit fc_transport_exit(void)970{971	transport_class_unregister(&fc_transport_class);972	transport_class_unregister(&fc_rport_class);973	transport_class_unregister(&fc_host_class);974	transport_class_unregister(&fc_vport_class);975}976 977/*978 * FC Remote Port Attribute Management979 */980 981#define fc_rport_show_function(field, format_string, sz, cast)		\982static ssize_t								\983show_fc_rport_##field (struct device *dev, 				\984		       struct device_attribute *attr, char *buf)	\985{									\986	struct fc_rport *rport = transport_class_to_rport(dev);		\987	struct Scsi_Host *shost = rport_to_shost(rport);		\988	struct fc_internal *i = to_fc_internal(shost->transportt);	\989	if ((i->f->get_rport_##field) &&				\990	    !((rport->port_state == FC_PORTSTATE_BLOCKED) ||		\991	      (rport->port_state == FC_PORTSTATE_DELETED) ||		\992	      (rport->port_state == FC_PORTSTATE_NOTPRESENT)))		\993		i->f->get_rport_##field(rport);				\994	return snprintf(buf, sz, format_string, cast rport->field); 	\995}996 997#define fc_rport_store_function(field)					\998static ssize_t								\999store_fc_rport_##field(struct device *dev,				\1000		       struct device_attribute *attr,			\1001		       const char *buf,	size_t count)			\1002{									\1003	int val;							\1004	struct fc_rport *rport = transport_class_to_rport(dev);		\1005	struct Scsi_Host *shost = rport_to_shost(rport);		\1006	struct fc_internal *i = to_fc_internal(shost->transportt);	\1007	char *cp;							\1008	if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||		\1009	    (rport->port_state == FC_PORTSTATE_DELETED) ||		\1010	    (rport->port_state == FC_PORTSTATE_NOTPRESENT))		\1011		return -EBUSY;						\1012	val = simple_strtoul(buf, &cp, 0);				\1013	if (*cp && (*cp != '\n'))					\1014		return -EINVAL;						\1015	i->f->set_rport_##field(rport, val);				\1016	return count;							\1017}1018 1019#define fc_rport_rd_attr(field, format_string, sz)			\1020	fc_rport_show_function(field, format_string, sz, )		\1021static FC_DEVICE_ATTR(rport, field, S_IRUGO,			\1022			 show_fc_rport_##field, NULL)1023 1024#define fc_rport_rd_attr_cast(field, format_string, sz, cast)		\1025	fc_rport_show_function(field, format_string, sz, (cast))	\1026static FC_DEVICE_ATTR(rport, field, S_IRUGO,			\1027			  show_fc_rport_##field, NULL)1028 1029#define fc_rport_rw_attr(field, format_string, sz)			\1030	fc_rport_show_function(field, format_string, sz, )		\1031	fc_rport_store_function(field)					\1032static FC_DEVICE_ATTR(rport, field, S_IRUGO | S_IWUSR,		\1033			show_fc_rport_##field,				\1034			store_fc_rport_##field)1035 1036 1037#define fc_private_rport_show_function(field, format_string, sz, cast)	\1038static ssize_t								\1039show_fc_rport_##field (struct device *dev, 				\1040		       struct device_attribute *attr, char *buf)	\1041{									\1042	struct fc_rport *rport = transport_class_to_rport(dev);		\1043	return snprintf(buf, sz, format_string, cast rport->field); 	\1044}1045 1046#define fc_private_rport_rd_attr(field, format_string, sz)		\1047	fc_private_rport_show_function(field, format_string, sz, )	\1048static FC_DEVICE_ATTR(rport, field, S_IRUGO,			\1049			 show_fc_rport_##field, NULL)1050 1051#define fc_private_rport_rd_attr_cast(field, format_string, sz, cast)	\1052	fc_private_rport_show_function(field, format_string, sz, (cast)) \1053static FC_DEVICE_ATTR(rport, field, S_IRUGO,			\1054			  show_fc_rport_##field, NULL)1055 1056 1057#define fc_private_rport_rd_enum_attr(title, maxlen)			\1058static ssize_t								\1059show_fc_rport_##title (struct device *dev,				\1060		       struct device_attribute *attr, char *buf)	\1061{									\1062	struct fc_rport *rport = transport_class_to_rport(dev);		\1063	const char *name;						\1064	name = get_fc_##title##_name(rport->title);			\1065	if (!name)							\1066		return -EINVAL;						\1067	return snprintf(buf, maxlen, "%s\n", name);			\1068}									\1069static FC_DEVICE_ATTR(rport, title, S_IRUGO,			\1070			show_fc_rport_##title, NULL)1071 1072 1073#define SETUP_RPORT_ATTRIBUTE_RD(field)					\1074	i->private_rport_attrs[count] = device_attr_rport_##field; \1075	i->private_rport_attrs[count].attr.mode = S_IRUGO;		\1076	i->private_rport_attrs[count].store = NULL;			\1077	i->rport_attrs[count] = &i->private_rport_attrs[count];		\1078	if (i->f->show_rport_##field)					\1079		count++1080 1081#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(field)				\1082	i->private_rport_attrs[count] = device_attr_rport_##field; \1083	i->private_rport_attrs[count].attr.mode = S_IRUGO;		\1084	i->private_rport_attrs[count].store = NULL;			\1085	i->rport_attrs[count] = &i->private_rport_attrs[count];		\1086	count++1087 1088#define SETUP_RPORT_ATTRIBUTE_RW(field)					\1089	i->private_rport_attrs[count] = device_attr_rport_##field; \1090	if (!i->f->set_rport_##field) {					\1091		i->private_rport_attrs[count].attr.mode = S_IRUGO;	\1092		i->private_rport_attrs[count].store = NULL;		\1093	}								\1094	i->rport_attrs[count] = &i->private_rport_attrs[count];		\1095	if (i->f->show_rport_##field)					\1096		count++1097 1098#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(field)				\1099{									\1100	i->private_rport_attrs[count] = device_attr_rport_##field; \1101	i->rport_attrs[count] = &i->private_rport_attrs[count];		\1102	count++;							\1103}1104 1105 1106/* The FC Transport Remote Port Attributes: */1107 1108/* Fixed Remote Port Attributes */1109 1110fc_private_rport_rd_attr(maxframe_size, "%u bytes\n", 20);1111 1112static ssize_t1113show_fc_rport_supported_classes (struct device *dev,1114				 struct device_attribute *attr, char *buf)1115{1116	struct fc_rport *rport = transport_class_to_rport(dev);1117	if (rport->supported_classes == FC_COS_UNSPECIFIED)1118		return snprintf(buf, 20, "unspecified\n");1119	return get_fc_cos_names(rport->supported_classes, buf);1120}1121static FC_DEVICE_ATTR(rport, supported_classes, S_IRUGO,1122		show_fc_rport_supported_classes, NULL);1123 1124/* Dynamic Remote Port Attributes */1125 1126/*1127 * dev_loss_tmo attribute1128 */1129static int fc_str_to_dev_loss(const char *buf, unsigned long *val)1130{1131	char *cp;1132 1133	*val = simple_strtoul(buf, &cp, 0);1134	if (*cp && (*cp != '\n'))1135		return -EINVAL;1136	/*1137	 * Check for overflow; dev_loss_tmo is u321138	 */1139	if (*val > UINT_MAX)1140		return -EINVAL;1141 1142	return 0;1143}1144 1145static int fc_rport_set_dev_loss_tmo(struct fc_rport *rport,1146				     unsigned long val)1147{1148	struct Scsi_Host *shost = rport_to_shost(rport);1149	struct fc_internal *i = to_fc_internal(shost->transportt);1150 1151	if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||1152	    (rport->port_state == FC_PORTSTATE_DELETED) ||1153	    (rport->port_state == FC_PORTSTATE_NOTPRESENT))1154		return -EBUSY;1155	/*1156	 * Check for overflow; dev_loss_tmo is u321157	 */1158	if (val > UINT_MAX)1159		return -EINVAL;1160 1161	/*1162	 * If fast_io_fail is off we have to cap1163	 * dev_loss_tmo at SCSI_DEVICE_BLOCK_MAX_TIMEOUT1164	 */1165	if (rport->fast_io_fail_tmo == -1 &&1166	    val > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)1167		return -EINVAL;1168 1169	i->f->set_rport_dev_loss_tmo(rport, val);1170	return 0;1171}1172 1173fc_rport_show_function(dev_loss_tmo, "%u\n", 20, )1174static ssize_t1175store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,1176			    const char *buf, size_t count)1177{1178	struct fc_rport *rport = transport_class_to_rport(dev);1179	unsigned long val;1180	int rc;1181 1182	rc = fc_str_to_dev_loss(buf, &val);1183	if (rc)1184		return rc;1185 1186	rc = fc_rport_set_dev_loss_tmo(rport, val);1187	if (rc)1188		return rc;1189	return count;1190}1191static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,1192		show_fc_rport_dev_loss_tmo, store_fc_rport_dev_loss_tmo);1193 1194 1195/* Private Remote Port Attributes */1196 1197fc_private_rport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);1198fc_private_rport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);1199fc_private_rport_rd_attr(port_id, "0x%06x\n", 20);1200 1201static ssize_t1202show_fc_rport_roles (struct device *dev, struct device_attribute *attr,1203		     char *buf)1204{1205	struct fc_rport *rport = transport_class_to_rport(dev);1206 1207	/* identify any roles that are port_id specific */1208	if ((rport->port_id != -1) &&1209	    (rport->port_id & FC_WELLKNOWN_PORTID_MASK) ==1210					FC_WELLKNOWN_PORTID_MASK) {1211		switch (rport->port_id & FC_WELLKNOWN_ROLE_MASK) {1212		case FC_FPORT_PORTID:1213			return snprintf(buf, 30, "Fabric Port\n");1214		case FC_FABCTLR_PORTID:1215			return snprintf(buf, 30, "Fabric Controller\n");1216		case FC_DIRSRVR_PORTID:1217			return snprintf(buf, 30, "Directory Server\n");1218		case FC_TIMESRVR_PORTID:1219			return snprintf(buf, 30, "Time Server\n");1220		case FC_MGMTSRVR_PORTID:1221			return snprintf(buf, 30, "Management Server\n");1222		default:1223			return snprintf(buf, 30, "Unknown Fabric Entity\n");1224		}1225	} else {1226		if (rport->roles == FC_PORT_ROLE_UNKNOWN)1227			return snprintf(buf, 20, "unknown\n");1228		return get_fc_port_roles_names(rport->roles, buf);1229	}1230}1231static FC_DEVICE_ATTR(rport, roles, S_IRUGO,1232		show_fc_rport_roles, NULL);1233 1234static ssize_t fc_rport_set_marginal_state(struct device *dev,1235						struct device_attribute *attr,1236						const char *buf, size_t count)1237{1238	struct fc_rport *rport = transport_class_to_rport(dev);1239	enum fc_port_state port_state;1240	int ret = 0;1241 1242	ret = get_fc_port_state_match(buf, &port_state);1243	if (ret)1244		return -EINVAL;1245	if (port_state == FC_PORTSTATE_MARGINAL) {1246		/*1247		 * Change the state to Marginal only if the1248		 * current rport state is Online1249		 * Allow only Online->Marginal1250		 */1251		if (rport->port_state == FC_PORTSTATE_ONLINE)1252			rport->port_state = port_state;1253		else if (port_state != rport->port_state)1254			return -EINVAL;1255	} else if (port_state == FC_PORTSTATE_ONLINE) {1256		/*1257		 * Change the state to Online only if the1258		 * current rport state is Marginal1259		 * Allow only Marginal->Online1260		 */1261		if (rport->port_state == FC_PORTSTATE_MARGINAL)1262			rport->port_state = port_state;1263		else if (port_state != rport->port_state)1264			return -EINVAL;1265	} else1266		return -EINVAL;1267	return count;1268}1269 1270static ssize_t1271show_fc_rport_port_state(struct device *dev,1272				struct device_attribute *attr, char *buf)1273{1274	const char *name;1275	struct fc_rport *rport = transport_class_to_rport(dev);1276 1277	name = get_fc_port_state_name(rport->port_state);1278	if (!name)1279		return -EINVAL;1280 1281	return snprintf(buf, 20, "%s\n", name);1282}1283 1284static FC_DEVICE_ATTR(rport, port_state, 0444 | 0200,1285			show_fc_rport_port_state, fc_rport_set_marginal_state);1286 1287fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20);1288 1289/*1290 * fast_io_fail_tmo attribute1291 */1292static ssize_t1293show_fc_rport_fast_io_fail_tmo (struct device *dev,1294				struct device_attribute *attr, char *buf)1295{1296	struct fc_rport *rport = transport_class_to_rport(dev);1297 1298	if (rport->fast_io_fail_tmo == -1)1299		return snprintf(buf, 5, "off\n");1300	return snprintf(buf, 20, "%d\n", rport->fast_io_fail_tmo);1301}1302 1303static ssize_t1304store_fc_rport_fast_io_fail_tmo(struct device *dev,1305				struct device_attribute *attr, const char *buf,1306				size_t count)1307{1308	int val;1309	char *cp;1310	struct fc_rport *rport = transport_class_to_rport(dev);1311 1312	if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||1313	    (rport->port_state == FC_PORTSTATE_DELETED) ||1314	    (rport->port_state == FC_PORTSTATE_NOTPRESENT))1315		return -EBUSY;1316	if (strncmp(buf, "off", 3) == 0)1317		rport->fast_io_fail_tmo = -1;1318	else {1319		val = simple_strtoul(buf, &cp, 0);1320		if ((*cp && (*cp != '\n')) || (val < 0))1321			return -EINVAL;1322		/*1323		 * Cap fast_io_fail by dev_loss_tmo or1324		 * SCSI_DEVICE_BLOCK_MAX_TIMEOUT.1325		 */1326		if ((val >= rport->dev_loss_tmo) ||1327		    (val > SCSI_DEVICE_BLOCK_MAX_TIMEOUT))1328			return -EINVAL;1329 1330		rport->fast_io_fail_tmo = val;1331	}1332	return count;1333}1334static FC_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,1335	show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);1336 1337#define fc_rport_fpin_statistic(name)					\1338static ssize_t fc_rport_fpinstat_##name(struct device *cd,		\1339				  struct device_attribute *attr,	\1340				  char *buf)				\1341{									\1342	struct fc_rport *rport = transport_class_to_rport(cd);		\1343									\1344	return snprintf(buf, 20, "0x%llx\n", rport->fpin_stats.name);	\1345}									\1346static FC_DEVICE_ATTR(rport, fpin_##name, 0444, fc_rport_fpinstat_##name, NULL)1347 1348fc_rport_fpin_statistic(dn);1349fc_rport_fpin_statistic(dn_unknown);1350fc_rport_fpin_statistic(dn_timeout);1351fc_rport_fpin_statistic(dn_unable_to_route);1352fc_rport_fpin_statistic(dn_device_specific);1353fc_rport_fpin_statistic(cn);1354fc_rport_fpin_statistic(cn_clear);1355fc_rport_fpin_statistic(cn_lost_credit);1356fc_rport_fpin_statistic(cn_credit_stall);1357fc_rport_fpin_statistic(cn_oversubscription);1358fc_rport_fpin_statistic(cn_device_specific);1359fc_rport_fpin_statistic(li);1360fc_rport_fpin_statistic(li_failure_unknown);1361fc_rport_fpin_statistic(li_link_failure_count);1362fc_rport_fpin_statistic(li_loss_of_sync_count);1363fc_rport_fpin_statistic(li_loss_of_signals_count);1364fc_rport_fpin_statistic(li_prim_seq_err_count);1365fc_rport_fpin_statistic(li_invalid_tx_word_count);1366fc_rport_fpin_statistic(li_invalid_crc_count);1367fc_rport_fpin_statistic(li_device_specific);1368 1369static struct attribute *fc_rport_statistics_attrs[] = {1370	&device_attr_rport_fpin_dn.attr,1371	&device_attr_rport_fpin_dn_unknown.attr,1372	&device_attr_rport_fpin_dn_timeout.attr,1373	&device_attr_rport_fpin_dn_unable_to_route.attr,1374	&device_attr_rport_fpin_dn_device_specific.attr,1375	&device_attr_rport_fpin_li.attr,1376	&device_attr_rport_fpin_li_failure_unknown.attr,1377	&device_attr_rport_fpin_li_link_failure_count.attr,1378	&device_attr_rport_fpin_li_loss_of_sync_count.attr,1379	&device_attr_rport_fpin_li_loss_of_signals_count.attr,1380	&device_attr_rport_fpin_li_prim_seq_err_count.attr,1381	&device_attr_rport_fpin_li_invalid_tx_word_count.attr,1382	&device_attr_rport_fpin_li_invalid_crc_count.attr,1383	&device_attr_rport_fpin_li_device_specific.attr,1384	&device_attr_rport_fpin_cn.attr,1385	&device_attr_rport_fpin_cn_clear.attr,1386	&device_attr_rport_fpin_cn_lost_credit.attr,1387	&device_attr_rport_fpin_cn_credit_stall.attr,1388	&device_attr_rport_fpin_cn_oversubscription.attr,1389	&device_attr_rport_fpin_cn_device_specific.attr,1390	NULL1391};1392 1393static struct attribute_group fc_rport_statistics_group = {1394	.name = "statistics",1395	.attrs = fc_rport_statistics_attrs,1396};1397 1398 1399/*1400 * FC SCSI Target Attribute Management1401 */1402 1403/*1404 * Note: in the target show function we recognize when the remote1405 *  port is in the hierarchy and do not allow the driver to get1406 *  involved in sysfs functions. The driver only gets involved if1407 *  it's the "old" style that doesn't use rports.1408 */1409#define fc_starget_show_function(field, format_string, sz, cast)	\1410static ssize_t								\1411show_fc_starget_##field (struct device *dev, 				\1412			 struct device_attribute *attr, char *buf)	\1413{									\1414	struct scsi_target *starget = transport_class_to_starget(dev);	\1415	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);	\1416	struct fc_internal *i = to_fc_internal(shost->transportt);	\1417	struct fc_rport *rport = starget_to_rport(starget);		\1418	if (rport)							\1419		fc_starget_##field(starget) = rport->field;		\1420	else if (i->f->get_starget_##field)				\1421		i->f->get_starget_##field(starget);			\1422	return snprintf(buf, sz, format_string, 			\1423		cast fc_starget_##field(starget)); 			\1424}1425 1426#define fc_starget_rd_attr(field, format_string, sz)			\1427	fc_starget_show_function(field, format_string, sz, )		\1428static FC_DEVICE_ATTR(starget, field, S_IRUGO,			\1429			 show_fc_starget_##field, NULL)1430 1431#define fc_starget_rd_attr_cast(field, format_string, sz, cast)		\1432	fc_starget_show_function(field, format_string, sz, (cast))	\1433static FC_DEVICE_ATTR(starget, field, S_IRUGO,			\1434			  show_fc_starget_##field, NULL)1435 1436#define SETUP_STARGET_ATTRIBUTE_RD(field)				\1437	i->private_starget_attrs[count] = device_attr_starget_##field; \1438	i->private_starget_attrs[count].attr.mode = S_IRUGO;		\1439	i->private_starget_attrs[count].store = NULL;			\1440	i->starget_attrs[count] = &i->private_starget_attrs[count];	\1441	if (i->f->show_starget_##field)					\1442		count++1443 1444#define SETUP_STARGET_ATTRIBUTE_RW(field)				\1445	i->private_starget_attrs[count] = device_attr_starget_##field; \1446	if (!i->f->set_starget_##field) {				\1447		i->private_starget_attrs[count].attr.mode = S_IRUGO;	\1448		i->private_starget_attrs[count].store = NULL;		\1449	}								\1450	i->starget_attrs[count] = &i->private_starget_attrs[count];	\1451	if (i->f->show_starget_##field)					\1452		count++1453 1454/* The FC Transport SCSI Target Attributes: */1455fc_starget_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);1456fc_starget_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);1457fc_starget_rd_attr(port_id, "0x%06x\n", 20);1458 1459 1460/*1461 * FC Virtual Port Attribute Management1462 */1463 1464#define fc_vport_show_function(field, format_string, sz, cast)		\1465static ssize_t								\1466show_fc_vport_##field (struct device *dev, 				\1467		       struct device_attribute *attr, char *buf)	\1468{									\1469	struct fc_vport *vport = transport_class_to_vport(dev);		\1470	struct Scsi_Host *shost = vport_to_shost(vport);		\1471	struct fc_internal *i = to_fc_internal(shost->transportt);	\1472	if ((i->f->get_vport_##field) &&				\1473	    !(vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)))	\1474		i->f->get_vport_##field(vport);				\1475	return snprintf(buf, sz, format_string, cast vport->field); 	\1476}1477 1478#define fc_vport_store_function(field)					\1479static ssize_t								\1480store_fc_vport_##field(struct device *dev,				\1481		       struct device_attribute *attr,			\1482		       const char *buf,	size_t count)			\1483{									\1484	int val;							\1485	struct fc_vport *vport = transport_class_to_vport(dev);		\1486	struct Scsi_Host *shost = vport_to_shost(vport);		\1487	struct fc_internal *i = to_fc_internal(shost->transportt);	\1488	char *cp;							\1489	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))	\1490		return -EBUSY;						\1491	val = simple_strtoul(buf, &cp, 0);				\1492	if (*cp && (*cp != '\n'))					\1493		return -EINVAL;						\1494	i->f->set_vport_##field(vport, val);				\1495	return count;							\1496}1497 1498#define fc_vport_store_str_function(field, slen)			\1499static ssize_t								\1500store_fc_vport_##field(struct device *dev,				\1501		       struct device_attribute *attr, 			\1502		       const char *buf,	size_t count)			\1503{									\1504	struct fc_vport *vport = transport_class_to_vport(dev);		\1505	struct Scsi_Host *shost = vport_to_shost(vport);		\1506	struct fc_internal *i = to_fc_internal(shost->transportt);	\1507	unsigned int cnt=count;						\1508									\1509	/* count may include a LF at end of string */			\1510	if (buf[cnt-1] == '\n')						\1511		cnt--;							\1512	if (cnt > ((slen) - 1))						\1513		return -EINVAL;						\1514	memcpy(vport->field, buf, cnt);					\1515	i->f->set_vport_##field(vport);					\1516	return count;							\1517}1518 1519#define fc_vport_rd_attr(field, format_string, sz)			\1520	fc_vport_show_function(field, format_string, sz, )		\1521static FC_DEVICE_ATTR(vport, field, S_IRUGO,			\1522			 show_fc_vport_##field, NULL)1523 1524#define fc_vport_rd_attr_cast(field, format_string, sz, cast)		\1525	fc_vport_show_function(field, format_string, sz, (cast))	\1526static FC_DEVICE_ATTR(vport, field, S_IRUGO,			\1527			  show_fc_vport_##field, NULL)1528 1529#define fc_vport_rw_attr(field, format_string, sz)			\1530	fc_vport_show_function(field, format_string, sz, )		\1531	fc_vport_store_function(field)					\1532static FC_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\1533			show_fc_vport_##field,				\1534			store_fc_vport_##field)1535 1536#define fc_private_vport_show_function(field, format_string, sz, cast)	\1537static ssize_t								\1538show_fc_vport_##field (struct device *dev,				\1539		       struct device_attribute *attr, char *buf)	\1540{									\1541	struct fc_vport *vport = transport_class_to_vport(dev);		\1542	return snprintf(buf, sz, format_string, cast vport->field); 	\1543}1544 1545#define fc_private_vport_store_u32_function(field)			\1546static ssize_t								\1547store_fc_vport_##field(struct device *dev,				\1548		       struct device_attribute *attr,			\1549		       const char *buf,	size_t count)			\1550{									\1551	u32 val;							\1552	struct fc_vport *vport = transport_class_to_vport(dev);		\1553	char *cp;							\1554	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))		\1555		return -EBUSY;						\1556	val = simple_strtoul(buf, &cp, 0);				\1557	if (*cp && (*cp != '\n'))					\1558		return -EINVAL;						\1559	vport->field = val;						\1560	return count;							\1561}1562 1563 1564#define fc_private_vport_rd_attr(field, format_string, sz)		\1565	fc_private_vport_show_function(field, format_string, sz, )	\1566static FC_DEVICE_ATTR(vport, field, S_IRUGO,			\1567			 show_fc_vport_##field, NULL)1568 1569#define fc_private_vport_rd_attr_cast(field, format_string, sz, cast)	\1570	fc_private_vport_show_function(field, format_string, sz, (cast)) \1571static FC_DEVICE_ATTR(vport, field, S_IRUGO,			\1572			  show_fc_vport_##field, NULL)1573 1574#define fc_private_vport_rw_u32_attr(field, format_string, sz)		\1575	fc_private_vport_show_function(field, format_string, sz, )	\1576	fc_private_vport_store_u32_function(field)			\1577static FC_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\1578			show_fc_vport_##field,				\1579			store_fc_vport_##field)1580 1581 1582#define fc_private_vport_rd_enum_attr(title, maxlen)			\1583static ssize_t								\1584show_fc_vport_##title (struct device *dev,				\1585		       struct device_attribute *attr,			\1586		       char *buf)					\1587{									\1588	struct fc_vport *vport = transport_class_to_vport(dev);		\1589	const char *name;						\1590	name = get_fc_##title##_name(vport->title);			\1591	if (!name)							\1592		return -EINVAL;						\1593	return snprintf(buf, maxlen, "%s\n", name);			\1594}									\1595static FC_DEVICE_ATTR(vport, title, S_IRUGO,			\1596			show_fc_vport_##title, NULL)1597 1598 1599#define SETUP_VPORT_ATTRIBUTE_RD(field)					\1600	i->private_vport_attrs[count] = device_attr_vport_##field; \1601	i->private_vport_attrs[count].attr.mode = S_IRUGO;		\1602	i->private_vport_attrs[count].store = NULL;			\1603	i->vport_attrs[count] = &i->private_vport_attrs[count];		\1604	if (i->f->get_##field)						\1605		count++1606	/* NOTE: Above MACRO differs: checks function not show bit */1607 1608#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field)				\1609	i->private_vport_attrs[count] = device_attr_vport_##field; \1610	i->private_vport_attrs[count].attr.mode = S_IRUGO;		\1611	i->private_vport_attrs[count].store = NULL;			\1612	i->vport_attrs[count] = &i->private_vport_attrs[count];		\1613	count++1614 1615#define SETUP_VPORT_ATTRIBUTE_WR(field)					\1616	i->private_vport_attrs[count] = device_attr_vport_##field; \1617	i->vport_attrs[count] = &i->private_vport_attrs[count];		\1618	if (i->f->field)						\1619		count++1620	/* NOTE: Above MACRO differs: checks function */1621 1622#define SETUP_VPORT_ATTRIBUTE_RW(field)					\1623	i->private_vport_attrs[count] = device_attr_vport_##field; \1624	if (!i->f->set_vport_##field) {					\1625		i->private_vport_attrs[count].attr.mode = S_IRUGO;	\1626		i->private_vport_attrs[count].store = NULL;		\1627	}								\1628	i->vport_attrs[count] = &i->private_vport_attrs[count];		\1629	count++1630	/* NOTE: Above MACRO differs: does not check show bit */1631 1632#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field)				\1633{									\1634	i->private_vport_attrs[count] = device_attr_vport_##field; \1635	i->vport_attrs[count] = &i->private_vport_attrs[count];		\1636	count++;							\1637}1638 1639 1640/* The FC Transport Virtual Port Attributes: */1641 1642/* Fixed Virtual Port Attributes */1643 1644/* Dynamic Virtual Port Attributes */1645 1646/* Private Virtual Port Attributes */1647 1648fc_private_vport_rd_enum_attr(vport_state, FC_VPORTSTATE_MAX_NAMELEN);1649fc_private_vport_rd_enum_attr(vport_last_state, FC_VPORTSTATE_MAX_NAMELEN);1650fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);1651fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);1652 1653static ssize_t1654show_fc_vport_roles (struct device *dev, struct device_attribute *attr,1655		     char *buf)1656{1657	struct fc_vport *vport = transport_class_to_vport(dev);1658 1659	if (vport->roles == FC_PORT_ROLE_UNKNOWN)1660		return snprintf(buf, 20, "unknown\n");1661	return get_fc_port_roles_names(vport->roles, buf);1662}1663static FC_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);1664 1665fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);1666 1667fc_private_vport_show_function(symbolic_name, "%s\n",1668		FC_VPORT_SYMBOLIC_NAMELEN + 1, )1669fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)1670static FC_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,1671		show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);1672 1673static ssize_t1674store_fc_vport_delete(struct device *dev, struct device_attribute *attr,1675		      const char *buf, size_t count)1676{1677	struct fc_vport *vport = transport_class_to_vport(dev);1678	struct Scsi_Host *shost = vport_to_shost(vport);1679	unsigned long flags;1680 1681	spin_lock_irqsave(shost->host_lock, flags);1682	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) {1683		spin_unlock_irqrestore(shost->host_lock, flags);1684		return -EBUSY;1685	}1686	vport->flags |= FC_VPORT_DELETING;1687	spin_unlock_irqrestore(shost->host_lock, flags);1688 1689	fc_queue_work(shost, &vport->vport_delete_work);1690	return count;1691}1692static FC_DEVICE_ATTR(vport, vport_delete, S_IWUSR,1693			NULL, store_fc_vport_delete);1694 1695 1696/*1697 * Enable/Disable vport1698 *  Write "1" to disable, write "0" to enable1699 */1700static ssize_t1701store_fc_vport_disable(struct device *dev, struct device_attribute *attr,1702		       const char *buf,1703			   size_t count)1704{1705	struct fc_vport *vport = transport_class_to_vport(dev);1706	struct Scsi_Host *shost = vport_to_shost(vport);1707	struct fc_internal *i = to_fc_internal(shost->transportt);1708	int stat;1709 1710	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))1711		return -EBUSY;1712 1713	if (*buf == '0') {1714		if (vport->vport_state != FC_VPORT_DISABLED)1715			return -EALREADY;1716	} else if (*buf == '1') {1717		if (vport->vport_state == FC_VPORT_DISABLED)1718			return -EALREADY;1719	} else1720		return -EINVAL;1721 1722	stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));1723	return stat ? stat : count;1724}1725static FC_DEVICE_ATTR(vport, vport_disable, S_IWUSR,1726			NULL, store_fc_vport_disable);1727 1728 1729/*1730 * Host Attribute Management1731 */1732 1733#define fc_host_show_function(field, format_string, sz, cast)		\1734static ssize_t								\1735show_fc_host_##field (struct device *dev,				\1736		      struct device_attribute *attr, char *buf)		\1737{									\1738	struct Scsi_Host *shost = transport_class_to_shost(dev);	\1739	struct fc_internal *i = to_fc_internal(shost->transportt);	\1740	if (i->f->get_host_##field)					\1741		i->f->get_host_##field(shost);				\1742	return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \1743}1744 1745#define fc_host_store_function(field)					\1746static ssize_t								\1747store_fc_host_##field(struct device *dev, 				\1748		      struct device_attribute *attr,			\1749		      const char *buf,	size_t count)			\1750{									\1751	int val;							\1752	struct Scsi_Host *shost = transport_class_to_shost(dev);	\1753	struct fc_internal *i = to_fc_internal(shost->transportt);	\1754	char *cp;							\1755									\1756	val = simple_strtoul(buf, &cp, 0);				\1757	if (*cp && (*cp != '\n'))					\1758		return -EINVAL;						\1759	i->f->set_host_##field(shost, val);				\1760	return count;							\1761}1762 1763#define fc_host_store_str_function(field, slen)				\1764static ssize_t								\1765store_fc_host_##field(struct device *dev,				\1766		      struct device_attribute *attr,			\1767		      const char *buf, size_t count)			\1768{									\1769	struct Scsi_Host *shost = transport_class_to_shost(dev);	\1770	struct fc_internal *i = to_fc_internal(shost->transportt);	\1771	unsigned int cnt=count;						\1772									\1773	/* count may include a LF at end of string */			\1774	if (buf[cnt-1] == '\n')						\1775		cnt--;							\1776	if (cnt > ((slen) - 1))						\1777		return -EINVAL;						\1778	memcpy(fc_host_##field(shost), buf, cnt);			\1779	i->f->set_host_##field(shost);					\1780	return count;							\1781}1782 1783#define fc_host_rd_attr(field, format_string, sz)			\1784	fc_host_show_function(field, format_string, sz, )		\1785static FC_DEVICE_ATTR(host, field, S_IRUGO,			\1786			 show_fc_host_##field, NULL)1787 1788#define fc_host_rd_attr_cast(field, format_string, sz, cast)		\1789	fc_host_show_function(field, format_string, sz, (cast))		\1790static FC_DEVICE_ATTR(host, field, S_IRUGO,			\1791			  show_fc_host_##field, NULL)1792 1793#define fc_host_rw_attr(field, format_string, sz)			\1794	fc_host_show_function(field, format_string, sz, )		\1795	fc_host_store_function(field)					\1796static FC_DEVICE_ATTR(host, field, S_IRUGO | S_IWUSR,		\1797			show_fc_host_##field,				\1798			store_fc_host_##field)1799 1800#define fc_host_rd_enum_attr(title, maxlen)				\1801static ssize_t								\1802show_fc_host_##title (struct device *dev,				\1803		      struct device_attribute *attr, char *buf)		\1804{									\1805	struct Scsi_Host *shost = transport_class_to_shost(dev);	\1806	struct fc_internal *i = to_fc_internal(shost->transportt);	\1807	const char *name;						\1808	if (i->f->get_host_##title)					\1809		i->f->get_host_##title(shost);				\1810	name = get_fc_##title##_name(fc_host_##title(shost));		\1811	if (!name)							\1812		return -EINVAL;						\1813	return snprintf(buf, maxlen, "%s\n", name);			\1814}									\1815static FC_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)1816 1817#define SETUP_HOST_ATTRIBUTE_RD(field)					\1818	i->private_host_attrs[count] = device_attr_host_##field;	\1819	i->private_host_attrs[count].attr.mode = S_IRUGO;		\1820	i->private_host_attrs[count].store = NULL;			\1821	i->host_attrs[count] = &i->private_host_attrs[count];		\1822	if (i->f->show_host_##field)					\1823		count++1824 1825#define SETUP_HOST_ATTRIBUTE_RD_NS(field)				\1826	i->private_host_attrs[count] = device_attr_host_##field;	\1827	i->private_host_attrs[count].attr.mode = S_IRUGO;		\1828	i->private_host_attrs[count].store = NULL;			\1829	i->host_attrs[count] = &i->private_host_attrs[count];		\1830	count++1831 1832#define SETUP_HOST_ATTRIBUTE_RW(field)					\1833	i->private_host_attrs[count] = device_attr_host_##field;	\1834	if (!i->f->set_host_##field) {					\1835		i->private_host_attrs[count].attr.mode = S_IRUGO;	\1836		i->private_host_attrs[count].store = NULL;		\1837	}								\1838	i->host_attrs[count] = &i->private_host_attrs[count];		\1839	if (i->f->show_host_##field)					\1840		count++1841 1842 1843#define fc_private_host_show_function(field, format_string, sz, cast)	\1844static ssize_t								\1845show_fc_host_##field (struct device *dev,				\1846		      struct device_attribute *attr, char *buf)		\1847{									\1848	struct Scsi_Host *shost = transport_class_to_shost(dev);	\1849	return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \1850}1851 1852#define fc_private_host_rd_attr(field, format_string, sz)		\1853	fc_private_host_show_function(field, format_string, sz, )	\1854static FC_DEVICE_ATTR(host, field, S_IRUGO,			\1855			 show_fc_host_##field, NULL)1856 1857#define fc_private_host_rd_attr_cast(field, format_string, sz, cast)	\1858	fc_private_host_show_function(field, format_string, sz, (cast)) \1859static FC_DEVICE_ATTR(host, field, S_IRUGO,			\1860			  show_fc_host_##field, NULL)1861 1862#define SETUP_PRIVATE_HOST_ATTRIBUTE_RD(field)			\1863	i->private_host_attrs[count] = device_attr_host_##field;	\1864	i->private_host_attrs[count].attr.mode = S_IRUGO;		\1865	i->private_host_attrs[count].store = NULL;			\1866	i->host_attrs[count] = &i->private_host_attrs[count];		\1867	count++1868 1869#define SETUP_PRIVATE_HOST_ATTRIBUTE_RW(field)			\1870{									\1871	i->private_host_attrs[count] = device_attr_host_##field;	\1872	i->host_attrs[count] = &i->private_host_attrs[count];		\1873	count++;							\1874}1875 1876 1877/* Fixed Host Attributes */1878 1879static ssize_t1880show_fc_host_supported_classes (struct device *dev,1881			        struct device_attribute *attr, char *buf)1882{1883	struct Scsi_Host *shost = transport_class_to_shost(dev);1884 1885	if (fc_host_supported_classes(shost) == FC_COS_UNSPECIFIED)1886		return snprintf(buf, 20, "unspecified\n");1887 1888	return get_fc_cos_names(fc_host_supported_classes(shost), buf);1889}1890static FC_DEVICE_ATTR(host, supported_classes, S_IRUGO,1891		show_fc_host_supported_classes, NULL);1892 1893static ssize_t1894show_fc_host_supported_fc4s (struct device *dev,1895			     struct device_attribute *attr, char *buf)1896{1897	struct Scsi_Host *shost = transport_class_to_shost(dev);1898	return (ssize_t)show_fc_fc4s(buf, fc_host_supported_fc4s(shost));1899}1900static FC_DEVICE_ATTR(host, supported_fc4s, S_IRUGO,1901		show_fc_host_supported_fc4s, NULL);1902 1903static ssize_t1904show_fc_host_supported_speeds (struct device *dev,1905			       struct device_attribute *attr, char *buf)1906{1907	struct Scsi_Host *shost = transport_class_to_shost(dev);1908 1909	if (fc_host_supported_speeds(shost) == FC_PORTSPEED_UNKNOWN)1910		return snprintf(buf, 20, "unknown\n");1911 1912	return get_fc_port_speed_names(fc_host_supported_speeds(shost), buf);1913}1914static FC_DEVICE_ATTR(host, supported_speeds, S_IRUGO,1915		show_fc_host_supported_speeds, NULL);1916 1917 1918fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);1919fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);1920fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,1921			     unsigned long long);1922fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);1923fc_private_host_rd_attr(max_npiv_vports, "%u\n", 20);1924fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));1925fc_private_host_rd_attr(manufacturer, "%s\n", FC_SERIAL_NUMBER_SIZE + 1);1926fc_private_host_rd_attr(model, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1);1927fc_private_host_rd_attr(model_description, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1);1928fc_private_host_rd_attr(hardware_version, "%s\n", FC_VERSION_STRING_SIZE + 1);1929fc_private_host_rd_attr(driver_version, "%s\n", FC_VERSION_STRING_SIZE + 1);1930fc_private_host_rd_attr(firmware_version, "%s\n", FC_VERSION_STRING_SIZE + 1);1931fc_private_host_rd_attr(optionrom_version, "%s\n", FC_VERSION_STRING_SIZE + 1);1932 1933 1934/* Dynamic Host Attributes */1935 1936static ssize_t1937show_fc_host_active_fc4s (struct device *dev,1938			  struct device_attribute *attr, char *buf)1939{1940	struct Scsi_Host *shost = transport_class_to_shost(dev);1941	struct fc_internal *i = to_fc_internal(shost->transportt);1942 1943	if (i->f->get_host_active_fc4s)1944		i->f->get_host_active_fc4s(shost);1945 1946	return (ssize_t)show_fc_fc4s(buf, fc_host_active_fc4s(shost));1947}1948static FC_DEVICE_ATTR(host, active_fc4s, S_IRUGO,1949		show_fc_host_active_fc4s, NULL);1950 1951static ssize_t1952show_fc_host_speed (struct device *dev,1953		    struct device_attribute *attr, char *buf)1954{1955	struct Scsi_Host *shost = transport_class_to_shost(dev);1956	struct fc_internal *i = to_fc_internal(shost->transportt);1957 1958	if (i->f->get_host_speed)1959		i->f->get_host_speed(shost);1960 1961	if (fc_host_speed(shost) == FC_PORTSPEED_UNKNOWN)1962		return snprintf(buf, 20, "unknown\n");1963 1964	return get_fc_port_speed_names(fc_host_speed(shost), buf);1965}1966static FC_DEVICE_ATTR(host, speed, S_IRUGO,1967		show_fc_host_speed, NULL);1968 1969 1970fc_host_rd_attr(port_id, "0x%06x\n", 20);1971fc_host_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN);1972fc_host_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);1973fc_host_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long);1974fc_host_rd_attr(symbolic_name, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1);1975 1976fc_private_host_show_function(system_hostname, "%s\n",1977		FC_SYMBOLIC_NAME_SIZE + 1, )1978fc_host_store_str_function(system_hostname, FC_SYMBOLIC_NAME_SIZE)1979static FC_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR,1980		show_fc_host_system_hostname, store_fc_host_system_hostname);1981 1982 1983/* Private Host Attributes */1984 1985static ssize_t1986show_fc_private_host_tgtid_bind_type(struct device *dev,1987				     struct device_attribute *attr, char *buf)1988{1989	struct Scsi_Host *shost = transport_class_to_shost(dev);1990	const char *name;1991 1992	name = get_fc_tgtid_bind_type_name(fc_host_tgtid_bind_type(shost));1993	if (!name)1994		return -EINVAL;1995	return snprintf(buf, FC_BINDTYPE_MAX_NAMELEN, "%s\n", name);1996}1997 1998#define get_list_head_entry(pos, head, member) 		\1999	pos = list_entry((head)->next, typeof(*pos), member)2000 2001static ssize_t2002store_fc_private_host_tgtid_bind_type(struct device *dev,2003	struct device_attribute *attr, const char *buf, size_t count)2004{2005	struct Scsi_Host *shost = transport_class_to_shost(dev);2006	struct fc_rport *rport;2007 	enum fc_tgtid_binding_type val;2008	unsigned long flags;2009 2010	if (get_fc_tgtid_bind_type_match(buf, &val))2011		return -EINVAL;2012 2013	/* if changing bind type, purge all unused consistent bindings */2014	if (val != fc_host_tgtid_bind_type(shost)) {2015		spin_lock_irqsave(shost->host_lock, flags);2016		while (!list_empty(&fc_host_rport_bindings(shost))) {2017			get_list_head_entry(rport,2018				&fc_host_rport_bindings(shost), peers);2019			list_del(&rport->peers);2020			rport->port_state = FC_PORTSTATE_DELETED;2021			fc_queue_work(shost, &rport->rport_delete_work);2022		}2023		spin_unlock_irqrestore(shost->host_lock, flags);2024	}2025 2026	fc_host_tgtid_bind_type(shost) = val;2027	return count;2028}2029 2030static FC_DEVICE_ATTR(host, tgtid_bind_type, S_IRUGO | S_IWUSR,2031			show_fc_private_host_tgtid_bind_type,2032			store_fc_private_host_tgtid_bind_type);2033 2034static ssize_t2035store_fc_private_host_issue_lip(struct device *dev,2036	struct device_attribute *attr, const char *buf, size_t count)2037{2038	struct Scsi_Host *shost = transport_class_to_shost(dev);2039	struct fc_internal *i = to_fc_internal(shost->transportt);2040	int ret;2041 2042	/* ignore any data value written to the attribute */2043	if (i->f->issue_fc_host_lip) {2044		ret = i->f->issue_fc_host_lip(shost);2045		return ret ? ret: count;2046	}2047 2048	return -ENOENT;2049}2050 2051static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,2052			store_fc_private_host_issue_lip);2053 2054static ssize_t2055store_fc_private_host_dev_loss_tmo(struct device *dev,2056				   struct device_attribute *attr,2057				   const char *buf, size_t count)2058{2059	struct Scsi_Host *shost = transport_class_to_shost(dev);2060	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);2061	struct fc_rport *rport;2062	unsigned long val, flags;2063	int rc;2064 2065	rc = fc_str_to_dev_loss(buf, &val);2066	if (rc)2067		return rc;2068 2069	fc_host_dev_loss_tmo(shost) = val;2070	spin_lock_irqsave(shost->host_lock, flags);2071	list_for_each_entry(rport, &fc_host->rports, peers)2072		fc_rport_set_dev_loss_tmo(rport, val);2073	spin_unlock_irqrestore(shost->host_lock, flags);2074	return count;2075}2076 2077fc_private_host_show_function(dev_loss_tmo, "%d\n", 20, );2078static FC_DEVICE_ATTR(host, dev_loss_tmo, S_IRUGO | S_IWUSR,2079		      show_fc_host_dev_loss_tmo,2080		      store_fc_private_host_dev_loss_tmo);2081 2082fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);2083 2084/*2085 * Host Statistics Management2086 */2087 2088/* Show a given attribute in the statistics group */2089static ssize_t2090fc_stat_show(const struct device *dev, char *buf, unsigned long offset)2091{2092	struct Scsi_Host *shost = transport_class_to_shost(dev);2093	struct fc_internal *i = to_fc_internal(shost->transportt);2094	struct fc_host_statistics *stats;2095	ssize_t ret = -ENOENT;2096 2097	if (offset > sizeof(struct fc_host_statistics) ||2098	    offset % sizeof(u64) != 0)2099		WARN_ON(1);2100 2101	if (i->f->get_fc_host_stats) {2102		stats = (i->f->get_fc_host_stats)(shost);2103		if (stats)2104			ret = snprintf(buf, 20, "0x%llx\n",2105			      (unsigned long long)*(u64 *)(((u8 *) stats) + offset));2106	}2107	return ret;2108}2109 2110 2111/* generate a read-only statistics attribute */2112#define fc_host_statistic(name)						\2113static ssize_t show_fcstat_##name(struct device *cd,			\2114				  struct device_attribute *attr,	\2115				  char *buf)				\2116{									\2117	return fc_stat_show(cd, buf, 					\2118			    offsetof(struct fc_host_statistics, name));	\2119}									\2120static FC_DEVICE_ATTR(host, name, S_IRUGO, show_fcstat_##name, NULL)2121 2122fc_host_statistic(seconds_since_last_reset);2123fc_host_statistic(tx_frames);2124fc_host_statistic(tx_words);2125fc_host_statistic(rx_frames);2126fc_host_statistic(rx_words);2127fc_host_statistic(lip_count);2128fc_host_statistic(nos_count);2129fc_host_statistic(error_frames);2130fc_host_statistic(dumped_frames);2131fc_host_statistic(link_failure_count);2132fc_host_statistic(loss_of_sync_count);2133fc_host_statistic(loss_of_signal_count);2134fc_host_statistic(prim_seq_protocol_err_count);2135fc_host_statistic(invalid_tx_word_count);2136fc_host_statistic(invalid_crc_count);2137fc_host_statistic(fcp_input_requests);2138fc_host_statistic(fcp_output_requests);2139fc_host_statistic(fcp_control_requests);2140fc_host_statistic(fcp_input_megabytes);2141fc_host_statistic(fcp_output_megabytes);2142fc_host_statistic(fcp_packet_alloc_failures);2143fc_host_statistic(fcp_packet_aborts);2144fc_host_statistic(fcp_frame_alloc_failures);2145fc_host_statistic(fc_no_free_exch);2146fc_host_statistic(fc_no_free_exch_xid);2147fc_host_statistic(fc_xid_not_found);2148fc_host_statistic(fc_xid_busy);2149fc_host_statistic(fc_seq_not_found);2150fc_host_statistic(fc_non_bls_resp);2151fc_host_statistic(cn_sig_warn);2152fc_host_statistic(cn_sig_alarm);2153 2154 2155#define fc_host_fpin_statistic(name)					\2156static ssize_t fc_host_fpinstat_##name(struct device *cd,		\2157				  struct device_attribute *attr,	\2158				  char *buf)				\2159{									\2160	struct Scsi_Host *shost = transport_class_to_shost(cd);		\2161	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);	\2162									\2163	return snprintf(buf, 20, "0x%llx\n", fc_host->fpin_stats.name);	\2164}									\2165static FC_DEVICE_ATTR(host, fpin_##name, 0444, fc_host_fpinstat_##name, NULL)2166 2167fc_host_fpin_statistic(dn);2168fc_host_fpin_statistic(dn_unknown);2169fc_host_fpin_statistic(dn_timeout);2170fc_host_fpin_statistic(dn_unable_to_route);2171fc_host_fpin_statistic(dn_device_specific);2172fc_host_fpin_statistic(cn);2173fc_host_fpin_statistic(cn_clear);2174fc_host_fpin_statistic(cn_lost_credit);2175fc_host_fpin_statistic(cn_credit_stall);2176fc_host_fpin_statistic(cn_oversubscription);2177fc_host_fpin_statistic(cn_device_specific);2178fc_host_fpin_statistic(li);2179fc_host_fpin_statistic(li_failure_unknown);2180fc_host_fpin_statistic(li_link_failure_count);2181fc_host_fpin_statistic(li_loss_of_sync_count);2182fc_host_fpin_statistic(li_loss_of_signals_count);2183fc_host_fpin_statistic(li_prim_seq_err_count);2184fc_host_fpin_statistic(li_invalid_tx_word_count);2185fc_host_fpin_statistic(li_invalid_crc_count);2186fc_host_fpin_statistic(li_device_specific);2187 2188static ssize_t2189fc_reset_statistics(struct device *dev, struct device_attribute *attr,2190		    const char *buf, size_t count)2191{2192	struct Scsi_Host *shost = transport_class_to_shost(dev);2193	struct fc_internal *i = to_fc_internal(shost->transportt);2194 2195	/* ignore any data value written to the attribute */2196	if (i->f->reset_fc_host_stats) {2197		i->f->reset_fc_host_stats(shost);2198		return count;2199	}2200 2201	return -ENOENT;2202}2203static FC_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,2204				fc_reset_statistics);2205 2206static struct attribute *fc_statistics_attrs[] = {2207	&device_attr_host_seconds_since_last_reset.attr,2208	&device_attr_host_tx_frames.attr,2209	&device_attr_host_tx_words.attr,2210	&device_attr_host_rx_frames.attr,2211	&device_attr_host_rx_words.attr,2212	&device_attr_host_lip_count.attr,2213	&device_attr_host_nos_count.attr,2214	&device_attr_host_error_frames.attr,2215	&device_attr_host_dumped_frames.attr,2216	&device_attr_host_link_failure_count.attr,2217	&device_attr_host_loss_of_sync_count.attr,2218	&device_attr_host_loss_of_signal_count.attr,2219	&device_attr_host_prim_seq_protocol_err_count.attr,2220	&device_attr_host_invalid_tx_word_count.attr,2221	&device_attr_host_invalid_crc_count.attr,2222	&device_attr_host_fcp_input_requests.attr,2223	&device_attr_host_fcp_output_requests.attr,2224	&device_attr_host_fcp_control_requests.attr,2225	&device_attr_host_fcp_input_megabytes.attr,2226	&device_attr_host_fcp_output_megabytes.attr,2227	&device_attr_host_fcp_packet_alloc_failures.attr,2228	&device_attr_host_fcp_packet_aborts.attr,2229	&device_attr_host_fcp_frame_alloc_failures.attr,2230	&device_attr_host_fc_no_free_exch.attr,2231	&device_attr_host_fc_no_free_exch_xid.attr,2232	&device_attr_host_fc_xid_not_found.attr,2233	&device_attr_host_fc_xid_busy.attr,2234	&device_attr_host_fc_seq_not_found.attr,2235	&device_attr_host_fc_non_bls_resp.attr,2236	&device_attr_host_cn_sig_warn.attr,2237	&device_attr_host_cn_sig_alarm.attr,2238	&device_attr_host_reset_statistics.attr,2239	&device_attr_host_fpin_dn.attr,2240	&device_attr_host_fpin_dn_unknown.attr,2241	&device_attr_host_fpin_dn_timeout.attr,2242	&device_attr_host_fpin_dn_unable_to_route.attr,2243	&device_attr_host_fpin_dn_device_specific.attr,2244	&device_attr_host_fpin_li.attr,2245	&device_attr_host_fpin_li_failure_unknown.attr,2246	&device_attr_host_fpin_li_link_failure_count.attr,2247	&device_attr_host_fpin_li_loss_of_sync_count.attr,2248	&device_attr_host_fpin_li_loss_of_signals_count.attr,2249	&device_attr_host_fpin_li_prim_seq_err_count.attr,2250	&device_attr_host_fpin_li_invalid_tx_word_count.attr,2251	&device_attr_host_fpin_li_invalid_crc_count.attr,2252	&device_attr_host_fpin_li_device_specific.attr,2253	&device_attr_host_fpin_cn.attr,2254	&device_attr_host_fpin_cn_clear.attr,2255	&device_attr_host_fpin_cn_lost_credit.attr,2256	&device_attr_host_fpin_cn_credit_stall.attr,2257	&device_attr_host_fpin_cn_oversubscription.attr,2258	&device_attr_host_fpin_cn_device_specific.attr,2259	NULL2260};2261 2262static struct attribute_group fc_statistics_group = {2263	.name = "statistics",2264	.attrs = fc_statistics_attrs,2265};2266 2267 2268/* Host Vport Attributes */2269 2270static int2271fc_parse_wwn(const char *ns, u64 *nm)2272{2273	unsigned int i, j;2274	u8 wwn[8];2275 2276	memset(wwn, 0, sizeof(wwn));2277 2278	/* Validate and store the new name */2279	for (i=0, j=0; i < 16; i++) {2280		int value;2281 2282		value = hex_to_bin(*ns++);2283		if (value >= 0)2284			j = (j << 4) | value;2285		else2286			return -EINVAL;2287		if (i % 2) {2288			wwn[i/2] = j & 0xff;2289			j = 0;2290		}2291	}2292 2293	*nm = wwn_to_u64(wwn);2294 2295	return 0;2296}2297 2298 2299/*2300 * "Short-cut" sysfs variable to create a new vport on a FC Host.2301 * Input is a string of the form "<WWPN>:<WWNN>". Other attributes2302 * will default to a NPIV-based FCP_Initiator; The WWNs are specified2303 * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)2304 */2305static ssize_t2306store_fc_host_vport_create(struct device *dev, struct device_attribute *attr,2307			   const char *buf, size_t count)2308{2309	struct Scsi_Host *shost = transport_class_to_shost(dev);2310	struct fc_vport_identifiers vid;2311	struct fc_vport *vport;2312	unsigned int cnt=count;2313	int stat;2314 2315	memset(&vid, 0, sizeof(vid));2316 2317	/* count may include a LF at end of string */2318	if (buf[cnt-1] == '\n')2319		cnt--;2320 2321	/* validate we have enough characters for WWPN */2322	if ((cnt != (16+1+16)) || (buf[16] != ':'))2323		return -EINVAL;2324 2325	stat = fc_parse_wwn(&buf[0], &vid.port_name);2326	if (stat)2327		return stat;2328 2329	stat = fc_parse_wwn(&buf[17], &vid.node_name);2330	if (stat)2331		return stat;2332 2333	vid.roles = FC_PORT_ROLE_FCP_INITIATOR;2334	vid.vport_type = FC_PORTTYPE_NPIV;2335	/* vid.symbolic_name is already zero/NULL's */2336	vid.disable = false;		/* always enabled */2337 2338	/* we only allow support on Channel 0 !!! */2339	stat = fc_vport_setup(shost, 0, &shost->shost_gendev, &vid, &vport);2340	return stat ? stat : count;2341}2342static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,2343			store_fc_host_vport_create);2344 2345 2346/*2347 * "Short-cut" sysfs variable to delete a vport on a FC Host.2348 * Vport is identified by a string containing "<WWPN>:<WWNN>".2349 * The WWNs are specified as hex characters, and may *not* contain2350 * any prefixes (e.g. 0x, x, etc)2351 */2352static ssize_t2353store_fc_host_vport_delete(struct device *dev, struct device_attribute *attr,2354			   const char *buf, size_t count)2355{2356	struct Scsi_Host *shost = transport_class_to_shost(dev);2357	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);2358	struct fc_vport *vport;2359	u64 wwpn, wwnn;2360	unsigned long flags;2361	unsigned int cnt=count;2362	int stat, match;2363 2364	/* count may include a LF at end of string */2365	if (buf[cnt-1] == '\n')2366		cnt--;2367 2368	/* validate we have enough characters for WWPN */2369	if ((cnt != (16+1+16)) || (buf[16] != ':'))2370		return -EINVAL;2371 2372	stat = fc_parse_wwn(&buf[0], &wwpn);2373	if (stat)2374		return stat;2375 2376	stat = fc_parse_wwn(&buf[17], &wwnn);2377	if (stat)2378		return stat;2379 2380	spin_lock_irqsave(shost->host_lock, flags);2381	match = 0;2382	/* we only allow support on Channel 0 !!! */2383	list_for_each_entry(vport, &fc_host->vports, peers) {2384		if ((vport->channel == 0) &&2385		    (vport->port_name == wwpn) && (vport->node_name == wwnn)) {2386			if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))2387				break;2388			vport->flags |= FC_VPORT_DELETING;2389			match = 1;2390			break;2391		}2392	}2393	spin_unlock_irqrestore(shost->host_lock, flags);2394 2395	if (!match)2396		return -ENODEV;2397 2398	stat = fc_vport_terminate(vport);2399	return stat ? stat : count;2400}2401static FC_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,2402			store_fc_host_vport_delete);2403 2404 2405static int fc_host_match(struct attribute_container *cont,2406			  struct device *dev)2407{2408	struct Scsi_Host *shost;2409	struct fc_internal *i;2410 2411	if (!scsi_is_host_device(dev))2412		return 0;2413 2414	shost = dev_to_shost(dev);2415	if (!shost->transportt  || shost->transportt->host_attrs.ac.class2416	    != &fc_host_class.class)2417		return 0;2418 2419	i = to_fc_internal(shost->transportt);2420 2421	return &i->t.host_attrs.ac == cont;2422}2423 2424static int fc_target_match(struct attribute_container *cont,2425			    struct device *dev)2426{2427	struct Scsi_Host *shost;2428	struct fc_internal *i;2429 2430	if (!scsi_is_target_device(dev))2431		return 0;2432 2433	shost = dev_to_shost(dev->parent);2434	if (!shost->transportt  || shost->transportt->host_attrs.ac.class2435	    != &fc_host_class.class)2436		return 0;2437 2438	i = to_fc_internal(shost->transportt);2439 2440	return &i->t.target_attrs.ac == cont;2441}2442 2443static void fc_rport_dev_release(struct device *dev)2444{2445	struct fc_rport *rport = dev_to_rport(dev);2446	put_device(dev->parent);2447	kfree(rport);2448}2449 2450int scsi_is_fc_rport(const struct device *dev)2451{2452	return dev->release == fc_rport_dev_release;2453}2454EXPORT_SYMBOL(scsi_is_fc_rport);2455 2456static int fc_rport_match(struct attribute_container *cont,2457			    struct device *dev)2458{2459	struct Scsi_Host *shost;2460	struct fc_internal *i;2461 2462	if (!scsi_is_fc_rport(dev))2463		return 0;2464 2465	shost = dev_to_shost(dev->parent);2466	if (!shost->transportt  || shost->transportt->host_attrs.ac.class2467	    != &fc_host_class.class)2468		return 0;2469 2470	i = to_fc_internal(shost->transportt);2471 2472	return &i->rport_attr_cont.ac == cont;2473}2474 2475 2476static void fc_vport_dev_release(struct device *dev)2477{2478	struct fc_vport *vport = dev_to_vport(dev);2479	put_device(dev->parent);		/* release kobj parent */2480	kfree(vport);2481}2482 2483static int scsi_is_fc_vport(const struct device *dev)2484{2485	return dev->release == fc_vport_dev_release;2486}2487 2488static int fc_vport_match(struct attribute_container *cont,2489			    struct device *dev)2490{2491	struct fc_vport *vport;2492	struct Scsi_Host *shost;2493	struct fc_internal *i;2494 2495	if (!scsi_is_fc_vport(dev))2496		return 0;2497	vport = dev_to_vport(dev);2498 2499	shost = vport_to_shost(vport);2500	if (!shost->transportt  || shost->transportt->host_attrs.ac.class2501	    != &fc_host_class.class)2502		return 0;2503 2504	i = to_fc_internal(shost->transportt);2505	return &i->vport_attr_cont.ac == cont;2506}2507 2508 2509/**2510 * fc_eh_timed_out - FC Transport I/O timeout intercept handler2511 * @scmd:	The SCSI command which timed out2512 *2513 * This routine protects against error handlers getting invoked while a2514 * rport is in a blocked state, typically due to a temporarily loss of2515 * connectivity. If the error handlers are allowed to proceed, requests2516 * to abort i/o, reset the target, etc will likely fail as there is no way2517 * to communicate with the device to perform the requested function. These2518 * failures may result in the midlayer taking the device offline, requiring2519 * manual intervention to restore operation.2520 *2521 * This routine, called whenever an i/o times out, validates the state of2522 * the underlying rport. If the rport is blocked, it returns2523 * EH_RESET_TIMER, which will continue to reschedule the timeout.2524 * Eventually, either the device will return, or devloss_tmo will fire,2525 * and when the timeout then fires, it will be handled normally.2526 * If the rport is not blocked, normal error handling continues.2527 *2528 * Notes:2529 *	This routine assumes no locks are held on entry.2530 */2531enum scsi_timeout_action fc_eh_timed_out(struct scsi_cmnd *scmd)2532{2533	struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device));2534 2535	if (rport->port_state == FC_PORTSTATE_BLOCKED)2536		return SCSI_EH_RESET_TIMER;2537 2538	return SCSI_EH_NOT_HANDLED;2539}2540EXPORT_SYMBOL(fc_eh_timed_out);2541 2542/*2543 * Called by fc_user_scan to locate an rport on the shost that2544 * matches the channel and target id, and invoke scsi_scan_target()2545 * on the rport.2546 */2547static void2548fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, u64 lun)2549{2550	struct fc_rport *rport;2551	unsigned long flags;2552 2553	spin_lock_irqsave(shost->host_lock, flags);2554 2555	list_for_each_entry(rport, &fc_host_rports(shost), peers) {2556		if (rport->scsi_target_id == -1)2557			continue;2558 2559		if ((rport->port_state != FC_PORTSTATE_ONLINE) &&2560			(rport->port_state != FC_PORTSTATE_MARGINAL))2561			continue;2562 2563		if ((channel == rport->channel) &&2564		    (id == rport->scsi_target_id)) {2565			spin_unlock_irqrestore(shost->host_lock, flags);2566			scsi_scan_target(&rport->dev, channel, id, lun,2567					 SCSI_SCAN_MANUAL);2568			return;2569		}2570	}2571 2572	spin_unlock_irqrestore(shost->host_lock, flags);2573}2574 2575/*2576 * Called via sysfs scan routines. Necessary, as the FC transport2577 * wants to place all target objects below the rport object. So this2578 * routine must invoke the scsi_scan_target() routine with the rport2579 * object as the parent.2580 */2581static int2582fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, u64 lun)2583{2584	uint chlo, chhi;2585	uint tgtlo, tgthi;2586 2587	if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||2588	    ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||2589	    ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))2590		return -EINVAL;2591 2592	if (channel == SCAN_WILD_CARD) {2593		chlo = 0;2594		chhi = shost->max_channel + 1;2595	} else {2596		chlo = channel;2597		chhi = channel + 1;2598	}2599 2600	if (id == SCAN_WILD_CARD) {2601		tgtlo = 0;2602		tgthi = shost->max_id;2603	} else {2604		tgtlo = id;2605		tgthi = id + 1;2606	}2607 2608	for ( ; chlo < chhi; chlo++)2609		for ( ; tgtlo < tgthi; tgtlo++)2610			fc_user_scan_tgt(shost, chlo, tgtlo, lun);2611 2612	return 0;2613}2614 2615struct scsi_transport_template *2616fc_attach_transport(struct fc_function_template *ft)2617{2618	int count;2619	struct fc_internal *i = kzalloc(sizeof(struct fc_internal),2620					GFP_KERNEL);2621 2622	if (unlikely(!i))2623		return NULL;2624 2625	i->t.target_attrs.ac.attrs = &i->starget_attrs[0];2626	i->t.target_attrs.ac.class = &fc_transport_class.class;2627	i->t.target_attrs.ac.match = fc_target_match;2628	i->t.target_size = sizeof(struct fc_starget_attrs);2629	transport_container_register(&i->t.target_attrs);2630 2631	i->t.host_attrs.ac.attrs = &i->host_attrs[0];2632	i->t.host_attrs.ac.class = &fc_host_class.class;2633	i->t.host_attrs.ac.match = fc_host_match;2634	i->t.host_size = sizeof(struct fc_host_attrs);2635	if (ft->get_fc_host_stats)2636		i->t.host_attrs.statistics = &fc_statistics_group;2637	transport_container_register(&i->t.host_attrs);2638 2639	i->rport_attr_cont.ac.attrs = &i->rport_attrs[0];2640	i->rport_attr_cont.ac.class = &fc_rport_class.class;2641	i->rport_attr_cont.ac.match = fc_rport_match;2642	i->rport_attr_cont.statistics = &fc_rport_statistics_group;2643	transport_container_register(&i->rport_attr_cont);2644 2645	i->vport_attr_cont.ac.attrs = &i->vport_attrs[0];2646	i->vport_attr_cont.ac.class = &fc_vport_class.class;2647	i->vport_attr_cont.ac.match = fc_vport_match;2648	transport_container_register(&i->vport_attr_cont);2649 2650	i->f = ft;2651 2652	/* Transport uses the shost workq for scsi scanning */2653	i->t.create_work_queue = 1;2654 2655	i->t.user_scan = fc_user_scan;2656 2657	/*2658	 * Setup SCSI Target Attributes.2659	 */2660	count = 0;2661	SETUP_STARGET_ATTRIBUTE_RD(node_name);2662	SETUP_STARGET_ATTRIBUTE_RD(port_name);2663	SETUP_STARGET_ATTRIBUTE_RD(port_id);2664 2665	BUG_ON(count > FC_STARGET_NUM_ATTRS);2666 2667	i->starget_attrs[count] = NULL;2668 2669 2670	/*2671	 * Setup SCSI Host Attributes.2672	 */2673	count=0;2674	SETUP_HOST_ATTRIBUTE_RD(node_name);2675	SETUP_HOST_ATTRIBUTE_RD(port_name);2676	SETUP_HOST_ATTRIBUTE_RD(permanent_port_name);2677	SETUP_HOST_ATTRIBUTE_RD(supported_classes);2678	SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);2679	SETUP_HOST_ATTRIBUTE_RD(supported_speeds);2680	SETUP_HOST_ATTRIBUTE_RD(maxframe_size);2681	if (ft->vport_create) {2682		SETUP_HOST_ATTRIBUTE_RD_NS(max_npiv_vports);2683		SETUP_HOST_ATTRIBUTE_RD_NS(npiv_vports_inuse);2684	}2685	SETUP_HOST_ATTRIBUTE_RD(serial_number);2686	SETUP_HOST_ATTRIBUTE_RD(manufacturer);2687	SETUP_HOST_ATTRIBUTE_RD(model);2688	SETUP_HOST_ATTRIBUTE_RD(model_description);2689	SETUP_HOST_ATTRIBUTE_RD(hardware_version);2690	SETUP_HOST_ATTRIBUTE_RD(driver_version);2691	SETUP_HOST_ATTRIBUTE_RD(firmware_version);2692	SETUP_HOST_ATTRIBUTE_RD(optionrom_version);2693 2694	SETUP_HOST_ATTRIBUTE_RD(port_id);2695	SETUP_HOST_ATTRIBUTE_RD(port_type);2696	SETUP_HOST_ATTRIBUTE_RD(port_state);2697	SETUP_HOST_ATTRIBUTE_RD(active_fc4s);2698	SETUP_HOST_ATTRIBUTE_RD(speed);2699	SETUP_HOST_ATTRIBUTE_RD(fabric_name);2700	SETUP_HOST_ATTRIBUTE_RD(symbolic_name);2701	SETUP_HOST_ATTRIBUTE_RW(system_hostname);2702 2703	/* Transport-managed attributes */2704	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(dev_loss_tmo);2705	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);2706	if (ft->issue_fc_host_lip)2707		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);2708	if (ft->vport_create)2709		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_create);2710	if (ft->vport_delete)2711		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_delete);2712 2713	BUG_ON(count > FC_HOST_NUM_ATTRS);2714 2715	i->host_attrs[count] = NULL;2716 2717	/*2718	 * Setup Remote Port Attributes.2719	 */2720	count=0;2721	SETUP_RPORT_ATTRIBUTE_RD(maxframe_size);2722	SETUP_RPORT_ATTRIBUTE_RD(supported_classes);2723	SETUP_RPORT_ATTRIBUTE_RW(dev_loss_tmo);2724	SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(node_name);2725	SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_name);2726	SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_id);2727	SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles);2728	SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(port_state);2729	SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id);2730	SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(fast_io_fail_tmo);2731 2732	BUG_ON(count > FC_RPORT_NUM_ATTRS);2733 2734	i->rport_attrs[count] = NULL;2735 2736	/*2737	 * Setup Virtual Port Attributes.2738	 */2739	count=0;2740	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_state);2741	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_last_state);2742	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(node_name);2743	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(port_name);2744	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(roles);2745	SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_type);2746	SETUP_VPORT_ATTRIBUTE_RW(symbolic_name);2747	SETUP_VPORT_ATTRIBUTE_WR(vport_delete);2748	SETUP_VPORT_ATTRIBUTE_WR(vport_disable);2749 2750	BUG_ON(count > FC_VPORT_NUM_ATTRS);2751 2752	i->vport_attrs[count] = NULL;2753 2754	return &i->t;2755}2756EXPORT_SYMBOL(fc_attach_transport);2757 2758void fc_release_transport(struct scsi_transport_template *t)2759{2760	struct fc_internal *i = to_fc_internal(t);2761 2762	transport_container_unregister(&i->t.target_attrs);2763	transport_container_unregister(&i->t.host_attrs);2764	transport_container_unregister(&i->rport_attr_cont);2765	transport_container_unregister(&i->vport_attr_cont);2766 2767	kfree(i);2768}2769EXPORT_SYMBOL(fc_release_transport);2770 2771/**2772 * fc_queue_work - Queue work to the fc_host workqueue.2773 * @shost:	Pointer to Scsi_Host bound to fc_host.2774 * @work:	Work to queue for execution.2775 *2776 * Return value:2777 * 	1 - work queued for execution2778 *	0 - work is already queued2779 *	-EINVAL - work queue doesn't exist2780 */2781static int2782fc_queue_work(struct Scsi_Host *shost, struct work_struct *work)2783{2784	if (unlikely(!fc_host_work_q(shost))) {2785		printk(KERN_ERR2786			"ERROR: FC host '%s' attempted to queue work, "2787			"when no workqueue created.\n", shost->hostt->name);2788		dump_stack();2789 2790		return -EINVAL;2791	}2792 2793	return queue_work(fc_host_work_q(shost), work);2794}2795 2796/**2797 * fc_flush_work - Flush a fc_host's workqueue.2798 * @shost:	Pointer to Scsi_Host bound to fc_host.2799 */2800static void2801fc_flush_work(struct Scsi_Host *shost)2802{2803	if (!fc_host_work_q(shost)) {2804		printk(KERN_ERR2805			"ERROR: FC host '%s' attempted to flush work, "2806			"when no workqueue created.\n", shost->hostt->name);2807		dump_stack();2808		return;2809	}2810 2811	flush_workqueue(fc_host_work_q(shost));2812}2813 2814/**2815 * fc_queue_devloss_work - Schedule work for the fc_host devloss workqueue.2816 * @shost:	Pointer to Scsi_Host bound to fc_host.2817 * @work:	Work to queue for execution.2818 * @delay:	jiffies to delay the work queuing2819 *2820 * Return value:2821 * 	1 on success / 0 already queued / < 0 for error2822 */2823static int2824fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work,2825				unsigned long delay)2826{2827	if (unlikely(!fc_host_devloss_work_q(shost))) {2828		printk(KERN_ERR2829			"ERROR: FC host '%s' attempted to queue work, "2830			"when no workqueue created.\n", shost->hostt->name);2831		dump_stack();2832 2833		return -EINVAL;2834	}2835 2836	return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);2837}2838 2839/**2840 * fc_flush_devloss - Flush a fc_host's devloss workqueue.2841 * @shost:	Pointer to Scsi_Host bound to fc_host.2842 */2843static void2844fc_flush_devloss(struct Scsi_Host *shost)2845{2846	if (!fc_host_devloss_work_q(shost)) {2847		printk(KERN_ERR2848			"ERROR: FC host '%s' attempted to flush work, "2849			"when no workqueue created.\n", shost->hostt->name);2850		dump_stack();2851		return;2852	}2853 2854	flush_workqueue(fc_host_devloss_work_q(shost));2855}2856 2857 2858/**2859 * fc_remove_host - called to terminate any fc_transport-related elements for a scsi host.2860 * @shost:	Which &Scsi_Host2861 *2862 * This routine is expected to be called immediately preceding the2863 * a driver's call to scsi_remove_host().2864 *2865 * WARNING: A driver utilizing the fc_transport, which fails to call2866 *   this routine prior to scsi_remove_host(), will leave dangling2867 *   objects in /sys/class/fc_remote_ports. Access to any of these2868 *   objects can result in a system crash !!!2869 *2870 * Notes:2871 *	This routine assumes no locks are held on entry.2872 */2873void2874fc_remove_host(struct Scsi_Host *shost)2875{2876	struct fc_vport *vport = NULL, *next_vport = NULL;2877	struct fc_rport *rport = NULL, *next_rport = NULL;2878	struct workqueue_struct *work_q;2879	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);2880	unsigned long flags;2881 2882	spin_lock_irqsave(shost->host_lock, flags);2883 2884	/* Remove any vports */2885	list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) {2886		vport->flags |= FC_VPORT_DELETING;2887		fc_queue_work(shost, &vport->vport_delete_work);2888	}2889 2890	/* Remove any remote ports */2891	list_for_each_entry_safe(rport, next_rport,2892			&fc_host->rports, peers) {2893		list_del(&rport->peers);2894		rport->port_state = FC_PORTSTATE_DELETED;2895		fc_queue_work(shost, &rport->rport_delete_work);2896	}2897 2898	list_for_each_entry_safe(rport, next_rport,2899			&fc_host->rport_bindings, peers) {2900		list_del(&rport->peers);2901		rport->port_state = FC_PORTSTATE_DELETED;2902		fc_queue_work(shost, &rport->rport_delete_work);2903	}2904 2905	spin_unlock_irqrestore(shost->host_lock, flags);2906 2907	/* flush all scan work items */2908	scsi_flush_work(shost);2909 2910	/* flush all stgt delete, and rport delete work items, then kill it  */2911	if (fc_host->work_q) {2912		work_q = fc_host->work_q;2913		fc_host->work_q = NULL;2914		destroy_workqueue(work_q);2915	}2916 2917	/* flush all devloss work items, then kill it  */2918	if (fc_host->devloss_work_q) {2919		work_q = fc_host->devloss_work_q;2920		fc_host->devloss_work_q = NULL;2921		destroy_workqueue(work_q);2922	}2923}2924EXPORT_SYMBOL(fc_remove_host);2925 2926static void fc_terminate_rport_io(struct fc_rport *rport)2927{2928	struct Scsi_Host *shost = rport_to_shost(rport);2929	struct fc_internal *i = to_fc_internal(shost->transportt);2930 2931	/* Involve the LLDD if possible to terminate all io on the rport. */2932	if (i->f->terminate_rport_io)2933		i->f->terminate_rport_io(rport);2934 2935	/*2936	 * Must unblock to flush queued IO. scsi-ml will fail incoming reqs.2937	 */2938	scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE);2939}2940 2941/**2942 * fc_starget_delete - called to delete the scsi descendants of an rport2943 * @work:	remote port to be operated on.2944 *2945 * Deletes target and all sdevs.2946 */2947static void2948fc_starget_delete(struct work_struct *work)2949{2950	struct fc_rport *rport =2951		container_of(work, struct fc_rport, stgt_delete_work);2952 2953	fc_terminate_rport_io(rport);2954	scsi_remove_target(&rport->dev);2955}2956 2957 2958/**2959 * fc_rport_final_delete - finish rport termination and delete it.2960 * @work:	remote port to be deleted.2961 */2962static void2963fc_rport_final_delete(struct work_struct *work)2964{2965	struct fc_rport *rport =2966		container_of(work, struct fc_rport, rport_delete_work);2967	struct device *dev = &rport->dev;2968	struct Scsi_Host *shost = rport_to_shost(rport);2969	struct fc_internal *i = to_fc_internal(shost->transportt);2970	unsigned long flags;2971	int do_callback = 0;2972 2973	fc_terminate_rport_io(rport);2974 2975	/*2976	 * if a scan is pending, flush the SCSI Host work_q so that2977	 * that we can reclaim the rport scan work element.2978	 */2979	if (rport->flags & FC_RPORT_SCAN_PENDING)2980		scsi_flush_work(shost);2981 2982	/*2983	 * Cancel any outstanding timers. These should really exist2984	 * only when rmmod'ing the LLDD and we're asking for2985	 * immediate termination of the rports2986	 */2987	spin_lock_irqsave(shost->host_lock, flags);2988	if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {2989		spin_unlock_irqrestore(shost->host_lock, flags);2990		if (!cancel_delayed_work(&rport->fail_io_work))2991			fc_flush_devloss(shost);2992		if (!cancel_delayed_work(&rport->dev_loss_work))2993			fc_flush_devloss(shost);2994		cancel_work_sync(&rport->scan_work);2995		spin_lock_irqsave(shost->host_lock, flags);2996		rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;2997	}2998	spin_unlock_irqrestore(shost->host_lock, flags);2999 3000	/* Delete SCSI target and sdevs */3001	if (rport->scsi_target_id != -1)3002		fc_starget_delete(&rport->stgt_delete_work);3003 3004	/*3005	 * Notify the driver that the rport is now dead. The LLDD will3006	 * also guarantee that any communication to the rport is terminated3007	 *3008	 * Avoid this call if we already called it when we preserved the3009	 * rport for the binding.3010	 */3011	spin_lock_irqsave(shost->host_lock, flags);3012	if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) &&3013	    (i->f->dev_loss_tmo_callbk)) {3014		rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE;3015		do_callback = 1;3016	}3017	spin_unlock_irqrestore(shost->host_lock, flags);3018 3019	if (do_callback)3020		i->f->dev_loss_tmo_callbk(rport);3021 3022	fc_bsg_remove(rport->rqst_q);3023 3024	transport_remove_device(dev);3025	device_del(dev);3026	transport_destroy_device(dev);3027	scsi_host_put(shost);			/* for fc_host->rport list */3028	put_device(dev);			/* for self-reference */3029}3030 3031 3032/**3033 * fc_remote_port_create - allocates and creates a remote FC port.3034 * @shost:	scsi host the remote port is connected to.3035 * @channel:	Channel on shost port connected to.3036 * @ids:	The world wide names, fc address, and FC4 port3037 *		roles for the remote port.3038 *3039 * Allocates and creates the remoter port structure, including the3040 * class and sysfs creation.3041 *3042 * Notes:3043 *	This routine assumes no locks are held on entry.3044 */3045static struct fc_rport *3046fc_remote_port_create(struct Scsi_Host *shost, int channel,3047		      struct fc_rport_identifiers  *ids)3048{3049	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);3050	struct fc_internal *fci = to_fc_internal(shost->transportt);3051	struct fc_rport *rport;3052	struct device *dev;3053	unsigned long flags;3054	int error;3055	size_t size;3056 3057	size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size);3058	rport = kzalloc(size, GFP_KERNEL);3059	if (unlikely(!rport)) {3060		printk(KERN_ERR "%s: allocation failure\n", __func__);3061		return NULL;3062	}3063 3064	rport->maxframe_size = -1;3065	rport->supported_classes = FC_COS_UNSPECIFIED;3066	rport->dev_loss_tmo = fc_host->dev_loss_tmo;3067	memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));3068	memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));3069	rport->port_id = ids->port_id;3070	rport->roles = ids->roles;3071	rport->port_state = FC_PORTSTATE_ONLINE;3072	if (fci->f->dd_fcrport_size)3073		rport->dd_data = &rport[1];3074	rport->channel = channel;3075	rport->fast_io_fail_tmo = -1;3076 3077	INIT_DELAYED_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport);3078	INIT_DELAYED_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io);3079	INIT_WORK(&rport->scan_work, fc_scsi_scan_rport);3080	INIT_WORK(&rport->stgt_delete_work, fc_starget_delete);3081	INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete);3082 3083	spin_lock_irqsave(shost->host_lock, flags);3084 3085	rport->number = fc_host->next_rport_number++;3086	if ((rport->roles & FC_PORT_ROLE_FCP_TARGET) ||3087	    (rport->roles & FC_PORT_ROLE_FCP_DUMMY_INITIATOR))3088		rport->scsi_target_id = fc_host->next_target_id++;3089	else3090		rport->scsi_target_id = -1;3091	list_add_tail(&rport->peers, &fc_host->rports);3092	scsi_host_get(shost);			/* for fc_host->rport list */3093 3094	spin_unlock_irqrestore(shost->host_lock, flags);3095 3096	dev = &rport->dev;3097	device_initialize(dev);			/* takes self reference */3098	dev->parent = get_device(&shost->shost_gendev); /* parent reference */3099	dev->release = fc_rport_dev_release;3100	dev_set_name(dev, "rport-%d:%d-%d",3101		     shost->host_no, channel, rport->number);3102	transport_setup_device(dev);3103 3104	error = device_add(dev);3105	if (error) {3106		printk(KERN_ERR "FC Remote Port device_add failed\n");3107		goto delete_rport;3108	}3109	transport_add_device(dev);3110	transport_configure_device(dev);3111 3112	fc_bsg_rportadd(shost, rport);3113	/* ignore any bsg add error - we just can't do sgio */3114 3115	if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {3116		/* initiate a scan of the target */3117		rport->flags |= FC_RPORT_SCAN_PENDING;3118		scsi_queue_work(shost, &rport->scan_work);3119	}3120 3121	return rport;3122 3123delete_rport:3124	transport_destroy_device(dev);3125	spin_lock_irqsave(shost->host_lock, flags);3126	list_del(&rport->peers);3127	scsi_host_put(shost);			/* for fc_host->rport list */3128	spin_unlock_irqrestore(shost->host_lock, flags);3129	put_device(dev->parent);3130	kfree(rport);3131	return NULL;3132}3133 3134/**3135 * fc_remote_port_add - notify fc transport of the existence of a remote FC port.3136 * @shost:	scsi host the remote port is connected to.3137 * @channel:	Channel on shost port connected to.3138 * @ids:	The world wide names, fc address, and FC4 port3139 *		roles for the remote port.3140 *3141 * The LLDD calls this routine to notify the transport of the existence3142 * of a remote port. The LLDD provides the unique identifiers (wwpn,wwn)3143 * of the port, it's FC address (port_id), and the FC4 roles that are3144 * active for the port.3145 *3146 * For ports that are FCP targets (aka scsi targets), the FC transport3147 * maintains consistent target id bindings on behalf of the LLDD.3148 * A consistent target id binding is an assignment of a target id to3149 * a remote port identifier, which persists while the scsi host is3150 * attached. The remote port can disappear, then later reappear, and3151 * it's target id assignment remains the same. This allows for shifts3152 * in FC addressing (if binding by wwpn or wwnn) with no apparent3153 * changes to the scsi subsystem which is based on scsi host number and3154 * target id values.  Bindings are only valid during the attachment of3155 * the scsi host. If the host detaches, then later re-attaches, target3156 * id bindings may change.3157 *3158 * This routine is responsible for returning a remote port structure.3159 * The routine will search the list of remote ports it maintains3160 * internally on behalf of consistent target id mappings. If found, the3161 * remote port structure will be reused. Otherwise, a new remote port3162 * structure will be allocated.3163 *3164 * Whenever a remote port is allocated, a new fc_remote_port class3165 * device is created.3166 *3167 * Should not be called from interrupt context.3168 *3169 * Notes:3170 *	This routine assumes no locks are held on entry.3171 */3172struct fc_rport *3173fc_remote_port_add(struct Scsi_Host *shost, int channel,3174	struct fc_rport_identifiers  *ids)3175{3176	struct fc_internal *fci = to_fc_internal(shost->transportt);3177	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);3178	struct fc_rport *rport;3179	unsigned long flags;3180	int match = 0;3181 3182	/* ensure any stgt delete functions are done */3183	fc_flush_work(shost);3184 3185	/*3186	 * Search the list of "active" rports, for an rport that has been3187	 * deleted, but we've held off the real delete while the target3188	 * is in a "blocked" state.3189	 */3190	spin_lock_irqsave(shost->host_lock, flags);3191 3192	list_for_each_entry(rport, &fc_host->rports, peers) {3193 3194		if ((rport->port_state == FC_PORTSTATE_BLOCKED ||3195		     rport->port_state == FC_PORTSTATE_NOTPRESENT) &&3196			(rport->channel == channel)) {3197 3198			switch (fc_host->tgtid_bind_type) {3199			case FC_TGTID_BIND_BY_WWPN:3200			case FC_TGTID_BIND_NONE:3201				if (rport->port_name == ids->port_name)3202					match = 1;3203				break;3204			case FC_TGTID_BIND_BY_WWNN:3205				if (rport->node_name == ids->node_name)3206					match = 1;3207				break;3208			case FC_TGTID_BIND_BY_ID:3209				if (rport->port_id == ids->port_id)3210					match = 1;3211				break;3212			}3213 3214			if (match) {3215 3216				memcpy(&rport->node_name, &ids->node_name,3217					sizeof(rport->node_name));3218				memcpy(&rport->port_name, &ids->port_name,3219					sizeof(rport->port_name));3220				rport->port_id = ids->port_id;3221 3222				rport->port_state = FC_PORTSTATE_ONLINE;3223				rport->roles = ids->roles;3224 3225				spin_unlock_irqrestore(shost->host_lock, flags);3226 3227				if (fci->f->dd_fcrport_size)3228					memset(rport->dd_data, 0,3229						fci->f->dd_fcrport_size);3230 3231				/*3232				 * If we were not a target, cancel the3233				 * io terminate and rport timers, and3234				 * we're done.3235				 *3236				 * If we were a target, but our new role3237				 * doesn't indicate a target, leave the3238				 * timers running expecting the role to3239				 * change as the target fully logs in. If3240				 * it doesn't, the target will be torn down.3241				 *3242				 * If we were a target, and our role shows3243				 * we're still a target, cancel the timers3244				 * and kick off a scan.3245				 */3246 3247				/* was a target, not in roles */3248				if ((rport->scsi_target_id != -1) &&3249				    (!(ids->roles & FC_PORT_ROLE_FCP_TARGET)))3250					return rport;3251 3252				/*3253				 * Stop the fail io and dev_loss timers.3254				 * If they flush, the port_state will3255				 * be checked and will NOOP the function.3256				 */3257				if (!cancel_delayed_work(&rport->fail_io_work))3258					fc_flush_devloss(shost);3259				if (!cancel_delayed_work(&rport->dev_loss_work))3260					fc_flush_devloss(shost);3261 3262				spin_lock_irqsave(shost->host_lock, flags);3263 3264				rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |3265						  FC_RPORT_DEVLOSS_PENDING |3266						  FC_RPORT_DEVLOSS_CALLBK_DONE);3267 3268				spin_unlock_irqrestore(shost->host_lock, flags);3269 3270				/* if target, initiate a scan */3271				if (rport->scsi_target_id != -1) {3272					scsi_target_unblock(&rport->dev,3273							    SDEV_RUNNING);3274					spin_lock_irqsave(shost->host_lock,3275							  flags);3276					rport->flags |= FC_RPORT_SCAN_PENDING;3277					scsi_queue_work(shost,3278							&rport->scan_work);3279					spin_unlock_irqrestore(shost->host_lock,3280							flags);3281				}3282 3283				fc_bsg_goose_queue(rport);3284 3285				return rport;3286			}3287		}3288	}3289 3290	/*3291	 * Search the bindings array3292	 * Note: if never a FCP target, you won't be on this list3293	 */3294	if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) {3295 3296		/* search for a matching consistent binding */3297 3298		list_for_each_entry(rport, &fc_host->rport_bindings,3299					peers) {3300			if (rport->channel != channel)3301				continue;3302 3303			switch (fc_host->tgtid_bind_type) {3304			case FC_TGTID_BIND_BY_WWPN:3305				if (rport->port_name == ids->port_name)3306					match = 1;3307				break;3308			case FC_TGTID_BIND_BY_WWNN:3309				if (rport->node_name == ids->node_name)3310					match = 1;3311				break;3312			case FC_TGTID_BIND_BY_ID:3313				if (rport->port_id == ids->port_id)3314					match = 1;3315				break;3316			case FC_TGTID_BIND_NONE: /* to keep compiler happy */3317				break;3318			}3319 3320			if (match) {3321				list_move_tail(&rport->peers, &fc_host->rports);3322				break;3323			}3324		}3325 3326		if (match) {3327			memcpy(&rport->node_name, &ids->node_name,3328				sizeof(rport->node_name));3329			memcpy(&rport->port_name, &ids->port_name,3330				sizeof(rport->port_name));3331			rport->port_id = ids->port_id;3332			rport->port_state = FC_PORTSTATE_ONLINE;3333			rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;3334 3335			if (fci->f->dd_fcrport_size)3336				memset(rport->dd_data, 0,3337						fci->f->dd_fcrport_size);3338			spin_unlock_irqrestore(shost->host_lock, flags);3339 3340			fc_remote_port_rolechg(rport, ids->roles);3341			return rport;3342		}3343	}3344 3345	spin_unlock_irqrestore(shost->host_lock, flags);3346 3347	/* No consistent binding found - create new remote port entry */3348	rport = fc_remote_port_create(shost, channel, ids);3349 3350	return rport;3351}3352EXPORT_SYMBOL(fc_remote_port_add);3353 3354 3355/**3356 * fc_remote_port_delete - notifies the fc transport that a remote port is no longer in existence.3357 * @rport:	The remote port that no longer exists3358 *3359 * The LLDD calls this routine to notify the transport that a remote3360 * port is no longer part of the topology. Note: Although a port3361 * may no longer be part of the topology, it may persist in the remote3362 * ports displayed by the fc_host. We do this under 2 conditions:3363 *3364 * 1) If the port was a scsi target, we delay its deletion by "blocking" it.3365 *    This allows the port to temporarily disappear, then reappear without3366 *    disrupting the SCSI device tree attached to it. During the "blocked"3367 *    period the port will still exist.3368 *3369 * 2) If the port was a scsi target and disappears for longer than we3370 *    expect, we'll delete the port and the tear down the SCSI device tree3371 *    attached to it. However, we want to semi-persist the target id assigned3372 *    to that port if it eventually does exist. The port structure will3373 *    remain (although with minimal information) so that the target id3374 *    bindings also remain.3375 *3376 * If the remote port is not an FCP Target, it will be fully torn down3377 * and deallocated, including the fc_remote_port class device.3378 *3379 * If the remote port is an FCP Target, the port will be placed in a3380 * temporary blocked state. From the LLDD's perspective, the rport no3381 * longer exists. From the SCSI midlayer's perspective, the SCSI target3382 * exists, but all sdevs on it are blocked from further I/O. The following3383 * is then expected.3384 *3385 *   If the remote port does not return (signaled by a LLDD call to3386 *   fc_remote_port_add()) within the dev_loss_tmo timeout, then the3387 *   scsi target is removed - killing all outstanding i/o and removing the3388 *   scsi devices attached to it. The port structure will be marked Not3389 *   Present and be partially cleared, leaving only enough information to3390 *   recognize the remote port relative to the scsi target id binding if3391 *   it later appears.  The port will remain as long as there is a valid3392 *   binding (e.g. until the user changes the binding type or unloads the3393 *   scsi host with the binding).3394 *3395 *   If the remote port returns within the dev_loss_tmo value (and matches3396 *   according to the target id binding type), the port structure will be3397 *   reused. If it is no longer a SCSI target, the target will be torn3398 *   down. If it continues to be a SCSI target, then the target will be3399 *   unblocked (allowing i/o to be resumed), and a scan will be activated3400 *   to ensure that all luns are detected.3401 *3402 * Called from normal process context only - cannot be called from interrupt.3403 *3404 * Notes:3405 *	This routine assumes no locks are held on entry.3406 */3407void3408fc_remote_port_delete(struct fc_rport  *rport)3409{3410	struct Scsi_Host *shost = rport_to_shost(rport);3411	unsigned long timeout = rport->dev_loss_tmo;3412	unsigned long flags;3413 3414	/*3415	 * No need to flush the fc_host work_q's, as all adds are synchronous.3416	 *3417	 * We do need to reclaim the rport scan work element, so eventually3418	 * (in fc_rport_final_delete()) we'll flush the scsi host work_q if3419	 * there's still a scan pending.3420	 */3421 3422	spin_lock_irqsave(shost->host_lock, flags);3423 3424	if ((rport->port_state != FC_PORTSTATE_ONLINE) &&3425		(rport->port_state != FC_PORTSTATE_MARGINAL)) {3426		spin_unlock_irqrestore(shost->host_lock, flags);3427		return;3428	}3429 3430	/*3431	 * In the past, we if this was not an FCP-Target, we would3432	 * unconditionally just jump to deleting the rport.3433	 * However, rports can be used as node containers by the LLDD,3434	 * and its not appropriate to just terminate the rport at the3435	 * first sign of a loss in connectivity. The LLDD may want to3436	 * send ELS traffic to re-validate the login. If the rport is3437	 * immediately deleted, it makes it inappropriate for a node3438	 * container.3439	 * So... we now unconditionally wait dev_loss_tmo before3440	 * destroying an rport.3441	 */3442 3443	rport->port_state = FC_PORTSTATE_BLOCKED;3444 3445	rport->flags |= FC_RPORT_DEVLOSS_PENDING;3446 3447	spin_unlock_irqrestore(shost->host_lock, flags);3448 3449	scsi_block_targets(shost, &rport->dev);3450 3451	/* see if we need to kill io faster than waiting for device loss */3452	if ((rport->fast_io_fail_tmo != -1) &&3453	    (rport->fast_io_fail_tmo < timeout))3454		fc_queue_devloss_work(shost, &rport->fail_io_work,3455					rport->fast_io_fail_tmo * HZ);3456 3457	/* cap the length the devices can be blocked until they are deleted */3458	fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ);3459}3460EXPORT_SYMBOL(fc_remote_port_delete);3461 3462/**3463 * fc_remote_port_rolechg - notifies the fc transport that the roles on a remote may have changed.3464 * @rport:	The remote port that changed.3465 * @roles:      New roles for this port.3466 *3467 * Description: The LLDD calls this routine to notify the transport that the3468 * roles on a remote port may have changed. The largest effect of this is3469 * if a port now becomes a FCP Target, it must be allocated a3470 * scsi target id.  If the port is no longer a FCP target, any3471 * scsi target id value assigned to it will persist in case the3472 * role changes back to include FCP Target. No changes in the scsi3473 * midlayer will be invoked if the role changes (in the expectation3474 * that the role will be resumed. If it doesn't normal error processing3475 * will take place).3476 *3477 * Should not be called from interrupt context.3478 *3479 * Notes:3480 *	This routine assumes no locks are held on entry.3481 */3482void3483fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)3484{3485	struct Scsi_Host *shost = rport_to_shost(rport);3486	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);3487	unsigned long flags;3488	int create = 0;3489 3490	spin_lock_irqsave(shost->host_lock, flags);3491	if (roles & FC_PORT_ROLE_FCP_TARGET) {3492		if (rport->scsi_target_id == -1) {3493			rport->scsi_target_id = fc_host->next_target_id++;3494			create = 1;3495		} else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET))3496			create = 1;3497	}3498 3499	rport->roles = roles;3500 3501	spin_unlock_irqrestore(shost->host_lock, flags);3502 3503	if (create) {3504		/*3505		 * There may have been a delete timer running on the3506		 * port. Ensure that it is cancelled as we now know3507		 * the port is an FCP Target.3508		 * Note: we know the rport exists and is in an online3509		 *  state as the LLDD would not have had an rport3510		 *  reference to pass us.3511		 *3512		 * Take no action on the del_timer failure as the state3513		 * machine state change will validate the3514		 * transaction.3515		 */3516		if (!cancel_delayed_work(&rport->fail_io_work))3517			fc_flush_devloss(shost);3518		if (!cancel_delayed_work(&rport->dev_loss_work))3519			fc_flush_devloss(shost);3520 3521		spin_lock_irqsave(shost->host_lock, flags);3522		rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |3523				  FC_RPORT_DEVLOSS_PENDING |3524				  FC_RPORT_DEVLOSS_CALLBK_DONE);3525		spin_unlock_irqrestore(shost->host_lock, flags);3526 3527		/* ensure any stgt delete functions are done */3528		fc_flush_work(shost);3529 3530		scsi_target_unblock(&rport->dev, SDEV_RUNNING);3531		/* initiate a scan of the target */3532		spin_lock_irqsave(shost->host_lock, flags);3533		rport->flags |= FC_RPORT_SCAN_PENDING;3534		scsi_queue_work(shost, &rport->scan_work);3535		spin_unlock_irqrestore(shost->host_lock, flags);3536	}3537}3538EXPORT_SYMBOL(fc_remote_port_rolechg);3539 3540/**3541 * fc_timeout_deleted_rport - Timeout handler for a deleted remote port.3542 * @work:	rport target that failed to reappear in the allotted time.3543 *3544 * Description: An attempt to delete a remote port blocks, and if it fails3545 *              to return in the allotted time this gets called.3546 */3547static void3548fc_timeout_deleted_rport(struct work_struct *work)3549{3550	struct fc_rport *rport =3551		container_of(work, struct fc_rport, dev_loss_work.work);3552	struct Scsi_Host *shost = rport_to_shost(rport);3553	struct fc_internal *i = to_fc_internal(shost->transportt);3554	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);3555	unsigned long flags;3556	int do_callback = 0;3557 3558	spin_lock_irqsave(shost->host_lock, flags);3559 3560	rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;3561 3562	/*3563	 * If the port is ONLINE, then it came back. If it was a SCSI3564	 * target, validate it still is. If not, tear down the3565	 * scsi_target on it.3566	 */3567	if (((rport->port_state == FC_PORTSTATE_ONLINE) ||3568		(rport->port_state == FC_PORTSTATE_MARGINAL)) &&3569	    (rport->scsi_target_id != -1) &&3570	    !(rport->roles & FC_PORT_ROLE_FCP_TARGET)) {3571		dev_printk(KERN_ERR, &rport->dev,3572			"blocked FC remote port time out: no longer"3573			" a FCP target, removing starget\n");3574		spin_unlock_irqrestore(shost->host_lock, flags);3575		scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE);3576		fc_queue_work(shost, &rport->stgt_delete_work);3577		return;3578	}3579 3580	/* NOOP state - we're flushing workq's */3581	if (rport->port_state != FC_PORTSTATE_BLOCKED) {3582		spin_unlock_irqrestore(shost->host_lock, flags);3583		dev_printk(KERN_ERR, &rport->dev,3584			"blocked FC remote port time out: leaving"3585			" rport%s alone\n",3586			(rport->scsi_target_id != -1) ?  " and starget" : "");3587		return;3588	}3589 3590	if ((fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) ||3591	    (rport->scsi_target_id == -1)) {3592		list_del(&rport->peers);3593		rport->port_state = FC_PORTSTATE_DELETED;3594		dev_printk(KERN_ERR, &rport->dev,3595			"blocked FC remote port time out: removing"3596			" rport%s\n",3597			(rport->scsi_target_id != -1) ?  " and starget" : "");3598		fc_queue_work(shost, &rport->rport_delete_work);3599		spin_unlock_irqrestore(shost->host_lock, flags);3600		return;3601	}3602 3603	dev_printk(KERN_ERR, &rport->dev,3604		"blocked FC remote port time out: removing target and "3605		"saving binding\n");3606 3607	list_move_tail(&rport->peers, &fc_host->rport_bindings);3608 3609	/*3610	 * Note: We do not remove or clear the hostdata area. This allows3611	 *   host-specific target data to persist along with the3612	 *   scsi_target_id. It's up to the host to manage it's hostdata area.3613	 */3614 3615	/*3616	 * Reinitialize port attributes that may change if the port comes back.3617	 */3618	rport->maxframe_size = -1;3619	rport->supported_classes = FC_COS_UNSPECIFIED;3620	rport->roles = FC_PORT_ROLE_UNKNOWN;3621	rport->port_state = FC_PORTSTATE_NOTPRESENT;3622	rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;3623 3624	/*3625	 * Pre-emptively kill I/O rather than waiting for the work queue3626	 * item to teardown the starget. (FCOE libFC folks prefer this3627	 * and to have the rport_port_id still set when it's done).3628	 */3629	spin_unlock_irqrestore(shost->host_lock, flags);3630	fc_terminate_rport_io(rport);3631 3632	spin_lock_irqsave(shost->host_lock, flags);3633 3634	if (rport->port_state == FC_PORTSTATE_NOTPRESENT) {	/* still missing */3635 3636		/* remove the identifiers that aren't used in the consisting binding */3637		switch (fc_host->tgtid_bind_type) {3638		case FC_TGTID_BIND_BY_WWPN:3639			rport->node_name = -1;3640			rport->port_id = -1;3641			break;3642		case FC_TGTID_BIND_BY_WWNN:3643			rport->port_name = -1;3644			rport->port_id = -1;3645			break;3646		case FC_TGTID_BIND_BY_ID:3647			rport->node_name = -1;3648			rport->port_name = -1;3649			break;3650		case FC_TGTID_BIND_NONE:	/* to keep compiler happy */3651			break;3652		}3653 3654		/*3655		 * As this only occurs if the remote port (scsi target)3656		 * went away and didn't come back - we'll remove3657		 * all attached scsi devices.3658		 */3659		rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE;3660		fc_queue_work(shost, &rport->stgt_delete_work);3661 3662		do_callback = 1;3663	}3664 3665	spin_unlock_irqrestore(shost->host_lock, flags);3666 3667	/*3668	 * Notify the driver that the rport is now dead. The LLDD will3669	 * also guarantee that any communication to the rport is terminated3670	 *3671	 * Note: we set the CALLBK_DONE flag above to correspond3672	 */3673	if (do_callback && i->f->dev_loss_tmo_callbk)3674		i->f->dev_loss_tmo_callbk(rport);3675}3676 3677 3678/**3679 * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a disconnected SCSI target.3680 * @work:	rport to terminate io on.3681 *3682 * Notes: Only requests the failure of the io, not that all are flushed3683 *    prior to returning.3684 */3685static void3686fc_timeout_fail_rport_io(struct work_struct *work)3687{3688	struct fc_rport *rport =3689		container_of(work, struct fc_rport, fail_io_work.work);3690 3691	if (rport->port_state != FC_PORTSTATE_BLOCKED)3692		return;3693 3694	rport->flags |= FC_RPORT_FAST_FAIL_TIMEDOUT;3695	fc_terminate_rport_io(rport);3696}3697 3698/**3699 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port.3700 * @work:	remote port to be scanned.3701 */3702static void3703fc_scsi_scan_rport(struct work_struct *work)3704{3705	struct fc_rport *rport =3706		container_of(work, struct fc_rport, scan_work);3707	struct Scsi_Host *shost = rport_to_shost(rport);3708	struct fc_internal *i = to_fc_internal(shost->transportt);3709	unsigned long flags;3710 3711	if (((rport->port_state == FC_PORTSTATE_ONLINE) ||3712		(rport->port_state == FC_PORTSTATE_MARGINAL)) &&3713	    (rport->roles & FC_PORT_ROLE_FCP_TARGET) &&3714	    !(i->f->disable_target_scan)) {3715		scsi_scan_target(&rport->dev, rport->channel,3716				 rport->scsi_target_id, SCAN_WILD_CARD,3717				 SCSI_SCAN_RESCAN);3718	}3719 3720	spin_lock_irqsave(shost->host_lock, flags);3721	rport->flags &= ~FC_RPORT_SCAN_PENDING;3722	spin_unlock_irqrestore(shost->host_lock, flags);3723}3724 3725/**3726 * fc_block_rport() - Block SCSI eh thread for blocked fc_rport.3727 * @rport: Remote port that scsi_eh is trying to recover.3728 *3729 * This routine can be called from a FC LLD scsi_eh callback. It3730 * blocks the scsi_eh thread until the fc_rport leaves the3731 * FC_PORTSTATE_BLOCKED, or the fast_io_fail_tmo fires. This is3732 * necessary to avoid the scsi_eh failing recovery actions for blocked3733 * rports which would lead to offlined SCSI devices.3734 *3735 * Returns: 0 if the fc_rport left the state FC_PORTSTATE_BLOCKED.3736 *	    FAST_IO_FAIL if the fast_io_fail_tmo fired, this should be3737 *	    passed back to scsi_eh.3738 */3739int fc_block_rport(struct fc_rport *rport)3740{3741	struct Scsi_Host *shost = rport_to_shost(rport);3742	unsigned long flags;3743 3744	spin_lock_irqsave(shost->host_lock, flags);3745	while (rport->port_state == FC_PORTSTATE_BLOCKED &&3746	       !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)) {3747		spin_unlock_irqrestore(shost->host_lock, flags);3748		msleep(1000);3749		spin_lock_irqsave(shost->host_lock, flags);3750	}3751	spin_unlock_irqrestore(shost->host_lock, flags);3752 3753	if (rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)3754		return FAST_IO_FAIL;3755 3756	return 0;3757}3758EXPORT_SYMBOL(fc_block_rport);3759 3760/**3761 * fc_block_scsi_eh - Block SCSI eh thread for blocked fc_rport3762 * @cmnd: SCSI command that scsi_eh is trying to recover3763 *3764 * This routine can be called from a FC LLD scsi_eh callback. It3765 * blocks the scsi_eh thread until the fc_rport leaves the3766 * FC_PORTSTATE_BLOCKED, or the fast_io_fail_tmo fires. This is3767 * necessary to avoid the scsi_eh failing recovery actions for blocked3768 * rports which would lead to offlined SCSI devices.3769 *3770 * Returns: 0 if the fc_rport left the state FC_PORTSTATE_BLOCKED.3771 *	    FAST_IO_FAIL if the fast_io_fail_tmo fired, this should be3772 *	    passed back to scsi_eh.3773 */3774int fc_block_scsi_eh(struct scsi_cmnd *cmnd)3775{3776	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));3777 3778	if (WARN_ON_ONCE(!rport))3779		return FAST_IO_FAIL;3780 3781	return fc_block_rport(rport);3782}3783EXPORT_SYMBOL(fc_block_scsi_eh);3784 3785/*3786 * fc_eh_should_retry_cmd - Checks if the cmd should be retried or not3787 * @scmd:        The SCSI command to be checked3788 *3789 * This checks the rport state to decide if a cmd is3790 * retryable.3791 *3792 * Returns: true if the rport state is not in marginal state.3793 */3794bool fc_eh_should_retry_cmd(struct scsi_cmnd *scmd)3795{3796	struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device));3797 3798	if ((rport->port_state != FC_PORTSTATE_ONLINE) &&3799		(scsi_cmd_to_rq(scmd)->cmd_flags & REQ_FAILFAST_TRANSPORT)) {3800		set_host_byte(scmd, DID_TRANSPORT_MARGINAL);3801		return false;3802	}3803	return true;3804}3805EXPORT_SYMBOL_GPL(fc_eh_should_retry_cmd);3806 3807/**3808 * fc_vport_setup - allocates and creates a FC virtual port.3809 * @shost:	scsi host the virtual port is connected to.3810 * @channel:	Channel on shost port connected to.3811 * @pdev:	parent device for vport3812 * @ids:	The world wide names, FC4 port roles, etc for3813 *              the virtual port.3814 * @ret_vport:	The pointer to the created vport.3815 *3816 * Allocates and creates the vport structure, calls the parent host3817 * to instantiate the vport, this completes w/ class and sysfs creation.3818 *3819 * Notes:3820 *	This routine assumes no locks are held on entry.3821 */3822static int3823fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,3824	struct fc_vport_identifiers  *ids, struct fc_vport **ret_vport)3825{3826	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);3827	struct fc_internal *fci = to_fc_internal(shost->transportt);3828	struct fc_vport *vport;3829	struct device *dev;3830	unsigned long flags;3831	size_t size;3832	int error;3833 3834	*ret_vport = NULL;3835 3836	if ( ! fci->f->vport_create)3837		return -ENOENT;3838 3839	size = (sizeof(struct fc_vport) + fci->f->dd_fcvport_size);3840	vport = kzalloc(size, GFP_KERNEL);3841	if (unlikely(!vport)) {3842		printk(KERN_ERR "%s: allocation failure\n", __func__);3843		return -ENOMEM;3844	}3845 3846	vport->vport_state = FC_VPORT_UNKNOWN;3847	vport->vport_last_state = FC_VPORT_UNKNOWN;3848	vport->node_name = ids->node_name;3849	vport->port_name = ids->port_name;3850	vport->roles = ids->roles;3851	vport->vport_type = ids->vport_type;3852	if (fci->f->dd_fcvport_size)3853		vport->dd_data = &vport[1];3854	vport->shost = shost;3855	vport->channel = channel;3856	vport->flags = FC_VPORT_CREATING;3857	INIT_WORK(&vport->vport_delete_work, fc_vport_sched_delete);3858 3859	spin_lock_irqsave(shost->host_lock, flags);3860 3861	if (fc_host->npiv_vports_inuse >= fc_host->max_npiv_vports) {3862		spin_unlock_irqrestore(shost->host_lock, flags);3863		kfree(vport);3864		return -ENOSPC;3865	}3866	fc_host->npiv_vports_inuse++;3867	vport->number = fc_host->next_vport_number++;3868	list_add_tail(&vport->peers, &fc_host->vports);3869	scsi_host_get(shost);			/* for fc_host->vport list */3870 3871	spin_unlock_irqrestore(shost->host_lock, flags);3872 3873	dev = &vport->dev;3874	device_initialize(dev);			/* takes self reference */3875	dev->parent = get_device(pdev);		/* takes parent reference */3876	dev->release = fc_vport_dev_release;3877	dev_set_name(dev, "vport-%d:%d-%d",3878		     shost->host_no, channel, vport->number);3879	transport_setup_device(dev);3880 3881	error = device_add(dev);3882	if (error) {3883		printk(KERN_ERR "FC Virtual Port device_add failed\n");3884		goto delete_vport;3885	}3886	transport_add_device(dev);3887	transport_configure_device(dev);3888 3889	error = fci->f->vport_create(vport, ids->disable);3890	if (error) {3891		printk(KERN_ERR "FC Virtual Port LLDD Create failed\n");3892		goto delete_vport_all;3893	}3894 3895	/*3896	 * if the parent isn't the physical adapter's Scsi_Host, ensure3897	 * the Scsi_Host at least contains a symlink to the vport.3898	 */3899	if (pdev != &shost->shost_gendev) {3900		error = sysfs_create_link(&shost->shost_gendev.kobj,3901				 &dev->kobj, dev_name(dev));3902		if (error)3903			printk(KERN_ERR3904				"%s: Cannot create vport symlinks for "3905				"%s, err=%d\n",3906				__func__, dev_name(dev), error);3907	}3908	spin_lock_irqsave(shost->host_lock, flags);3909	vport->flags &= ~FC_VPORT_CREATING;3910	spin_unlock_irqrestore(shost->host_lock, flags);3911 3912	dev_printk(KERN_NOTICE, pdev,3913			"%s created via shost%d channel %d\n", dev_name(dev),3914			shost->host_no, channel);3915 3916	*ret_vport = vport;3917 3918	return 0;3919 3920delete_vport_all:3921	transport_remove_device(dev);3922	device_del(dev);3923delete_vport:3924	transport_destroy_device(dev);3925	spin_lock_irqsave(shost->host_lock, flags);3926	list_del(&vport->peers);3927	scsi_host_put(shost);			/* for fc_host->vport list */3928	fc_host->npiv_vports_inuse--;3929	spin_unlock_irqrestore(shost->host_lock, flags);3930	put_device(dev->parent);3931	kfree(vport);3932 3933	return error;3934}3935 3936/**3937 * fc_vport_create - Admin App or LLDD requests creation of a vport3938 * @shost:	scsi host the virtual port is connected to.3939 * @channel:	channel on shost port connected to.3940 * @ids:	The world wide names, FC4 port roles, etc for3941 *              the virtual port.3942 *3943 * Notes:3944 *	This routine assumes no locks are held on entry.3945 */3946struct fc_vport *3947fc_vport_create(struct Scsi_Host *shost, int channel,3948	struct fc_vport_identifiers *ids)3949{3950	int stat;3951	struct fc_vport *vport;3952 3953	stat = fc_vport_setup(shost, channel, &shost->shost_gendev,3954		 ids, &vport);3955	return stat ? NULL : vport;3956}3957EXPORT_SYMBOL(fc_vport_create);3958 3959/**3960 * fc_vport_terminate - Admin App or LLDD requests termination of a vport3961 * @vport:	fc_vport to be terminated3962 *3963 * Calls the LLDD vport_delete() function, then deallocates and removes3964 * the vport from the shost and object tree.3965 *3966 * Notes:3967 *	This routine assumes no locks are held on entry.3968 */3969int3970fc_vport_terminate(struct fc_vport *vport)3971{3972	struct Scsi_Host *shost = vport_to_shost(vport);3973	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);3974	struct fc_internal *i = to_fc_internal(shost->transportt);3975	struct device *dev = &vport->dev;3976	unsigned long flags;3977	int stat;3978 3979	if (i->f->vport_delete)3980		stat = i->f->vport_delete(vport);3981	else3982		stat = -ENOENT;3983 3984	spin_lock_irqsave(shost->host_lock, flags);3985	vport->flags &= ~FC_VPORT_DELETING;3986	if (!stat) {3987		vport->flags |= FC_VPORT_DELETED;3988		list_del(&vport->peers);3989		fc_host->npiv_vports_inuse--;3990		scsi_host_put(shost);		/* for fc_host->vport list */3991	}3992	spin_unlock_irqrestore(shost->host_lock, flags);3993 3994	if (stat)3995		return stat;3996 3997	if (dev->parent != &shost->shost_gendev)3998		sysfs_remove_link(&shost->shost_gendev.kobj, dev_name(dev));3999	transport_remove_device(dev);4000	device_del(dev);4001	transport_destroy_device(dev);4002 4003	/*4004	 * Removing our self-reference should mean our4005	 * release function gets called, which will drop the remaining4006	 * parent reference and free the data structure.4007	 */4008	put_device(dev);			/* for self-reference */4009 4010	return 0; /* SUCCESS */4011}4012EXPORT_SYMBOL(fc_vport_terminate);4013 4014/**4015 * fc_vport_sched_delete - workq-based delete request for a vport4016 * @work:	vport to be deleted.4017 */4018static void4019fc_vport_sched_delete(struct work_struct *work)4020{4021	struct fc_vport *vport =4022		container_of(work, struct fc_vport, vport_delete_work);4023	int stat;4024 4025	stat = fc_vport_terminate(vport);4026	if (stat)4027		dev_printk(KERN_ERR, vport->dev.parent,4028			"%s: %s could not be deleted created via "4029			"shost%d channel %d - error %d\n", __func__,4030			dev_name(&vport->dev), vport->shost->host_no,4031			vport->channel, stat);4032}4033 4034 4035/*4036 * BSG support4037 */4038 4039/**4040 * fc_bsg_job_timeout - handler for when a bsg request timesout4041 * @req:	request that timed out4042 */4043static enum blk_eh_timer_return4044fc_bsg_job_timeout(struct request *req)4045{4046	struct bsg_job *job = blk_mq_rq_to_pdu(req);4047	struct Scsi_Host *shost = fc_bsg_to_shost(job);4048	struct fc_rport *rport = fc_bsg_to_rport(job);4049	struct fc_internal *i = to_fc_internal(shost->transportt);4050	int err = 0, inflight = 0;4051 4052	if (rport && rport->port_state == FC_PORTSTATE_BLOCKED)4053		return BLK_EH_RESET_TIMER;4054 4055	inflight = bsg_job_get(job);4056 4057	if (inflight && i->f->bsg_timeout) {4058		/* call LLDD to abort the i/o as it has timed out */4059		err = i->f->bsg_timeout(job);4060		if (err == -EAGAIN) {4061			bsg_job_put(job);4062			return BLK_EH_RESET_TIMER;4063		} else if (err)4064			printk(KERN_ERR "ERROR: FC BSG request timeout - LLD "4065				"abort failed with status %d\n", err);4066	}4067 4068	/* the blk_end_sync_io() doesn't check the error */4069	if (inflight)4070		blk_mq_end_request(req, BLK_STS_IOERR);4071	return BLK_EH_DONE;4072}4073 4074/**4075 * fc_bsg_host_dispatch - process fc host bsg requests and dispatch to LLDD4076 * @shost:	scsi host rport attached to4077 * @job:	bsg job to be processed4078 */4079static int fc_bsg_host_dispatch(struct Scsi_Host *shost, struct bsg_job *job)4080{4081	struct fc_internal *i = to_fc_internal(shost->transportt);4082	struct fc_bsg_request *bsg_request = job->request;4083	struct fc_bsg_reply *bsg_reply = job->reply;4084	int cmdlen = sizeof(uint32_t);	/* start with length of msgcode */4085	int ret;4086 4087	/* check if we really have all the request data needed */4088	if (job->request_len < cmdlen) {4089		ret = -ENOMSG;4090		goto fail_host_msg;4091	}4092 4093	/* Validate the host command */4094	switch (bsg_request->msgcode) {4095	case FC_BSG_HST_ADD_RPORT:4096		cmdlen += sizeof(struct fc_bsg_host_add_rport);4097		break;4098 4099	case FC_BSG_HST_DEL_RPORT:4100		cmdlen += sizeof(struct fc_bsg_host_del_rport);4101		break;4102 4103	case FC_BSG_HST_ELS_NOLOGIN:4104		cmdlen += sizeof(struct fc_bsg_host_els);4105		/* there better be a xmt and rcv payloads */4106		if ((!job->request_payload.payload_len) ||4107		    (!job->reply_payload.payload_len)) {4108			ret = -EINVAL;4109			goto fail_host_msg;4110		}4111		break;4112 4113	case FC_BSG_HST_CT:4114		cmdlen += sizeof(struct fc_bsg_host_ct);4115		/* there better be xmt and rcv payloads */4116		if ((!job->request_payload.payload_len) ||4117		    (!job->reply_payload.payload_len)) {4118			ret = -EINVAL;4119			goto fail_host_msg;4120		}4121		break;4122 4123	case FC_BSG_HST_VENDOR:4124		cmdlen += sizeof(struct fc_bsg_host_vendor);4125		if ((shost->hostt->vendor_id == 0L) ||4126		    (bsg_request->rqst_data.h_vendor.vendor_id !=4127			shost->hostt->vendor_id)) {4128			ret = -ESRCH;4129			goto fail_host_msg;4130		}4131		break;4132 4133	default:4134		ret = -EBADR;4135		goto fail_host_msg;4136	}4137 4138	ret = i->f->bsg_request(job);4139	if (!ret)4140		return 0;4141 4142fail_host_msg:4143	/* return the errno failure code as the only status */4144	BUG_ON(job->reply_len < sizeof(uint32_t));4145	bsg_reply->reply_payload_rcv_len = 0;4146	bsg_reply->result = ret;4147	job->reply_len = sizeof(uint32_t);4148	bsg_job_done(job, bsg_reply->result,4149		       bsg_reply->reply_payload_rcv_len);4150	return 0;4151}4152 4153 4154/*4155 * fc_bsg_goose_queue - restart rport queue in case it was stopped4156 * @rport:	rport to be restarted4157 */4158static void4159fc_bsg_goose_queue(struct fc_rport *rport)4160{4161	struct request_queue *q = rport->rqst_q;4162 4163	if (q)4164		blk_mq_run_hw_queues(q, true);4165}4166 4167/**4168 * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD4169 * @shost:	scsi host rport attached to4170 * @job:	bsg job to be processed4171 */4172static int fc_bsg_rport_dispatch(struct Scsi_Host *shost, struct bsg_job *job)4173{4174	struct fc_internal *i = to_fc_internal(shost->transportt);4175	struct fc_bsg_request *bsg_request = job->request;4176	struct fc_bsg_reply *bsg_reply = job->reply;4177	int cmdlen = sizeof(uint32_t);	/* start with length of msgcode */4178	int ret;4179 4180	/* check if we really have all the request data needed */4181	if (job->request_len < cmdlen) {4182		ret = -ENOMSG;4183		goto fail_rport_msg;4184	}4185 4186	/* Validate the rport command */4187	switch (bsg_request->msgcode) {4188	case FC_BSG_RPT_ELS:4189		cmdlen += sizeof(struct fc_bsg_rport_els);4190		goto check_bidi;4191 4192	case FC_BSG_RPT_CT:4193		cmdlen += sizeof(struct fc_bsg_rport_ct);4194check_bidi:4195		/* there better be xmt and rcv payloads */4196		if ((!job->request_payload.payload_len) ||4197		    (!job->reply_payload.payload_len)) {4198			ret = -EINVAL;4199			goto fail_rport_msg;4200		}4201		break;4202	default:4203		ret = -EBADR;4204		goto fail_rport_msg;4205	}4206 4207	ret = i->f->bsg_request(job);4208	if (!ret)4209		return 0;4210 4211fail_rport_msg:4212	/* return the errno failure code as the only status */4213	BUG_ON(job->reply_len < sizeof(uint32_t));4214	bsg_reply->reply_payload_rcv_len = 0;4215	bsg_reply->result = ret;4216	job->reply_len = sizeof(uint32_t);4217	bsg_job_done(job, bsg_reply->result,4218		       bsg_reply->reply_payload_rcv_len);4219	return 0;4220}4221 4222static int fc_bsg_dispatch(struct bsg_job *job)4223{4224	struct Scsi_Host *shost = fc_bsg_to_shost(job);4225 4226	if (scsi_is_fc_rport(job->dev))4227		return fc_bsg_rport_dispatch(shost, job);4228	else4229		return fc_bsg_host_dispatch(shost, job);4230}4231 4232static blk_status_t fc_bsg_rport_prep(struct fc_rport *rport)4233{4234	if (rport->port_state == FC_PORTSTATE_BLOCKED &&4235	    !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT))4236		return BLK_STS_RESOURCE;4237 4238	if ((rport->port_state != FC_PORTSTATE_ONLINE) &&4239		(rport->port_state != FC_PORTSTATE_MARGINAL))4240		return BLK_STS_IOERR;4241 4242	return BLK_STS_OK;4243}4244 4245 4246static int fc_bsg_dispatch_prep(struct bsg_job *job)4247{4248	struct fc_rport *rport = fc_bsg_to_rport(job);4249	blk_status_t ret;4250 4251	ret = fc_bsg_rport_prep(rport);4252	switch (ret) {4253	case BLK_STS_OK:4254		break;4255	case BLK_STS_RESOURCE:4256		return -EAGAIN;4257	default:4258		return -EIO;4259	}4260 4261	return fc_bsg_dispatch(job);4262}4263 4264/**4265 * fc_bsg_hostadd - Create and add the bsg hooks so we can receive requests4266 * @shost:	shost for fc_host4267 * @fc_host:	fc_host adding the structures to4268 */4269static int4270fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)4271{4272	struct device *dev = &shost->shost_gendev;4273	struct fc_internal *i = to_fc_internal(shost->transportt);4274	struct queue_limits lim;4275	struct request_queue *q;4276	char bsg_name[20];4277 4278	fc_host->rqst_q = NULL;4279 4280	if (!i->f->bsg_request)4281		return -ENOTSUPP;4282 4283	snprintf(bsg_name, sizeof(bsg_name),4284		 "fc_host%d", shost->host_no);4285	scsi_init_limits(shost, &lim);4286	lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);4287	q = bsg_setup_queue(dev, bsg_name, &lim, fc_bsg_dispatch,4288			fc_bsg_job_timeout, i->f->dd_bsg_size);4289	if (IS_ERR(q)) {4290		dev_err(dev,4291			"fc_host%d: bsg interface failed to initialize - setup queue\n",4292			shost->host_no);4293		return PTR_ERR(q);4294	}4295	blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT);4296	fc_host->rqst_q = q;4297	return 0;4298}4299 4300/**4301 * fc_bsg_rportadd - Create and add the bsg hooks so we can receive requests4302 * @shost:	shost that rport is attached to4303 * @rport:	rport that the bsg hooks are being attached to4304 */4305static int4306fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport)4307{4308	struct device *dev = &rport->dev;4309	struct fc_internal *i = to_fc_internal(shost->transportt);4310	struct queue_limits lim;4311	struct request_queue *q;4312 4313	rport->rqst_q = NULL;4314 4315	if (!i->f->bsg_request)4316		return -ENOTSUPP;4317 4318	scsi_init_limits(shost, &lim);4319	lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);4320	q = bsg_setup_queue(dev, dev_name(dev), &lim, fc_bsg_dispatch_prep,4321				fc_bsg_job_timeout, i->f->dd_bsg_size);4322	if (IS_ERR(q)) {4323		dev_err(dev, "failed to setup bsg queue\n");4324		return PTR_ERR(q);4325	}4326	blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);4327	rport->rqst_q = q;4328	return 0;4329}4330 4331 4332/**4333 * fc_bsg_remove - Deletes the bsg hooks on fchosts/rports4334 * @q:	the request_queue that is to be torn down.4335 *4336 * Notes:4337 *   Before unregistering the queue empty any requests that are blocked4338 *4339 *4340 */4341static void4342fc_bsg_remove(struct request_queue *q)4343{4344	bsg_remove_queue(q);4345}4346 4347 4348/* Original Author:  Martin Hicks */4349MODULE_AUTHOR("James Smart");4350MODULE_DESCRIPTION("FC Transport Attributes");4351MODULE_LICENSE("GPL");4352 4353module_init(fc_transport_init);4354module_exit(fc_transport_exit);4355