[SCSI] core, classes, mpt2sas: have scsi_internal_device_unblock take new state
[deliverable/linux.git] / drivers / scsi / scsi_lib.c
index 340c569d45355095aabfc232e042401c9dcbce4e..36521a0ac54ba50a7bfe3745f3bf1452293141d0 100644 (file)
@@ -2444,6 +2444,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block);
 /**
  * scsi_internal_device_unblock - resume a device after a block request
  * @sdev:      device to resume
+ * @new_state: state to set devices to after unblocking
  *
  * Called by scsi lld's or the midlayer to restart the device queue
  * for the previously suspended scsi device.  Called from interrupt or
@@ -2453,25 +2454,30 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block);
  *
  * Notes:       
  *     This routine transitions the device to the SDEV_RUNNING state
- *     (which must be a legal transition) allowing the midlayer to
- *     goose the queue for this device.  This routine assumes the 
- *     host_lock is held upon entry.
+ *     or to one of the offline states (which must be a legal transition)
+ *     allowing the midlayer to goose the queue for this device. This
+ *     routine assumes the host_lock is held upon entry.
  */
 int
-scsi_internal_device_unblock(struct scsi_device *sdev)
+scsi_internal_device_unblock(struct scsi_device *sdev,
+                            enum scsi_device_state new_state)
 {
        struct request_queue *q = sdev->request_queue; 
        unsigned long flags;
-       
-       /* 
-        * Try to transition the scsi device to SDEV_RUNNING
-        * and goose the device queue if successful.  
+
+       /*
+        * Try to transition the scsi device to SDEV_RUNNING or one of the
+        * offlined states and goose the device queue if successful.
         */
        if (sdev->sdev_state == SDEV_BLOCK)
-               sdev->sdev_state = SDEV_RUNNING;
-       else if (sdev->sdev_state == SDEV_CREATED_BLOCK)
-               sdev->sdev_state = SDEV_CREATED;
-       else if (sdev->sdev_state != SDEV_CANCEL &&
+               sdev->sdev_state = new_state;
+       else if (sdev->sdev_state == SDEV_CREATED_BLOCK) {
+               if (new_state == SDEV_TRANSPORT_OFFLINE ||
+                   new_state == SDEV_OFFLINE)
+                       sdev->sdev_state = new_state;
+               else
+                       sdev->sdev_state = SDEV_CREATED;
+       } else if (sdev->sdev_state != SDEV_CANCEL &&
                 sdev->sdev_state != SDEV_OFFLINE)
                return -EINVAL;
 
@@ -2512,26 +2518,26 @@ EXPORT_SYMBOL_GPL(scsi_target_block);
 static void
 device_unblock(struct scsi_device *sdev, void *data)
 {
-       scsi_internal_device_unblock(sdev);
+       scsi_internal_device_unblock(sdev, *(enum scsi_device_state *)data);
 }
 
 static int
 target_unblock(struct device *dev, void *data)
 {
        if (scsi_is_target_device(dev))
-               starget_for_each_device(to_scsi_target(dev), NULL,
+               starget_for_each_device(to_scsi_target(dev), data,
                                        device_unblock);
        return 0;
 }
 
 void
-scsi_target_unblock(struct device *dev)
+scsi_target_unblock(struct device *dev, enum scsi_device_state new_state)
 {
        if (scsi_is_target_device(dev))
-               starget_for_each_device(to_scsi_target(dev), NULL,
+               starget_for_each_device(to_scsi_target(dev), &new_state,
                                        device_unblock);
        else
-               device_for_each_child(dev, NULL, target_unblock);
+               device_for_each_child(dev, &new_state, target_unblock);
 }
 EXPORT_SYMBOL_GPL(scsi_target_unblock);
 
This page took 0.024929 seconds and 5 git commands to generate.