octeontx2-af: Add LSO format configuration mailbox

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>
This commit is contained in:
Nithin Dabilpuram 2018-12-02 18:17:48 +05:30 committed by David S. Miller
parent 159a8a6734
commit da5d32e1ab
3 changed files with 91 additions and 7 deletions

View File

@ -204,6 +204,9 @@ M(NIX_MARK_FORMAT_CFG, 0x800f, nix_mark_format_cfg, \
nix_mark_format_cfg, \ nix_mark_format_cfg, \
nix_mark_format_cfg_rsp) \ nix_mark_format_cfg_rsp) \
M(NIX_SET_RX_CFG, 0x8010, nix_set_rx_cfg, nix_rx_cfg, msg_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) M(NIX_RXVLAN_ALLOC, 0x8012, nix_rxvlan_alloc, msg_req, msg_rsp)
/* Messages initiated by AF (range 0xC00 - 0xDFF) */ /* 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_FIELD = -415,
NIX_AF_ERR_RSS_NOSPC_ALGO = -416, NIX_AF_ERR_RSS_NOSPC_ALGO = -416,
NIX_AF_ERR_MARK_CFG_FAIL = -417, NIX_AF_ERR_MARK_CFG_FAIL = -417,
NIX_AF_ERR_LSO_CFG_FAIL = -418,
NIX_AF_INVAL_NPA_PF_FUNC = -419, NIX_AF_INVAL_NPA_PF_FUNC = -419,
NIX_AF_INVAL_SSO_PF_FUNC = -420, NIX_AF_INVAL_SSO_PF_FUNC = -420,
}; };
@ -628,6 +632,18 @@ struct nix_frs_cfg {
u16 minlen; 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 */ /* NPC mbox message structs */
#define NPC_MCAM_ENTRY_INVALID 0xFFFF #define NPC_MCAM_ENTRY_INVALID 0xFFFF

View File

@ -180,11 +180,17 @@ struct nix_flowkey {
int in_use; int in_use;
}; };
struct nix_lso {
u8 total;
u8 in_use;
};
struct nix_hw { struct nix_hw {
struct nix_txsch txsch[NIX_TXSCH_LVL_CNT]; /* Tx schedulers */ struct nix_txsch txsch[NIX_TXSCH_LVL_CNT]; /* Tx schedulers */
struct nix_mcast mcast; struct nix_mcast mcast;
struct nix_flowkey flowkey; struct nix_flowkey flowkey;
struct nix_mark_format mark_format; struct nix_mark_format mark_format;
struct nix_lso lso;
}; };
struct rvu_hwinfo { 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); struct nix_mark_format_cfg_rsp *rsp);
int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req, int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req,
struct msg_rsp *rsp); 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 */ /* NPC APIs */
int rvu_npc_init(struct rvu *rvu); int rvu_npc_init(struct rvu *rvu);

View File

@ -298,17 +298,21 @@ static void nix_setup_lso_tso_l4(struct rvu *rvu, int blkaddr,
/* TCP's flags field */ /* TCP's flags field */
field.layer = NIX_TXLAYER_OL4; field.layer = NIX_TXLAYER_OL4;
field.offset = 12; field.offset = 12;
field.sizem1 = 0; /* not needed */ field.sizem1 = 1; /* 2 bytes */
field.alg = NIX_LSOALG_TCP_FLAGS; field.alg = NIX_LSOALG_TCP_FLAGS;
rvu_write64(rvu, blkaddr, rvu_write64(rvu, blkaddr,
NIX_AF_LSO_FORMATX_FIELDX(format, (*fidx)++), NIX_AF_LSO_FORMATX_FIELDX(format, (*fidx)++),
*(u64 *)&field); *(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; 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 */ /* Enable LSO */
cfg = rvu_read64(rvu, blkaddr, NIX_AF_LSO_CFG); cfg = rvu_read64(rvu, blkaddr, NIX_AF_LSO_CFG);
/* For TSO, set first and middle segment flags to /* 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); cfg |= (0xFFF2ULL << 32) | (0xFFF2ULL << 16);
rvu_write64(rvu, blkaddr, NIX_AF_LSO_CFG, cfg | BIT_ULL(63)); 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; idx = NIX_LSO_FORMAT_IDX_TSOV4;
nix_setup_lso_tso_l3(rvu, blkaddr, idx, true, &fidx); nix_setup_lso_tso_l3(rvu, blkaddr, idx, true, &fidx);
nix_setup_lso_tso_l4(rvu, blkaddr, idx, &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, rvu_write64(rvu, blkaddr,
NIX_AF_LSO_FORMATX_FIELDX(idx, fidx), 0x0ULL); NIX_AF_LSO_FORMATX_FIELDX(idx, fidx), 0x0ULL);
} }
nix_hw->lso.in_use++;
/* Configure format fields for TCPv6 segmentation offload */ /* Configure format fields for TCPv6 segmentation offload */
idx = NIX_LSO_FORMAT_IDX_TSOV6; idx = NIX_LSO_FORMAT_IDX_TSOV6;
@ -340,6 +348,7 @@ static void nix_setup_lso(struct rvu *rvu, int blkaddr)
rvu_write64(rvu, blkaddr, rvu_write64(rvu, blkaddr,
NIX_AF_LSO_FORMATX_FIELDX(idx, fidx), 0x0ULL); 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) 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 */ /* Restore CINT timer delay to HW reset values */
rvu_write64(rvu, blkaddr, NIX_AF_CINT_DELAY, 0x0ULL); rvu_write64(rvu, blkaddr, NIX_AF_CINT_DELAY, 0x0ULL);
/* Configure segmentation offload formats */
nix_setup_lso(rvu, blkaddr);
if (blkaddr == BLKADDR_NIX0) { if (blkaddr == BLKADDR_NIX0) {
hw->nix0 = devm_kzalloc(rvu->dev, hw->nix0 = devm_kzalloc(rvu->dev,
sizeof(struct nix_hw), GFP_KERNEL); sizeof(struct nix_hw), GFP_KERNEL);
@ -2745,6 +2751,9 @@ int rvu_nix_init(struct rvu *rvu)
if (err) if (err)
return 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. /* Config Outer/Inner L2, IP, TCP, UDP and SCTP NPC layer info.
* This helps HW protocol checker to identify headers * This helps HW protocol checker to identify headers
* and validate length and checksums. * 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); 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;
}