Merge branch 'v5.16/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/amlogic...
[linux-2.6-microblaze.git] / drivers / scsi / scsi_sysfs.c
index d3d3622..d4edce9 100644 (file)
@@ -792,6 +792,7 @@ store_state_field(struct device *dev, struct device_attribute *attr,
        int i, ret;
        struct scsi_device *sdev = to_scsi_device(dev);
        enum scsi_device_state state = 0;
+       bool rescan_dev = false;
 
        for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
                const int len = strlen(sdev_states[i].name);
@@ -810,20 +811,27 @@ store_state_field(struct device *dev, struct device_attribute *attr,
        }
 
        mutex_lock(&sdev->state_mutex);
-       ret = scsi_device_set_state(sdev, state);
-       /*
-        * If the device state changes to SDEV_RUNNING, we need to
-        * run the queue to avoid I/O hang, and rescan the device
-        * to revalidate it. Running the queue first is necessary
-        * because another thread may be waiting inside
-        * blk_mq_freeze_queue_wait() and because that call may be
-        * waiting for pending I/O to finish.
-        */
-       if (ret == 0 && state == SDEV_RUNNING) {
+       if (sdev->sdev_state == SDEV_RUNNING && state == SDEV_RUNNING) {
+               ret = 0;
+       } else {
+               ret = scsi_device_set_state(sdev, state);
+               if (ret == 0 && state == SDEV_RUNNING)
+                       rescan_dev = true;
+       }
+       mutex_unlock(&sdev->state_mutex);
+
+       if (rescan_dev) {
+               /*
+                * If the device state changes to SDEV_RUNNING, we need to
+                * run the queue to avoid I/O hang, and rescan the device
+                * to revalidate it. Running the queue first is necessary
+                * because another thread may be waiting inside
+                * blk_mq_freeze_queue_wait() and because that call may be
+                * waiting for pending I/O to finish.
+                */
                blk_mq_run_hw_queues(sdev->request_queue, true);
                scsi_rescan_device(dev);
        }
-       mutex_unlock(&sdev->state_mutex);
 
        return ret == 0 ? count : -EINVAL;
 }
@@ -1383,6 +1391,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
                         * We're treating error on bsg register as non-fatal, so
                         * pretend nothing went wrong.
                         */
+                       error = PTR_ERR(sdev->bsg_dev);
                        sdev_printk(KERN_INFO, sdev,
                                    "Failed to register bsg queue, errno=%d\n",
                                    error);
@@ -1580,7 +1589,6 @@ 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;
@@ -1592,15 +1600,7 @@ 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_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));
+       sdev->sdev_gendev.groups = hostt->sdev_groups;
 
        device_initialize(&sdev->sdev_dev);
        sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev);