提交 a1383a59 编写于 作者: J Jason Yan 提交者: Xie XiuQi

scsi: libsas: check expander phy linkrate instead of domain device

euler inclusion
category: bugfix
bugzilla: 5457
CVE: NA

Sometimes the sata domain device cannot be probed so we'd better check the
expander phy's linkrate to see if it is greater than the pathway.
Signed-off-by: NJason Yan <yanaijie@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 756ccd10
......@@ -430,18 +430,29 @@ static enum sas_linkrate sas_find_min_pathway(struct domain_device *ddev)
return min_linkrate;
}
static void sas_ata_check_pathway(void *data, async_cookie_t cookie)
static inline void sas_ata_set_linkrate(struct domain_device *dev,
int phy_num,
enum sas_linkrate linkrate)
{
struct domain_device *dev = data;
struct domain_device *ddev = dev->parent;
struct sas_phy_linkrates rates;
enum sas_linkrate linkrate;
int ret;
if (!ddev) {
sas_put_device(dev);
return;
}
rates.minimum_linkrate = 0;
rates.maximum_linkrate = linkrate;
ret = sas_smp_phy_control(dev, phy_num, PHY_FUNC_LINK_RESET, &rates);
SAS_DPRINTK("ex %016llx phy%02d set max linkrate to %X %s\n",
SAS_ADDR(dev->sas_addr), phy_num, linkrate,
ret ? "failed" : "succeed");
}
static void sas_ata_check_pathway(void *data, async_cookie_t cookie)
{
struct domain_device *dev = data;
struct expander_device *ex = &dev->ex_dev;
struct ex_phy *ex_phy;
enum sas_linkrate linkrate;
int i;
/*
* According to Serial Attached SCSI - 1.1 (SAS-1.1):
......@@ -454,20 +465,18 @@ static void sas_ata_check_pathway(void *data, async_cookie_t cookie)
* initiator port.
*/
linkrate = sas_find_min_pathway(ddev);
linkrate = sas_find_min_pathway(dev);
if (dev->linkrate > linkrate) {
struct sas_phy *phy = sas_get_local_phy(dev);
for (i = 0; i < ex->num_phys; i++) {
ex_phy = &ex->ex_phy[i];
rates.minimum_linkrate = 0;
rates.maximum_linkrate = linkrate;
ret = sas_smp_phy_control(ddev, phy->number,
PHY_FUNC_LINK_RESET, &rates);
if (!ex_phy_is_sata(ex_phy))
continue;
SAS_DPRINTK("ex %016llx phy%02d set max linkrate to %X %s\n",
SAS_ADDR(ddev->sas_addr), phy->number, linkrate,
ret ? "failed" : "succeed");
sas_put_local_phy(phy);
if (ex_phy->linkrate > linkrate) {
sas_ata_set_linkrate(dev, i, linkrate);
ex_phy->linkrate = linkrate;
}
}
sas_put_device(dev);
......@@ -480,7 +489,8 @@ void sas_ata_check_topology(struct asd_sas_port *port)
spin_lock(&port->dev_list_lock);
list_for_each_entry(dev, &port->dev_list, dev_list_node) {
if (!dev_is_sata(dev))
if (dev->dev_type != SAS_EDGE_EXPANDER_DEVICE &&
dev->dev_type != SAS_FANOUT_EXPANDER_DEVICE)
continue;
/* hold a reference since we may be
......
......@@ -36,6 +36,13 @@ static inline int dev_is_sata(struct domain_device *dev)
dev->dev_type == SAS_SATA_PM_PORT || dev->dev_type == SAS_SATA_PENDING;
}
static inline int ex_phy_is_sata(struct ex_phy *phy)
{
return ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) &&
phy->attached_dev_type == SAS_END_DEVICE;
}
int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy);
int sas_ata_init(struct domain_device *dev);
void sas_ata_task_abort(struct sas_task *task);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册