PCI: aardvark: Fix reporting Data Link Layer Link Active
Add support for reporting PCI_EXP_LNKSTA_DLLLA bit in Link Control register
on emulated bridge via current LTSSM state. Also correctly indicate DLLLA
capability via PCI_EXP_LNKCAP_DLLLARC bit in Link Control Capability
register.
Link: https://lore.kernel.org/r/20211005180952.6812-14-kabel@kernel.org
Fixes: 8a3ebd8de3
("PCI: aardvark: Implement emulated root PCI bridge config space")
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <kabel@kernel.org>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Marek Behún <kabel@kernel.org>
Cc: stable@vger.kernel.org
This commit is contained in:
parent
661c399a65
commit
2b650b7ff2
|
@ -317,6 +317,20 @@ static inline bool advk_pcie_link_up(struct advk_pcie *pcie)
|
|||
return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED;
|
||||
}
|
||||
|
||||
static inline bool advk_pcie_link_active(struct advk_pcie *pcie)
|
||||
{
|
||||
/*
|
||||
* According to PCIe Base specification 3.0, Table 4-14: Link
|
||||
* Status Mapped to the LTSSM, and 4.2.6.3.6 Configuration.Idle
|
||||
* is Link Up mapped to LTSSM Configuration.Idle, Recovery, L0,
|
||||
* L0s, L1 and L2 states. And according to 3.2.1. Data Link
|
||||
* Control and Management State Machine Rules is DL Up status
|
||||
* reported in DL Active state.
|
||||
*/
|
||||
u8 ltssm_state = advk_pcie_ltssm_state(pcie);
|
||||
return ltssm_state >= LTSSM_CONFIG_IDLE && ltssm_state < LTSSM_DISABLED;
|
||||
}
|
||||
|
||||
static inline bool advk_pcie_link_training(struct advk_pcie *pcie)
|
||||
{
|
||||
/*
|
||||
|
@ -766,12 +780,26 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
|
|||
return PCI_BRIDGE_EMUL_HANDLED;
|
||||
}
|
||||
|
||||
case PCI_EXP_LNKCAP: {
|
||||
u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
|
||||
/*
|
||||
* PCI_EXP_LNKCAP_DLLLARC bit is hardwired in aardvark HW to 0.
|
||||
* But support for PCI_EXP_LNKSTA_DLLLA is emulated via ltssm
|
||||
* state so explicitly enable PCI_EXP_LNKCAP_DLLLARC flag.
|
||||
*/
|
||||
val |= PCI_EXP_LNKCAP_DLLLARC;
|
||||
*value = val;
|
||||
return PCI_BRIDGE_EMUL_HANDLED;
|
||||
}
|
||||
|
||||
case PCI_EXP_LNKCTL: {
|
||||
/* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */
|
||||
u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) &
|
||||
~(PCI_EXP_LNKSTA_LT << 16);
|
||||
if (advk_pcie_link_training(pcie))
|
||||
val |= (PCI_EXP_LNKSTA_LT << 16);
|
||||
if (advk_pcie_link_active(pcie))
|
||||
val |= (PCI_EXP_LNKSTA_DLLLA << 16);
|
||||
*value = val;
|
||||
return PCI_BRIDGE_EMUL_HANDLED;
|
||||
}
|
||||
|
@ -779,7 +807,6 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
|
|||
case PCI_CAP_LIST_ID:
|
||||
case PCI_EXP_DEVCAP:
|
||||
case PCI_EXP_DEVCTL:
|
||||
case PCI_EXP_LNKCAP:
|
||||
*value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
|
||||
return PCI_BRIDGE_EMUL_HANDLED;
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue