提交 89ae26ec 编写于 作者: L Luo Jiaxing 提交者: Xie XiuQi

scsi: hisi_sas: Reject request of setting minimum_linkrate exceed 1.5 Gbit at...

scsi: hisi_sas: Reject request of setting minimum_linkrate exceed 1.5 Gbit at directly attached environment

At directly attached env, we found out that user can successfully
set a higher linkrate to minimum_linkrate than negotiated_linkrate.
Like below:

maximum_linkrate: 6.0 Gbit
minimum_linkrate: 6.0 Gbit
negotiated_linkrate: 3.0 Gbit

It mean that the bound of max and min linkrate cannot limit the
negotiated linkrate. This may cause trouble to user.

Actually, we only send maximum_linkrate to SAS controller, and SAS
controller will try all the linkrate under the setting value and
finally negotiate with the highest possible linkrate.

So to the SAS controller at directly attached env, the min linkrate
is unnecessary. If we want to avoid this issue, the best way is to
reject the request of setting minimum_linkrate exceed 1.5 Gbit.
Signed-off-by: NLuo Jiaxing <luojiaxing@huawei.com>
Signed-off-by: NJohn Garry <john.garry@huawei.com>

Feature or Bugfix:Bugfix
Signed-off-by: Nluojiaxing <luojiaxing@huawei.com>
Reviewed-by: Nchenxiang <chenxiang66@hisilicon.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 ff4e59c0
...@@ -1048,7 +1048,7 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) ...@@ -1048,7 +1048,7 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
return hisi_sas_task_exec(task, gfp_flags, 0, NULL); return hisi_sas_task_exec(task, gfp_flags, 0, NULL);
} }
static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no, static int hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no,
struct sas_phy_linkrates *r) struct sas_phy_linkrates *r)
{ {
struct sas_phy_linkrates _r; struct sas_phy_linkrates _r;
...@@ -1057,6 +1057,9 @@ static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no, ...@@ -1057,6 +1057,9 @@ static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no,
struct asd_sas_phy *sas_phy = &phy->sas_phy; struct asd_sas_phy *sas_phy = &phy->sas_phy;
enum sas_linkrate min, max; enum sas_linkrate min, max;
if (r->minimum_linkrate > SAS_LINK_RATE_1_5_GBPS)
return -EINVAL;
if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) { if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
max = sas_phy->phy->maximum_linkrate; max = sas_phy->phy->maximum_linkrate;
min = r->minimum_linkrate; min = r->minimum_linkrate;
...@@ -1064,7 +1067,8 @@ static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no, ...@@ -1064,7 +1067,8 @@ static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no,
max = r->maximum_linkrate; max = r->maximum_linkrate;
min = sas_phy->phy->minimum_linkrate; min = sas_phy->phy->minimum_linkrate;
} else } else
return; return -EINVAL;
_r.maximum_linkrate = max; _r.maximum_linkrate = max;
_r.minimum_linkrate = min; _r.minimum_linkrate = min;
...@@ -1075,6 +1079,8 @@ static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no, ...@@ -1075,6 +1079,8 @@ static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no,
msleep(100); msleep(100);
hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, &_r); hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, &_r);
hisi_hba->hw->phy_start(hisi_hba, phy_no); hisi_hba->hw->phy_start(hisi_hba, phy_no);
return 0;
} }
static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
...@@ -1100,8 +1106,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, ...@@ -1100,8 +1106,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
break; break;
case PHY_FUNC_SET_LINK_RATE: case PHY_FUNC_SET_LINK_RATE:
hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata); return hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata);
break;
case PHY_FUNC_GET_EVENTS: case PHY_FUNC_GET_EVENTS:
if (hisi_hba->hw->get_events) { if (hisi_hba->hw->get_events) {
hisi_hba->hw->get_events(hisi_hba, phy_no); hisi_hba->hw->get_events(hisi_hba, phy_no);
......
...@@ -1416,13 +1416,6 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) ...@@ -1416,13 +1416,6 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
res = IRQ_NONE; res = IRQ_NONE;
goto end; goto end;
} }
if (sas_phy->phy->minimum_linkrate > link_rate) {
dev_err(dev, "phydown: phy%d's min linkrete outof bound\n",
phy_no);
disable_phy_v3_hw(hisi_hba, phy_no);
res = IRQ_NONE;
goto end;
}
sas_phy->linkrate = link_rate; sas_phy->linkrate = link_rate;
phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册