提交 3ce47fcf 编写于 作者: P Pali Rohár 提交者: Zheng Zengkai

PCI: aardvark: Fix checking for link up via LTSSM state

stable inclusion
from stable-5.10.80
commit 1085ee5236ef46836690a29a6e6749e61f904105
bugzilla: 185821 https://gitee.com/openeuler/kernel/issues/I4L7CG

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=1085ee5236ef46836690a29a6e6749e61f904105

--------------------------------

commit 661c399a upstream.

Current implementation of advk_pcie_link_up() is wrong as it marks also
link disabled or hot reset states as link up.

Fix it by marking link up only to those states which are defined in PCIe
Base specification 3.0, Table 4-14: Link Status Mapped to the LTSSM.

To simplify implementation, Define macros for every LTSSM state which
aardvark hardware can return in CFG_REG register.

Fix also checking for link training according to the same Table 4-14.
Define a new function advk_pcie_link_training() for this purpose.

Link: https://lore.kernel.org/r/20211005180952.6812-13-kabel@kernel.org
Fixes: 8c39d710 ("PCI: aardvark: Add Aardvark PCI host controller driver")
Signed-off-by: NPali Rohár <pali@kernel.org>
Signed-off-by: NMarek Behún <kabel@kernel.org>
Signed-off-by: NLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: NMarek Behún <kabel@kernel.org>
Cc: stable@vger.kernel.org
Cc: Remi Pommarel <repk@triplefau.lt>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NChen Jun <chenjun102@huawei.com>
Reviewed-by: NWeilong Chen <chenweilong@huawei.com>
Acked-by: NWeilong Chen <chenweilong@huawei.com>
Signed-off-by: NChen Jun <chenjun102@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 a79d3fe3
...@@ -163,8 +163,50 @@ ...@@ -163,8 +163,50 @@
#define CFG_REG (LMI_BASE_ADDR + 0x0) #define CFG_REG (LMI_BASE_ADDR + 0x0)
#define LTSSM_SHIFT 24 #define LTSSM_SHIFT 24
#define LTSSM_MASK 0x3f #define LTSSM_MASK 0x3f
#define LTSSM_L0 0x10
#define RC_BAR_CONFIG 0x300 #define RC_BAR_CONFIG 0x300
/* LTSSM values in CFG_REG */
enum {
LTSSM_DETECT_QUIET = 0x0,
LTSSM_DETECT_ACTIVE = 0x1,
LTSSM_POLLING_ACTIVE = 0x2,
LTSSM_POLLING_COMPLIANCE = 0x3,
LTSSM_POLLING_CONFIGURATION = 0x4,
LTSSM_CONFIG_LINKWIDTH_START = 0x5,
LTSSM_CONFIG_LINKWIDTH_ACCEPT = 0x6,
LTSSM_CONFIG_LANENUM_ACCEPT = 0x7,
LTSSM_CONFIG_LANENUM_WAIT = 0x8,
LTSSM_CONFIG_COMPLETE = 0x9,
LTSSM_CONFIG_IDLE = 0xa,
LTSSM_RECOVERY_RCVR_LOCK = 0xb,
LTSSM_RECOVERY_SPEED = 0xc,
LTSSM_RECOVERY_RCVR_CFG = 0xd,
LTSSM_RECOVERY_IDLE = 0xe,
LTSSM_L0 = 0x10,
LTSSM_RX_L0S_ENTRY = 0x11,
LTSSM_RX_L0S_IDLE = 0x12,
LTSSM_RX_L0S_FTS = 0x13,
LTSSM_TX_L0S_ENTRY = 0x14,
LTSSM_TX_L0S_IDLE = 0x15,
LTSSM_TX_L0S_FTS = 0x16,
LTSSM_L1_ENTRY = 0x17,
LTSSM_L1_IDLE = 0x18,
LTSSM_L2_IDLE = 0x19,
LTSSM_L2_TRANSMIT_WAKE = 0x1a,
LTSSM_DISABLED = 0x20,
LTSSM_LOOPBACK_ENTRY_MASTER = 0x21,
LTSSM_LOOPBACK_ACTIVE_MASTER = 0x22,
LTSSM_LOOPBACK_EXIT_MASTER = 0x23,
LTSSM_LOOPBACK_ENTRY_SLAVE = 0x24,
LTSSM_LOOPBACK_ACTIVE_SLAVE = 0x25,
LTSSM_LOOPBACK_EXIT_SLAVE = 0x26,
LTSSM_HOT_RESET = 0x27,
LTSSM_RECOVERY_EQUALIZATION_PHASE0 = 0x28,
LTSSM_RECOVERY_EQUALIZATION_PHASE1 = 0x29,
LTSSM_RECOVERY_EQUALIZATION_PHASE2 = 0x2a,
LTSSM_RECOVERY_EQUALIZATION_PHASE3 = 0x2b,
};
#define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) #define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44)
/* PCIe core controller registers */ /* PCIe core controller registers */
...@@ -269,13 +311,35 @@ static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg) ...@@ -269,13 +311,35 @@ static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg)
return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8); return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8);
} }
static int advk_pcie_link_up(struct advk_pcie *pcie) static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie)
{ {
u32 val, ltssm_state; u32 val;
u8 ltssm_state;
val = advk_readl(pcie, CFG_REG); val = advk_readl(pcie, CFG_REG);
ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK; ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK;
return ltssm_state >= LTSSM_L0; return ltssm_state;
}
static inline bool advk_pcie_link_up(struct advk_pcie *pcie)
{
/* check if LTSSM is in normal operation - some L* state */
u8 ltssm_state = advk_pcie_ltssm_state(pcie);
return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED;
}
static inline bool advk_pcie_link_training(struct advk_pcie *pcie)
{
/*
* According to PCIe Base specification 3.0, Table 4-14: Link
* Status Mapped to the LTSSM is Link Training mapped to LTSSM
* Configuration and Recovery states.
*/
u8 ltssm_state = advk_pcie_ltssm_state(pcie);
return ((ltssm_state >= LTSSM_CONFIG_LINKWIDTH_START &&
ltssm_state < LTSSM_L0) ||
(ltssm_state >= LTSSM_RECOVERY_EQUALIZATION_PHASE0 &&
ltssm_state <= LTSSM_RECOVERY_EQUALIZATION_PHASE3));
} }
static int advk_pcie_wait_for_link(struct advk_pcie *pcie) static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
...@@ -298,7 +362,7 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie) ...@@ -298,7 +362,7 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)
size_t retries; size_t retries;
for (retries = 0; retries < RETRAIN_WAIT_MAX_RETRIES; ++retries) { for (retries = 0; retries < RETRAIN_WAIT_MAX_RETRIES; ++retries) {
if (!advk_pcie_link_up(pcie)) if (advk_pcie_link_training(pcie))
break; break;
udelay(RETRAIN_WAIT_USLEEP_US); udelay(RETRAIN_WAIT_USLEEP_US);
} }
...@@ -738,7 +802,7 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, ...@@ -738,7 +802,7 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
/* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */ /* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */
u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) & u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) &
~(PCI_EXP_LNKSTA_LT << 16); ~(PCI_EXP_LNKSTA_LT << 16);
if (!advk_pcie_link_up(pcie)) if (advk_pcie_link_training(pcie))
val |= (PCI_EXP_LNKSTA_LT << 16); val |= (PCI_EXP_LNKSTA_LT << 16);
*value = val; *value = val;
return PCI_BRIDGE_EMUL_HANDLED; return PCI_BRIDGE_EMUL_HANDLED;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册