[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20220419022206.36381-6-shenjian15@huawei.com>
Date: Tue, 19 Apr 2022 10:21:52 +0800
From: Jian Shen <shenjian15@...wei.com>
To: <davem@...emloft.net>, <kuba@...nel.org>, <andrew@...n.ch>,
<ecree.xilinx@...il.com>, <hkallweit1@...il.com>,
<alexandr.lobakin@...el.com>, <saeed@...nel.org>, <leon@...nel.org>
CC: <netdev@...r.kernel.org>, <linuxarm@...neuler.org>,
<lipeng321@...wei.com>
Subject: [RFCv6 PATCH net-next 05/19] net: simplify the netdev features expression
To make the semantic patches simple, split the complex opreation of
netdev_features to simple ones, and replace some feature macroes with
global netdev features variables.
Signed-off-by: Jian Shen <shenjian15@...wei.com>
---
.../net/ethernet/hisilicon/hns3/hns3_enet.c | 10 +--
drivers/net/ethernet/sfc/ef10.c | 5 +-
drivers/net/ethernet/sfc/efx.c | 7 +-
drivers/net/ethernet/sfc/efx_common.c | 14 ++--
drivers/net/ethernet/sfc/falcon/efx.c | 12 ++--
include/linux/netdev_features_helper.h | 14 ++--
net/core/dev.c | 69 ++++++++++++-------
net/ethtool/features.c | 4 +-
net/ethtool/ioctl.c | 47 +++++++++----
9 files changed, 120 insertions(+), 62 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 74ebba5b9bc3..0234d9755a9f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2476,7 +2476,7 @@ static netdev_features_t hns3_features_check(struct sk_buff *skb,
* len of 480 bytes.
*/
if (len > HNS3_MAX_HDR_LEN)
- features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+ features &= ~netdev_csum_gso_features_mask;
return features;
}
@@ -3308,7 +3308,7 @@ static void hns3_set_default_feature(struct net_device *netdev)
if (test_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps))
netdev->features |= NETIF_F_HW_CSUM;
else
- netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ netdev->features |= netdev_ip_csum_features;
if (test_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps))
netdev->features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
@@ -3323,9 +3323,11 @@ static void hns3_set_default_feature(struct net_device *netdev)
netdev_features_zero(&vlan_off_features);
netdev_features_set_array(&hns3_vlan_off_feature_set,
&vlan_off_features);
- netdev->vlan_features |= netdev->features & ~vlan_off_features;
+ features = netdev->features & ~vlan_off_features;
+ netdev->vlan_features |= features;
- netdev->hw_enc_features |= netdev->vlan_features | NETIF_F_TSO_MANGLEID;
+ netdev->hw_enc_features |= netdev->vlan_features;
+ netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
}
static int hns3_alloc_buffer(struct hns3_enet_ring *ring,
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 63fc4c771955..01bc65ba0d31 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1357,7 +1357,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
/* add encapsulated checksum offload features */
if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx))
- hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ hw_enc_features |= netdev_ip_csum_features;
/* add encapsulated TSO features */
if (efx_has_cap(efx, TX_TSO_V2_ENCAP)) {
netdev_features_t encap_tso_features;
@@ -1366,7 +1366,8 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
netdev_features_set_array(&ef10_tso_feature_set,
&encap_tso_features);
- hw_enc_features |= encap_tso_features | NETIF_F_TSO;
+ hw_enc_features |= encap_tso_features;
+ hw_enc_features |= NETIF_F_TSO;
efx->net_dev->features |= encap_tso_features;
}
efx->net_dev->hw_enc_features = hw_enc_features;
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 15a896f397f2..a44378ae484a 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1004,6 +1004,7 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
{
struct net_device *net_dev = efx->net_dev;
int rc = efx_pci_probe_main(efx);
+ netdev_features_t tmp;
if (rc)
return rc;
@@ -1018,7 +1019,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
/* Determine netdevice features */
net_dev->features |= *efx->type->offload_features;
netdev_active_features_set_array(net_dev, &efx_active_feature_set);
- if (*efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
+ if ((*efx->type->offload_features & NETIF_F_IPV6_CSUM) ||
+ (*efx->type->offload_features & NETIF_F_HW_CSUM))
net_dev->features |= NETIF_F_TSO6;
/* Check whether device supports TSO */
if (!efx->type->tso_versions || !efx->type->tso_versions(efx))
@@ -1027,7 +1029,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
net_dev->vlan_features |= NETIF_F_ALL_TSO;
netdev_vlan_features_set_array(net_dev, &efx_vlan_feature_set);
- net_dev->hw_features |= net_dev->features & ~efx->fixed_features;
+ tmp = net_dev->features & ~efx->fixed_features;
+ net_dev->hw_features |= tmp;
/* Disable receiving frames with bad FCS, by default. */
net_dev->features &= ~NETIF_F_RXALL;
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index af37c990217e..815acba14394 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -212,10 +212,12 @@ void efx_set_rx_mode(struct net_device *net_dev)
int efx_set_features(struct net_device *net_dev, netdev_features_t data)
{
struct efx_nic *efx = netdev_priv(net_dev);
+ netdev_features_t tmp;
int rc;
/* If disabling RX n-tuple filtering, clear existing filters */
- if (net_dev->features & ~data & NETIF_F_NTUPLE) {
+ tmp = net_dev->features & ~data;
+ if (tmp & NETIF_F_NTUPLE) {
rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
if (rc)
return rc;
@@ -224,8 +226,9 @@ int efx_set_features(struct net_device *net_dev, netdev_features_t data)
/* If Rx VLAN filter is changed, update filters via mac_reconfigure.
* If rx-fcs is changed, mac_reconfigure updates that too.
*/
- if ((net_dev->features ^ data) & (NETIF_F_HW_VLAN_CTAG_FILTER |
- NETIF_F_RXFCS)) {
+ tmp = net_dev->features ^ data;
+ if (tmp & NETIF_F_HW_VLAN_CTAG_FILTER ||
+ tmp & NETIF_F_RXFCS) {
/* efx_set_rx_mode() will schedule MAC work to update filters
* when a new features are finally set in net_dev.
*/
@@ -1367,10 +1370,9 @@ netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev
if (skb_inner_transport_offset(skb) >
EFX_TSO2_MAX_HDRLEN)
features &= ~(NETIF_F_GSO_MASK);
- if (features & (NETIF_F_GSO_MASK | NETIF_F_CSUM_MASK))
+ if (features & netdev_csum_gso_features_mask)
if (!efx_can_encap_offloads(efx, skb))
- features &= ~(NETIF_F_GSO_MASK |
- NETIF_F_CSUM_MASK);
+ features &= ~netdev_csum_gso_features_mask;
}
return features;
}
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c
index 7d2276aa2bf6..665190413841 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2188,17 +2188,20 @@ static void ef4_set_rx_mode(struct net_device *net_dev)
static int ef4_set_features(struct net_device *net_dev, netdev_features_t data)
{
struct ef4_nic *efx = netdev_priv(net_dev);
+ netdev_features_t tmp;
int rc;
/* If disabling RX n-tuple filtering, clear existing filters */
- if (net_dev->features & ~data & NETIF_F_NTUPLE) {
+ tmp = net_dev->features & ~data;
+ if (tmp & NETIF_F_NTUPLE) {
rc = efx->type->filter_clear_rx(efx, EF4_FILTER_PRI_MANUAL);
if (rc)
return rc;
}
/* If Rx VLAN filter is changed, update filters via mac_reconfigure */
- if ((net_dev->features ^ data) & NETIF_F_HW_VLAN_CTAG_FILTER) {
+ tmp = net_dev->features ^ data;
+ if (tmp & NETIF_F_HW_VLAN_CTAG_FILTER) {
/* ef4_set_rx_mode() will schedule MAC work to update filters
* when a new features are finally set in net_dev.
*/
@@ -2910,8 +2913,9 @@ static int ef4_pci_probe(struct pci_dev *pci_dev,
if (rc)
goto fail3;
- net_dev->features |= (*efx->type->offload_features | NETIF_F_SG |
- NETIF_F_RXCSUM);
+ net_dev->features |= *efx->type->offload_features;
+ net_dev->features |= NETIF_F_SG;
+ net_dev->features |= NETIF_F_RXCSUM;
/* Mask for features that also apply to VLAN devices */
netdev_vlan_features_set_array(net_dev, &efx_vlan_feature_set);
net_dev->hw_features = net_dev->features & ~efx->fixed_features;
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h
index 5cc6368f65e5..b68a85d2b982 100644
--- a/include/linux/netdev_features_helper.h
+++ b/include/linux/netdev_features_helper.h
@@ -585,11 +585,14 @@ static inline bool netdev_features_subset(const netdev_features_t src1,
static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
netdev_features_t f2)
{
- if ((f1 ^ f2) & NETIF_F_HW_CSUM) {
+ netdev_features_t tmp;
+
+ tmp = f1 ^ f2;
+ if (tmp & NETIF_F_HW_CSUM) {
if (f1 & NETIF_F_HW_CSUM)
- f1 |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+ f1 |= netdev_ip_csum_features;
else
- f2 |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+ f2 |= netdev_ip_csum_features;
}
return f1 & f2;
@@ -598,7 +601,10 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
static inline netdev_features_t
netdev_get_wanted_features(struct net_device *dev)
{
- return (dev->features & ~dev->hw_features) | dev->wanted_features;
+ netdev_features_t tmp;
+
+ tmp = dev->features & ~dev->hw_features;
+ return dev->wanted_features | tmp;
}
#endif
diff --git a/net/core/dev.c b/net/core/dev.c
index 85bb418e8ef1..ccf170a5f151 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3340,10 +3340,11 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
* work.
*/
if (features & NETIF_F_GSO_PARTIAL) {
- netdev_features_t partial_features = NETIF_F_GSO_ROBUST;
+ netdev_features_t partial_features;
struct net_device *dev = skb->dev;
- partial_features |= dev->features & dev->gso_partial_features;
+ partial_features = dev->features & dev->gso_partial_features;
+ partial_features |= NETIF_F_GSO_ROBUST;
if (!skb_gso_ok(skb, features | partial_features))
features &= ~NETIF_F_GSO_PARTIAL;
}
@@ -3432,7 +3433,7 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
if (skb->ip_summed != CHECKSUM_NONE &&
!can_checksum_protocol(features, type)) {
- features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+ features &= ~netdev_csum_gso_features_mask;
}
if (illegal_highdma(skb->dev, skb))
features &= ~NETIF_F_SG;
@@ -3496,6 +3497,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
netdev_features_t features = dev->features;
+ netdev_features_t tmp;
if (skb_is_gso(skb))
features = gso_features_check(skb, dev, features);
@@ -3507,17 +3509,16 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
if (skb->encapsulation)
features &= dev->hw_enc_features;
- if (skb_vlan_tagged(skb))
- features = netdev_intersect_features(features,
- dev->vlan_features |
- NETIF_F_HW_VLAN_CTAG_TX |
- NETIF_F_HW_VLAN_STAG_TX);
+ if (skb_vlan_tagged(skb)) {
+ tmp = dev->vlan_features | netdev_tx_vlan_features;
+ features = netdev_intersect_features(features, tmp);
+ }
if (dev->netdev_ops->ndo_features_check)
- features &= dev->netdev_ops->ndo_features_check(skb, dev,
- features);
+ tmp = dev->netdev_ops->ndo_features_check(skb, dev, features);
else
- features &= dflt_features_check(skb, dev, features);
+ tmp = dflt_features_check(skb, dev, features);
+ features &= tmp;
return harmonize_features(skb, features);
}
@@ -3588,7 +3589,7 @@ int skb_csum_hwoffload_help(struct sk_buff *skb,
if (features & NETIF_F_HW_CSUM)
return 0;
- if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
+ if (features & netdev_ip_csum_features) {
switch (skb->csum_offset) {
case offsetof(struct tcphdr, check):
case offsetof(struct udphdr, check):
@@ -9493,11 +9494,13 @@ static void netdev_sync_lower_features(struct net_device *upper,
static netdev_features_t netdev_fix_features(struct net_device *dev,
netdev_features_t features)
{
+ netdev_features_t tmp;
+
/* Fix illegal checksum combinations */
if ((features & NETIF_F_HW_CSUM) &&
- (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+ (features & netdev_ip_csum_features)) {
netdev_warn(dev, "mixed HW and IP checksum settings.\n");
- features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
+ features &= ~netdev_ip_csum_features;
}
/* TSO requires that SG is present as well. */
@@ -9524,7 +9527,9 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
features &= ~NETIF_F_TSO_MANGLEID;
/* TSO ECN requires that TSO is present as well. */
- if ((features & NETIF_F_ALL_TSO) == NETIF_F_TSO_ECN)
+ tmp = NETIF_F_ALL_TSO;
+ tmp &= ~NETIF_F_TSO_ECN;
+ if (!(features & tmp) && (features & NETIF_F_TSO_ECN))
features &= ~NETIF_F_TSO_ECN;
/* Software GSO depends on SG. */
@@ -9572,8 +9577,8 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
}
if (features & NETIF_F_HW_TLS_TX) {
- bool ip_csum = (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) ==
- (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+ bool ip_csum = (features & netdev_ip_csum_features) ==
+ netdev_ip_csum_features;
bool hw_csum = features & NETIF_F_HW_CSUM;
if (!ip_csum && !hw_csum) {
@@ -9902,8 +9907,8 @@ int register_netdevice(struct net_device *dev)
}
}
- if (((dev->hw_features | dev->features) &
- NETIF_F_HW_VLAN_CTAG_FILTER) &&
+ if ((dev->hw_features & NETIF_F_HW_VLAN_CTAG_FILTER ||
+ dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
(!dev->netdev_ops->ndo_vlan_rx_add_vid ||
!dev->netdev_ops->ndo_vlan_rx_kill_vid)) {
netdev_WARN(dev, "Buggy VLAN acceleration in driver!\n");
@@ -9920,7 +9925,8 @@ int register_netdevice(struct net_device *dev)
/* Transfer changeable features to wanted_features and enable
* software offloads (GSO and GRO).
*/
- dev->hw_features |= (NETIF_F_SOFT_FEATURES | NETIF_F_SOFT_FEATURES_OFF);
+ dev->hw_features |= NETIF_F_SOFT_FEATURES;
+ dev->hw_features |= NETIF_F_SOFT_FEATURES_OFF;
dev->features |= NETIF_F_SOFT_FEATURES;
if (dev->udp_tunnel_nic_info) {
@@ -9953,7 +9959,8 @@ int register_netdevice(struct net_device *dev)
/* Make NETIF_F_SG inheritable to tunnel devices.
*/
- dev->hw_enc_features |= NETIF_F_SG | NETIF_F_GSO_PARTIAL;
+ dev->hw_enc_features |= NETIF_F_SG;
+ dev->hw_enc_features |= NETIF_F_GSO_PARTIAL;
/* Make NETIF_F_SG inheritable to MPLS.
*/
@@ -11040,16 +11047,28 @@ static int dev_cpu_dead(unsigned int oldcpu)
netdev_features_t netdev_increment_features(netdev_features_t all,
netdev_features_t one, netdev_features_t mask)
{
+ netdev_features_t tmp;
+
if (mask & NETIF_F_HW_CSUM)
mask |= NETIF_F_CSUM_MASK;
mask |= NETIF_F_VLAN_CHALLENGED;
- all |= one & (NETIF_F_ONE_FOR_ALL | NETIF_F_CSUM_MASK) & mask;
- all &= one | ~NETIF_F_ALL_FOR_ALL;
+ tmp = NETIF_F_ONE_FOR_ALL | NETIF_F_CSUM_MASK;
+ tmp &= one;
+ tmp &= mask;
+ all |= tmp;
+
+ netdev_features_fill(&tmp);
+ tmp &= ~NETIF_F_ALL_FOR_ALL;
+ tmp |= one;
+ all &= tmp;
/* If one device supports hw checksumming, set for all. */
- if (all & NETIF_F_HW_CSUM)
- all &= ~(NETIF_F_CSUM_MASK & ~NETIF_F_HW_CSUM);
+ if (all & NETIF_F_HW_CSUM) {
+ tmp = NETIF_F_CSUM_MASK;
+ tmp &= ~NETIF_F_HW_CSUM;
+ all &= ~tmp;
+ }
return all;
}
diff --git a/net/ethtool/features.c b/net/ethtool/features.c
index 55d449a2d3fc..67a837d44491 100644
--- a/net/ethtool/features.c
+++ b/net/ethtool/features.c
@@ -220,6 +220,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
struct ethnl_req_info req_info = {};
struct nlattr **tb = info->attrs;
struct net_device *dev;
+ netdev_features_t tmp;
bool mod;
int ret;
@@ -253,7 +254,8 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
bitmap_or(req_wanted, new_wanted, req_wanted, NETDEV_FEATURE_COUNT);
if (!bitmap_equal(req_wanted, old_wanted, NETDEV_FEATURE_COUNT)) {
dev->wanted_features &= ~dev->hw_features;
- dev->wanted_features |= ethnl_bitmap_to_features(req_wanted) & dev->hw_features;
+ tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features;
+ dev->wanted_features |= tmp;
__netdev_update_features(dev);
}
ethnl_features_to_bitmap(new_active, dev->features);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 243ee8a0bd18..b2d500b27a5b 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -126,6 +126,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
struct ethtool_sfeatures cmd;
struct ethtool_set_features_block features[ETHTOOL_DEV_FEATURE_WORDS];
netdev_features_t wanted = 0, valid = 0;
+ netdev_features_t tmp;
int i, ret = 0;
if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
@@ -143,19 +144,23 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
wanted |= (netdev_features_t)features[i].requested << (32 * i);
}
- if (valid & ~NETIF_F_ETHTOOL_BITS)
+ tmp = valid & ~NETIF_F_ETHTOOL_BITS;
+ if (tmp)
return -EINVAL;
- if (valid & ~dev->hw_features) {
+ tmp = valid & ~dev->hw_features;
+ if (tmp) {
valid &= dev->hw_features;
ret |= ETHTOOL_F_UNSUPPORTED;
}
dev->wanted_features &= ~valid;
- dev->wanted_features |= wanted & valid;
+ tmp = wanted & valid;
+ dev->wanted_features |= tmp;
__netdev_update_features(dev);
- if ((dev->wanted_features ^ dev->features) & valid)
+ tmp = dev->wanted_features ^ dev->features;
+ if (tmp & valid)
ret |= ETHTOOL_F_WISH;
return ret;
@@ -222,28 +227,38 @@ static void __ethtool_get_strings(struct net_device *dev,
static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd)
{
+ netdev_features_t tmp;
+
/* feature masks of legacy discrete ethtool ops */
+ netdev_features_zero(&tmp);
switch (eth_cmd) {
case ETHTOOL_GTXCSUM:
case ETHTOOL_STXCSUM:
- return NETIF_F_CSUM_MASK | NETIF_F_FCOE_CRC |
- NETIF_F_SCTP_CRC;
+ tmp = NETIF_F_CSUM_MASK;
+ tmp |= NETIF_F_FCOE_CRC;
+ tmp |= NETIF_F_SCTP_CRC;
+ return tmp;
case ETHTOOL_GRXCSUM:
case ETHTOOL_SRXCSUM:
- return NETIF_F_RXCSUM;
+ tmp |= NETIF_F_RXCSUM;
+ return tmp;
case ETHTOOL_GSG:
case ETHTOOL_SSG:
- return NETIF_F_SG | NETIF_F_FRAGLIST;
+ tmp |= NETIF_F_SG;
+ tmp |= NETIF_F_FRAGLIST;
+ return tmp;
case ETHTOOL_GTSO:
case ETHTOOL_STSO:
return NETIF_F_ALL_TSO;
case ETHTOOL_GGSO:
case ETHTOOL_SGSO:
- return NETIF_F_GSO;
+ tmp |= NETIF_F_GSO;
+ return tmp;
case ETHTOOL_GGRO:
case ETHTOOL_SGRO:
- return NETIF_F_GRO;
+ tmp |= NETIF_F_GRO;
+ return tmp;
default:
BUG();
}
@@ -319,6 +334,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
{
netdev_features_t features = 0, changed;
netdev_features_t eth_all_features;
+ netdev_features_t tmp;
if (data & ~ETH_ALL_FLAGS)
return -EINVAL;
@@ -338,12 +354,15 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
netdev_features_set_array(ðtool_all_feature_set, ð_all_features);
/* allow changing only bits set in hw_features */
- changed = (features ^ dev->features) & eth_all_features;
- if (changed & ~dev->hw_features)
+ changed = dev->features ^ features;
+ changed &= eth_all_features;
+ tmp = changed & ~dev->hw_features;
+ if (tmp)
return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
- dev->wanted_features =
- (dev->wanted_features & ~changed) | (features & changed);
+ dev->wanted_features &= ~changed;
+ tmp = features & changed;
+ dev->wanted_features |= tmp;
__netdev_update_features(dev);
--
2.33.0
Powered by blists - more mailing lists