#define SCSI_SENSE_VALID(scmd) \
        (((scmd)->sense_buffer[0] & 0x70) == 0x70)
 
-/*
- * Special value for scanning to specify scanning or rescanning of all
- * possible channels, (target) ids, or luns on a given shost.
- */
-#define SCAN_WILD_CARD ~0
-
 /* hosts.c */
 extern int scsi_init_hosts(void);
 extern void scsi_exit_hosts(void);
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
        if (IS_ERR(shost))
                return PTR_ERR(shost);
 
-       error = scsi_scan_host_selected(shost, channel, id, lun, 1);
+       if (shost->transportt->user_scan)
+               error = shost->transportt->user_scan(shost, channel, id, lun);
+       else
+               error = scsi_scan_host_selected(shost, channel, id, lun, 1);
        scsi_host_put(shost);
        return error;
 }
 
        struct scsi_target *starget;
        struct scsi_target *found_target;
 
-       /*
-        * Obtain the real parent from the transport. The transport
-        * is allowed to fail (no error) if there is nothing at that
-        * target id.
-        */
-       if (shost->transportt->target_parent) {
-               spin_lock_irqsave(shost->host_lock, flags);
-               parent = shost->transportt->target_parent(shost, channel, id);
-               spin_unlock_irqrestore(shost->host_lock, flags);
-               if (!parent)
-                       return NULL;
-       }
-
        starget = kmalloc(size, GFP_KERNEL);
        if (!starget) {
                printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
        struct scsi_device *sdev;
        struct device *parent = &shost->shost_gendev;
        int res;
-       struct scsi_target *starget = scsi_alloc_target(parent, channel, id);
+       struct scsi_target *starget;
 
+       starget = scsi_alloc_target(parent, channel, id);
        if (!starget)
                return ERR_PTR(-ENOMEM);
 
 
                return -EINVAL;
        if (check_set(&lun, s3))
                return -EINVAL;
-       res = scsi_scan_host_selected(shost, channel, id, lun, 1);
+       if (shost->transportt->user_scan)
+               res = shost->transportt->user_scan(shost, channel, id, lun);
+       else
+               res = scsi_scan_host_selected(shost, channel, id, lun, 1);
        return res;
 }
 
 
 /*
  * Must be called with shost->host_lock held
  */
-static struct device *fc_target_parent(struct Scsi_Host *shost,
-                                       int channel, uint id)
+static int fc_user_scan(struct Scsi_Host *shost, uint channel,
+               uint id, uint lun)
 {
        struct fc_rport *rport;
 
-       list_for_each_entry(rport, &fc_host_rports(shost), peers)
-               if ((rport->channel == channel) &&
-                   (rport->scsi_target_id == id))
-                       return &rport->dev;
+       list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+               if (rport->scsi_target_id == -1)
+                       continue;
 
-       return NULL;
+               if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
+                   (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
+                       scsi_scan_target(&rport->dev, rport->channel,
+                                        rport->scsi_target_id, lun, 1);
+               }
+       }
+
+       return 0;
 }
 
 struct scsi_transport_template *
        /* Transport uses the shost workq for scsi scanning */
        i->t.create_work_queue = 1;
 
-       i->t.target_parent = fc_target_parent;
+       i->t.user_scan = fc_user_scan;
        
        /*
         * Setup SCSI Target Attributes.
 
 #include <linux/slab.h>
 #include <linux/string.h>
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport.h>
 
 struct sas_host_attrs {
        struct list_head rphy_list;
-       spinlock_t lock;
+       struct mutex lock;
        u32 next_target_id;
 };
 #define to_sas_host_attrs(host)        ((struct sas_host_attrs *)(host)->shost_data)
        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 
        INIT_LIST_HEAD(&sas_host->rphy_list);
-       spin_lock_init(&sas_host->lock);
+       mutex_init(&sas_host->lock);
        sas_host->next_target_id = 0;
        return 0;
 }
        transport_add_device(&rphy->dev);
        transport_configure_device(&rphy->dev);
 
-       spin_lock(&sas_host->lock);
+       mutex_lock(&sas_host->lock);
        list_add_tail(&rphy->list, &sas_host->rphy_list);
        if (identify->device_type == SAS_END_DEVICE &&
            (identify->target_port_protocols &
                rphy->scsi_target_id = sas_host->next_target_id++;
        else
                rphy->scsi_target_id = -1;
-       spin_unlock(&sas_host->lock);
+       mutex_unlock(&sas_host->lock);
 
        if (rphy->scsi_target_id != -1) {
                scsi_scan_target(&rphy->dev, parent->number,
        struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 
-       spin_lock(&sas_host->lock);
+       mutex_lock(&sas_host->lock);
        list_del(&rphy->list);
-       spin_unlock(&sas_host->lock);
+       mutex_unlock(&sas_host->lock);
 
        transport_destroy_device(&rphy->dev);
        put_device(rphy->dev.parent);
        device_del(dev);
        transport_destroy_device(dev);
 
-       spin_lock(&sas_host->lock);
+       mutex_lock(&sas_host->lock);
        list_del(&rphy->list);
-       spin_unlock(&sas_host->lock);
+       mutex_unlock(&sas_host->lock);
 
        parent->rphy = NULL;
 
  * SCSI scan helper
  */
 
-static struct device *sas_target_parent(struct Scsi_Host *shost,
-                                       int channel, uint id)
+static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+               uint id, uint lun)
 {
        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
        struct sas_rphy *rphy;
-       struct device *dev = NULL;
 
-       spin_lock(&sas_host->lock);
+       mutex_lock(&sas_host->lock);
        list_for_each_entry(rphy, &sas_host->rphy_list, list) {
                struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
-               if (parent->number == channel &&
-                   rphy->scsi_target_id == id)
-                       dev = &rphy->dev;
+
+               if (rphy->scsi_target_id == -1)
+                       continue;
+
+               if ((channel == SCAN_WILD_CARD || channel == parent->number) &&
+                   (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
+                       scsi_scan_target(&rphy->dev, parent->number,
+                                        rphy->scsi_target_id, lun, 1);
+               }
        }
-       spin_unlock(&sas_host->lock);
+       mutex_unlock(&sas_host->lock);
 
-       return dev;
+       return 0;
 }
 
 
                return NULL;
        memset(i, 0, sizeof(struct sas_internal));
 
-       i->t.target_parent = sas_target_parent;
+       i->t.user_scan = sas_user_scan;
 
        i->t.host_attrs.ac.attrs = &i->host_attrs[0];
        i->t.host_attrs.ac.class = &sas_host_class.class;
 
 #define MAX_SCSI_DEVICE_CODE 15
 extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
 
+/*
+ * Special value for scanning to specify scanning or rescanning of all
+ * possible channels, (target) ids, or luns on a given shost.
+ */
+#define SCAN_WILD_CARD ~0
+
 /*
  *      SCSI opcodes
  */
 
        struct transport_container device_attrs;
 
        /*
-        * If set, call target_parent prior to allocating a scsi_target,
-        * so we get the appropriate parent for the target. This function
-        * is required for transports like FC and iSCSI that do not put the
-        * scsi_target under scsi_host.
+        * If set, called from sysfs and legacy procfs rescanning code.
         */
-       struct device *(*target_parent)(struct Scsi_Host *, int, uint);
+       int (*user_scan)(struct Scsi_Host *, uint, uint, uint);
 
        /* The size of the specific transport attribute structure (a
         * space of this size will be left at the end of the