Commit b17caa17 authored by Dan Williams's avatar Dan Williams Committed by James Bottomley

[SCSI] libsas: fix sas_discover_devices return code handling

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.

Cc: <stable@vger.kernel.org>
Tested-by: default avatarDan Melnic <dan.melnic@amd.com>
Reported-by: default avatarDan Melnic <dan.melnic@amd.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Reviewed-by: default avatarJack Wang <jack_wang@usish.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 26f2f199
...@@ -868,7 +868,7 @@ static struct domain_device *sas_ex_discover_end_dev( ...@@ -868,7 +868,7 @@ static struct domain_device *sas_ex_discover_end_dev(
} }
/* See if this phy is part of a wide port */ /* See if this phy is part of a wide port */
static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
{ {
struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id];
int i; int i;
...@@ -884,11 +884,11 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) ...@@ -884,11 +884,11 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
sas_port_add_phy(ephy->port, phy->phy); sas_port_add_phy(ephy->port, phy->phy);
phy->port = ephy->port; phy->port = ephy->port;
phy->phy_state = PHY_DEVICE_DISCOVERED; phy->phy_state = PHY_DEVICE_DISCOVERED;
return 0; return true;
} }
} }
return -ENODEV; return false;
} }
static struct domain_device *sas_ex_discover_expander( static struct domain_device *sas_ex_discover_expander(
...@@ -1030,8 +1030,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) ...@@ -1030,8 +1030,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
return res; return res;
} }
res = sas_ex_join_wide_port(dev, phy_id); if (sas_ex_join_wide_port(dev, phy_id)) {
if (!res) {
SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
phy_id, SAS_ADDR(ex_phy->attached_sas_addr)); phy_id, SAS_ADDR(ex_phy->attached_sas_addr));
return res; return res;
...@@ -1077,8 +1076,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) ...@@ -1077,8 +1076,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) ==
SAS_ADDR(child->sas_addr)) { SAS_ADDR(child->sas_addr)) {
ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED;
res = sas_ex_join_wide_port(dev, i); if (sas_ex_join_wide_port(dev, i))
if (!res)
SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr));
...@@ -1943,32 +1941,20 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) ...@@ -1943,32 +1941,20 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
{ {
struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id];
struct domain_device *child; struct domain_device *child;
bool found = false; int res;
int res, i;
SAS_DPRINTK("ex %016llx phy%d new device attached\n", SAS_DPRINTK("ex %016llx phy%d new device attached\n",
SAS_ADDR(dev->sas_addr), phy_id); SAS_ADDR(dev->sas_addr), phy_id);
res = sas_ex_phy_discover(dev, phy_id); res = sas_ex_phy_discover(dev, phy_id);
if (res) if (res)
goto out; return res;
/* to support the wide port inserted */
for (i = 0; i < dev->ex_dev.num_phys; i++) { if (sas_ex_join_wide_port(dev, phy_id))
struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i];
if (i == phy_id)
continue;
if (SAS_ADDR(ex_phy_temp->attached_sas_addr) ==
SAS_ADDR(ex_phy->attached_sas_addr)) {
found = true;
break;
}
}
if (found) {
sas_ex_join_wide_port(dev, phy_id);
return 0; return 0;
}
res = sas_ex_discover_devices(dev, phy_id); res = sas_ex_discover_devices(dev, phy_id);
if (!res) if (res)
goto out; return res;
list_for_each_entry(child, &dev->ex_dev.children, siblings) { list_for_each_entry(child, &dev->ex_dev.children, siblings) {
if (SAS_ADDR(child->sas_addr) == if (SAS_ADDR(child->sas_addr) ==
SAS_ADDR(ex_phy->attached_sas_addr)) { SAS_ADDR(ex_phy->attached_sas_addr)) {
...@@ -1978,7 +1964,6 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) ...@@ -1978,7 +1964,6 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
break; break;
} }
} }
out:
return res; return res;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment