Commit 7ee74697 authored by Jerin Jacob's avatar Jerin Jacob Committed by David S. Miller

octeontx2-af: Add support for runtime RSS algo index reservation

Introduced reserve_flowkey_alg_idx()to reserve RSS algorithm index,
it would internally use set_flowkey_fields() to generate fields
based on the flow key dynamically.

On AF driver init, it would reserve a predefined set RSS algo indexes,
which will be available all the time for all the AF driver consumers.
The leftover algo indexes can be reserved at runtime through
exiting nix_rss_flowkey_cfg mailbox message.

The NIX_FLOW_KEY_TYPE_PORT is removed from predefined a set of RSS flow
type as it is not used by any consumer.
Signed-off-by: default avatarJerin Jacob <jerinj@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b648366c
...@@ -193,18 +193,4 @@ enum nix_scheduler { ...@@ -193,18 +193,4 @@ enum nix_scheduler {
#define DEFAULT_RSS_CONTEXT_GROUP 0 #define DEFAULT_RSS_CONTEXT_GROUP 0
#define MAX_RSS_INDIR_TBL_SIZE 256 /* 1 << Max adder bits */ #define MAX_RSS_INDIR_TBL_SIZE 256 /* 1 << Max adder bits */
/* NIX flow tag algorithm indices, max is 31 */
enum {
NIX_FLOW_KEY_ALG_PORT,
NIX_FLOW_KEY_ALG_IP,
NIX_FLOW_KEY_ALG_TCP,
NIX_FLOW_KEY_ALG_UDP,
NIX_FLOW_KEY_ALG_SCTP,
NIX_FLOW_KEY_ALG_TCP_UDP,
NIX_FLOW_KEY_ALG_TCP_SCTP,
NIX_FLOW_KEY_ALG_UDP_SCTP,
NIX_FLOW_KEY_ALG_TCP_UDP_SCTP,
NIX_FLOW_KEY_ALG_MAX,
};
#endif /* COMMON_H */ #endif /* COMMON_H */
...@@ -415,6 +415,7 @@ enum nix_af_status { ...@@ -415,6 +415,7 @@ enum nix_af_status {
NIX_AF_SMQ_FLUSH_FAILED = -413, NIX_AF_SMQ_FLUSH_FAILED = -413,
NIX_AF_ERR_LF_RESET = -414, NIX_AF_ERR_LF_RESET = -414,
NIX_AF_ERR_RSS_NOSPC_FIELD = -415, NIX_AF_ERR_RSS_NOSPC_FIELD = -415,
NIX_AF_ERR_RSS_NOSPC_ALGO = -416,
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,
}; };
......
...@@ -164,9 +164,16 @@ struct npc_pkind { ...@@ -164,9 +164,16 @@ struct npc_pkind {
u32 *pfchan_map; u32 *pfchan_map;
}; };
struct nix_flowkey {
#define NIX_FLOW_KEY_ALG_MAX 32
u32 flowkey[NIX_FLOW_KEY_ALG_MAX];
int 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 rvu_hwinfo { struct rvu_hwinfo {
......
...@@ -1597,57 +1597,16 @@ int rvu_mbox_handler_nix_stats_rst(struct rvu *rvu, struct msg_req *req, ...@@ -1597,57 +1597,16 @@ int rvu_mbox_handler_nix_stats_rst(struct rvu *rvu, struct msg_req *req,
} }
/* Returns the ALG index to be set into NPC_RX_ACTION */ /* Returns the ALG index to be set into NPC_RX_ACTION */
static int get_flowkey_alg_idx(u32 flow_cfg) static int get_flowkey_alg_idx(struct nix_hw *nix_hw, u32 flow_cfg)
{ {
u32 ip_cfg; int i;
flow_cfg &= ~NIX_FLOW_KEY_TYPE_PORT;
ip_cfg = NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6;
if (flow_cfg == ip_cfg)
return NIX_FLOW_KEY_ALG_IP;
else if (flow_cfg == (ip_cfg | NIX_FLOW_KEY_TYPE_TCP))
return NIX_FLOW_KEY_ALG_TCP;
else if (flow_cfg == (ip_cfg | NIX_FLOW_KEY_TYPE_UDP))
return NIX_FLOW_KEY_ALG_UDP;
else if (flow_cfg == (ip_cfg | NIX_FLOW_KEY_TYPE_SCTP))
return NIX_FLOW_KEY_ALG_SCTP;
else if (flow_cfg == (ip_cfg | NIX_FLOW_KEY_TYPE_TCP |
NIX_FLOW_KEY_TYPE_UDP))
return NIX_FLOW_KEY_ALG_TCP_UDP;
else if (flow_cfg == (ip_cfg | NIX_FLOW_KEY_TYPE_TCP |
NIX_FLOW_KEY_TYPE_SCTP))
return NIX_FLOW_KEY_ALG_TCP_SCTP;
else if (flow_cfg == (ip_cfg | NIX_FLOW_KEY_TYPE_UDP |
NIX_FLOW_KEY_TYPE_SCTP))
return NIX_FLOW_KEY_ALG_UDP_SCTP;
else if (flow_cfg == (ip_cfg | NIX_FLOW_KEY_TYPE_TCP |
NIX_FLOW_KEY_TYPE_UDP | NIX_FLOW_KEY_TYPE_SCTP))
return NIX_FLOW_KEY_ALG_TCP_UDP_SCTP;
return NIX_FLOW_KEY_ALG_PORT;
}
int rvu_mbox_handler_nix_rss_flowkey_cfg(struct rvu *rvu, /* Scan over exiting algo entries to find a match */
struct nix_rss_flowkey_cfg *req, for (i = 0; i < nix_hw->flowkey.in_use; i++)
struct nix_rss_flowkey_cfg_rsp *rsp) if (nix_hw->flowkey.flowkey[i] == flow_cfg)
{ return i;
struct rvu_hwinfo *hw = rvu->hw;
u16 pcifunc = req->hdr.pcifunc;
int alg_idx, nixlf, blkaddr;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); return -ERANGE;
if (blkaddr < 0)
return NIX_AF_ERR_AF_LF_INVALID;
nixlf = rvu_get_lf(rvu, &hw->block[blkaddr], pcifunc, 0);
if (nixlf < 0)
return NIX_AF_ERR_AF_LF_INVALID;
alg_idx = get_flowkey_alg_idx(req->flowkey_cfg);
rsp->alg_idx = alg_idx;
rvu_npc_update_flowkey_alg_idx(rvu, pcifunc, nixlf, req->group,
alg_idx, req->mcam_index);
return 0;
} }
static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
...@@ -1781,71 +1740,141 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) ...@@ -1781,71 +1740,141 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
return NIX_AF_ERR_RSS_NOSPC_FIELD; return NIX_AF_ERR_RSS_NOSPC_FIELD;
} }
static void nix_rx_flowkey_alg_cfg(struct rvu *rvu, int blkaddr) static int reserve_flowkey_alg_idx(struct rvu *rvu, int blkaddr, u32 flow_cfg)
{ {
u64 field[NIX_FLOW_KEY_ALG_MAX][FIELDS_PER_ALG]; u64 field[FIELDS_PER_ALG];
u32 flowkey_cfg, minkey_cfg; struct nix_hw *hw;
int alg, fid; int fid, rc;
memset(&field, 0, sizeof(u64) * NIX_FLOW_KEY_ALG_MAX * FIELDS_PER_ALG); hw = get_nix_hw(rvu->hw, blkaddr);
if (!hw)
return -EINVAL;
/* Only incoming channel number */ /* No room to add new flow hash algoritham */
flowkey_cfg = NIX_FLOW_KEY_TYPE_PORT; if (hw->flowkey.in_use >= NIX_FLOW_KEY_ALG_MAX)
set_flowkey_fields((void *)&field[NIX_FLOW_KEY_ALG_PORT], flowkey_cfg); return NIX_AF_ERR_RSS_NOSPC_ALGO;
/* For a incoming pkt if none of the fields match then flowkey /* Generate algo fields for the given flow_cfg */
* will be zero, hence tag generated will also be zero. rc = set_flowkey_fields((struct nix_rx_flowkey_alg *)field, flow_cfg);
* RSS entry at rsse_index = NIX_AF_LF()_RSS_GRP()[OFFSET] will if (rc)
* be used to queue the packet. return rc;
*/
/* Update ALGX_FIELDX register with generated fields */
for (fid = 0; fid < FIELDS_PER_ALG; fid++)
rvu_write64(rvu, blkaddr,
NIX_AF_RX_FLOW_KEY_ALGX_FIELDX(hw->flowkey.in_use,
fid), field[fid]);
/* Store the flow_cfg for futher lookup */
rc = hw->flowkey.in_use;
hw->flowkey.flowkey[rc] = flow_cfg;
hw->flowkey.in_use++;
return rc;
}
int rvu_mbox_handler_nix_rss_flowkey_cfg(struct rvu *rvu,
struct nix_rss_flowkey_cfg *req,
struct nix_rss_flowkey_cfg_rsp *rsp)
{
struct rvu_hwinfo *hw = rvu->hw;
u16 pcifunc = req->hdr.pcifunc;
int alg_idx, nixlf, blkaddr;
struct nix_hw *nix_hw;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
if (blkaddr < 0)
return NIX_AF_ERR_AF_LF_INVALID;
nixlf = rvu_get_lf(rvu, &hw->block[blkaddr], pcifunc, 0);
if (nixlf < 0)
return NIX_AF_ERR_AF_LF_INVALID;
nix_hw = get_nix_hw(rvu->hw, blkaddr);
if (!nix_hw)
return -EINVAL;
alg_idx = get_flowkey_alg_idx(nix_hw, req->flowkey_cfg);
/* Failed to get algo index from the exiting list, reserve new */
if (alg_idx < 0) {
alg_idx = reserve_flowkey_alg_idx(rvu, blkaddr,
req->flowkey_cfg);
if (alg_idx < 0)
return alg_idx;
}
rsp->alg_idx = alg_idx;
rvu_npc_update_flowkey_alg_idx(rvu, pcifunc, nixlf, req->group,
alg_idx, req->mcam_index);
return 0;
}
static int nix_rx_flowkey_alg_cfg(struct rvu *rvu, int blkaddr)
{
u32 flowkey_cfg, minkey_cfg;
int alg, fid, rc;
/* Disable all flow key algx fieldx */
for (alg = 0; alg < NIX_FLOW_KEY_ALG_MAX; alg++) {
for (fid = 0; fid < FIELDS_PER_ALG; fid++)
rvu_write64(rvu, blkaddr,
NIX_AF_RX_FLOW_KEY_ALGX_FIELDX(alg, fid),
0);
}
/* IPv4/IPv6 SIP/DIPs */ /* IPv4/IPv6 SIP/DIPs */
flowkey_cfg = NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6; flowkey_cfg = NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6;
set_flowkey_fields((void *)&field[NIX_FLOW_KEY_ALG_IP], flowkey_cfg); rc = reserve_flowkey_alg_idx(rvu, blkaddr, flowkey_cfg);
if (rc < 0)
return rc;
/* TCPv4/v6 4-tuple, SIP, DIP, Sport, Dport */ /* TCPv4/v6 4-tuple, SIP, DIP, Sport, Dport */
minkey_cfg = flowkey_cfg; minkey_cfg = flowkey_cfg;
flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_TCP; flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_TCP;
set_flowkey_fields((void *)&field[NIX_FLOW_KEY_ALG_TCP], flowkey_cfg); rc = reserve_flowkey_alg_idx(rvu, blkaddr, flowkey_cfg);
if (rc < 0)
return rc;
/* UDPv4/v6 4-tuple, SIP, DIP, Sport, Dport */ /* UDPv4/v6 4-tuple, SIP, DIP, Sport, Dport */
flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_UDP; flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_UDP;
set_flowkey_fields((void *)&field[NIX_FLOW_KEY_ALG_UDP], flowkey_cfg); rc = reserve_flowkey_alg_idx(rvu, blkaddr, flowkey_cfg);
if (rc < 0)
return rc;
/* SCTPv4/v6 4-tuple, SIP, DIP, Sport, Dport */ /* SCTPv4/v6 4-tuple, SIP, DIP, Sport, Dport */
flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_SCTP; flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_SCTP;
set_flowkey_fields((void *)&field[NIX_FLOW_KEY_ALG_SCTP], flowkey_cfg); rc = reserve_flowkey_alg_idx(rvu, blkaddr, flowkey_cfg);
if (rc < 0)
return rc;
/* TCP/UDP v4/v6 4-tuple, rest IP pkts 2-tuple */ /* TCP/UDP v4/v6 4-tuple, rest IP pkts 2-tuple */
flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_TCP | flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_TCP |
NIX_FLOW_KEY_TYPE_UDP; NIX_FLOW_KEY_TYPE_UDP;
set_flowkey_fields((void *)&field[NIX_FLOW_KEY_ALG_TCP_UDP], rc = reserve_flowkey_alg_idx(rvu, blkaddr, flowkey_cfg);
flowkey_cfg); if (rc < 0)
return rc;
/* TCP/SCTP v4/v6 4-tuple, rest IP pkts 2-tuple */ /* TCP/SCTP v4/v6 4-tuple, rest IP pkts 2-tuple */
flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_TCP | flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_TCP |
NIX_FLOW_KEY_TYPE_SCTP; NIX_FLOW_KEY_TYPE_SCTP;
set_flowkey_fields((void *)&field[NIX_FLOW_KEY_ALG_TCP_SCTP], rc = reserve_flowkey_alg_idx(rvu, blkaddr, flowkey_cfg);
flowkey_cfg); if (rc < 0)
return rc;
/* UDP/SCTP v4/v6 4-tuple, rest IP pkts 2-tuple */ /* UDP/SCTP v4/v6 4-tuple, rest IP pkts 2-tuple */
flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_UDP | flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_UDP |
NIX_FLOW_KEY_TYPE_SCTP; NIX_FLOW_KEY_TYPE_SCTP;
set_flowkey_fields((void *)&field[NIX_FLOW_KEY_ALG_UDP_SCTP], rc = reserve_flowkey_alg_idx(rvu, blkaddr, flowkey_cfg);
flowkey_cfg); if (rc < 0)
return rc;
/* TCP/UDP/SCTP v4/v6 4-tuple, rest IP pkts 2-tuple */ /* TCP/UDP/SCTP v4/v6 4-tuple, rest IP pkts 2-tuple */
flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_TCP | flowkey_cfg = minkey_cfg | NIX_FLOW_KEY_TYPE_TCP |
NIX_FLOW_KEY_TYPE_UDP | NIX_FLOW_KEY_TYPE_SCTP; NIX_FLOW_KEY_TYPE_UDP | NIX_FLOW_KEY_TYPE_SCTP;
set_flowkey_fields((void *)&field[NIX_FLOW_KEY_ALG_TCP_UDP_SCTP], rc = reserve_flowkey_alg_idx(rvu, blkaddr, flowkey_cfg);
flowkey_cfg); if (rc < 0)
return rc;
for (alg = 0; alg < NIX_FLOW_KEY_ALG_MAX; alg++) { return 0;
for (fid = 0; fid < FIELDS_PER_ALG; fid++)
rvu_write64(rvu, blkaddr,
NIX_AF_RX_FLOW_KEY_ALGX_FIELDX(alg, fid),
field[alg][fid]);
}
} }
int rvu_mbox_handler_nix_set_mac_addr(struct rvu *rvu, int rvu_mbox_handler_nix_set_mac_addr(struct rvu *rvu,
...@@ -2314,7 +2343,9 @@ int rvu_nix_init(struct rvu *rvu) ...@@ -2314,7 +2343,9 @@ int rvu_nix_init(struct rvu *rvu)
rvu_write64(rvu, blkaddr, NIX_AF_RX_DEF_OIP4, rvu_write64(rvu, blkaddr, NIX_AF_RX_DEF_OIP4,
(NPC_LID_LC << 8) | (NPC_LT_LC_IP << 4) | 0x0F); (NPC_LID_LC << 8) | (NPC_LT_LC_IP << 4) | 0x0F);
nix_rx_flowkey_alg_cfg(rvu, blkaddr); err = nix_rx_flowkey_alg_cfg(rvu, blkaddr);
if (err)
return err;
/* Initialize CGX/LBK/SDP link credits, min/max pkt lengths */ /* Initialize CGX/LBK/SDP link credits, min/max pkt lengths */
nix_link_config(rvu, blkaddr); nix_link_config(rvu, blkaddr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment