This patch exports a transport identifier for each host. This removes the need for heuristics in management utilities that need to know the transport type. The identifier is set by the SCSI transport class except for ATA, USB and FireWire. The default identifier is SPI as not all legacy HBA drivers are using transport classes. This patch is based on work by FUJITA Tomonori . Signed-off-by: Martin K. Petersen --- diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3237,6 +3237,7 @@ int ata_scsi_add_hosts(struct ata_host * shost->max_lun = 1; shost->max_channel = 1; shost->max_cmd_len = 16; + shost->transport_id = SCSI_TRANSPORT_ATA; /* Schedule policy is determined by ->qc_defer() * callback and it needs to see every deferred qc. diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -1138,6 +1138,7 @@ static int sbp2_probe(struct device *dev if (scsi_add_host(shost, &unit->device) < 0) goto fail_shost_put; + shost->transport_id = SCSI_TRANSPORT_SBP; fw_device_get(device); fw_unit_get(unit); diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -880,6 +880,7 @@ static struct sbp2_lu *sbp2_alloc_device } shost->hostdata[0] = (unsigned long)lu; + shost->transport_id = SCSI_TRANSPORT_SBP; if (!scsi_add_host(shost, &ud->device)) { lu->shost = shost; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -140,6 +140,34 @@ static DEVICE_ATTR(name, S_IRUGO, show_# #define shost_rd_attr(field, format_string) \ shost_rd_attr2(field, field, format_string) +static const struct { + enum scsi_transport_id value; + char *name; +} scsi_transport_names[] = { + { SCSI_TRANSPORT_SPI, "spi" }, + { SCSI_TRANSPORT_FC, "fc" }, + { SCSI_TRANSPORT_SAS, "sas" }, + { SCSI_TRANSPORT_ISCSI, "iscsi" }, + { SCSI_TRANSPORT_SBP, "sbp" }, + { SCSI_TRANSPORT_USB, "usb" }, + { SCSI_TRANSPORT_ATA, "ata" }, +}; + +static const char *scsi_transport_name(enum scsi_transport_id id) +{ + int i; + char *name = NULL; + + for (i = 0; i < ARRAY_SIZE(scsi_transport_names); i++) { + if (scsi_transport_names[i].value == id) { + name = scsi_transport_names[i].name; + break; + } + } + + return name; +} + /* * Create the actual show/store functions and data structures. */ @@ -244,6 +272,20 @@ show_shost_active_mode(struct device *de static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL); +static ssize_t +show_shost_transport_name(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + const char *name = scsi_transport_name(shost->transport_id); + + if (!name) + return -EINVAL; + + return snprintf(buf, 20, "%s\n", name); +} +static DEVICE_ATTR(transport_name, S_IRUGO, show_shost_transport_name, NULL); + shost_rd_attr(unique_id, "%u\n"); shost_rd_attr(host_busy, "%hu\n"); shost_rd_attr(cmd_per_lun, "%hd\n"); @@ -268,6 +310,7 @@ static struct attribute *scsi_sysfs_shos &dev_attr_active_mode.attr, &dev_attr_prot_capabilities.attr, &dev_attr_prot_guard_type.attr, + &dev_attr_transport_name.attr, NULL }; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -410,6 +410,7 @@ static int fc_host_setup(struct transpor fc_host->work_q = NULL; return -ENOMEM; } + shost->transport_id = SCSI_TRANSPORT_FC; return 0; } diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -246,6 +246,7 @@ static int iscsi_setup_host(struct trans memset(ihost, 0, sizeof(*ihost)); atomic_set(&ihost->nr_scans, 0); mutex_init(&ihost->mutex); + shost->transport_id = SCSI_TRANSPORT_ISCSI; return 0; } diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -287,6 +287,7 @@ static int sas_host_setup(struct transpo dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n", shost->host_no); + shost->transport_id = SCSI_TRANSPORT_SAS; return 0; } diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -63,6 +63,7 @@ static int srp_host_setup(struct transpo struct srp_host_attrs *srp_host = to_srp_host_attrs(shost); atomic_set(&srp_host->next_port_id, 0); + shost->transport_id = SCSI_TRANSPORT_SRP; return 0; } diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -868,6 +868,7 @@ int usb_stor_probe1(struct us_data **pus * Allow 16-byte CDBs and thus > 2TB */ host->max_cmd_len = 16; + host->transport_id = SCSI_TRANSPORT_USB; *pus = us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); mutex_init(&(us->dev_mutex)); diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -508,4 +508,15 @@ static inline __u32 scsi_to_u32(__u8 *pt return (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + ptr[3]; } +enum scsi_transport_id { + SCSI_TRANSPORT_UNKNOWN = 0, + SCSI_TRANSPORT_SPI, + SCSI_TRANSPORT_FC, + SCSI_TRANSPORT_SAS, + SCSI_TRANSPORT_ISCSI, + SCSI_TRANSPORT_SBP, + SCSI_TRANSPORT_USB, + SCSI_TRANSPORT_ATA, +}; + #endif /* _SCSI_SCSI_H */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -648,6 +648,7 @@ struct Scsi_Host { enum scsi_host_state shost_state; + enum scsi_transport_id transport_id; /* ldm bits */ struct device shost_gendev, shost_dev;