aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
-rw-r--r--drivers/scsi/scsi_transport_sas.c58
1 files changed, 38 insertions, 20 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index edabbd05d258..a3e0b7bc2d7b 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
63struct sas_host_attrs { 64struct 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,10 +635,10 @@ 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->port_identifier,
641 rphy->scsi_target_id, ~0, 0); 642 rphy->scsi_target_id, ~0, 0);
642 } 643 }
643 644
@@ -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);
@@ -687,15 +688,27 @@ sas_rphy_delete(struct sas_rphy *rphy)
687 struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 688 struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
688 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 689 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
689 690
690 scsi_remove_target(dev); 691 switch (rphy->identify.device_type) {
692 case SAS_END_DEVICE:
693 scsi_remove_target(dev);
694 break;
695 case SAS_EDGE_EXPANDER_DEVICE:
696 case SAS_FANOUT_EXPANDER_DEVICE:
697 device_for_each_child(dev, NULL, do_sas_phy_delete);
698 break;
699 default:
700 break;
701 }
691 702
692 transport_remove_device(dev); 703 transport_remove_device(dev);
693 device_del(dev); 704 device_del(dev);
694 transport_destroy_device(dev); 705 transport_destroy_device(dev);
695 706
696 spin_lock(&sas_host->lock); 707 mutex_lock(&sas_host->lock);
697 list_del(&rphy->list); 708 list_del(&rphy->list);
698 spin_unlock(&sas_host->lock); 709 mutex_unlock(&sas_host->lock);
710
711 parent->rphy = NULL;
699 712
700 put_device(&parent->dev); 713 put_device(&parent->dev);
701} 714}
@@ -719,23 +732,28 @@ EXPORT_SYMBOL(scsi_is_sas_rphy);
719 * SCSI scan helper 732 * SCSI scan helper
720 */ 733 */
721 734
722static struct device *sas_target_parent(struct Scsi_Host *shost, 735static int sas_user_scan(struct Scsi_Host *shost, uint channel,
723 int channel, uint id) 736 uint id, uint lun)
724{ 737{
725 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 738 struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
726 struct sas_rphy *rphy; 739 struct sas_rphy *rphy;
727 struct device *dev = NULL;
728 740
729 spin_lock(&sas_host->lock); 741 mutex_lock(&sas_host->lock);
730 list_for_each_entry(rphy, &sas_host->rphy_list, list) { 742 list_for_each_entry(rphy, &sas_host->rphy_list, list) {
731 struct sas_phy *parent = dev_to_phy(rphy->dev.parent); 743 struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
732 if (parent->number == channel && 744
733 rphy->scsi_target_id == id) 745 if (rphy->scsi_target_id == -1)
734 dev = &rphy->dev; 746 continue;
747
748 if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
749 (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
750 scsi_scan_target(&rphy->dev, parent->port_identifier,
751 rphy->scsi_target_id, lun, 1);
752 }
735 } 753 }
736 spin_unlock(&sas_host->lock); 754 mutex_unlock(&sas_host->lock);
737 755
738 return dev; 756 return 0;
739} 757}
740 758
741 759
@@ -780,7 +798,7 @@ sas_attach_transport(struct sas_function_template *ft)
780 return NULL; 798 return NULL;
781 memset(i, 0, sizeof(struct sas_internal)); 799 memset(i, 0, sizeof(struct sas_internal));
782 800
783 i->t.target_parent = sas_target_parent; 801 i->t.user_scan = sas_user_scan;
784 802
785 i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 803 i->t.host_attrs.ac.attrs = &i->host_attrs[0];
786 i->t.host_attrs.ac.class = &sas_host_class.class; 804 i->t.host_attrs.ac.class = &sas_host_class.class;