octeontx2-af: Support for MAC address filters in CGX
authorVidhya Raman <vraman@marvell.com>
Tue, 16 Oct 2018 11:27:08 +0000 (16:57 +0530)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Oct 2018 04:33:42 +0000 (21:33 -0700)
This patch adds support for setting MAC address filters in CGX
for PF interfaces. Also PF interfaces can be put in promiscuous
mode. Dataplane PFs access this functionality using mailbox
messages to the AF driver.

Signed-off-by: Vidhya Raman <vraman@marvell.com>
Signed-off-by: Stanislaw Kardach <skardach@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/cgx.c
drivers/net/ethernet/marvell/octeontx2/af/cgx.h
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c

index a7dc6f265df8a4523447d0368c3c3dcf0cd0d7eb..e7ae9e0af9fe2a0f299e43a91285263163c4c465 100644 (file)
@@ -119,6 +119,81 @@ void *cgx_get_pdata(int cgx_id)
 }
 EXPORT_SYMBOL(cgx_get_pdata);
 
+static u64 mac2u64 (u8 *mac_addr)
+{
+       u64 mac = 0;
+       int index;
+
+       for (index = ETH_ALEN - 1; index >= 0; index--)
+               mac |= ((u64)*mac_addr++) << (8 * index);
+       return mac;
+}
+
+int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr)
+{
+       struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
+       u64 cfg;
+
+       /* copy 6bytes from macaddr */
+       /* memcpy(&cfg, mac_addr, 6); */
+
+       cfg = mac2u64 (mac_addr);
+
+       cgx_write(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (lmac_id * 0x8)),
+                 cfg | CGX_DMAC_CAM_ADDR_ENABLE | ((u64)lmac_id << 49));
+
+       cfg = cgx_read(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
+       cfg |= CGX_DMAC_CTL0_CAM_ENABLE;
+       cgx_write(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
+
+       return 0;
+}
+EXPORT_SYMBOL(cgx_lmac_addr_set);
+
+u64 cgx_lmac_addr_get(u8 cgx_id, u8 lmac_id)
+{
+       struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
+       u64 cfg;
+
+       cfg = cgx_read(cgx_dev, 0, CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8);
+       return cfg & CGX_RX_DMAC_ADR_MASK;
+}
+EXPORT_SYMBOL(cgx_lmac_addr_get);
+
+void cgx_lmac_promisc_config(int cgx_id, int lmac_id, bool enable)
+{
+       struct cgx *cgx = cgx_get_pdata(cgx_id);
+       u64 cfg = 0;
+
+       if (!cgx)
+               return;
+
+       if (enable) {
+               /* Enable promiscuous mode on LMAC */
+               cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
+               cfg &= ~(CGX_DMAC_CAM_ACCEPT | CGX_DMAC_MCAST_MODE);
+               cfg |= CGX_DMAC_BCAST_MODE;
+               cgx_write(cgx, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
+
+               cfg = cgx_read(cgx, 0,
+                              (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8));
+               cfg &= ~CGX_DMAC_CAM_ADDR_ENABLE;
+               cgx_write(cgx, 0,
+                         (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8), cfg);
+       } else {
+               /* Disable promiscuous mode */
+               cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
+               cfg |= CGX_DMAC_CAM_ACCEPT | CGX_DMAC_MCAST_MODE;
+               cgx_write(cgx, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
+               cfg = cgx_read(cgx, 0,
+                              (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8));
+               cfg |= CGX_DMAC_CAM_ADDR_ENABLE;
+               cgx_write(cgx, 0,
+                         (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8), cfg);
+       }
+}
+EXPORT_SYMBOL(cgx_lmac_promisc_config);
+
 int cgx_get_rx_stats(void *cgxd, int lmac_id, int idx, u64 *rx_stat)
 {
        struct cgx *cgx = cgxd;
index 8f596dfb6b2a15ca22ee5e7fbab295f2632e2257..3ae426bff7210581a014d09608f967d329bcabd5 100644 (file)
 #define CGXX_CMRX_RX_ID_MAP            0x060
 #define CGXX_CMRX_RX_STAT0             0x070
 #define CGXX_CMRX_RX_LMACS             0x128
+#define CGXX_CMRX_RX_DMAC_CTL0         0x1F8
+#define  CGX_DMAC_CTL0_CAM_ENABLE              BIT_ULL(3)
+#define  CGX_DMAC_CAM_ACCEPT                   BIT_ULL(3)
+#define  CGX_DMAC_MCAST_MODE                   BIT_ULL(1)
+#define  CGX_DMAC_BCAST_MODE                   BIT_ULL(0)
+#define CGXX_CMRX_RX_DMAC_CAM0         0x200
+#define  CGX_DMAC_CAM_ADDR_ENABLE              BIT_ULL(48)
+#define CGXX_CMRX_RX_DMAC_CAM1         0x400
+#define CGX_RX_DMAC_ADR_MASK                   GENMASK_ULL(47, 0)
 #define CGXX_CMRX_TX_STAT0             0x700
 #define CGXX_SCRATCH0_REG              0x1050
 #define CGXX_SCRATCH1_REG              0x1058
@@ -71,4 +80,7 @@ int cgx_lmac_evh_register(struct cgx_event_cb *cb, void *cgxd, int lmac_id);
 int cgx_get_tx_stats(void *cgxd, int lmac_id, int idx, u64 *tx_stat);
 int cgx_get_rx_stats(void *cgxd, int lmac_id, int idx, u64 *rx_stat);
 int cgx_lmac_rx_tx_enable(void *cgxd, int lmac_id, bool enable);
+int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr);
+u64 cgx_lmac_addr_get(u8 cgx_id, u8 lmac_id);
+void cgx_lmac_promisc_config(int cgx_id, int lmac_id, bool enable);
 #endif /* CGX_H */
index 03dd04d53f3b66b0468165f519fe7136e4ef0faa..53946e80adefc9335f8ceb3b15c72640f468d0da 100644 (file)
@@ -127,6 +127,12 @@ M(MSIX_OFFSET,             0x004, msg_req, msix_offset_rsp)                \
 M(CGX_START_RXTX,      0x200, msg_req, msg_rsp)                        \
 M(CGX_STOP_RXTX,       0x201, msg_req, msg_rsp)                        \
 M(CGX_STATS,           0x202, msg_req, cgx_stats_rsp)                  \
+M(CGX_MAC_ADDR_SET,    0x203, cgx_mac_addr_set_or_get,                 \
+                               cgx_mac_addr_set_or_get)                \
+M(CGX_MAC_ADDR_GET,    0x204, cgx_mac_addr_set_or_get,                 \
+                               cgx_mac_addr_set_or_get)                \
+M(CGX_PROMISC_ENABLE,  0x205, msg_req, msg_rsp)                        \
+M(CGX_PROMISC_DISABLE, 0x206, msg_req, msg_rsp)                        \
 /* NPA mbox IDs (range 0x400 - 0x5FF) */                               \
 /* SSO/SSOW mbox IDs (range 0x600 - 0x7FF) */                          \
 /* TIM mbox IDs (range 0x800 - 0x9FF) */                               \
@@ -221,4 +227,11 @@ struct cgx_stats_rsp {
        u64 tx_stats[CGX_TX_STATS_COUNT];
 };
 
+/* Structure for requesting the operation for
+ * setting/getting mac address in the CGX interface
+ */
+struct cgx_mac_addr_set_or_get {
+       struct mbox_msghdr hdr;
+       u8 mac_addr[ETH_ALEN];
+};
 #endif /* MBOX_H */
index 8ee66632ed29c170f5f4d5a004806729e10af47c..331b8b39cbfb65f28505147c046749ec1e0e4b32 100644 (file)
@@ -173,4 +173,14 @@ int rvu_mbox_handler_CGX_STOP_RXTX(struct rvu *rvu, struct msg_req *req,
                                   struct msg_rsp *rsp);
 int rvu_mbox_handler_CGX_STATS(struct rvu *rvu, struct msg_req *req,
                               struct cgx_stats_rsp *rsp);
+int rvu_mbox_handler_CGX_MAC_ADDR_SET(struct rvu *rvu,
+                                     struct cgx_mac_addr_set_or_get *req,
+                                     struct cgx_mac_addr_set_or_get *rsp);
+int rvu_mbox_handler_CGX_MAC_ADDR_GET(struct rvu *rvu,
+                                     struct cgx_mac_addr_set_or_get *req,
+                                     struct cgx_mac_addr_set_or_get *rsp);
+int rvu_mbox_handler_CGX_PROMISC_ENABLE(struct rvu *rvu, struct msg_req *req,
+                                       struct msg_rsp *rsp);
+int rvu_mbox_handler_CGX_PROMISC_DISABLE(struct rvu *rvu, struct msg_req *req,
+                                        struct msg_rsp *rsp);
 #endif /* RVU_H */
index a4aa1e07e8f90eac29dacb0a6a44aa6ad0140035..71e795e13aa8ff666b1f6335c1ac671a28439f3b 100644 (file)
@@ -261,3 +261,76 @@ int rvu_mbox_handler_CGX_STATS(struct rvu *rvu, struct msg_req *req,
        }
        return 0;
 }
+
+int rvu_mbox_handler_CGX_MAC_ADDR_SET(struct rvu *rvu,
+                                     struct cgx_mac_addr_set_or_get *req,
+                                     struct cgx_mac_addr_set_or_get *rsp)
+{
+       int pf = rvu_get_pf(req->hdr.pcifunc);
+       u8 cgx_id, lmac_id;
+
+       rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+
+       cgx_lmac_addr_set(cgx_id, lmac_id, req->mac_addr);
+
+       return 0;
+}
+
+int rvu_mbox_handler_CGX_MAC_ADDR_GET(struct rvu *rvu,
+                                     struct cgx_mac_addr_set_or_get *req,
+                                     struct cgx_mac_addr_set_or_get *rsp)
+{
+       int pf = rvu_get_pf(req->hdr.pcifunc);
+       u8 cgx_id, lmac_id;
+       int rc = 0, i;
+       u64 cfg;
+
+       rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+
+       rsp->hdr.rc = rc;
+       cfg = cgx_lmac_addr_get(cgx_id, lmac_id);
+       /* copy 48 bit mac address to req->mac_addr */
+       for (i = 0; i < ETH_ALEN; i++)
+               rsp->mac_addr[i] = cfg >> (ETH_ALEN - 1 - i) * 8;
+       return 0;
+}
+
+int rvu_mbox_handler_CGX_PROMISC_ENABLE(struct rvu *rvu, struct msg_req *req,
+                                       struct msg_rsp *rsp)
+{
+       u16 pcifunc = req->hdr.pcifunc;
+       int pf = rvu_get_pf(pcifunc);
+       u8 cgx_id, lmac_id;
+
+       /* This msg is expected only from PFs that are mapped to CGX LMACs,
+        * if received from other PF/VF simply ACK, nothing to do.
+        */
+       if ((req->hdr.pcifunc & RVU_PFVF_FUNC_MASK) ||
+           !is_pf_cgxmapped(rvu, pf))
+               return -ENODEV;
+
+       rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+
+       cgx_lmac_promisc_config(cgx_id, lmac_id, true);
+       return 0;
+}
+
+int rvu_mbox_handler_CGX_PROMISC_DISABLE(struct rvu *rvu, struct msg_req *req,
+                                        struct msg_rsp *rsp)
+{
+       u16 pcifunc = req->hdr.pcifunc;
+       int pf = rvu_get_pf(pcifunc);
+       u8 cgx_id, lmac_id;
+
+       /* This msg is expected only from PFs that are mapped to CGX LMACs,
+        * if received from other PF/VF simply ACK, nothing to do.
+        */
+       if ((req->hdr.pcifunc & RVU_PFVF_FUNC_MASK) ||
+           !is_pf_cgxmapped(rvu, pf))
+               return -ENODEV;
+
+       rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+
+       cgx_lmac_promisc_config(cgx_id, lmac_id, false);
+       return 0;
+}