diff options
Diffstat (limited to 'drivers/net/ethernet/marvell/octeontx2/nic')
5 files changed, 199 insertions, 61 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c index bfddbff7bcdf..28fb643d2917 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c @@ -399,9 +399,10 @@ static int otx2_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc) static int otx2_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc) { struct otx2_nic *pfvf = netdev_priv(dev); + u8 old_pfc_en; int err; - /* Save PFC configuration to interface */ + old_pfc_en = pfvf->pfc_en; pfvf->pfc_en = pfc->pfc_en; if (pfvf->hw.tx_queues >= NIX_PF_PFC_PRIO_MAX) @@ -411,13 +412,17 @@ static int otx2_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc) * supported by the tx queue configuration */ err = otx2_check_pfc_config(pfvf); - if (err) + if (err) { + pfvf->pfc_en = old_pfc_en; return err; + } process_pfc: err = otx2_config_priority_flow_ctrl(pfvf); - if (err) + if (err) { + pfvf->pfc_en = old_pfc_en; return err; + } /* Request Per channel Bpids */ if (pfc->pfc_en) @@ -425,6 +430,12 @@ process_pfc: err = otx2_pfc_txschq_update(pfvf); if (err) { + if (pfc->pfc_en) + otx2_nix_config_bp(pfvf, false); + + otx2_pfc_txschq_stop(pfvf); + pfvf->pfc_en = old_pfc_en; + otx2_config_priority_flow_ctrl(pfvf); dev_err(pfvf->dev, "%s failed to update TX schedulers\n", __func__); return err; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c index 53f6258a973c..7f786de61014 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c @@ -314,7 +314,6 @@ static int otx2_set_channels(struct net_device *dev, pfvf->hw.tx_queues = channel->tx_count; if (pfvf->xdp_prog) pfvf->hw.xdp_queues = channel->rx_count; - pfvf->hw.non_qos_queues = pfvf->hw.tx_queues + pfvf->hw.xdp_queues; if (if_up) err = dev->netdev_ops->ndo_open(dev); @@ -835,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; @@ -859,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; @@ -914,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); @@ -1318,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, @@ -1340,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, @@ -1441,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, @@ -1459,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 0c17ebdda148..e5fe67e73865 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -1650,6 +1650,21 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) mutex_unlock(&mbox->lock); } +static bool otx2_promisc_use_mce_list(struct otx2_nic *pfvf) +{ + int vf; + + /* The AF driver will determine whether to allow the VF netdev or not */ + if (is_otx2_vf(pfvf->pcifunc)) + return true; + + /* check if there are any trusted VFs associated with the PF netdev */ + for (vf = 0; vf < pci_num_vf(pfvf->pdev); vf++) + if (pfvf->vf_configs[vf].trusted) + return true; + return false; +} + static void otx2_do_set_rx_mode(struct otx2_nic *pf) { struct net_device *netdev = pf->netdev; @@ -1682,7 +1697,8 @@ static void otx2_do_set_rx_mode(struct otx2_nic *pf) if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST)) req->mode |= NIX_RX_MODE_ALLMULTI; - req->mode |= NIX_RX_MODE_USE_MCE; + if (otx2_promisc_use_mce_list(pf)) + req->mode |= NIX_RX_MODE_USE_MCE; otx2_sync_mbox_msg(&pf->mbox); mutex_unlock(&pf->mbox.lock); @@ -1728,6 +1744,7 @@ int otx2_open(struct net_device *netdev) /* RQ and SQs are mapped to different CQs, * so find out max CQ IRQs (i.e CINTs) needed. */ + pf->hw.non_qos_queues = pf->hw.tx_queues + pf->hw.xdp_queues; pf->hw.cint_cnt = max3(pf->hw.rx_queues, pf->hw.tx_queues, pf->hw.tc_tx_queues); @@ -2627,8 +2644,6 @@ static int otx2_xdp_setup(struct otx2_nic *pf, struct bpf_prog *prog) xdp_features_clear_redirect_target(dev); } - pf->hw.non_qos_queues += pf->hw.xdp_queues; - if (if_up) otx2_open(pf->netdev); @@ -2691,11 +2706,14 @@ static int otx2_ndo_set_vf_trust(struct net_device *netdev, int vf, pf->vf_configs[vf].trusted = enable; rc = otx2_set_vf_permissions(pf, vf, OTX2_TRUSTED_VF); - if (rc) + if (rc) { pf->vf_configs[vf].trusted = !enable; - else + } else { netdev_info(pf->netdev, "VF %d is %strusted\n", vf, enable ? "" : "not "); + otx2_set_rx_mode(netdev); + } + return rc; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index db1e0e0e812d..4fd44b6eecea 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); @@ -815,6 +912,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 +1162,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 +1196,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 +1244,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/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c index 4d519ea833b2..f828d32737af 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c @@ -1403,7 +1403,7 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, bool *need_xdp_flush) { - unsigned char *hard_start, *data; + unsigned char *hard_start; int qidx = cq->cq_idx; struct xdp_buff xdp; struct page *page; @@ -1417,9 +1417,8 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf, xdp_init_buff(&xdp, pfvf->rbsize, &cq->xdp_rxq); - data = (unsigned char *)phys_to_virt(pa); - hard_start = page_address(page); - xdp_prepare_buff(&xdp, hard_start, data - hard_start, + hard_start = (unsigned char *)phys_to_virt(pa); + xdp_prepare_buff(&xdp, hard_start, OTX2_HEAD_ROOM, cqe->sg.seg_size, false); act = bpf_prog_run_xdp(prog, &xdp); |