mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge branch 'gve-optimize-and-enable-hw-gro-for-dqo'
Ankit Garg says: ==================== gve: optimize and enable HW GRO for DQO The DQO device has always performed HW GRO, not LRO. This series updates the feature bit and modifies the RX path to enhance support. It sets gso_segs correctly so the software stack can continue coalescing, and pulls network headers into the skb linear space to avoid multiple small memory copies when header-split is disabled. We also enable HW GRO by default on supported devices. ==================== Link: https://patch.msgid.link/20260303195549.2679070-1-joshwash@google.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -791,7 +791,7 @@ static void gve_adminq_get_create_rx_queue_cmd(struct gve_priv *priv,
|
||||
cmd->create_rx_queue.rx_buff_ring_size =
|
||||
cpu_to_be16(priv->rx_desc_cnt);
|
||||
cmd->create_rx_queue.enable_rsc =
|
||||
!!(priv->dev->features & NETIF_F_LRO);
|
||||
!!(priv->dev->features & NETIF_F_GRO_HW);
|
||||
if (priv->header_split_enabled)
|
||||
cmd->create_rx_queue.header_buffer_size =
|
||||
cpu_to_be16(priv->header_buf_size);
|
||||
@@ -1117,9 +1117,11 @@ int gve_adminq_describe_device(struct gve_priv *priv)
|
||||
|
||||
gve_set_default_rss_sizes(priv);
|
||||
|
||||
/* DQO supports LRO. */
|
||||
if (!gve_is_gqi(priv))
|
||||
priv->dev->hw_features |= NETIF_F_LRO;
|
||||
/* DQO supports HW-GRO. */
|
||||
if (gve_is_dqo(priv)) {
|
||||
priv->dev->hw_features |= NETIF_F_GRO_HW;
|
||||
priv->dev->features |= NETIF_F_GRO_HW;
|
||||
}
|
||||
|
||||
priv->max_registered_pages =
|
||||
be64_to_cpu(descriptor->max_registered_pages);
|
||||
|
||||
@@ -1758,9 +1758,9 @@ static int gve_verify_xdp_configuration(struct net_device *dev,
|
||||
struct gve_priv *priv = netdev_priv(dev);
|
||||
u16 max_xdp_mtu;
|
||||
|
||||
if (dev->features & NETIF_F_LRO) {
|
||||
if (dev->features & NETIF_F_GRO_HW) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"XDP is not supported when LRO is on.");
|
||||
"XDP is not supported when HW-GRO is on.");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@@ -2177,12 +2177,13 @@ static int gve_set_features(struct net_device *netdev,
|
||||
|
||||
gve_get_curr_alloc_cfgs(priv, &tx_alloc_cfg, &rx_alloc_cfg);
|
||||
|
||||
if ((netdev->features & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
|
||||
netdev->features ^= NETIF_F_LRO;
|
||||
if (priv->xdp_prog && (netdev->features & NETIF_F_LRO)) {
|
||||
if ((netdev->features & NETIF_F_GRO_HW) !=
|
||||
(features & NETIF_F_GRO_HW)) {
|
||||
netdev->features ^= NETIF_F_GRO_HW;
|
||||
if (priv->xdp_prog && (netdev->features & NETIF_F_GRO_HW)) {
|
||||
netdev_warn(netdev,
|
||||
"XDP is not supported when LRO is on.\n");
|
||||
err = -EOPNOTSUPP;
|
||||
"HW-GRO is not supported when XDP is on.");
|
||||
err = -EOPNOTSUPP;
|
||||
goto revert_features;
|
||||
}
|
||||
if (netif_running(netdev)) {
|
||||
|
||||
@@ -942,11 +942,18 @@ static int gve_rx_complete_rsc(struct sk_buff *skb,
|
||||
struct gve_ptype ptype)
|
||||
{
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
int rsc_segments, rsc_seg_len, hdr_len;
|
||||
skb_frag_t *frag;
|
||||
void *va;
|
||||
|
||||
/* Only TCP is supported right now. */
|
||||
/* HW-GRO only coalesces TCP. */
|
||||
if (ptype.l4_type != GVE_L4_TYPE_TCP)
|
||||
return -EINVAL;
|
||||
|
||||
rsc_seg_len = le16_to_cpu(desc->rsc_seg_len);
|
||||
if (!rsc_seg_len)
|
||||
return 0;
|
||||
|
||||
switch (ptype.l3_type) {
|
||||
case GVE_L3_TYPE_IPV4:
|
||||
shinfo->gso_type = SKB_GSO_TCPV4;
|
||||
@@ -958,7 +965,31 @@ static int gve_rx_complete_rsc(struct sk_buff *skb,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
shinfo->gso_size = le16_to_cpu(desc->rsc_seg_len);
|
||||
if (skb_headlen(skb)) {
|
||||
/* With header-split, payload is in the non-linear part */
|
||||
rsc_segments = DIV_ROUND_UP(skb->data_len, rsc_seg_len);
|
||||
} else {
|
||||
/* HW-GRO packets are guaranteed to have complete TCP/IP
|
||||
* headers in frag[0] when header-split is not enabled.
|
||||
*/
|
||||
frag = &skb_shinfo(skb)->frags[0];
|
||||
va = skb_frag_address(frag);
|
||||
hdr_len =
|
||||
eth_get_headlen(skb->dev, va, skb_frag_size(frag));
|
||||
rsc_segments = DIV_ROUND_UP(skb->len - hdr_len, rsc_seg_len);
|
||||
skb_copy_to_linear_data(skb, va, hdr_len);
|
||||
skb_frag_size_sub(frag, hdr_len);
|
||||
/* Verify we didn't empty the fragment completely as that could
|
||||
* otherwise lead to page leaks.
|
||||
*/
|
||||
DEBUG_NET_WARN_ON_ONCE(!skb_frag_size(frag));
|
||||
skb_frag_off_add(frag, hdr_len);
|
||||
skb->data_len -= hdr_len;
|
||||
skb->tail += hdr_len;
|
||||
}
|
||||
shinfo->gso_size = rsc_seg_len;
|
||||
shinfo->gso_segs = rsc_segments;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -991,7 +1022,7 @@ static int gve_rx_complete_skb(struct gve_rx_ring *rx, struct napi_struct *napi,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (skb_headlen(rx->ctx.skb_head) == 0)
|
||||
if (rx->ctx.skb_head == napi->skb)
|
||||
napi_gro_frags(napi);
|
||||
else
|
||||
napi_gro_receive(napi, rx->ctx.skb_head);
|
||||
|
||||
Reference in New Issue
Block a user