From c7ebbbce366c02e5657ac6b6059933fe0353b175 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 9 Sep 2005 16:22:50 +0200 Subject: [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 managment 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. This submission doesn't handle hot-plug addition or removal of SAS devices and thus doesn't do scanning in a workqueue yet, that will be added in phase2 after this submission. In a third phase I will add additional managment infrastructure. I think this submission is ready for 2.6.14, but additional comments are of course very welcome. I'd like to thanks James Smart a lot for his very useful input on the design. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- include/scsi/scsi_transport_sas.h | 100 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 include/scsi/scsi_transport_sas.h (limited to 'include/scsi') diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h new file mode 100644 index 000000000000..bc4aeb660dd3 --- /dev/null +++ b/include/scsi/scsi_transport_sas.h @@ -0,0 +1,100 @@ +#ifndef SCSI_TRANSPORT_SAS_H +#define SCSI_TRANSPORT_SAS_H + +#include +#include + +struct scsi_transport_template; +struct sas_rphy; + + +enum sas_device_type { + SAS_PHY_UNUSED, + SAS_END_DEVICE, + SAS_EDGE_EXPANDER_DEVICE, + SAS_FANOUT_EXPANDER_DEVICE, +}; + +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, + SAS_PHY_DISABLED, + SAS_LINK_RATE_FAILED, + SAS_SATA_SPINUP_HOLD, + SAS_SATA_PORT_SELECTOR, + SAS_LINK_RATE_1_5_GBPS, + SAS_LINK_RATE_3_0_GBPS, + SAS_LINK_VIRTUAL, +}; + +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; +}; + +/* The functions by which the transport class and the driver communicate */ +struct sas_function_template { +}; + +struct sas_phy { + struct device dev; + int number; + struct sas_identify identify; + 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; + struct sas_rphy *rphy; +}; + +#define dev_to_phy(d) \ + container_of((d), struct sas_phy, dev) +#define transport_class_to_phy(cdev) \ + dev_to_phy((cdev)->dev) +#define phy_to_shost(phy) \ + dev_to_shost((phy)->dev.parent) + +struct sas_rphy { + struct device dev; + struct sas_identify identify; + struct list_head list; + u32 scsi_target_id; +}; + +#define dev_to_rphy(d) \ + container_of((d), struct sas_rphy, dev) +#define transport_class_to_rphy(cdev) \ + dev_to_rphy((cdev)->dev) +#define rphy_to_shost(rphy) \ + dev_to_shost((rphy)->dev.parent) + +extern void sas_remove_host(struct Scsi_Host *); + +extern struct sas_phy *sas_phy_alloc(struct device *, int); +extern void sas_phy_free(struct sas_phy *); +extern int sas_phy_add(struct sas_phy *); +extern void sas_phy_delete(struct sas_phy *); +extern int scsi_is_sas_phy(const struct device *); + +extern struct sas_rphy *sas_rphy_alloc(struct sas_phy *); +void sas_rphy_free(struct sas_rphy *); +extern int sas_rphy_add(struct sas_rphy *); +extern void sas_rphy_delete(struct sas_rphy *); +extern int scsi_is_sas_rphy(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 */ -- cgit v1.2.2 From 218fba0004390b0101e681f6db1b8920c1109e54 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 31 Aug 2005 15:18:35 -0700 Subject: [SCSI] fc_transport: Generalize WWN to u64 interger conversions. On some platforms the hard-casting of 8 byte node_name and port_name arrays to an u64 would cause unaligned-access warnings. Generalize the conversions with a transport helper function which performs consistent shifting of WWN bytes. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- include/scsi/scsi_transport_fc.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/scsi') diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 70ad16315a16..115db056dc6b 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -439,4 +439,12 @@ int fc_remote_port_block(struct fc_rport *rport); void fc_remote_port_unblock(struct fc_rport *rport); int scsi_is_fc_rport(const struct device *); +static inline u64 wwn_to_u64(u8 *wwn) +{ + return (u64)wwn[0] << 56 | (u64)wwn[1] << 48 | + (u64)wwn[2] << 40 | (u64)wwn[3] << 32 | + (u64)wwn[4] << 24 | (u64)wwn[5] << 16 | + (u64)wwn[6] << 8 | (u64)wwn[7]; +} + #endif /* SCSI_TRANSPORT_FC_H */ -- cgit v1.2.2 From 146f7262ee0ec7fc6882f06e5fcb13883308073c Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 10 Sep 2005 12:44:09 -0500 Subject: [SCSI] Alter the scsi_add_device() API to conform to what users expect The original API returned either an ERR_PTR() or a refcounted sdev. Unfortunately, if it's successful, you need to do a scsi_device_put() on the sdev otherwise the refcounting is wrong. Everyone seems to expect that scsi_add_device() should be callable without doing the ref put, so alter the API so it is (we still have __scsi_add_device with the original behaviour). The only actual caller that needs altering is the one in firewire ... not because it gets this right, but because it acts on the error if one is returned. Acked-by: Stefan Richter Signed-off-by: James Bottomley --- include/scsi/scsi_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/scsi') diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index da63722c0123..c0e4c67d836f 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -178,8 +178,8 @@ static inline struct scsi_target *scsi_target(struct scsi_device *sdev) extern struct scsi_device *__scsi_add_device(struct Scsi_Host *, uint, uint, uint, void *hostdata); -#define scsi_add_device(host, channel, target, lun) \ - __scsi_add_device(host, channel, target, lun, NULL) +extern int scsi_add_device(struct Scsi_Host *host, uint channel, + uint target, uint lun); extern void scsi_remove_device(struct scsi_device *); extern int scsi_device_cancel(struct scsi_device *, int); -- cgit v1.2.2