diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 179 |
1 files changed, 108 insertions, 71 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 43a964d635b4..7899e3dda9bf 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -53,8 +53,8 @@ struct sas_host_attrs { /* * 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 = \ +#define SAS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ + struct device_attribute dev_attr_##_prefix##_##_name = \ __ATTR(_name,_mode,_show,_store) @@ -192,6 +192,16 @@ static void sas_non_host_smp_request(struct request_queue *q) sas_smp_request(q, rphy_to_shost(rphy), rphy); } +static void sas_host_release(struct device *dev) +{ + struct Scsi_Host *shost = dev_to_shost(dev); + struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); + struct request_queue *q = sas_host->q; + + if (q) + blk_cleanup_queue(q); +} + static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) { struct request_queue *q; @@ -199,6 +209,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) struct device *dev; char namebuf[BUS_ID_SIZE]; const char *name; + void (*release)(struct device *); if (!to_sas_internal(shost->transportt)->f->smp_handler) { printk("%s can't handle SMP requests\n", shost->hostt->name); @@ -209,17 +220,19 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) q = blk_init_queue(sas_non_host_smp_request, NULL); dev = &rphy->dev; name = dev->bus_id; + release = NULL; } else { q = blk_init_queue(sas_host_smp_request, NULL); dev = &shost->shost_gendev; snprintf(namebuf, sizeof(namebuf), "sas_host%d", shost->host_no); name = namebuf; + release = sas_host_release; } if (!q) return -ENOMEM; - error = bsg_register_queue(q, dev, name); + error = bsg_register_queue(q, dev, name, release); if (error) { blk_cleanup_queue(q); return -ENOMEM; @@ -253,7 +266,6 @@ static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy) return; bsg_unregister_queue(q); - blk_cleanup_queue(q); } /* @@ -261,7 +273,7 @@ static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy) */ static int sas_host_setup(struct transport_container *tc, struct device *dev, - struct class_device *cdev) + struct device *cdev) { struct Scsi_Host *shost = dev_to_shost(dev); struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); @@ -280,7 +292,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, } static int sas_host_remove(struct transport_container *tc, struct device *dev, - struct class_device *cdev) + struct device *cdev) { struct Scsi_Host *shost = dev_to_shost(dev); @@ -356,22 +368,24 @@ EXPORT_SYMBOL(sas_remove_host); #define sas_phy_show_simple(field, name, format_string, cast) \ static ssize_t \ -show_sas_phy_##name(struct class_device *cdev, char *buf) \ +show_sas_phy_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct sas_phy *phy = transport_class_to_phy(cdev); \ + struct sas_phy *phy = transport_class_to_phy(dev); \ \ return snprintf(buf, 20, format_string, cast phy->field); \ } #define sas_phy_simple_attr(field, name, format_string, type) \ sas_phy_show_simple(field, name, format_string, (type)) \ -static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) +static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) #define sas_phy_show_protocol(field, name) \ static ssize_t \ -show_sas_phy_##name(struct class_device *cdev, char *buf) \ +show_sas_phy_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct sas_phy *phy = transport_class_to_phy(cdev); \ + struct sas_phy *phy = transport_class_to_phy(dev); \ \ if (!phy->field) \ return snprintf(buf, 20, "none\n"); \ @@ -380,13 +394,14 @@ show_sas_phy_##name(struct class_device *cdev, char *buf) \ #define sas_phy_protocol_attr(field, name) \ sas_phy_show_protocol(field, name) \ -static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) +static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) #define sas_phy_show_linkspeed(field) \ static ssize_t \ -show_sas_phy_##field(struct class_device *cdev, char *buf) \ +show_sas_phy_##field(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct sas_phy *phy = transport_class_to_phy(cdev); \ + struct sas_phy *phy = transport_class_to_phy(dev); \ \ return get_sas_linkspeed_names(phy->field, buf); \ } @@ -394,10 +409,11 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \ /* Fudge to tell if we're minimum or maximum */ #define sas_phy_store_linkspeed(field) \ static ssize_t \ -store_sas_phy_##field(struct class_device *cdev, const char *buf, \ - size_t count) \ +store_sas_phy_##field(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ { \ - struct sas_phy *phy = transport_class_to_phy(cdev); \ + 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); \ u32 value; \ @@ -416,19 +432,20 @@ store_sas_phy_##field(struct class_device *cdev, const char *buf, \ #define sas_phy_linkspeed_rw_attr(field) \ sas_phy_show_linkspeed(field) \ sas_phy_store_linkspeed(field) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, \ +static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, \ store_sas_phy_##field) #define sas_phy_linkspeed_attr(field) \ sas_phy_show_linkspeed(field) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) +static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) #define sas_phy_show_linkerror(field) \ static ssize_t \ -show_sas_phy_##field(struct class_device *cdev, char *buf) \ +show_sas_phy_##field(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct sas_phy *phy = transport_class_to_phy(cdev); \ + 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; \ @@ -441,24 +458,25 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \ #define sas_phy_linkerror_attr(field) \ sas_phy_show_linkerror(field) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) +static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) static ssize_t -show_sas_device_type(struct class_device *cdev, char *buf) +show_sas_device_type(struct device *dev, + struct device_attribute *attr, char *buf) { - struct sas_phy *phy = transport_class_to_phy(cdev); + struct sas_phy *phy = transport_class_to_phy(dev); if (!phy->identify.device_type) return snprintf(buf, 20, "none\n"); return get_sas_device_type_names(phy->identify.device_type, buf); } -static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); +static DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); -static ssize_t do_sas_phy_enable(struct class_device *cdev, +static ssize_t do_sas_phy_enable(struct device *dev, size_t count, int enable) { - struct sas_phy *phy = transport_class_to_phy(cdev); + 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; @@ -470,18 +488,19 @@ static ssize_t do_sas_phy_enable(struct class_device *cdev, return count; }; -static ssize_t store_sas_phy_enable(struct class_device *cdev, - const char *buf, size_t count) +static ssize_t +store_sas_phy_enable(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { if (count < 1) return -EINVAL; switch (buf[0]) { case '0': - do_sas_phy_enable(cdev, count, 0); + do_sas_phy_enable(dev, count, 0); break; case '1': - do_sas_phy_enable(cdev, count, 1); + do_sas_phy_enable(dev, count, 1); break; default: return -EINVAL; @@ -490,20 +509,22 @@ static ssize_t store_sas_phy_enable(struct class_device *cdev, return count; } -static ssize_t show_sas_phy_enable(struct class_device *cdev, char *buf) +static ssize_t +show_sas_phy_enable(struct device *dev, struct device_attribute *attr, + char *buf) { - struct sas_phy *phy = transport_class_to_phy(cdev); + struct sas_phy *phy = transport_class_to_phy(dev); return snprintf(buf, 20, "%d", phy->enabled); } -static CLASS_DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable, +static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable, store_sas_phy_enable); -static ssize_t do_sas_phy_reset(struct class_device *cdev, - size_t count, int hard_reset) +static ssize_t +do_sas_phy_reset(struct device *dev, size_t count, int hard_reset) { - struct sas_phy *phy = transport_class_to_phy(cdev); + 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; @@ -514,19 +535,21 @@ static ssize_t do_sas_phy_reset(struct class_device *cdev, return count; }; -static ssize_t store_sas_link_reset(struct class_device *cdev, - const char *buf, size_t count) +static ssize_t +store_sas_link_reset(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - return do_sas_phy_reset(cdev, count, 0); + return do_sas_phy_reset(dev, count, 0); } -static CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); +static DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); -static ssize_t store_sas_hard_reset(struct class_device *cdev, - const char *buf, size_t count) +static ssize_t +store_sas_hard_reset(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - return do_sas_phy_reset(cdev, count, 1); + return do_sas_phy_reset(dev, count, 1); } -static CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); +static DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); sas_phy_protocol_attr(identify.initiator_port_protocols, initiator_port_protocols); @@ -695,16 +718,17 @@ EXPORT_SYMBOL(scsi_is_sas_phy); */ #define sas_port_show_simple(field, name, format_string, cast) \ static ssize_t \ -show_sas_port_##name(struct class_device *cdev, char *buf) \ +show_sas_port_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct sas_port *port = transport_class_to_sas_port(cdev); \ + struct sas_port *port = transport_class_to_sas_port(dev); \ \ return snprintf(buf, 20, format_string, cast port->field); \ } #define sas_port_simple_attr(field, name, format_string, type) \ sas_port_show_simple(field, name, format_string, (type)) \ -static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL) +static DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL) sas_port_simple_attr(num_phys, num_phys, "%d\n", int); @@ -1017,23 +1041,25 @@ EXPORT_SYMBOL(sas_port_mark_backlink); #define sas_rphy_show_simple(field, name, format_string, cast) \ static ssize_t \ -show_sas_rphy_##name(struct class_device *cdev, char *buf) \ +show_sas_rphy_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ + struct sas_rphy *rphy = transport_class_to_rphy(dev); \ \ return snprintf(buf, 20, format_string, cast rphy->field); \ } #define sas_rphy_simple_attr(field, name, format_string, type) \ sas_rphy_show_simple(field, name, format_string, (type)) \ -static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ +static SAS_DEVICE_ATTR(rphy, name, S_IRUGO, \ show_sas_rphy_##name, NULL) #define sas_rphy_show_protocol(field, name) \ static ssize_t \ -show_sas_rphy_##name(struct class_device *cdev, char *buf) \ +show_sas_rphy_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ + struct sas_rphy *rphy = transport_class_to_rphy(dev); \ \ if (!rphy->field) \ return snprintf(buf, 20, "none\n"); \ @@ -1042,13 +1068,14 @@ show_sas_rphy_##name(struct class_device *cdev, char *buf) \ #define sas_rphy_protocol_attr(field, name) \ sas_rphy_show_protocol(field, name) \ -static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ +static SAS_DEVICE_ATTR(rphy, name, S_IRUGO, \ show_sas_rphy_##name, NULL) static ssize_t -show_sas_rphy_device_type(struct class_device *cdev, char *buf) +show_sas_rphy_device_type(struct device *dev, + struct device_attribute *attr, char *buf) { - struct sas_rphy *rphy = transport_class_to_rphy(cdev); + struct sas_rphy *rphy = transport_class_to_rphy(dev); if (!rphy->identify.device_type) return snprintf(buf, 20, "none\n"); @@ -1056,13 +1083,14 @@ show_sas_rphy_device_type(struct class_device *cdev, char *buf) rphy->identify.device_type, buf); } -static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, +static SAS_DEVICE_ATTR(rphy, device_type, S_IRUGO, show_sas_rphy_device_type, NULL); static ssize_t -show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) +show_sas_rphy_enclosure_identifier(struct device *dev, + struct device_attribute *attr, char *buf) { - struct sas_rphy *rphy = transport_class_to_rphy(cdev); + struct sas_rphy *rphy = transport_class_to_rphy(dev); struct sas_phy *phy = dev_to_phy(rphy->dev.parent); struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); struct sas_internal *i = to_sas_internal(shost->transportt); @@ -1082,13 +1110,14 @@ show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); } -static SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, +static SAS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, show_sas_rphy_enclosure_identifier, NULL); static ssize_t -show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) +show_sas_rphy_bay_identifier(struct device *dev, + struct device_attribute *attr, char *buf) { - struct sas_rphy *rphy = transport_class_to_rphy(cdev); + struct sas_rphy *rphy = transport_class_to_rphy(dev); struct sas_phy *phy = dev_to_phy(rphy->dev.parent); struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); struct sas_internal *i = to_sas_internal(shost->transportt); @@ -1103,7 +1132,7 @@ show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) return sprintf(buf, "%d\n", val); } -static SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, +static SAS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, show_sas_rphy_bay_identifier, NULL); sas_rphy_protocol_attr(identify.initiator_port_protocols, @@ -1161,9 +1190,10 @@ static DECLARE_TRANSPORT_CLASS(sas_end_dev_class, #define sas_end_dev_show_simple(field, name, format_string, cast) \ static ssize_t \ -show_sas_end_dev_##name(struct class_device *cdev, char *buf) \ +show_sas_end_dev_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ + struct sas_rphy *rphy = transport_class_to_rphy(dev); \ struct sas_end_device *rdev = rphy_to_end_device(rphy); \ \ return snprintf(buf, 20, format_string, cast rdev->field); \ @@ -1171,7 +1201,7 @@ show_sas_end_dev_##name(struct class_device *cdev, char *buf) \ #define sas_end_dev_simple_attr(field, name, format_string, type) \ sas_end_dev_show_simple(field, name, format_string, (type)) \ -static SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ +static SAS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ show_sas_end_dev_##name, NULL) sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); @@ -1185,9 +1215,10 @@ static DECLARE_TRANSPORT_CLASS(sas_expander_class, #define sas_expander_show_simple(field, name, format_string, cast) \ static ssize_t \ -show_sas_expander_##name(struct class_device *cdev, char *buf) \ +show_sas_expander_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ - struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ + struct sas_rphy *rphy = transport_class_to_rphy(dev); \ struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ \ return snprintf(buf, 20, format_string, cast edev->field); \ @@ -1195,7 +1226,7 @@ show_sas_expander_##name(struct class_device *cdev, char *buf) \ #define sas_expander_simple_attr(field, name, format_string, type) \ sas_expander_show_simple(field, name, format_string, (type)) \ -static SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \ +static SAS_DEVICE_ATTR(expander, name, S_IRUGO, \ show_sas_expander_##name, NULL) sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); @@ -1282,6 +1313,9 @@ static void sas_expander_release(struct device *dev) struct sas_rphy *rphy = dev_to_rphy(dev); struct sas_expander_device *edev = rphy_to_expander_device(rphy); + if (rphy->q) + blk_cleanup_queue(rphy->q); + put_device(dev->parent); kfree(edev); } @@ -1291,6 +1325,9 @@ static void sas_end_device_release(struct device *dev) struct sas_rphy *rphy = dev_to_rphy(dev); struct sas_end_device *edev = rphy_to_end_device(rphy); + if (rphy->q) + blk_cleanup_queue(rphy->q); + put_device(dev->parent); kfree(edev); } @@ -1554,14 +1591,14 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, */ #define SETUP_TEMPLATE(attrb, field, perm, test) \ - i->private_##attrb[count] = class_device_attr_##field; \ + i->private_##attrb[count] = dev_attr_##field; \ i->private_##attrb[count].attr.mode = perm; \ i->attrb[count] = &i->private_##attrb[count]; \ if (test) \ count++ #define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm) \ - i->private_##attrb[count] = class_device_attr_##field; \ + i->private_##attrb[count] = dev_attr_##field; \ i->private_##attrb[count].attr.mode = perm; \ if (ro_test) { \ i->private_##attrb[count].attr.mode = ro_perm; \ |