octeontx2-af: Add support for Tx packet marking
authorKrzysztof Kanas <kkanas@marvell.com>
Sun, 2 Dec 2018 12:47:45 +0000 (18:17 +0530)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Dec 2018 00:23:08 +0000 (16:23 -0800)
NIX_AF_MARK_FORMAT(0..127)_CTL register enables an SW defined
means to mark/insert various data in the packet based on
final packet color from traffic shaping HW.

0..127 works as an index to choose the algorithm. On success,
the mailbox returns the index to the client.

Add NIX_MARK_FORMAT_CFG mailbox which reserves mark format based on
tuple (offset, y_mask, y_val, r_mask, r_val)

If the tuple is requested again for mark format that was already
reserved, then it will be reused. If not it will reserve a new entry
if space is available.

Also on AF init commonly used marker format such as VLAN DEI, IPv4
ECN, IPv4 DSCP are reserved for AF consumers.

Signed-off-by: Krzysztof Kanas <kkanas@marvell.com>
Signed-off-by: Jerin Jacob <jerinj@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c

index 640a230..146f8f9 100644 (file)
@@ -200,6 +200,9 @@ M(NIX_SET_RX_MODE,  0x800b, nix_set_rx_mode, nix_rx_mode, msg_rsp)  \
 M(NIX_SET_HW_FRS,      0x800c, nix_set_hw_frs, nix_frs_cfg, msg_rsp)   \
 M(NIX_LF_START_RX,     0x800d, nix_lf_start_rx, msg_req, msg_rsp)      \
 M(NIX_LF_STOP_RX,      0x800e, nix_lf_stop_rx, msg_req, msg_rsp)       \
+M(NIX_MARK_FORMAT_CFG, 0x800f, nix_mark_format_cfg,                    \
+                                nix_mark_format_cfg,                   \
+                                nix_mark_format_cfg_rsp)               \
 M(NIX_RXVLAN_ALLOC,    0x8012, nix_rxvlan_alloc, msg_req, msg_rsp)
 
 /* Messages initiated by AF (range 0xC00 - 0xDFF) */
@@ -416,6 +419,7 @@ enum nix_af_status {
        NIX_AF_ERR_LF_RESET         = -414,
        NIX_AF_ERR_RSS_NOSPC_FIELD  = -415,
        NIX_AF_ERR_RSS_NOSPC_ALGO   = -416,
+       NIX_AF_ERR_MARK_CFG_FAIL    = -417,
        NIX_AF_INVAL_NPA_PF_FUNC    = -419,
        NIX_AF_INVAL_SSO_PF_FUNC    = -420,
 };
@@ -583,6 +587,20 @@ struct nix_set_mac_addr {
        u8 mac_addr[ETH_ALEN]; /* MAC address to be set for this pcifunc */
 };
 
+struct nix_mark_format_cfg {
+       struct mbox_msghdr hdr;
+       u8 offset;
+       u8 y_mask;
+       u8 y_val;
+       u8 r_mask;
+       u8 r_val;
+};
+
+struct nix_mark_format_cfg_rsp {
+       struct mbox_msghdr hdr;
+       u8 mark_format_idx;
+};
+
 struct nix_rx_mode {
        struct mbox_msghdr hdr;
 #define NIX_RX_MODE_UCAST      BIT(0)
index b184172..563e3bf 100644 (file)
@@ -163,6 +163,12 @@ struct nix_txsch {
        u32  *pfvf_map;
 };
 
+struct nix_mark_format {
+       u8 total;
+       u8 in_use;
+       u32 *cfg;
+};
+
 struct npc_pkind {
        struct rsrc_bmap rsrc;
        u32     *pfchan_map;
@@ -178,6 +184,7 @@ struct nix_hw {
        struct nix_txsch txsch[NIX_TXSCH_LVL_CNT]; /* Tx schedulers */
        struct nix_mcast mcast;
        struct nix_flowkey flowkey;
+       struct nix_mark_format mark_format;
 };
 
 struct rvu_hwinfo {
@@ -377,6 +384,8 @@ int rvu_mbox_handler_npa_lf_free(struct rvu *rvu, struct msg_req *req,
 /* NIX APIs */
 bool is_nixlf_attached(struct rvu *rvu, u16 pcifunc);
 int rvu_nix_init(struct rvu *rvu);
+int rvu_nix_reserve_mark_format(struct rvu *rvu, struct nix_hw *nix_hw,
+                               int blkaddr, u32 cfg);
 void rvu_nix_freemem(struct rvu *rvu);
 int rvu_get_nixlf_count(struct rvu *rvu);
 void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int npalf);
@@ -421,6 +430,9 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req,
                                     struct msg_rsp *rsp);
 int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
                                    struct msg_rsp *rsp);
+int rvu_mbox_handler_nix_mark_format_cfg(struct rvu *rvu,
+                                        struct nix_mark_format_cfg  *req,
+                                        struct nix_mark_format_cfg_rsp *rsp);
 
 /* NPC APIs */
 int rvu_npc_init(struct rvu *rvu);
index 2a72298..4363966 100644 (file)
@@ -43,6 +43,19 @@ enum mc_buf_cnt {
        MC_BUF_CNT_2048,
 };
 
+enum nix_makr_fmt_indexes {
+       NIX_MARK_CFG_IP_DSCP_RED,
+       NIX_MARK_CFG_IP_DSCP_YELLOW,
+       NIX_MARK_CFG_IP_DSCP_YELLOW_RED,
+       NIX_MARK_CFG_IP_ECN_RED,
+       NIX_MARK_CFG_IP_ECN_YELLOW,
+       NIX_MARK_CFG_IP_ECN_YELLOW_RED,
+       NIX_MARK_CFG_VLAN_DEI_RED,
+       NIX_MARK_CFG_VLAN_DEI_YELLOW,
+       NIX_MARK_CFG_VLAN_DEI_YELLOW_RED,
+       NIX_MARK_CFG_MAX,
+};
+
 /* For now considering MC resources needed for broadcast
  * pkt replication only. i.e 256 HWVFs + 12 PFs.
  */
@@ -939,6 +952,41 @@ int rvu_mbox_handler_nix_lf_free(struct rvu *rvu, struct msg_req *req,
        return 0;
 }
 
+int rvu_mbox_handler_nix_mark_format_cfg(struct rvu *rvu,
+                                        struct nix_mark_format_cfg  *req,
+                                        struct nix_mark_format_cfg_rsp *rsp)
+{
+       u16 pcifunc = req->hdr.pcifunc;
+       struct nix_hw *nix_hw;
+       struct rvu_pfvf *pfvf;
+       int blkaddr, rc;
+       u32 cfg;
+
+       pfvf = rvu_get_pfvf(rvu, pcifunc);
+       blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
+       if (!pfvf->nixlf || blkaddr < 0)
+               return NIX_AF_ERR_AF_LF_INVALID;
+
+       nix_hw = get_nix_hw(rvu->hw, blkaddr);
+       if (!nix_hw)
+               return -EINVAL;
+
+       cfg = (((u32)req->offset & 0x7) << 16) |
+             (((u32)req->y_mask & 0xF) << 12) |
+             (((u32)req->y_val & 0xF) << 8) |
+             (((u32)req->r_mask & 0xF) << 4) | ((u32)req->r_val & 0xF);
+
+       rc = rvu_nix_reserve_mark_format(rvu, nix_hw, blkaddr, cfg);
+       if (rc < 0) {
+               dev_err(rvu->dev, "No mark_format_ctl for (pf:%d, vf:%d)",
+                       rvu_get_pf(pcifunc), pcifunc & RVU_PFVF_FUNC_MASK);
+               return NIX_AF_ERR_MARK_CFG_FAIL;
+       }
+
+       rsp->mark_format_idx = rc;
+       return 0;
+}
+
 /* Disable shaping of pkts by a scheduler queue
  * at a given scheduler level.
  */
@@ -1829,6 +1877,57 @@ static int nix_setup_txschq(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr)
        return 0;
 }
 
+int rvu_nix_reserve_mark_format(struct rvu *rvu, struct nix_hw *nix_hw,
+                               int blkaddr, u32 cfg)
+{
+       int fmt_idx;
+
+       for (fmt_idx = 0; fmt_idx < nix_hw->mark_format.in_use; fmt_idx++) {
+               if (nix_hw->mark_format.cfg[fmt_idx] == cfg)
+                       return fmt_idx;
+       }
+       if (fmt_idx >= nix_hw->mark_format.total)
+               return -ERANGE;
+
+       rvu_write64(rvu, blkaddr, NIX_AF_MARK_FORMATX_CTL(fmt_idx), cfg);
+       nix_hw->mark_format.cfg[fmt_idx] = cfg;
+       nix_hw->mark_format.in_use++;
+       return fmt_idx;
+}
+
+static int nix_af_mark_format_setup(struct rvu *rvu, struct nix_hw *nix_hw,
+                                   int blkaddr)
+{
+       u64 cfgs[] = {
+               [NIX_MARK_CFG_IP_DSCP_RED]         = 0x10003,
+               [NIX_MARK_CFG_IP_DSCP_YELLOW]      = 0x11200,
+               [NIX_MARK_CFG_IP_DSCP_YELLOW_RED]  = 0x11203,
+               [NIX_MARK_CFG_IP_ECN_RED]          = 0x6000c,
+               [NIX_MARK_CFG_IP_ECN_YELLOW]       = 0x60c00,
+               [NIX_MARK_CFG_IP_ECN_YELLOW_RED]   = 0x60c0c,
+               [NIX_MARK_CFG_VLAN_DEI_RED]        = 0x30008,
+               [NIX_MARK_CFG_VLAN_DEI_YELLOW]     = 0x30800,
+               [NIX_MARK_CFG_VLAN_DEI_YELLOW_RED] = 0x30808,
+       };
+       int i, rc;
+       u64 total;
+
+       total = (rvu_read64(rvu, blkaddr, NIX_AF_PSE_CONST) & 0xFF00) >> 8;
+       nix_hw->mark_format.total = (u8)total;
+       nix_hw->mark_format.cfg = devm_kcalloc(rvu->dev, total, sizeof(u32),
+                                              GFP_KERNEL);
+       if (!nix_hw->mark_format.cfg)
+               return -ENOMEM;
+       for (i = 0; i < NIX_MARK_CFG_MAX; i++) {
+               rc = rvu_nix_reserve_mark_format(rvu, nix_hw, blkaddr, cfgs[i]);
+               if (rc < 0)
+                       dev_err(rvu->dev, "Err %d in setup mark format %d\n",
+                               i, rc);
+       }
+
+       return 0;
+}
+
 int rvu_mbox_handler_nix_stats_rst(struct rvu *rvu, struct msg_req *req,
                                   struct msg_rsp *rsp)
 {
@@ -2589,6 +2688,10 @@ int rvu_nix_init(struct rvu *rvu)
                if (err)
                        return err;
 
+               err = nix_af_mark_format_setup(rvu, hw->nix0, blkaddr);
+               if (err)
+                       return err;
+
                err = nix_setup_mcast(rvu, hw->nix0, blkaddr);
                if (err)
                        return err;