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 a7dc6f2..e7ae9e0 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 8f596df..3ae426b 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 03dd04d..53946e8 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 8ee6663..331b8b3 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 a4aa1e0..71e795e 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;
+}