aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_sas.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2006-01-13 19:04:00 +0100
committerJames Bottomley <jejb@mulgrave.(none)>2006-01-14 10:55:05 -0600
commite02f3f59225d8c3b2a0ad0dc941a09865e27da61 (patch)
tree37d2931f5d24dc063d9606ec6b5e8db359b439c7 /drivers/scsi/scsi_transport_sas.c
parent[SCSI] fusion - adding support for FC949ES (diff)
downloadlinux-dev-e02f3f59225d8c3b2a0ad0dc941a09865e27da61.tar.xz
linux-dev-e02f3f59225d8c3b2a0ad0dc941a09865e27da61.zip
[SCSI] remove target parent limitiation
When James Smart fixed the issue of the userspace scan atributes crashing the system with the FC transport class he added a patch to let the transport class check if the parent is valid for a given transport class. When adding support for the integrated raid of fusion sas devices we ran into a problem with that, as it didn't allow adding virtual raid volumes without the transport class knowing about it. So this patch adds a user_scan attribute instead, that takes over from scsi_scan_host_selected if the transport class sets it and thus lets the transport class control the user-initiated scanning. As this plugs the hole about user-initiated scanning the target_parent hook goes away and we rely on callers of the scanning routines to do something sensible. For SAS this meant I had to switch from a spinlock to a mutex to synchronize the topology linked lists, in FC they were completely unsynchronized which seems wrong. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
-rw-r--r--drivers/scsi/scsi_transport_sas.c42
1 files changed, 24 insertions, 18 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index e950435a11d8..fb6641b42dfa 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -29,6 +29,7 @@
#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>
@@ -62,7 +63,7 @@ struct sas_internal {
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)
@@ -165,7 +166,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
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;
}
@@ -626,7 +627,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
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 &
@@ -634,7 +635,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
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,
@@ -661,9 +662,9 @@ void sas_rphy_free(struct sas_rphy *rphy)
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);
@@ -703,9 +704,9 @@ sas_rphy_delete(struct sas_rphy *rphy)
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;
@@ -731,23 +732,28 @@ EXPORT_SYMBOL(scsi_is_sas_rphy);
* 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;
}
@@ -792,7 +798,7 @@ sas_attach_transport(struct sas_function_template *ft)
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;