From 33b114e935a2202206e224dd2c695cee5a5986bf Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 11 Jan 2006 14:20:43 +0100 Subject: [SCSI] sas: clear parent->rphy in sas_rphy_delete We need to clear the backpointer on rphy removal, else we'll run into problems with host removal after a device has been hot unplugged. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi/scsi_transport_sas.c') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index edabbd05d258..357b52f5f996 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -697,6 +697,8 @@ sas_rphy_delete(struct sas_rphy *rphy) list_del(&rphy->list); spin_unlock(&sas_host->lock); + parent->rphy = NULL; + put_device(&parent->dev); } EXPORT_SYMBOL(sas_rphy_delete); -- cgit v1.2.2 From d4054239929479907f20b9d68c905589125ad343 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 4 Jan 2006 13:45:20 +0100 Subject: [SCSI] sas: fix removal of devices behind expanders We need to iterate over all children when removing and expander, else stale objects will be around after host removal. This fixes the oops Eric Moore saw when removing and reloading mptsas. Also don't try the scsi_remove_target call unless operating on an end device. The current unconditional call is harmless but confusing. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/scsi_transport_sas.c') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 357b52f5f996..e950435a11d8 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -687,7 +687,17 @@ sas_rphy_delete(struct sas_rphy *rphy) struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); - scsi_remove_target(dev); + switch (rphy->identify.device_type) { + case SAS_END_DEVICE: + scsi_remove_target(dev); + break; + case SAS_EDGE_EXPANDER_DEVICE: + case SAS_FANOUT_EXPANDER_DEVICE: + device_for_each_child(dev, NULL, do_sas_phy_delete); + break; + default: + break; + } transport_remove_device(dev); device_del(dev); -- cgit v1.2.2 From e02f3f59225d8c3b2a0ad0dc941a09865e27da61 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Jan 2006 19:04:00 +0100 Subject: [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 Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 42 ++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'drivers/scsi/scsi_transport_sas.c') 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 #include +#include #include #include #include @@ -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; -- cgit v1.2.2 From e6bc863cf25f30ed8e2a4d41b76d5688f8efaee9 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Fri, 13 Jan 2006 16:33:59 -0700 Subject: [SCSI] scsi_transport_sas: mapping the rphy channel equal to the port identifier We will be mapping the RAID volumes in mptsas to a reserved channel that is one larger than the anticapated number of ports on the direct attached host adapter. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/scsi_transport_sas.c') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index fb6641b42dfa..a3e0b7bc2d7b 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -638,7 +638,7 @@ int sas_rphy_add(struct sas_rphy *rphy) mutex_unlock(&sas_host->lock); if (rphy->scsi_target_id != -1) { - scsi_scan_target(&rphy->dev, parent->number, + scsi_scan_target(&rphy->dev, parent->port_identifier, rphy->scsi_target_id, ~0, 0); } @@ -745,9 +745,9 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, if (rphy->scsi_target_id == -1) continue; - if ((channel == SCAN_WILD_CARD || channel == parent->number) && + if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) && (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { - scsi_scan_target(&rphy->dev, parent->number, + scsi_scan_target(&rphy->dev, parent->port_identifier, rphy->scsi_target_id, lun, 1); } } -- cgit v1.2.2