linux/drivers/scsi/scsi_transport_sas.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2005-2006 Dell Inc.
 *
 * Serial Attached SCSI (SAS) transport class.
 *
 * The SAS transport class contains common code to deal with SAS HBAs,
 * an aproximated representation of SAS topologies in the driver model,
 * and various sysfs attributes to expose these topologies and management
 * interfaces to userspace.
 *
 * In addition to the basic SCSI core objects this transport class
 * introduces two additional intermediate objects:  The SAS PHY
 * as represented by struct sas_phy defines an "outgoing" PHY on
 * a SAS HBA or Expander, and the SAS remote PHY represented by
 * struct sas_rphy defines an "incoming" PHY on a SAS Expander or
 * end device.  Note that this is purely a software concept, the
 * underlying hardware for a PHY and a remote PHY is the exactly
 * the same.
 *
 * There is no concept of a SAS port in this code, users can see
 * what PHYs form a wide port based on the port_identifier attribute,
 * which is the same for all PHYs in a port.
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/blkdev.h>
#include <linux/bsg.h>

#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>

#include "scsi_sas_internal.h"
struct sas_host_attrs {};
#define to_sas_host_attrs(host)


/*
 * Hack to allow attributes of the same name in different objects.
 */
#define SAS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store)


/*
 * Pretty printing helpers
 */

#define sas_bitfield_name_match(title, table)

#define sas_bitfield_name_set(title, table)

#define sas_bitfield_name_search(title, table)

static struct {} sas_device_type_names[] =;
sas_bitfield_name_search(device_type, sas_device_type_names)


static struct {} sas_protocol_names[] =;
sas_bitfield_name_match(protocol, sas_protocol_names)

static struct {} sas_linkspeed_names[] =;
sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
sas_bitfield_name_set(linkspeed, sas_linkspeed_names)

static struct sas_end_device *sas_sdev_to_rdev(struct scsi_device *sdev)
{}

static int sas_smp_dispatch(struct bsg_job *job)
{}

static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
{}

/*
 * SAS host attributes
 */

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

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

static DECLARE_TRANSPORT_CLASS(sas_host_class,
		"sas_host", sas_host_setup, sas_host_remove, NULL);

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

static int do_sas_phy_delete(struct device *dev, void *data)
{}

/**
 * sas_remove_children  -  tear down a devices SAS data structures
 * @dev:	device belonging to the sas object
 *
 * Removes all SAS PHYs and remote PHYs for a given object
 */
void sas_remove_children(struct device *dev)
{}
EXPORT_SYMBOL();

/**
 * sas_remove_host  -  tear down a Scsi_Host's SAS data structures
 * @shost:	Scsi Host that is torn down
 *
 * Removes all SAS PHYs and remote PHYs for a given Scsi_Host and remove the
 * Scsi_Host as well.
 *
 * Note: Do not call scsi_remove_host() on the Scsi_Host any more, as it is
 * already removed.
 */
void sas_remove_host(struct Scsi_Host *shost)
{}
EXPORT_SYMBOL();

/**
 * sas_get_address - return the SAS address of the device
 * @sdev: scsi device
 *
 * Returns the SAS address of the scsi device
 */
u64 sas_get_address(struct scsi_device *sdev)
{}
EXPORT_SYMBOL();

/**
 * sas_tlr_supported - checking TLR bit in vpd 0x90
 * @sdev: scsi device struct
 *
 * Check Transport Layer Retries are supported or not.
 * If vpd page 0x90 is present, TRL is supported.
 *
 */
unsigned int
sas_tlr_supported(struct scsi_device *sdev)
{}
EXPORT_SYMBOL_GPL();

/**
 * sas_disable_tlr - setting TLR flags
 * @sdev: scsi device struct
 *
 * Seting tlr_enabled flag to 0.
 *
 */
void
sas_disable_tlr(struct scsi_device *sdev)
{}
EXPORT_SYMBOL_GPL();

/**
 * sas_enable_tlr - setting TLR flags
 * @sdev: scsi device struct
 *
 * Seting tlr_enabled flag 1.
 *
 */
void sas_enable_tlr(struct scsi_device *sdev)
{}
EXPORT_SYMBOL_GPL();

unsigned int sas_is_tlr_enabled(struct scsi_device *sdev)
{}
EXPORT_SYMBOL_GPL();

/**
 * sas_ata_ncq_prio_supported - Check for ATA NCQ command priority support
 * @sdev: SCSI device
 *
 * Check if an ATA device supports NCQ priority using VPD page 89h (ATA
 * Information). Since this VPD page is implemented only for ATA devices,
 * this function always returns false for SCSI devices.
 */
bool sas_ata_ncq_prio_supported(struct scsi_device *sdev)
{}
EXPORT_SYMBOL_GPL();

/*
 * SAS Phy attributes
 */

#define sas_phy_show_simple(field, name, format_string, cast)

#define sas_phy_simple_attr(field, name, format_string, type)

#define sas_phy_show_protocol(field, name)

#define sas_phy_protocol_attr(field, name)

#define sas_phy_show_linkspeed(field)

/* Fudge to tell if we're minimum or maximum */
#define sas_phy_store_linkspeed(field)

#define sas_phy_linkspeed_rw_attr(field)

#define sas_phy_linkspeed_attr(field)


#define sas_phy_show_linkerror(field)

#define sas_phy_linkerror_attr(field)


static ssize_t
show_sas_device_type(struct device *dev,
		     struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);

static ssize_t do_sas_phy_enable(struct device *dev,
		size_t count, int enable)
{
	struct sas_phy *phy = transport_class_to_phy(dev);
	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
	struct sas_internal *i = to_sas_internal(shost->transportt);
	int error;

	error = i->f->phy_enable(phy, enable);
	if (error)
		return error;
	phy->enabled = enable;
	return count;
};

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

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

static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
			 store_sas_phy_enable);

static ssize_t
do_sas_phy_reset(struct device *dev, size_t count, int hard_reset)
{
	struct sas_phy *phy = transport_class_to_phy(dev);
	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
	struct sas_internal *i = to_sas_internal(shost->transportt);
	int error;

	error = i->f->phy_reset(phy, hard_reset);
	if (error)
		return error;
	phy->enabled = 1;
	return count;
};

static ssize_t
store_sas_link_reset(struct device *dev, struct device_attribute *attr,
		     const char *buf, size_t count)
{}
static DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);

static ssize_t
store_sas_hard_reset(struct device *dev, struct device_attribute *attr,
		     const char *buf, size_t count)
{}
static DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);

sas_phy_protocol_attr();
sas_phy_protocol_attr();
sas_phy_simple_attr();
sas_phy_simple_attr();
sas_phy_linkspeed_attr();
sas_phy_linkspeed_attr();
sas_phy_linkspeed_rw_attr();
sas_phy_linkspeed_attr();
sas_phy_linkspeed_rw_attr();
sas_phy_linkerror_attr();
sas_phy_linkerror_attr();
sas_phy_linkerror_attr();
sas_phy_linkerror_attr();

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

static DECLARE_TRANSPORT_CLASS(sas_phy_class,
		"sas_phy", sas_phy_setup, NULL, NULL);

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

static void sas_phy_release(struct device *dev)
{}

/**
 * sas_phy_alloc  -  allocates and initialize a SAS PHY structure
 * @parent:	Parent device
 * @number:	Phy index
 *
 * Allocates an SAS PHY structure.  It will be added in the device tree
 * below the device specified by @parent, which has to be either a Scsi_Host
 * or sas_rphy.
 *
 * Returns:
 *	SAS PHY allocated or %NULL if the allocation failed.
 */
struct sas_phy *sas_phy_alloc(struct device *parent, int number)
{}
EXPORT_SYMBOL();

/**
 * sas_phy_add  -  add a SAS PHY to the device hierarchy
 * @phy:	The PHY to be added
 *
 * Publishes a SAS PHY to the rest of the system.
 */
int sas_phy_add(struct sas_phy *phy)
{}
EXPORT_SYMBOL();

/**
 * sas_phy_free  -  free a SAS PHY
 * @phy:	SAS PHY to free
 *
 * Frees the specified SAS PHY.
 *
 * Note:
 *   This function must only be called on a PHY that has not
 *   successfully been added using sas_phy_add().
 */
void sas_phy_free(struct sas_phy *phy)
{}
EXPORT_SYMBOL();

/**
 * sas_phy_delete  -  remove SAS PHY
 * @phy:	SAS PHY to remove
 *
 * Removes the specified SAS PHY.  If the SAS PHY has an
 * associated remote PHY it is removed before.
 */
void
sas_phy_delete(struct sas_phy *phy)
{}
EXPORT_SYMBOL();

/**
 * scsi_is_sas_phy  -  check if a struct device represents a SAS PHY
 * @dev:	device to check
 *
 * Returns:
 *	%1 if the device represents a SAS PHY, %0 else
 */
int scsi_is_sas_phy(const struct device *dev)
{}
EXPORT_SYMBOL();

/*
 * SAS Port attributes
 */
#define sas_port_show_simple(field, name, format_string, cast)

#define sas_port_simple_attr(field, name, format_string, type)

sas_port_simple_attr();

static DECLARE_TRANSPORT_CLASS(sas_port_class,
			       "sas_port", NULL, NULL, NULL);

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


static void sas_port_release(struct device *dev)
{}

static void sas_port_create_link(struct sas_port *port,
				 struct sas_phy *phy)
{}

static void sas_port_delete_link(struct sas_port *port,
				 struct sas_phy *phy)
{}

/** sas_port_alloc - allocate and initialize a SAS port structure
 *
 * @parent:	parent device
 * @port_id:	port number
 *
 * Allocates a SAS port structure.  It will be added to the device tree
 * below the device specified by @parent which must be either a Scsi_Host
 * or a sas_expander_device.
 *
 * Returns %NULL on error
 */
struct sas_port *sas_port_alloc(struct device *parent, int port_id)
{}
EXPORT_SYMBOL();

/** sas_port_alloc_num - allocate and initialize a SAS port structure
 *
 * @parent:	parent device
 *
 * Allocates a SAS port structure and a number to go with it.  This
 * interface is really for adapters where the port number has no
 * meansing, so the sas class should manage them.  It will be added to
 * the device tree below the device specified by @parent which must be
 * either a Scsi_Host or a sas_expander_device.
 *
 * Returns %NULL on error
 */
struct sas_port *sas_port_alloc_num(struct device *parent)
{}
EXPORT_SYMBOL();

/**
 * sas_port_add - add a SAS port to the device hierarchy
 * @port:	port to be added
 *
 * publishes a port to the rest of the system
 */
int sas_port_add(struct sas_port *port)
{}
EXPORT_SYMBOL();

/**
 * sas_port_free  -  free a SAS PORT
 * @port:	SAS PORT to free
 *
 * Frees the specified SAS PORT.
 *
 * Note:
 *   This function must only be called on a PORT that has not
 *   successfully been added using sas_port_add().
 */
void sas_port_free(struct sas_port *port)
{}
EXPORT_SYMBOL();

/**
 * sas_port_delete  -  remove SAS PORT
 * @port:	SAS PORT to remove
 *
 * Removes the specified SAS PORT.  If the SAS PORT has an
 * associated phys, unlink them from the port as well.
 */
void sas_port_delete(struct sas_port *port)
{}
EXPORT_SYMBOL();

/**
 * scsi_is_sas_port -  check if a struct device represents a SAS port
 * @dev:	device to check
 *
 * Returns:
 *	%1 if the device represents a SAS Port, %0 else
 */
int scsi_is_sas_port(const struct device *dev)
{}
EXPORT_SYMBOL();

/**
 * sas_port_get_phy - try to take a reference on a port member
 * @port: port to check
 */
struct sas_phy *sas_port_get_phy(struct sas_port *port)
{}
EXPORT_SYMBOL();

/**
 * sas_port_add_phy - add another phy to a port to form a wide port
 * @port:	port to add the phy to
 * @phy:	phy to add
 *
 * When a port is initially created, it is empty (has no phys).  All
 * ports must have at least one phy to operated, and all wide ports
 * must have at least two.  The current code makes no difference
 * between ports and wide ports, but the only object that can be
 * connected to a remote device is a port, so ports must be formed on
 * all devices with phys if they're connected to anything.
 */
void sas_port_add_phy(struct sas_port *port, struct sas_phy *phy)
{}
EXPORT_SYMBOL();

/**
 * sas_port_delete_phy - remove a phy from a port or wide port
 * @port:	port to remove the phy from
 * @phy:	phy to remove
 *
 * This operation is used for tearing down ports again.  It must be
 * done to every port or wide port before calling sas_port_delete.
 */
void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)
{}
EXPORT_SYMBOL();

void sas_port_mark_backlink(struct sas_port *port)
{}
EXPORT_SYMBOL();

/*
 * SAS remote PHY attributes.
 */

#define sas_rphy_show_simple(field, name, format_string, cast)

#define sas_rphy_simple_attr(field, name, format_string, type)

#define sas_rphy_show_protocol(field, name)

#define sas_rphy_protocol_attr(field, name)

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

static SAS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
		show_sas_rphy_device_type, NULL);

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

static SAS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO,
		show_sas_rphy_enclosure_identifier, NULL);

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

static SAS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO,
		show_sas_rphy_bay_identifier, NULL);

sas_rphy_protocol_attr();
sas_rphy_protocol_attr();
sas_rphy_simple_attr();
sas_rphy_simple_attr();
sas_rphy_simple_attr();

/* only need 8 bytes of data plus header (4 or 8) */
#define BUF_SIZE

int sas_read_port_mode_page(struct scsi_device *sdev)
{}
EXPORT_SYMBOL();

static DECLARE_TRANSPORT_CLASS(sas_end_dev_class,
			       "sas_end_device", NULL, NULL, NULL);

#define sas_end_dev_show_simple(field, name, format_string, cast)

#define sas_end_dev_simple_attr(field, name, format_string, type)

sas_end_dev_simple_attr();
sas_end_dev_simple_attr();
sas_end_dev_simple_attr();
sas_end_dev_simple_attr();
sas_end_dev_simple_attr();

static DECLARE_TRANSPORT_CLASS(sas_expander_class,
			       "sas_expander", NULL, NULL, NULL);

#define sas_expander_show_simple(field, name, format_string, cast)

#define sas_expander_simple_attr(field, name, format_string, type)

sas_expander_simple_attr();
sas_expander_simple_attr();
sas_expander_simple_attr();
sas_expander_simple_attr();
sas_expander_simple_attr();
sas_expander_simple_attr();
sas_expander_simple_attr();

static DECLARE_TRANSPORT_CLASS(sas_rphy_class,
		"sas_device", NULL, NULL, NULL);

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

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

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

static void sas_expander_release(struct device *dev)
{}

static void sas_end_device_release(struct device *dev)
{}

/**
 * sas_rphy_initialize - common rphy initialization
 * @rphy:	rphy to initialise
 *
 * Used by both sas_end_device_alloc() and sas_expander_alloc() to
 * initialise the common rphy component of each.
 */
static void sas_rphy_initialize(struct sas_rphy *rphy)
{}

/**
 * sas_end_device_alloc - allocate an rphy for an end device
 * @parent: which port
 *
 * Allocates an SAS remote PHY structure, connected to @parent.
 *
 * Returns:
 *	SAS PHY allocated or %NULL if the allocation failed.
 */
struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)
{}
EXPORT_SYMBOL();

/**
 * sas_expander_alloc - allocate an rphy for an end device
 * @parent: which port
 * @type: SAS_EDGE_EXPANDER_DEVICE or SAS_FANOUT_EXPANDER_DEVICE
 *
 * Allocates an SAS remote PHY structure, connected to @parent.
 *
 * Returns:
 *	SAS PHY allocated or %NULL if the allocation failed.
 */
struct sas_rphy *sas_expander_alloc(struct sas_port *parent,
				    enum sas_device_type type)
{}
EXPORT_SYMBOL();

/**
 * sas_rphy_add  -  add a SAS remote PHY to the device hierarchy
 * @rphy:	The remote PHY to be added
 *
 * Publishes a SAS remote PHY to the rest of the system.
 */
int sas_rphy_add(struct sas_rphy *rphy)
{}
EXPORT_SYMBOL();

/**
 * sas_rphy_free  -  free a SAS remote PHY
 * @rphy: SAS remote PHY to free
 *
 * Frees the specified SAS remote PHY.
 *
 * Note:
 *   This function must only be called on a remote
 *   PHY that has not successfully been added using
 *   sas_rphy_add() (or has been sas_rphy_remove()'d)
 */
void sas_rphy_free(struct sas_rphy *rphy)
{}
EXPORT_SYMBOL();

/**
 * sas_rphy_delete  -  remove and free SAS remote PHY
 * @rphy:	SAS remote PHY to remove and free
 *
 * Removes the specified SAS remote PHY and frees it.
 */
void
sas_rphy_delete(struct sas_rphy *rphy)
{}
EXPORT_SYMBOL();

/**
 * sas_rphy_unlink  -  unlink SAS remote PHY
 * @rphy:	SAS remote phy to unlink from its parent port
 *
 * Removes port reference to an rphy
 */
void sas_rphy_unlink(struct sas_rphy *rphy)
{}
EXPORT_SYMBOL();

/**
 * sas_rphy_remove  -  remove SAS remote PHY
 * @rphy:	SAS remote phy to remove
 *
 * Removes the specified SAS remote PHY.
 */
void
sas_rphy_remove(struct sas_rphy *rphy)
{}
EXPORT_SYMBOL();

/**
 * scsi_is_sas_rphy  -  check if a struct device represents a SAS remote PHY
 * @dev:	device to check
 *
 * Returns:
 *	%1 if the device represents a SAS remote PHY, %0 else
 */
int scsi_is_sas_rphy(const struct device *dev)
{}
EXPORT_SYMBOL();


/*
 * SCSI scan helper
 */

static int sas_user_scan(struct Scsi_Host *shost, uint channel,
		uint id, u64 lun)
{}


/*
 * Setup / Teardown code
 */

#define SETUP_TEMPLATE(attrb, field, perm, test)

#define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm)

#define SETUP_RPORT_ATTRIBUTE(field)

#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func)

#define SETUP_PHY_ATTRIBUTE(field)

#define SETUP_PHY_ATTRIBUTE_RW(field)

#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func)

#define SETUP_PORT_ATTRIBUTE(field)

#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func)

#define SETUP_PHY_ATTRIBUTE_WRONLY(field)

#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func)

#define SETUP_END_DEV_ATTRIBUTE(field)

#define SETUP_EXPANDER_ATTRIBUTE(field)

/**
 * sas_attach_transport  -  instantiate SAS transport template
 * @ft:		SAS transport class function template
 */
struct scsi_transport_template *
sas_attach_transport(struct sas_function_template *ft)
{}
EXPORT_SYMBOL();

/**
 * sas_release_transport  -  release SAS transport template instance
 * @t:		transport template instance
 */
void sas_release_transport(struct scsi_transport_template *t)
{}
EXPORT_SYMBOL();

static __init int sas_transport_init(void)
{}

static void __exit sas_transport_exit(void)
{}

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

module_init();
module_exit(sas_transport_exit);