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 55addd7..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;
 }