| From 2b650b7ff20eb7ea8ef9031d20fb657286ab90cc Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> |
| Date: Tue, 5 Oct 2021 20:09:52 +0200 |
| Subject: PCI: aardvark: Fix reporting Data Link Layer Link Active |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Pali Rohár <pali@kernel.org> |
| |
| commit 2b650b7ff20eb7ea8ef9031d20fb657286ab90cc upstream. |
| |
| 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: 8a3ebd8de328 ("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 |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/pci/controller/pci-aardvark.c | 29 ++++++++++++++++++++++++++++- |
| 1 file changed, 28 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/pci/controller/pci-aardvark.c |
| +++ b/drivers/pci/controller/pci-aardvark.c |
| @@ -278,6 +278,20 @@ static inline bool advk_pcie_link_up(str |
| 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) |
| { |
| /* |
| @@ -576,12 +590,26 @@ advk_pci_bridge_emul_pcie_conf_read(stru |
| 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; |
| } |
| @@ -589,7 +617,6 @@ advk_pci_bridge_emul_pcie_conf_read(stru |
| 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: |