diff options
Diffstat (limited to 'drivers/scsi/scsi_sysfs.c')
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 81 |
1 files changed, 41 insertions, 40 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b598dfcbb67d..3d98db6a97e6 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -424,15 +424,10 @@ static struct attribute *scsi_sysfs_shost_attrs[] = { NULL }; -static struct attribute_group scsi_shost_attr_group = { +const struct attribute_group scsi_shost_attr_group = { .attrs = scsi_sysfs_shost_attrs, }; -const struct attribute_group *scsi_sysfs_shost_attr_groups[] = { - &scsi_shost_attr_group, - NULL -}; - static void scsi_device_cls_release(struct device *class_dev) { struct scsi_device *sdev; @@ -1333,7 +1328,7 @@ static int scsi_target_add(struct scsi_target *starget) **/ int scsi_sysfs_add_sdev(struct scsi_device *sdev) { - int error, i; + int error; struct scsi_target *starget = sdev->sdev_target; error = scsi_target_add(starget); @@ -1386,23 +1381,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) } } - /* add additional host specific attributes */ - if (sdev->host->hostt->sdev_attrs) { - for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) { - error = device_create_file(&sdev->sdev_gendev, - sdev->host->hostt->sdev_attrs[i]); - if (error) - return error; - } - } - - if (sdev->host->hostt->sdev_groups) { - error = sysfs_create_groups(&sdev->sdev_gendev.kobj, - sdev->host->hostt->sdev_groups); - if (error) - return error; - } - scsi_autopm_put_device(sdev); return error; } @@ -1442,10 +1420,6 @@ void __scsi_remove_device(struct scsi_device *sdev) if (res != 0) return; - if (sdev->host->hostt->sdev_groups) - sysfs_remove_groups(&sdev->sdev_gendev.kobj, - sdev->host->hostt->sdev_groups); - if (IS_ENABLED(CONFIG_BLK_DEV_BSG) && sdev->bsg_dev) bsg_unregister_queue(sdev->bsg_dev); device_unregister(&sdev->sdev_dev); @@ -1584,23 +1558,31 @@ EXPORT_SYMBOL(scsi_register_interface); **/ int scsi_sysfs_add_host(struct Scsi_Host *shost) { - int error, i; - - /* add host specific attributes */ - if (shost->hostt->shost_attrs) { - for (i = 0; shost->hostt->shost_attrs[i]; i++) { - error = device_create_file(&shost->shost_dev, - shost->hostt->shost_attrs[i]); - if (error) - return error; - } - } - transport_register_device(&shost->shost_gendev); transport_configure_device(&shost->shost_gendev); return 0; } +/* + * Convert an array of struct device_attribute pointers into an array of + * struct attribute pointers. + */ +struct attribute **scsi_convert_dev_attrs(struct device *dev, + struct device_attribute **dev_attr) +{ + struct attribute **attrs; + int i; + + for (i = 0; dev_attr[i]; i++) + ; + attrs = devm_kzalloc(dev, (i + 1) * sizeof(*attrs), GFP_KERNEL); + if (!attrs) + return NULL; + for (i = 0; dev_attr[i]; i++) + attrs[i] = &dev_attr[i]->attr; + return attrs; +} + static struct device_type scsi_dev_type = { .name = "scsi_device", .release = scsi_device_dev_release, @@ -1609,8 +1591,10 @@ static struct device_type scsi_dev_type = { void scsi_sysfs_device_initialize(struct scsi_device *sdev) { + int i, j = 0; unsigned long flags; struct Scsi_Host *shost = sdev->host; + struct scsi_host_template *hostt = shost->hostt; struct scsi_target *starget = sdev->sdev_target; device_initialize(&sdev->sdev_gendev); @@ -1619,6 +1603,23 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) scsi_enable_async_suspend(&sdev->sdev_gendev); dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%llu", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); + sdev->gendev_attr_groups[j++] = &scsi_sdev_attr_group; + if (hostt->sdev_attrs) { + sdev->lld_attr_group = (struct attribute_group){ + .attrs = scsi_convert_dev_attrs(&sdev->sdev_gendev, + hostt->sdev_attrs) + }; + if (sdev->lld_attr_group.attrs) + sdev->gendev_attr_groups[j++] = &sdev->lld_attr_group; + } + if (hostt->sdev_groups) { + for (i = 0; hostt->sdev_groups[i] && + j < ARRAY_SIZE(sdev->gendev_attr_groups); + i++, j++) { + sdev->gendev_attr_groups[j] = hostt->sdev_groups[i]; + } + } + WARN_ON_ONCE(j >= ARRAY_SIZE(sdev->gendev_attr_groups)); device_initialize(&sdev->sdev_dev); sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev); |