> 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


Reply via email to