RE: [PATCH net-next] net: mana: Add support for jumbo frame

From: Haiyang Zhang
Date: Mon Mar 20 2023 - 11:29:43 EST




> -----Original Message-----
> From: Yunsheng Lin <linyunsheng@xxxxxxxxxx>
> Sent: Monday, March 20, 2023 5:42 AM
> To: Haiyang Zhang <haiyangz@xxxxxxxxxxxxx>; linux-hyperv@xxxxxxxxxxxxxxx;
> netdev@xxxxxxxxxxxxxxx
> Cc: Dexuan Cui <decui@xxxxxxxxxxxxx>; KY Srinivasan <kys@xxxxxxxxxxxxx>;
> Paul Rosswurm <paulros@xxxxxxxxxxxxx>; olaf@xxxxxxxxx;
> vkuznets@xxxxxxxxxx; davem@xxxxxxxxxxxxx; wei.liu@xxxxxxxxxx;
> edumazet@xxxxxxxxxx; kuba@xxxxxxxxxx; pabeni@xxxxxxxxxx;
> leon@xxxxxxxxxx; Long Li <longli@xxxxxxxxxxxxx>;
> ssengar@xxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
> Subject: Re: [PATCH net-next] net: mana: Add support for jumbo frame
>
> On 2023/3/20 5:27, Haiyang Zhang wrote:
> > During probe, get the hardware allowed max MTU by querying the device
> > configuration. Users can select MTU up to the device limit. Also,
> > when XDP is in use, we currently limit the buffer size to one page.
> >
> > Updated RX data path to allocate and use RX queue DMA buffers with
> > proper size based on the MTU setting.
>
> The change in this patch seems better to splitted into more reviewable
> patchset. Perhaps refactor the RX queue DMA buffers allocation to handle
> different size first, then add support for the jumbo frame.

Will consider.

>
> >
> > Signed-off-by: Haiyang Zhang <haiyangz@xxxxxxxxxxxxx>
> > ---
> > .../net/ethernet/microsoft/mana/mana_bpf.c | 22 +-
> > drivers/net/ethernet/microsoft/mana/mana_en.c | 229 ++++++++++++----
> --
> > include/net/mana/gdma.h | 4 +
> > include/net/mana/mana.h | 18 +-
> > 4 files changed, 183 insertions(+), 90 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/microsoft/mana/mana_bpf.c
> b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
> > index 3caea631229c..23b1521c0df9 100644
> > --- a/drivers/net/ethernet/microsoft/mana/mana_bpf.c
> > +++ b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
> > @@ -133,12 +133,6 @@ u32 mana_run_xdp(struct net_device *ndev,
> struct mana_rxq *rxq,
> > return act;
> > }
> >
> > -static unsigned int mana_xdp_fraglen(unsigned int len)
> > -{
> > - return SKB_DATA_ALIGN(len) +
> > - SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
> > -}
> > -
> > struct bpf_prog *mana_xdp_get(struct mana_port_context *apc)
> > {
> > ASSERT_RTNL();
> > @@ -179,17 +173,18 @@ static int mana_xdp_set(struct net_device *ndev,
> struct bpf_prog *prog,
> > {
> > struct mana_port_context *apc = netdev_priv(ndev);
> > struct bpf_prog *old_prog;
> > - int buf_max;
> > + struct gdma_context *gc;
> > +
> > + gc = apc->ac->gdma_dev->gdma_context;
> >
> > old_prog = mana_xdp_get(apc);
> >
> > if (!old_prog && !prog)
> > return 0;
> >
> > - buf_max = XDP_PACKET_HEADROOM + mana_xdp_fraglen(ndev-
> >mtu + ETH_HLEN);
> > - if (prog && buf_max > PAGE_SIZE) {
> > - netdev_err(ndev, "XDP: mtu:%u too large, buf_max:%u\n",
> > - ndev->mtu, buf_max);
> > + if (prog && ndev->mtu > MANA_XDP_MTU_MAX) {
> > + netdev_err(ndev, "XDP: mtu:%u too large, mtu_max:%lu\n",
> > + ndev->mtu, MANA_XDP_MTU_MAX);
> > NL_SET_ERR_MSG_MOD(extack, "XDP: mtu too large");
> >
> > return -EOPNOTSUPP;
> > @@ -206,6 +201,11 @@ static int mana_xdp_set(struct net_device *ndev,
> struct bpf_prog *prog,
> > if (apc->port_is_up)
> > mana_chn_setxdp(apc, prog);
> >
> > + if (prog)
> > + ndev->max_mtu = MANA_XDP_MTU_MAX;
> > + else
> > + ndev->max_mtu = gc->adapter_mtu - ETH_HLEN;
> > +
> > return 0;
> > }
> >
> > diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c
> b/drivers/net/ethernet/microsoft/mana/mana_en.c
> > index 492474b4d8aa..07738b7e85f2 100644
> > --- a/drivers/net/ethernet/microsoft/mana/mana_en.c
> > +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
> > @@ -427,6 +427,34 @@ static u16 mana_select_queue(struct net_device
> *ndev, struct sk_buff *skb,
> > return txq;
> > }
> >
> > +static int mana_change_mtu(struct net_device *ndev, int new_mtu)
> > +{
> > + unsigned int old_mtu = ndev->mtu;
> > + int err, err2;
> > +
> > + err = mana_detach(ndev, false);
> > + if (err) {
> > + netdev_err(ndev, "mana_detach failed: %d\n", err);
> > + return err;
> > + }
> > +
> > + ndev->mtu = new_mtu;
> > +
> > + err = mana_attach(ndev);
> > + if (!err)
> > + return 0;
> > +
> > + netdev_err(ndev, "mana_attach failed: %d\n", err);
> > +
> > + /* Try to roll it back to the old configuration. */
> > + ndev->mtu = old_mtu;
> > + err2 = mana_attach(ndev);
> > + if (err2)
> > + netdev_err(ndev, "mana re-attach failed: %d\n", err2);
> > +
> > + return err;
> > +}
> > +
> > static const struct net_device_ops mana_devops = {
> > .ndo_open = mana_open,
> > .ndo_stop = mana_close,
> > @@ -436,6 +464,7 @@ static const struct net_device_ops mana_devops = {
> > .ndo_get_stats64 = mana_get_stats64,
> > .ndo_bpf = mana_bpf,
> > .ndo_xdp_xmit = mana_xdp_xmit,
> > + .ndo_change_mtu = mana_change_mtu,
> > };
> >
> > static void mana_cleanup_port_context(struct mana_port_context *apc)
> > @@ -625,6 +654,9 @@ static int mana_query_device_cfg(struct
> mana_context *ac, u32 proto_major_ver,
> >
> > mana_gd_init_req_hdr(&req.hdr, MANA_QUERY_DEV_CONFIG,
> > sizeof(req), sizeof(resp));
> > +
> > + req.hdr.resp.msg_version = GDMA_MESSAGE_V2;
>
> hdr->req.msg_version and hdr->resp.msg_version are both set to
> GDMA_MESSAGE_V1 in mana_gd_init_req_hdr(), is there any reason
> why hdr->req.msg_version is not set to GDMA_MESSAGE_V2?

The request version is still V1 in our hardware.

> Does initializing req.hdr.resp.msg_version to GDMA_MESSAGE_V2
> in mana_gd_init_req_hdr() without reset it to GDMA_MESSAGE_V2
> in mana_query_device_cfg() affect other user?

Yes, other users still need V1. So only this message response version is set
to V2.

>
>
> > +
> > req.proto_major_ver = proto_major_ver;
> > req.proto_minor_ver = proto_minor_ver;
> > req.proto_micro_ver = proto_micro_ver;
> > @@ -647,6 +679,11 @@ static int mana_query_device_cfg(struct
> mana_context *ac, u32 proto_major_ver,
> >
> > *max_num_vports = resp.max_num_vports;
> >
> > + if (resp.hdr.response.msg_version == GDMA_MESSAGE_V2)
>
> It seems the driver is setting resp.hdr.response.msg_version to
> GDMA_MESSAGE_V2 above, and do the checking here. Does older
> firmware reset the resp.hdr.response.msg_version to GDMA_MESSAGE_V1
> in order to enable compatibility between firmware and driver?

Yes older firmware still using V1.

>
> > + gc->adapter_mtu = resp.adapter_mtu;
> > + else
> > + gc->adapter_mtu = ETH_FRAME_LEN;
> > +
> > return 0;
> > }
> >
> > @@ -1185,10 +1222,10 @@ static void mana_post_pkt_rxq(struct
> mana_rxq *rxq)
> > WARN_ON_ONCE(recv_buf_oob->wqe_inf.wqe_size_in_bu != 1);
> > }
> >
> > -static struct sk_buff *mana_build_skb(void *buf_va, uint pkt_len,
> > - struct xdp_buff *xdp)
> > +static struct sk_buff *mana_build_skb(struct mana_rxq *rxq, void *buf_va,
> > + uint pkt_len, struct xdp_buff *xdp)
> > {
> > - struct sk_buff *skb = build_skb(buf_va, PAGE_SIZE);
> > + struct sk_buff *skb = napi_build_skb(buf_va, rxq->alloc_size);
>
> Changing build_skb() to napi_build_skb() seems like an optimization
> unrelated to jumbo frame support, seems like another patch to do that?
Will do. Thanks.

- Haiyang