summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_fc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-27 11:25:00 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-27 11:25:00 -0700
commit064922a805ec7aadfafdd27aa6b4908d737c3c1d (patch)
tree922d058f751964ccf73f5705d7c492b6d45a9425 /drivers/scsi/scsi_transport_fc.c
parent42cadc86008aae0fd9ff31642dc01ed50723cf32 (diff)
parentecc1241e80a0bdc854b1602a44be3ad106753d4f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (40 commits) [SCSI] jazz_esp, sgiwd93, sni_53c710, sun3x_esp: fix platform driver hotplug/coldplug [SCSI] aic7xxx: add const [SCSI] aic7xxx: add static [SCSI] aic7xxx: Update _shipped files [SCSI] aic7xxx: teach aicasm to not emit unused debug code/data [SCSI] qla2xxx: Update version number to 8.02.01-k2. [SCSI] qla2xxx: Correct regression in relogin code. [SCSI] qla2xxx: Correct misc. endian and byte-ordering issues. [SCSI] qla2xxx: make qla2x00_issue_iocb_timeout() static [SCSI] qla2xxx: qla_os.c, make 2 functions static [SCSI] qla2xxx: Re-register FDMI information after a LIP. [SCSI] qla2xxx: Correct SRB usage-after-completion/free issues. [SCSI] qla2xxx: Correct ISP84XX verify-chip response handling. [SCSI] qla2xxx: Wakeup DPC thread to process any deferred-work requests. [SCSI] qla2xxx: Collapse RISC-RAM retrieval code during a firmware-dump. [SCSI] m68k: new mac_esp scsi driver [SCSI] zfcp: Add some statistics provided by the FCP adapter to the sysfs [SCSI] zfcp: Print some messages only during ERP [SCSI] zfcp: Wait for free SBAL during exchange config [SCSI] scsi_transport_fc: fc_user_scan correction ...
Diffstat (limited to 'drivers/scsi/scsi_transport_fc.c')
-rw-r--r--drivers/scsi/scsi_transport_fc.c60
1 files changed, 53 insertions, 7 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 6b092a6c295..5fd64e70029 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -1961,12 +1961,17 @@ fc_timed_out(struct scsi_cmnd *scmd)
}
/*
- * Must be called with shost->host_lock held
+ * Called by fc_user_scan to locate an rport on the shost that
+ * matches the channel and target id, and invoke scsi_scan_target()
+ * on the rport.
*/
-static int fc_user_scan(struct Scsi_Host *shost, uint channel,
- uint id, uint lun)
+static void
+fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun)
{
struct fc_rport *rport;
+ unsigned long flags;
+
+ spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry(rport, &fc_host_rports(shost), peers) {
if (rport->scsi_target_id == -1)
@@ -1975,13 +1980,54 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel,
if (rport->port_state != FC_PORTSTATE_ONLINE)
continue;
- 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);
+ if ((channel == rport->channel) &&
+ (id == rport->scsi_target_id)) {
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ scsi_scan_target(&rport->dev, channel, id, lun, 1);
+ return;
}
}
+ spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
+/*
+ * Called via sysfs scan routines. Necessary, as the FC transport
+ * wants to place all target objects below the rport object. So this
+ * routine must invoke the scsi_scan_target() routine with the rport
+ * object as the parent.
+ */
+static int
+fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, uint lun)
+{
+ uint chlo, chhi;
+ uint tgtlo, tgthi;
+
+ if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
+ ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
+ ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
+ return -EINVAL;
+
+ if (channel == SCAN_WILD_CARD) {
+ chlo = 0;
+ chhi = shost->max_channel + 1;
+ } else {
+ chlo = channel;
+ chhi = channel + 1;
+ }
+
+ if (id == SCAN_WILD_CARD) {
+ tgtlo = 0;
+ tgthi = shost->max_id;
+ } else {
+ tgtlo = id;
+ tgthi = id + 1;
+ }
+
+ for ( ; chlo < chhi; chlo++)
+ for ( ; tgtlo < tgthi; tgtlo++)
+ fc_user_scan_tgt(shost, chlo, tgtlo, lun);
+
return 0;
}