From 89ae26ec65980d05adcaa6c8e1b09d4f4def6ee9 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Thu, 17 Jan 2019 20:09:19 +0800 Subject: [PATCH] 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: Luo Jiaxing Signed-off-by: John Garry Feature or Bugfix:Bugfix Signed-off-by: luojiaxing Reviewed-by: chenxiang Signed-off-by: Yang Yingliang --- drivers/scsi/hisi_sas/hisi_sas_main.c | 13 +++++++++---- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 ------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 5decd6d4b8ee..57bc5d4dc368 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -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); } -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; @@ -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; 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) { max = sas_phy->phy->maximum_linkrate; min = r->minimum_linkrate; @@ -1064,7 +1067,8 @@ static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no, max = r->maximum_linkrate; min = sas_phy->phy->minimum_linkrate; } else - return; + return -EINVAL; + _r.maximum_linkrate = max; _r.minimum_linkrate = min; @@ -1075,6 +1079,8 @@ static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no, msleep(100); hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, &_r); 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, @@ -1100,8 +1106,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, break; case PHY_FUNC_SET_LINK_RATE: - hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata); - break; + return hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata); case PHY_FUNC_GET_EVENTS: if (hisi_hba->hw->get_events) { hisi_hba->hw->get_events(hisi_hba, phy_no); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 922ff1002c01..6fd178390deb 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -1416,13 +1416,6 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) res = IRQ_NONE; 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; phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); -- GitLab