diff options
author | Christoph Hellwig <hch@lst.de> | 2006-01-13 13:04:00 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2006-01-14 11:55:05 -0500 |
commit | e02f3f59225d8c3b2a0ad0dc941a09865e27da61 (patch) | |
tree | 37d2931f5d24dc063d9606ec6b5e8db359b439c7 /drivers/scsi/scsi_transport_sas.c | |
parent | 6d5b0c315e0c14f8a0fe274eda7676d62cbd8584 (diff) |
[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.c | 42 |
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 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/string.h> | 30 | #include <linux/string.h> |
31 | 31 | ||
32 | #include <scsi/scsi.h> | ||
32 | #include <scsi/scsi_device.h> | 33 | #include <scsi/scsi_device.h> |
33 | #include <scsi/scsi_host.h> | 34 | #include <scsi/scsi_host.h> |
34 | #include <scsi/scsi_transport.h> | 35 | #include <scsi/scsi_transport.h> |
@@ -62,7 +63,7 @@ struct sas_internal { | |||
62 | 63 | ||
63 | struct sas_host_attrs { | 64 | struct sas_host_attrs { |
64 | struct list_head rphy_list; | 65 | struct list_head rphy_list; |
65 | spinlock_t lock; | 66 | struct mutex lock; |
66 | u32 next_target_id; | 67 | u32 next_target_id; |
67 | }; | 68 | }; |
68 | #define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) | 69 | #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, | |||
165 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | 166 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); |
166 | 167 | ||
167 | INIT_LIST_HEAD(&sas_host->rphy_list); | 168 | INIT_LIST_HEAD(&sas_host->rphy_list); |
168 | spin_lock_init(&sas_host->lock); | 169 | mutex_init(&sas_host->lock); |
169 | sas_host->next_target_id = 0; | 170 | sas_host->next_target_id = 0; |
170 | return 0; | 171 | return 0; |
171 | } | 172 | } |
@@ -626,7 +627,7 @@ int sas_rphy_add(struct sas_rphy *rphy) | |||
626 | transport_add_device(&rphy->dev); | 627 | transport_add_device(&rphy->dev); |
627 | transport_configure_device(&rphy->dev); | 628 | transport_configure_device(&rphy->dev); |
628 | 629 | ||
629 | spin_lock(&sas_host->lock); | 630 | mutex_lock(&sas_host->lock); |
630 | list_add_tail(&rphy->list, &sas_host->rphy_list); | 631 | list_add_tail(&rphy->list, &sas_host->rphy_list); |
631 | if (identify->device_type == SAS_END_DEVICE && | 632 | if (identify->device_type == SAS_END_DEVICE && |
632 | (identify->target_port_protocols & | 633 | (identify->target_port_protocols & |
@@ -634,7 +635,7 @@ int sas_rphy_add(struct sas_rphy *rphy) | |||
634 | rphy->scsi_target_id = sas_host->next_target_id++; | 635 | rphy->scsi_target_id = sas_host->next_target_id++; |
635 | else | 636 | else |
636 | rphy->scsi_target_id = -1; | 637 | rphy->scsi_target_id = -1; |
637 | spin_unlock(&sas_host->lock); | 638 | mutex_unlock(&sas_host->lock); |
638 | 639 | ||
639 | if (rphy->scsi_target_id != -1) { | 640 | if (rphy->scsi_target_id != -1) { |
640 | scsi_scan_target(&rphy->dev, parent->number, | 641 | scsi_scan_target(&rphy->dev, parent->number, |
@@ -661,9 +662,9 @@ void sas_rphy_free(struct sas_rphy *rphy) | |||
661 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); | 662 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); |
662 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | 663 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); |
663 | 664 | ||
664 | spin_lock(&sas_host->lock); | 665 | mutex_lock(&sas_host->lock); |
665 | list_del(&rphy->list); | 666 | list_del(&rphy->list); |
666 | spin_unlock(&sas_host->lock); | 667 | mutex_unlock(&sas_host->lock); |
667 | 668 | ||
668 | transport_destroy_device(&rphy->dev); | 669 | transport_destroy_device(&rphy->dev); |
669 | put_device(rphy->dev.parent); | 670 | put_device(rphy->dev.parent); |
@@ -703,9 +704,9 @@ sas_rphy_delete(struct sas_rphy *rphy) | |||
703 | device_del(dev); | 704 | device_del(dev); |
704 | transport_destroy_device(dev); | 705 | transport_destroy_device(dev); |
705 | 706 | ||
706 | spin_lock(&sas_host->lock); | 707 | mutex_lock(&sas_host->lock); |
707 | list_del(&rphy->list); | 708 | list_del(&rphy->list); |
708 | spin_unlock(&sas_host->lock); | 709 | mutex_unlock(&sas_host->lock); |
709 | 710 | ||
710 | parent->rphy = NULL; | 711 | parent->rphy = NULL; |
711 | 712 | ||
@@ -731,23 +732,28 @@ EXPORT_SYMBOL(scsi_is_sas_rphy); | |||
731 | * SCSI scan helper | 732 | * SCSI scan helper |
732 | */ | 733 | */ |
733 | 734 | ||
734 | static struct device *sas_target_parent(struct Scsi_Host *shost, | 735 | static int sas_user_scan(struct Scsi_Host *shost, uint channel, |
735 | int channel, uint id) | 736 | uint id, uint lun) |
736 | { | 737 | { |
737 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | 738 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); |
738 | struct sas_rphy *rphy; | 739 | struct sas_rphy *rphy; |
739 | struct device *dev = NULL; | ||
740 | 740 | ||
741 | spin_lock(&sas_host->lock); | 741 | mutex_lock(&sas_host->lock); |
742 | list_for_each_entry(rphy, &sas_host->rphy_list, list) { | 742 | list_for_each_entry(rphy, &sas_host->rphy_list, list) { |
743 | struct sas_phy *parent = dev_to_phy(rphy->dev.parent); | 743 | struct sas_phy *parent = dev_to_phy(rphy->dev.parent); |
744 | if (parent->number == channel && | 744 | |
745 | rphy->scsi_target_id == id) | 745 | if (rphy->scsi_target_id == -1) |
746 | dev = &rphy->dev; | 746 | continue; |
747 | |||
748 | if ((channel == SCAN_WILD_CARD || channel == parent->number) && | ||
749 | (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { | ||
750 | scsi_scan_target(&rphy->dev, parent->number, | ||
751 | rphy->scsi_target_id, lun, 1); | ||
752 | } | ||
747 | } | 753 | } |
748 | spin_unlock(&sas_host->lock); | 754 | mutex_unlock(&sas_host->lock); |
749 | 755 | ||
750 | return dev; | 756 | return 0; |
751 | } | 757 | } |
752 | 758 | ||
753 | 759 | ||
@@ -792,7 +798,7 @@ sas_attach_transport(struct sas_function_template *ft) | |||
792 | return NULL; | 798 | return NULL; |
793 | memset(i, 0, sizeof(struct sas_internal)); | 799 | memset(i, 0, sizeof(struct sas_internal)); |
794 | 800 | ||
795 | i->t.target_parent = sas_target_parent; | 801 | i->t.user_scan = sas_user_scan; |
796 | 802 | ||
797 | i->t.host_attrs.ac.attrs = &i->host_attrs[0]; | 803 | i->t.host_attrs.ac.attrs = &i->host_attrs[0]; |
798 | i->t.host_attrs.ac.class = &sas_host_class.class; | 804 | i->t.host_attrs.ac.class = &sas_host_class.class; |