Commit 9cf0c123 authored by Martin K. Petersen's avatar Martin K. Petersen

Merge patch series "scsi: libsas: Fix the failure of adding phy with zero-address to new port"

Xingui Yang <yangxingui@huawei.com> says:

This series is to solve the problem of a BUG() when adding phy with
zero address to a new port.

Link: https://lore.kernel.org/r/20240312141103.31358-1-yangxingui@huawei.comSigned-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents f92141e1 06036a0a
...@@ -26,6 +26,28 @@ static int sas_configure_phy(struct domain_device *dev, int phy_id, ...@@ -26,6 +26,28 @@ static int sas_configure_phy(struct domain_device *dev, int phy_id,
u8 *sas_addr, int include); u8 *sas_addr, int include);
static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr);
static void sas_port_add_ex_phy(struct sas_port *port, struct ex_phy *ex_phy)
{
sas_port_add_phy(port, ex_phy->phy);
ex_phy->port = port;
ex_phy->phy_state = PHY_DEVICE_DISCOVERED;
}
static void sas_ex_add_parent_port(struct domain_device *dev, int phy_id)
{
struct expander_device *ex = &dev->ex_dev;
struct ex_phy *ex_phy = &ex->ex_phy[phy_id];
if (!ex->parent_port) {
ex->parent_port = sas_port_alloc(&dev->rphy->dev, phy_id);
/* FIXME: error handling */
BUG_ON(!ex->parent_port);
BUG_ON(sas_port_add(ex->parent_port));
sas_port_mark_backlink(ex->parent_port);
}
sas_port_add_ex_phy(ex->parent_port, ex_phy);
}
/* ---------- SMP task management ---------- */ /* ---------- SMP task management ---------- */
/* Give it some long enough timeout. In seconds. */ /* Give it some long enough timeout. In seconds. */
...@@ -239,8 +261,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, ...@@ -239,8 +261,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
/* help some expanders that fail to zero sas_address in the 'no /* help some expanders that fail to zero sas_address in the 'no
* device' case * device' case
*/ */
if (phy->attached_dev_type == SAS_PHY_UNUSED || if (phy->attached_dev_type == SAS_PHY_UNUSED)
phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
else else
memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE); memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
...@@ -857,9 +878,7 @@ static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id) ...@@ -857,9 +878,7 @@ static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr, if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr,
SAS_ADDR_SIZE) && ephy->port) { SAS_ADDR_SIZE) && ephy->port) {
sas_port_add_phy(ephy->port, phy->phy); sas_port_add_ex_phy(ephy->port, phy);
phy->port = ephy->port;
phy->phy_state = PHY_DEVICE_DISCOVERED;
return true; return true;
} }
} }
...@@ -963,11 +982,11 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) ...@@ -963,11 +982,11 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
/* Parent and domain coherency */ /* Parent and domain coherency */
if (!dev->parent && sas_phy_match_port_addr(dev->port, ex_phy)) { if (!dev->parent && sas_phy_match_port_addr(dev->port, ex_phy)) {
sas_add_parent_port(dev, phy_id); sas_ex_add_parent_port(dev, phy_id);
return 0; return 0;
} }
if (dev->parent && sas_phy_match_dev_addr(dev->parent, ex_phy)) { if (dev->parent && sas_phy_match_dev_addr(dev->parent, ex_phy)) {
sas_add_parent_port(dev, phy_id); sas_ex_add_parent_port(dev, phy_id);
if (ex_phy->routing_attr == TABLE_ROUTING) if (ex_phy->routing_attr == TABLE_ROUTING)
sas_configure_phy(dev, phy_id, dev->port->sas_addr, 1); sas_configure_phy(dev, phy_id, dev->port->sas_addr, 1);
return 0; return 0;
...@@ -1849,9 +1868,12 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent, ...@@ -1849,9 +1868,12 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
if (phy->port) { if (phy->port) {
sas_port_delete_phy(phy->port, phy->phy); sas_port_delete_phy(phy->port, phy->phy);
sas_device_set_phy(found, phy->port); sas_device_set_phy(found, phy->port);
if (phy->port->num_phys == 0) if (phy->port->num_phys == 0) {
list_add_tail(&phy->port->del_list, list_add_tail(&phy->port->del_list,
&parent->port->sas_port_del_list); &parent->port->sas_port_del_list);
if (ex_dev->parent_port == phy->port)
ex_dev->parent_port = NULL;
}
phy->port = NULL; phy->port = NULL;
} }
} }
......
...@@ -189,21 +189,6 @@ static inline void sas_phy_set_target(struct asd_sas_phy *p, struct domain_devic ...@@ -189,21 +189,6 @@ static inline void sas_phy_set_target(struct asd_sas_phy *p, struct domain_devic
} }
} }
static inline void sas_add_parent_port(struct domain_device *dev, int phy_id)
{
struct expander_device *ex = &dev->ex_dev;
struct ex_phy *ex_phy = &ex->ex_phy[phy_id];
if (!ex->parent_port) {
ex->parent_port = sas_port_alloc(&dev->rphy->dev, phy_id);
/* FIXME: error handling */
BUG_ON(!ex->parent_port);
BUG_ON(sas_port_add(ex->parent_port));
sas_port_mark_backlink(ex->parent_port);
}
sas_port_add_phy(ex->parent_port, ex_phy->phy);
}
static inline struct domain_device *sas_alloc_device(void) static inline struct domain_device *sas_alloc_device(void)
{ {
struct domain_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL); struct domain_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
......
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