Commit e9c5a106 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-NETIF_F_GRO_HW'

Michael Chan says:

====================
Introduce NETIF_F_GRO_HW

Introduce NETIF_F_GRO_HW feature flag and convert drivers that support
hardware GRO to use the new flag.

v5:
- Documentation changes requested by Alexander Duyck.
- bnx2x changes requested by Manish Chopra to enable LRO by default, and
disable GRO_HW if disable_tpa module parameter is set.

v4:
- more changes requested by Alexander Duyck:
- check GRO_HW/GRO dependency in drivers's ndo_fix_features().
- Reverse the order of RXCSUM and GRO_HW dependency check in
netdev_fix_features().
- No propagation in netdev_disable_gro_hw().

v3:
- Let driver's ndo_fix_features() disable NETIF_F_LRO when NETIF_F_GRO_HW
is set instead of doing it in common netdev_fix_features().

v2:
- NETIF_F_GRO_HW flag propagation between upper and lower devices not
required (see patch 1).
- NETIF_F_GRO_HW depends on NETIF_F_GRO and NETIF_F_RXCSUM.
- Add dev_disable_gro_hw() to disable GRO_HW for generic XDP.
- Use ndo_fix_features() on all 3 drivers to drop GRO_HW when it is not
supported
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 398b841e 18c602de
...@@ -163,3 +163,12 @@ This requests that the NIC receive all possible frames, including errored ...@@ -163,3 +163,12 @@ This requests that the NIC receive all possible frames, including errored
frames (such as bad FCS, etc). This can be helpful when sniffing a link with frames (such as bad FCS, etc). This can be helpful when sniffing a link with
bad packets on it. Some NICs may receive more packets if also put into normal bad packets on it. Some NICs may receive more packets if also put into normal
PROMISC mode. PROMISC mode.
* rx-gro-hw
This requests that the NIC enables Hardware GRO (generic receive offload).
Hardware GRO is basically the exact reverse of TSO, and is generally
stricter than Hardware LRO. A packet stream merged by Hardware GRO must
be re-segmentable by GSO or TSO back to the exact original packet stream.
Hardware GRO is dependent on RXCSUM since every packet successfully merged
by hardware must also have the checksum verified by hardware.
...@@ -2482,8 +2482,7 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index) ...@@ -2482,8 +2482,7 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
*/ */
if (bp->dev->features & NETIF_F_LRO) if (bp->dev->features & NETIF_F_LRO)
fp->mode = TPA_MODE_LRO; fp->mode = TPA_MODE_LRO;
else if (bp->dev->features & NETIF_F_GRO && else if (bp->dev->features & NETIF_F_GRO_HW)
bnx2x_mtu_allows_gro(bp->dev->mtu))
fp->mode = TPA_MODE_GRO; fp->mode = TPA_MODE_GRO;
else else
fp->mode = TPA_MODE_DISABLED; fp->mode = TPA_MODE_DISABLED;
...@@ -4874,6 +4873,9 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu) ...@@ -4874,6 +4873,9 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
*/ */
dev->mtu = new_mtu; dev->mtu = new_mtu;
if (!bnx2x_mtu_allows_gro(new_mtu))
dev->features &= ~NETIF_F_GRO_HW;
if (IS_PF(bp) && SHMEM2_HAS(bp, curr_cfg)) if (IS_PF(bp) && SHMEM2_HAS(bp, curr_cfg))
SHMEM2_WR(bp, curr_cfg, CURR_CFG_MET_OS); SHMEM2_WR(bp, curr_cfg, CURR_CFG_MET_OS);
...@@ -4903,10 +4905,13 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev, ...@@ -4903,10 +4905,13 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
} }
/* TPA requires Rx CSUM offloading */ /* TPA requires Rx CSUM offloading */
if (!(features & NETIF_F_RXCSUM)) { if (!(features & NETIF_F_RXCSUM))
features &= ~NETIF_F_LRO;
if (!(features & NETIF_F_GRO) || !bnx2x_mtu_allows_gro(dev->mtu))
features &= ~NETIF_F_GRO_HW;
if (features & NETIF_F_GRO_HW)
features &= ~NETIF_F_LRO; features &= ~NETIF_F_LRO;
features &= ~NETIF_F_GRO;
}
return features; return features;
} }
...@@ -4933,12 +4938,7 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features) ...@@ -4933,12 +4938,7 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
} }
} }
/* if GRO is changed while LRO is enabled, don't force a reload */ /* Don't care about GRO changes */
if ((changes & NETIF_F_GRO) && (features & NETIF_F_LRO))
changes &= ~NETIF_F_GRO;
/* if GRO is changed while HW TPA is off, don't force a reload */
if ((changes & NETIF_F_GRO) && bp->disable_tpa)
changes &= ~NETIF_F_GRO; changes &= ~NETIF_F_GRO;
if (changes) if (changes)
......
...@@ -12400,8 +12400,8 @@ static int bnx2x_init_bp(struct bnx2x *bp) ...@@ -12400,8 +12400,8 @@ static int bnx2x_init_bp(struct bnx2x *bp)
/* Set TPA flags */ /* Set TPA flags */
if (bp->disable_tpa) { if (bp->disable_tpa) {
bp->dev->hw_features &= ~NETIF_F_LRO; bp->dev->hw_features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
bp->dev->features &= ~NETIF_F_LRO; bp->dev->features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
} }
if (CHIP_IS_E1(bp)) if (CHIP_IS_E1(bp))
...@@ -13273,7 +13273,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, ...@@ -13273,7 +13273,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO | NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO | NETIF_F_GRO_HW |
NETIF_F_RXHASH | NETIF_F_HW_VLAN_CTAG_TX; NETIF_F_RXHASH | NETIF_F_HW_VLAN_CTAG_TX;
if (!chip_is_e1x) { if (!chip_is_e1x) {
dev->hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_GRE_CSUM | dev->hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_GRE_CSUM |
...@@ -13309,6 +13309,8 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, ...@@ -13309,6 +13309,8 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX; dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX;
dev->features |= NETIF_F_HIGHDMA; dev->features |= NETIF_F_HIGHDMA;
if (dev->features & NETIF_F_LRO)
dev->features &= ~NETIF_F_GRO_HW;
/* Add Loopback capability to the device */ /* Add Loopback capability to the device */
dev->hw_features |= NETIF_F_LOOPBACK; dev->hw_features |= NETIF_F_LOOPBACK;
......
...@@ -2755,7 +2755,7 @@ void bnxt_set_tpa_flags(struct bnxt *bp) ...@@ -2755,7 +2755,7 @@ void bnxt_set_tpa_flags(struct bnxt *bp)
return; return;
if (bp->dev->features & NETIF_F_LRO) if (bp->dev->features & NETIF_F_LRO)
bp->flags |= BNXT_FLAG_LRO; bp->flags |= BNXT_FLAG_LRO;
if (bp->dev->features & NETIF_F_GRO) else if (bp->dev->features & NETIF_F_GRO_HW)
bp->flags |= BNXT_FLAG_GRO; bp->flags |= BNXT_FLAG_GRO;
} }
...@@ -2843,10 +2843,10 @@ int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode) ...@@ -2843,10 +2843,10 @@ int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU); min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU);
bp->flags &= ~BNXT_FLAG_AGG_RINGS; bp->flags &= ~BNXT_FLAG_AGG_RINGS;
bp->flags |= BNXT_FLAG_NO_AGG_RINGS | BNXT_FLAG_RX_PAGE_MODE; bp->flags |= BNXT_FLAG_NO_AGG_RINGS | BNXT_FLAG_RX_PAGE_MODE;
bp->dev->hw_features &= ~NETIF_F_LRO;
bp->dev->features &= ~NETIF_F_LRO;
bp->rx_dir = DMA_BIDIRECTIONAL; bp->rx_dir = DMA_BIDIRECTIONAL;
bp->rx_skb_func = bnxt_rx_page_skb; bp->rx_skb_func = bnxt_rx_page_skb;
/* Disable LRO or GRO_HW */
netdev_update_features(bp->dev);
} else { } else {
bp->dev->max_mtu = bp->max_mtu; bp->dev->max_mtu = bp->max_mtu;
bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE; bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE;
...@@ -6788,6 +6788,15 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev, ...@@ -6788,6 +6788,15 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp)) if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp))
features &= ~NETIF_F_NTUPLE; features &= ~NETIF_F_NTUPLE;
if (bp->flags & BNXT_FLAG_NO_AGG_RINGS)
features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
if (!(features & NETIF_F_GRO))
features &= ~NETIF_F_GRO_HW;
if (features & NETIF_F_GRO_HW)
features &= ~NETIF_F_LRO;
/* Both CTAG and STAG VLAN accelaration on the RX side have to be /* Both CTAG and STAG VLAN accelaration on the RX side have to be
* turned on or off together. * turned on or off together.
*/ */
...@@ -6821,9 +6830,9 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features) ...@@ -6821,9 +6830,9 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
bool update_tpa = false; bool update_tpa = false;
flags &= ~BNXT_FLAG_ALL_CONFIG_FEATS; flags &= ~BNXT_FLAG_ALL_CONFIG_FEATS;
if ((features & NETIF_F_GRO) && !BNXT_CHIP_TYPE_NITRO_A0(bp)) if (features & NETIF_F_GRO_HW)
flags |= BNXT_FLAG_GRO; flags |= BNXT_FLAG_GRO;
if (features & NETIF_F_LRO) else if (features & NETIF_F_LRO)
flags |= BNXT_FLAG_LRO; flags |= BNXT_FLAG_LRO;
if (bp->flags & BNXT_FLAG_NO_AGG_RINGS) if (bp->flags & BNXT_FLAG_NO_AGG_RINGS)
...@@ -7924,8 +7933,8 @@ static int bnxt_get_dflt_rings(struct bnxt *bp, int *max_rx, int *max_tx, ...@@ -7924,8 +7933,8 @@ static int bnxt_get_dflt_rings(struct bnxt *bp, int *max_rx, int *max_tx,
if (rc) if (rc)
return rc; return rc;
bp->flags |= BNXT_FLAG_NO_AGG_RINGS; bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
bp->dev->hw_features &= ~NETIF_F_LRO; bp->dev->hw_features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
bp->dev->features &= ~NETIF_F_LRO; bp->dev->features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
bnxt_set_ring_params(bp); bnxt_set_ring_params(bp);
} }
...@@ -8108,7 +8117,11 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -8108,7 +8117,11 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->vlan_features = dev->hw_features | NETIF_F_HIGHDMA; dev->vlan_features = dev->hw_features | NETIF_F_HIGHDMA;
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX | dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX; NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX;
if (!BNXT_CHIP_TYPE_NITRO_A0(bp))
dev->hw_features |= NETIF_F_GRO_HW;
dev->features |= dev->hw_features | NETIF_F_HIGHDMA; dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
if (dev->features & NETIF_F_GRO_HW)
dev->features &= ~NETIF_F_LRO;
dev->priv_flags |= IFF_UNICAST_FLT; dev->priv_flags |= IFF_UNICAST_FLT;
#ifdef CONFIG_BNXT_SRIOV #ifdef CONFIG_BNXT_SRIOV
......
...@@ -494,6 +494,8 @@ int qede_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid); ...@@ -494,6 +494,8 @@ int qede_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid);
void qede_vlan_mark_nonconfigured(struct qede_dev *edev); void qede_vlan_mark_nonconfigured(struct qede_dev *edev);
int qede_configure_vlan_filters(struct qede_dev *edev); int qede_configure_vlan_filters(struct qede_dev *edev);
netdev_features_t qede_fix_features(struct net_device *dev,
netdev_features_t features);
int qede_set_features(struct net_device *dev, netdev_features_t features); int qede_set_features(struct net_device *dev, netdev_features_t features);
void qede_set_rx_mode(struct net_device *ndev); void qede_set_rx_mode(struct net_device *ndev);
void qede_config_rx_mode(struct net_device *ndev); void qede_config_rx_mode(struct net_device *ndev);
......
...@@ -940,6 +940,9 @@ int qede_change_mtu(struct net_device *ndev, int new_mtu) ...@@ -940,6 +940,9 @@ int qede_change_mtu(struct net_device *ndev, int new_mtu)
DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
"Configuring MTU size of %d\n", new_mtu); "Configuring MTU size of %d\n", new_mtu);
if (new_mtu > PAGE_SIZE)
ndev->features &= ~NETIF_F_GRO_HW;
/* Set the mtu field and re-start the interface if needed */ /* Set the mtu field and re-start the interface if needed */
args.u.mtu = new_mtu; args.u.mtu = new_mtu;
args.func = &qede_update_mtu; args.func = &qede_update_mtu;
......
...@@ -895,19 +895,26 @@ static void qede_set_features_reload(struct qede_dev *edev, ...@@ -895,19 +895,26 @@ static void qede_set_features_reload(struct qede_dev *edev,
edev->ndev->features = args->u.features; edev->ndev->features = args->u.features;
} }
netdev_features_t qede_fix_features(struct net_device *dev,
netdev_features_t features)
{
struct qede_dev *edev = netdev_priv(dev);
if (edev->xdp_prog || edev->ndev->mtu > PAGE_SIZE ||
!(features & NETIF_F_GRO))
features &= ~NETIF_F_GRO_HW;
return features;
}
int qede_set_features(struct net_device *dev, netdev_features_t features) int qede_set_features(struct net_device *dev, netdev_features_t features)
{ {
struct qede_dev *edev = netdev_priv(dev); struct qede_dev *edev = netdev_priv(dev);
netdev_features_t changes = features ^ dev->features; netdev_features_t changes = features ^ dev->features;
bool need_reload = false; bool need_reload = false;
/* No action needed if hardware GRO is disabled during driver load */ if (changes & NETIF_F_GRO_HW)
if (changes & NETIF_F_GRO) { need_reload = true;
if (dev->features & NETIF_F_GRO)
need_reload = !edev->gro_disable;
else
need_reload = edev->gro_disable;
}
if (need_reload) { if (need_reload) {
struct qede_reload_args args; struct qede_reload_args args;
......
...@@ -545,6 +545,7 @@ static const struct net_device_ops qede_netdev_ops = { ...@@ -545,6 +545,7 @@ static const struct net_device_ops qede_netdev_ops = {
#endif #endif
.ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
.ndo_fix_features = qede_fix_features,
.ndo_set_features = qede_set_features, .ndo_set_features = qede_set_features,
.ndo_get_stats64 = qede_get_stats64, .ndo_get_stats64 = qede_get_stats64,
#ifdef CONFIG_QED_SRIOV #ifdef CONFIG_QED_SRIOV
...@@ -572,6 +573,7 @@ static const struct net_device_ops qede_netdev_vf_ops = { ...@@ -572,6 +573,7 @@ static const struct net_device_ops qede_netdev_vf_ops = {
.ndo_change_mtu = qede_change_mtu, .ndo_change_mtu = qede_change_mtu,
.ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
.ndo_fix_features = qede_fix_features,
.ndo_set_features = qede_set_features, .ndo_set_features = qede_set_features,
.ndo_get_stats64 = qede_get_stats64, .ndo_get_stats64 = qede_get_stats64,
.ndo_udp_tunnel_add = qede_udp_tunnel_add, .ndo_udp_tunnel_add = qede_udp_tunnel_add,
...@@ -589,6 +591,7 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = { ...@@ -589,6 +591,7 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = {
.ndo_change_mtu = qede_change_mtu, .ndo_change_mtu = qede_change_mtu,
.ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
.ndo_fix_features = qede_fix_features,
.ndo_set_features = qede_set_features, .ndo_set_features = qede_set_features,
.ndo_get_stats64 = qede_get_stats64, .ndo_get_stats64 = qede_get_stats64,
.ndo_udp_tunnel_add = qede_udp_tunnel_add, .ndo_udp_tunnel_add = qede_udp_tunnel_add,
...@@ -676,7 +679,7 @@ static void qede_init_ndev(struct qede_dev *edev) ...@@ -676,7 +679,7 @@ static void qede_init_ndev(struct qede_dev *edev)
ndev->priv_flags |= IFF_UNICAST_FLT; ndev->priv_flags |= IFF_UNICAST_FLT;
/* user-changeble features */ /* user-changeble features */
hw_features = NETIF_F_GRO | NETIF_F_SG | hw_features = NETIF_F_GRO | NETIF_F_GRO_HW | NETIF_F_SG |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO6; NETIF_F_TSO | NETIF_F_TSO6;
...@@ -1228,18 +1231,9 @@ static int qede_alloc_sge_mem(struct qede_dev *edev, struct qede_rx_queue *rxq) ...@@ -1228,18 +1231,9 @@ static int qede_alloc_sge_mem(struct qede_dev *edev, struct qede_rx_queue *rxq)
dma_addr_t mapping; dma_addr_t mapping;
int i; int i;
/* Don't perform FW aggregations in case of XDP */
if (edev->xdp_prog)
edev->gro_disable = 1;
if (edev->gro_disable) if (edev->gro_disable)
return 0; return 0;
if (edev->ndev->mtu > PAGE_SIZE) {
edev->gro_disable = 1;
return 0;
}
for (i = 0; i < ETH_TPA_MAX_AGGS_NUM; i++) { for (i = 0; i < ETH_TPA_MAX_AGGS_NUM; i++) {
struct qede_agg_info *tpa_info = &rxq->tpa_info[i]; struct qede_agg_info *tpa_info = &rxq->tpa_info[i];
struct sw_rx_data *replace_buf = &tpa_info->buffer; struct sw_rx_data *replace_buf = &tpa_info->buffer;
...@@ -1269,6 +1263,7 @@ static int qede_alloc_sge_mem(struct qede_dev *edev, struct qede_rx_queue *rxq) ...@@ -1269,6 +1263,7 @@ static int qede_alloc_sge_mem(struct qede_dev *edev, struct qede_rx_queue *rxq)
err: err:
qede_free_sge_mem(edev, rxq); qede_free_sge_mem(edev, rxq);
edev->gro_disable = 1; edev->gro_disable = 1;
edev->ndev->features &= ~NETIF_F_GRO_HW;
return -ENOMEM; return -ENOMEM;
} }
...@@ -1511,7 +1506,7 @@ static void qede_init_fp(struct qede_dev *edev) ...@@ -1511,7 +1506,7 @@ static void qede_init_fp(struct qede_dev *edev)
edev->ndev->name, queue_id); edev->ndev->name, queue_id);
} }
edev->gro_disable = !(edev->ndev->features & NETIF_F_GRO); edev->gro_disable = !(edev->ndev->features & NETIF_F_GRO_HW);
} }
static int qede_set_real_num_queues(struct qede_dev *edev) static int qede_set_real_num_queues(struct qede_dev *edev)
......
...@@ -78,6 +78,8 @@ enum { ...@@ -78,6 +78,8 @@ enum {
NETIF_F_HW_ESP_TX_CSUM_BIT, /* ESP with TX checksum offload */ NETIF_F_HW_ESP_TX_CSUM_BIT, /* ESP with TX checksum offload */
NETIF_F_RX_UDP_TUNNEL_PORT_BIT, /* Offload of RX port for UDP tunnels */ NETIF_F_RX_UDP_TUNNEL_PORT_BIT, /* Offload of RX port for UDP tunnels */
NETIF_F_GRO_HW_BIT, /* Hardware Generic receive offload */
/* /*
* Add your fresh new feature above and remember to update * Add your fresh new feature above and remember to update
* netdev_features_strings[] in net/core/ethtool.c and maybe * netdev_features_strings[] in net/core/ethtool.c and maybe
...@@ -97,6 +99,7 @@ enum { ...@@ -97,6 +99,7 @@ enum {
#define NETIF_F_FRAGLIST __NETIF_F(FRAGLIST) #define NETIF_F_FRAGLIST __NETIF_F(FRAGLIST)
#define NETIF_F_FSO __NETIF_F(FSO) #define NETIF_F_FSO __NETIF_F(FSO)
#define NETIF_F_GRO __NETIF_F(GRO) #define NETIF_F_GRO __NETIF_F(GRO)
#define NETIF_F_GRO_HW __NETIF_F(GRO_HW)
#define NETIF_F_GSO __NETIF_F(GSO) #define NETIF_F_GSO __NETIF_F(GSO)
#define NETIF_F_GSO_ROBUST __NETIF_F(GSO_ROBUST) #define NETIF_F_GSO_ROBUST __NETIF_F(GSO_ROBUST)
#define NETIF_F_HIGHDMA __NETIF_F(HIGHDMA) #define NETIF_F_HIGHDMA __NETIF_F(HIGHDMA)
......
...@@ -1542,6 +1542,23 @@ void dev_disable_lro(struct net_device *dev) ...@@ -1542,6 +1542,23 @@ void dev_disable_lro(struct net_device *dev)
} }
EXPORT_SYMBOL(dev_disable_lro); EXPORT_SYMBOL(dev_disable_lro);
/**
* dev_disable_gro_hw - disable HW Generic Receive Offload on a device
* @dev: device
*
* Disable HW Generic Receive Offload (GRO_HW) on a net device. Must be
* called under RTNL. This is needed if Generic XDP is installed on
* the device.
*/
static void dev_disable_gro_hw(struct net_device *dev)
{
dev->wanted_features &= ~NETIF_F_GRO_HW;
netdev_update_features(dev);
if (unlikely(dev->features & NETIF_F_GRO_HW))
netdev_WARN(dev, "failed to disable GRO_HW!\n");
}
static int call_netdevice_notifier(struct notifier_block *nb, unsigned long val, static int call_netdevice_notifier(struct notifier_block *nb, unsigned long val,
struct net_device *dev) struct net_device *dev)
{ {
...@@ -4564,6 +4581,7 @@ static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp) ...@@ -4564,6 +4581,7 @@ static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp)
} else if (new && !old) { } else if (new && !old) {
static_key_slow_inc(&generic_xdp_needed); static_key_slow_inc(&generic_xdp_needed);
dev_disable_lro(dev); dev_disable_lro(dev);
dev_disable_gro_hw(dev);
} }
break; break;
...@@ -7424,6 +7442,18 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, ...@@ -7424,6 +7442,18 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
features &= ~dev->gso_partial_features; features &= ~dev->gso_partial_features;
} }
if (!(features & NETIF_F_RXCSUM)) {
/* NETIF_F_GRO_HW implies doing RXCSUM since every packet
* successfully merged by hardware must also have the
* checksum verified by hardware. If the user does not
* want to enable RXCSUM, logically, we should disable GRO_HW.
*/
if (features & NETIF_F_GRO_HW) {
netdev_dbg(dev, "Dropping NETIF_F_GRO_HW since no RXCSUM feature.\n");
features &= ~NETIF_F_GRO_HW;
}
}
return features; return features;
} }
......
...@@ -73,6 +73,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] ...@@ -73,6 +73,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[NETIF_F_LLTX_BIT] = "tx-lockless", [NETIF_F_LLTX_BIT] = "tx-lockless",
[NETIF_F_NETNS_LOCAL_BIT] = "netns-local", [NETIF_F_NETNS_LOCAL_BIT] = "netns-local",
[NETIF_F_GRO_BIT] = "rx-gro", [NETIF_F_GRO_BIT] = "rx-gro",
[NETIF_F_GRO_HW_BIT] = "rx-gro-hw",
[NETIF_F_LRO_BIT] = "rx-lro", [NETIF_F_LRO_BIT] = "rx-lro",
[NETIF_F_TSO_BIT] = "tx-tcp-segmentation", [NETIF_F_TSO_BIT] = "tx-tcp-segmentation",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment