OSDN Git Service

octeontx2-af: Reset all RVU blocks
authorSunil Goutham <sgoutham@marvell.com>
Wed, 10 Oct 2018 12:44:22 +0000 (18:14 +0530)
committerDavid S. Miller <davem@davemloft.net>
Wed, 10 Oct 2018 17:06:01 +0000 (10:06 -0700)
Go through all BLKADDRs and check which ones are implemented
on this silicon and do a HW reset of each implemented block.
Also added all RVU AF and PF register offsets.

Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h [new file with mode: 0644]
drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h [new file with mode: 0644]

index 5af4da6..a3ce158 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/sysfs.h>
 
 #include "rvu.h"
+#include "rvu_reg.h"
 
 #define DRV_NAME       "octeontx2-af"
 #define DRV_STRING      "Marvell OcteonTX2 RVU Admin Function Driver"
@@ -33,6 +34,69 @@ MODULE_LICENSE("GPL v2");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, rvu_id_table);
 
+/* Poll a RVU block's register 'offset', for a 'zero'
+ * or 'nonzero' at bits specified by 'mask'
+ */
+int rvu_poll_reg(struct rvu *rvu, u64 block, u64 offset, u64 mask, bool zero)
+{
+       void __iomem *reg;
+       int timeout = 100;
+       u64 reg_val;
+
+       reg = rvu->afreg_base + ((block << 28) | offset);
+       while (timeout) {
+               reg_val = readq(reg);
+               if (zero && !(reg_val & mask))
+                       return 0;
+               if (!zero && (reg_val & mask))
+                       return 0;
+               usleep_range(1, 2);
+               timeout--;
+       }
+       return -EBUSY;
+}
+
+static void rvu_check_block_implemented(struct rvu *rvu)
+{
+       struct rvu_hwinfo *hw = rvu->hw;
+       struct rvu_block *block;
+       int blkid;
+       u64 cfg;
+
+       /* For each block check if 'implemented' bit is set */
+       for (blkid = 0; blkid < BLK_COUNT; blkid++) {
+               block = &hw->block[blkid];
+               cfg = rvupf_read64(rvu, RVU_PF_BLOCK_ADDRX_DISC(blkid));
+               if (cfg & BIT_ULL(11))
+                       block->implemented = true;
+       }
+}
+
+static void rvu_block_reset(struct rvu *rvu, int blkaddr, u64 rst_reg)
+{
+       struct rvu_block *block = &rvu->hw->block[blkaddr];
+
+       if (!block->implemented)
+               return;
+
+       rvu_write64(rvu, blkaddr, rst_reg, BIT_ULL(0));
+       rvu_poll_reg(rvu, blkaddr, rst_reg, BIT_ULL(63), true);
+}
+
+static void rvu_reset_all_blocks(struct rvu *rvu)
+{
+       /* Do a HW reset of all RVU blocks */
+       rvu_block_reset(rvu, BLKADDR_NPA, NPA_AF_BLK_RST);
+       rvu_block_reset(rvu, BLKADDR_NIX0, NIX_AF_BLK_RST);
+       rvu_block_reset(rvu, BLKADDR_NPC, NPC_AF_BLK_RST);
+       rvu_block_reset(rvu, BLKADDR_SSO, SSO_AF_BLK_RST);
+       rvu_block_reset(rvu, BLKADDR_TIM, TIM_AF_BLK_RST);
+       rvu_block_reset(rvu, BLKADDR_CPT0, CPT_AF_BLK_RST);
+       rvu_block_reset(rvu, BLKADDR_NDC0, NDC_AF_BLK_RST);
+       rvu_block_reset(rvu, BLKADDR_NDC1, NDC_AF_BLK_RST);
+       rvu_block_reset(rvu, BLKADDR_NDC2, NDC_AF_BLK_RST);
+}
+
 static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct device *dev = &pdev->dev;
@@ -43,6 +107,12 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!rvu)
                return -ENOMEM;
 
+       rvu->hw = devm_kzalloc(dev, sizeof(struct rvu_hwinfo), GFP_KERNEL);
+       if (!rvu->hw) {
+               devm_kfree(dev, rvu);
+               return -ENOMEM;
+       }
+
        pci_set_drvdata(pdev, rvu);
        rvu->pdev = pdev;
        rvu->dev = &pdev->dev;
@@ -80,6 +150,11 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto err_release_regions;
        }
 
+       /* Check which blocks the HW supports */
+       rvu_check_block_implemented(rvu);
+
+       rvu_reset_all_blocks(rvu);
+
        return 0;
 
 err_release_regions:
@@ -88,6 +163,7 @@ err_disable_device:
        pci_disable_device(pdev);
 err_freemem:
        pci_set_drvdata(pdev, NULL);
+       devm_kfree(&pdev->dev, rvu->hw);
        devm_kfree(dev, rvu);
        return err;
 }
@@ -100,6 +176,7 @@ static void rvu_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
 
+       devm_kfree(&pdev->dev, rvu->hw);
        devm_kfree(&pdev->dev, rvu);
 }
 
index 4a4b0ad..e2c54d0 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef RVU_H
 #define RVU_H
 
+#include "rvu_struct.h"
+
 /* PCI device IDs */
 #define        PCI_DEVID_OCTEONTX2_RVU_AF              0xA065
 
 
 #define NAME_SIZE                              32
 
+struct rvu_block {
+       bool implemented;
+};
+
+struct rvu_hwinfo {
+       struct rvu_block block[BLK_COUNT]; /* Block info */
+};
+
 struct rvu {
        void __iomem            *afreg_base;
        void __iomem            *pfreg_base;
        struct pci_dev          *pdev;
        struct device           *dev;
+       struct rvu_hwinfo       *hw;
 };
 
+static inline void rvu_write64(struct rvu *rvu, u64 block, u64 offset, u64 val)
+{
+       writeq(val, rvu->afreg_base + ((block << 28) | offset));
+}
+
+static inline u64 rvu_read64(struct rvu *rvu, u64 block, u64 offset)
+{
+       return readq(rvu->afreg_base + ((block << 28) | offset));
+}
+
+static inline void rvupf_write64(struct rvu *rvu, u64 offset, u64 val)
+{
+       writeq(val, rvu->pfreg_base + offset);
+}
+
+static inline u64 rvupf_read64(struct rvu *rvu, u64 offset)
+{
+       return readq(rvu->pfreg_base + offset);
+}
+
+/* Function Prototypes
+ * RVU
+ */
+
+int rvu_poll_reg(struct rvu *rvu, u64 block, u64 offset, u64 mask, bool zero);
+
 #endif /* RVU_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
new file mode 100644 (file)
index 0000000..f4ba5a1
--- /dev/null
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Marvell OcteonTx2 RVU Admin Function driver
+ *
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RVU_REG_H
+#define RVU_REG_H
+
+/* Admin function registers */
+#define RVU_AF_MSIXTR_BASE                  (0x10)
+#define RVU_AF_ECO                          (0x20)
+#define RVU_AF_BLK_RST                      (0x30)
+#define RVU_AF_PF_BAR4_ADDR                 (0x40)
+#define RVU_AF_RAS                          (0x100)
+#define RVU_AF_RAS_W1S                      (0x108)
+#define RVU_AF_RAS_ENA_W1S                  (0x110)
+#define RVU_AF_RAS_ENA_W1C                  (0x118)
+#define RVU_AF_GEN_INT                      (0x120)
+#define RVU_AF_GEN_INT_W1S                  (0x128)
+#define RVU_AF_GEN_INT_ENA_W1S              (0x130)
+#define RVU_AF_GEN_INT_ENA_W1C              (0x138)
+#define        RVU_AF_AFPF_MBOX0                   (0x02000)
+#define        RVU_AF_AFPF_MBOX1                   (0x02008)
+#define RVU_AF_AFPFX_MBOXX(a, b)            (0x2000 | (a) << 4 | (b) << 3)
+#define RVU_AF_PFME_STATUS                  (0x2800)
+#define RVU_AF_PFTRPEND                     (0x2810)
+#define RVU_AF_PFTRPEND_W1S                 (0x2820)
+#define RVU_AF_PF_RST                       (0x2840)
+#define RVU_AF_HWVF_RST                     (0x2850)
+#define RVU_AF_PFAF_MBOX_INT                (0x2880)
+#define RVU_AF_PFAF_MBOX_INT_W1S            (0x2888)
+#define RVU_AF_PFAF_MBOX_INT_ENA_W1S        (0x2890)
+#define RVU_AF_PFAF_MBOX_INT_ENA_W1C        (0x2898)
+#define RVU_AF_PFFLR_INT                    (0x28a0)
+#define RVU_AF_PFFLR_INT_W1S                (0x28a8)
+#define RVU_AF_PFFLR_INT_ENA_W1S            (0x28b0)
+#define RVU_AF_PFFLR_INT_ENA_W1C            (0x28b8)
+#define RVU_AF_PFME_INT                     (0x28c0)
+#define RVU_AF_PFME_INT_W1S                 (0x28c8)
+#define RVU_AF_PFME_INT_ENA_W1S             (0x28d0)
+#define RVU_AF_PFME_INT_ENA_W1C             (0x28d8)
+
+/* Admin function's privileged PF/VF registers */
+#define RVU_PRIV_CONST                      (0x8000000)
+#define RVU_PRIV_GEN_CFG                    (0x8000010)
+#define RVU_PRIV_CLK_CFG                    (0x8000020)
+#define RVU_PRIV_ACTIVE_PC                  (0x8000030)
+#define RVU_PRIV_PFX_CFG(a)                 (0x8000100 | (a) << 16)
+#define RVU_PRIV_PFX_MSIX_CFG(a)            (0x8000110 | (a) << 16)
+#define RVU_PRIV_PFX_ID_CFG(a)              (0x8000120 | (a) << 16)
+#define RVU_PRIV_PFX_INT_CFG(a)             (0x8000200 | (a) << 16)
+#define RVU_PRIV_PFX_NIX_CFG                (0x8000300)
+#define RVU_PRIV_PFX_NPA_CFG               (0x8000310)
+#define RVU_PRIV_PFX_SSO_CFG                (0x8000320)
+#define RVU_PRIV_PFX_SSOW_CFG               (0x8000330)
+#define RVU_PRIV_PFX_TIM_CFG                (0x8000340)
+#define RVU_PRIV_PFX_CPT_CFG                (0x8000350)
+#define RVU_PRIV_BLOCK_TYPEX_REV(a)         (0x8000400 | (a) << 3)
+#define RVU_PRIV_HWVFX_INT_CFG(a)           (0x8001280 | (a) << 16)
+#define RVU_PRIV_HWVFX_NIX_CFG              (0x8001300)
+#define RVU_PRIV_HWVFX_NPA_CFG              (0x8001310)
+#define RVU_PRIV_HWVFX_SSO_CFG              (0x8001320)
+#define RVU_PRIV_HWVFX_SSOW_CFG             (0x8001330)
+#define RVU_PRIV_HWVFX_TIM_CFG              (0x8001340)
+#define RVU_PRIV_HWVFX_CPT_CFG              (0x8001350)
+
+/* RVU PF registers */
+#define        RVU_PF_VFX_PFVF_MBOX0               (0x00000)
+#define        RVU_PF_VFX_PFVF_MBOX1               (0x00008)
+#define RVU_PF_VFX_PFVF_MBOXX(a, b)         (0x0 | (a) << 12 | (b) << 3)
+#define RVU_PF_VF_BAR4_ADDR                 (0x10)
+#define RVU_PF_BLOCK_ADDRX_DISC(a)          (0x200 | (a) << 3)
+#define RVU_PF_VFME_STATUSX(a)              (0x800 | (a) << 3)
+#define RVU_PF_VFTRPENDX(a)                 (0x820 | (a) << 3)
+#define RVU_PF_VFTRPEND_W1SX(a)             (0x840 | (a) << 3)
+#define RVU_PF_VFPF_MBOX_INTX(a)            (0x880 | (a) << 3)
+#define RVU_PF_VFPF_MBOX_INT_W1SX(a)        (0x8A0 | (a) << 3)
+#define RVU_PF_VFPF_MBOX_INT_ENA_W1SX(a)    (0x8C0 | (a) << 3)
+#define RVU_PF_VFPF_MBOX_INT_ENA_W1CX(a)    (0x8E0 | (a) << 3)
+#define RVU_PF_VFFLR_INTX(a)                (0x900 | (a) << 3)
+#define RVU_PF_VFFLR_INT_W1SX(a)            (0x920 | (a) << 3)
+#define RVU_PF_VFFLR_INT_ENA_W1SX(a)        (0x940 | (a) << 3)
+#define RVU_PF_VFFLR_INT_ENA_W1CX(a)        (0x960 | (a) << 3)
+#define RVU_PF_VFME_INTX(a)                 (0x980 | (a) << 3)
+#define RVU_PF_VFME_INT_W1SX(a)             (0x9A0 | (a) << 3)
+#define RVU_PF_VFME_INT_ENA_W1SX(a)         (0x9C0 | (a) << 3)
+#define RVU_PF_VFME_INT_ENA_W1CX(a)         (0x9E0 | (a) << 3)
+#define RVU_PF_PFAF_MBOX0                   (0xC00)
+#define RVU_PF_PFAF_MBOX1                   (0xC08)
+#define RVU_PF_PFAF_MBOXX(a)                (0xC00 | (a) << 3)
+#define RVU_PF_INT                          (0xc20)
+#define RVU_PF_INT_W1S                      (0xc28)
+#define RVU_PF_INT_ENA_W1S                  (0xc30)
+#define RVU_PF_INT_ENA_W1C                  (0xc38)
+#define RVU_PF_MSIX_VECX_ADDR(a)            (0x000 | (a) << 4)
+#define RVU_PF_MSIX_VECX_CTL(a)             (0x008 | (a) << 4)
+#define RVU_PF_MSIX_PBAX(a)                 (0xF0000 | (a) << 3)
+
+#define NPA_AF_BLK_RST                  (0x0000)
+#define NIX_AF_BLK_RST                  (0x00B0)
+#define SSO_AF_BLK_RST                  (0x10f8)
+#define TIM_AF_BLK_RST                  (0x10)
+#define CPT_AF_BLK_RST                  (0x46000)
+#define NDC_AF_BLK_RST                  (0x002F0)
+#define NPC_AF_BLK_RST                  (0x00040)
+
+#endif /* RVU_REG_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h
new file mode 100644 (file)
index 0000000..9e11333
--- /dev/null
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Marvell OcteonTx2 RVU Admin Function driver
+ *
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RVU_STRUCT_H
+#define RVU_STRUCT_H
+
+/* RVU Block Address Enumeration */
+enum rvu_block_addr_e {
+       BLKADDR_RVUM    = 0x0ULL,
+       BLKADDR_LMT     = 0x1ULL,
+       BLKADDR_MSIX    = 0x2ULL,
+       BLKADDR_NPA     = 0x3ULL,
+       BLKADDR_NIX0    = 0x4ULL,
+       BLKADDR_NIX1    = 0x5ULL,
+       BLKADDR_NPC     = 0x6ULL,
+       BLKADDR_SSO     = 0x7ULL,
+       BLKADDR_SSOW    = 0x8ULL,
+       BLKADDR_TIM     = 0x9ULL,
+       BLKADDR_CPT0    = 0xaULL,
+       BLKADDR_CPT1    = 0xbULL,
+       BLKADDR_NDC0    = 0xcULL,
+       BLKADDR_NDC1    = 0xdULL,
+       BLKADDR_NDC2    = 0xeULL,
+       BLK_COUNT       = 0xfULL,
+};
+
+#endif /* RVU_STRUCT_H */