[PATCH] minimal SAS transport class

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a minmal, bottom-up SAS transport class.  So far it only exposed
information about the SAS port/phy and SAS device (scsi target).  I hope
this will integrate nicely with the top-down work Luben has done once he
finally releases it publically, but for now I think we should have
something so SAS drivers can go in the tree.

In detail this transport class does:

 - introduces a SAS port object between the Scsi_Host and scsi_target,
   this is used to hold all information specific to the SAS port and
   PHY - right now they're used interchangable as I haven't found the
   right abstraction for wide ports yet - if there is a proper solution
   at all as the SAS spec leaves binding PHYs together to wide ports
   up to the implementation.
 - adds some attributes to the scsi_target, and an API call to
   preinitialize them.

It does not:

 - handle any managment interfaces or chaning of attributes
 - any SAS devices that are not scsi targets, most importantly there's
   no support for SMP and extenders yet
 - wide ports (as mentioned above)
 - software device discovery (although I know Luben has some nice code
   for that)
 - everythig not mentioned here

A bit of warning: I've only tested this with an SATA disk attached to
a SAS HBA so far because I don't have any real SAS storage yet.

To use the transport class you need a patched fusion driver for now,
use the LSI tarball at:

  ftp://ftp.lsil.com/HostAdapterDrivers/linux/Fusion-MPT/mptlinux-3.02.55-src.tar.gz

plus my patch at:

  http://verein.lst.de/~hch/fusion-sas-transport-class.diff

I'll try to port my changes plus basic SAS support over to the mainline
driver, but the driver is currently not endian clean which makes it hard
for me to actually test it.

Signed-off-by: Christoph Hellwig <hch@xxxxxx>

Index: scsi-misc-2.6/drivers/scsi/Kconfig
===================================================================
--- scsi-misc-2.6.orig/drivers/scsi/Kconfig	2005-08-13 13:53:51.000000000 +0200
+++ scsi-misc-2.6/drivers/scsi/Kconfig	2005-08-15 15:34:56.000000000 +0200
@@ -229,6 +229,13 @@
 	  each attached iSCSI device to sysfs, say Y.
 	  Otherwise, say N.
 
+config SCSI_SAS_ATTRS
+	tristate "SAS Transport Attributes"
+	depends on SCSI
+	help
+	  If you wish to export transport-specific information about
+	  each attached SAS device to sysfs, say Y.
+
 endmenu
 
 menu "SCSI low-level drivers"
Index: scsi-misc-2.6/drivers/scsi/Makefile
===================================================================
--- scsi-misc-2.6.orig/drivers/scsi/Makefile	2005-08-13 13:53:51.000000000 +0200
+++ scsi-misc-2.6/drivers/scsi/Makefile	2005-08-15 15:35:12.000000000 +0200
@@ -29,6 +29,7 @@
 obj-$(CONFIG_SCSI_SPI_ATTRS)	+= scsi_transport_spi.o
 obj-$(CONFIG_SCSI_FC_ATTRS) 	+= scsi_transport_fc.o
 obj-$(CONFIG_SCSI_ISCSI_ATTRS)	+= scsi_transport_iscsi.o
+obj-$(CONFIG_SCSI_SAS_ATTRS)	+= scsi_transport_sas.o
 
 obj-$(CONFIG_SCSI_AMIGA7XX)	+= amiga7xx.o	53c7xx.o
 obj-$(CONFIG_A3000_SCSI)	+= a3000.o	wd33c93.o
Index: scsi-misc-2.6/drivers/scsi/scsi_transport_sas.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ scsi-misc-2.6/drivers/scsi/scsi_transport_sas.c	2005-08-15 15:40:00.000000000 +0200
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2005 Dell Inc.
+ *	Released under GPL v2.
+ *
+ * Based on the FC transport class work by James Smart, Emulex Corporation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_sas.h>
+
+
+#define SAS_TARGET_ATTRS	25
+#define SAS_PORT_ATTRS		25
+
+struct sas_internal {
+	struct scsi_transport_template t;
+	struct sas_function_template *f;
+
+	struct class_device_attribute private_target_attrs[SAS_TARGET_ATTRS];
+	struct class_device_attribute private_port_attrs[SAS_TARGET_ATTRS];
+
+	struct transport_container port_attr_cont;
+
+	/*
+	 * The array of null terminated pointers to attributes
+	 * needed by scsi_sysfs.c
+	 */
+	struct class_device_attribute *target_attrs[SAS_TARGET_ATTRS];
+	struct class_device_attribute *port_attrs[SAS_PORT_ATTRS + 1];
+};
+#define to_sas_internal(tmpl)	container_of(tmpl, struct sas_internal, t)
+
+/*
+ * Hack to allow attributes of the same name in different objects.
+ */
+#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+	struct class_device_attribute class_device_attr_##_prefix##_##_name = \
+	__ATTR(_name,_mode,_show,_store)
+
+
+/*
+ * Pretty printing helpers
+ */
+
+#define sas_bitfield_name_match(title, table)			\
+static ssize_t							\
+get_sas_##title##_names(u32 table_key, char *buf)		\
+{								\
+	char *prefix = "";					\
+	ssize_t len = 0;					\
+	int i;							\
+								\
+	for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {	\
+		if (table[i].value & table_key) {		\
+			len += sprintf(buf + len, "%s%s",	\
+				prefix, table[i].name);		\
+			prefix = ", ";				\
+		}						\
+	}							\
+	len += sprintf(buf + len, "\n");			\
+	return len;						\
+}
+
+#define sas_bitfield_name_search(title, table)			\
+static ssize_t							\
+get_sas_##title##_names(u32 table_key, char *buf)		\
+{								\
+	ssize_t len = 0;					\
+	int i;							\
+								\
+	for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {	\
+		if (table[i].value == table_key) {		\
+			len += sprintf(buf + len, "%s",		\
+				table[i].name);			\
+			break;					\
+		}						\
+	}							\
+	len += sprintf(buf + len, "\n");			\
+	return len;						\
+}
+
+static struct {
+	u32		value;
+	char		*name;
+} sas_device_type_names[] = {
+	{ SAS_PHY_UNUSED,		"unused" },
+	{ SAS_END_DEVICE,		"end device" },
+	{ SAS_EDGE_EXPANDER_DEVICE,	"edge expander" },
+	{ SAS_FANOUT_EXPANDER_DEVICE,	"fanout expander" },
+};
+sas_bitfield_name_search(device_type, sas_device_type_names)
+
+
+static struct {
+	u32		value;
+	char		*name;
+} sas_protocol_names[] = {
+	{ SAS_PROTOCOL_SATA,		"sata" },
+	{ SAS_PROTOCOL_SMP,		"smp" },
+	{ SAS_PROTOCOL_STP,		"stp" },
+	{ SAS_PROTOCOL_SSP,		"ssp" },
+};
+sas_bitfield_name_match(protocol, sas_protocol_names)
+
+static struct {
+	u32		value;
+	char		*name;
+} sas_linkspeed_names[] = {
+	{ SAS_LINK_RATE_UNKNOWN,	"Unknown" },
+	{ SAS_PHY_DISABLED,		"Phy disabled" },
+	{ SAS_LINK_RATE_FAILED,		"Link Rate failed" },
+	{ SAS_SATA_SPINUP_HOLD,		"Spin-up hold" },
+	{ SAS_LINK_RATE_1_5_GBPS,	"1.5 Gbit" },
+	{ SAS_LINK_RATE_3_0_GBPS,	"3.0 Gbit" },
+};
+sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
+
+
+/*
+ * SAS target attributes
+ */
+
+#define sas_transport_show_simple(field, name, format_string)		\
+static ssize_t								\
+show_sas_transport_##name(struct class_device *cdev, char *buf)		\
+{									\
+	struct scsi_target *starget = transport_class_to_starget(cdev);	\
+	struct sas_transport_attrs *tp;					\
+									\
+	tp = (struct sas_transport_attrs *)&starget->starget_data;	\
+	return snprintf(buf, 20, format_string, tp->field);		\
+}
+
+#define sas_transport_simple_attr(field, name, format_string)		\
+	sas_transport_show_simple(field, name, format_string)		\
+static SAS_CLASS_DEVICE_ATTR(transport, name, S_IRUGO, 			\
+		show_sas_transport_##name, NULL)
+
+#define sas_transport_show_protocol(field, name)			\
+static ssize_t								\
+show_sas_transport_##name(struct class_device *cdev, char *buf)		\
+{									\
+	struct scsi_target *starget = transport_class_to_starget(cdev);	\
+	struct sas_transport_attrs *tp =				\
+		(struct sas_transport_attrs *)&starget->starget_data;	\
+									\
+	if (!tp->field)							\
+		return snprintf(buf, 20, "none\n");			\
+	return get_sas_protocol_names(tp->field, buf);			\
+}
+
+#define sas_transport_protocol_attr(field, name)			\
+	sas_transport_show_protocol(field, name)			\
+static SAS_CLASS_DEVICE_ATTR(transport, name, S_IRUGO,			\
+		show_sas_transport_##name, NULL)
+
+static ssize_t
+show_sas_transport_device_type(struct class_device *cdev, char *buf)
+{
+	struct scsi_target *starget = transport_class_to_starget(cdev);
+	struct sas_transport_attrs *tp =
+		(struct sas_transport_attrs *)&starget->starget_data;
+
+	if (!tp->attached.device_type)
+		return snprintf(buf, 20, "none\n");
+	return get_sas_device_type_names(tp->attached.device_type, buf);
+}
+
+static SAS_CLASS_DEVICE_ATTR(transport, device_type, S_IRUGO,
+		show_sas_transport_device_type, NULL);
+
+sas_transport_protocol_attr(attached.initiator_port_protocols,
+		initiator_port_protocols);
+sas_transport_protocol_attr(attached.target_port_protocols,
+		target_port_protocols);
+sas_transport_simple_attr(attached.sas_address,
+		sas_address, "0x%llx\n");
+sas_transport_simple_attr(attached.phy_identifier,
+		phy_identifier, "%d\n");
+
+static DECLARE_TRANSPORT_CLASS(sas_transport_class,
+		"sas_transport", NULL, NULL, NULL);
+
+static int sas_target_match(struct attribute_container *cont,
+			    struct device *dev)
+{
+	struct Scsi_Host *shost;
+	struct sas_internal *i;
+
+	if (!scsi_is_target_device(dev))
+		return 0;
+	shost = dev_to_shost(dev->parent);
+
+	if (!shost->transportt)
+		return 0;
+	if (shost->transportt->target_attrs.ac.class !=
+			&sas_transport_class.class)
+		return 0;
+
+	i = to_sas_internal(shost->transportt);
+	return &i->t.target_attrs.ac == cont;
+}
+
+void sas_add_target(struct sas_port *port, struct sas_identify *attached,
+		uint channel, uint target)
+{
+	if (attached->target_port_protocols &
+	    (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))
+		scsi_scan_target(&port->dev, channel, target, ~0, 0, attached);
+}
+EXPORT_SYMBOL(sas_add_target);
+
+
+/*
+ * SAS Port attributes
+ */
+
+#define sas_port_show_simple(field, name, format_string)		\
+static ssize_t								\
+show_sas_port_##name(struct class_device *cdev, char *buf)		\
+{									\
+	struct sas_port *port = transport_class_to_port(cdev);		\
+									\
+	return snprintf(buf, 20, format_string, port->attrs->field);	\
+}
+
+#define sas_port_simple_attr(field, name, format_string)		\
+	sas_port_show_simple(field, name, format_string)		\
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
+
+#define sas_port_show_protocol(field, name)				\
+static ssize_t								\
+show_sas_port_##name(struct class_device *cdev, char *buf)		\
+{									\
+	struct sas_port *port = transport_class_to_port(cdev);		\
+									\
+	if (!port->attrs->field)					\
+		return snprintf(buf, 20, "none\n");			\
+	return get_sas_protocol_names(port->attrs->field, buf);		\
+}
+
+#define sas_port_protocol_attr(field, name)				\
+	sas_port_show_protocol(field, name)				\
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
+
+#define sas_port_show_linkspeed(field)					\
+static ssize_t								\
+show_sas_port_##field(struct class_device *cdev, char *buf)		\
+{									\
+	struct sas_port *port = transport_class_to_port(cdev);		\
+									\
+	return get_sas_linkspeed_names(port->attrs->field, buf);	\
+}
+
+#define sas_port_linkspeed_attr(field)					\
+	sas_port_show_linkspeed(field)					\
+static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_port_##field, NULL)
+
+static ssize_t
+show_sas_device_type(struct class_device *cdev, char *buf)
+{
+	struct sas_port *port = transport_class_to_port(cdev);
+
+	if (!port->attrs->identify.device_type)
+		return snprintf(buf, 20, "none\n");
+	return get_sas_device_type_names(
+			port->attrs->identify.device_type, buf);
+}
+
+static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
+
+sas_port_protocol_attr(identify.initiator_port_protocols,
+		initiator_port_protocols);
+sas_port_protocol_attr(identify.target_port_protocols,
+		target_port_protocols);
+sas_port_simple_attr(identify.sas_address,
+		sas_address, "0x%llx\n");
+sas_port_simple_attr(identify.phy_identifier,
+		phy_identifier, "%d\n");
+sas_port_simple_attr(port_identifier, port_identifier, "%d\n");
+sas_port_linkspeed_attr(negotiated_linkrate);
+sas_port_linkspeed_attr(minimum_linkrate_hw);
+sas_port_linkspeed_attr(minimum_linkrate);
+sas_port_linkspeed_attr(maximum_linkrate_hw);
+sas_port_linkspeed_attr(maximum_linkrate);
+
+
+static DECLARE_TRANSPORT_CLASS(sas_port_class,
+		"sas_port", NULL, NULL, NULL);
+
+static int sas_port_match(struct attribute_container *cont, struct device *dev)
+{
+	struct Scsi_Host *shost;
+	struct sas_internal *i;
+
+	if (!scsi_is_sas_port(dev))
+		return 0;
+	shost = dev_to_shost(dev->parent);
+
+	if (!shost->transportt)
+		return 0;
+	if (shost->transportt->target_attrs.ac.class !=
+			&sas_transport_class.class)
+		return 0;
+
+	i = to_sas_internal(shost->transportt);
+	return &i->port_attr_cont.ac == cont;
+}
+
+static void sas_port_release(struct device *dev)
+{
+	struct sas_port *port = dev_to_port(dev);
+
+	kfree(port->attrs);
+	put_device(dev->parent);
+	kfree(port);
+}
+
+struct sas_port *
+sas_port_add(struct Scsi_Host *shost, int number,
+		struct sas_port_attrs *attrs)
+{
+	struct sas_port *port;
+	int error;
+
+	port = kmalloc(sizeof(*port), GFP_KERNEL);
+	if (!port)
+		return ERR_PTR(-ENOMEM);
+	memset(port, 0, sizeof(*port));
+
+	get_device(&shost->shost_gendev);
+
+	port->attrs = attrs;
+	port->number = number;
+
+	device_initialize(&port->dev);
+	port->dev.parent = get_device(&shost->shost_gendev);
+	port->dev.release = sas_port_release;
+	sprintf(port->dev.bus_id, "port-%d:%d",
+		shost->host_no, number);
+	transport_setup_device(&port->dev);
+
+	error = device_add(&port->dev);
+	if (error)
+		goto out_transport_destroy;
+	transport_add_device(&port->dev);
+	transport_configure_device(&port->dev);
+
+	return port;
+
+ out_transport_destroy:
+	transport_destroy_device(&port->dev);
+	put_device(port->dev.parent);
+	put_device(port->dev.parent);
+	put_device(&shost->shost_gendev);
+	kfree(port);
+	return NULL;
+}
+EXPORT_SYMBOL(sas_port_add);
+
+void
+sas_port_delete(struct sas_port *port)
+{
+	struct Scsi_Host *shost = port_to_shost(port);
+	struct device *dev = &port->dev;
+
+	scsi_remove_target(&port->dev);
+
+	transport_remove_device(dev);
+	device_del(dev);
+	transport_destroy_device(dev);
+	put_device(&shost->shost_gendev);
+}
+EXPORT_SYMBOL(sas_port_delete);
+
+int scsi_is_sas_port(const struct device *dev)
+{
+	return dev->release == sas_port_release;
+}
+EXPORT_SYMBOL(scsi_is_sas_port);
+
+
+/*
+ * Setup / Teardown code
+ */
+
+#define SETUP_TARGET_ATTRIBUTE(field)					\
+	i->private_target_attrs[count] = class_device_attr_##field;	\
+	i->private_target_attrs[count].attr.mode = S_IRUGO;		\
+	i->private_target_attrs[count].store = NULL;			\
+	i->target_attrs[count] = &i->private_target_attrs[count];	\
+	count++
+
+#define SETUP_PORT_ATTRIBUTE(field)					\
+	i->private_port_attrs[count] = class_device_attr_##field;	\
+        i->private_port_attrs[count].attr.mode = S_IRUGO;		\
+        i->private_port_attrs[count].store = NULL;			\
+        i->port_attrs[count] = &i->private_port_attrs[count];		\
+	count++
+
+struct scsi_transport_template *
+sas_attach_transport(struct sas_function_template *ft)
+{
+	struct sas_internal *i;
+	int count;
+
+	i = kmalloc(sizeof(struct sas_internal), GFP_KERNEL);
+	if (!i)
+		return NULL;
+	memset(i, 0, sizeof(struct sas_internal));
+
+	i->t.target_attrs.ac.class = &sas_transport_class.class;
+	i->t.target_attrs.ac.attrs = &i->target_attrs[0];
+	i->t.target_attrs.ac.match = sas_target_match;
+	transport_container_register(&i->t.target_attrs);
+	i->t.target_size = sizeof(struct sas_transport_attrs);
+
+	i->port_attr_cont.ac.class = &sas_port_class.class;
+	i->port_attr_cont.ac.attrs = &i->port_attrs[0];
+	i->port_attr_cont.ac.match = sas_port_match;
+	transport_container_register(&i->port_attr_cont);
+
+	i->f = ft;
+
+	count = 0;
+	SETUP_PORT_ATTRIBUTE(initiator_port_protocols);
+	SETUP_PORT_ATTRIBUTE(target_port_protocols);
+	SETUP_PORT_ATTRIBUTE(device_type);
+	SETUP_PORT_ATTRIBUTE(sas_address);
+	SETUP_PORT_ATTRIBUTE(phy_identifier);
+	SETUP_PORT_ATTRIBUTE(port_identifier);
+	SETUP_PORT_ATTRIBUTE(negotiated_linkrate);
+	SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw);
+	SETUP_PORT_ATTRIBUTE(minimum_linkrate);
+	SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw);
+	SETUP_PORT_ATTRIBUTE(maximum_linkrate);
+	i->port_attrs[count] = NULL;
+
+	count = 0;
+	SETUP_TARGET_ATTRIBUTE(transport_initiator_port_protocols);
+	SETUP_TARGET_ATTRIBUTE(transport_target_port_protocols);
+	SETUP_TARGET_ATTRIBUTE(transport_device_type);
+	SETUP_TARGET_ATTRIBUTE(transport_sas_address);
+	SETUP_TARGET_ATTRIBUTE(transport_phy_identifier);
+	i->target_attrs[count] = NULL;
+
+	return &i->t;
+}
+EXPORT_SYMBOL(sas_attach_transport);
+
+void sas_release_transport(struct scsi_transport_template *t)
+{
+	struct sas_internal *i = to_sas_internal(t);
+
+	transport_container_unregister(&i->t.target_attrs);
+	transport_container_unregister(&i->port_attr_cont);
+
+	kfree(i);
+}
+EXPORT_SYMBOL(sas_release_transport);
+
+static __init int sas_transport_init(void)
+{
+	int error = transport_class_register(&sas_transport_class);
+	if (!error) {
+		error = transport_class_register(&sas_port_class);
+		if (error)
+			transport_class_unregister(&sas_transport_class);
+	}
+	return error;
+
+}
+
+static void __exit sas_transport_exit(void)
+{
+	transport_class_unregister(&sas_transport_class);
+	transport_class_unregister(&sas_port_class);
+}
+
+MODULE_AUTHOR("Christoph Hellwig");
+MODULE_DESCRIPTION("SAS Transport Attributes");
+MODULE_LICENSE("GPL");
+
+module_init(sas_transport_init);
+module_exit(sas_transport_exit);
Index: scsi-misc-2.6/include/scsi/scsi_transport_sas.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ scsi-misc-2.6/include/scsi/scsi_transport_sas.h	2005-08-15 15:33:45.000000000 +0200
@@ -0,0 +1,88 @@
+#ifndef SCSI_TRANSPORT_SAS_H
+#define SCSI_TRANSPORT_SAS_H
+
+#include <linux/transport_class.h>
+#include <linux/types.h>
+
+
+struct scsi_transport_template;
+
+enum sas_device_type {
+	SAS_PHY_UNUSED			= 0x00,
+	SAS_END_DEVICE			= 0x10,
+	SAS_EDGE_EXPANDER_DEVICE	= 0x20,
+	SAS_FANOUT_EXPANDER_DEVICE	= 0x30,
+};
+
+enum sas_protocol {
+	SAS_PROTOCOL_SATA		= 0x01,
+	SAS_PROTOCOL_SMP		= 0x02,
+	SAS_PROTOCOL_STP		= 0x04,
+	SAS_PROTOCOL_SSP		= 0x08,
+};
+
+enum sas_linkrate {
+	SAS_LINK_RATE_UNKNOWN		= 0x00,
+	SAS_PHY_DISABLED		= 0x01,
+	SAS_LINK_RATE_FAILED		= 0x02,
+	SAS_SATA_SPINUP_HOLD		= 0x03,
+	SAS_SATA_PORT_SELECTOR		= 0x04,
+	SAS_LINK_RATE_1_5_GBPS		= 0x08,
+	SAS_LINK_RATE_3_0_GBPS		= 0x09,
+	SAS_LINK_VIRTUAL		= 0x10,
+};
+
+struct sas_identify {
+	enum sas_device_type	device_type;
+	enum sas_protocol	initiator_port_protocols;
+	enum sas_protocol	target_port_protocols;
+	u64			sas_address;
+	u8			phy_identifier;
+};
+
+struct sas_transport_attrs {
+	struct sas_identify	attached;
+};
+
+struct sas_port_attrs {
+	struct list_head	port_list;
+	struct sas_identify	identify;
+	struct sas_identify	attached;
+	enum sas_linkrate	negotiated_linkrate;
+	enum sas_linkrate	minimum_linkrate_hw;
+	enum sas_linkrate	minimum_linkrate;
+	enum sas_linkrate	maximum_linkrate_hw;
+	enum sas_linkrate	maximum_linkrate;
+	u8			port_identifier;
+};
+
+/* The functions by which the transport class and the driver communicate */
+struct sas_function_template {
+};
+
+struct sas_port {
+	struct device		dev;
+	int			number;
+	struct sas_port_attrs	*attrs;
+};
+
+#define dev_to_port(d) \
+	container_of((d), struct sas_port, dev)
+#define transport_class_to_port(cdev) \
+	dev_to_port((cdev)->dev)
+#define port_to_shost(port) \
+	dev_to_shost((port)->dev.parent)
+
+extern void sas_add_target(struct sas_port *, struct sas_identify *,
+		uint, uint);
+
+extern struct sas_port *sas_port_add(struct Scsi_Host *, int,
+		struct sas_port_attrs *);
+extern void sas_port_delete(struct sas_port *);
+extern int scsi_is_sas_port(const struct device *);
+
+extern struct scsi_transport_template *
+sas_attach_transport(struct sas_function_template *);
+extern void sas_release_transport(struct scsi_transport_template *);
+
+#endif /* SCSI_TRANSPORT_SAS_H */
-
: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux