linux/drivers/scsi/scsi_transport_fc.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  FiberChannel transport specific attributes exported to sysfs.
 *
 *  Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
 *  Copyright (C) 2004-2007   James Smart, Emulex Corporation
 *    Rewrite for host, target, device, and remote port attributes,
 *    statistics, and service functions...
 *    Add vports, etc
 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/bsg-lib.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_cmnd.h>
#include <net/netlink.h>
#include <scsi/scsi_netlink_fc.h>
#include <scsi/scsi_bsg_fc.h>
#include <uapi/scsi/fc/fc_els.h>
#include "scsi_priv.h"

static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
static void fc_vport_sched_delete(struct work_struct *work);
static int fc_vport_setup(struct Scsi_Host *shost, int channel,
	struct device *pdev, struct fc_vport_identifiers  *ids,
	struct fc_vport **vport);
static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *);
static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *);
static void fc_bsg_remove(struct request_queue *);
static void fc_bsg_goose_queue(struct fc_rport *);
static void fc_li_stats_update(u16 event_type,
			       struct fc_fpin_stats *stats);
static void fc_delivery_stats_update(u32 reason_code,
				     struct fc_fpin_stats *stats);
static void fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats);

/*
 * Module Parameters
 */

/*
 * dev_loss_tmo: the default number of seconds that the FC transport
 *   should insulate the loss of a remote port.
 *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
 */
static unsigned int fc_dev_loss_tmo =;		/* seconds */

module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

/*
 * Redefine so that we can have same named attributes in the
 * sdev/starget/host objects.
 */
#define FC_DEVICE_ATTR(_prefix,_name,_mode,_show,_store)

#define fc_enum_name_search(title, table_type, table)

#define fc_enum_name_match(title, table_type, table)


/* Convert fc_port_type values to ascii string name */
static struct {} fc_port_type_names[] =;
fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
#define FC_PORTTYPE_MAX_NAMELEN

/* Reuse fc_port_type enum function for vport_type */
#define get_fc_vport_type_name


/* Convert fc_host_event_code values to ascii string name */
static const struct {} fc_host_event_code_names[] =;
fc_enum_name_search(host_event_code, fc_host_event_code,
		fc_host_event_code_names)
#define FC_HOST_EVENT_CODE_MAX_NAMELEN


/* Convert fc_port_state values to ascii string name */
static struct {} fc_port_state_names[] =;
fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
fc_enum_name_match(port_state, fc_port_state, fc_port_state_names)
#define FC_PORTSTATE_MAX_NAMELEN


/* Convert fc_vport_state values to ascii string name */
static struct {} fc_vport_state_names[] =;
fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names)
#define FC_VPORTSTATE_MAX_NAMELEN

/* Reuse fc_vport_state enum function for vport_last_state */
#define get_fc_vport_last_state_name


/* Convert fc_tgtid_binding_type values to ascii string name */
static const struct {} fc_tgtid_binding_type_names[] =;
fc_enum_name_search(tgtid_bind_type, fc_tgtid_binding_type,
		fc_tgtid_binding_type_names)
fc_enum_name_match(tgtid_bind_type, fc_tgtid_binding_type,
		fc_tgtid_binding_type_names)
#define FC_BINDTYPE_MAX_NAMELEN


#define fc_bitfield_name_search(title, table)


/* Convert FC_COS bit values to ascii string name */
static const struct {} fc_cos_names[] =;
fc_bitfield_name_search(cos, fc_cos_names)


/* Convert FC_PORTSPEED bit values to ascii string name */
static const struct {} fc_port_speed_names[] =;
fc_bitfield_name_search(port_speed, fc_port_speed_names)


static int
show_fc_fc4s (char *buf, u8 *fc4_list)
{}


/* Convert FC_PORT_ROLE bit values to ascii string name */
static const struct {} fc_port_role_names[] =;
fc_bitfield_name_search(port_roles, fc_port_role_names)

/*
 * Define roles that are specific to port_id. Values are relative to ROLE_MASK.
 */
#define FC_WELLKNOWN_PORTID_MASK
#define FC_WELLKNOWN_ROLE_MASK
#define FC_FPORT_PORTID
#define FC_FABCTLR_PORTID
#define FC_DIRSRVR_PORTID
#define FC_TIMESRVR_PORTID
#define FC_MGMTSRVR_PORTID


static void fc_timeout_deleted_rport(struct work_struct *work);
static void fc_timeout_fail_rport_io(struct work_struct *work);
static void fc_scsi_scan_rport(struct work_struct *work);

/*
 * Attribute counts pre object type...
 * Increase these values if you add attributes
 */
#define FC_STARGET_NUM_ATTRS
#define FC_RPORT_NUM_ATTRS
#define FC_VPORT_NUM_ATTRS
#define FC_HOST_NUM_ATTRS

struct fc_internal {};

#define to_fc_internal(tmpl)

static int fc_target_setup(struct transport_container *tc, struct device *dev,
			   struct device *cdev)
{}

static DECLARE_TRANSPORT_CLASS(fc_transport_class,
			       "fc_transport",
			       fc_target_setup,
			       NULL,
			       NULL);

static int fc_host_setup(struct transport_container *tc, struct device *dev,
			 struct device *cdev)
{}

static int fc_host_remove(struct transport_container *tc, struct device *dev,
			 struct device *cdev)
{}

static DECLARE_TRANSPORT_CLASS(fc_host_class,
			       "fc_host",
			       fc_host_setup,
			       fc_host_remove,
			       NULL);

/*
 * Setup and Remove actions for remote ports are handled
 * in the service functions below.
 */
static DECLARE_TRANSPORT_CLASS(fc_rport_class,
			       "fc_remote_ports",
			       NULL,
			       NULL,
			       NULL);

/*
 * Setup and Remove actions for virtual ports are handled
 * in the service functions below.
 */
static DECLARE_TRANSPORT_CLASS(fc_vport_class,
			       "fc_vports",
			       NULL,
			       NULL,
			       NULL);

/*
 * Netlink Infrastructure
 */

static atomic_t fc_event_seq;

/**
 * fc_get_event_number - Obtain the next sequential FC event number
 *
 * Notes:
 *   We could have inlined this, but it would have required fc_event_seq to
 *   be exposed. For now, live with the subroutine call.
 *   Atomic used to avoid lock/unlock...
 */
u32
fc_get_event_number(void)
{}
EXPORT_SYMBOL();

/**
 * fc_host_post_fc_event - routine to do the work of posting an event
 *                      on an fc_host.
 * @shost:		host the event occurred on
 * @event_number:	fc event number obtained from get_fc_event_number()
 * @event_code:		fc_host event being posted
 * @data_len:		amount, in bytes, of event data
 * @data_buf:		pointer to event data
 * @vendor_id:          value for Vendor id
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
void
fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number,
		enum fc_host_event_code event_code,
		u32 data_len, char *data_buf, u64 vendor_id)
{}
EXPORT_SYMBOL();

/**
 * fc_host_post_event - called to post an even on an fc_host.
 * @shost:		host the event occurred on
 * @event_number:	fc event number obtained from get_fc_event_number()
 * @event_code:		fc_host event being posted
 * @event_data:		32bits of data for the event being posted
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
void
fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
		enum fc_host_event_code event_code, u32 event_data)
{}
EXPORT_SYMBOL();


/**
 * fc_host_post_vendor_event - called to post a vendor unique event
 *                      on an fc_host
 * @shost:		host the event occurred on
 * @event_number:	fc event number obtained from get_fc_event_number()
 * @data_len:		amount, in bytes, of vendor unique data
 * @data_buf:		pointer to vendor unique data
 * @vendor_id:          Vendor id
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
void
fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
		u32 data_len, char * data_buf, u64 vendor_id)
{}
EXPORT_SYMBOL();

/**
 * fc_find_rport_by_wwpn - find the fc_rport pointer for a given wwpn
 * @shost:		host the fc_rport is associated with
 * @wwpn:		wwpn of the fc_rport device
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
struct fc_rport *
fc_find_rport_by_wwpn(struct Scsi_Host *shost, u64 wwpn)
{}
EXPORT_SYMBOL();

static void
fc_li_stats_update(u16 event_type,
		   struct fc_fpin_stats *stats)
{}

static void
fc_delivery_stats_update(u32 reason_code, struct fc_fpin_stats *stats)
{}

static void
fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats)
{}

/*
 * fc_fpin_li_stats_update - routine to update Link Integrity
 * event statistics.
 * @shost:		host the FPIN was received on
 * @tlv:		pointer to link integrity descriptor
 *
 */
static void
fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
{}

/*
 * fc_fpin_delivery_stats_update - routine to update Delivery Notification
 * event statistics.
 * @shost:		host the FPIN was received on
 * @tlv:		pointer to delivery descriptor
 *
 */
static void
fc_fpin_delivery_stats_update(struct Scsi_Host *shost,
			      struct fc_tlv_desc *tlv)
{}

/*
 * fc_fpin_peer_congn_stats_update - routine to update Peer Congestion
 * event statistics.
 * @shost:		host the FPIN was received on
 * @tlv:		pointer to peer congestion descriptor
 *
 */
static void
fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost,
				struct fc_tlv_desc *tlv)
{}

/*
 * fc_fpin_congn_stats_update - routine to update Congestion
 * event statistics.
 * @shost:		host the FPIN was received on
 * @tlv:		pointer to congestion descriptor
 *
 */
static void
fc_fpin_congn_stats_update(struct Scsi_Host *shost,
			   struct fc_tlv_desc *tlv)
{}

/**
 * fc_host_fpin_rcv - routine to process a received FPIN.
 * @shost:		host the FPIN was received on
 * @fpin_len:		length of FPIN payload, in bytes
 * @fpin_buf:		pointer to FPIN payload
 * @event_acknowledge:	1, if LLDD handles this event.
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
void
fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf,
		u8 event_acknowledge)
{}
EXPORT_SYMBOL();


static __init int fc_transport_init(void)
{}

static void __exit fc_transport_exit(void)
{}

/*
 * FC Remote Port Attribute Management
 */

#define fc_rport_show_function(field, format_string, sz, cast)

#define fc_rport_store_function(field)

#define fc_rport_rd_attr(field, format_string, sz)

#define fc_rport_rd_attr_cast(field, format_string, sz, cast)

#define fc_rport_rw_attr(field, format_string, sz)


#define fc_private_rport_show_function(field, format_string, sz, cast)

#define fc_private_rport_rd_attr(field, format_string, sz)

#define fc_private_rport_rd_attr_cast(field, format_string, sz, cast)


#define fc_private_rport_rd_enum_attr(title, maxlen)


#define SETUP_RPORT_ATTRIBUTE_RD(field)

#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(field)

#define SETUP_RPORT_ATTRIBUTE_RW(field)

#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(field)


/* The FC Transport Remote Port Attributes: */

/* Fixed Remote Port Attributes */

fc_private_rport_rd_attr();

static ssize_t
show_fc_rport_supported_classes (struct device *dev,
				 struct device_attribute *attr, char *buf)
{}
static FC_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
		show_fc_rport_supported_classes, NULL);

/* Dynamic Remote Port Attributes */

/*
 * dev_loss_tmo attribute
 */
static int fc_str_to_dev_loss(const char *buf, unsigned long *val)
{}

static int fc_rport_set_dev_loss_tmo(struct fc_rport *rport,
				     unsigned long val)
{}

fc_rport_show_function()
static ssize_t
store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
			    const char *buf, size_t count)
{}
static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
		show_fc_rport_dev_loss_tmo, store_fc_rport_dev_loss_tmo);


/* Private Remote Port Attributes */

fc_private_rport_rd_attr_cast();
fc_private_rport_rd_attr_cast();
fc_private_rport_rd_attr();

static ssize_t
show_fc_rport_roles (struct device *dev, struct device_attribute *attr,
		     char *buf)
{}
static FC_DEVICE_ATTR(rport, roles, S_IRUGO,
		show_fc_rport_roles, NULL);

static ssize_t fc_rport_set_marginal_state(struct device *dev,
						struct device_attribute *attr,
						const char *buf, size_t count)
{}

static ssize_t
show_fc_rport_port_state(struct device *dev,
				struct device_attribute *attr, char *buf)
{}

static FC_DEVICE_ATTR(rport, port_state, 0444 | 0200,
			show_fc_rport_port_state, fc_rport_set_marginal_state);

fc_private_rport_rd_attr();

/*
 * fast_io_fail_tmo attribute
 */
static ssize_t
show_fc_rport_fast_io_fail_tmo (struct device *dev,
				struct device_attribute *attr, char *buf)
{}

static ssize_t
store_fc_rport_fast_io_fail_tmo(struct device *dev,
				struct device_attribute *attr, const char *buf,
				size_t count)
{}
static FC_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
	show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);

#define fc_rport_fpin_statistic(name)

fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();
fc_rport_fpin_statistic();

static struct attribute *fc_rport_statistics_attrs[] =;

static struct attribute_group fc_rport_statistics_group =;


/*
 * FC SCSI Target Attribute Management
 */

/*
 * Note: in the target show function we recognize when the remote
 *  port is in the hierarchy and do not allow the driver to get
 *  involved in sysfs functions. The driver only gets involved if
 *  it's the "old" style that doesn't use rports.
 */
#define fc_starget_show_function(field, format_string, sz, cast)

#define fc_starget_rd_attr(field, format_string, sz)

#define fc_starget_rd_attr_cast(field, format_string, sz, cast)

#define SETUP_STARGET_ATTRIBUTE_RD(field)

#define SETUP_STARGET_ATTRIBUTE_RW(field)

/* The FC Transport SCSI Target Attributes: */
fc_starget_rd_attr_cast();
fc_starget_rd_attr_cast();
fc_starget_rd_attr();


/*
 * FC Virtual Port Attribute Management
 */

#define fc_vport_show_function(field, format_string, sz, cast)

#define fc_vport_store_function(field)

#define fc_vport_store_str_function(field, slen)

#define fc_vport_rd_attr(field, format_string, sz)

#define fc_vport_rd_attr_cast(field, format_string, sz, cast)

#define fc_vport_rw_attr(field, format_string, sz)

#define fc_private_vport_show_function(field, format_string, sz, cast)

#define fc_private_vport_store_u32_function(field)


#define fc_private_vport_rd_attr(field, format_string, sz)

#define fc_private_vport_rd_attr_cast(field, format_string, sz, cast)

#define fc_private_vport_rw_u32_attr(field, format_string, sz)


#define fc_private_vport_rd_enum_attr(title, maxlen)


#define SETUP_VPORT_ATTRIBUTE_RD(field)
	/* NOTE: Above MACRO differs: checks function not show bit */

#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field)

#define SETUP_VPORT_ATTRIBUTE_WR(field)
	/* NOTE: Above MACRO differs: checks function */

#define SETUP_VPORT_ATTRIBUTE_RW(field)
	/* NOTE: Above MACRO differs: does not check show bit */

#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field)


/* The FC Transport Virtual Port Attributes: */

/* Fixed Virtual Port Attributes */

/* Dynamic Virtual Port Attributes */

/* Private Virtual Port Attributes */

fc_private_vport_rd_enum_attr();
fc_private_vport_rd_enum_attr();
fc_private_vport_rd_attr_cast();
fc_private_vport_rd_attr_cast();

static ssize_t
show_fc_vport_roles (struct device *dev, struct device_attribute *attr,
		     char *buf)
{}
static FC_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);

fc_private_vport_rd_enum_attr();

fc_private_vport_show_function()
fc_vport_store_str_function()
static FC_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
		show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);

static ssize_t
store_fc_vport_delete(struct device *dev, struct device_attribute *attr,
		      const char *buf, size_t count)
{}
static FC_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
			NULL, store_fc_vport_delete);


/*
 * Enable/Disable vport
 *  Write "1" to disable, write "0" to enable
 */
static ssize_t
store_fc_vport_disable(struct device *dev, struct device_attribute *attr,
		       const char *buf,
			   size_t count)
{}
static FC_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
			NULL, store_fc_vport_disable);


/*
 * Host Attribute Management
 */

#define fc_host_show_function(field, format_string, sz, cast)

#define fc_host_store_function(field)

#define fc_host_store_str_function(field, slen)

#define fc_host_rd_attr(field, format_string, sz)

#define fc_host_rd_attr_cast(field, format_string, sz, cast)

#define fc_host_rw_attr(field, format_string, sz)

#define fc_host_rd_enum_attr(title, maxlen)

#define SETUP_HOST_ATTRIBUTE_RD(field)

#define SETUP_HOST_ATTRIBUTE_RD_NS(field)

#define SETUP_HOST_ATTRIBUTE_RW(field)


#define fc_private_host_show_function(field, format_string, sz, cast)

#define fc_private_host_rd_attr(field, format_string, sz)

#define fc_private_host_rd_attr_cast(field, format_string, sz, cast)

#define SETUP_PRIVATE_HOST_ATTRIBUTE_RD(field)

#define SETUP_PRIVATE_HOST_ATTRIBUTE_RW(field)


/* Fixed Host Attributes */

static ssize_t
show_fc_host_supported_classes (struct device *dev,
			        struct device_attribute *attr, char *buf)
{}
static FC_DEVICE_ATTR(host, supported_classes, S_IRUGO,
		show_fc_host_supported_classes, NULL);

static ssize_t
show_fc_host_supported_fc4s (struct device *dev,
			     struct device_attribute *attr, char *buf)
{}
static FC_DEVICE_ATTR(host, supported_fc4s, S_IRUGO,
		show_fc_host_supported_fc4s, NULL);

static ssize_t
show_fc_host_supported_speeds (struct device *dev,
			       struct device_attribute *attr, char *buf)
{}
static FC_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
		show_fc_host_supported_speeds, NULL);


fc_private_host_rd_attr_cast();
fc_private_host_rd_attr_cast();
fc_private_host_rd_attr_cast();
fc_private_host_rd_attr();
fc_private_host_rd_attr();
fc_private_host_rd_attr();
fc_private_host_rd_attr();
fc_private_host_rd_attr();
fc_private_host_rd_attr();
fc_private_host_rd_attr();
fc_private_host_rd_attr();
fc_private_host_rd_attr();
fc_private_host_rd_attr();


/* Dynamic Host Attributes */

static ssize_t
show_fc_host_active_fc4s (struct device *dev,
			  struct device_attribute *attr, char *buf)
{}
static FC_DEVICE_ATTR(host, active_fc4s, S_IRUGO,
		show_fc_host_active_fc4s, NULL);

static ssize_t
show_fc_host_speed (struct device *dev,
		    struct device_attribute *attr, char *buf)
{}
static FC_DEVICE_ATTR(host, speed, S_IRUGO,
		show_fc_host_speed, NULL);


fc_host_rd_attr();
fc_host_rd_enum_attr();
fc_host_rd_enum_attr();
fc_host_rd_attr_cast();
fc_host_rd_attr();

fc_private_host_show_function()
fc_host_store_str_function()
static FC_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR,
		show_fc_host_system_hostname, store_fc_host_system_hostname);


/* Private Host Attributes */

static ssize_t
show_fc_private_host_tgtid_bind_type(struct device *dev,
				     struct device_attribute *attr, char *buf)
{}

#define get_list_head_entry(pos, head, member)

static ssize_t
store_fc_private_host_tgtid_bind_type(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{}

static FC_DEVICE_ATTR(host, tgtid_bind_type, S_IRUGO | S_IWUSR,
			show_fc_private_host_tgtid_bind_type,
			store_fc_private_host_tgtid_bind_type);

static ssize_t
store_fc_private_host_issue_lip(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{}

static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
			store_fc_private_host_issue_lip);

static ssize_t
store_fc_private_host_dev_loss_tmo(struct device *dev,
				   struct device_attribute *attr,
				   const char *buf, size_t count)
{}

fc_private_host_show_function(dev_loss_tmo, "%d\n", 20, );
static FC_DEVICE_ATTR(host, dev_loss_tmo, S_IRUGO | S_IWUSR,
		      show_fc_host_dev_loss_tmo,
		      store_fc_private_host_dev_loss_tmo);

fc_private_host_rd_attr();

/*
 * Host Statistics Management
 */

/* Show a given attribute in the statistics group */
static ssize_t
fc_stat_show(const struct device *dev, char *buf, unsigned long offset)
{}


/* generate a read-only statistics attribute */
#define fc_host_statistic(name)

fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();
fc_host_statistic();


#define fc_host_fpin_statistic(name)

fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();
fc_host_fpin_statistic();

static ssize_t
fc_reset_statistics(struct device *dev, struct device_attribute *attr,
		    const char *buf, size_t count)
{}
static FC_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
				fc_reset_statistics);

static struct attribute *fc_statistics_attrs[] =;

static struct attribute_group fc_statistics_group =;


/* Host Vport Attributes */

static int
fc_parse_wwn(const char *ns, u64 *nm)
{}


/*
 * "Short-cut" sysfs variable to create a new vport on a FC Host.
 * Input is a string of the form "<WWPN>:<WWNN>". Other attributes
 * will default to a NPIV-based FCP_Initiator; The WWNs are specified
 * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
 */
static ssize_t
store_fc_host_vport_create(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t count)
{}
static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
			store_fc_host_vport_create);


/*
 * "Short-cut" sysfs variable to delete a vport on a FC Host.
 * Vport is identified by a string containing "<WWPN>:<WWNN>".
 * The WWNs are specified as hex characters, and may *not* contain
 * any prefixes (e.g. 0x, x, etc)
 */
static ssize_t
store_fc_host_vport_delete(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t count)
{}
static FC_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
			store_fc_host_vport_delete);


static int fc_host_match(struct attribute_container *cont,
			  struct device *dev)
{}

static int fc_target_match(struct attribute_container *cont,
			    struct device *dev)
{}

static void fc_rport_dev_release(struct device *dev)
{}

int scsi_is_fc_rport(const struct device *dev)
{}
EXPORT_SYMBOL();

static int fc_rport_match(struct attribute_container *cont,
			    struct device *dev)
{}


static void fc_vport_dev_release(struct device *dev)
{}

static int scsi_is_fc_vport(const struct device *dev)
{}

static int fc_vport_match(struct attribute_container *cont,
			    struct device *dev)
{}


/**
 * fc_eh_timed_out - FC Transport I/O timeout intercept handler
 * @scmd:	The SCSI command which timed out
 *
 * This routine protects against error handlers getting invoked while a
 * rport is in a blocked state, typically due to a temporarily loss of
 * connectivity. If the error handlers are allowed to proceed, requests
 * to abort i/o, reset the target, etc will likely fail as there is no way
 * to communicate with the device to perform the requested function. These
 * failures may result in the midlayer taking the device offline, requiring
 * manual intervention to restore operation.
 *
 * This routine, called whenever an i/o times out, validates the state of
 * the underlying rport. If the rport is blocked, it returns
 * EH_RESET_TIMER, which will continue to reschedule the timeout.
 * Eventually, either the device will return, or devloss_tmo will fire,
 * and when the timeout then fires, it will be handled normally.
 * If the rport is not blocked, normal error handling continues.
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
enum scsi_timeout_action fc_eh_timed_out(struct scsi_cmnd *scmd)
{}
EXPORT_SYMBOL();

/*
 * Called by fc_user_scan to locate an rport on the shost that
 * matches the channel and target id, and invoke scsi_scan_target()
 * on the rport.
 */
static void
fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, u64 lun)
{}

/*
 * Called via sysfs scan routines. Necessary, as the FC transport
 * wants to place all target objects below the rport object. So this
 * routine must invoke the scsi_scan_target() routine with the rport
 * object as the parent.
 */
static int
fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, u64 lun)
{}

struct scsi_transport_template *
fc_attach_transport(struct fc_function_template *ft)
{}
EXPORT_SYMBOL();

void fc_release_transport(struct scsi_transport_template *t)
{}
EXPORT_SYMBOL();

/**
 * fc_queue_work - Queue work to the fc_host workqueue.
 * @shost:	Pointer to Scsi_Host bound to fc_host.
 * @work:	Work to queue for execution.
 *
 * Return value:
 * 	1 - work queued for execution
 *	0 - work is already queued
 *	-EINVAL - work queue doesn't exist
 */
static int
fc_queue_work(struct Scsi_Host *shost, struct work_struct *work)
{}

/**
 * fc_flush_work - Flush a fc_host's workqueue.
 * @shost:	Pointer to Scsi_Host bound to fc_host.
 */
static void
fc_flush_work(struct Scsi_Host *shost)
{}

/**
 * fc_queue_devloss_work - Schedule work for the fc_host devloss workqueue.
 * @shost:	Pointer to Scsi_Host bound to fc_host.
 * @work:	Work to queue for execution.
 * @delay:	jiffies to delay the work queuing
 *
 * Return value:
 * 	1 on success / 0 already queued / < 0 for error
 */
static int
fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work,
				unsigned long delay)
{}

/**
 * fc_flush_devloss - Flush a fc_host's devloss workqueue.
 * @shost:	Pointer to Scsi_Host bound to fc_host.
 */
static void
fc_flush_devloss(struct Scsi_Host *shost)
{}


/**
 * fc_remove_host - called to terminate any fc_transport-related elements for a scsi host.
 * @shost:	Which &Scsi_Host
 *
 * This routine is expected to be called immediately preceding the
 * a driver's call to scsi_remove_host().
 *
 * WARNING: A driver utilizing the fc_transport, which fails to call
 *   this routine prior to scsi_remove_host(), will leave dangling
 *   objects in /sys/class/fc_remote_ports. Access to any of these
 *   objects can result in a system crash !!!
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
void
fc_remove_host(struct Scsi_Host *shost)
{}
EXPORT_SYMBOL();

static void fc_terminate_rport_io(struct fc_rport *rport)
{}

/**
 * fc_starget_delete - called to delete the scsi descendants of an rport
 * @work:	remote port to be operated on.
 *
 * Deletes target and all sdevs.
 */
static void
fc_starget_delete(struct work_struct *work)
{}


/**
 * fc_rport_final_delete - finish rport termination and delete it.
 * @work:	remote port to be deleted.
 */
static void
fc_rport_final_delete(struct work_struct *work)
{}


/**
 * fc_remote_port_create - allocates and creates a remote FC port.
 * @shost:	scsi host the remote port is connected to.
 * @channel:	Channel on shost port connected to.
 * @ids:	The world wide names, fc address, and FC4 port
 *		roles for the remote port.
 *
 * Allocates and creates the remoter port structure, including the
 * class and sysfs creation.
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
static struct fc_rport *
fc_remote_port_create(struct Scsi_Host *shost, int channel,
		      struct fc_rport_identifiers  *ids)
{}

/**
 * fc_remote_port_add - notify fc transport of the existence of a remote FC port.
 * @shost:	scsi host the remote port is connected to.
 * @channel:	Channel on shost port connected to.
 * @ids:	The world wide names, fc address, and FC4 port
 *		roles for the remote port.
 *
 * The LLDD calls this routine to notify the transport of the existence
 * of a remote port. The LLDD provides the unique identifiers (wwpn,wwn)
 * of the port, it's FC address (port_id), and the FC4 roles that are
 * active for the port.
 *
 * For ports that are FCP targets (aka scsi targets), the FC transport
 * maintains consistent target id bindings on behalf of the LLDD.
 * A consistent target id binding is an assignment of a target id to
 * a remote port identifier, which persists while the scsi host is
 * attached. The remote port can disappear, then later reappear, and
 * it's target id assignment remains the same. This allows for shifts
 * in FC addressing (if binding by wwpn or wwnn) with no apparent
 * changes to the scsi subsystem which is based on scsi host number and
 * target id values.  Bindings are only valid during the attachment of
 * the scsi host. If the host detaches, then later re-attaches, target
 * id bindings may change.
 *
 * This routine is responsible for returning a remote port structure.
 * The routine will search the list of remote ports it maintains
 * internally on behalf of consistent target id mappings. If found, the
 * remote port structure will be reused. Otherwise, a new remote port
 * structure will be allocated.
 *
 * Whenever a remote port is allocated, a new fc_remote_port class
 * device is created.
 *
 * Should not be called from interrupt context.
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
struct fc_rport *
fc_remote_port_add(struct Scsi_Host *shost, int channel,
	struct fc_rport_identifiers  *ids)
{}
EXPORT_SYMBOL();


/**
 * fc_remote_port_delete - notifies the fc transport that a remote port is no longer in existence.
 * @rport:	The remote port that no longer exists
 *
 * The LLDD calls this routine to notify the transport that a remote
 * port is no longer part of the topology. Note: Although a port
 * may no longer be part of the topology, it may persist in the remote
 * ports displayed by the fc_host. We do this under 2 conditions:
 *
 * 1) If the port was a scsi target, we delay its deletion by "blocking" it.
 *    This allows the port to temporarily disappear, then reappear without
 *    disrupting the SCSI device tree attached to it. During the "blocked"
 *    period the port will still exist.
 *
 * 2) If the port was a scsi target and disappears for longer than we
 *    expect, we'll delete the port and the tear down the SCSI device tree
 *    attached to it. However, we want to semi-persist the target id assigned
 *    to that port if it eventually does exist. The port structure will
 *    remain (although with minimal information) so that the target id
 *    bindings also remain.
 *
 * If the remote port is not an FCP Target, it will be fully torn down
 * and deallocated, including the fc_remote_port class device.
 *
 * If the remote port is an FCP Target, the port will be placed in a
 * temporary blocked state. From the LLDD's perspective, the rport no
 * longer exists. From the SCSI midlayer's perspective, the SCSI target
 * exists, but all sdevs on it are blocked from further I/O. The following
 * is then expected.
 *
 *   If the remote port does not return (signaled by a LLDD call to
 *   fc_remote_port_add()) within the dev_loss_tmo timeout, then the
 *   scsi target is removed - killing all outstanding i/o and removing the
 *   scsi devices attached to it. The port structure will be marked Not
 *   Present and be partially cleared, leaving only enough information to
 *   recognize the remote port relative to the scsi target id binding if
 *   it later appears.  The port will remain as long as there is a valid
 *   binding (e.g. until the user changes the binding type or unloads the
 *   scsi host with the binding).
 *
 *   If the remote port returns within the dev_loss_tmo value (and matches
 *   according to the target id binding type), the port structure will be
 *   reused. If it is no longer a SCSI target, the target will be torn
 *   down. If it continues to be a SCSI target, then the target will be
 *   unblocked (allowing i/o to be resumed), and a scan will be activated
 *   to ensure that all luns are detected.
 *
 * Called from normal process context only - cannot be called from interrupt.
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
void
fc_remote_port_delete(struct fc_rport  *rport)
{}
EXPORT_SYMBOL();

/**
 * fc_remote_port_rolechg - notifies the fc transport that the roles on a remote may have changed.
 * @rport:	The remote port that changed.
 * @roles:      New roles for this port.
 *
 * Description: The LLDD calls this routine to notify the transport that the
 * roles on a remote port may have changed. The largest effect of this is
 * if a port now becomes a FCP Target, it must be allocated a
 * scsi target id.  If the port is no longer a FCP target, any
 * scsi target id value assigned to it will persist in case the
 * role changes back to include FCP Target. No changes in the scsi
 * midlayer will be invoked if the role changes (in the expectation
 * that the role will be resumed. If it doesn't normal error processing
 * will take place).
 *
 * Should not be called from interrupt context.
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
void
fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
{}
EXPORT_SYMBOL();

/**
 * fc_timeout_deleted_rport - Timeout handler for a deleted remote port.
 * @work:	rport target that failed to reappear in the allotted time.
 *
 * Description: An attempt to delete a remote port blocks, and if it fails
 *              to return in the allotted time this gets called.
 */
static void
fc_timeout_deleted_rport(struct work_struct *work)
{}


/**
 * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a disconnected SCSI target.
 * @work:	rport to terminate io on.
 *
 * Notes: Only requests the failure of the io, not that all are flushed
 *    prior to returning.
 */
static void
fc_timeout_fail_rport_io(struct work_struct *work)
{}

/**
 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port.
 * @work:	remote port to be scanned.
 */
static void
fc_scsi_scan_rport(struct work_struct *work)
{}

/**
 * fc_block_rport() - Block SCSI eh thread for blocked fc_rport.
 * @rport: Remote port that scsi_eh is trying to recover.
 *
 * This routine can be called from a FC LLD scsi_eh callback. It
 * blocks the scsi_eh thread until the fc_rport leaves the
 * FC_PORTSTATE_BLOCKED, or the fast_io_fail_tmo fires. This is
 * necessary to avoid the scsi_eh failing recovery actions for blocked
 * rports which would lead to offlined SCSI devices.
 *
 * Returns: 0 if the fc_rport left the state FC_PORTSTATE_BLOCKED.
 *	    FAST_IO_FAIL if the fast_io_fail_tmo fired, this should be
 *	    passed back to scsi_eh.
 */
int fc_block_rport(struct fc_rport *rport)
{}
EXPORT_SYMBOL();

/**
 * fc_block_scsi_eh - Block SCSI eh thread for blocked fc_rport
 * @cmnd: SCSI command that scsi_eh is trying to recover
 *
 * This routine can be called from a FC LLD scsi_eh callback. It
 * blocks the scsi_eh thread until the fc_rport leaves the
 * FC_PORTSTATE_BLOCKED, or the fast_io_fail_tmo fires. This is
 * necessary to avoid the scsi_eh failing recovery actions for blocked
 * rports which would lead to offlined SCSI devices.
 *
 * Returns: 0 if the fc_rport left the state FC_PORTSTATE_BLOCKED.
 *	    FAST_IO_FAIL if the fast_io_fail_tmo fired, this should be
 *	    passed back to scsi_eh.
 */
int fc_block_scsi_eh(struct scsi_cmnd *cmnd)
{}
EXPORT_SYMBOL();

/*
 * fc_eh_should_retry_cmd - Checks if the cmd should be retried or not
 * @scmd:        The SCSI command to be checked
 *
 * This checks the rport state to decide if a cmd is
 * retryable.
 *
 * Returns: true if the rport state is not in marginal state.
 */
bool fc_eh_should_retry_cmd(struct scsi_cmnd *scmd)
{}
EXPORT_SYMBOL_GPL();

/**
 * fc_vport_setup - allocates and creates a FC virtual port.
 * @shost:	scsi host the virtual port is connected to.
 * @channel:	Channel on shost port connected to.
 * @pdev:	parent device for vport
 * @ids:	The world wide names, FC4 port roles, etc for
 *              the virtual port.
 * @ret_vport:	The pointer to the created vport.
 *
 * Allocates and creates the vport structure, calls the parent host
 * to instantiate the vport, this completes w/ class and sysfs creation.
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
static int
fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,
	struct fc_vport_identifiers  *ids, struct fc_vport **ret_vport)
{}

/**
 * fc_vport_create - Admin App or LLDD requests creation of a vport
 * @shost:	scsi host the virtual port is connected to.
 * @channel:	channel on shost port connected to.
 * @ids:	The world wide names, FC4 port roles, etc for
 *              the virtual port.
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
struct fc_vport *
fc_vport_create(struct Scsi_Host *shost, int channel,
	struct fc_vport_identifiers *ids)
{}
EXPORT_SYMBOL();

/**
 * fc_vport_terminate - Admin App or LLDD requests termination of a vport
 * @vport:	fc_vport to be terminated
 *
 * Calls the LLDD vport_delete() function, then deallocates and removes
 * the vport from the shost and object tree.
 *
 * Notes:
 *	This routine assumes no locks are held on entry.
 */
int
fc_vport_terminate(struct fc_vport *vport)
{}
EXPORT_SYMBOL();

/**
 * fc_vport_sched_delete - workq-based delete request for a vport
 * @work:	vport to be deleted.
 */
static void
fc_vport_sched_delete(struct work_struct *work)
{}


/*
 * BSG support
 */

/**
 * fc_bsg_job_timeout - handler for when a bsg request timesout
 * @req:	request that timed out
 */
static enum blk_eh_timer_return
fc_bsg_job_timeout(struct request *req)
{}

/**
 * fc_bsg_host_dispatch - process fc host bsg requests and dispatch to LLDD
 * @shost:	scsi host rport attached to
 * @job:	bsg job to be processed
 */
static int fc_bsg_host_dispatch(struct Scsi_Host *shost, struct bsg_job *job)
{}


/*
 * fc_bsg_goose_queue - restart rport queue in case it was stopped
 * @rport:	rport to be restarted
 */
static void
fc_bsg_goose_queue(struct fc_rport *rport)
{}

/**
 * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD
 * @shost:	scsi host rport attached to
 * @job:	bsg job to be processed
 */
static int fc_bsg_rport_dispatch(struct Scsi_Host *shost, struct bsg_job *job)
{}

static int fc_bsg_dispatch(struct bsg_job *job)
{}

static blk_status_t fc_bsg_rport_prep(struct fc_rport *rport)
{}


static int fc_bsg_dispatch_prep(struct bsg_job *job)
{}

/**
 * fc_bsg_hostadd - Create and add the bsg hooks so we can receive requests
 * @shost:	shost for fc_host
 * @fc_host:	fc_host adding the structures to
 */
static int
fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
{}

/**
 * fc_bsg_rportadd - Create and add the bsg hooks so we can receive requests
 * @shost:	shost that rport is attached to
 * @rport:	rport that the bsg hooks are being attached to
 */
static int
fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport)
{}


/**
 * fc_bsg_remove - Deletes the bsg hooks on fchosts/rports
 * @q:	the request_queue that is to be torn down.
 *
 * Notes:
 *   Before unregistering the queue empty any requests that are blocked
 *
 *
 */
static void
fc_bsg_remove(struct request_queue *q)
{}


/* Original Author:  Martin Hicks */
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

module_init();
module_exit(fc_transport_exit);