summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArindam Nath <arindam.nath@amd.com>2020-02-05 21:24:18 +0530
committerJon Mason <jdmason@kudzu.us>2020-03-13 10:04:19 -0400
commitcb004c28dd2fabbb57bc03fb002f780054c28780 (patch)
treedfdb413825fd4ced57703b9e88f40897365e7dff
parent8ad1a2f351c1ade21ad7a2f0bc34fc887878f965 (diff)
downloadlinux-cb004c28dd2fabbb57bc03fb002f780054c28780.tar.bz2
NTB: Fix access to link status and control register
The design of AMD NTB implementation is such that NTB primary acts as an endpoint device and NTB secondary is an endpoint device behind a combination of Switch Upstream and Switch Downstream. Considering that, the link status and control register needs to be accessed differently based on the NTB topology. So in the case of NTB secondary, we first get the pointer to the Switch Downstream device for the NTB device. Then we get the pointer to the Switch Upstream device. Once we have that, we read the Link Status and Control register to get the correct status of link at the secondary. In the case of NTB primary, simply reading the Link Status and Control register of the NTB device itself will suffice. Suggested-by: Jiasen Lin <linjiasen@hygon.cn> Signed-off-by: Arindam Nath <arindam.nath@amd.com> Signed-off-by: Jon Mason <jdmason@kudzu.us>
-rw-r--r--drivers/ntb/hw/amd/ntb_hw_amd.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c
index ae911053ba9c..9a60f34a37c2 100644
--- a/drivers/ntb/hw/amd/ntb_hw_amd.c
+++ b/drivers/ntb/hw/amd/ntb_hw_amd.c
@@ -842,6 +842,9 @@ static inline void ndev_init_struct(struct amd_ntb_dev *ndev,
static int amd_poll_link(struct amd_ntb_dev *ndev)
{
void __iomem *mmio = ndev->peer_mmio;
+ struct pci_dev *pdev = NULL;
+ struct pci_dev *pci_swds = NULL;
+ struct pci_dev *pci_swus = NULL;
u32 reg, stat;
int rc;
@@ -855,10 +858,41 @@ static int amd_poll_link(struct amd_ntb_dev *ndev)
ndev->cntl_sta = reg;
- rc = pcie_capability_read_dword(ndev->ntb.pdev,
- PCI_EXP_LNKCTL, &stat);
- if (rc)
+ if (ndev->ntb.topo == NTB_TOPO_SEC) {
+ /* Locate the pointer to Downstream Switch for this device */
+ pci_swds = pci_upstream_bridge(ndev->ntb.pdev);
+ if (pci_swds) {
+ /*
+ * Locate the pointer to Upstream Switch for
+ * the Downstream Switch.
+ */
+ pci_swus = pci_upstream_bridge(pci_swds);
+ if (pci_swus) {
+ rc = pcie_capability_read_dword(pci_swus,
+ PCI_EXP_LNKCTL,
+ &stat);
+ if (rc)
+ return 0;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else if (ndev->ntb.topo == NTB_TOPO_PRI) {
+ /*
+ * For NTB primary, we simply read the Link Status and control
+ * register of the NTB device itself.
+ */
+ pdev = ndev->ntb.pdev;
+ rc = pcie_capability_read_dword(pdev, PCI_EXP_LNKCTL, &stat);
+ if (rc)
+ return 0;
+ } else {
+ /* Catch all for everything else */
return 0;
+ }
+
ndev->lnk_sta = stat;
return 1;