aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_expander.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
-rw-r--r--drivers/scsi/libsas/sas_expander.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 17b45a0c7bc3..83f2fd70ce76 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -826,9 +826,14 @@ static struct domain_device *sas_ex_discover_end_dev(
#ifdef CONFIG_SCSI_SAS_ATA
if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) {
if (child->linkrate > parent->min_linkrate) {
+ struct sas_phy *cphy = child->phy;
+ enum sas_linkrate min_prate = cphy->minimum_linkrate,
+ parent_min_lrate = parent->min_linkrate,
+ min_linkrate = (min_prate > parent_min_lrate) ?
+ parent_min_lrate : 0;
struct sas_phy_linkrates rates = {
.maximum_linkrate = parent->min_linkrate,
- .minimum_linkrate = parent->min_linkrate,
+ .minimum_linkrate = min_linkrate,
};
int ret;
@@ -865,7 +870,7 @@ static struct domain_device *sas_ex_discover_end_dev(
res = sas_discover_sata(child);
if (res) {
- pr_notice("sas_discover_sata() for device %16llx at %016llx:0x%x returned 0x%x\n",
+ pr_notice("sas_discover_sata() for device %16llx at %016llx:%02d returned 0x%x\n",
SAS_ADDR(child->sas_addr),
SAS_ADDR(parent->sas_addr), phy_id, res);
goto out_list_del;
@@ -890,7 +895,7 @@ static struct domain_device *sas_ex_discover_end_dev(
res = sas_discover_end_dev(child);
if (res) {
- pr_notice("sas_discover_end_dev() for device %16llx at %016llx:0x%x returned 0x%x\n",
+ pr_notice("sas_discover_end_dev() for device %16llx at %016llx:%02d returned 0x%x\n",
SAS_ADDR(child->sas_addr),
SAS_ADDR(parent->sas_addr), phy_id, res);
goto out_list_del;
@@ -955,7 +960,7 @@ static struct domain_device *sas_ex_discover_expander(
int res;
if (phy->routing_attr == DIRECT_ROUTING) {
- pr_warn("ex %016llx:0x%x:D <--> ex %016llx:0x%x is not allowed\n",
+ pr_warn("ex %016llx:%02d:D <--> ex %016llx:0x%x is not allowed\n",
SAS_ADDR(parent->sas_addr), phy_id,
SAS_ADDR(phy->attached_sas_addr),
phy->attached_phy_id);
@@ -1065,7 +1070,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
ex_phy->attached_dev_type != SAS_FANOUT_EXPANDER_DEVICE &&
ex_phy->attached_dev_type != SAS_EDGE_EXPANDER_DEVICE &&
ex_phy->attached_dev_type != SAS_SATA_PENDING) {
- pr_warn("unknown device type(0x%x) attached to ex %016llx phy 0x%x\n",
+ pr_warn("unknown device type(0x%x) attached to ex %016llx phy%02d\n",
ex_phy->attached_dev_type,
SAS_ADDR(dev->sas_addr),
phy_id);
@@ -1081,7 +1086,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
}
if (sas_ex_join_wide_port(dev, phy_id)) {
- pr_debug("Attaching ex phy%d to wide port %016llx\n",
+ pr_debug("Attaching ex phy%02d to wide port %016llx\n",
phy_id, SAS_ADDR(ex_phy->attached_sas_addr));
return res;
}
@@ -1093,7 +1098,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
break;
case SAS_FANOUT_EXPANDER_DEVICE:
if (SAS_ADDR(dev->port->disc.fanout_sas_addr)) {
- pr_debug("second fanout expander %016llx phy 0x%x attached to ex %016llx phy 0x%x\n",
+ pr_debug("second fanout expander %016llx phy%02d attached to ex %016llx phy%02d\n",
SAS_ADDR(ex_phy->attached_sas_addr),
ex_phy->attached_phy_id,
SAS_ADDR(dev->sas_addr),
@@ -1126,7 +1131,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
SAS_ADDR(child->sas_addr)) {
ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED;
if (sas_ex_join_wide_port(dev, i))
- pr_debug("Attaching ex phy%d to wide port %016llx\n",
+ pr_debug("Attaching ex phy%02d to wide port %016llx\n",
i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr));
}
}
@@ -1151,7 +1156,7 @@ static int sas_find_sub_addr(struct domain_device *dev, u8 *sub_addr)
phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE) &&
phy->routing_attr == SUBTRACTIVE_ROUTING) {
- memcpy(sub_addr, phy->attached_sas_addr,SAS_ADDR_SIZE);
+ memcpy(sub_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
return 1;
}
@@ -1163,7 +1168,7 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev)
{
struct expander_device *ex = &dev->ex_dev;
struct domain_device *child;
- u8 sub_addr[8] = {0, };
+ u8 sub_addr[SAS_ADDR_SIZE] = {0, };
list_for_each_entry(child, &ex->children, siblings) {
if (child->dev_type != SAS_EDGE_EXPANDER_DEVICE &&
@@ -1173,7 +1178,7 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev)
sas_find_sub_addr(child, sub_addr);
continue;
} else {
- u8 s2[8];
+ u8 s2[SAS_ADDR_SIZE];
if (sas_find_sub_addr(child, s2) &&
(SAS_ADDR(sub_addr) != SAS_ADDR(s2))) {
@@ -1261,7 +1266,7 @@ static int sas_check_ex_subtractive_boundary(struct domain_device *dev)
else if (SAS_ADDR(sub_sas_addr) !=
SAS_ADDR(phy->attached_sas_addr)) {
- pr_notice("ex %016llx phy 0x%x diverges(%016llx) on subtractive boundary(%016llx). Disabled\n",
+ pr_notice("ex %016llx phy%02d diverges(%016llx) on subtractive boundary(%016llx). Disabled\n",
SAS_ADDR(dev->sas_addr), i,
SAS_ADDR(phy->attached_sas_addr),
SAS_ADDR(sub_sas_addr));
@@ -1282,7 +1287,7 @@ static void sas_print_parent_topology_bug(struct domain_device *child,
};
struct domain_device *parent = child->parent;
- pr_notice("%s ex %016llx phy 0x%x <--> %s ex %016llx phy 0x%x has %c:%c routing link!\n",
+ pr_notice("%s ex %016llx phy%02d <--> %s ex %016llx phy%02d has %c:%c routing link!\n",
ex_type[parent->dev_type],
SAS_ADDR(parent->sas_addr),
parent_phy->phy_id,
@@ -1304,7 +1309,7 @@ static int sas_check_eeds(struct domain_device *child,
if (SAS_ADDR(parent->port->disc.fanout_sas_addr) != 0) {
res = -ENODEV;
- pr_warn("edge ex %016llx phy S:0x%x <--> edge ex %016llx phy S:0x%x, while there is a fanout ex %016llx\n",
+ pr_warn("edge ex %016llx phy S:%02d <--> edge ex %016llx phy S:%02d, while there is a fanout ex %016llx\n",
SAS_ADDR(parent->sas_addr),
parent_phy->phy_id,
SAS_ADDR(child->sas_addr),
@@ -1327,7 +1332,7 @@ static int sas_check_eeds(struct domain_device *child,
;
else {
res = -ENODEV;
- pr_warn("edge ex %016llx phy 0x%x <--> edge ex %016llx phy 0x%x link forms a third EEDS!\n",
+ pr_warn("edge ex %016llx phy%02d <--> edge ex %016llx phy%02d link forms a third EEDS!\n",
SAS_ADDR(parent->sas_addr),
parent_phy->phy_id,
SAS_ADDR(child->sas_addr),
@@ -1445,11 +1450,11 @@ static int sas_configure_present(struct domain_device *dev, int phy_id,
goto out;
res = rri_resp[2];
if (res == SMP_RESP_NO_INDEX) {
- pr_warn("overflow of indexes: dev %016llx phy 0x%x index 0x%x\n",
+ pr_warn("overflow of indexes: dev %016llx phy%02d index 0x%x\n",
SAS_ADDR(dev->sas_addr), phy_id, i);
goto out;
} else if (res != SMP_RESP_FUNC_ACC) {
- pr_notice("%s: dev %016llx phy 0x%x index 0x%x result 0x%x\n",
+ pr_notice("%s: dev %016llx phy%02d index 0x%x result 0x%x\n",
__func__, SAS_ADDR(dev->sas_addr), phy_id,
i, res);
goto out;
@@ -1515,7 +1520,7 @@ static int sas_configure_set(struct domain_device *dev, int phy_id,
goto out;
res = cri_resp[2];
if (res == SMP_RESP_NO_INDEX) {
- pr_warn("overflow of indexes: dev %016llx phy 0x%x index 0x%x\n",
+ pr_warn("overflow of indexes: dev %016llx phy%02d index 0x%x\n",
SAS_ADDR(dev->sas_addr), phy_id, index);
}
out:
@@ -1760,10 +1765,11 @@ static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
res = sas_get_phy_discover(dev, phy_id, disc_resp);
if (res == 0) {
- memcpy(sas_addr, disc_resp->disc.attached_sas_addr, 8);
+ memcpy(sas_addr, disc_resp->disc.attached_sas_addr,
+ SAS_ADDR_SIZE);
*type = to_dev_type(dr);
if (*type == 0)
- memset(sas_addr, 0, 8);
+ memset(sas_addr, 0, SAS_ADDR_SIZE);
}
kfree(disc_resp);
return res;
@@ -1870,10 +1876,12 @@ static int sas_find_bcast_dev(struct domain_device *dev,
if (phy_id != -1) {
*src_dev = dev;
ex->ex_change_count = ex_change_count;
- pr_info("Expander phy change count has changed\n");
+ pr_info("ex %016llx phy%02d change count has changed\n",
+ SAS_ADDR(dev->sas_addr), phy_id);
return res;
} else
- pr_info("Expander phys DID NOT change\n");
+ pr_info("ex %016llx phys DID NOT change\n",
+ SAS_ADDR(dev->sas_addr));
}
list_for_each_entry(ch, &ex->children, siblings) {
if (ch->dev_type == SAS_EDGE_EXPANDER_DEVICE || ch->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
@@ -1983,7 +1991,7 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
struct domain_device *child;
int res;
- pr_debug("ex %016llx phy%d new device attached\n",
+ pr_debug("ex %016llx phy%02d new device attached\n",
SAS_ADDR(dev->sas_addr), phy_id);
res = sas_ex_phy_discover(dev, phy_id);
if (res)
@@ -2022,15 +2030,23 @@ static bool dev_type_flutter(enum sas_device_type new, enum sas_device_type old)
return false;
}
-static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
+static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
+ bool last, int sibling)
{
struct expander_device *ex = &dev->ex_dev;
struct ex_phy *phy = &ex->ex_phy[phy_id];
enum sas_device_type type = SAS_PHY_UNUSED;
- u8 sas_addr[8];
+ u8 sas_addr[SAS_ADDR_SIZE];
+ char msg[80] = "";
int res;
- memset(sas_addr, 0, 8);
+ if (!last)
+ sprintf(msg, ", part of a wide port with phy%02d", sibling);
+
+ pr_debug("ex %016llx rediscovering phy%02d%s\n",
+ SAS_ADDR(dev->sas_addr), phy_id, msg);
+
+ memset(sas_addr, 0, SAS_ADDR_SIZE);
res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type);
switch (res) {
case SMP_RESP_NO_PHY:
@@ -2052,6 +2068,11 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) {
phy->phy_state = PHY_EMPTY;
sas_unregister_devs_sas_addr(dev, phy_id, last);
+ /*
+ * Even though the PHY is empty, for convenience we discover
+ * the PHY to update the PHY info, like negotiated linkrate.
+ */
+ sas_ex_phy_discover(dev, phy_id);
return res;
} else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
dev_type_flutter(type, phy->attached_dev_type)) {
@@ -2062,13 +2083,13 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING)
action = ", needs recovery";
- pr_debug("ex %016llx phy 0x%x broadcast flutter%s\n",
+ pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
SAS_ADDR(dev->sas_addr), phy_id, action);
return res;
}
/* we always have to delete the old device when we went here */
- pr_info("ex %016llx phy 0x%x replace %016llx\n",
+ pr_info("ex %016llx phy%02d replace %016llx\n",
SAS_ADDR(dev->sas_addr), phy_id,
SAS_ADDR(phy->attached_sas_addr));
sas_unregister_devs_sas_addr(dev, phy_id, last);
@@ -2098,7 +2119,7 @@ static int sas_rediscover(struct domain_device *dev, const int phy_id)
int i;
bool last = true; /* is this the last phy of the port */
- pr_debug("ex %016llx phy%d originated BROADCAST(CHANGE)\n",
+ pr_debug("ex %016llx phy%02d originated BROADCAST(CHANGE)\n",
SAS_ADDR(dev->sas_addr), phy_id);
if (SAS_ADDR(changed_phy->attached_sas_addr) != 0) {
@@ -2109,13 +2130,11 @@ static int sas_rediscover(struct domain_device *dev, const int phy_id)
continue;
if (SAS_ADDR(phy->attached_sas_addr) ==
SAS_ADDR(changed_phy->attached_sas_addr)) {
- pr_debug("phy%d part of wide port with phy%d\n",
- phy_id, i);
last = false;
break;
}
}
- res = sas_rediscover_dev(dev, phy_id, last);
+ res = sas_rediscover_dev(dev, phy_id, last, i);
} else
res = sas_discover_new(dev, phy_id);
return res;