Commit caeddc04 authored by Luo Jiaxing's avatar Luo Jiaxing Committed by Martin K. Petersen
Browse files

scsi: hisi_sas: Do not modify upper fields of PROG_PHY_LINK_RATE reg

When updating PROG_PHY_LINK_RATE to set linkrate for a phy we used a
hard-coded initial value instead of getting the current value from the
register. The assumption was that this register would not be modified, but
in fact it was partially modified in a new version of hardware. The
hard-coded value we used changed the default value of the register to a an
incorrect setting and as a result the SAS controller could not change
linkrate for the phy.

Delete hard-coded value and always read the latest value of register before
updating it.

Link: https://lore.kernel.org/r/1598958790-232272-4-git-send-email-john.garry@huawei.com


Signed-off-by: default avatarLuo Jiaxing <luojiaxing@huawei.com>
Signed-off-by: default avatarJohn Garry <john.garry@huawei.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 4b3a1f1f
Loading
Loading
Loading
Loading
+14 −11
Original line number Diff line number Diff line
@@ -191,6 +191,8 @@
#define PHY_CFG_PHY_RST_OFF		3
#define PHY_CFG_PHY_RST_MSK		(0x1 << PHY_CFG_PHY_RST_OFF)
#define PROG_PHY_LINK_RATE		(PORT_BASE + 0x8)
#define CFG_PROG_PHY_LINK_RATE_OFF	0
#define CFG_PROG_PHY_LINK_RATE_MSK	(0xff << CFG_PROG_PHY_LINK_RATE_OFF)
#define CFG_PROG_OOB_PHY_LINK_RATE_OFF	8
#define CFG_PROG_OOB_PHY_LINK_RATE_MSK	(0xf << CFG_PROG_OOB_PHY_LINK_RATE_OFF)
#define PHY_CTRL			(PORT_BASE + 0x14)
@@ -598,20 +600,19 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
	hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);

	for (i = 0; i < hisi_hba->n_phy; i++) {
		enum sas_linkrate max;
		struct hisi_sas_phy *phy = &hisi_hba->phy[i];
		struct asd_sas_phy *sas_phy = &phy->sas_phy;
		u32 prog_phy_link_rate = 0x800;
		u32 prog_phy_link_rate = hisi_sas_phy_read32(hisi_hba, i,
							   PROG_PHY_LINK_RATE);

		prog_phy_link_rate &= ~CFG_PROG_PHY_LINK_RATE_MSK;
		if (!sas_phy->phy || (sas_phy->phy->maximum_linkrate <
				SAS_LINK_RATE_1_5_GBPS)) {
			prog_phy_link_rate = 0x855;
		} else {
			enum sas_linkrate max = sas_phy->phy->maximum_linkrate;

			prog_phy_link_rate =
				hisi_sas_get_prog_phy_linkrate_mask(max) |
				0x800;
		}
				SAS_LINK_RATE_1_5_GBPS))
			max = SAS_LINK_RATE_12_0_GBPS;
		else
			max = sas_phy->phy->maximum_linkrate;
		prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
		hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
			prog_phy_link_rate);
		hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00);
@@ -2501,8 +2502,10 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no,
		struct sas_phy_linkrates *r)
{
	enum sas_linkrate max = r->maximum_linkrate;
	u32 prog_phy_link_rate = 0x800;
	u32 prog_phy_link_rate = hisi_sas_phy_read32(hisi_hba, phy_no,
						     PROG_PHY_LINK_RATE);

	prog_phy_link_rate &= ~CFG_PROG_PHY_LINK_RATE_MSK;
	prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
	hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
			     prog_phy_link_rate);