diff options
-rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 6b092a6c295d..5fd64e70029d 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) | |||
1961 | } | 1961 | } |
1962 | 1962 | ||
1963 | /* | 1963 | /* |
1964 | * Must be called with shost->host_lock held | 1964 | * Called by fc_user_scan to locate an rport on the shost that |
1965 | * matches the channel and target id, and invoke scsi_scan_target() | ||
1966 | * on the rport. | ||
1965 | */ | 1967 | */ |
1966 | static int fc_user_scan(struct Scsi_Host *shost, uint channel, | 1968 | static void |
1967 | uint id, uint lun) | 1969 | fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun) |
1968 | { | 1970 | { |
1969 | struct fc_rport *rport; | 1971 | struct fc_rport *rport; |
1972 | unsigned long flags; | ||
1973 | |||
1974 | spin_lock_irqsave(shost->host_lock, flags); | ||
1970 | 1975 | ||
1971 | list_for_each_entry(rport, &fc_host_rports(shost), peers) { | 1976 | list_for_each_entry(rport, &fc_host_rports(shost), peers) { |
1972 | if (rport->scsi_target_id == -1) | 1977 | if (rport->scsi_target_id == -1) |
@@ -1975,13 +1980,54 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel, | |||
1975 | if (rport->port_state != FC_PORTSTATE_ONLINE) | 1980 | if (rport->port_state != FC_PORTSTATE_ONLINE) |
1976 | continue; | 1981 | continue; |
1977 | 1982 | ||
1978 | if ((channel == SCAN_WILD_CARD || channel == rport->channel) && | 1983 | if ((channel == rport->channel) && |
1979 | (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) { | 1984 | (id == rport->scsi_target_id)) { |
1980 | scsi_scan_target(&rport->dev, rport->channel, | 1985 | spin_unlock_irqrestore(shost->host_lock, flags); |
1981 | rport->scsi_target_id, lun, 1); | 1986 | scsi_scan_target(&rport->dev, channel, id, lun, 1); |
1987 | return; | ||
1982 | } | 1988 | } |
1983 | } | 1989 | } |
1984 | 1990 | ||
1991 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1992 | } | ||
1993 | |||
1994 | /* | ||
1995 | * Called via sysfs scan routines. Necessary, as the FC transport | ||
1996 | * wants to place all target objects below the rport object. So this | ||
1997 | * routine must invoke the scsi_scan_target() routine with the rport | ||
1998 | * object as the parent. | ||
1999 | */ | ||
2000 | static int | ||
2001 | fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, uint lun) | ||
2002 | { | ||
2003 | uint chlo, chhi; | ||
2004 | uint tgtlo, tgthi; | ||
2005 | |||
2006 | if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || | ||
2007 | ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || | ||
2008 | ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) | ||
2009 | return -EINVAL; | ||
2010 | |||
2011 | if (channel == SCAN_WILD_CARD) { | ||
2012 | chlo = 0; | ||
2013 | chhi = shost->max_channel + 1; | ||
2014 | } else { | ||
2015 | chlo = channel; | ||
2016 | chhi = channel + 1; | ||
2017 | } | ||
2018 | |||
2019 | if (id == SCAN_WILD_CARD) { | ||
2020 | tgtlo = 0; | ||
2021 | tgthi = shost->max_id; | ||
2022 | } else { | ||
2023 | tgtlo = id; | ||
2024 | tgthi = id + 1; | ||
2025 | } | ||
2026 | |||
2027 | for ( ; chlo < chhi; chlo++) | ||
2028 | for ( ; tgtlo < tgthi; tgtlo++) | ||
2029 | fc_user_scan_tgt(shost, chlo, tgtlo, lun); | ||
2030 | |||
1985 | return 0; | 2031 | return 0; |
1986 | } | 2032 | } |
1987 | 2033 | ||