mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e9c5a106e9
11 changed files with 105 additions and 40 deletions
|
@ -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
|
||||
bad packets on it. Some NICs may receive more packets if also put into normal
|
||||
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)
|
|||
*/
|
||||
if (bp->dev->features & NETIF_F_LRO)
|
||||
fp->mode = TPA_MODE_LRO;
|
||||
else if (bp->dev->features & NETIF_F_GRO &&
|
||||
bnx2x_mtu_allows_gro(bp->dev->mtu))
|
||||
else if (bp->dev->features & NETIF_F_GRO_HW)
|
||||
fp->mode = TPA_MODE_GRO;
|
||||
else
|
||||
fp->mode = TPA_MODE_DISABLED;
|
||||
|
@ -4874,6 +4873,9 @@ int bnx2x_change_mtu(struct net_device *dev, int 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))
|
||||
SHMEM2_WR(bp, curr_cfg, CURR_CFG_MET_OS);
|
||||
|
||||
|
@ -4903,10 +4905,13 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
|
|||
}
|
||||
|
||||
/* 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_GRO;
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
@ -4933,13 +4938,8 @@ 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 */
|
||||
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;
|
||||
/* Don't care about GRO changes */
|
||||
changes &= ~NETIF_F_GRO;
|
||||
|
||||
if (changes)
|
||||
bnx2x_reload = true;
|
||||
|
|
|
@ -12400,8 +12400,8 @@ static int bnx2x_init_bp(struct bnx2x *bp)
|
|||
|
||||
/* Set TPA flags */
|
||||
if (bp->disable_tpa) {
|
||||
bp->dev->hw_features &= ~NETIF_F_LRO;
|
||||
bp->dev->features &= ~NETIF_F_LRO;
|
||||
bp->dev->hw_features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
|
||||
bp->dev->features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
|
||||
}
|
||||
|
||||
if (CHIP_IS_E1(bp))
|
||||
|
@ -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 |
|
||||
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;
|
||||
if (!chip_is_e1x) {
|
||||
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,
|
|||
|
||||
dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX;
|
||||
dev->features |= NETIF_F_HIGHDMA;
|
||||
if (dev->features & NETIF_F_LRO)
|
||||
dev->features &= ~NETIF_F_GRO_HW;
|
||||
|
||||
/* Add Loopback capability to the device */
|
||||
dev->hw_features |= NETIF_F_LOOPBACK;
|
||||
|
|
|
@ -2755,7 +2755,7 @@ void bnxt_set_tpa_flags(struct bnxt *bp)
|
|||
return;
|
||||
if (bp->dev->features & NETIF_F_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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
bp->flags &= ~BNXT_FLAG_AGG_RINGS;
|
||||
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_skb_func = bnxt_rx_page_skb;
|
||||
/* Disable LRO or GRO_HW */
|
||||
netdev_update_features(bp->dev);
|
||||
} else {
|
||||
bp->dev->max_mtu = bp->max_mtu;
|
||||
bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE;
|
||||
|
@ -6788,6 +6788,15 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
|
|||
if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp))
|
||||
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
|
||||
* turned on or off together.
|
||||
*/
|
||||
|
@ -6821,9 +6830,9 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
|
|||
bool update_tpa = false;
|
||||
|
||||
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;
|
||||
if (features & NETIF_F_LRO)
|
||||
else if (features & NETIF_F_LRO)
|
||||
flags |= BNXT_FLAG_LRO;
|
||||
|
||||
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,
|
|||
if (rc)
|
||||
return rc;
|
||||
bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
|
||||
bp->dev->hw_features &= ~NETIF_F_LRO;
|
||||
bp->dev->features &= ~NETIF_F_LRO;
|
||||
bp->dev->hw_features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
|
||||
bp->dev->features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
|
||||
bnxt_set_ring_params(bp);
|
||||
}
|
||||
|
||||
|
@ -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->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;
|
||||
if (!BNXT_CHIP_TYPE_NITRO_A0(bp))
|
||||
dev->hw_features |= NETIF_F_GRO_HW;
|
||||
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;
|
||||
|
||||
#ifdef CONFIG_BNXT_SRIOV
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
void qede_set_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)
|
|||
DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
|
||||
"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 */
|
||||
args.u.mtu = new_mtu;
|
||||
args.func = &qede_update_mtu;
|
||||
|
|
|
@ -895,19 +895,26 @@ static void qede_set_features_reload(struct qede_dev *edev,
|
|||
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)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
netdev_features_t changes = features ^ dev->features;
|
||||
bool need_reload = false;
|
||||
|
||||
/* No action needed if hardware GRO is disabled during driver load */
|
||||
if (changes & NETIF_F_GRO) {
|
||||
if (dev->features & NETIF_F_GRO)
|
||||
need_reload = !edev->gro_disable;
|
||||
else
|
||||
need_reload = edev->gro_disable;
|
||||
}
|
||||
if (changes & NETIF_F_GRO_HW)
|
||||
need_reload = true;
|
||||
|
||||
if (need_reload) {
|
||||
struct qede_reload_args args;
|
||||
|
|
|
@ -545,6 +545,7 @@ static const struct net_device_ops qede_netdev_ops = {
|
|||
#endif
|
||||
.ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
|
||||
.ndo_fix_features = qede_fix_features,
|
||||
.ndo_set_features = qede_set_features,
|
||||
.ndo_get_stats64 = qede_get_stats64,
|
||||
#ifdef CONFIG_QED_SRIOV
|
||||
|
@ -572,6 +573,7 @@ static const struct net_device_ops qede_netdev_vf_ops = {
|
|||
.ndo_change_mtu = qede_change_mtu,
|
||||
.ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
|
||||
.ndo_fix_features = qede_fix_features,
|
||||
.ndo_set_features = qede_set_features,
|
||||
.ndo_get_stats64 = qede_get_stats64,
|
||||
.ndo_udp_tunnel_add = qede_udp_tunnel_add,
|
||||
|
@ -589,6 +591,7 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = {
|
|||
.ndo_change_mtu = qede_change_mtu,
|
||||
.ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
|
||||
.ndo_fix_features = qede_fix_features,
|
||||
.ndo_set_features = qede_set_features,
|
||||
.ndo_get_stats64 = qede_get_stats64,
|
||||
.ndo_udp_tunnel_add = qede_udp_tunnel_add,
|
||||
|
@ -676,7 +679,7 @@ static void qede_init_ndev(struct qede_dev *edev)
|
|||
ndev->priv_flags |= IFF_UNICAST_FLT;
|
||||
|
||||
/* 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_TSO | NETIF_F_TSO6;
|
||||
|
||||
|
@ -1228,18 +1231,9 @@ static int qede_alloc_sge_mem(struct qede_dev *edev, struct qede_rx_queue *rxq)
|
|||
dma_addr_t mapping;
|
||||
int i;
|
||||
|
||||
/* Don't perform FW aggregations in case of XDP */
|
||||
if (edev->xdp_prog)
|
||||
edev->gro_disable = 1;
|
||||
|
||||
if (edev->gro_disable)
|
||||
return 0;
|
||||
|
||||
if (edev->ndev->mtu > PAGE_SIZE) {
|
||||
edev->gro_disable = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ETH_TPA_MAX_AGGS_NUM; i++) {
|
||||
struct qede_agg_info *tpa_info = &rxq->tpa_info[i];
|
||||
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)
|
|||
err:
|
||||
qede_free_sge_mem(edev, rxq);
|
||||
edev->gro_disable = 1;
|
||||
edev->ndev->features &= ~NETIF_F_GRO_HW;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -1511,7 +1506,7 @@ static void qede_init_fp(struct qede_dev *edev)
|
|||
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)
|
||||
|
|
|
@ -78,6 +78,8 @@ enum {
|
|||
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_GRO_HW_BIT, /* Hardware Generic receive offload */
|
||||
|
||||
/*
|
||||
* Add your fresh new feature above and remember to update
|
||||
* netdev_features_strings[] in net/core/ethtool.c and maybe
|
||||
|
@ -97,6 +99,7 @@ enum {
|
|||
#define NETIF_F_FRAGLIST __NETIF_F(FRAGLIST)
|
||||
#define NETIF_F_FSO __NETIF_F(FSO)
|
||||
#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_ROBUST __NETIF_F(GSO_ROBUST)
|
||||
#define NETIF_F_HIGHDMA __NETIF_F(HIGHDMA)
|
||||
|
|
|
@ -1542,6 +1542,23 @@ void dev_disable_lro(struct net_device *dev)
|
|||
}
|
||||
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,
|
||||
struct net_device *dev)
|
||||
{
|
||||
|
@ -4564,6 +4581,7 @@ static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp)
|
|||
} else if (new && !old) {
|
||||
static_key_slow_inc(&generic_xdp_needed);
|
||||
dev_disable_lro(dev);
|
||||
dev_disable_gro_hw(dev);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -7424,6 +7442,18 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
|
|||
[NETIF_F_LLTX_BIT] = "tx-lockless",
|
||||
[NETIF_F_NETNS_LOCAL_BIT] = "netns-local",
|
||||
[NETIF_F_GRO_BIT] = "rx-gro",
|
||||
[NETIF_F_GRO_HW_BIT] = "rx-gro-hw",
|
||||
[NETIF_F_LRO_BIT] = "rx-lro",
|
||||
|
||||
[NETIF_F_TSO_BIT] = "tx-tcp-segmentation",
|
||||
|
|
Loading…
Reference in a new issue