summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/marvell/octeontx2/nic
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:36 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:36 +0000
commit50ba0232fd5312410f1b65247e774244f89a628e (patch)
treefd8f2fc78e9e548af0ff9590276602ee6125be00 /drivers/net/ethernet/marvell/octeontx2/nic
parentReleasing progress-linux version 6.7.12-1~progress7.99u1. (diff)
downloadlinux-50ba0232fd5312410f1b65247e774244f89a628e.tar.xz
linux-50ba0232fd5312410f1b65247e774244f89a628e.zip
Merging upstream version 6.8.9.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/net/ethernet/marvell/octeontx2/nic')
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c80
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c134
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/qos.c1
4 files changed, 166 insertions, 51 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index 8b7fc0af91..7f786de610 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -834,21 +834,26 @@ static int otx2_rss_ctx_create(struct otx2_nic *pfvf,
return 0;
}
-/* RSS context configuration */
-static int otx2_set_rxfh_context(struct net_device *dev, const u32 *indir,
- const u8 *hkey, const u8 hfunc,
- u32 *rss_context, bool delete)
+/* Configure RSS table and hash key */
+static int otx2_set_rxfh(struct net_device *dev,
+ struct ethtool_rxfh_param *rxfh,
+ struct netlink_ext_ack *extack)
{
+ u32 rss_context = DEFAULT_RSS_CONTEXT_GROUP;
struct otx2_nic *pfvf = netdev_priv(dev);
struct otx2_rss_ctx *rss_ctx;
struct otx2_rss_info *rss;
int ret, idx;
- if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
+ if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
+ rxfh->hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
- if (*rss_context != ETH_RXFH_CONTEXT_ALLOC &&
- *rss_context >= MAX_RSS_GROUPS)
+ if (rxfh->rss_context)
+ rss_context = rxfh->rss_context;
+
+ if (rss_context != ETH_RXFH_CONTEXT_ALLOC &&
+ rss_context >= MAX_RSS_GROUPS)
return -EINVAL;
rss = &pfvf->hw.rss_info;
@@ -858,40 +863,45 @@ static int otx2_set_rxfh_context(struct net_device *dev, const u32 *indir,
return -EIO;
}
- if (hkey) {
- memcpy(rss->key, hkey, sizeof(rss->key));
+ if (rxfh->key) {
+ memcpy(rss->key, rxfh->key, sizeof(rss->key));
otx2_set_rss_key(pfvf);
}
- if (delete)
- return otx2_rss_ctx_delete(pfvf, *rss_context);
+ if (rxfh->rss_delete)
+ return otx2_rss_ctx_delete(pfvf, rss_context);
- if (*rss_context == ETH_RXFH_CONTEXT_ALLOC) {
- ret = otx2_rss_ctx_create(pfvf, rss_context);
+ if (rss_context == ETH_RXFH_CONTEXT_ALLOC) {
+ ret = otx2_rss_ctx_create(pfvf, &rss_context);
+ rxfh->rss_context = rss_context;
if (ret)
return ret;
}
- if (indir) {
- rss_ctx = rss->rss_ctx[*rss_context];
+ if (rxfh->indir) {
+ rss_ctx = rss->rss_ctx[rss_context];
for (idx = 0; idx < rss->rss_size; idx++)
- rss_ctx->ind_tbl[idx] = indir[idx];
+ rss_ctx->ind_tbl[idx] = rxfh->indir[idx];
}
- otx2_set_rss_table(pfvf, *rss_context);
+ otx2_set_rss_table(pfvf, rss_context);
return 0;
}
-static int otx2_get_rxfh_context(struct net_device *dev, u32 *indir,
- u8 *hkey, u8 *hfunc, u32 rss_context)
+/* Get RSS configuration */
+static int otx2_get_rxfh(struct net_device *dev,
+ struct ethtool_rxfh_param *rxfh)
{
+ u32 rss_context = DEFAULT_RSS_CONTEXT_GROUP;
struct otx2_nic *pfvf = netdev_priv(dev);
struct otx2_rss_ctx *rss_ctx;
struct otx2_rss_info *rss;
+ u32 *indir = rxfh->indir;
int idx, rx_queues;
rss = &pfvf->hw.rss_info;
- if (hfunc)
- *hfunc = ETH_RSS_HASH_TOP;
+ rxfh->hfunc = ETH_RSS_HASH_TOP;
+ if (rxfh->rss_context)
+ rss_context = rxfh->rss_context;
if (!indir)
return 0;
@@ -913,30 +923,12 @@ static int otx2_get_rxfh_context(struct net_device *dev, u32 *indir,
for (idx = 0; idx < rss->rss_size; idx++)
indir[idx] = rss_ctx->ind_tbl[idx];
}
- if (hkey)
- memcpy(hkey, rss->key, sizeof(rss->key));
+ if (rxfh->key)
+ memcpy(rxfh->key, rss->key, sizeof(rss->key));
return 0;
}
-/* Get RSS configuration */
-static int otx2_get_rxfh(struct net_device *dev, u32 *indir,
- u8 *hkey, u8 *hfunc)
-{
- return otx2_get_rxfh_context(dev, indir, hkey, hfunc,
- DEFAULT_RSS_CONTEXT_GROUP);
-}
-
-/* Configure RSS table and hash key */
-static int otx2_set_rxfh(struct net_device *dev, const u32 *indir,
- const u8 *hkey, const u8 hfunc)
-{
-
- u32 rss_context = DEFAULT_RSS_CONTEXT_GROUP;
-
- return otx2_set_rxfh_context(dev, indir, hkey, hfunc, &rss_context, 0);
-}
-
static u32 otx2_get_msglevel(struct net_device *netdev)
{
struct otx2_nic *pfvf = netdev_priv(netdev);
@@ -1317,6 +1309,7 @@ static void otx2_get_fec_stats(struct net_device *netdev,
}
static const struct ethtool_ops otx2_ethtool_ops = {
+ .cap_rss_ctx_supported = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE,
@@ -1339,8 +1332,6 @@ static const struct ethtool_ops otx2_ethtool_ops = {
.get_rxfh_indir_size = otx2_get_rxfh_indir_size,
.get_rxfh = otx2_get_rxfh,
.set_rxfh = otx2_set_rxfh,
- .get_rxfh_context = otx2_get_rxfh_context,
- .set_rxfh_context = otx2_set_rxfh_context,
.get_msglevel = otx2_get_msglevel,
.set_msglevel = otx2_set_msglevel,
.get_pauseparam = otx2_get_pauseparam,
@@ -1440,6 +1431,7 @@ static int otx2vf_get_link_ksettings(struct net_device *netdev,
}
static const struct ethtool_ops otx2vf_ethtool_ops = {
+ .cap_rss_ctx_supported = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE,
@@ -1458,8 +1450,6 @@ static const struct ethtool_ops otx2vf_ethtool_ops = {
.get_rxfh_indir_size = otx2_get_rxfh_indir_size,
.get_rxfh = otx2_get_rxfh,
.set_rxfh = otx2_set_rxfh,
- .get_rxfh_context = otx2_get_rxfh_context,
- .set_rxfh_context = otx2_set_rxfh_context,
.get_ringparam = otx2_get_ringparam,
.set_ringparam = otx2_set_ringparam,
.get_coalesce = otx2_get_coalesce,
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index b40bd0e467..3f46d5e0fb 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1933,7 +1933,7 @@ int otx2_open(struct net_device *netdev)
* mcam entries are enabled to receive the packets. Hence disable the
* packet I/O.
*/
- if (err == EIO)
+ if (err == -EIO)
goto err_disable_rxtx;
else if (err)
goto err_tx_stop_queues;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
index db1e0e0e81..60ee7ae2c4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
@@ -29,6 +29,8 @@
#define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4)
+#define MCAST_INVALID_GRP (-1U)
+
struct otx2_tc_flow_stats {
u64 bytes;
u64 pkts;
@@ -47,6 +49,7 @@ struct otx2_tc_flow {
bool is_act_police;
u32 prio;
struct npc_install_flow_req req;
+ u32 mcast_grp_idx;
u64 rate;
u32 burst;
bool is_pps;
@@ -355,22 +358,96 @@ static int otx2_tc_act_set_police(struct otx2_nic *nic,
return rc;
}
+static int otx2_tc_update_mcast(struct otx2_nic *nic,
+ struct npc_install_flow_req *req,
+ struct netlink_ext_ack *extack,
+ struct otx2_tc_flow *node,
+ struct nix_mcast_grp_update_req *ureq,
+ u8 num_intf)
+{
+ struct nix_mcast_grp_update_req *grp_update_req;
+ struct nix_mcast_grp_create_req *creq;
+ struct nix_mcast_grp_create_rsp *crsp;
+ u32 grp_index;
+ int rc;
+
+ mutex_lock(&nic->mbox.lock);
+ creq = otx2_mbox_alloc_msg_nix_mcast_grp_create(&nic->mbox);
+ if (!creq) {
+ rc = -ENOMEM;
+ goto error;
+ }
+
+ creq->dir = NIX_MCAST_INGRESS;
+ /* Send message to AF */
+ rc = otx2_sync_mbox_msg(&nic->mbox);
+ if (rc) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to create multicast group");
+ goto error;
+ }
+
+ crsp = (struct nix_mcast_grp_create_rsp *)otx2_mbox_get_rsp(&nic->mbox.mbox,
+ 0,
+ &creq->hdr);
+ if (IS_ERR(crsp)) {
+ rc = PTR_ERR(crsp);
+ goto error;
+ }
+
+ grp_index = crsp->mcast_grp_idx;
+ grp_update_req = otx2_mbox_alloc_msg_nix_mcast_grp_update(&nic->mbox);
+ if (!grp_update_req) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to update multicast group");
+ rc = -ENOMEM;
+ goto error;
+ }
+
+ ureq->op = NIX_MCAST_OP_ADD_ENTRY;
+ ureq->mcast_grp_idx = grp_index;
+ ureq->num_mce_entry = num_intf;
+ ureq->pcifunc[0] = nic->pcifunc;
+ ureq->channel[0] = nic->hw.tx_chan_base;
+
+ ureq->dest_type[0] = NIX_RX_RSS;
+ ureq->rq_rss_index[0] = 0;
+ memcpy(&ureq->hdr, &grp_update_req->hdr, sizeof(struct mbox_msghdr));
+ memcpy(grp_update_req, ureq, sizeof(struct nix_mcast_grp_update_req));
+
+ /* Send message to AF */
+ rc = otx2_sync_mbox_msg(&nic->mbox);
+ if (rc) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to update multicast group");
+ goto error;
+ }
+
+ mutex_unlock(&nic->mbox.lock);
+ req->op = NIX_RX_ACTIONOP_MCAST;
+ req->index = grp_index;
+ node->mcast_grp_idx = grp_index;
+ return 0;
+
+error:
+ mutex_unlock(&nic->mbox.lock);
+ return rc;
+}
+
static int otx2_tc_parse_actions(struct otx2_nic *nic,
struct flow_action *flow_action,
struct npc_install_flow_req *req,
struct flow_cls_offload *f,
struct otx2_tc_flow *node)
{
+ struct nix_mcast_grp_update_req dummy_grp_update_req = { 0 };
struct netlink_ext_ack *extack = f->common.extack;
+ bool pps = false, mcast = false;
struct flow_action_entry *act;
struct net_device *target;
struct otx2_nic *priv;
u32 burst, mark = 0;
u8 nr_police = 0;
- bool pps = false;
+ u8 num_intf = 1;
+ int err, i;
u64 rate;
- int err;
- int i;
if (!flow_action_has_entries(flow_action)) {
NL_SET_ERR_MSG_MOD(extack, "no tc actions specified");
@@ -442,11 +519,30 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
req->index = act->rx_queue;
break;
+ case FLOW_ACTION_MIRRED_INGRESS:
+ target = act->dev;
+ priv = netdev_priv(target);
+ dummy_grp_update_req.pcifunc[num_intf] = priv->pcifunc;
+ dummy_grp_update_req.channel[num_intf] = priv->hw.tx_chan_base;
+ dummy_grp_update_req.dest_type[num_intf] = NIX_RX_RSS;
+ dummy_grp_update_req.rq_rss_index[num_intf] = 0;
+ mcast = true;
+ num_intf++;
+ break;
+
default:
return -EOPNOTSUPP;
}
}
+ if (mcast) {
+ err = otx2_tc_update_mcast(nic, req, extack, node,
+ &dummy_grp_update_req,
+ num_intf);
+ if (err)
+ return err;
+ }
+
if (nr_police > 1) {
NL_SET_ERR_MSG_MOD(extack,
"rate limit police offload requires a single action");
@@ -541,6 +637,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
BIT(FLOW_DISSECTOR_KEY_IPSEC) |
BIT_ULL(FLOW_DISSECTOR_KEY_MPLS) |
+ BIT_ULL(FLOW_DISSECTOR_KEY_ICMP) |
BIT_ULL(FLOW_DISSECTOR_KEY_IP)))) {
netdev_info(nic->netdev, "unsupported flow used key 0x%llx",
dissector->used_keys);
@@ -591,6 +688,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
struct flow_match_control match;
+ u32 val;
flow_rule_match_control(rule, &match);
if (match.mask->flags & FLOW_DIS_FIRST_FRAG) {
@@ -599,12 +697,14 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
}
if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
+ val = match.key->flags & FLOW_DIS_IS_FRAGMENT;
if (ntohs(flow_spec->etype) == ETH_P_IP) {
- flow_spec->ip_flag = IPV4_FLAG_MORE;
+ flow_spec->ip_flag = val ? IPV4_FLAG_MORE : 0;
flow_mask->ip_flag = IPV4_FLAG_MORE;
req->features |= BIT_ULL(NPC_IPFRAG_IPV4);
} else if (ntohs(flow_spec->etype) == ETH_P_IPV6) {
- flow_spec->next_header = IPPROTO_FRAGMENT;
+ flow_spec->next_header = val ?
+ IPPROTO_FRAGMENT : 0;
flow_mask->next_header = 0xff;
req->features |= BIT_ULL(NPC_IPFRAG_IPV6);
} else {
@@ -815,6 +915,19 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
}
}
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP)) {
+ struct flow_match_icmp match;
+
+ flow_rule_match_icmp(rule, &match);
+
+ flow_spec->icmp_type = match.key->type;
+ flow_mask->icmp_type = match.mask->type;
+ req->features |= BIT_ULL(NPC_TYPE_ICMP);
+
+ flow_spec->icmp_code = match.key->code;
+ flow_mask->icmp_code = match.mask->code;
+ req->features |= BIT_ULL(NPC_CODE_ICMP);
+ }
return otx2_tc_parse_actions(nic, &rule->action, req, f, node);
}
@@ -1052,6 +1165,7 @@ static int otx2_tc_del_flow(struct otx2_nic *nic,
struct flow_cls_offload *tc_flow_cmd)
{
struct otx2_flow_config *flow_cfg = nic->flow_cfg;
+ struct nix_mcast_grp_destroy_req *grp_destroy_req;
struct otx2_tc_flow *flow_node;
int err;
@@ -1085,6 +1199,15 @@ static int otx2_tc_del_flow(struct otx2_nic *nic,
mutex_unlock(&nic->mbox.lock);
}
+ /* Remove the multicast/mirror related nodes */
+ if (flow_node->mcast_grp_idx != MCAST_INVALID_GRP) {
+ mutex_lock(&nic->mbox.lock);
+ grp_destroy_req = otx2_mbox_alloc_msg_nix_mcast_grp_destroy(&nic->mbox);
+ grp_destroy_req->mcast_grp_idx = flow_node->mcast_grp_idx;
+ otx2_sync_mbox_msg(&nic->mbox);
+ mutex_unlock(&nic->mbox.lock);
+ }
+
free_mcam_flow:
otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL);
@@ -1124,6 +1247,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
spin_lock_init(&new_node->lock);
new_node->cookie = tc_flow_cmd->cookie;
new_node->prio = tc_flow_cmd->common.prio;
+ new_node->mcast_grp_idx = MCAST_INVALID_GRP;
memset(&dummy, 0, sizeof(struct npc_install_flow_req));
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
index 1e77bbf5d2..1723e9912a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
@@ -382,6 +382,7 @@ static void otx2_qos_read_txschq_cfg_tl(struct otx2_qos_node *parent,
otx2_qos_read_txschq_cfg_tl(node, cfg);
cnt = cfg->static_node_pos[node->level];
cfg->schq_contig_list[node->level][cnt] = node->schq;
+ cfg->schq_index_used[node->level][cnt] = true;
cfg->schq_contig[node->level]++;
cfg->static_node_pos[node->level]++;
otx2_qos_read_txschq_cfg_schq(node, cfg);