octeontx2-af: Add LSO format configuration mailbox
authorNithin Dabilpuram <ndabilpuram@marvell.com>
Sun, 2 Dec 2018 12:47:48 +0000 (18:17 +0530)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Dec 2018 00:23:08 +0000 (16:23 -0800)
NIX_AF_LSO_FORMAT(0..31)_FIELD(0..7) register enables an SW defined
means to define LSO packet modification formats.

0..31 works as an index to choose the algorithm, On success, the mailbox
returns the index to the client of chosen LSO algorithm selection.
This index will be used in configuring the transmit descriptors.

Add mailbox interface to dynamically reserve and configure LSO format.

This commit also fixes 'sizem1' for NIX_LSOALG_TCP_FLAGS
to '1' i.e 2 Bytes.

Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
Signed-off-by: Sunil Goutham <sgoutham@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 0707a5aa6b1f28f6a31abeb903034dc0f136367b..f8c332b1acec01c5a841a02fab6a8ea03348733f 100644 (file)
@@ -204,6 +204,9 @@ M(NIX_MARK_FORMAT_CFG,      0x800f, nix_mark_format_cfg,                    \
                                 nix_mark_format_cfg,                   \
                                 nix_mark_format_cfg_rsp)               \
 M(NIX_SET_RX_CFG,      0x8010, nix_set_rx_cfg, nix_rx_cfg, msg_rsp)    \
+M(NIX_LSO_FORMAT_CFG,  0x8011, nix_lso_format_cfg,                     \
+                                nix_lso_format_cfg,                    \
+                                nix_lso_format_cfg_rsp)                \
 M(NIX_RXVLAN_ALLOC,    0x8012, nix_rxvlan_alloc, msg_req, msg_rsp)
 
 /* Messages initiated by AF (range 0xC00 - 0xDFF) */
@@ -421,6 +424,7 @@ enum nix_af_status {
        NIX_AF_ERR_RSS_NOSPC_FIELD  = -415,
        NIX_AF_ERR_RSS_NOSPC_ALGO   = -416,
        NIX_AF_ERR_MARK_CFG_FAIL    = -417,
+       NIX_AF_ERR_LSO_CFG_FAIL     = -418,
        NIX_AF_INVAL_NPA_PF_FUNC    = -419,
        NIX_AF_INVAL_SSO_PF_FUNC    = -420,
 };
@@ -628,6 +632,18 @@ struct nix_frs_cfg {
        u16     minlen;
 };
 
+struct nix_lso_format_cfg {
+       struct mbox_msghdr hdr;
+       u64 field_mask;
+#define NIX_LSO_FIELD_MAX      8
+       u64 fields[NIX_LSO_FIELD_MAX];
+};
+
+struct nix_lso_format_cfg_rsp {
+       struct mbox_msghdr hdr;
+       u8 lso_format_idx;
+};
+
 /* NPC mbox message structs */
 
 #define NPC_MCAM_ENTRY_INVALID 0xFFFF
index c6d61a3a57299f3600d473540eadda7b743fe6a7..3abdb98fb3481dd034023132edf6c8573de7d635 100644 (file)
@@ -180,11 +180,17 @@ struct nix_flowkey {
        int in_use;
 };
 
+struct nix_lso {
+       u8 total;
+       u8 in_use;
+};
+
 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 nix_lso lso;
 };
 
 struct rvu_hwinfo {
@@ -435,7 +441,9 @@ int rvu_mbox_handler_nix_mark_format_cfg(struct rvu *rvu,
                                         struct nix_mark_format_cfg_rsp *rsp);
 int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req,
                                    struct msg_rsp *rsp);
-
+int rvu_mbox_handler_nix_lso_format_cfg(struct rvu *rvu,
+                                       struct nix_lso_format_cfg *req,
+                                       struct nix_lso_format_cfg_rsp *rsp);
 
 /* NPC APIs */
 int rvu_npc_init(struct rvu *rvu);
index f1bd9de54cb7caf42befae7e9e344b7abf1209c7..4a7609fd6dd07bba4180f5b39d860ad717cc215b 100644 (file)
@@ -298,17 +298,21 @@ static void nix_setup_lso_tso_l4(struct rvu *rvu, int blkaddr,
        /* TCP's flags field */
        field.layer = NIX_TXLAYER_OL4;
        field.offset = 12;
-       field.sizem1 = 0; /* not needed */
+       field.sizem1 = 1; /* 2 bytes */
        field.alg = NIX_LSOALG_TCP_FLAGS;
        rvu_write64(rvu, blkaddr,
                    NIX_AF_LSO_FORMATX_FIELDX(format, (*fidx)++),
                    *(u64 *)&field);
 }
 
-static void nix_setup_lso(struct rvu *rvu, int blkaddr)
+static void nix_setup_lso(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr)
 {
        u64 cfg, idx, fidx = 0;
 
+       /* Get max HW supported format indices */
+       cfg = (rvu_read64(rvu, blkaddr, NIX_AF_CONST1) >> 48) & 0xFF;
+       nix_hw->lso.total = cfg;
+
        /* Enable LSO */
        cfg = rvu_read64(rvu, blkaddr, NIX_AF_LSO_CFG);
        /* For TSO, set first and middle segment flags to
@@ -318,7 +322,10 @@ static void nix_setup_lso(struct rvu *rvu, int blkaddr)
        cfg |= (0xFFF2ULL << 32) | (0xFFF2ULL << 16);
        rvu_write64(rvu, blkaddr, NIX_AF_LSO_CFG, cfg | BIT_ULL(63));
 
-       /* Configure format fields for TCPv4 segmentation offload */
+       /* Setup default static LSO formats
+        *
+        * Configure format fields for TCPv4 segmentation offload
+        */
        idx = NIX_LSO_FORMAT_IDX_TSOV4;
        nix_setup_lso_tso_l3(rvu, blkaddr, idx, true, &fidx);
        nix_setup_lso_tso_l4(rvu, blkaddr, idx, &fidx);
@@ -328,6 +335,7 @@ static void nix_setup_lso(struct rvu *rvu, int blkaddr)
                rvu_write64(rvu, blkaddr,
                            NIX_AF_LSO_FORMATX_FIELDX(idx, fidx), 0x0ULL);
        }
+       nix_hw->lso.in_use++;
 
        /* Configure format fields for TCPv6 segmentation offload */
        idx = NIX_LSO_FORMAT_IDX_TSOV6;
@@ -340,6 +348,7 @@ static void nix_setup_lso(struct rvu *rvu, int blkaddr)
                rvu_write64(rvu, blkaddr,
                            NIX_AF_LSO_FORMATX_FIELDX(idx, fidx), 0x0ULL);
        }
+       nix_hw->lso.in_use++;
 }
 
 static void nix_ctx_free(struct rvu *rvu, struct rvu_pfvf *pfvf)
@@ -2724,9 +2733,6 @@ int rvu_nix_init(struct rvu *rvu)
        /* Restore CINT timer delay to HW reset values */
        rvu_write64(rvu, blkaddr, NIX_AF_CINT_DELAY, 0x0ULL);
 
-       /* Configure segmentation offload formats */
-       nix_setup_lso(rvu, blkaddr);
-
        if (blkaddr == BLKADDR_NIX0) {
                hw->nix0 = devm_kzalloc(rvu->dev,
                                        sizeof(struct nix_hw), GFP_KERNEL);
@@ -2745,6 +2751,9 @@ int rvu_nix_init(struct rvu *rvu)
                if (err)
                        return err;
 
+               /* Configure segmentation offload formats */
+               nix_setup_lso(rvu, hw->nix0, blkaddr);
+
                /* Config Outer/Inner L2, IP, TCP, UDP and SCTP NPC layer info.
                 * This helps HW protocol checker to identify headers
                 * and validate length and checksums.
@@ -2897,3 +2906,54 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
 
        nix_ctx_free(rvu, pfvf);
 }
+
+int rvu_mbox_handler_nix_lso_format_cfg(struct rvu *rvu,
+                                       struct nix_lso_format_cfg *req,
+                                       struct nix_lso_format_cfg_rsp *rsp)
+{
+       u16 pcifunc = req->hdr.pcifunc;
+       struct nix_hw *nix_hw;
+       struct rvu_pfvf *pfvf;
+       int blkaddr, idx, f;
+       u64 reg;
+
+       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;
+
+       /* Find existing matching LSO format, if any */
+       for (idx = 0; idx < nix_hw->lso.in_use; idx++) {
+               for (f = 0; f < NIX_LSO_FIELD_MAX; f++) {
+                       reg = rvu_read64(rvu, blkaddr,
+                                        NIX_AF_LSO_FORMATX_FIELDX(idx, f));
+                       if (req->fields[f] != (reg & req->field_mask))
+                               break;
+               }
+
+               if (f == NIX_LSO_FIELD_MAX)
+                       break;
+       }
+
+       if (idx < nix_hw->lso.in_use) {
+               /* Match found */
+               rsp->lso_format_idx = idx;
+               return 0;
+       }
+
+       if (nix_hw->lso.in_use == nix_hw->lso.total)
+               return NIX_AF_ERR_LSO_CFG_FAIL;
+
+       rsp->lso_format_idx = nix_hw->lso.in_use++;
+
+       for (f = 0; f < NIX_LSO_FIELD_MAX; f++)
+               rvu_write64(rvu, blkaddr,
+                           NIX_AF_LSO_FORMATX_FIELDX(rsp->lso_format_idx, f),
+                           req->fields[f]);
+
+       return 0;
+}