aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-06-22 02:36:20 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-08-09 11:27:34 -0400
commit3f67ec4b517d985ac6961a1a03f91339e62657c0 (patch)
tree1305d7aed880c49dd1ccf35fac67faf230c714a4
parent2da74cd8a6bad64d02207396c76d0939f3c57aaa (diff)
SCSI: libsas: fix sas_discover_devices return code handling
commit b17caa174a7e1fd2e17b26e210d4ee91c4c28b37 upstream. commit 198439e4 [SCSI] libsas: do not set res = 0 in sas_ex_discover_dev() commit 19252de6 [SCSI] libsas: fix wide port hotplug issues The above commits seem to have confused the return value of sas_ex_discover_dev which is non-zero on failure and sas_ex_join_wide_port which just indicates short circuiting discovery on already established ports. The result is random discovery failures depending on configuration. Calls to sas_ex_join_wide_port are the source of the trouble as its return value is errantly assigned to 'res'. Convert it to bool and stop returning its result up the stack. Tested-by: Dan Melnic <dan.melnic@amd.com> Reported-by: Dan Melnic <dan.melnic@amd.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Jack Wang <jack_wang@usish.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/scsi/libsas/sas_expander.c39
1 files changed, 12 insertions, 27 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index e8ebe688326..d2f95761ba3 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -770,7 +770,7 @@ static struct domain_device *sas_ex_discover_end_dev(
770} 770}
771 771
772/* See if this phy is part of a wide port */ 772/* See if this phy is part of a wide port */
773static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) 773static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
774{ 774{
775 struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; 775 struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id];
776 int i; 776 int i;
@@ -786,11 +786,11 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
786 sas_port_add_phy(ephy->port, phy->phy); 786 sas_port_add_phy(ephy->port, phy->phy);
787 phy->port = ephy->port; 787 phy->port = ephy->port;
788 phy->phy_state = PHY_DEVICE_DISCOVERED; 788 phy->phy_state = PHY_DEVICE_DISCOVERED;
789 return 0; 789 return true;
790 } 790 }
791 } 791 }
792 792
793 return -ENODEV; 793 return false;
794} 794}
795 795
796static struct domain_device *sas_ex_discover_expander( 796static struct domain_device *sas_ex_discover_expander(
@@ -928,8 +928,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
928 return res; 928 return res;
929 } 929 }
930 930
931 res = sas_ex_join_wide_port(dev, phy_id); 931 if (sas_ex_join_wide_port(dev, phy_id)) {
932 if (!res) {
933 SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", 932 SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
934 phy_id, SAS_ADDR(ex_phy->attached_sas_addr)); 933 phy_id, SAS_ADDR(ex_phy->attached_sas_addr));
935 return res; 934 return res;
@@ -974,8 +973,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
974 if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == 973 if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) ==
975 SAS_ADDR(child->sas_addr)) { 974 SAS_ADDR(child->sas_addr)) {
976 ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; 975 ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED;
977 res = sas_ex_join_wide_port(dev, i); 976 if (sas_ex_join_wide_port(dev, i))
978 if (!res)
979 SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", 977 SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
980 i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); 978 i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr));
981 979
@@ -1838,32 +1836,20 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
1838{ 1836{
1839 struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; 1837 struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id];
1840 struct domain_device *child; 1838 struct domain_device *child;
1841 bool found = false; 1839 int res;
1842 int res, i;
1843 1840
1844 SAS_DPRINTK("ex %016llx phy%d new device attached\n", 1841 SAS_DPRINTK("ex %016llx phy%d new device attached\n",
1845 SAS_ADDR(dev->sas_addr), phy_id); 1842 SAS_ADDR(dev->sas_addr), phy_id);
1846 res = sas_ex_phy_discover(dev, phy_id); 1843 res = sas_ex_phy_discover(dev, phy_id);
1847 if (res) 1844 if (res)
1848 goto out; 1845 return res;
1849 /* to support the wide port inserted */ 1846
1850 for (i = 0; i < dev->ex_dev.num_phys; i++) { 1847 if (sas_ex_join_wide_port(dev, phy_id))
1851 struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i];
1852 if (i == phy_id)
1853 continue;
1854 if (SAS_ADDR(ex_phy_temp->attached_sas_addr) ==
1855 SAS_ADDR(ex_phy->attached_sas_addr)) {
1856 found = true;
1857 break;
1858 }
1859 }
1860 if (found) {
1861 sas_ex_join_wide_port(dev, phy_id);
1862 return 0; 1848 return 0;
1863 } 1849
1864 res = sas_ex_discover_devices(dev, phy_id); 1850 res = sas_ex_discover_devices(dev, phy_id);
1865 if (!res) 1851 if (res)
1866 goto out; 1852 return res;
1867 list_for_each_entry(child, &dev->ex_dev.children, siblings) { 1853 list_for_each_entry(child, &dev->ex_dev.children, siblings) {
1868 if (SAS_ADDR(child->sas_addr) == 1854 if (SAS_ADDR(child->sas_addr) ==
1869 SAS_ADDR(ex_phy->attached_sas_addr)) { 1855 SAS_ADDR(ex_phy->attached_sas_addr)) {
@@ -1873,7 +1859,6 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
1873 break; 1859 break;
1874 } 1860 }
1875 } 1861 }
1876out:
1877 return res; 1862 return res;
1878} 1863}
1879 1864