> Subject: [PATCH V2,net-next, 1/2] net: mana: Add support for coalesced RX > packets on CQE > > From: Haiyang Zhang <[email protected]> > > Our NIC can have up to 4 RX packets on 1 CQE. To support this feature, check > and process the type CQE_RX_COALESCED_4. The default setting is disabled, > to avoid possible regression on latency. > > And add ethtool handler to switch this feature. To turn it on, run: > ethtool -C <nic> rx-frames 4 > To turn it off: > ethtool -C <nic> rx-frames 1 > > Signed-off-by: Haiyang Zhang <[email protected]>
Reviewed-by: Long Li <[email protected]> > --- > V2: > Updated extack msg, as recommended by Jakub Kicinski, and Simon Horman. > > --- > drivers/net/ethernet/microsoft/mana/mana_en.c | 32 ++++++----- > .../ethernet/microsoft/mana/mana_ethtool.c | 55 +++++++++++++++++++ > include/net/mana/mana.h | 2 + > 3 files changed, 74 insertions(+), 15 deletions(-) > > diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c > b/drivers/net/ethernet/microsoft/mana/mana_en.c > index 1ad154f9db1a..a46a1adf83bc 100644 > --- a/drivers/net/ethernet/microsoft/mana/mana_en.c > +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c > @@ -1330,7 +1330,7 @@ static int mana_cfg_vport_steering(struct > mana_port_context *apc, > req->update_hashkey = update_key; > req->update_indir_tab = update_tab; > req->default_rxobj = apc->default_rxobj; > - req->cqe_coalescing_enable = 0; > + req->cqe_coalescing_enable = apc->cqe_coalescing_enable; > > if (update_key) > memcpy(&req->hashkey, apc->hashkey, > MANA_HASH_KEY_SIZE); @@ -1864,11 +1864,12 @@ static struct sk_buff > *mana_build_skb(struct mana_rxq *rxq, void *buf_va, } > > static void mana_rx_skb(void *buf_va, bool from_pool, > - struct mana_rxcomp_oob *cqe, struct mana_rxq *rxq) > + struct mana_rxcomp_oob *cqe, struct mana_rxq *rxq, > + int i) > { > struct mana_stats_rx *rx_stats = &rxq->stats; > struct net_device *ndev = rxq->ndev; > - uint pkt_len = cqe->ppi[0].pkt_len; > + uint pkt_len = cqe->ppi[i].pkt_len; > u16 rxq_idx = rxq->rxq_idx; > struct napi_struct *napi; > struct xdp_buff xdp = {}; > @@ -1912,7 +1913,7 @@ static void mana_rx_skb(void *buf_va, bool > from_pool, > } > > if (cqe->rx_hashtype != 0 && (ndev->features & NETIF_F_RXHASH)) { > - hash_value = cqe->ppi[0].pkt_hash; > + hash_value = cqe->ppi[i].pkt_hash; > > if (cqe->rx_hashtype & MANA_HASH_L4) > skb_set_hash(skb, hash_value, PKT_HASH_TYPE_L4); > @@ -2047,9 +2048,11 @@ static void mana_process_rx_cqe(struct > mana_rxq *rxq, struct mana_cq *cq, > struct mana_recv_buf_oob *rxbuf_oob; > struct mana_port_context *apc; > struct device *dev = gc->dev; > + bool coalesced = false; > void *old_buf = NULL; > u32 curr, pktlen; > bool old_fp; > + int i = 0; > > apc = netdev_priv(ndev); > > @@ -2064,9 +2067,8 @@ static void mana_process_rx_cqe(struct mana_rxq > *rxq, struct mana_cq *cq, > goto drop; > > case CQE_RX_COALESCED_4: > - netdev_err(ndev, "RX coalescing is unsupported\n"); > - apc->eth_stats.rx_coalesced_err++; > - return; > + coalesced = true; > + break; > > case CQE_RX_OBJECT_FENCE: > complete(&rxq->fence_event); > @@ -2079,14 +2081,10 @@ static void mana_process_rx_cqe(struct > mana_rxq *rxq, struct mana_cq *cq, > return; > } > > - pktlen = oob->ppi[0].pkt_len; > - > - if (pktlen == 0) { > - /* data packets should never have packetlength of zero */ > - netdev_err(ndev, "RX pkt len=0, rq=%u, cq=%u, > rxobj=0x%llx\n", > - rxq->gdma_id, cq->gdma_id, rxq->rxobj); > +nextpkt: > + pktlen = oob->ppi[i].pkt_len; > + if (pktlen == 0) > return; > - } > > curr = rxq->buf_index; > rxbuf_oob = &rxq->rx_oobs[curr]; > @@ -2097,12 +2095,15 @@ static void mana_process_rx_cqe(struct > mana_rxq *rxq, struct mana_cq *cq, > /* Unsuccessful refill will have old_buf == NULL. > * In this case, mana_rx_skb() will drop the packet. > */ > - mana_rx_skb(old_buf, old_fp, oob, rxq); > + mana_rx_skb(old_buf, old_fp, oob, rxq, i); > > drop: > mana_move_wq_tail(rxq->gdma_rq, rxbuf_oob- > >wqe_inf.wqe_size_in_bu); > > mana_post_pkt_rxq(rxq); > + > + if (coalesced && (++i < MANA_RXCOMP_OOB_NUM_PPI)) > + goto nextpkt; > } > > static void mana_poll_rx_cq(struct mana_cq *cq) @@ -3276,6 +3277,7 @@ > static int mana_probe_port(struct mana_context *ac, int port_idx, > apc->port_handle = INVALID_MANA_HANDLE; > apc->pf_filter_handle = INVALID_MANA_HANDLE; > apc->port_idx = port_idx; > + apc->cqe_coalescing_enable = 0; > > mutex_init(&apc->vport_mutex); > apc->vport_use_count = 0; > diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c > b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c > index 0e2f4343ac67..b2b9bfb50396 100644 > --- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c > +++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c > @@ -397,6 +397,58 @@ static void mana_get_channels(struct net_device > *ndev, > channel->combined_count = apc->num_queues; } > > +static int mana_get_coalesce(struct net_device *ndev, > + struct ethtool_coalesce *ec, > + struct kernel_ethtool_coalesce *kernel_coal, > + struct netlink_ext_ack *extack) { > + struct mana_port_context *apc = netdev_priv(ndev); > + > + ec->rx_max_coalesced_frames = > + apc->cqe_coalescing_enable ? > MANA_RXCOMP_OOB_NUM_PPI : 1; > + > + return 0; > +} > + > +static int mana_set_coalesce(struct net_device *ndev, > + struct ethtool_coalesce *ec, > + struct kernel_ethtool_coalesce *kernel_coal, > + struct netlink_ext_ack *extack) { > + struct mana_port_context *apc = netdev_priv(ndev); > + u8 saved_cqe_coalescing_enable; > + int err; > + > + if (ec->rx_max_coalesced_frames != 1 && > + ec->rx_max_coalesced_frames != MANA_RXCOMP_OOB_NUM_PPI) > { > + NL_SET_ERR_MSG_FMT(extack, > + "rx-frames must be 1 or %u, got %u", > + MANA_RXCOMP_OOB_NUM_PPI, > + ec->rx_max_coalesced_frames); > + return -EINVAL; > + } > + > + saved_cqe_coalescing_enable = apc->cqe_coalescing_enable; > + apc->cqe_coalescing_enable = > + ec->rx_max_coalesced_frames == > MANA_RXCOMP_OOB_NUM_PPI; > + > + if (!apc->port_is_up) > + return 0; > + > + err = mana_config_rss(apc, TRI_STATE_TRUE, false, false); > + > + if (err) { > + netdev_err(ndev, "Set rx-frames to %u failed:%d\n", > + ec->rx_max_coalesced_frames, err); > + NL_SET_ERR_MSG_FMT(extack, "Set rx-frames to %u failed", > + ec->rx_max_coalesced_frames); > + > + apc->cqe_coalescing_enable = saved_cqe_coalescing_enable; > + } > + > + return err; > +} > + > static int mana_set_channels(struct net_device *ndev, > struct ethtool_channels *channels) { @@ -517,6 > +569,7 @@ static int mana_get_link_ksettings(struct net_device *ndev, } > > const struct ethtool_ops mana_ethtool_ops = { > + .supported_coalesce_params = > ETHTOOL_COALESCE_RX_MAX_FRAMES, > .get_ethtool_stats = mana_get_ethtool_stats, > .get_sset_count = mana_get_sset_count, > .get_strings = mana_get_strings, > @@ -527,6 +580,8 @@ const struct ethtool_ops mana_ethtool_ops = { > .set_rxfh = mana_set_rxfh, > .get_channels = mana_get_channels, > .set_channels = mana_set_channels, > + .get_coalesce = mana_get_coalesce, > + .set_coalesce = mana_set_coalesce, > .get_ringparam = mana_get_ringparam, > .set_ringparam = mana_set_ringparam, > .get_link_ksettings = mana_get_link_ksettings, > diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h index > d7e089c6b694..51d26ebeff6c 100644 > --- a/include/net/mana/mana.h > +++ b/include/net/mana/mana.h > @@ -556,6 +556,8 @@ struct mana_port_context { > bool port_is_up; > bool port_st_save; /* Saved port state */ > > + u8 cqe_coalescing_enable; > + > struct mana_ethtool_stats eth_stats; > > struct mana_ethtool_phy_stats phy_stats; > -- > 2.34.1
