]> git.hungrycats.org Git - linux/commitdiff
[PATCH] target code updates to support scanned targets
authorAndrew Vasquez <andrew.vasquez@qlogic.com>
Tue, 15 Mar 2005 11:49:34 +0000 (05:49 -0600)
committerJames Bottomley <jejb@titanic.il.steeleye.com>
Tue, 15 Mar 2005 11:49:34 +0000 (05:49 -0600)
* add scsi_target_block() and scsi_target_unblock() routines which
  take a generic-device.  Side note:  there are mixture of
  scsi_<object>_<action>() and scsi_<action>_<noun>() functions defined
  in the scsi APIs -- going forward are there any 'guides' or
  suggestions on which to choose?
* modify scsi_remove_target() to take a generic-device.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
include/scsi/scsi_device.h

index bf76514298438216803d39b67c7e3f70f5dc6617..c47bc3f483b63988aa272b1f7bc9e4236a984ba4 100644 (file)
@@ -1935,3 +1935,55 @@ scsi_internal_device_unblock(struct scsi_device *sdev)
        return 0;
 }
 EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
+
+static void
+device_block(struct scsi_device *sdev, void *data)
+{
+       scsi_internal_device_block(sdev);
+}
+
+static int
+target_block(struct device *dev, void *data)
+{
+       if (scsi_is_target_device(dev))
+               starget_for_each_device(to_scsi_target(dev), NULL,
+                                       device_block);
+       return 0;
+}
+
+void
+scsi_target_block(struct device *dev)
+{
+       if (scsi_is_target_device(dev))
+               starget_for_each_device(to_scsi_target(dev), NULL,
+                                       device_block);
+       else
+               device_for_each_child(dev, NULL, target_block);
+}
+EXPORT_SYMBOL_GPL(scsi_target_block);
+
+static void
+device_unblock(struct scsi_device *sdev, void *data)
+{
+       scsi_internal_device_unblock(sdev);
+}
+
+static int
+target_unblock(struct device *dev, void *data)
+{
+       if (scsi_is_target_device(dev))
+               starget_for_each_device(to_scsi_target(dev), NULL,
+                                       device_unblock);
+       return 0;
+}
+
+void
+scsi_target_unblock(struct device *dev)
+{
+       if (scsi_is_target_device(dev))
+               starget_for_each_device(to_scsi_target(dev), NULL,
+                                       device_unblock);
+       else
+               device_for_each_child(dev, NULL, target_unblock);
+}
+EXPORT_SYMBOL_GPL(scsi_target_unblock);
index b8f5eab1cc5914595beb49c6652277504f66841f..b6165617a0de9ad4ca2696d1139e6e3da9d03027 100644 (file)
@@ -1399,7 +1399,7 @@ void scsi_forget_host(struct Scsi_Host *shost)
        spin_lock_irqsave(shost->host_lock, flags);
        list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
                spin_unlock_irqrestore(shost->host_lock, flags);
-               scsi_remove_target(starget);
+               scsi_remove_target(&starget->dev);
                spin_lock_irqsave(shost->host_lock, flags);
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
index 2674624bc2dcd8a2cd2c885e34858dab1731c7bb..61afa000b244cf248de3b28ec9691e97815375f2 100644 (file)
@@ -652,15 +652,7 @@ out:
 }
 EXPORT_SYMBOL(scsi_remove_device);
 
-/**
- * scsi_remove_target - try to remove a target and all its devices
- * @starget: the target to remove
- *
- * Note: This is slightly racy.  It is possible that if the user
- * requests the addition of another device then the target won't be
- * removed.
- */
-void scsi_remove_target(struct scsi_target *starget)
+void __scsi_remove_target(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        unsigned long flags;
@@ -679,6 +671,31 @@ void scsi_remove_target(struct scsi_target *starget)
        spin_unlock_irqrestore(shost->host_lock, flags);
        scsi_target_reap(starget);
 }
+
+/**
+ * scsi_remove_target - try to remove a target and all its devices
+ * @dev: generic starget or parent of generic stargets to be removed
+ *
+ * Note: This is slightly racy.  It is possible that if the user
+ * requests the addition of another device then the target won't be
+ * removed.
+ */
+void scsi_remove_target(struct device *dev)
+{
+       struct device *rdev, *idev, *next;
+
+       if (scsi_is_target_device(dev)) {
+               __scsi_remove_target(to_scsi_target(dev));
+               return;
+       }
+
+       rdev = get_device(dev);
+       list_for_each_entry_safe(idev, next, &dev->children, node) {
+               if (scsi_is_target_device(idev))
+                       __scsi_remove_target(to_scsi_target(idev));
+       }
+       put_device(rdev);
+}
 EXPORT_SYMBOL(scsi_remove_target);
 
 int scsi_register_driver(struct device_driver *drv)
index 8e0606110057a11ce2f9ec6ec06fd8d4b3b04a0b..d528aeb443ca224f0805d450d9ba54c18bd761a8 100644 (file)
@@ -236,7 +236,9 @@ extern void scsi_target_resume(struct scsi_target *);
 extern void scsi_scan_target(struct device *parent, unsigned int channel,
                             unsigned int id, unsigned int lun, int rescan);
 extern void scsi_target_reap(struct scsi_target *);
-extern void scsi_remove_target(struct scsi_target *);
+extern void scsi_target_block(struct device *);
+extern void scsi_target_unblock(struct device *);
+extern void scsi_remove_target(struct device *);
 extern const char *scsi_device_state_name(enum scsi_device_state);
 extern int scsi_is_sdev_device(const struct device *);
 extern int scsi_is_target_device(const struct device *);