For the prototype of netdev_features_t is u64, and the number of netdevice feature bits is 64 now. So there is no space to introduce new feature bit.
This patchset try to solve it by change the prototype of netdev_features_t from u64 to structure below: typedef struct { DECLARE_BITMAP(bits, NETDEV_FEATURE_COUNT); } netdev_features_t;
With this change, it's necessary to introduce a set of bitmap operation helpers for netdev features. As the nic drivers are not supposed to modify netdev_features directly, it also introduces wrappers helpers to this. [patch 1]
To avoid mistake using NETIF_F_XXX as NETIF_F_XXX_BIT as input macroes for above helpers, remove all the macroes of NETIF_F_XXX. [patch 19]
The features group macroes in netdev_features.h are replaced by a set of const features defined in netdev_features.c. [patch 2-3] For example: macro NETIF_F_ALL_TSO is replaced by netdev_all_tso_features
There are some drivers(e.g. sfc) use netdev_features in global structure initialization. Changed the its netdev_features_t memeber to netdev_features_t *, and make it prefer to a netdev_features_t global variables. [patch 4]
As suggestion from Andrew Lunn, I wrote some semantic patches to do the work(replacing the netdev features operator by helpers). [patch 7-18] To make the semantic patches simple, I split the complex opreation of netdev_features to simple logical operation. [patch 5, 6]
With the prototype is no longer u64, the implementation of print interface for netdev features(%pNF) is changed to bitmap. [patch 19]
The whole work is not complete yet. I just use these changes on several files(hns3 driver, sfc drivers, net/ethtool, net/core/dev.c), in order to show how these helpers will be used. I will apply these helpers to the whole tree later, sofar I want to get more suggestions for this scheme, any comments would be appreciated.
The former discussion please see [1][2][3][4].
[1]:https://www.spinics.net/lists/netdev/msg769952.html [2]:https://www.spinics.net/lists/netdev/msg777764.html [3]:https://lore.kernel.org/netdev/20211107101519.29264-1-shenjian15@huawei.com/... [4]:https://www.spinics.net/lists/netdev/msg809293.html
ChangeLog: V5-V6: suggestions from Jakub Kicinski: drop the rename for netdev->features simplify names of some helpers, and move them to a new header file refine the implement for netdev_features_set_array V4->V5: adjust the patch structure, use semantic patch with coccinelle V3->V4: rename netdev->features to netdev->active_features remove helpes for handle first 64 bits remove __NETIF_F(name) macroes replace features group macroes with const features V2->V3: use structure for bitmap, suggest by Edward Cree V1->V2: Extend the prototype from u64 to bitmap, suggest by Andrew Lunn
Jian Shen (19): net: introduce operation helpers for netdev features net: replace general features macroes with global netdev_features variables net: replace multiple feature bits with netdev features array net: sfc: replace const features initialization with netdev features array net: simplify the netdev features expression net: adjust variables definition for netdev_features_t net: use netdev_feature_add helpers net: use netdev_features_or helpers net: use netdev_features_xor helpers net: use netdev_feature_del helpers net: use netdev_features_andnot helpers net: use netdev_feature_test helpers net: use netdev_features_intersects helpers net: use netdev_features_and helpers net: use netdev_features_subset helpers net: use netdev_features_equal helpers net: use netdev_features_copy helpers net: use netdev_xxx_features helpers net: redefine the prototype of netdev_features_t
.../net/ethernet/hisilicon/hns3/hns3_enet.c | 108 ++- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 4 +- .../net/ethernet/netronome/nfp/nfp_net_repr.c | 1 + drivers/net/ethernet/sfc/ef10.c | 38 +- drivers/net/ethernet/sfc/ef100_nic.c | 48 +- drivers/net/ethernet/sfc/ef100_rx.c | 4 +- drivers/net/ethernet/sfc/ef100_tx.c | 8 +- drivers/net/ethernet/sfc/ef10_sriov.c | 6 +- drivers/net/ethernet/sfc/efx.c | 82 ++- drivers/net/ethernet/sfc/efx_common.c | 31 +- drivers/net/ethernet/sfc/falcon/efx.c | 67 +- drivers/net/ethernet/sfc/falcon/efx.h | 3 + drivers/net/ethernet/sfc/falcon/falcon.c | 4 +- drivers/net/ethernet/sfc/falcon/net_driver.h | 5 +- drivers/net/ethernet/sfc/falcon/rx.c | 4 +- drivers/net/ethernet/sfc/farch.c | 2 +- drivers/net/ethernet/sfc/mcdi_filters.c | 13 +- drivers/net/ethernet/sfc/mcdi_port_common.c | 2 +- drivers/net/ethernet/sfc/net_driver.h | 5 +- drivers/net/ethernet/sfc/rx.c | 2 +- drivers/net/ethernet/sfc/rx_common.c | 4 +- drivers/net/ethernet/sfc/rx_common.h | 4 + drivers/net/ethernet/sfc/siena.c | 3 +- drivers/net/wireguard/device.c | 10 +- include/linux/netdev_features.h | 193 ++---- include/linux/netdev_features_helper.h | 653 ++++++++++++++++++ include/linux/netdevice.h | 109 +-- lib/vsprintf.c | 11 +- net/8021q/vlan_dev.c | 1 + net/core/Makefile | 2 +- net/core/dev.c | 389 +++++++---- net/core/netdev_features.c | 241 +++++++ net/ethtool/features.c | 90 +-- net/ethtool/ioctl.c | 135 ++-- 34 files changed, 1723 insertions(+), 559 deletions(-) create mode 100644 include/linux/netdev_features_helper.h create mode 100644 net/core/netdev_features.c
Introduce a set of bitmap operation helpers for netdev features, then we can use them to replace the logical operation with them. As the nic driversare not supposed to modify netdev_features directly, it also introduces wrappers helpers to this.
The implementation of these helpers are based on the old prototype of netdev_features_t is still u64. I will rewrite them on the last patch, when the prototype changes.
To avoid interdependencies between netdev_features_helper.h and netdevice.h, put the helpers for testing feature is set in the netdevice.h, and move advandced helpers like netdev_get_wanted_features() and netdev_intersect_features() to netdev_features_helper.h.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/netronome/nfp/nfp_net_repr.c | 1 + include/linux/netdev_features.h | 12 + include/linux/netdev_features_helper.h | 604 ++++++++++++++++++ include/linux/netdevice.h | 45 +- net/8021q/vlan_dev.c | 1 + net/core/dev.c | 1 + 6 files changed, 646 insertions(+), 18 deletions(-) create mode 100644 include/linux/netdev_features_helper.h
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c index ba3fa7eac98d..08f2c54e0a11 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c @@ -4,6 +4,7 @@ #include <linux/etherdevice.h> #include <linux/io-64-nonatomic-hi-lo.h> #include <linux/lockdep.h> +#include <linux/netdev_features_helper.h> #include <net/dst_metadata.h>
#include "nfpcore/nfp_cpp.h" diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 2c6b9e416225..e2b66fa3d7d6 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -11,6 +11,18 @@
typedef u64 netdev_features_t;
+struct netdev_feature_set { + unsigned int cnt; + unsigned short feature_bits[]; +}; + +#define DECLARE_NETDEV_FEATURE_SET(name, features...) \ + static unsigned short __##name##_s[] = {features}; \ + struct netdev_feature_set name = { \ + .cnt = ARRAY_SIZE(__##name##_s), \ + .feature_bits = {features}, \ + } + enum { NETIF_F_SG_BIT, /* Scatter/gather IO. */ NETIF_F_IP_CSUM_BIT, /* Can checksum TCP/UDP over IPv4. */ diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h new file mode 100644 index 000000000000..5cc6368f65e5 --- /dev/null +++ b/include/linux/netdev_features_helper.h @@ -0,0 +1,604 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Network device features helpers. + */ +#ifndef _LINUX_NETDEV_FEATURES_HELPER_H +#define _LINUX_NETDEV_FEATURES_HELPER_H + +#include <linux/netdevice.h> + +static inline void netdev_features_zero(netdev_features_t *dst) +{ + *dst = 0; +} + +static inline void netdev_features_fill(netdev_features_t *dst) +{ + *dst = ~0ULL; +} + +static inline bool netdev_features_empty(const netdev_features_t src) +{ + return src == 0; +} + +/* helpers for netdev features '==' operation */ +static inline bool netdev_features_equal(const netdev_features_t src1, + const netdev_features_t src2) +{ + return src1 == src2; +} + +/* active_feature prefer to netdev->features */ +#define netdev_active_features_equal(ndev, __features) \ + netdev_features_equal(ndev->features, __features) + +#define netdev_hw_features_equal(ndev, __features) \ + netdev_features_equal(ndev->hw_features, __features) + +#define netdev_wanted_features_equal(ndev, __features) \ + netdev_features_equal(ndev->wanted_features, __features) + +#define netdev_vlan_features_equal(ndev, __features) \ + netdev_features_equal(ndev->vlan_features, __features) + +#define netdev_hw_enc_features_equal(ndev, __features) \ + netdev_features_equal(ndev->hw_enc_features, __features) + +#define netdev_mpls_features_equal(ndev, __features) \ + netdev_features_equal(ndev->mpls_features, __features) + +#define netdev_gso_partial_features_equal(ndev, __features) \ + netdev_features_equal(ndev->gso_partial_features, __features) + +/* helpers for netdev features '&' operation */ +static inline netdev_features_t +netdev_features_and(const netdev_features_t a, const netdev_features_t b) +{ + return a & b; +} + +#define netdev_active_features_and(ndev, __features) \ + netdev_features_and(ndev->features, __features) + +#define netdev_hw_features_and(ndev, __features) \ + netdev_features_and(ndev->hw_features, __features) + +#define netdev_wanted_features_and(ndev, __features) \ + netdev_features_and(ndev->wanted_features, __features) + +#define netdev_vlan_features_and(ndev, __features) \ + netdev_features_and(ndev->vlan_features, __features) + +#define netdev_hw_enc_features_and(ndev, __features) \ + netdev_features_and(ndev->hw_enc_features, __features) + +#define netdev_mpls_features_and(ndev, __features) \ + netdev_features_and(ndev->mpls_features, __features) + +#define netdev_gso_partial_features_and(ndev, __features) \ + netdev_features_and(ndev->gso_partial_features, __features) + +/* helpers for netdev features '&=' operation */ +static inline void +netdev_features_mask(netdev_features_t *dst, + const netdev_features_t features) +{ + *dst = netdev_features_and(*dst, features); +} + +static inline void +netdev_active_features_mask(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->features = netdev_active_features_and(ndev, features); +} + +static inline void +netdev_hw_features_mask(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_features = netdev_hw_features_and(ndev, features); +} + +static inline void +netdev_wanted_features_mask(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->wanted_features = netdev_wanted_features_and(ndev, features); +} + +static inline void +netdev_vlan_features_mask(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->vlan_features = netdev_vlan_features_and(ndev, features); +} + +static inline void +netdev_hw_enc_features_mask(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_enc_features = netdev_hw_enc_features_and(ndev, features); +} + +static inline void +netdev_mpls_features_mask(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->mpls_features = netdev_mpls_features_and(ndev, features); +} + +static inline void +netdev_gso_partial_features_mask(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->gso_partial_features = netdev_mpls_features_and(ndev, features); +} + +/* helpers for netdev features '|' operation */ +static inline netdev_features_t +netdev_features_or(const netdev_features_t a, const netdev_features_t b) +{ + return a | b; +} + +#define netdev_active_features_or(ndev, __features) \ + netdev_features_or(ndev->features, __features) + +#define netdev_hw_features_or(ndev, __features) \ + netdev_features_or(ndev->hw_features, __features) + +#define netdev_wanted_features_or(ndev, __features) \ + netdev_features_or(ndev->wanted_features, __features) + +#define netdev_vlan_features_or(ndev, __features) \ + netdev_features_or(ndev->vlan_features, __features) + +#define netdev_hw_enc_features_or(ndev, __features) \ + netdev_features_or(ndev->hw_enc_features, __features) + +#define netdev_mpls_features_or(ndev, __features) \ + netdev_features_or(ndev->mpls_features, __features) + +#define netdev_gso_partial_features_or(ndev, __features) \ + netdev_features_or(ndev->gso_partial_features, __features) + +/* helpers for netdev features '|=' operation */ +static inline void +netdev_features_set(netdev_features_t *dst, const netdev_features_t features) +{ + *dst = netdev_features_or(*dst, features); +} + +static inline void +netdev_active_features_set(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->features = netdev_active_features_or(ndev, features); +} + +static inline void +netdev_hw_features_set(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_features = netdev_hw_features_or(ndev, features); +} + +static inline void +netdev_wanted_features_set(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->wanted_features = netdev_wanted_features_or(ndev, features); +} + +static inline void +netdev_vlan_features_set(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->vlan_features = netdev_vlan_features_or(ndev, features); +} + +static inline void +netdev_hw_enc_features_set(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_enc_features = netdev_hw_enc_features_or(ndev, features); +} + +static inline void +netdev_mpls_features_set(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->mpls_features = netdev_mpls_features_or(ndev, features); +} + +static inline void +netdev_gso_partial_features_set(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->gso_partial_features = netdev_mpls_features_or(ndev, features); +} + +/* helpers for netdev features '^' operation */ +static inline netdev_features_t +netdev_features_xor(const netdev_features_t a, const netdev_features_t b) +{ + return a ^ b; +} + +#define netdev_active_features_xor(ndev, __features) \ + netdev_features_xor(ndev->features, __features) + +#define netdev_hw_features_xor(ndev, __features) \ + netdev_features_xor(ndev->hw_features, __features) + +#define netdev_wanted_features_xor(ndev, __features) \ + netdev_features_xor(ndev->wanted_features, __features) + +#define netdev_vlan_features_xor(ndev, __features) \ + netdev_features_xor(ndev->vlan_features, __features) + +#define netdev_hw_enc_features_xor(ndev, __features) \ + netdev_features_xor(ndev->hw_enc_features, __features) + +#define netdev_mpls_features_xor(ndev, __features) \ + netdev_features_xor(ndev->mpls_features, __features) + +#define netdev_gso_partial_features_xor(ndev, __features) \ + netdev_features_xor(ndev->gso_partial_features, __features) + +/* helpers for netdev features '^=' operation */ +static inline void +netdev_features_toggle(netdev_features_t *dst, const netdev_features_t features) +{ + *dst = netdev_features_xor(*dst, features); +} + +static inline void +netdev_active_features_toggle(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->features = netdev_active_features_xor(ndev, features); +} + +static inline void +netdev_hw_features_toggle(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_features = netdev_hw_features_xor(ndev, features); +} + +static inline void +netdev_wanted_features_toggle(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->wanted_features = netdev_wanted_features_xor(ndev, features); +} + +static inline void +netdev_vlan_features_toggle(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->vlan_features = netdev_vlan_features_xor(ndev, features); +} + +static inline void +netdev_hw_enc_features_toggle(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_enc_features = netdev_hw_enc_features_xor(ndev, features); +} + +static inline void +netdev_mpls_features_toggle(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->mpls_features = netdev_mpls_features_xor(ndev, features); +} + +static inline void +netdev_gso_partial_features_toggle(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->gso_partial_features = + netdev_gso_partial_features_xor(ndev, features); +} + +/* helpers for netdev features '& ~' operation */ +static inline netdev_features_t +netdev_features_andnot(const netdev_features_t a, const netdev_features_t b) +{ + return a & ~b; +} + +#define netdev_active_features_andnot(ndev, __features) \ + netdev_features_andnot(ndev->features, __features) + +#define netdev_hw_features_andnot(ndev, __features) \ + netdev_features_andnot(ndev->hw_features, __features) + +#define netdev_wanted_features_andnot(ndev, __features) \ + netdev_features_andnot(ndev->wanted_features, __features) + +#define netdev_vlan_features_andnot(ndev, __features) \ + netdev_features_andnot(ndev->vlan_features, __features) + +#define netdev_hw_enc_features_andnot(ndev, __features) \ + netdev_features_andnot(ndev->hw_enc_features, __features) + +#define netdev_mpls_features_andnot(ndev, __features) \ + netdev_features_andnot(ndev->mpls_features, __features) + +#define netdev_gso_partial_features_andnot(ndev, __features) \ + netdev_features_andnot(ndev->gso_partial_features, __features) + +#define netdev_active_features_andnot_r(ndev, __features) \ + netdev_features_andnot(__features, ndev->features) + +#define netdev_hw_features_andnot_r(ndev, __features) \ + netdev_features_andnot(__features, ndev->hw_features) + +#define netdev_wanted_features_andnot_r(ndev, __features) \ + netdev_features_andnot(__features, ndev->wanted_features) + +#define netdev_vlan_features_andnot_r(ndev, __features) \ + netdev_features_andnot(__features, ndev->vlan_features) + +#define netdev_hw_enc_features_andnot_r(ndev, __features) \ + netdev_features_andnot(__features, ndev->hw_enc_features) + +#define netdev_mpls_features_andnot_r(ndev, __features) \ + netdev_features_andnot(__features, ndev->mpls_features) + +#define netdev_gso_partial_features_andnot_r(ndev, __features) \ + netdev_features_andnot(__features, ndev->gso_partial_features) + +static inline void +netdev_features_clear(netdev_features_t *dst, const netdev_features_t features) +{ + *dst = netdev_features_andnot(*dst, features); +} + +static inline void +netdev_active_features_clear(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->features = netdev_active_features_andnot(ndev, features); +} + +static inline void +netdev_hw_features_clear(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_features = netdev_hw_features_andnot(ndev, features); +} + +static inline void +netdev_wanted_features_clear(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->wanted_features = netdev_wanted_features_andnot(ndev, features); +} + +static inline void +netdev_vlan_features_clear(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->vlan_features = netdev_vlan_features_andnot(ndev, features); +} + +static inline void +netdev_hw_enc_features_clear(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_enc_features = netdev_hw_enc_features_andnot(ndev, features); +} + +static inline void +netdev_mpls_features_clear(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->mpls_features = netdev_mpls_features_andnot(ndev, features); +} + +static inline void +netdev_gso_partial_features_clear(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->gso_partial_features = + netdev_gso_partial_features_andnot(ndev, features); +} + +/* helpers for netdev features 'set bit' operation */ +static inline void netdev_feature_add(int nr, netdev_features_t *src) +{ + *src |= __NETIF_F_BIT(nr); +} + +#define netdev_active_feature_add(ndev, nr) \ + netdev_feature_add(nr, &ndev->features) + +#define netdev_hw_feature_add(ndev, nr) \ + netdev_feature_add(nr, &ndev->hw_features) + +#define netdev_wanted_feature_add(ndev, nr) \ + netdev_feature_add(nr, &ndev->wanted_features) + +#define netdev_vlan_feature_add(ndev, nr) \ + netdev_feature_add(nr, &ndev->vlan_features) + +#define netdev_hw_enc_feature_add(ndev, nr) \ + netdev_feature_add(nr, &ndev->hw_enc_features) + +#define netdev_mpls_feature_add(ndev, nr) \ + netdev_feature_add(nr, &ndev->mpls_features) + +#define netdev_gso_partial_feature_add(ndev, nr) \ + netdev_feature_add(nr, &ndev->gso_partial_features) + +/* helpers for netdev features 'set bit array' operation */ +static inline void +netdev_features_set_array(const struct netdev_feature_set *set, + netdev_features_t *dst) +{ + int i; + + for (i = 0; i < set->cnt; i++) + netdev_feature_add(set->feature_bits[i], dst); +} + +#define netdev_active_features_set_array(ndev, set) \ + netdev_features_set_array(set, &ndev->features) + +#define netdev_hw_features_set_array(ndev, set) \ + netdev_features_set_array(set, &ndev->hw_features) + +#define netdev_wanted_features_set_array(ndev, set) \ + netdev_features_set_array(set, &ndev->wanted_features) + +#define netdev_vlan_features_set_array(ndev, set) \ + netdev_features_set_array(set, &ndev->vlan_features) + +#define netdev_hw_enc_features_set_array(ndev, set) \ + netdev_features_set_array(set, &ndev->hw_enc_features) + +#define netdev_mpls_features_set_array(ndev, set) \ + netdev_features_set_array(set, &ndev->mpls_features) + +#define netdev_gso_partial_features_set_array(ndev, set) \ + netdev_features_set_array(set, &ndev->gso_partial_features) + +/* helpers for netdev features 'clear bit' operation */ +static inline void netdev_feature_del(int nr, netdev_features_t *src) +{ + *src &= ~__NETIF_F_BIT(nr); +} + +#define netdev_active_feature_del(ndev, nr) \ + netdev_feature_del(nr, &ndev->features) + +#define netdev_hw_feature_del(ndev, nr) \ + netdev_feature_del(nr, &ndev->hw_features) + +#define netdev_wanted_feature_del(ndev, nr) \ + netdev_feature_del(nr, &ndev->wanted_features) + +#define netdev_vlan_feature_del(ndev, nr) \ + netdev_feature_del(nr, &ndev->vlan_features) + +#define netdev_hw_enc_feature_del(ndev, nr) \ + netdev_feature_del(nr, &ndev->hw_enc_features) + +#define netdev_mpls_feature_del(ndev, nr) \ + netdev_feature_del(nr, &ndev->mpls_features) + +#define netdev_gso_partial_feature_del(ndev, nr) \ + netdev_feature_del(nr, &ndev->gso_partial_features) + +static inline bool netdev_features_intersects(const netdev_features_t src1, + const netdev_features_t src2) +{ + return (src1 & src2) > 0; +} + +#define netdev_active_features_intersects(ndev, __features) \ + netdev_features_intersects(ndev->features, __features) + +#define netdev_hw_features_intersects(ndev, __features) \ + netdev_features_intersects(ndev->hw_features, __features) + +#define netdev_wanted_features_intersects(ndev, __features) \ + netdev_features_intersects(ndev->wanted_features, __features) + +#define netdev_vlan_features_intersects(ndev, __features) \ + netdev_features_intersects(ndev->vlan_features, __features) + +#define netdev_hw_enc_features_intersects(ndev, __features) \ + netdev_features_intersects(ndev->hw_enc_features, __features) + +#define netdev_mpls_features_intersects(ndev, __features) \ + netdev_features_intersects(ndev->mpls_features, __features) + +#define netdev_gso_partial_features_intersects(ndev, __features) \ + netdev_features_intersects(ndev->gso_partial_features, __features) + +/* helpers for netdev features '=' operation */ +static inline void netdev_active_features_copy(struct net_device *netdev, + const netdev_features_t src) +{ + netdev->features = src; +} + +static inline void netdev_hw_features_copy(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->hw_features = src; +} + +static inline void netdev_wanted_features_copy(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->wanted_features = src; +} + +static inline void netdev_vlan_features_copy(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->vlan_features = src; +} + +static inline void netdev_hw_enc_features_copy(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->hw_enc_features = src; +} + +static inline void netdev_mpls_features_copy(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->mpls_features = src; +} + +static inline void netdev_gso_partial_features_copy(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->gso_partial_features = src; +} + +/* helpers for netdev features 'get' operation */ +#define netdev_active_features(ndev) ((ndev)->features) +#define netdev_hw_features(ndev) ((ndev)->hw_features) +#define netdev_wanted_features(ndev) ((ndev)->wanted_features) +#define netdev_vlan_features(ndev) ((ndev)->vlan_features) +#define netdev_hw_enc_features(ndev) ((ndev)->hw_enc_features) +#define netdev_mpls_features(ndev) ((ndev)->mpls_features) +#define netdev_gso_partial_features(ndev) ((ndev)->gso_partial_features) + +/* helpers for netdev features 'subset' */ +static inline bool netdev_features_subset(const netdev_features_t src1, + const netdev_features_t src2) +{ + return (src1 & src2) == src2; +} + +static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, + netdev_features_t f2) +{ + if ((f1 ^ f2) & NETIF_F_HW_CSUM) { + if (f1 & NETIF_F_HW_CSUM) + f1 |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + else + f2 |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + } + + return f1 & f2; +} + +static inline netdev_features_t +netdev_get_wanted_features(struct net_device *dev) +{ + return (dev->features & ~dev->hw_features) | dev->wanted_features; +} + +#endif diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7b2a0b739684..a092423653e2 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2304,6 +2304,33 @@ struct net_device { }; #define to_net_dev(d) container_of(d, struct net_device, dev)
+/* helpers for netdev features 'test bit' operation */ +static inline bool netdev_feature_test(int nr, const netdev_features_t src) +{ + return (src & __NETIF_F_BIT(nr)) > 0; +} + +#define netdev_active_feature_test(ndev, nr) \ + netdev_feature_test(nr, ndev->features) + +#define netdev_hw_feature_test(ndev, nr) \ + netdev_feature_test(nr, ndev->hw_features) + +#define netdev_wanted_feature_test(ndev, nr) \ + netdev_feature_test(nr, ndev->wanted_features) + +#define netdev_vlan_feature_test(ndev, nr) \ + netdev_feature_test(nr, ndev->vlan_features) + +#define netdev_hw_enc_feature_test(ndev, nr) \ + netdev_feature_test(nr, ndev->hw_enc_features) + +#define netdev_mpls_feature_test(ndev, nr) \ + netdev_feature_test(nr, ndev->mpls_features) + +#define netdev_gso_partial_feature_test(ndev, nr) \ + netdev_feature_test(nr, ndev->gso_partial_features) + static inline bool netif_elide_gro(const struct net_device *dev) { if (!(dev->features & NETIF_F_GRO) || dev->xdp_prog) @@ -4815,24 +4842,6 @@ const char *netdev_drivername(const struct net_device *dev);
void linkwatch_run_queue(void);
-static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, - netdev_features_t f2) -{ - if ((f1 ^ f2) & NETIF_F_HW_CSUM) { - if (f1 & NETIF_F_HW_CSUM) - f1 |= (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); - else - f2 |= (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); - } - - return f1 & f2; -} - -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 netdev_increment_features(netdev_features_t all, netdev_features_t one, netdev_features_t mask);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index e5d23e75572a..2c9b353f13e8 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -24,6 +24,7 @@ #include <linux/net_tstamp.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> +#include <linux/netdev_features_helper.h> #include <linux/phy.h> #include <net/arp.h>
diff --git a/net/core/dev.c b/net/core/dev.c index d5a362d53b34..4d6b57752eee 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -88,6 +88,7 @@ #include <linux/interrupt.h> #include <linux/if_ether.h> #include <linux/netdevice.h> +#include <linux/netdev_features_helper.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/skbuff.h>
From: Jian Shen shenjian15@huawei.com Date: Tue, 19 Apr 2022 10:21:48 +0800
I suggest using `const` here. Those sets are needed only to initialize bitmaps, that's it. They are not supposed to be modified. This would be one more hardening here to avoid some weird usages of sets, and also would place them in .rodata instead of just .data.
Function old new delta main 35 33 -2 Total: Before=78, After=76, chg -2.56% add/remove: 0/2 grow/shrink: 0/0 up/down: 0/-14 (-14) Data old new delta arr1 6 - -6 arr2 8 - -8 Total: Before=15, After=1, chg -93.33% add/remove: 2/0 grow/shrink: 0/0 up/down: 14/0 (14) RO Data old new delta arr1 - 8 +8 arr2 - 6 +6 Total: Before=36, After=50, chg +38.89%
As you can see, there's a 2-byte code optimization. And that was just a simpliest oneliner. The gains will be much bigger from the real usages.
The problem with the current macro is that it doesn't allow to declare feature sets as static. Because the temporary array for counting the number of bits goes first, and doing
static DECLARE_NETDEV_FEATURE_SET();
wouldn't change anything. But we want to have most feature sets static as they will be needed only inside one file. Making every of them global would hurt optimization.
At the end, I came to
#define DECLARE_NETDEV_FEATURE_SET(name, features...) \ const struct netdev_feature_set name = { \ .feature_bits = { features }, \ .cnt = sizeof((u16 []){ features }) / sizeof(u16), \ }
because ARRAY_SIZE() can be taken only from a variable, not from a compound literal. But this one is actually OK. We don't need ARRAY_SIZE() in here since we define an unnamed array of an explicit type that we know for sure inline. So there's no chance to do it wrong as long as the @features argument is correct.
The ability to make it static is important. For example, when I marked them both static, I got
add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0) Function old new delta Total: Before=76, After=76, chg +0.00% add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0) Data old new delta Total: Before=1, After=1, chg +0.00% add/remove: 0/2 grow/shrink: 0/0 up/down: 0/-14 (-14) RO Data old new delta arr1 6 - -6 arr2 8 - -8 Total: Before=50, After=36, chg -28.00%
i.e. both of the sets were removed, because my main() was:
printf("cnt1: %u, cnt2: %u\n", arr1.cnt, arr2.cnt);
The compiler saw that I don't use them, except for printing values which are actually compile-time constants, and wiped them. Previously, they were global so it didn't have a clue if they're used anywhere else. This was a simple stupid example, but it will bring a lot more value in real use cases. So please consider my variant :D
--- 8< ---
-- 2.33.0
Thanks, Al
There are many netdev_features bits group used in kernel. The definition will be illegal when using feature bit more than 64. Replace these macroes with global netdev_features variables, initialize them when netdev module init.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/wireguard/device.c | 10 +- include/linux/netdev_features.h | 102 +++++++++----- net/core/Makefile | 2 +- net/core/dev.c | 87 ++++++++++++ net/core/netdev_features.c | 241 ++++++++++++++++++++++++++++++++ 5 files changed, 400 insertions(+), 42 deletions(-) create mode 100644 net/core/netdev_features.c
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 0fad1331303c..bca987ed02c9 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -273,9 +273,9 @@ static const struct device_type device_type = { .name = KBUILD_MODNAME }; static void wg_setup(struct net_device *dev) { struct wg_device *wg = netdev_priv(dev); - enum { WG_NETDEV_FEATURES = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | + netdev_features_t wg_netdev_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO | - NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA }; + NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA; const int overhead = MESSAGE_MINIMUM_LENGTH + sizeof(struct udphdr) + max(sizeof(struct ipv6hdr), sizeof(struct iphdr));
@@ -289,9 +289,9 @@ static void wg_setup(struct net_device *dev) dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->priv_flags |= IFF_NO_QUEUE; dev->features |= NETIF_F_LLTX; - dev->features |= WG_NETDEV_FEATURES; - dev->hw_features |= WG_NETDEV_FEATURES; - dev->hw_enc_features |= WG_NETDEV_FEATURES; + dev->features |= wg_netdev_features; + dev->hw_features |= wg_netdev_features; + dev->hw_enc_features |= wg_netdev_features; dev->mtu = ETH_DATA_LEN - overhead; dev->max_mtu = round_down(INT_MAX, MESSAGE_PADDING_MULTIPLE) - overhead;
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index e2b66fa3d7d6..16b2313e1dec 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -7,6 +7,7 @@
#include <linux/types.h> #include <linux/bitops.h> +#include <linux/cache.h> #include <asm/byteorder.h>
typedef u64 netdev_features_t; @@ -113,6 +114,55 @@ enum { /**/NETDEV_FEATURE_COUNT };
+extern netdev_features_t netdev_ethtool_features __ro_after_init; +extern netdev_features_t netdev_never_change_features __ro_after_init; +extern netdev_features_t netdev_gso_features_mask __ro_after_init; +extern netdev_features_t netdev_ip_csum_features __ro_after_init; +extern netdev_features_t netdev_csum_features_mask __ro_after_init; +extern netdev_features_t netdev_general_tso_features __ro_after_init; +extern netdev_features_t netdev_all_tso_features __ro_after_init; +extern netdev_features_t netdev_tso_ecn_features __ro_after_init; +extern netdev_features_t netdev_all_fcoe_features __ro_after_init; +extern netdev_features_t netdev_gso_software_features __ro_after_init; +extern netdev_features_t netdev_one_for_all_features __ro_after_init; +extern netdev_features_t netdev_all_for_all_features __ro_after_init; +extern netdev_features_t netdev_upper_disable_features __ro_after_init; +extern netdev_features_t netdev_soft_features __ro_after_init; +extern netdev_features_t netdev_soft_off_features __ro_after_init; +extern netdev_features_t netdev_all_vlan_features __ro_after_init; +extern netdev_features_t netdev_rx_vlan_features __ro_after_init; +extern netdev_features_t netdev_tx_vlan_features __ro_after_init; +extern netdev_features_t netdev_ctag_vlan_features __ro_after_init; +extern netdev_features_t netdev_stag_vlan_features __ro_after_init; +extern netdev_features_t netdev_vlan_filter_features __ro_after_init; +extern netdev_features_t netdev_gso_encap_all_features __ro_after_init; +extern netdev_features_t netdev_xfrm_features __ro_after_init; +extern netdev_features_t netdev_tls_features __ro_after_init; +extern netdev_features_t netdev_csum_gso_features_mask __ro_after_init; +extern struct netdev_feature_set netif_f_never_change_feature_set; +extern struct netdev_feature_set netif_f_gso_feature_set_mask; +extern struct netdev_feature_set netif_f_ip_csum_feature_set; +extern struct netdev_feature_set netif_f_csum_feature_set_mask; +extern struct netdev_feature_set netif_f_general_tso_feature_set; +extern struct netdev_feature_set netif_f_all_tso_feature_set; +extern struct netdev_feature_set netif_f_tso_ecn_feature_set; +extern struct netdev_feature_set netif_f_all_fcoe_feature_set; +extern struct netdev_feature_set netif_f_gso_soft_feature_set; +extern struct netdev_feature_set netif_f_one_for_all_feature_set; +extern struct netdev_feature_set netif_f_all_for_all_feature_set; +extern struct netdev_feature_set netif_f_upper_disables_feature_set; +extern struct netdev_feature_set netif_f_soft_feature_set; +extern struct netdev_feature_set netif_f_soft_off_feature_set; +extern struct netdev_feature_set netif_f_vlan_feature_set; +extern struct netdev_feature_set netif_f_tx_vlan_feature_set; +extern struct netdev_feature_set netif_f_rx_vlan_feature_set; +extern struct netdev_feature_set netif_f_vlan_filter_feature_set; +extern struct netdev_feature_set netif_f_ctag_vlan_feature_set; +extern struct netdev_feature_set netif_f_stag_vlan_feature_set; +extern struct netdev_feature_set netif_f_gso_encap_feature_set; +extern struct netdev_feature_set netif_f_xfrm_feature_set; +extern struct netdev_feature_set netif_f_tls_feature_set; + /* copy'n'paste compression ;) */ #define __NETIF_F_BIT(bit) ((netdev_features_t)1 << (bit)) #define __NETIF_F(name) __NETIF_F_BIT(NETIF_F_##name##_BIT) @@ -204,73 +254,53 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)
/* Features valid for ethtool to change */ /* = all defined minus driver/device-class-related */ -#define NETIF_F_NEVER_CHANGE (NETIF_F_VLAN_CHALLENGED | \ - NETIF_F_LLTX | NETIF_F_NETNS_LOCAL) +#define NETIF_F_NEVER_CHANGE netdev_never_change_features
/* remember that ((t)1 << t_BITS) is undefined in C99 */ -#define NETIF_F_ETHTOOL_BITS ((__NETIF_F_BIT(NETDEV_FEATURE_COUNT - 1) | \ - (__NETIF_F_BIT(NETDEV_FEATURE_COUNT - 1) - 1)) & \ - ~NETIF_F_NEVER_CHANGE) +#define NETIF_F_ETHTOOL_BITS netdev_ethtool_features
/* Segmentation offload feature mask */ -#define NETIF_F_GSO_MASK (__NETIF_F_BIT(NETIF_F_GSO_LAST + 1) - \ - __NETIF_F_BIT(NETIF_F_GSO_SHIFT)) +#define NETIF_F_GSO_MASK netdev_gso_features_mask
/* List of IP checksum features. Note that NETIF_F_HW_CSUM should not be * set in features when NETIF_F_IP_CSUM or NETIF_F_IPV6_CSUM are set-- * this would be contradictory */ -#define NETIF_F_CSUM_MASK (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ - NETIF_F_HW_CSUM) +#define NETIF_F_CSUM_MASK netdev_csum_features_mask
-#define NETIF_F_ALL_TSO (NETIF_F_TSO | NETIF_F_TSO6 | \ - NETIF_F_TSO_ECN | NETIF_F_TSO_MANGLEID) +#define NETIF_F_ALL_TSO netdev_all_tso_features
-#define NETIF_F_ALL_FCOE (NETIF_F_FCOE_CRC | NETIF_F_FCOE_MTU | \ - NETIF_F_FSO) +#define NETIF_F_ALL_FCOE netdev_all_fcoe_features
/* List of features with software fallbacks. */ -#define NETIF_F_GSO_SOFTWARE (NETIF_F_ALL_TSO | NETIF_F_GSO_SCTP | \ - NETIF_F_GSO_UDP_L4 | NETIF_F_GSO_FRAGLIST) +#define NETIF_F_GSO_SOFTWARE netdev_gso_software_features
/* * If one device supports one of these features, then enable them * for all in netdev_increment_features. */ -#define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \ - NETIF_F_SG | NETIF_F_HIGHDMA | \ - NETIF_F_FRAGLIST | NETIF_F_VLAN_CHALLENGED) +#define NETIF_F_ONE_FOR_ALL netdev_one_for_all_features
/* * If one device doesn't support one of these features, then disable it * for all in netdev_increment_features. */ -#define NETIF_F_ALL_FOR_ALL (NETIF_F_NOCACHE_COPY | NETIF_F_FSO) +#define NETIF_F_ALL_FOR_ALL netdev_all_for_all_features
/* * If upper/master device has these features disabled, they must be disabled * on all lower/slave devices as well. */ -#define NETIF_F_UPPER_DISABLES NETIF_F_LRO +#define NETIF_F_UPPER_DISABLES netdev_upper_disable_features
/* changeable features with no special hardware requirements */ -#define NETIF_F_SOFT_FEATURES (NETIF_F_GSO | NETIF_F_GRO) +#define NETIF_F_SOFT_FEATURES netdev_soft_features
/* Changeable features with no special hardware requirements that defaults to off. */ -#define NETIF_F_SOFT_FEATURES_OFF (NETIF_F_GRO_FRAGLIST | NETIF_F_GRO_UDP_FWD) - -#define NETIF_F_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_FILTER | \ - NETIF_F_HW_VLAN_CTAG_RX | \ - NETIF_F_HW_VLAN_CTAG_TX | \ - NETIF_F_HW_VLAN_STAG_FILTER | \ - NETIF_F_HW_VLAN_STAG_RX | \ - NETIF_F_HW_VLAN_STAG_TX) - -#define NETIF_F_GSO_ENCAP_ALL (NETIF_F_GSO_GRE | \ - NETIF_F_GSO_GRE_CSUM | \ - NETIF_F_GSO_IPXIP4 | \ - NETIF_F_GSO_IPXIP6 | \ - NETIF_F_GSO_UDP_TUNNEL | \ - NETIF_F_GSO_UDP_TUNNEL_CSUM) +#define NETIF_F_SOFT_FEATURES_OFF netdev_soft_off_features + +#define NETIF_F_VLAN_FEATURES netdev_all_vlan_features + +#define NETIF_F_GSO_ENCAP_ALL netdev_gso_encap_all_features
#endif /* _LINUX_NETDEV_FEATURES_H */ diff --git a/net/core/Makefile b/net/core/Makefile index a8e4f737692b..9d2127d25d72 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o obj-y += dev.o dev_addr_lists.o dst.o netevent.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ - fib_notifier.o xdp.o flow_offload.o gro.o + fib_notifier.o xdp.o flow_offload.o gro.o netdev_features.o
obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o
diff --git a/net/core/dev.c b/net/core/dev.c index 4d6b57752eee..85bb418e8ef1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -146,6 +146,7 @@ #include <linux/sctp.h> #include <net/udp_tunnel.h> #include <linux/net_namespace.h> +#include <linux/netdev_features_helper.h> #include <linux/indirect_call_wrapper.h> #include <net/devlink.h> #include <linux/pm_runtime.h> @@ -11255,6 +11256,90 @@ static struct pernet_operations __net_initdata default_device_ops = { .exit_batch = default_device_exit_batch, };
+static void netdev_features_init(void) +{ + netdev_features_t features; + + netdev_features_set_array(&netif_f_never_change_feature_set, + &netdev_never_change_features); + + netdev_features_set_array(&netif_f_gso_feature_set_mask, + &netdev_gso_features_mask); + + netdev_features_set_array(&netif_f_ip_csum_feature_set, + &netdev_ip_csum_features); + + netdev_features_set_array(&netif_f_csum_feature_set_mask, + &netdev_csum_features_mask); + + netdev_features_set_array(&netif_f_general_tso_feature_set, + &netdev_general_tso_features); + + netdev_features_set_array(&netif_f_all_tso_feature_set, + &netdev_all_tso_features); + + netdev_features_set_array(&netif_f_tso_ecn_feature_set, + &netdev_tso_ecn_features); + + netdev_features_set_array(&netif_f_all_fcoe_feature_set, + &netdev_all_fcoe_features); + + netdev_features_set_array(&netif_f_gso_soft_feature_set, + &netdev_gso_software_features); + + netdev_features_set_array(&netif_f_one_for_all_feature_set, + &netdev_one_for_all_features); + + netdev_features_set_array(&netif_f_all_for_all_feature_set, + &netdev_all_for_all_features); + + netdev_features_set_array(&netif_f_upper_disables_feature_set, + &netdev_upper_disable_features); + + netdev_features_set_array(&netif_f_soft_feature_set, + &netdev_soft_features); + + netdev_features_set_array(&netif_f_soft_off_feature_set, + &netdev_soft_off_features); + + netdev_features_set_array(&netif_f_rx_vlan_feature_set, + &netdev_rx_vlan_features); + + netdev_features_set_array(&netif_f_tx_vlan_feature_set, + &netdev_tx_vlan_features); + + netdev_features_set_array(&netif_f_vlan_filter_feature_set, + &netdev_vlan_filter_features); + + netdev_all_vlan_features = netdev_rx_vlan_features; + netdev_features_set(&netdev_all_vlan_features, netdev_tx_vlan_features); + netdev_features_set(&netdev_all_vlan_features, + netdev_vlan_filter_features); + + netdev_features_set_array(&netif_f_ctag_vlan_feature_set, + &netdev_ctag_vlan_features); + + netdev_features_set_array(&netif_f_stag_vlan_feature_set, + &netdev_stag_vlan_features); + + netdev_features_set_array(&netif_f_gso_encap_feature_set, + &netdev_gso_encap_all_features); + + netdev_features_set_array(&netif_f_xfrm_feature_set, + &netdev_xfrm_features); + + netdev_features_set_array(&netif_f_tls_feature_set, + &netdev_tls_features); + + netdev_csum_gso_features_mask = + netdev_features_or(netdev_gso_software_features, + netdev_csum_features_mask); + + netdev_features_fill(&features); + netdev_ethtool_features = + netdev_features_andnot(features, netdev_never_change_features); +} + /* * Initialize the DEV module. At boot time this walks the device list and * unhooks any devices that fail to initialise (normally hardware not @@ -11285,6 +11370,8 @@ static int __init net_dev_init(void) if (register_pernet_subsys(&netdev_net_ops)) goto out;
+ netdev_features_init(); + /* * Initialise the packet receive queues. */ diff --git a/net/core/netdev_features.c b/net/core/netdev_features.c new file mode 100644 index 000000000000..db870038213a --- /dev/null +++ b/net/core/netdev_features.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Network device features. + */ + +#include <linux/netdev_features.h> +#include <linux/netdev_features_helper.h> + +netdev_features_t netdev_ethtool_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_ethtool_features); + +netdev_features_t netdev_never_change_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_never_change_features); + +netdev_features_t netdev_gso_features_mask __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_gso_features_mask); + +netdev_features_t netdev_ip_csum_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_ip_csum_features); + +netdev_features_t netdev_csum_features_mask __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_csum_features_mask); + +netdev_features_t netdev_general_tso_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_general_tso_features); + +netdev_features_t netdev_all_tso_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_all_tso_features); + +netdev_features_t netdev_tso_ecn_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_tso_ecn_features); + +netdev_features_t netdev_all_fcoe_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_all_fcoe_features); + +netdev_features_t netdev_gso_software_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_gso_software_features); + +netdev_features_t netdev_one_for_all_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_one_for_all_features); + +netdev_features_t netdev_all_for_all_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_all_for_all_features); + +netdev_features_t netdev_upper_disable_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_upper_disable_features); + +netdev_features_t netdev_soft_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_soft_features); + +netdev_features_t netdev_soft_off_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_soft_off_features); + +netdev_features_t netdev_all_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_all_vlan_features); + +netdev_features_t netdev_vlan_filter_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_vlan_filter_features); + +netdev_features_t netdev_rx_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_rx_vlan_features); + +netdev_features_t netdev_tx_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_tx_vlan_features); + +netdev_features_t netdev_ctag_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_ctag_vlan_features); + +netdev_features_t netdev_stag_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_stag_vlan_features); + +netdev_features_t netdev_gso_encap_all_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_gso_encap_all_features); + +netdev_features_t netdev_xfrm_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_xfrm_features); + +netdev_features_t netdev_tls_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_tls_features); + +netdev_features_t netdev_csum_gso_features_mask __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_csum_gso_features_mask); + +DECLARE_NETDEV_FEATURE_SET(netif_f_never_change_feature_set, + NETIF_F_VLAN_CHALLENGED_BIT, + NETIF_F_LLTX_BIT, + NETIF_F_NETNS_LOCAL_BIT); +EXPORT_SYMBOL_GPL(netif_f_never_change_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_gso_feature_set_mask, + NETIF_F_TSO_BIT, + NETIF_F_GSO_ROBUST_BIT, + NETIF_F_TSO_ECN_BIT, + NETIF_F_TSO_MANGLEID_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_FSO_BIT, + NETIF_F_GSO_GRE_BIT, + NETIF_F_GSO_GRE_CSUM_BIT, + NETIF_F_GSO_IPXIP4_BIT, + NETIF_F_GSO_IPXIP6_BIT, + NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, + NETIF_F_GSO_PARTIAL_BIT, + NETIF_F_GSO_TUNNEL_REMCSUM_BIT, + NETIF_F_GSO_SCTP_BIT, + NETIF_F_GSO_ESP_BIT, + NETIF_F_GSO_UDP_BIT, + NETIF_F_GSO_UDP_L4_BIT, + NETIF_F_GSO_FRAGLIST_BIT); +EXPORT_SYMBOL_GPL(netif_f_gso_feature_set_mask); + +DECLARE_NETDEV_FEATURE_SET(netif_f_ip_csum_feature_set, + NETIF_F_IP_CSUM_BIT, + NETIF_F_IPV6_CSUM_BIT); +EXPORT_SYMBOL_GPL(netif_f_ip_csum_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_csum_feature_set_mask, + NETIF_F_IP_CSUM_BIT, + NETIF_F_IPV6_CSUM_BIT, + NETIF_F_HW_CSUM_BIT); +EXPORT_SYMBOL_GPL(netif_f_csum_feature_set_mask); + +DECLARE_NETDEV_FEATURE_SET(netif_f_general_tso_feature_set, + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT); +EXPORT_SYMBOL_GPL(netif_f_general_tso_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_all_tso_feature_set, + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_TSO_ECN_BIT, + NETIF_F_TSO_MANGLEID_BIT); +EXPORT_SYMBOL_GPL(netif_f_all_tso_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_tso_ecn_feature_set, + NETIF_F_TSO_ECN_BIT); +EXPORT_SYMBOL_GPL(netif_f_tso_ecn_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_all_fcoe_feature_set, + NETIF_F_FCOE_CRC_BIT, + NETIF_F_FCOE_MTU_BIT, + NETIF_F_FSO_BIT); +EXPORT_SYMBOL_GPL(netif_f_all_fcoe_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_gso_soft_feature_set, + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_TSO_ECN_BIT, + NETIF_F_TSO_MANGLEID_BIT, + NETIF_F_GSO_SCTP_BIT, + NETIF_F_GSO_UDP_L4_BIT, + NETIF_F_GSO_FRAGLIST_BIT); +EXPORT_SYMBOL_GPL(netif_f_gso_soft_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_one_for_all_feature_set, + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_TSO_ECN_BIT, + NETIF_F_TSO_MANGLEID_BIT, + NETIF_F_GSO_SCTP_BIT, + NETIF_F_GSO_UDP_L4_BIT, + NETIF_F_GSO_FRAGLIST_BIT, + NETIF_F_GSO_ROBUST_BIT, + NETIF_F_SG_BIT, + NETIF_F_HIGHDMA_BIT, + NETIF_F_FRAGLIST_BIT, + NETIF_F_VLAN_CHALLENGED); +EXPORT_SYMBOL_GPL(netif_f_one_for_all_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_all_for_all_feature_set, + NETIF_F_NOCACHE_COPY_BIT, + NETIF_F_FSO_BIT); +EXPORT_SYMBOL_GPL(netif_f_all_for_all_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_upper_disables_feature_set, + NETIF_F_LRO_BIT); +EXPORT_SYMBOL_GPL(netif_f_upper_disables_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_soft_feature_set, + NETIF_F_GSO_BIT, + NETIF_F_GRO_BIT); +EXPORT_SYMBOL_GPL(netif_f_soft_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_soft_off_feature_set, + NETIF_F_GRO_FRAGLIST_BIT, + NETIF_F_GRO_UDP_FWD_BIT); +EXPORT_SYMBOL_GPL(netif_f_soft_off_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_vlan_feature_set, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + NETIF_F_HW_VLAN_CTAG_RX_BIT, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_HW_VLAN_STAG_FILTER_BIT, + NETIF_F_HW_VLAN_STAG_RX_BIT, + NETIF_F_HW_VLAN_STAG_TX_BIT); +EXPORT_SYMBOL_GPL(netif_f_vlan_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_tx_vlan_feature_set, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_HW_VLAN_STAG_TX_BIT); +EXPORT_SYMBOL_GPL(netif_f_tx_vlan_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_rx_vlan_feature_set, + NETIF_F_HW_VLAN_CTAG_RX_BIT, + NETIF_F_HW_VLAN_STAG_RX_BIT); +EXPORT_SYMBOL_GPL(netif_f_rx_vlan_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_vlan_filter_feature_set, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + NETIF_F_HW_VLAN_STAG_FILTER_BIT); +EXPORT_SYMBOL_GPL(netif_f_vlan_filter_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_ctag_vlan_feature_set, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_HW_VLAN_CTAG_RX_BIT); +EXPORT_SYMBOL_GPL(netif_f_ctag_vlan_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_stag_vlan_feature_set, + NETIF_F_HW_VLAN_STAG_TX_BIT, + NETIF_F_HW_VLAN_STAG_RX_BIT); +EXPORT_SYMBOL_GPL(netif_f_stag_vlan_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_gso_encap_feature_set, + NETIF_F_GSO_GRE_BIT, + NETIF_F_GSO_GRE_CSUM_BIT, + NETIF_F_GSO_IPXIP4_BIT, + NETIF_F_GSO_IPXIP6_BIT, + NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT); +EXPORT_SYMBOL_GPL(netif_f_gso_encap_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_xfrm_feature_set, + NETIF_F_HW_ESP_BIT, + NETIF_F_HW_ESP_TX_CSUM_BIT, + NETIF_F_GSO_ESP_BIT); +EXPORT_SYMBOL_GPL(netif_f_xfrm_feature_set); + +DECLARE_NETDEV_FEATURE_SET(netif_f_tls_feature_set, + NETIF_F_HW_TLS_TX_BIT, + NETIF_F_HW_TLS_RX_BIT); +EXPORT_SYMBOL_GPL(netif_f_tls_feature_set);
From: Jian Shen shenjian15@huawei.com Date: Tue, 19 Apr 2022 10:21:49 +0800
--- 8< ---
It is an initialization function, so it must be marked as __init.
I'm not sure it does make sense to have an empty newline between each call. I'd leave newlines only between the "regular" blocks and the "multi-call" blocks, I mean, stuff like VLAN, GSO and @netdev_ethtool_features.
--- 8< ---
-- 2.33.0
Thanks, Al
在 2022/4/19 22:49, Alexander Lobakin 写道:
right, I will add it, thanks!
At first, I added empty newline per call for the it used three lines. Now the new call just use two lines, I will remove some unnecessary blank lines.
Thanks!
From: shenjian (K) shenjian15@huawei.com Date: Wed, 20 Apr 2022 17:54:13 +0800
I see no news regarding the conversion since the end of April, maybe I could pick it and finish if nobody objects? I'll preserve the original authorship for sure.
Thanks, Olek
在 2022/7/20 23:09, Alexander Lobakin 写道:
Hi, Alexander
Sorry for late to finish the whole patchset with treewide changes, but I'm still working on it. And most of the convertsions have been completed. I will send to new patchset in two weeks.
Jian
From: shenjian (K) shenjian15@huawei.com Date: Thu, 21 Jul 2022 09:15:59 +0800
Oh okay, I was only worried that it could be abandoned for some reason. Great to hear it's almost done, 120+ drivers is not something quick or exciting :) I'll start reviewing the series, at least its "core" part, as soon as it hits netdev ML. Thanks!
Jian
+ &netdev_gso_features_mask);
[...]
Olek
在 2022/7/21 22:57, Alexander Lobakin 写道:
Thanks, I will speed up efforts.
I'll start reviewing the series, at least its "core" part, as soon as it hits netdev ML. Thanks!
Yes, It's need sufficient review, I want to get as many as possible advices for it. Thanks!
From: shenjian (K) shenjian15@huawei.com Date: Wed, 20 Apr 2022 17:54:13 +0800
I see no news regarding the conversion since the end of April, maybe I could pick it and finish if nobody objects? I'll preserve the original authorship for sure.
Thanks, Olek
From: shenjian (K) shenjian15@huawei.com Date: Wed, 20 Apr 2022 17:54:13 +0800
(sorry for the triple mail, at first References got screwed, then encoding =)
I see no news regarding the conversion since the end of April, maybe I could pick it and finish if nobody objects? I'll preserve the original authorship for sure.
Thanks, Olek
There are many netdev_features bits group used in drivers, replace them with netdev features array.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 44 ++++++++++++++----- drivers/net/ethernet/sfc/ef10.c | 11 ++++- drivers/net/ethernet/sfc/ef100_nic.c | 24 +++++++--- drivers/net/ethernet/sfc/efx.c | 21 ++++++--- drivers/net/ethernet/sfc/falcon/efx.c | 10 +++-- drivers/net/ethernet/sfc/falcon/net_driver.h | 1 + drivers/net/ethernet/sfc/net_driver.h | 1 + net/ethtool/ioctl.c | 17 +++++-- 8 files changed, 100 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 14dc12c2155d..74ebba5b9bc3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -12,6 +12,7 @@ #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/module.h> +#include <linux/netdev_features_helper.h> #include <linux/pci.h> #include <linux/aer.h> #include <linux/skbuff.h> @@ -3253,23 +3254,46 @@ static struct pci_driver hns3_driver = { .err_handler = &hns3_err_handler, };
+DECLARE_NETDEV_FEATURE_SET(hns3_default_feature_set, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + NETIF_F_HW_VLAN_CTAG_RX_BIT, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_RXCSUM_BIT, + NETIF_F_SG_BIT, + NETIF_F_GSO_BIT, + NETIF_F_GRO_BIT, + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_GSO_GRE_BIT, + NETIF_F_GSO_GRE_CSUM_BIT, + NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_SCTP_CRC_BIT, + NETIF_F_FRAGLIST); + +DECLARE_NETDEV_FEATURE_SET(hns3_vlan_off_feature_set, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + NETIF_F_HW_VLAN_CTAG_RX_BIT, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_GRO_HW_BIT, + NETIF_F_NTUPLE_BIT, + NETIF_F_HW_TC_BIT); + /* set default feature to hns3 */ static void hns3_set_default_feature(struct net_device *netdev) { struct hnae3_handle *h = hns3_get_handle(netdev); struct pci_dev *pdev = h->pdev; struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev); + netdev_features_t vlan_off_features; + netdev_features_t features;
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
- netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO | - NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE | - NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_SCTP_CRC | NETIF_F_FRAGLIST; + netdev_features_zero(&features); + netdev_features_set_array(&hns3_default_feature_set, &features); + netdev->features |= features;
if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { netdev->features |= NETIF_F_GRO_HW; @@ -3296,10 +3320,10 @@ static void hns3_set_default_feature(struct net_device *netdev) if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
- netdev->vlan_features |= netdev->features & - ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_GRO_HW | NETIF_F_NTUPLE | - NETIF_F_HW_TC); + 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;
netdev->hw_enc_features |= netdev->vlan_features | NETIF_F_TSO_MANGLEID; } diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 50d535981a35..bb31043902e4 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1301,6 +1301,12 @@ static void efx_ef10_fini_nic(struct efx_nic *efx) nic_data->mc_stats = NULL; }
+DECLARE_NETDEV_FEATURE_SET(ef10_tso_feature_set, + NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_GSO_GRE_BIT, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, + NETIF_F_GSO_GRE_CSUM_BIT); + static int efx_ef10_init_nic(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; @@ -1356,8 +1362,9 @@ static int efx_ef10_init_nic(struct efx_nic *efx) if (efx_has_cap(efx, TX_TSO_V2_ENCAP)) { netdev_features_t encap_tso_features;
- encap_tso_features = NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE | - NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM; + netdev_features_zero(&encap_tso_features); + netdev_features_set_array(&ef10_tso_feature_set, + &encap_tso_features);
hw_enc_features |= encap_tso_features | NETIF_F_TSO; efx->net_dev->features |= encap_tso_features; diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index a07cbf45a326..18bf6a33b355 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -147,6 +147,15 @@ static int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address) return 0; }
+DECLARE_NETDEV_FEATURE_SET(ef100_tso_feature_set, + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_GSO_PARTIAL_BIT, + NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, + NETIF_F_GSO_GRE_BIT, + NETIF_F_GSO_GRE_CSUM_BIT); + static int efx_ef100_init_datapath_caps(struct efx_nic *efx) { MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V7_OUT_LEN); @@ -185,10 +194,10 @@ static int efx_ef100_init_datapath_caps(struct efx_nic *efx)
if (efx_ef100_has_cap(nic_data->datapath_caps2, TX_TSO_V3)) { struct net_device *net_dev = efx->net_dev; - netdev_features_t tso = NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_PARTIAL | - NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_GRE | NETIF_F_GSO_GRE_CSUM; + netdev_features_t tso;
+ netdev_features_zero(&tso); + netdev_features_set_array(&ef100_tso_feature_set, &tso); net_dev->features |= tso; net_dev->hw_features |= tso; net_dev->hw_enc_features |= tso; @@ -1105,6 +1114,11 @@ static int ef100_check_design_params(struct efx_nic *efx) return rc; }
+DECLARE_NETDEV_FEATURE_SET(ef100_vlan_feature_set, + NETIF_F_HW_CSUM_BIT, + NETIF_F_SG_BIT, + NETIF_F_HIGHDMA_BIT); + /* NIC probe and remove */ static int ef100_probe_main(struct efx_nic *efx) @@ -1126,8 +1140,8 @@ static int ef100_probe_main(struct efx_nic *efx) net_dev->features |= efx->type->offload_features; net_dev->hw_features |= efx->type->offload_features; net_dev->hw_enc_features |= efx->type->offload_features; - net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_ALL_TSO; + net_dev->vlan_features |= NETIF_F_ALL_TSO; + netdev_vlan_features_set_array(net_dev, &ef100_vlan_feature_set);
/* Populate design-parameter defaults */ nic_data->tso_max_hdr_len = ESE_EF100_DP_GZ_TSO_MAX_HDR_LEN_DEFAULT; diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 302dc835ac3d..bd76e1c5f879 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -988,6 +988,18 @@ static int efx_pci_probe_main(struct efx_nic *efx) return rc; }
+DECLARE_NETDEV_FEATURE_SET(efx_active_feature_set, + NETIF_F_SG_BIT, + NETIF_F_TSO_BIT, + NETIF_F_RXCSUM_BIT, + NETIF_F_RXALL_BIT); + +DECLARE_NETDEV_FEATURE_SET(efx_vlan_feature_set, + NETIF_F_HW_CSUM_BIT, + NETIF_F_SG_BIT, + NETIF_F_HIGHDMA_BIT, + NETIF_F_RXCSUM_BIT); + static int efx_pci_probe_post_io(struct efx_nic *efx) { struct net_device *net_dev = efx->net_dev; @@ -1004,17 +1016,16 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) }
/* Determine netdevice features */ - net_dev->features |= (efx->type->offload_features | NETIF_F_SG | - NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_RXALL); + 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)) net_dev->features |= NETIF_F_TSO6; /* Check whether device supports TSO */ if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) net_dev->features &= ~NETIF_F_ALL_TSO; /* Mask for features that also apply to VLAN devices */ - net_dev->vlan_features |= (NETIF_F_HW_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_ALL_TSO | - NETIF_F_RXCSUM); + 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;
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 60c595ef7589..eeae4edf4a47 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2859,6 +2859,12 @@ static int ef4_pci_probe_main(struct ef4_nic *efx) return rc; }
+DECLARE_NETDEV_FEATURE_SET(efx_vlan_feature_set, + NETIF_F_HW_CSUM_BIT, + NETIF_F_SG_BIT, + NETIF_F_HIGHDMA_BIT, + NETIF_F_RXCSUM_BIT); + /* NIC initialisation * * This is called at module load (or hotplug insertion, @@ -2907,9 +2913,7 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, net_dev->features |= (efx->type->offload_features | NETIF_F_SG | NETIF_F_RXCSUM); /* Mask for features that also apply to VLAN devices */ - net_dev->vlan_features |= (NETIF_F_HW_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_RXCSUM); - + netdev_vlan_features_set_array(net_dev, &efx_vlan_feature_set); net_dev->hw_features = net_dev->features & ~efx->fixed_features;
/* Disable VLAN filtering by default. It may be enforced if diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h index a381cf9ec4f3..e1c7e3098a95 100644 --- a/drivers/net/ethernet/sfc/falcon/net_driver.h +++ b/drivers/net/ethernet/sfc/falcon/net_driver.h @@ -26,6 +26,7 @@ #include <linux/vmalloc.h> #include <linux/i2c.h> #include <linux/mtd/mtd.h> +#include <linux/netdev_features_helper.h> #include <net/busy_poll.h>
#include "enum.h" diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index c75dc75e2857..2407fd4ef785 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -25,6 +25,7 @@ #include <linux/rwsem.h> #include <linux/vmalloc.h> #include <linux/mtd/mtd.h> +#include <linux/netdev_features_helper.h> #include <net/busy_poll.h> #include <net/xdp.h>
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 326e14ee05db..243ee8a0bd18 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -15,6 +15,7 @@ #include <linux/errno.h> #include <linux/ethtool.h> #include <linux/netdevice.h> +#include <linux/netdev_features_helper.h> #include <linux/net_tstamp.h> #include <linux/phy.h> #include <linux/bitops.h> @@ -288,9 +289,13 @@ static int ethtool_set_one_feature(struct net_device *dev,
#define ETH_ALL_FLAGS (ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | \ ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH) -#define ETH_ALL_FEATURES (NETIF_F_LRO | NETIF_F_HW_VLAN_CTAG_RX | \ - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_NTUPLE | \ - NETIF_F_RXHASH) + +DECLARE_NETDEV_FEATURE_SET(ethtool_all_feature_set, + NETIF_F_LRO_BIT, + NETIF_F_HW_VLAN_CTAG_RX_BIT, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_NTUPLE_BIT, + NETIF_F_RXHASH_BIT);
static u32 __ethtool_get_flags(struct net_device *dev) { @@ -313,6 +318,7 @@ static u32 __ethtool_get_flags(struct net_device *dev) static int __ethtool_set_flags(struct net_device *dev, u32 data) { netdev_features_t features = 0, changed; + netdev_features_t eth_all_features;
if (data & ~ETH_ALL_FLAGS) return -EINVAL; @@ -328,8 +334,11 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) if (data & ETH_FLAG_RXHASH) features |= NETIF_F_RXHASH;
+ netdev_features_zero(ð_all_features); + 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; + changed = (features ^ dev->features) & eth_all_features; if (changed & ~dev->hw_features) return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
There are some drivers(e.g. sfc) use netdev_features in global structure initialization. Changed the its netdev_features_t memeber to netdev_features_t *, and make it prefer to a netdev_features_t global variables.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/sfc/ef10.c | 11 +---- drivers/net/ethernet/sfc/ef100_nic.c | 15 +++---- drivers/net/ethernet/sfc/efx.c | 46 +++++++++++++++++++- drivers/net/ethernet/sfc/falcon/efx.c | 25 ++++++++++- drivers/net/ethernet/sfc/falcon/efx.h | 3 ++ drivers/net/ethernet/sfc/falcon/falcon.c | 4 +- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- drivers/net/ethernet/sfc/rx_common.c | 2 +- drivers/net/ethernet/sfc/rx_common.h | 4 ++ drivers/net/ethernet/sfc/siena.c | 3 +- 11 files changed, 87 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index bb31043902e4..63fc4c771955 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -4021,13 +4021,6 @@ static unsigned int efx_ef10_recycle_ring_size(const struct efx_nic *efx) return ret; }
-#define EF10_OFFLOAD_FEATURES \ - (NETIF_F_IP_CSUM | \ - NETIF_F_HW_VLAN_CTAG_FILTER | \ - NETIF_F_IPV6_CSUM | \ - NETIF_F_RXHASH | \ - NETIF_F_NTUPLE) - const struct efx_nic_type efx_hunt_a0_vf_nic_type = { .is_vf = true, .mem_bar = efx_ef10_vf_mem_bar, @@ -4128,7 +4121,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { .always_rx_scatter = true, .min_interrupt_mode = EFX_INT_MODE_MSIX, .timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH, - .offload_features = EF10_OFFLOAD_FEATURES, + .offload_features = &ef10_offload_features, .mcdi_max_ver = 2, .max_rx_ip_filters = EFX_MCDI_FILTER_TBL_ROWS, .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE | @@ -4266,7 +4259,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .option_descriptors = true, .min_interrupt_mode = EFX_INT_MODE_LEGACY, .timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH, - .offload_features = EF10_OFFLOAD_FEATURES, + .offload_features = &ef10_offload_features, .mcdi_max_ver = 2, .max_rx_ip_filters = EFX_MCDI_FILTER_TBL_ROWS, .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE | diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index 18bf6a33b355..679530f20bd6 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -714,16 +714,11 @@ static unsigned int efx_ef100_recycle_ring_size(const struct efx_nic *efx)
/* NIC level access functions */ -#define EF100_OFFLOAD_FEATURES (NETIF_F_HW_CSUM | NETIF_F_RXCSUM | \ - NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_NTUPLE | \ - NETIF_F_RXHASH | NETIF_F_RXFCS | NETIF_F_TSO_ECN | NETIF_F_RXALL | \ - NETIF_F_HW_VLAN_CTAG_TX) - const struct efx_nic_type ef100_pf_nic_type = { .revision = EFX_REV_EF100, .is_vf = false, .probe = ef100_probe_pf, - .offload_features = EF100_OFFLOAD_FEATURES, + .offload_features = &ef100_offload_features, .mcdi_max_ver = 2, .mcdi_request = ef100_mcdi_request, .mcdi_poll_response = ef100_mcdi_poll_response, @@ -809,7 +804,7 @@ const struct efx_nic_type ef100_vf_nic_type = { .revision = EFX_REV_EF100, .is_vf = true, .probe = ef100_probe_vf, - .offload_features = EF100_OFFLOAD_FEATURES, + .offload_features = &ef100_offload_features, .mcdi_max_ver = 2, .mcdi_request = ef100_mcdi_request, .mcdi_poll_response = ef100_mcdi_poll_response, @@ -1137,9 +1132,9 @@ static int ef100_probe_main(struct efx_nic *efx) return -ENOMEM; efx->nic_data = nic_data; nic_data->efx = efx; - net_dev->features |= efx->type->offload_features; - net_dev->hw_features |= efx->type->offload_features; - net_dev->hw_enc_features |= efx->type->offload_features; + net_dev->features |= *efx->type->offload_features; + net_dev->hw_features |= *efx->type->offload_features; + net_dev->hw_enc_features |= *efx->type->offload_features; net_dev->vlan_features |= NETIF_F_ALL_TSO; netdev_vlan_features_set_array(net_dev, &ef100_vlan_feature_set);
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index bd76e1c5f879..15a896f397f2 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1016,9 +1016,9 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) }
/* Determine netdevice features */ - net_dev->features |= efx->type->offload_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 | 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)) @@ -1289,6 +1289,46 @@ static struct pci_driver efx_pci_driver = { #endif };
+DECLARE_NETDEV_FEATURE_SET(ef10_offload_feature_set, + NETIF_F_IP_CSUM_BIT, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + NETIF_F_IPV6_CSUM_BIT, + NETIF_F_RXHASH_BIT, + NETIF_F_NTUPLE_BIT); + +DECLARE_NETDEV_FEATURE_SET(ef100_offload_feature_set, + NETIF_F_HW_CSUM_BIT, + NETIF_F_RXCSUM_BIT, + NETIF_F_HIGHDMA_BIT, + NETIF_F_SG_BIT, + NETIF_F_FRAGLIST_BIT, + NETIF_F_NTUPLE_BIT, + NETIF_F_RXHASH_BIT, + NETIF_F_RXFCS_BIT, + NETIF_F_TSO_ECN_BIT, + NETIF_F_RXALL_BIT, + NETIF_F_HW_VLAN_CTAG_TX_BIT); + +DECLARE_NETDEV_FEATURE_SET(siena_offload_feature_set, + NETIF_F_IP_CSUM_BIT, + NETIF_F_IPV6_CSUM_BIT, + NETIF_F_RXHASH_BIT, + NETIF_F_NTUPLE_BIT); + +netdev_features_t ef10_offload_features __ro_after_init; +netdev_features_t ef100_offload_features __ro_after_init; +netdev_features_t siena_offload_features __ro_after_init; + +static void efx_features_init(void) +{ + netdev_features_set_array(&ef10_offload_feature_set, + &ef10_offload_features); + netdev_features_set_array(&ef100_offload_feature_set, + &ef100_offload_features); + netdev_features_set_array(&siena_offload_feature_set, + &siena_offload_features); +} + /************************************************************************** * * Kernel module interface @@ -1323,6 +1363,8 @@ static int __init efx_init_module(void) if (rc < 0) goto err_pci_ef100;
+ efx_features_init(); + return 0;
err_pci_ef100: diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index eeae4edf4a47..7d2276aa2bf6 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -1694,7 +1694,7 @@ static int ef4_probe_filters(struct ef4_nic *efx) goto out_unlock;
#ifdef CONFIG_RFS_ACCEL - if (efx->type->offload_features & NETIF_F_NTUPLE) { + if (*efx->type->offload_features & NETIF_F_NTUPLE) { struct ef4_channel *channel; int i, success = 1;
@@ -2910,7 +2910,7 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, if (rc) goto fail3;
- net_dev->features |= (efx->type->offload_features | NETIF_F_SG | + net_dev->features |= (*efx->type->offload_features | NETIF_F_SG | NETIF_F_RXCSUM); /* Mask for features that also apply to VLAN devices */ netdev_vlan_features_set_array(net_dev, &efx_vlan_feature_set); @@ -3174,6 +3174,25 @@ static struct pci_driver ef4_pci_driver = { .err_handler = &ef4_err_handlers, };
+DECLARE_NETDEV_FEATURE_SET(falcon_b0_offload_feature_set, + NETIF_F_IP_CSUM_BIT, + NETIF_F_RXHASH_BIT, + NETIF_F_NTUPLE_BIT); + +DECLARE_NETDEV_FEATURE_SET(falcon_a1_offload_feature_set, + NETIF_F_IP_CSUM_BIT); + +netdev_features_t falcon_b0_offload_features __ro_after_init; +netdev_features_t falcon_a1_offload_features __ro_after_init; + +static void ef4_features_init(void) +{ + netdev_features_set_array(&falcon_b0_offload_feature_set, + &falcon_b0_offload_features); + netdev_features_set_array(&falcon_a1_offload_feature_set, + &falcon_a1_offload_features); +} + /************************************************************************** * * Kernel module interface @@ -3204,6 +3223,8 @@ static int __init ef4_init_module(void) if (rc < 0) goto err_pci;
+ ef4_features_init(); + return 0;
err_pci: diff --git a/drivers/net/ethernet/sfc/falcon/efx.h b/drivers/net/ethernet/sfc/falcon/efx.h index d3b4646545fa..f31b5c6e02bc 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.h +++ b/drivers/net/ethernet/sfc/falcon/efx.h @@ -271,4 +271,7 @@ static inline bool ef4_rwsem_assert_write_locked(struct rw_semaphore *sem) return true; }
+extern netdev_features_t falcon_b0_offload_features __ro_after_init; +extern netdev_features_t falcon_a1_offload_features __ro_after_init; + #endif /* EF4_EFX_H */ diff --git a/drivers/net/ethernet/sfc/falcon/falcon.c b/drivers/net/ethernet/sfc/falcon/falcon.c index 3324a6219a09..fda25f3f8e66 100644 --- a/drivers/net/ethernet/sfc/falcon/falcon.c +++ b/drivers/net/ethernet/sfc/falcon/falcon.c @@ -2799,7 +2799,7 @@ const struct ef4_nic_type falcon_a1_nic_type = { .can_rx_scatter = false, .max_interrupt_mode = EF4_INT_MODE_MSI, .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, - .offload_features = NETIF_F_IP_CSUM, + .offload_features = &falcon_a1_offload_features, };
const struct ef4_nic_type falcon_b0_nic_type = { @@ -2898,6 +2898,6 @@ const struct ef4_nic_type falcon_b0_nic_type = { .can_rx_scatter = true, .max_interrupt_mode = EF4_INT_MODE_MSIX, .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, - .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, + .offload_features = &falcon_b0_offload_features, .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, }; diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h index e1c7e3098a95..26aff929c6d2 100644 --- a/drivers/net/ethernet/sfc/falcon/net_driver.h +++ b/drivers/net/ethernet/sfc/falcon/net_driver.h @@ -1154,7 +1154,7 @@ struct ef4_nic_type { bool always_rx_scatter; unsigned int max_interrupt_mode; unsigned int timer_period_max; - netdev_features_t offload_features; + const netdev_features_t *offload_features; unsigned int max_rx_ip_filters; };
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 2407fd4ef785..6b52f2924bf7 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1480,7 +1480,7 @@ struct efx_nic_type { bool option_descriptors; unsigned int min_interrupt_mode; unsigned int timer_period_max; - netdev_features_t offload_features; + const netdev_features_t *offload_features; int mcdi_max_ver; unsigned int max_rx_ip_filters; u32 hwtstamp_filters; diff --git a/drivers/net/ethernet/sfc/rx_common.c b/drivers/net/ethernet/sfc/rx_common.c index 1b22c7be0088..acdc3c84aaaa 100644 --- a/drivers/net/ethernet/sfc/rx_common.c +++ b/drivers/net/ethernet/sfc/rx_common.c @@ -796,7 +796,7 @@ int efx_probe_filters(struct efx_nic *efx) goto out_unlock;
#ifdef CONFIG_RFS_ACCEL - if (efx->type->offload_features & NETIF_F_NTUPLE) { + if (*efx->type->offload_features & NETIF_F_NTUPLE) { struct efx_channel *channel; int i, success = 1;
diff --git a/drivers/net/ethernet/sfc/rx_common.h b/drivers/net/ethernet/sfc/rx_common.h index fbd2769307f9..09b38b0cb401 100644 --- a/drivers/net/ethernet/sfc/rx_common.h +++ b/drivers/net/ethernet/sfc/rx_common.h @@ -113,4 +113,8 @@ bool __efx_filter_rfs_expire(struct efx_channel *channel, unsigned int quota); int efx_probe_filters(struct efx_nic *efx); void efx_remove_filters(struct efx_nic *efx);
+extern netdev_features_t ef10_offload_features __ro_after_init; +extern netdev_features_t ef100_offload_features __ro_after_init; +extern netdev_features_t siena_offload_features __ro_after_init; + #endif diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index ce3060e15b54..74e3db5ccb53 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -1095,8 +1095,7 @@ const struct efx_nic_type siena_a0_nic_type = { .option_descriptors = false, .min_interrupt_mode = EFX_INT_MODE_LEGACY, .timer_period_max = 1 << FRF_CZ_TC_TIMER_VAL_WIDTH, - .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXHASH | NETIF_F_NTUPLE), + .offload_features = &siena_offload_features, .mcdi_max_ver = 1, .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, .hwtstamp_filters = (1 << HWTSTAMP_FILTER_NONE |
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@huawei.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);
For the prototype of netdev_features_t will be changed to be structure with bitmap, it's unable to be initialized when define it. So adjust it.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 +++- drivers/net/ethernet/sfc/ef10.c | 3 ++- drivers/net/ethernet/sfc/efx_common.c | 3 ++- drivers/net/ethernet/sfc/falcon/efx.c | 3 ++- net/core/dev.c | 14 ++++++++++---- net/ethtool/features.c | 4 +++- net/ethtool/ioctl.c | 14 ++++++++++---- 7 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 0234d9755a9f..34484d599e1b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2405,12 +2405,14 @@ static int hns3_nic_do_ioctl(struct net_device *netdev, static int hns3_nic_set_features(struct net_device *netdev, netdev_features_t features) { - netdev_features_t changed = netdev->features ^ features; struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = priv->ae_handle; + netdev_features_t changed; bool enable; int ret;
+ changed = netdev->features ^ features; + if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) { enable = !!(features & NETIF_F_GRO_HW); ret = h->ae_algo->ops->set_gro_en(h, enable); diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 01bc65ba0d31..42cc17a1d540 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1310,7 +1310,7 @@ DECLARE_NETDEV_FEATURE_SET(ef10_tso_feature_set, static int efx_ef10_init_nic(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; - netdev_features_t hw_enc_features = 0; + netdev_features_t hw_enc_features; int rc;
if (nic_data->must_check_datapath_caps) { @@ -1355,6 +1355,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx) nic_data->must_restore_piobufs = false; }
+ netdev_features_zero(&hw_enc_features); /* add encapsulated checksum offload features */ if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx)) hw_enc_features |= netdev_ip_csum_features; diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 815acba14394..4b890e68c5de 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -367,8 +367,8 @@ void efx_start_monitor(struct efx_nic *efx) */ static void efx_start_datapath(struct efx_nic *efx) { - netdev_features_t old_features = efx->net_dev->features; bool old_rx_scatter = efx->rx_scatter; + netdev_features_t old_features; size_t rx_buf_len;
/* Calculate the rx buffer allocation parameters required to @@ -413,6 +413,7 @@ static void efx_start_datapath(struct efx_nic *efx) /* Restore previously fixed features in hw_features and remove * features which are fixed now */ + old_features = efx->net_dev->features; efx->net_dev->hw_features |= efx->net_dev->features; efx->net_dev->hw_features &= ~efx->fixed_features; efx->net_dev->features |= efx->fixed_features; diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 665190413841..352ae87d901c 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -592,8 +592,8 @@ static int ef4_probe_channels(struct ef4_nic *efx) */ static void ef4_start_datapath(struct ef4_nic *efx) { - netdev_features_t old_features = efx->net_dev->features; bool old_rx_scatter = efx->rx_scatter; + netdev_features_t old_features; struct ef4_tx_queue *tx_queue; struct ef4_rx_queue *rx_queue; struct ef4_channel *channel; @@ -640,6 +640,7 @@ static void ef4_start_datapath(struct ef4_nic *efx) /* Restore previously fixed features in hw_features and remove * features which are fixed now */ + old_features = efx->net_dev->features; efx->net_dev->hw_features |= efx->net_dev->features; efx->net_dev->hw_features &= ~efx->fixed_features; efx->net_dev->features |= efx->fixed_features; diff --git a/net/core/dev.c b/net/core/dev.c index ccf170a5f151..48b0a49ebb39 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3496,9 +3496,11 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, 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 features; netdev_features_t tmp;
+ features = dev->features; + if (skb_is_gso(skb)) features = gso_features_check(skb, dev, features);
@@ -9450,10 +9452,11 @@ static void net_set_todo(struct net_device *dev) static netdev_features_t netdev_sync_upper_features(struct net_device *lower, struct net_device *upper, netdev_features_t features) { - netdev_features_t upper_disables = NETIF_F_UPPER_DISABLES; + netdev_features_t upper_disables; netdev_features_t feature; int feature_bit;
+ upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { feature = __NETIF_F_BIT(feature_bit); if (!(upper->wanted_features & feature) @@ -9470,10 +9473,11 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower, static void netdev_sync_lower_features(struct net_device *upper, struct net_device *lower, netdev_features_t features) { - netdev_features_t upper_disables = NETIF_F_UPPER_DISABLES; + netdev_features_t upper_disables; netdev_features_t feature; int feature_bit;
+ upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { feature = __NETIF_F_BIT(feature_bit); if (!(features & feature) && (lower->features & feature)) { @@ -9645,7 +9649,9 @@ int __netdev_update_features(struct net_device *dev) netdev_sync_lower_features(dev, lower, features);
if (!err) { - netdev_features_t diff = features ^ dev->features; + netdev_features_t diff; + + diff = features ^ dev->features;
if (diff & NETIF_F_RX_UDP_TUNNEL_PORT) { /* udp_tunnel_{get,drop}_rx_info both need diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 67a837d44491..2c64183012c1 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only
+#include <linux/netdev_features_helper.h> #include "netlink.h" #include "common.h" #include "bitset.h" @@ -144,9 +145,10 @@ static netdev_features_t ethnl_bitmap_to_features(unsigned long *src) { const unsigned int nft_bits = sizeof(netdev_features_t) * BITS_PER_BYTE; const unsigned int words = BITS_TO_LONGS(NETDEV_FEATURE_COUNT); - netdev_features_t ret = 0; + netdev_features_t ret; unsigned int i;
+ netdev_features_zero(&ret); for (i = 0; i < words; i++) ret |= (netdev_features_t)(src[i]) << (i * BITS_PER_LONG); ret &= ~(netdev_features_t)0 >> (nft_bits - NETDEV_FEATURE_COUNT); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index b2d500b27a5b..28164e990201 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -125,7 +125,8 @@ 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 wanted; + netdev_features_t valid; netdev_features_t tmp; int i, ret = 0;
@@ -139,6 +140,8 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) if (copy_from_user(features, useraddr, sizeof(features))) return -EFAULT;
+ netdev_features_zero(&wanted); + netdev_features_zero(&valid); for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) { valid |= (netdev_features_t)features[i].valid << (32 * i); wanted |= (netdev_features_t)features[i].requested << (32 * i); @@ -267,12 +270,13 @@ static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd) static int ethtool_get_one_feature(struct net_device *dev, char __user *useraddr, u32 ethcmd) { - netdev_features_t mask = ethtool_get_feature_mask(ethcmd); + netdev_features_t mask; struct ethtool_value edata = { .cmd = ethcmd, - .data = !!(dev->features & mask), };
+ mask = ethtool_get_feature_mask(ethcmd); + edata.data = !!(dev->features & mask); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; @@ -332,13 +336,15 @@ static u32 __ethtool_get_flags(struct net_device *dev)
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 features; + netdev_features_t changed; netdev_features_t tmp;
if (data & ~ETH_ALL_FLAGS) return -EINVAL;
+ netdev_features_zero(&features); if (data & ETH_FLAG_LRO) features |= NETIF_F_LRO; if (data & ETH_FLAG_RXVLAN)
Replace the '|' and '|=' operations of single feature bit by netdev_features_add helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 17 ++++++------ drivers/net/ethernet/sfc/ef10.c | 4 +-- drivers/net/ethernet/sfc/ef100_nic.c | 3 ++- drivers/net/ethernet/sfc/ef10_sriov.c | 3 ++- drivers/net/ethernet/sfc/efx.c | 4 +-- drivers/net/ethernet/sfc/falcon/efx.c | 6 ++--- net/core/dev.c | 26 +++++++++---------- net/ethtool/ioctl.c | 24 ++++++++--------- 8 files changed, 45 insertions(+), 42 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 34484d599e1b..a368fe002295 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3291,32 +3291,33 @@ static void hns3_set_default_feature(struct net_device *netdev)
netdev->priv_flags |= IFF_UNICAST_FLT;
- netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM; + netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_GRE_CSUM_BIT);
netdev_features_zero(&features); netdev_features_set_array(&hns3_default_feature_set, &features); netdev->features |= features;
if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { - netdev->features |= NETIF_F_GRO_HW; + netdev_active_feature_add(netdev, NETIF_F_GRO_HW_BIT);
if (!(h->flags & HNAE3_SUPPORT_VF)) - netdev->features |= NETIF_F_NTUPLE; + netdev_active_feature_add(netdev, NETIF_F_NTUPLE_BIT); }
if (test_bit(HNAE3_DEV_SUPPORT_UDP_GSO_B, ae_dev->caps)) - netdev->features |= NETIF_F_GSO_UDP_L4; + netdev_active_feature_add(netdev, NETIF_F_GSO_UDP_L4_BIT);
if (test_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps)) - netdev->features |= NETIF_F_HW_CSUM; + netdev_active_feature_add(netdev, NETIF_F_HW_CSUM_BIT); else 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; + netdev_active_feature_add(netdev, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
if (test_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps)) - netdev->features |= NETIF_F_HW_TC; + netdev_active_feature_add(netdev, NETIF_F_HW_TC_BIT);
netdev->hw_features |= netdev->features; if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) @@ -3329,7 +3330,7 @@ static void hns3_set_default_feature(struct net_device *netdev) netdev->vlan_features |= features;
netdev->hw_enc_features |= netdev->vlan_features; - netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID; + netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT); }
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 42cc17a1d540..9c99a820bad1 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -627,7 +627,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
if (nic_data->datapath_caps & (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_INCLUDE_FCS_LBN)) - efx->net_dev->hw_features |= NETIF_F_RXFCS; + netdev_hw_feature_add(efx->net_dev, NETIF_F_RXFCS_BIT);
rc = efx_mcdi_port_get_number(efx); if (rc < 0) @@ -1368,7 +1368,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx) &encap_tso_features);
hw_enc_features |= encap_tso_features; - hw_enc_features |= NETIF_F_TSO; + netdev_feature_add(NETIF_F_TSO_BIT, &hw_enc_features); efx->net_dev->features |= encap_tso_features; } efx->net_dev->hw_enc_features = hw_enc_features; diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index 679530f20bd6..b72be20af1b2 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -204,7 +204,8 @@ static int efx_ef100_init_datapath_caps(struct efx_nic *efx) /* EF100 HW can only offload outer checksums if they are UDP, * so for GRE_CSUM we have to use GSO_PARTIAL. */ - net_dev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM; + netdev_gso_partial_feature_add(net_dev, + NETIF_F_GSO_GRE_CSUM_BIT); } efx->num_mac_stats = MCDI_WORD(outbuf, GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS); diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index 7f5aa4a8c451..857e7520461d 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -243,7 +243,8 @@ static int efx_ef10_vadaptor_alloc_set_features(struct efx_nic *efx)
if (port_flags & (1 << MC_CMD_VPORT_ALLOC_IN_FLAG_VLAN_RESTRICT_LBN)) - efx->fixed_features |= NETIF_F_HW_VLAN_CTAG_FILTER; + netdev_feature_add(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + &efx->fixed_features); else efx->fixed_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index a44378ae484a..1a7fc9295ba0 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1021,7 +1021,7 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) netdev_active_features_set_array(net_dev, &efx_active_feature_set); if ((*efx->type->offload_features & NETIF_F_IPV6_CSUM) || (*efx->type->offload_features & NETIF_F_HW_CSUM)) - net_dev->features |= NETIF_F_TSO6; + netdev_active_feature_add(net_dev, NETIF_F_TSO6_BIT); /* Check whether device supports TSO */ if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) net_dev->features &= ~NETIF_F_ALL_TSO; @@ -1073,7 +1073,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev, return -ENOMEM; efx = netdev_priv(net_dev); efx->type = (const struct efx_nic_type *) entry->driver_data; - efx->fixed_features |= NETIF_F_HIGHDMA; + netdev_feature_add(NETIF_F_HIGHDMA_BIT, &efx->fixed_features);
pci_set_drvdata(pci_dev, efx); SET_NETDEV_DEV(net_dev, &pci_dev->dev); diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 352ae87d901c..5d044027e164 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2892,7 +2892,7 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, return -ENOMEM; efx = netdev_priv(net_dev); efx->type = (const struct ef4_nic_type *) entry->driver_data; - efx->fixed_features |= NETIF_F_HIGHDMA; + netdev_feature_add(NETIF_F_HIGHDMA_BIT, &efx->fixed_features);
pci_set_drvdata(pci_dev, efx); SET_NETDEV_DEV(net_dev, &pci_dev->dev); @@ -2915,8 +2915,8 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, goto fail3;
net_dev->features |= *efx->type->offload_features; - net_dev->features |= NETIF_F_SG; - net_dev->features |= NETIF_F_RXCSUM; + netdev_active_feature_add(net_dev, NETIF_F_SG_BIT); + netdev_active_feature_add(net_dev, NETIF_F_RXCSUM_BIT); /* 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/net/core/dev.c b/net/core/dev.c index 48b0a49ebb39..921f10018fbc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3344,7 +3344,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, struct net_device *dev = skb->dev;
partial_features = dev->features & dev->gso_partial_features; - partial_features |= NETIF_F_GSO_ROBUST; + netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, &partial_features); if (!skb_gso_ok(skb, features | partial_features)) features &= ~NETIF_F_GSO_PARTIAL; } @@ -9936,14 +9936,14 @@ int register_netdevice(struct net_device *dev) dev->features |= NETIF_F_SOFT_FEATURES;
if (dev->udp_tunnel_nic_info) { - dev->features |= NETIF_F_RX_UDP_TUNNEL_PORT; - dev->hw_features |= NETIF_F_RX_UDP_TUNNEL_PORT; + netdev_active_feature_add(dev, NETIF_F_RX_UDP_TUNNEL_PORT_BIT); + netdev_hw_feature_add(dev, NETIF_F_RX_UDP_TUNNEL_PORT_BIT); }
dev->wanted_features = dev->features & dev->hw_features;
if (!(dev->flags & IFF_LOOPBACK)) - dev->hw_features |= NETIF_F_NOCACHE_COPY; + netdev_hw_feature_add(dev, NETIF_F_NOCACHE_COPY_BIT);
/* If IPv4 TCP segmentation offload is supported we should also * allow the device to enable segmenting the frame with the option @@ -9951,26 +9951,26 @@ int register_netdevice(struct net_device *dev) * feature itself but allows the user to enable it later. */ if (dev->hw_features & NETIF_F_TSO) - dev->hw_features |= NETIF_F_TSO_MANGLEID; + netdev_hw_feature_add(dev, NETIF_F_TSO_MANGLEID_BIT); if (dev->vlan_features & NETIF_F_TSO) - dev->vlan_features |= NETIF_F_TSO_MANGLEID; + netdev_vlan_feature_add(dev, NETIF_F_TSO_MANGLEID_BIT); if (dev->mpls_features & NETIF_F_TSO) - dev->mpls_features |= NETIF_F_TSO_MANGLEID; + netdev_mpls_feature_add(dev, NETIF_F_TSO_MANGLEID_BIT); if (dev->hw_enc_features & NETIF_F_TSO) - dev->hw_enc_features |= NETIF_F_TSO_MANGLEID; + netdev_hw_enc_feature_add(dev, NETIF_F_TSO_MANGLEID_BIT);
/* Make NETIF_F_HIGHDMA inheritable to VLAN devices. */ - dev->vlan_features |= NETIF_F_HIGHDMA; + netdev_vlan_feature_add(dev, NETIF_F_HIGHDMA_BIT);
/* Make NETIF_F_SG inheritable to tunnel devices. */ - dev->hw_enc_features |= NETIF_F_SG; - dev->hw_enc_features |= NETIF_F_GSO_PARTIAL; + netdev_hw_enc_feature_add(dev, NETIF_F_SG_BIT); + netdev_hw_enc_feature_add(dev, NETIF_F_GSO_PARTIAL_BIT);
/* Make NETIF_F_SG inheritable to MPLS. */ - dev->mpls_features |= NETIF_F_SG; + netdev_mpls_feature_add(dev, NETIF_F_SG_BIT);
ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); ret = notifier_to_errno(ret); @@ -11057,7 +11057,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all,
if (mask & NETIF_F_HW_CSUM) mask |= NETIF_F_CSUM_MASK; - mask |= NETIF_F_VLAN_CHALLENGED; + netdev_feature_add(NETIF_F_VLAN_CHALLENGED_BIT, &mask);
tmp = NETIF_F_ONE_FOR_ALL | NETIF_F_CSUM_MASK; tmp &= one; diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 28164e990201..b258379006f1 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -239,28 +239,28 @@ static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd) case ETHTOOL_GTXCSUM: case ETHTOOL_STXCSUM: tmp = NETIF_F_CSUM_MASK; - tmp |= NETIF_F_FCOE_CRC; - tmp |= NETIF_F_SCTP_CRC; + netdev_feature_add(NETIF_F_FCOE_CRC_BIT, &tmp); + netdev_feature_add(NETIF_F_SCTP_CRC_BIT, &tmp); return tmp; case ETHTOOL_GRXCSUM: case ETHTOOL_SRXCSUM: - tmp |= NETIF_F_RXCSUM; + netdev_feature_add(NETIF_F_RXCSUM_BIT, &tmp); return tmp; case ETHTOOL_GSG: case ETHTOOL_SSG: - tmp |= NETIF_F_SG; - tmp |= NETIF_F_FRAGLIST; + netdev_feature_add(NETIF_F_SG_BIT, &tmp); + netdev_feature_add(NETIF_F_FRAGLIST_BIT, &tmp); return tmp; case ETHTOOL_GTSO: case ETHTOOL_STSO: return NETIF_F_ALL_TSO; case ETHTOOL_GGSO: case ETHTOOL_SGSO: - tmp |= NETIF_F_GSO; + netdev_feature_add(NETIF_F_GSO_BIT, &tmp); return tmp; case ETHTOOL_GGRO: case ETHTOOL_SGRO: - tmp |= NETIF_F_GRO; + netdev_feature_add(NETIF_F_GRO_BIT, &tmp); return tmp; default: BUG(); @@ -346,15 +346,15 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
netdev_features_zero(&features); if (data & ETH_FLAG_LRO) - features |= NETIF_F_LRO; + netdev_feature_add(NETIF_F_LRO_BIT, &features); if (data & ETH_FLAG_RXVLAN) - features |= NETIF_F_HW_VLAN_CTAG_RX; + netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT, &features); if (data & ETH_FLAG_TXVLAN) - features |= NETIF_F_HW_VLAN_CTAG_TX; + netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features); if (data & ETH_FLAG_NTUPLE) - features |= NETIF_F_NTUPLE; + netdev_feature_add(NETIF_F_NTUPLE_BIT, &features); if (data & ETH_FLAG_RXHASH) - features |= NETIF_F_RXHASH; + netdev_feature_add(NETIF_F_RXHASH_BIT, &features);
netdev_features_zero(ð_all_features); netdev_features_set_array(ðtool_all_feature_set, ð_all_features);
Replace the '|' and '|=' operations of features by netdev_features_or helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 10 +++++----- drivers/net/ethernet/sfc/ef10.c | 6 +++--- drivers/net/ethernet/sfc/ef100_nic.c | 14 +++++++------- drivers/net/ethernet/sfc/efx.c | 8 ++++---- drivers/net/ethernet/sfc/efx_common.c | 4 ++-- drivers/net/ethernet/sfc/falcon/efx.c | 8 ++++---- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- include/linux/netdev_features_helper.h | 6 +++--- net/core/dev.c | 18 +++++++++--------- net/ethtool/features.c | 5 +++-- net/ethtool/ioctl.c | 12 +++++++----- 12 files changed, 49 insertions(+), 46 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index a368fe002295..e43b3e8c4f84 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3295,7 +3295,7 @@ static void hns3_set_default_feature(struct net_device *netdev)
netdev_features_zero(&features); netdev_features_set_array(&hns3_default_feature_set, &features); - netdev->features |= features; + netdev_active_features_set(netdev, features);
if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { netdev_active_feature_add(netdev, NETIF_F_GRO_HW_BIT); @@ -3310,7 +3310,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_active_feature_add(netdev, NETIF_F_HW_CSUM_BIT); else - netdev->features |= netdev_ip_csum_features; + netdev_active_features_set(netdev, netdev_ip_csum_features);
if (test_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps)) netdev_active_feature_add(netdev, @@ -3319,7 +3319,7 @@ static void hns3_set_default_feature(struct net_device *netdev) if (test_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps)) netdev_active_feature_add(netdev, NETIF_F_HW_TC_BIT);
- netdev->hw_features |= netdev->features; + netdev_hw_features_set(netdev, netdev->features); if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
@@ -3327,9 +3327,9 @@ static void hns3_set_default_feature(struct net_device *netdev) netdev_features_set_array(&hns3_vlan_off_feature_set, &vlan_off_features); features = netdev->features & ~vlan_off_features; - netdev->vlan_features |= features; + netdev_vlan_features_set(netdev, features);
- netdev->hw_enc_features |= netdev->vlan_features; + netdev_hw_enc_features_set(netdev, netdev->vlan_features); netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT); }
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 9c99a820bad1..0674565d9ed1 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1358,7 +1358,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx) netdev_features_zero(&hw_enc_features); /* add encapsulated checksum offload features */ if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx)) - hw_enc_features |= netdev_ip_csum_features; + netdev_features_set(&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; @@ -1367,9 +1367,9 @@ 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; + netdev_features_set(&hw_enc_features, encap_tso_features); netdev_feature_add(NETIF_F_TSO_BIT, &hw_enc_features); - efx->net_dev->features |= encap_tso_features; + netdev_active_features_set(efx->net_dev, encap_tso_features); } efx->net_dev->hw_enc_features = hw_enc_features;
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index b72be20af1b2..e32012cae55a 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -198,9 +198,9 @@ static int efx_ef100_init_datapath_caps(struct efx_nic *efx)
netdev_features_zero(&tso); netdev_features_set_array(&ef100_tso_feature_set, &tso); - net_dev->features |= tso; - net_dev->hw_features |= tso; - net_dev->hw_enc_features |= tso; + netdev_active_features_set(net_dev, tso); + netdev_hw_features_set(net_dev, tso); + netdev_hw_enc_features_set(net_dev, tso); /* EF100 HW can only offload outer checksums if they are UDP, * so for GRE_CSUM we have to use GSO_PARTIAL. */ @@ -1133,10 +1133,10 @@ static int ef100_probe_main(struct efx_nic *efx) return -ENOMEM; efx->nic_data = nic_data; nic_data->efx = efx; - net_dev->features |= *efx->type->offload_features; - net_dev->hw_features |= *efx->type->offload_features; - net_dev->hw_enc_features |= *efx->type->offload_features; - net_dev->vlan_features |= NETIF_F_ALL_TSO; + netdev_active_features_set(net_dev, *efx->type->offload_features); + netdev_hw_features_set(net_dev, *efx->type->offload_features); + netdev_hw_enc_features_set(net_dev, *efx->type->offload_features); + netdev_vlan_features_set(net_dev, NETIF_F_ALL_TSO); netdev_vlan_features_set_array(net_dev, &ef100_vlan_feature_set);
/* Populate design-parameter defaults */ diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 1a7fc9295ba0..e346ad52c9a2 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1017,7 +1017,7 @@ 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(net_dev, *efx->type->offload_features); netdev_active_features_set_array(net_dev, &efx_active_feature_set); if ((*efx->type->offload_features & NETIF_F_IPV6_CSUM) || (*efx->type->offload_features & NETIF_F_HW_CSUM)) @@ -1026,11 +1026,11 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) net_dev->features &= ~NETIF_F_ALL_TSO; /* Mask for features that also apply to VLAN devices */ - net_dev->vlan_features |= NETIF_F_ALL_TSO; + netdev_vlan_features_set(net_dev, NETIF_F_ALL_TSO); netdev_vlan_features_set_array(net_dev, &efx_vlan_feature_set);
tmp = net_dev->features & ~efx->fixed_features; - net_dev->hw_features |= tmp; + netdev_hw_features_set(net_dev, tmp);
/* Disable receiving frames with bad FCS, by default. */ net_dev->features &= ~NETIF_F_RXALL; @@ -1040,7 +1040,7 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) * receive VLAN tagged packets due to vPort restrictions). */ net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; - net_dev->features |= efx->fixed_features; + netdev_active_features_set(net_dev, efx->fixed_features);
rc = efx_register_netdev(efx); if (!rc) diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 4b890e68c5de..f5536eb00dfc 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -414,9 +414,9 @@ static void efx_start_datapath(struct efx_nic *efx) * features which are fixed now */ old_features = efx->net_dev->features; - efx->net_dev->hw_features |= efx->net_dev->features; + netdev_hw_features_set(efx->net_dev, efx->net_dev->features); efx->net_dev->hw_features &= ~efx->fixed_features; - efx->net_dev->features |= efx->fixed_features; + netdev_active_features_set(efx->net_dev, efx->fixed_features); if (efx->net_dev->features != old_features) netdev_features_change(efx->net_dev);
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 5d044027e164..d246c5b805a1 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -641,9 +641,9 @@ static void ef4_start_datapath(struct ef4_nic *efx) * features which are fixed now */ old_features = efx->net_dev->features; - efx->net_dev->hw_features |= efx->net_dev->features; + netdev_hw_features_set(efx->net_dev, efx->net_dev->features); efx->net_dev->hw_features &= ~efx->fixed_features; - efx->net_dev->features |= efx->fixed_features; + netdev_active_features_set(efx->net_dev, efx->fixed_features); if (efx->net_dev->features != old_features) netdev_features_change(efx->net_dev);
@@ -2914,7 +2914,7 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, if (rc) goto fail3;
- net_dev->features |= *efx->type->offload_features; + netdev_active_features_set(net_dev, *efx->type->offload_features); netdev_active_feature_add(net_dev, NETIF_F_SG_BIT); netdev_active_feature_add(net_dev, NETIF_F_RXCSUM_BIT); /* Mask for features that also apply to VLAN devices */ @@ -2926,7 +2926,7 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, * receive VLAN tagged packets due to vPort restrictions). */ net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; - net_dev->features |= efx->fixed_features; + netdev_active_features_set(net_dev, efx->fixed_features);
rc = ef4_register_netdev(efx); if (rc) diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h index 26aff929c6d2..5365e2d8a975 100644 --- a/drivers/net/ethernet/sfc/falcon/net_driver.h +++ b/drivers/net/ethernet/sfc/falcon/net_driver.h @@ -1303,7 +1303,7 @@ static inline netdev_features_t ef4_supported_features(const struct ef4_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return net_dev->features | net_dev->hw_features; + return netdev_active_features_or(net_dev, net_dev->hw_features); }
/* Get the current TX queue insert index. */ diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 6b52f2924bf7..bcdcec3d61e1 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1688,7 +1688,7 @@ static inline netdev_features_t efx_supported_features(const struct efx_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return net_dev->features | net_dev->hw_features; + return netdev_active_features_or(net_dev, net_dev->hw_features); }
/* Get the current TX queue insert index. */ diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h index b68a85d2b982..0c4363588582 100644 --- a/include/linux/netdev_features_helper.h +++ b/include/linux/netdev_features_helper.h @@ -590,9 +590,9 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, tmp = f1 ^ f2; if (tmp & NETIF_F_HW_CSUM) { if (f1 & NETIF_F_HW_CSUM) - f1 |= netdev_ip_csum_features; + netdev_features_set(&f1, netdev_ip_csum_features); else - f2 |= netdev_ip_csum_features; + netdev_features_set(&f2, netdev_ip_csum_features); }
return f1 & f2; @@ -604,7 +604,7 @@ netdev_get_wanted_features(struct net_device *dev) netdev_features_t tmp;
tmp = dev->features & ~dev->hw_features; - return dev->wanted_features | tmp; + return netdev_wanted_features_or(dev, tmp); }
#endif diff --git a/net/core/dev.c b/net/core/dev.c index 921f10018fbc..13bb2cd8e2af 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3345,7 +3345,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
partial_features = dev->features & dev->gso_partial_features; netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, &partial_features); - if (!skb_gso_ok(skb, features | partial_features)) + if (!skb_gso_ok(skb, netdev_features_or(features, partial_features))) features &= ~NETIF_F_GSO_PARTIAL; }
@@ -3512,7 +3512,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) features &= dev->hw_enc_features;
if (skb_vlan_tagged(skb)) { - tmp = dev->vlan_features | netdev_tx_vlan_features; + tmp = netdev_vlan_features_or(dev, netdev_tx_vlan_features); features = netdev_intersect_features(features, tmp); }
@@ -9931,9 +9931,9 @@ 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; - dev->hw_features |= NETIF_F_SOFT_FEATURES_OFF; - dev->features |= NETIF_F_SOFT_FEATURES; + netdev_hw_features_set(dev, NETIF_F_SOFT_FEATURES); + netdev_hw_features_set(dev, NETIF_F_SOFT_FEATURES_OFF); + netdev_active_features_set(dev, NETIF_F_SOFT_FEATURES);
if (dev->udp_tunnel_nic_info) { netdev_active_feature_add(dev, NETIF_F_RX_UDP_TUNNEL_PORT_BIT); @@ -11056,17 +11056,17 @@ netdev_features_t netdev_increment_features(netdev_features_t all, netdev_features_t tmp;
if (mask & NETIF_F_HW_CSUM) - mask |= NETIF_F_CSUM_MASK; + netdev_features_set(&mask, NETIF_F_CSUM_MASK); netdev_feature_add(NETIF_F_VLAN_CHALLENGED_BIT, &mask);
- tmp = NETIF_F_ONE_FOR_ALL | NETIF_F_CSUM_MASK; + tmp = netdev_features_or(NETIF_F_ONE_FOR_ALL, NETIF_F_CSUM_MASK); tmp &= one; tmp &= mask; - all |= tmp; + netdev_features_set(&all, tmp);
netdev_features_fill(&tmp); tmp &= ~NETIF_F_ALL_FOR_ALL; - tmp |= one; + netdev_features_set(&tmp, one); all &= tmp;
/* If one device supports hw checksumming, set for all. */ diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 2c64183012c1..8e753afc0824 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -150,7 +150,8 @@ static netdev_features_t ethnl_bitmap_to_features(unsigned long *src)
netdev_features_zero(&ret); for (i = 0; i < words; i++) - ret |= (netdev_features_t)(src[i]) << (i * BITS_PER_LONG); + netdev_features_set(&ret, + (netdev_features_t)(src[i]) << (i * BITS_PER_LONG)); ret &= ~(netdev_features_t)0 >> (nft_bits - NETDEV_FEATURE_COUNT); return ret; } @@ -257,7 +258,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) if (!bitmap_equal(req_wanted, old_wanted, NETDEV_FEATURE_COUNT)) { dev->wanted_features &= ~dev->hw_features; tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features; - dev->wanted_features |= tmp; + netdev_wanted_features_set(dev, 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 b258379006f1..d18f305ee691 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -143,8 +143,10 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) netdev_features_zero(&wanted); netdev_features_zero(&valid); for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) { - valid |= (netdev_features_t)features[i].valid << (32 * i); - wanted |= (netdev_features_t)features[i].requested << (32 * i); + netdev_features_set(&valid, + (netdev_features_t)features[i].valid << (32 * i)); + netdev_features_set(&wanted, + (netdev_features_t)features[i].requested << (32 * i)); }
tmp = valid & ~NETIF_F_ETHTOOL_BITS; @@ -159,7 +161,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
dev->wanted_features &= ~valid; tmp = wanted & valid; - dev->wanted_features |= tmp; + netdev_wanted_features_set(dev, tmp); __netdev_update_features(dev);
tmp = dev->wanted_features ^ dev->features; @@ -297,7 +299,7 @@ static int ethtool_set_one_feature(struct net_device *dev, return -EOPNOTSUPP;
if (edata.data) - dev->wanted_features |= mask; + netdev_wanted_features_set(dev, mask); else dev->wanted_features &= ~mask;
@@ -368,7 +370,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
dev->wanted_features &= ~changed; tmp = features & changed; - dev->wanted_features |= tmp; + netdev_wanted_features_set(dev, tmp);
__netdev_update_features(dev);
Replace the '^' operations of features by netdev_features_xor helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- drivers/net/ethernet/sfc/efx_common.c | 2 +- drivers/net/ethernet/sfc/falcon/efx.c | 2 +- include/linux/netdev_features_helper.h | 2 +- net/core/dev.c | 2 +- net/ethtool/ioctl.c | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index e43b3e8c4f84..948317f210a4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2411,7 +2411,7 @@ static int hns3_nic_set_features(struct net_device *netdev, bool enable; int ret;
- changed = netdev->features ^ features; + changed = netdev_active_features_xor(netdev, features);
if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) { enable = !!(features & NETIF_F_GRO_HW); diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index f5536eb00dfc..5d3be6c4df54 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -226,7 +226,7 @@ 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. */ - tmp = net_dev->features ^ data; + tmp = netdev_active_features_xor(net_dev, data); if (tmp & NETIF_F_HW_VLAN_CTAG_FILTER || tmp & NETIF_F_RXFCS) { /* efx_set_rx_mode() will schedule MAC work to update filters diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index d246c5b805a1..b5ce520e8f2f 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2201,7 +2201,7 @@ static int ef4_set_features(struct net_device *net_dev, netdev_features_t data) }
/* If Rx VLAN filter is changed, update filters via mac_reconfigure */ - tmp = net_dev->features ^ data; + tmp = netdev_active_features_xor(net_dev, 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. diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h index 0c4363588582..7e2d66a5b803 100644 --- a/include/linux/netdev_features_helper.h +++ b/include/linux/netdev_features_helper.h @@ -587,7 +587,7 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, { netdev_features_t tmp;
- tmp = f1 ^ f2; + tmp = netdev_features_xor(f1, f2); if (tmp & NETIF_F_HW_CSUM) { if (f1 & NETIF_F_HW_CSUM) netdev_features_set(&f1, netdev_ip_csum_features); diff --git a/net/core/dev.c b/net/core/dev.c index 13bb2cd8e2af..076305d33a62 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9651,7 +9651,7 @@ int __netdev_update_features(struct net_device *dev) if (!err) { netdev_features_t diff;
- diff = features ^ dev->features; + diff = netdev_features_xor(features, dev->features);
if (diff & NETIF_F_RX_UDP_TUNNEL_PORT) { /* udp_tunnel_{get,drop}_rx_info both need diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index d18f305ee691..4a685224fba9 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -164,7 +164,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) netdev_wanted_features_set(dev, tmp); __netdev_update_features(dev);
- tmp = dev->wanted_features ^ dev->features; + tmp = netdev_wanted_features_xor(dev, dev->features); if (tmp & valid) ret |= ETHTOOL_F_WISH;
@@ -362,7 +362,7 @@ 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 = dev->features ^ features; + changed = netdev_active_features_xor(dev, features); changed &= eth_all_features; tmp = changed & ~dev->hw_features; if (tmp)
Replace the '&~' and '&= ~' operations of single feature bit by netdev_feature_del helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- drivers/net/ethernet/sfc/ef10_sriov.c | 3 +- drivers/net/ethernet/sfc/efx.c | 4 +- drivers/net/ethernet/sfc/falcon/efx.c | 2 +- drivers/net/ethernet/sfc/mcdi_filters.c | 9 +++-- net/core/dev.c | 39 ++++++++++--------- 6 files changed, 32 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 948317f210a4..fca355329040 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3321,7 +3321,7 @@ static void hns3_set_default_feature(struct net_device *netdev)
netdev_hw_features_set(netdev, netdev->features); if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) - netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + netdev_hw_feature_del(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
netdev_features_zero(&vlan_off_features); netdev_features_set_array(&hns3_vlan_off_feature_set, diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index 857e7520461d..4bea76d0b833 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -246,7 +246,8 @@ static int efx_ef10_vadaptor_alloc_set_features(struct efx_nic *efx) netdev_feature_add(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, &efx->fixed_features); else - efx->fixed_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + netdev_feature_del(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + &efx->fixed_features);
return 0;
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index e346ad52c9a2..e37007839e2f 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1033,13 +1033,13 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) netdev_hw_features_set(net_dev, tmp);
/* Disable receiving frames with bad FCS, by default. */ - net_dev->features &= ~NETIF_F_RXALL; + netdev_active_feature_del(net_dev, NETIF_F_RXALL_BIT);
/* Disable VLAN filtering by default. It may be enforced if * the feature is fixed (i.e. VLAN filters are required to * receive VLAN tagged packets due to vPort restrictions). */ - net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + netdev_active_feature_del(net_dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT); netdev_active_features_set(net_dev, efx->fixed_features);
rc = efx_register_netdev(efx); diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index b5ce520e8f2f..d2056fbaa3d1 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2925,7 +2925,7 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, * the feature is fixed (i.e. VLAN filters are required to * receive VLAN tagged packets due to vPort restrictions). */ - net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + netdev_active_feature_del(net_dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT); netdev_active_features_set(net_dev, efx->fixed_features);
rc = ef4_register_netdev(efx); diff --git a/drivers/net/ethernet/sfc/mcdi_filters.c b/drivers/net/ethernet/sfc/mcdi_filters.c index 1523be77b9db..508549db124b 100644 --- a/drivers/net/ethernet/sfc/mcdi_filters.c +++ b/drivers/net/ethernet/sfc/mcdi_filters.c @@ -1326,9 +1326,12 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining) (EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC_IG)))) { netif_info(efx, probe, net_dev, "VLAN filters are not supported in this firmware variant\n"); - net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; - efx->fixed_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; - net_dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + netdev_active_feature_del(net_dev, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT); + netdev_feature_del(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + &efx->fixed_features); + netdev_hw_feature_del(net_dev, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT); }
table->entry = vzalloc(array_size(EFX_MCDI_FILTER_TBL_ROWS, diff --git a/net/core/dev.c b/net/core/dev.c index 076305d33a62..4ea8231ecdee 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1583,7 +1583,7 @@ void dev_disable_lro(struct net_device *dev) struct net_device *lower_dev; struct list_head *iter;
- dev->wanted_features &= ~NETIF_F_LRO; + netdev_wanted_feature_del(dev, NETIF_F_LRO_BIT); netdev_update_features(dev);
if (unlikely(dev->features & NETIF_F_LRO)) @@ -1604,7 +1604,7 @@ EXPORT_SYMBOL(dev_disable_lro); */ static void dev_disable_gro_hw(struct net_device *dev) { - dev->wanted_features &= ~NETIF_F_GRO_HW; + netdev_wanted_feature_del(dev, NETIF_F_GRO_HW_BIT); netdev_update_features(dev);
if (unlikely(dev->features & NETIF_F_GRO_HW)) @@ -3346,7 +3346,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, partial_features = dev->features & dev->gso_partial_features; netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, &partial_features); if (!skb_gso_ok(skb, netdev_features_or(features, partial_features))) - features &= ~NETIF_F_GSO_PARTIAL; + netdev_feature_del(NETIF_F_GSO_PARTIAL_BIT, &features); }
BUILD_BUG_ON(SKB_GSO_CB_OFFSET + @@ -3436,7 +3436,7 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, features &= ~netdev_csum_gso_features_mask; } if (illegal_highdma(skb->dev, skb)) - features &= ~NETIF_F_SG; + netdev_feature_del(NETIF_F_SG_BIT, &features);
return features; } @@ -3487,7 +3487,8 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, inner_ip_hdr(skb) : ip_hdr(skb);
if (!(iph->frag_off & htons(IP_DF))) - features &= ~NETIF_F_TSO_MANGLEID; + netdev_feature_del(NETIF_F_TSO_MANGLEID_BIT, + &features); }
return features; @@ -9516,30 +9517,30 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, if ((features & NETIF_F_TSO) && !(features & NETIF_F_HW_CSUM) && !(features & NETIF_F_IP_CSUM)) { netdev_dbg(dev, "Dropping TSO features since no CSUM feature.\n"); - features &= ~NETIF_F_TSO; - features &= ~NETIF_F_TSO_ECN; + netdev_feature_del(NETIF_F_TSO_BIT, &features); + netdev_feature_del(NETIF_F_TSO_ECN_BIT, &features); }
if ((features & NETIF_F_TSO6) && !(features & NETIF_F_HW_CSUM) && !(features & NETIF_F_IPV6_CSUM)) { netdev_dbg(dev, "Dropping TSO6 features since no CSUM feature.\n"); - features &= ~NETIF_F_TSO6; + netdev_feature_del(NETIF_F_TSO6_BIT, &features); }
/* TSO with IPv4 ID mangling requires IPv4 TSO be enabled */ if ((features & NETIF_F_TSO_MANGLEID) && !(features & NETIF_F_TSO)) - features &= ~NETIF_F_TSO_MANGLEID; + netdev_feature_del(NETIF_F_TSO_MANGLEID_BIT, &features);
/* TSO ECN requires that TSO is present as well. */ tmp = NETIF_F_ALL_TSO; - tmp &= ~NETIF_F_TSO_ECN; + netdev_feature_del(NETIF_F_TSO_ECN_BIT, &tmp); if (!(features & tmp) && (features & NETIF_F_TSO_ECN)) - features &= ~NETIF_F_TSO_ECN; + netdev_feature_del(NETIF_F_TSO_ECN_BIT, &features);
/* Software GSO depends on SG. */ if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) { netdev_dbg(dev, "Dropping NETIF_F_GSO since no SG feature.\n"); - features &= ~NETIF_F_GSO; + netdev_feature_del(NETIF_F_GSO_BIT, &features); }
/* GSO partial features require GSO partial be set */ @@ -9558,7 +9559,7 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, */ if (features & NETIF_F_GRO_HW) { netdev_dbg(dev, "Dropping NETIF_F_GRO_HW since no RXCSUM feature.\n"); - features &= ~NETIF_F_GRO_HW; + netdev_feature_del(NETIF_F_GRO_HW_BIT, &features); } }
@@ -9566,18 +9567,18 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, if (features & NETIF_F_RXFCS) { if (features & NETIF_F_LRO) { netdev_dbg(dev, "Dropping LRO feature since RX-FCS is requested.\n"); - features &= ~NETIF_F_LRO; + netdev_feature_del(NETIF_F_LRO_BIT, &features); }
if (features & NETIF_F_GRO_HW) { netdev_dbg(dev, "Dropping HW-GRO feature since RX-FCS is requested.\n"); - features &= ~NETIF_F_GRO_HW; + netdev_feature_del(NETIF_F_GRO_HW_BIT, &features); } }
if ((features & NETIF_F_GRO_HW) && (features & NETIF_F_LRO)) { netdev_dbg(dev, "Dropping LRO feature since HW-GRO is requested.\n"); - features &= ~NETIF_F_LRO; + netdev_feature_del(NETIF_F_LRO_BIT, &features); }
if (features & NETIF_F_HW_TLS_TX) { @@ -9587,13 +9588,13 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
if (!ip_csum && !hw_csum) { netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n"); - features &= ~NETIF_F_HW_TLS_TX; + netdev_feature_del(NETIF_F_HW_TLS_TX_BIT, &features); } }
if ((features & NETIF_F_HW_TLS_RX) && !(features & NETIF_F_RXCSUM)) { netdev_dbg(dev, "Dropping TLS RX HW offload feature since no RXCSUM feature.\n"); - features &= ~NETIF_F_HW_TLS_RX; + netdev_feature_del(NETIF_F_HW_TLS_RX_BIT, &features); }
return features; @@ -11072,7 +11073,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all, /* If one device supports hw checksumming, set for all. */ if (all & NETIF_F_HW_CSUM) { tmp = NETIF_F_CSUM_MASK; - tmp &= ~NETIF_F_HW_CSUM; + netdev_feature_del(NETIF_F_HW_CSUM_BIT, &tmp); all &= ~tmp; }
Replace the '& ~' and '&= ~' operations of features by netdev_features_andnot helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 5 ++-- drivers/net/ethernet/sfc/efx.c | 4 ++-- drivers/net/ethernet/sfc/efx_common.c | 9 ++++---- drivers/net/ethernet/sfc/falcon/efx.c | 7 +++--- include/linux/netdev_features_helper.h | 2 +- net/core/dev.c | 23 ++++++++++--------- net/ethtool/features.c | 2 +- net/ethtool/ioctl.c | 12 +++++----- 8 files changed, 34 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index fca355329040..38706313aa6c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2478,7 +2478,8 @@ static netdev_features_t hns3_features_check(struct sk_buff *skb, * len of 480 bytes. */ if (len > HNS3_MAX_HDR_LEN) - features &= ~netdev_csum_gso_features_mask; + netdev_features_clear(&features, + netdev_csum_gso_features_mask);
return features; } @@ -3326,7 +3327,7 @@ 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); - features = netdev->features & ~vlan_off_features; + features = netdev_active_features_andnot(netdev, vlan_off_features); netdev_vlan_features_set(netdev, features);
netdev_hw_enc_features_set(netdev, netdev->vlan_features); diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index e37007839e2f..89c62304b5c3 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1024,12 +1024,12 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) netdev_active_feature_add(net_dev, NETIF_F_TSO6_BIT); /* Check whether device supports TSO */ if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) - net_dev->features &= ~NETIF_F_ALL_TSO; + netdev_active_features_clear(net_dev, NETIF_F_ALL_TSO); /* Mask for features that also apply to VLAN devices */ netdev_vlan_features_set(net_dev, NETIF_F_ALL_TSO); netdev_vlan_features_set_array(net_dev, &efx_vlan_feature_set);
- tmp = net_dev->features & ~efx->fixed_features; + tmp = netdev_active_features_andnot(net_dev, efx->fixed_features); netdev_hw_features_set(net_dev, tmp);
/* Disable receiving frames with bad FCS, by default. */ diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 5d3be6c4df54..8b95525aad20 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -216,7 +216,7 @@ int efx_set_features(struct net_device *net_dev, netdev_features_t data) int rc;
/* If disabling RX n-tuple filtering, clear existing filters */ - tmp = net_dev->features & ~data; + tmp = netdev_active_features_andnot(net_dev, data); if (tmp & NETIF_F_NTUPLE) { rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); if (rc) @@ -415,7 +415,7 @@ static void efx_start_datapath(struct efx_nic *efx) */ old_features = efx->net_dev->features; netdev_hw_features_set(efx->net_dev, efx->net_dev->features); - efx->net_dev->hw_features &= ~efx->fixed_features; + netdev_hw_features_clear(efx->net_dev, efx->fixed_features); netdev_active_features_set(efx->net_dev, efx->fixed_features); if (efx->net_dev->features != old_features) netdev_features_change(efx->net_dev); @@ -1370,10 +1370,11 @@ 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); + netdev_features_clear(&features, NETIF_F_GSO_MASK); if (features & netdev_csum_gso_features_mask) if (!efx_can_encap_offloads(efx, skb)) - features &= ~netdev_csum_gso_features_mask; + netdev_features_clear(&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 d2056fbaa3d1..921617de3638 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -642,7 +642,7 @@ static void ef4_start_datapath(struct ef4_nic *efx) */ old_features = efx->net_dev->features; netdev_hw_features_set(efx->net_dev, efx->net_dev->features); - efx->net_dev->hw_features &= ~efx->fixed_features; + netdev_hw_features_clear(efx->net_dev, efx->fixed_features); netdev_active_features_set(efx->net_dev, efx->fixed_features); if (efx->net_dev->features != old_features) netdev_features_change(efx->net_dev); @@ -2193,7 +2193,7 @@ static int ef4_set_features(struct net_device *net_dev, netdev_features_t data) int rc;
/* If disabling RX n-tuple filtering, clear existing filters */ - tmp = net_dev->features & ~data; + tmp = netdev_active_features_andnot(net_dev, data); if (tmp & NETIF_F_NTUPLE) { rc = efx->type->filter_clear_rx(efx, EF4_FILTER_PRI_MANUAL); if (rc) @@ -2919,7 +2919,8 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, netdev_active_feature_add(net_dev, NETIF_F_RXCSUM_BIT); /* 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; + net_dev->hw_features = netdev_active_features_andnot(net_dev, + efx->fixed_features);
/* Disable VLAN filtering by default. It may be enforced if * the feature is fixed (i.e. VLAN filters are required to diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h index 7e2d66a5b803..067b90ca3084 100644 --- a/include/linux/netdev_features_helper.h +++ b/include/linux/netdev_features_helper.h @@ -603,7 +603,7 @@ netdev_get_wanted_features(struct net_device *dev) { netdev_features_t tmp;
- tmp = dev->features & ~dev->hw_features; + tmp = netdev_active_features_andnot(dev, dev->hw_features); return netdev_wanted_features_or(dev, tmp); }
diff --git a/net/core/dev.c b/net/core/dev.c index 4ea8231ecdee..124d48b5d61a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3433,7 +3433,8 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
if (skb->ip_summed != CHECKSUM_NONE && !can_checksum_protocol(features, type)) { - features &= ~netdev_csum_gso_features_mask; + netdev_features_clear(&features, + netdev_csum_gso_features_mask); } if (illegal_highdma(skb->dev, skb)) netdev_feature_del(NETIF_F_SG_BIT, &features); @@ -3463,11 +3464,11 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, u16 gso_segs = skb_shinfo(skb)->gso_segs;
if (gso_segs > READ_ONCE(dev->gso_max_segs)) - return features & ~NETIF_F_GSO_MASK; + return netdev_features_andnot(features, NETIF_F_GSO_MASK);
if (!skb_shinfo(skb)->gso_type) { skb_warn_bad_offload(skb); - return features & ~NETIF_F_GSO_MASK; + return netdev_features_andnot(features, NETIF_F_GSO_MASK); }
/* Support for GSO partial features requires software @@ -3477,7 +3478,7 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, * segmented the frame. */ if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL)) - features &= ~dev->gso_partial_features; + netdev_features_clear(&features, dev->gso_partial_features);
/* Make sure to clear the IPv4 ID mangling feature if the * IPv4 header has the potential to be fragmented. @@ -9464,7 +9465,7 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower, && (features & feature)) { netdev_dbg(lower, "Dropping feature %pNF, upper dev %s has it off.\n", &feature, upper->name); - features &= ~feature; + netdev_features_clear(&features, feature); } }
@@ -9484,7 +9485,7 @@ static void netdev_sync_lower_features(struct net_device *upper, if (!(features & feature) && (lower->features & feature)) { netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", &feature, lower->name); - lower->wanted_features &= ~feature; + netdev_wanted_features_clear(lower, feature); __netdev_update_features(lower);
if (unlikely(lower->features & feature)) @@ -9505,13 +9506,13 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, if ((features & NETIF_F_HW_CSUM) && (features & netdev_ip_csum_features)) { netdev_warn(dev, "mixed HW and IP checksum settings.\n"); - features &= ~netdev_ip_csum_features; + netdev_features_clear(&features, netdev_ip_csum_features); }
/* TSO requires that SG is present as well. */ if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) { netdev_dbg(dev, "Dropping TSO features since no SG feature.\n"); - features &= ~NETIF_F_ALL_TSO; + netdev_features_clear(&features, NETIF_F_ALL_TSO); }
if ((features & NETIF_F_TSO) && !(features & NETIF_F_HW_CSUM) && @@ -9548,7 +9549,7 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, !(features & NETIF_F_GSO_PARTIAL)) { netdev_dbg(dev, "Dropping partially supported GSO features since no GSO partial.\n"); - features &= ~dev->gso_partial_features; + netdev_features_clear(&features, dev->gso_partial_features); }
if (!(features & NETIF_F_RXCSUM)) { @@ -11066,7 +11067,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all, netdev_features_set(&all, tmp);
netdev_features_fill(&tmp); - tmp &= ~NETIF_F_ALL_FOR_ALL; + netdev_features_clear(&tmp, NETIF_F_ALL_FOR_ALL); netdev_features_set(&tmp, one); all &= tmp;
@@ -11074,7 +11075,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all, if (all & NETIF_F_HW_CSUM) { tmp = NETIF_F_CSUM_MASK; netdev_feature_del(NETIF_F_HW_CSUM_BIT, &tmp); - all &= ~tmp; + netdev_features_clear(&all, tmp); }
return all; diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 8e753afc0824..2de4cabf41e0 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -256,7 +256,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) bitmap_andnot(new_wanted, old_wanted, req_mask, NETDEV_FEATURE_COUNT); 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; + netdev_wanted_features_clear(dev, dev->hw_features); tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features; netdev_wanted_features_set(dev, tmp); __netdev_update_features(dev); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 4a685224fba9..3c951a883076 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -149,17 +149,17 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) (netdev_features_t)features[i].requested << (32 * i)); }
- tmp = valid & ~NETIF_F_ETHTOOL_BITS; + tmp = netdev_features_andnot(valid, NETIF_F_ETHTOOL_BITS); if (tmp) return -EINVAL;
- tmp = valid & ~dev->hw_features; + netdev_hw_features_andnot_r(dev, valid); if (tmp) { valid &= dev->hw_features; ret |= ETHTOOL_F_UNSUPPORTED; }
- dev->wanted_features &= ~valid; + netdev_wanted_features_clear(dev, valid); tmp = wanted & valid; netdev_wanted_features_set(dev, tmp); __netdev_update_features(dev); @@ -301,7 +301,7 @@ static int ethtool_set_one_feature(struct net_device *dev, if (edata.data) netdev_wanted_features_set(dev, mask); else - dev->wanted_features &= ~mask; + netdev_wanted_features_clear(dev, mask);
__netdev_update_features(dev);
@@ -364,11 +364,11 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) /* allow changing only bits set in hw_features */ changed = netdev_active_features_xor(dev, features); changed &= eth_all_features; - tmp = changed & ~dev->hw_features; + tmp = netdev_hw_features_andnot_r(dev, changed); if (tmp) return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
- dev->wanted_features &= ~changed; + netdev_wanted_features_clear(dev, changed); tmp = features & changed; netdev_wanted_features_set(dev, tmp);
Replace the '&' operations of single feature bit by netdev_feature_test helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 30 +++--- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 4 +- drivers/net/ethernet/sfc/ef10.c | 2 +- drivers/net/ethernet/sfc/ef100_rx.c | 4 +- drivers/net/ethernet/sfc/ef100_tx.c | 8 +- drivers/net/ethernet/sfc/efx_common.c | 6 +- drivers/net/ethernet/sfc/falcon/efx.c | 7 +- drivers/net/ethernet/sfc/falcon/rx.c | 4 +- drivers/net/ethernet/sfc/farch.c | 2 +- drivers/net/ethernet/sfc/mcdi_filters.c | 4 +- drivers/net/ethernet/sfc/mcdi_port_common.c | 2 +- drivers/net/ethernet/sfc/rx.c | 2 +- drivers/net/ethernet/sfc/rx_common.c | 4 +- include/linux/netdev_features_helper.h | 4 +- include/linux/netdevice.h | 19 ++-- net/core/dev.c | 93 ++++++++++--------- net/ethtool/ioctl.c | 10 +- 17 files changed, 111 insertions(+), 94 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 38706313aa6c..f872a624faad 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1503,7 +1503,8 @@ static int hns3_handle_vtags(struct hns3_enet_ring *tx_ring, return -EINVAL;
if (skb->protocol == htons(ETH_P_8021Q) && - !(handle->kinfo.netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) { + !netdev_active_feature_test(handle->kinfo.netdev, + NETIF_F_HW_VLAN_CTAG_TX_BIT)) { /* When HW VLAN acceleration is turned off, and the stack * sets the protocol to 802.1q, the driver just need to * set the protocol to the encapsulated ethertype. @@ -2413,36 +2414,41 @@ static int hns3_nic_set_features(struct net_device *netdev,
changed = netdev_active_features_xor(netdev, features);
- if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) { - enable = !!(features & NETIF_F_GRO_HW); + if (netdev_feature_test(NETIF_F_GRO_HW_BIT, changed) && + h->ae_algo->ops->set_gro_en) { + enable = netdev_feature_test(NETIF_F_GRO_HW_BIT, features); ret = h->ae_algo->ops->set_gro_en(h, enable); if (ret) return ret; }
- if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && + if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed) && h->ae_algo->ops->enable_hw_strip_rxvtag) { - enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX); + enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, + features); ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, enable); if (ret) return ret; }
- if ((changed & NETIF_F_NTUPLE) && h->ae_algo->ops->enable_fd) { - enable = !!(features & NETIF_F_NTUPLE); + if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed) && + h->ae_algo->ops->enable_fd) { + enable = netdev_feature_test(NETIF_F_NTUPLE_BIT, features); h->ae_algo->ops->enable_fd(h, enable); }
- if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) && + if (netdev_active_feature_test(netdev, NETIF_F_HW_TC_BIT) && + !netdev_feature_test(NETIF_F_HW_TC_BIT, features) && h->ae_algo->ops->cls_flower_active(h)) { netdev_err(netdev, "there are offloaded TC filters active, cannot disable HW TC offload"); return -EINVAL; }
- if ((changed & NETIF_F_HW_VLAN_CTAG_FILTER) && + if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed) && h->ae_algo->ops->enable_vlan_filter) { - enable = !!(features & NETIF_F_HW_VLAN_CTAG_FILTER); + enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + features); ret = h->ae_algo->ops->enable_vlan_filter(h, enable); if (ret) return ret; @@ -3905,7 +3911,7 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
skb_checksum_none_assert(skb);
- if (!(netdev->features & NETIF_F_RXCSUM)) + if (!netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) return;
if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) @@ -4196,7 +4202,7 @@ static void hns3_handle_rx_vlan_tag(struct hns3_enet_ring *ring, * ot_vlan_tag in two layer tag case, and stored at vlan_tag * in one layer tag case. */ - if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { + if (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) { u16 vlan_tag;
if (hns3_parse_vlan_tag(ring, desc, l234info, &vlan_tag)) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index f4da77452126..088243621641 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -339,7 +339,7 @@ static void hns3_selftest_prepare(struct net_device *ndev, #if IS_ENABLED(CONFIG_VLAN_8021Q) /* Disable the vlan filter for selftest does not support it */ if (h->ae_algo->ops->enable_vlan_filter && - ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) + netdev_active_feature_test(ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT)) h->ae_algo->ops->enable_vlan_filter(h, false); #endif
@@ -365,7 +365,7 @@ static void hns3_selftest_restore(struct net_device *ndev, bool if_running)
#if IS_ENABLED(CONFIG_VLAN_8021Q) if (h->ae_algo->ops->enable_vlan_filter && - ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) + netdev_active_feature_test(ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT)) h->ae_algo->ops->enable_vlan_filter(h, true); #endif
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 0674565d9ed1..bf8274c03176 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -2703,7 +2703,7 @@ static u16 efx_ef10_handle_rx_event_errors(struct efx_channel *channel, bool handled = false;
if (EFX_QWORD_FIELD(*event, ESF_DZ_RX_ECRC_ERR)) { - if (!(efx->net_dev->features & NETIF_F_RXALL)) { + if (!netdev_active_feature_test(efx->net_dev, NETIF_F_RXALL_BIT)) { if (!efx->loopback_selftest) channel->n_rx_eth_crc_err += n_packets; return EFX_RX_PKT_DISCARD; diff --git a/drivers/net/ethernet/sfc/ef100_rx.c b/drivers/net/ethernet/sfc/ef100_rx.c index 85207acf7dee..cebd442c2261 100644 --- a/drivers/net/ethernet/sfc/ef100_rx.c +++ b/drivers/net/ethernet/sfc/ef100_rx.c @@ -64,7 +64,7 @@ void __ef100_rx_packet(struct efx_channel *channel) prefix = (u32 *)(eh - ESE_GZ_RX_PKT_PREFIX_LEN);
if (ef100_has_fcs_error(channel, prefix) && - unlikely(!(efx->net_dev->features & NETIF_F_RXALL))) + unlikely(!netdev_active_feature_test(efx->net_dev, NETIF_F_RXALL_BIT))) goto out;
rx_buf->len = le16_to_cpu((__force __le16)PREFIX_FIELD(prefix, LENGTH)); @@ -76,7 +76,7 @@ void __ef100_rx_packet(struct efx_channel *channel) goto out; }
- if (likely(efx->net_dev->features & NETIF_F_RXCSUM)) { + if (likely(netdev_active_feature_test(efx->net_dev, NETIF_F_RXCSUM_BIT))) { if (PREFIX_FIELD(prefix, NT_OR_INNER_L3_CLASS) == 1) { ++channel->n_rx_ip_hdr_chksum_err; } else { diff --git a/drivers/net/ethernet/sfc/ef100_tx.c b/drivers/net/ethernet/sfc/ef100_tx.c index 26ef51d6b542..4a85f53d672a 100644 --- a/drivers/net/ethernet/sfc/ef100_tx.c +++ b/drivers/net/ethernet/sfc/ef100_tx.c @@ -61,7 +61,7 @@ static bool ef100_tx_can_tso(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
if (!skb_is_gso_tcp(skb)) return false; - if (!(efx->net_dev->features & NETIF_F_TSO)) + if (!netdev_active_feature_test(efx->net_dev, NETIF_F_TSO_BIT)) return false;
mss = skb_shinfo(skb)->gso_size; @@ -175,9 +175,9 @@ static void ef100_make_send_desc(struct efx_nic *efx, ESF_GZ_TX_SEND_LEN, buffer->len, ESF_GZ_TX_SEND_ADDR, buffer->dma_addr);
- if (likely(efx->net_dev->features & NETIF_F_HW_CSUM)) + if (likely(netdev_active_feature_test(efx->net_dev, NETIF_F_HW_CSUM_BIT))) ef100_set_tx_csum_partial(skb, buffer, txd); - if (efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_TX && + if (netdev_active_feature_test(efx->net_dev, NETIF_F_HW_VLAN_CTAG_TX_BIT) && skb && skb_vlan_tag_present(skb)) ef100_set_tx_hw_vlan(skb, txd); } @@ -202,7 +202,7 @@ static void ef100_make_tso_desc(struct efx_nic *efx,
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID) mangleid = ESE_GZ_TX_DESC_IP4_ID_NO_OP; - if (efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_TX) + if (netdev_active_feature_test(efx->net_dev, NETIF_F_HW_VLAN_CTAG_TX_BIT)) vlan_enable = skb_vlan_tag_present(skb);
len = skb->len - buffer->len; diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 8b95525aad20..31363adcf5f1 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -217,7 +217,7 @@ int efx_set_features(struct net_device *net_dev, netdev_features_t data)
/* If disabling RX n-tuple filtering, clear existing filters */ tmp = netdev_active_features_andnot(net_dev, data); - if (tmp & NETIF_F_NTUPLE) { + if (netdev_feature_test(NETIF_F_NTUPLE_BIT, tmp)) { rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); if (rc) return rc; @@ -227,8 +227,8 @@ int efx_set_features(struct net_device *net_dev, netdev_features_t data) * If rx-fcs is changed, mac_reconfigure updates that too. */ tmp = netdev_active_features_xor(net_dev, data); - if (tmp & NETIF_F_HW_VLAN_CTAG_FILTER || - tmp & NETIF_F_RXFCS) { + if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, tmp) || + netdev_feature_test(NETIF_F_RXFCS_BIT, tmp)) { /* efx_set_rx_mode() will schedule MAC work to update filters * when a new features are finally set in net_dev. */ diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 921617de3638..52d3ced17602 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -1695,7 +1695,8 @@ static int ef4_probe_filters(struct ef4_nic *efx) goto out_unlock;
#ifdef CONFIG_RFS_ACCEL - if (*efx->type->offload_features & NETIF_F_NTUPLE) { + if (netdev_feature_test(NETIF_F_NTUPLE_BIT, + *efx->type->offload_features)) { struct ef4_channel *channel; int i, success = 1;
@@ -2194,7 +2195,7 @@ static int ef4_set_features(struct net_device *net_dev, netdev_features_t data)
/* If disabling RX n-tuple filtering, clear existing filters */ tmp = netdev_active_features_andnot(net_dev, data); - if (tmp & NETIF_F_NTUPLE) { + if (netdev_feature_test(NETIF_F_NTUPLE_BIT, tmp)) { rc = efx->type->filter_clear_rx(efx, EF4_FILTER_PRI_MANUAL); if (rc) return rc; @@ -2202,7 +2203,7 @@ static int ef4_set_features(struct net_device *net_dev, netdev_features_t data)
/* If Rx VLAN filter is changed, update filters via mac_reconfigure */ tmp = netdev_active_features_xor(net_dev, data); - if (tmp & NETIF_F_HW_VLAN_CTAG_FILTER) { + if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, tmp)) { /* ef4_set_rx_mode() will schedule MAC work to update filters * when a new features are finally set in net_dev. */ diff --git a/drivers/net/ethernet/sfc/falcon/rx.c b/drivers/net/ethernet/sfc/falcon/rx.c index 0c6cc2191369..2b587735b4ad 100644 --- a/drivers/net/ethernet/sfc/falcon/rx.c +++ b/drivers/net/ethernet/sfc/falcon/rx.c @@ -443,7 +443,7 @@ ef4_rx_packet_gro(struct ef4_channel *channel, struct ef4_rx_buffer *rx_buf, return; }
- if (efx->net_dev->features & NETIF_F_RXHASH) + if (netdev_active_feature_test(efx->net_dev, NETIF_F_RXHASH_BIT)) skb_set_hash(skb, ef4_rx_buf_hash(efx, eh), PKT_HASH_TYPE_L3); skb->ip_summed = ((rx_buf->flags & EF4_RX_PKT_CSUMMED) ? @@ -672,7 +672,7 @@ void __ef4_rx_packet(struct ef4_channel *channel) goto out; }
- if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM))) + if (unlikely(!netdev_active_feature_test(efx->net_dev, NETIF_F_RXCSUM_BIT))) rx_buf->flags &= ~EF4_RX_PKT_CSUMMED;
if ((rx_buf->flags & EF4_RX_PKT_TCP) && !channel->type->receive_skb) diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index 148dcd48b58d..061e67724f2e 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -921,7 +921,7 @@ static u16 efx_farch_handle_rx_not_ok(struct efx_rx_queue *rx_queue, (void) rx_ev_other_err; #endif
- if (efx->net_dev->features & NETIF_F_RXALL) + if (netdev_active_feature_test(efx->net_dev, NETIF_F_RXALL_BIT)) /* don't discard frame for CRC error */ rx_ev_eth_crc_err = false;
diff --git a/drivers/net/ethernet/sfc/mcdi_filters.c b/drivers/net/ethernet/sfc/mcdi_filters.c index 508549db124b..d0bb15312e28 100644 --- a/drivers/net/ethernet/sfc/mcdi_filters.c +++ b/drivers/net/ethernet/sfc/mcdi_filters.c @@ -1343,7 +1343,7 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining)
table->mc_promisc_last = false; table->vlan_filter = - !!(efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_FILTER); + netdev_active_feature_test(efx->net_dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT); INIT_LIST_HEAD(&table->vlan_list); init_rwsem(&table->lock);
@@ -1760,7 +1760,7 @@ void efx_mcdi_filter_sync_rx_mode(struct efx_nic *efx) * Do it in advance to avoid conflicts for unicast untagged and * VLAN 0 tagged filters. */ - vlan_filter = !!(net_dev->features & NETIF_F_HW_VLAN_CTAG_FILTER); + vlan_filter = netdev_active_feature_test(net_dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT); if (table->vlan_filter != vlan_filter) { table->vlan_filter = vlan_filter; efx_mcdi_filter_remove_old(efx); diff --git a/drivers/net/ethernet/sfc/mcdi_port_common.c b/drivers/net/ethernet/sfc/mcdi_port_common.c index 899cc1671004..52f24c51cdfc 100644 --- a/drivers/net/ethernet/sfc/mcdi_port_common.c +++ b/drivers/net/ethernet/sfc/mcdi_port_common.c @@ -1110,7 +1110,7 @@ int efx_mcdi_set_mac(struct efx_nic *efx)
MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_FLAGS, SET_MAC_IN_FLAG_INCLUDE_FCS, - !!(efx->net_dev->features & NETIF_F_RXFCS)); + netdev_active_feature_test(efx->net_dev, NETIF_F_RXFCS_BIT));
switch (efx->wanted_fc) { case EFX_FC_RX | EFX_FC_TX: diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 2375cef577e4..f64ae5623309 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -387,7 +387,7 @@ void __efx_rx_packet(struct efx_channel *channel) if (!efx_do_xdp(efx, channel, rx_buf, &eh)) goto out;
- if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM))) + if (unlikely(!netdev_active_feature_test(efx->net_dev, NETIF_F_RXCSUM_BIT))) rx_buf->flags &= ~EFX_RX_PKT_CSUMMED;
if ((rx_buf->flags & EFX_RX_PKT_TCP) && !channel->type->receive_skb) diff --git a/drivers/net/ethernet/sfc/rx_common.c b/drivers/net/ethernet/sfc/rx_common.c index acdc3c84aaaa..ce0f78135f81 100644 --- a/drivers/net/ethernet/sfc/rx_common.c +++ b/drivers/net/ethernet/sfc/rx_common.c @@ -517,7 +517,7 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, return; }
- if (efx->net_dev->features & NETIF_F_RXHASH && + if (netdev_active_feature_test(efx->net_dev, NETIF_F_RXHASH_BIT) && efx_rx_buf_hash_valid(efx, eh)) skb_set_hash(skb, efx_rx_buf_hash(efx, eh), PKT_HASH_TYPE_L3); @@ -796,7 +796,7 @@ int efx_probe_filters(struct efx_nic *efx) goto out_unlock;
#ifdef CONFIG_RFS_ACCEL - if (*efx->type->offload_features & NETIF_F_NTUPLE) { + if (netdev_feature_test(NETIF_F_NTUPLE_BIT, *efx->type->offload_features)) { struct efx_channel *channel; int i, success = 1;
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h index 067b90ca3084..56bdec209b1c 100644 --- a/include/linux/netdev_features_helper.h +++ b/include/linux/netdev_features_helper.h @@ -588,8 +588,8 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, netdev_features_t tmp;
tmp = netdev_features_xor(f1, f2); - if (tmp & NETIF_F_HW_CSUM) { - if (f1 & NETIF_F_HW_CSUM) + if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, tmp)) { + if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, f1)) netdev_features_set(&f1, netdev_ip_csum_features); else netdev_features_set(&f2, netdev_ip_csum_features); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a092423653e2..91983aede92c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2333,7 +2333,7 @@ static inline bool netdev_feature_test(int nr, const netdev_features_t src)
static inline bool netif_elide_gro(const struct net_device *dev) { - if (!(dev->features & NETIF_F_GRO) || dev->xdp_prog) + if (!netdev_active_feature_test(dev, NETIF_F_GRO_BIT) || dev->xdp_prog) return true; return false; } @@ -4354,7 +4354,7 @@ static inline void netif_tx_unlock_bh(struct net_device *dev) }
#define HARD_TX_LOCK(dev, txq, cpu) { \ - if ((dev->features & NETIF_F_LLTX) == 0) { \ + if (!netdev_active_feature_test(dev, NETIF_F_LLTX_BIT)) { \ __netif_tx_lock(txq, cpu); \ } else { \ __netif_tx_acquire(txq); \ @@ -4362,12 +4362,12 @@ static inline void netif_tx_unlock_bh(struct net_device *dev) }
#define HARD_TX_TRYLOCK(dev, txq) \ - (((dev->features & NETIF_F_LLTX) == 0) ? \ + (!netdev_active_feature_test(dev, NETIF_F_LLTX_BIT) ? \ __netif_tx_trylock(txq) : \ __netif_tx_acquire(txq))
#define HARD_TX_UNLOCK(dev, txq) { \ - if ((dev->features & NETIF_F_LLTX) == 0) { \ + if (!netdev_active_feature_test(dev, NETIF_F_LLTX_BIT)) { \ __netif_tx_unlock(txq); \ } else { \ __netif_tx_release(txq); \ @@ -4768,20 +4768,20 @@ static inline bool can_checksum_protocol(netdev_features_t features, __be16 protocol) { if (protocol == htons(ETH_P_FCOE)) - return !!(features & NETIF_F_FCOE_CRC); + return netdev_feature_test(NETIF_F_FCOE_CRC_BIT, features);
/* Assume this is an IP checksum (not SCTP CRC) */
- if (features & NETIF_F_HW_CSUM) { + if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features)) { /* Can checksum everything */ return true; }
switch (protocol) { case htons(ETH_P_IP): - return !!(features & NETIF_F_IP_CSUM); + return netdev_feature_test(NETIF_F_IP_CSUM_BIT, features); case htons(ETH_P_IPV6): - return !!(features & NETIF_F_IPV6_CSUM); + return netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, features); default: return false; } @@ -4898,7 +4898,8 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type) static inline bool skb_gso_ok(struct sk_buff *skb, netdev_features_t features) { return net_gso_ok(features, skb_shinfo(skb)->gso_type) && - (!skb_has_frag_list(skb) || (features & NETIF_F_FRAGLIST)); + (!skb_has_frag_list(skb) || + netdev_feature_test(NETIF_F_FRAGLIST_BIT, features)); }
static inline bool netif_needs_gso(struct sk_buff *skb, diff --git a/net/core/dev.c b/net/core/dev.c index 124d48b5d61a..2bcb65722583 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1586,7 +1586,7 @@ void dev_disable_lro(struct net_device *dev) netdev_wanted_feature_del(dev, NETIF_F_LRO_BIT); netdev_update_features(dev);
- if (unlikely(dev->features & NETIF_F_LRO)) + if (unlikely(netdev_active_feature_test(dev, NETIF_F_LRO_BIT))) netdev_WARN(dev, "failed to disable LRO!\n");
netdev_for_each_lower_dev(dev, lower_dev, iter) @@ -1607,7 +1607,7 @@ static void dev_disable_gro_hw(struct net_device *dev) netdev_wanted_feature_del(dev, NETIF_F_GRO_HW_BIT); netdev_update_features(dev);
- if (unlikely(dev->features & NETIF_F_GRO_HW)) + if (unlikely(netdev_active_feature_test(dev, NETIF_F_GRO_HW_BIT))) netdev_WARN(dev, "failed to disable GRO_HW!\n"); }
@@ -3339,7 +3339,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, * support segmentation on this frame without needing additional * work. */ - if (features & NETIF_F_GSO_PARTIAL) { + if (netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, features)) { netdev_features_t partial_features; struct net_device *dev = skb->dev;
@@ -3389,7 +3389,7 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) #ifdef CONFIG_HIGHMEM int i;
- if (!(dev->features & NETIF_F_HIGHDMA)) { + if (!netdev_active_feature_test(dev, NETIF_F_HIGHDMA_BIT)) { for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -3587,10 +3587,10 @@ int skb_csum_hwoffload_help(struct sk_buff *skb, const netdev_features_t features) { if (unlikely(skb_csum_is_sctp(skb))) - return !!(features & NETIF_F_SCTP_CRC) ? 0 : + return netdev_feature_test(NETIF_F_SCTP_CRC_BIT, features) ? 0 : skb_crc32c_csum_help(skb);
- if (features & NETIF_F_HW_CSUM) + if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features)) return 0;
if (features & netdev_ip_csum_features) { @@ -4343,7 +4343,7 @@ set_rps_cpu(struct net_device *dev, struct sk_buff *skb,
/* Should we steer this flow to a different hardware queue? */ if (!skb_rx_queue_recorded(skb) || !dev->rx_cpu_rmap || - !(dev->features & NETIF_F_NTUPLE)) + !netdev_active_feature_test(dev, NETIF_F_NTUPLE_BIT)) goto out; rxq_index = cpu_rmap_lookup_index(dev->rx_cpu_rmap, next_cpu); if (rxq_index == skb_get_rx_queue(skb)) @@ -9503,89 +9503,94 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, netdev_features_t tmp;
/* Fix illegal checksum combinations */ - if ((features & NETIF_F_HW_CSUM) && + if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features) && (features & netdev_ip_csum_features)) { netdev_warn(dev, "mixed HW and IP checksum settings.\n"); netdev_features_clear(&features, netdev_ip_csum_features); }
/* TSO requires that SG is present as well. */ - if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) { + if (features & NETIF_F_ALL_TSO && !netdev_feature_test(NETIF_F_SG_BIT, features)) { netdev_dbg(dev, "Dropping TSO features since no SG feature.\n"); netdev_features_clear(&features, NETIF_F_ALL_TSO); }
- if ((features & NETIF_F_TSO) && !(features & NETIF_F_HW_CSUM) && - !(features & NETIF_F_IP_CSUM)) { + if (netdev_feature_test(NETIF_F_TSO_BIT, features) && + !netdev_feature_test(NETIF_F_HW_CSUM_BIT, features) && + !netdev_feature_test(NETIF_F_IP_CSUM_BIT, features)) { netdev_dbg(dev, "Dropping TSO features since no CSUM feature.\n"); netdev_feature_del(NETIF_F_TSO_BIT, &features); netdev_feature_del(NETIF_F_TSO_ECN_BIT, &features); }
- if ((features & NETIF_F_TSO6) && !(features & NETIF_F_HW_CSUM) && - !(features & NETIF_F_IPV6_CSUM)) { + if (netdev_feature_test(NETIF_F_TSO6_BIT, features) && + !netdev_feature_test(NETIF_F_HW_CSUM_BIT, features) && + !netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, features)) { netdev_dbg(dev, "Dropping TSO6 features since no CSUM feature.\n"); netdev_feature_del(NETIF_F_TSO6_BIT, &features); }
/* TSO with IPv4 ID mangling requires IPv4 TSO be enabled */ - if ((features & NETIF_F_TSO_MANGLEID) && !(features & NETIF_F_TSO)) + if (netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features) && + !netdev_feature_test(NETIF_F_TSO_BIT, features)) netdev_feature_del(NETIF_F_TSO_MANGLEID_BIT, &features);
/* TSO ECN requires that TSO is present as well. */ tmp = NETIF_F_ALL_TSO; netdev_feature_del(NETIF_F_TSO_ECN_BIT, &tmp); - if (!(features & tmp) && (features & NETIF_F_TSO_ECN)) + if (!(features & tmp) && netdev_feature_test(NETIF_F_TSO_ECN_BIT, features)) netdev_feature_del(NETIF_F_TSO_ECN_BIT, &features);
/* Software GSO depends on SG. */ - if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) { + if ((netdev_feature_test(NETIF_F_GSO_BIT, features)) && !(netdev_feature_test(NETIF_F_SG_BIT, features))) { netdev_dbg(dev, "Dropping NETIF_F_GSO since no SG feature.\n"); netdev_feature_del(NETIF_F_GSO_BIT, &features); }
/* GSO partial features require GSO partial be set */ if ((features & dev->gso_partial_features) && - !(features & NETIF_F_GSO_PARTIAL)) { + !netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, features)) { netdev_dbg(dev, "Dropping partially supported GSO features since no GSO partial.\n"); netdev_features_clear(&features, dev->gso_partial_features); }
- if (!(features & NETIF_F_RXCSUM)) { + if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) { /* 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) { + if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) { netdev_dbg(dev, "Dropping NETIF_F_GRO_HW since no RXCSUM feature.\n"); netdev_feature_del(NETIF_F_GRO_HW_BIT, &features); } }
/* LRO/HW-GRO features cannot be combined with RX-FCS */ - if (features & NETIF_F_RXFCS) { - if (features & NETIF_F_LRO) { + if (netdev_feature_test(NETIF_F_RXFCS_BIT, features)) { + if (netdev_feature_test(NETIF_F_LRO_BIT, features)) { netdev_dbg(dev, "Dropping LRO feature since RX-FCS is requested.\n"); netdev_feature_del(NETIF_F_LRO_BIT, &features); }
- if (features & NETIF_F_GRO_HW) { + if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) { netdev_dbg(dev, "Dropping HW-GRO feature since RX-FCS is requested.\n"); netdev_feature_del(NETIF_F_GRO_HW_BIT, &features); } }
- if ((features & NETIF_F_GRO_HW) && (features & NETIF_F_LRO)) { + if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features) && + netdev_feature_test(NETIF_F_LRO_BIT, features)) { netdev_dbg(dev, "Dropping LRO feature since HW-GRO is requested.\n"); netdev_feature_del(NETIF_F_LRO_BIT, &features); }
- if (features & NETIF_F_HW_TLS_TX) { + if (netdev_feature_test(NETIF_F_HW_TLS_TX_BIT, features)) { bool ip_csum = (features & netdev_ip_csum_features) == netdev_ip_csum_features; - bool hw_csum = features & NETIF_F_HW_CSUM; + bool hw_csum = netdev_feature_test(NETIF_F_HW_CSUM_BIT, + features);
if (!ip_csum && !hw_csum) { netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n"); @@ -9593,7 +9598,8 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, } }
- if ((features & NETIF_F_HW_TLS_RX) && !(features & NETIF_F_RXCSUM)) { + if (netdev_feature_test(NETIF_F_HW_TLS_RX_BIT, features) && + !netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) { netdev_dbg(dev, "Dropping TLS RX HW offload feature since no RXCSUM feature.\n"); netdev_feature_del(NETIF_F_HW_TLS_RX_BIT, &features); } @@ -9655,7 +9661,7 @@ int __netdev_update_features(struct net_device *dev)
diff = netdev_features_xor(features, dev->features);
- if (diff & NETIF_F_RX_UDP_TUNNEL_PORT) { + if (netdev_feature_test(NETIF_F_RX_UDP_TUNNEL_PORT_BIT, diff)) { /* udp_tunnel_{get,drop}_rx_info both need * NETIF_F_RX_UDP_TUNNEL_PORT enabled on the * device, or they won't do anything. @@ -9663,7 +9669,8 @@ int __netdev_update_features(struct net_device *dev) * *before* calling udp_tunnel_get_rx_info, * but *after* calling udp_tunnel_drop_rx_info. */ - if (features & NETIF_F_RX_UDP_TUNNEL_PORT) { + if (netdev_feature_test(NETIF_F_RX_UDP_TUNNEL_PORT_BIT, + features)) { dev->features = features; udp_tunnel_get_rx_info(dev); } else { @@ -9671,8 +9678,9 @@ int __netdev_update_features(struct net_device *dev) } }
- if (diff & NETIF_F_HW_VLAN_CTAG_FILTER) { - if (features & NETIF_F_HW_VLAN_CTAG_FILTER) { + if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, diff)) { + if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + features)) { dev->features = features; err |= vlan_get_rx_ctag_filter_info(dev); } else { @@ -9680,8 +9688,9 @@ int __netdev_update_features(struct net_device *dev) } }
- if (diff & NETIF_F_HW_VLAN_STAG_FILTER) { - if (features & NETIF_F_HW_VLAN_STAG_FILTER) { + if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT, diff)) { + if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT, + features)) { dev->features = features; err |= vlan_get_rx_stag_filter_info(dev); } else { @@ -9915,8 +9924,8 @@ int register_netdevice(struct net_device *dev) } }
- if ((dev->hw_features & NETIF_F_HW_VLAN_CTAG_FILTER || - dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) && + if ((netdev_hw_feature_test(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT) || + netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT)) && (!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"); @@ -9952,13 +9961,13 @@ int register_netdevice(struct net_device *dev) * of ignoring a static IP ID value. This doesn't enable the * feature itself but allows the user to enable it later. */ - if (dev->hw_features & NETIF_F_TSO) + if (netdev_hw_feature_test(dev, NETIF_F_TSO_BIT)) netdev_hw_feature_add(dev, NETIF_F_TSO_MANGLEID_BIT); - if (dev->vlan_features & NETIF_F_TSO) + if (netdev_vlan_feature_test(dev, NETIF_F_TSO_BIT)) netdev_vlan_feature_add(dev, NETIF_F_TSO_MANGLEID_BIT); - if (dev->mpls_features & NETIF_F_TSO) + if (netdev_mpls_feature_test(dev, NETIF_F_TSO_BIT)) netdev_mpls_feature_add(dev, NETIF_F_TSO_MANGLEID_BIT); - if (dev->hw_enc_features & NETIF_F_TSO) + if (netdev_hw_enc_feature_test(dev, NETIF_F_TSO_BIT)) netdev_hw_enc_feature_add(dev, NETIF_F_TSO_MANGLEID_BIT);
/* Make NETIF_F_HIGHDMA inheritable to VLAN devices. @@ -10859,7 +10868,7 @@ int __dev_change_net_namespace(struct net_device *dev, struct net *net,
/* Don't allow namespace local devices to be moved. */ err = -EINVAL; - if (dev->features & NETIF_F_NETNS_LOCAL) + if (netdev_active_feature_test(dev, NETIF_F_NETNS_LOCAL_BIT)) goto out;
/* Ensure the device has been registrered */ @@ -11057,7 +11066,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all, { netdev_features_t tmp;
- if (mask & NETIF_F_HW_CSUM) + if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, mask)) netdev_features_set(&mask, NETIF_F_CSUM_MASK); netdev_feature_add(NETIF_F_VLAN_CHALLENGED_BIT, &mask);
@@ -11072,7 +11081,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all, all &= tmp;
/* If one device supports hw checksumming, set for all. */ - if (all & NETIF_F_HW_CSUM) { + if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, all)) { tmp = NETIF_F_CSUM_MASK; netdev_feature_del(NETIF_F_HW_CSUM_BIT, &tmp); netdev_features_clear(&all, tmp); @@ -11230,7 +11239,7 @@ static void __net_exit default_device_exit_net(struct net *net) char fb_name[IFNAMSIZ];
/* Ignore unmoveable devices (i.e. loopback) */ - if (dev->features & NETIF_F_NETNS_LOCAL) + if (netdev_active_feature_test(dev, NETIF_F_NETNS_LOCAL_BIT)) continue;
/* Leave virtual devices for the generic cleanup */ diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 3c951a883076..77f57fe00160 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -322,15 +322,15 @@ static u32 __ethtool_get_flags(struct net_device *dev) { u32 flags = 0;
- if (dev->features & NETIF_F_LRO) + if (netdev_active_feature_test(dev, NETIF_F_LRO_BIT)) flags |= ETH_FLAG_LRO; - if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) + if (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) flags |= ETH_FLAG_RXVLAN; - if (dev->features & NETIF_F_HW_VLAN_CTAG_TX) + if (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_TX_BIT)) flags |= ETH_FLAG_TXVLAN; - if (dev->features & NETIF_F_NTUPLE) + if (netdev_active_feature_test(dev, NETIF_F_NTUPLE_BIT)) flags |= ETH_FLAG_NTUPLE; - if (dev->features & NETIF_F_RXHASH) + if (netdev_active_feature_test(dev, NETIF_F_RXHASH_BIT)) flags |= ETH_FLAG_RXHASH;
return flags;
Replace the '(f1 & f2)' operations of features by netdev_features_intersects helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/sfc/efx_common.c | 4 ++-- net/core/dev.c | 21 ++++++++++++--------- net/ethtool/ioctl.c | 6 +++--- 3 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 31363adcf5f1..769f3a8b3ff9 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -1364,14 +1364,14 @@ netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev struct efx_nic *efx = netdev_priv(dev);
if (skb->encapsulation) { - if (features & NETIF_F_GSO_MASK) + if (netdev_features_intersects(features, NETIF_F_GSO_MASK)) /* Hardware can only do TSO with at most 208 bytes * of headers. */ if (skb_inner_transport_offset(skb) > EFX_TSO2_MAX_HDRLEN) netdev_features_clear(&features, NETIF_F_GSO_MASK); - if (features & netdev_csum_gso_features_mask) + if (netdev_features_intersects(features, netdev_csum_gso_features_mask)) if (!efx_can_encap_offloads(efx, skb)) netdev_features_clear(&features, netdev_csum_gso_features_mask); diff --git a/net/core/dev.c b/net/core/dev.c index 2bcb65722583..a83c2dcda755 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3593,7 +3593,7 @@ int skb_csum_hwoffload_help(struct sk_buff *skb, if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features)) return 0;
- if (features & netdev_ip_csum_features) { + if (netdev_features_intersects(features, netdev_ip_csum_features)) { switch (skb->csum_offset) { case offsetof(struct tcphdr, check): case offsetof(struct udphdr, check): @@ -9461,8 +9461,8 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower, upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { feature = __NETIF_F_BIT(feature_bit); - if (!(upper->wanted_features & feature) - && (features & feature)) { + if (!netdev_wanted_features_intersects(upper, feature) && + netdev_features_intersects(features, feature)) { netdev_dbg(lower, "Dropping feature %pNF, upper dev %s has it off.\n", &feature, upper->name); netdev_features_clear(&features, feature); @@ -9482,13 +9482,14 @@ static void netdev_sync_lower_features(struct net_device *upper, upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { feature = __NETIF_F_BIT(feature_bit); - if (!(features & feature) && (lower->features & feature)) { + if (!netdev_features_intersects(features, feature) && + netdev_active_features_intersects(lower, feature)) { netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", &feature, lower->name); netdev_wanted_features_clear(lower, feature); __netdev_update_features(lower);
- if (unlikely(lower->features & feature)) + if (unlikely(netdev_active_features_intersects(lower, feature))) netdev_WARN(upper, "failed to disable %pNF on %s!\n", &feature, lower->name); else @@ -9504,13 +9505,14 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
/* Fix illegal checksum combinations */ if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features) && - (features & netdev_ip_csum_features)) { + netdev_features_intersects(features, netdev_ip_csum_features)) { netdev_warn(dev, "mixed HW and IP checksum settings.\n"); netdev_features_clear(&features, netdev_ip_csum_features); }
/* TSO requires that SG is present as well. */ - if (features & NETIF_F_ALL_TSO && !netdev_feature_test(NETIF_F_SG_BIT, features)) { + if (netdev_features_intersects(features, NETIF_F_ALL_TSO) && + !netdev_feature_test(NETIF_F_SG_BIT, features)) { netdev_dbg(dev, "Dropping TSO features since no SG feature.\n"); netdev_features_clear(&features, NETIF_F_ALL_TSO); } @@ -9538,7 +9540,8 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, /* TSO ECN requires that TSO is present as well. */ tmp = NETIF_F_ALL_TSO; netdev_feature_del(NETIF_F_TSO_ECN_BIT, &tmp); - if (!(features & tmp) && netdev_feature_test(NETIF_F_TSO_ECN_BIT, features)) + if (!netdev_features_intersects(features, tmp) && + netdev_feature_test(NETIF_F_TSO_ECN_BIT, features)) netdev_feature_del(NETIF_F_TSO_ECN_BIT, &features);
/* Software GSO depends on SG. */ @@ -9548,7 +9551,7 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, }
/* GSO partial features require GSO partial be set */ - if ((features & dev->gso_partial_features) && + if (netdev_gso_partial_features_intersects(dev, features) && !netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, features)) { netdev_dbg(dev, "Dropping partially supported GSO features since no GSO partial.\n"); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 77f57fe00160..3fd1aa89de87 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -165,7 +165,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) __netdev_update_features(dev);
tmp = netdev_wanted_features_xor(dev, dev->features); - if (tmp & valid) + if (netdev_features_intersects(tmp, valid)) ret |= ETHTOOL_F_WISH;
return ret; @@ -278,7 +278,7 @@ static int ethtool_get_one_feature(struct net_device *dev, };
mask = ethtool_get_feature_mask(ethcmd); - edata.data = !!(dev->features & mask); + edata.data = !!netdev_active_features_intersects(dev, mask); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; @@ -366,7 +366,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) changed &= eth_all_features; tmp = netdev_hw_features_andnot_r(dev, changed); if (tmp) - return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP; + return netdev_hw_features_intersects(dev, changed) ? -EINVAL : -EOPNOTSUPP;
netdev_wanted_features_clear(dev, changed); tmp = features & changed;
Replace the '&' and '&=' operations of features by netdev_features_and helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- include/linux/netdev_features_helper.h | 2 +- net/core/dev.c | 18 ++++++++++-------- net/ethtool/features.c | 3 ++- net/ethtool/ioctl.c | 10 +++++----- 4 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h index 56bdec209b1c..79fa490b96cf 100644 --- a/include/linux/netdev_features_helper.h +++ b/include/linux/netdev_features_helper.h @@ -595,7 +595,7 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, netdev_features_set(&f2, netdev_ip_csum_features); }
- return f1 & f2; + return netdev_features_and(f1, f2); }
static inline netdev_features_t diff --git a/net/core/dev.c b/net/core/dev.c index a83c2dcda755..7f75084bcaa7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3343,7 +3343,8 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t partial_features; struct net_device *dev = skb->dev;
- partial_features = dev->features & dev->gso_partial_features; + partial_features = netdev_active_features_and(dev, + dev->gso_partial_features); netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, &partial_features); if (!skb_gso_ok(skb, netdev_features_or(features, partial_features))) netdev_feature_del(NETIF_F_GSO_PARTIAL_BIT, &features); @@ -3410,7 +3411,7 @@ static netdev_features_t net_mpls_features(struct sk_buff *skb, __be16 type) { if (eth_p_mpls(type)) - features &= skb->dev->mpls_features; + netdev_features_mask(&features, skb->dev->mpls_features);
return features; } @@ -3511,7 +3512,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) * features for the netdev */ if (skb->encapsulation) - features &= dev->hw_enc_features; + netdev_features_mask(&features, dev->hw_enc_features);
if (skb_vlan_tagged(skb)) { tmp = netdev_vlan_features_or(dev, netdev_tx_vlan_features); @@ -3522,7 +3523,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) tmp = dev->netdev_ops->ndo_features_check(skb, dev, features); else tmp = dflt_features_check(skb, dev, features); - features &= tmp; + netdev_features_mask(&features, tmp);
return harmonize_features(skb, features); } @@ -9954,7 +9955,8 @@ int register_netdevice(struct net_device *dev) netdev_hw_feature_add(dev, NETIF_F_RX_UDP_TUNNEL_PORT_BIT); }
- dev->wanted_features = dev->features & dev->hw_features; + dev->wanted_features = netdev_active_features_and(dev, + dev->hw_features);
if (!(dev->flags & IFF_LOOPBACK)) netdev_hw_feature_add(dev, NETIF_F_NOCACHE_COPY_BIT); @@ -11074,14 +11076,14 @@ netdev_features_t netdev_increment_features(netdev_features_t all, netdev_feature_add(NETIF_F_VLAN_CHALLENGED_BIT, &mask);
tmp = netdev_features_or(NETIF_F_ONE_FOR_ALL, NETIF_F_CSUM_MASK); - tmp &= one; - tmp &= mask; + netdev_features_mask(&tmp, one); + netdev_features_mask(&tmp, mask); netdev_features_set(&all, tmp);
netdev_features_fill(&tmp); netdev_features_clear(&tmp, NETIF_F_ALL_FOR_ALL); netdev_features_set(&tmp, one); - all &= tmp; + netdev_features_mask(&all, tmp);
/* If one device supports hw checksumming, set for all. */ if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, all)) { diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 2de4cabf41e0..c4d7a1f9366a 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -257,7 +257,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)) { netdev_wanted_features_clear(dev, dev->hw_features); - tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features; + tmp = netdev_hw_features_and(dev, + ethnl_bitmap_to_features(req_wanted)); netdev_wanted_features_set(dev, tmp); __netdev_update_features(dev); } diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 3fd1aa89de87..9275c1b2a7f6 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -155,12 +155,12 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
netdev_hw_features_andnot_r(dev, valid); if (tmp) { - valid &= dev->hw_features; + netdev_features_mask(&valid, dev->hw_features); ret |= ETHTOOL_F_UNSUPPORTED; }
netdev_wanted_features_clear(dev, valid); - tmp = wanted & valid; + tmp = netdev_features_and(wanted, valid); netdev_wanted_features_set(dev, tmp); __netdev_update_features(dev);
@@ -294,7 +294,7 @@ static int ethtool_set_one_feature(struct net_device *dev, return -EFAULT;
mask = ethtool_get_feature_mask(ethcmd); - mask &= dev->hw_features; + netdev_features_mask(&mask, dev->hw_features); if (!mask) return -EOPNOTSUPP;
@@ -363,13 +363,13 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
/* allow changing only bits set in hw_features */ changed = netdev_active_features_xor(dev, features); - changed &= eth_all_features; + netdev_features_mask(&changed, eth_all_features); tmp = netdev_hw_features_andnot_r(dev, changed); if (tmp) return netdev_hw_features_intersects(dev, changed) ? -EINVAL : -EOPNOTSUPP;
netdev_wanted_features_clear(dev, changed); - tmp = features & changed; + tmp = netdev_features_and(features, changed); netdev_wanted_features_set(dev, tmp);
__netdev_update_features(dev);
Replace the '(f1 & f2) == f2' operations of features by netdev_features_subset helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- net/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c index 7f75084bcaa7..03e64399c7b4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9591,8 +9591,8 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, }
if (netdev_feature_test(NETIF_F_HW_TLS_TX_BIT, features)) { - bool ip_csum = (features & netdev_ip_csum_features) == - netdev_ip_csum_features; + bool ip_csum = netdev_features_subset(features, + netdev_ip_csum_features); bool hw_csum = netdev_feature_test(NETIF_F_HW_CSUM_BIT, features);
Replace the '==' and '!=' operations of features by netdev_features_equal helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/sfc/efx_common.c | 2 +- drivers/net/ethernet/sfc/falcon/efx.c | 2 +- net/core/dev.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 769f3a8b3ff9..6851f2196041 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -417,7 +417,7 @@ static void efx_start_datapath(struct efx_nic *efx) netdev_hw_features_set(efx->net_dev, efx->net_dev->features); netdev_hw_features_clear(efx->net_dev, efx->fixed_features); netdev_active_features_set(efx->net_dev, efx->fixed_features); - if (efx->net_dev->features != old_features) + if (!netdev_active_features_equal(efx->net_dev, old_features)) netdev_features_change(efx->net_dev);
/* RX filters may also have scatter-enabled flags */ diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 52d3ced17602..0bbe83f661d1 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -644,7 +644,7 @@ static void ef4_start_datapath(struct ef4_nic *efx) netdev_hw_features_set(efx->net_dev, efx->net_dev->features); netdev_hw_features_clear(efx->net_dev, efx->fixed_features); netdev_active_features_set(efx->net_dev, efx->fixed_features); - if (efx->net_dev->features != old_features) + if (!netdev_active_features_equal(efx->net_dev, old_features)) netdev_features_change(efx->net_dev);
/* RX filters may also have scatter-enabled flags */ diff --git a/net/core/dev.c b/net/core/dev.c index 03e64399c7b4..c59f50898444 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9632,7 +9632,7 @@ int __netdev_update_features(struct net_device *dev) netdev_for_each_upper_dev_rcu(dev, upper, iter) features = netdev_sync_upper_features(dev, upper, features);
- if (dev->features == features) + if (netdev_active_features_equal(dev, features)) goto sync_lower;
netdev_dbg(dev, "Features changed: %pNF -> %pNF\n",
Replace the direct assignment for features members of netdev with netdev_features_copy helpers, for the nic drivers are not supposed to modify netdev_features directly
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- drivers/net/ethernet/sfc/ef10.c | 2 +- drivers/net/ethernet/sfc/falcon/efx.c | 4 ++-- net/core/dev.c | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index f872a624faad..06384ec2ac82 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2454,7 +2454,7 @@ static int hns3_nic_set_features(struct net_device *netdev, return ret; }
- netdev->features = features; + netdev_active_features_copy(netdev, features); return 0; }
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index bf8274c03176..b718dfae9389 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1371,7 +1371,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx) netdev_feature_add(NETIF_F_TSO_BIT, &hw_enc_features); netdev_active_features_set(efx->net_dev, encap_tso_features); } - efx->net_dev->hw_enc_features = hw_enc_features; + netdev_hw_enc_features_copy(efx->net_dev, hw_enc_features);
/* don't fail init if RSS setup doesn't work */ rc = efx->type->rx_push_rss_config(efx, false, diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 0bbe83f661d1..4fc2f06b2781 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2920,8 +2920,8 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, netdev_active_feature_add(net_dev, NETIF_F_RXCSUM_BIT); /* Mask for features that also apply to VLAN devices */ netdev_vlan_features_set_array(net_dev, &efx_vlan_feature_set); - net_dev->hw_features = netdev_active_features_andnot(net_dev, - efx->fixed_features); + netdev_hw_features_copy(net_dev, + netdev_active_features_andnot(net_dev, efx->fixed_features));
/* Disable VLAN filtering by default. It may be enforced if * the feature is fixed (i.e. VLAN filters are required to diff --git a/net/core/dev.c b/net/core/dev.c index c59f50898444..c7505f126318 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9675,7 +9675,7 @@ int __netdev_update_features(struct net_device *dev) */ if (netdev_feature_test(NETIF_F_RX_UDP_TUNNEL_PORT_BIT, features)) { - dev->features = features; + netdev_active_features_copy(dev, features); udp_tunnel_get_rx_info(dev); } else { udp_tunnel_drop_rx_info(dev); @@ -9685,7 +9685,7 @@ int __netdev_update_features(struct net_device *dev) if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, diff)) { if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) { - dev->features = features; + netdev_active_features_copy(dev, features); err |= vlan_get_rx_ctag_filter_info(dev); } else { vlan_drop_rx_ctag_filter_info(dev); @@ -9695,14 +9695,14 @@ int __netdev_update_features(struct net_device *dev) if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT, diff)) { if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT, features)) { - dev->features = features; + netdev_active_features_copy(dev, features); err |= vlan_get_rx_stag_filter_info(dev); } else { vlan_drop_rx_stag_filter_info(dev); } }
- dev->features = features; + netdev_active_features_copy(dev, features); }
return err < 0 ? 0 : 1; @@ -9955,8 +9955,8 @@ int register_netdevice(struct net_device *dev) netdev_hw_feature_add(dev, NETIF_F_RX_UDP_TUNNEL_PORT_BIT); }
- dev->wanted_features = netdev_active_features_and(dev, - dev->hw_features); + netdev_wanted_features_copy(dev, + netdev_active_features_and(dev, dev->hw_features));
if (!(dev->flags & IFF_LOOPBACK)) netdev_hw_feature_add(dev, NETIF_F_NOCACHE_COPY_BIT);
Replace the direct using for features members of netdev with netdev_xxx_features helpers, for the nic drivers are not supposed to modify netdev_features directly.
I'mo not sure for this patch is necessary, just keep the same rule with others.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 4 +-- drivers/net/ethernet/sfc/efx_common.c | 5 ++-- drivers/net/ethernet/sfc/falcon/efx.c | 5 ++-- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- include/linux/netdev_features_helper.h | 2 +- net/core/dev.c | 26 +++++++++++-------- net/ethtool/features.c | 14 +++++----- net/ethtool/ioctl.c | 16 ++++++------ 9 files changed, 41 insertions(+), 35 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 06384ec2ac82..f1d55fac404c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3326,7 +3326,7 @@ static void hns3_set_default_feature(struct net_device *netdev) if (test_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps)) netdev_active_feature_add(netdev, NETIF_F_HW_TC_BIT);
- netdev_hw_features_set(netdev, netdev->features); + netdev_hw_features_set(netdev, netdev_active_features(netdev)); if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) netdev_hw_feature_del(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
@@ -3336,7 +3336,7 @@ static void hns3_set_default_feature(struct net_device *netdev) features = netdev_active_features_andnot(netdev, vlan_off_features); netdev_vlan_features_set(netdev, features);
- netdev_hw_enc_features_set(netdev, netdev->vlan_features); + netdev_hw_enc_features_set(netdev, netdev_vlan_features(netdev)); netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT); }
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 6851f2196041..93e7a35ecb7d 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -413,8 +413,9 @@ static void efx_start_datapath(struct efx_nic *efx) /* Restore previously fixed features in hw_features and remove * features which are fixed now */ - old_features = efx->net_dev->features; - netdev_hw_features_set(efx->net_dev, efx->net_dev->features); + old_features = netdev_active_features(efx->net_dev); + netdev_hw_features_set(efx->net_dev, + netdev_active_features(efx->net_dev)); netdev_hw_features_clear(efx->net_dev, efx->fixed_features); netdev_active_features_set(efx->net_dev, efx->fixed_features); if (!netdev_active_features_equal(efx->net_dev, old_features)) diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 4fc2f06b2781..43ed76ed5533 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -640,8 +640,9 @@ static void ef4_start_datapath(struct ef4_nic *efx) /* Restore previously fixed features in hw_features and remove * features which are fixed now */ - old_features = efx->net_dev->features; - netdev_hw_features_set(efx->net_dev, efx->net_dev->features); + old_features = netdev_active_features(efx->net_dev); + netdev_hw_features_set(efx->net_dev, + netdev_active_features(efx->net_dev)); netdev_hw_features_clear(efx->net_dev, efx->fixed_features); netdev_active_features_set(efx->net_dev, efx->fixed_features); if (!netdev_active_features_equal(efx->net_dev, old_features)) diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h index 5365e2d8a975..137b3479135b 100644 --- a/drivers/net/ethernet/sfc/falcon/net_driver.h +++ b/drivers/net/ethernet/sfc/falcon/net_driver.h @@ -1303,7 +1303,7 @@ static inline netdev_features_t ef4_supported_features(const struct ef4_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return netdev_active_features_or(net_dev, net_dev->hw_features); + return netdev_active_features_or(net_dev, netdev_hw_features(net_dev)); }
/* Get the current TX queue insert index. */ diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index bcdcec3d61e1..f574e5c99584 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1688,7 +1688,7 @@ static inline netdev_features_t efx_supported_features(const struct efx_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return netdev_active_features_or(net_dev, net_dev->hw_features); + return netdev_active_features_or(net_dev, netdev_hw_features(net_dev)); }
/* Get the current TX queue insert index. */ diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h index 79fa490b96cf..6b2a9080fdea 100644 --- a/include/linux/netdev_features_helper.h +++ b/include/linux/netdev_features_helper.h @@ -603,7 +603,7 @@ netdev_get_wanted_features(struct net_device *dev) { netdev_features_t tmp;
- tmp = netdev_active_features_andnot(dev, dev->hw_features); + tmp = netdev_active_features_andnot(dev, netdev_hw_features(dev)); return netdev_wanted_features_or(dev, tmp); }
diff --git a/net/core/dev.c b/net/core/dev.c index c7505f126318..0962935f478e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3190,7 +3190,7 @@ static void skb_warn_bad_offload(const struct sk_buff *skb) } skb_dump(KERN_WARNING, skb, false); WARN(1, "%s: caps=(%pNF, %pNF)\n", - name, dev ? &dev->features : &null_features, + name, dev ? &netdev_active_features(dev) : &null_features, skb->sk ? &skb->sk->sk_route_caps : &null_features); }
@@ -3344,7 +3344,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, struct net_device *dev = skb->dev;
partial_features = netdev_active_features_and(dev, - dev->gso_partial_features); + netdev_gso_partial_features(dev)); netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, &partial_features); if (!skb_gso_ok(skb, netdev_features_or(features, partial_features))) netdev_feature_del(NETIF_F_GSO_PARTIAL_BIT, &features); @@ -3411,7 +3411,8 @@ static netdev_features_t net_mpls_features(struct sk_buff *skb, __be16 type) { if (eth_p_mpls(type)) - netdev_features_mask(&features, skb->dev->mpls_features); + netdev_features_mask(&features, + netdev_mpls_features(skb->dev));
return features; } @@ -3479,7 +3480,8 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, * segmented the frame. */ if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL)) - netdev_features_clear(&features, dev->gso_partial_features); + netdev_features_clear(&features, + netdev_gso_partial_features(dev));
/* Make sure to clear the IPv4 ID mangling feature if the * IPv4 header has the potential to be fragmented. @@ -3502,7 +3504,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) netdev_features_t features; netdev_features_t tmp;
- features = dev->features; + features = netdev_active_features(dev);
if (skb_is_gso(skb)) features = gso_features_check(skb, dev, features); @@ -3512,7 +3514,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) * features for the netdev */ if (skb->encapsulation) - netdev_features_mask(&features, dev->hw_enc_features); + netdev_features_mask(&features, netdev_hw_enc_features(dev));
if (skb_vlan_tagged(skb)) { tmp = netdev_vlan_features_or(dev, netdev_tx_vlan_features); @@ -9556,7 +9558,8 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, !netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, features)) { netdev_dbg(dev, "Dropping partially supported GSO features since no GSO partial.\n"); - netdev_features_clear(&features, dev->gso_partial_features); + netdev_features_clear(&features, + netdev_gso_partial_features(dev)); }
if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) { @@ -9636,7 +9639,7 @@ int __netdev_update_features(struct net_device *dev) goto sync_lower;
netdev_dbg(dev, "Features changed: %pNF -> %pNF\n", - &dev->features, &features); + &netdev_active_features(dev), &features);
if (dev->netdev_ops->ndo_set_features) err = dev->netdev_ops->ndo_set_features(dev, features); @@ -9646,7 +9649,7 @@ int __netdev_update_features(struct net_device *dev) if (unlikely(err < 0)) { netdev_err(dev, "set_features() failed (%d); wanted %pNF, left %pNF\n", - err, &features, &dev->features); + err, &features, &netdev_active_features(dev)); /* return non-0 since some features might have changed and * it's better to fire a spurious notification than miss it */ @@ -9663,7 +9666,8 @@ int __netdev_update_features(struct net_device *dev) if (!err) { netdev_features_t diff;
- diff = netdev_features_xor(features, dev->features); + diff = netdev_features_xor(features, + netdev_active_features(dev));
if (netdev_feature_test(NETIF_F_RX_UDP_TUNNEL_PORT_BIT, diff)) { /* udp_tunnel_{get,drop}_rx_info both need @@ -9956,7 +9960,7 @@ int register_netdevice(struct net_device *dev) }
netdev_wanted_features_copy(dev, - netdev_active_features_and(dev, dev->hw_features)); + netdev_active_features_and(dev, netdev_hw_features(dev)));
if (!(dev->flags & IFF_LOOPBACK)) netdev_hw_feature_add(dev, NETIF_F_NOCACHE_COPY_BIT); diff --git a/net/ethtool/features.c b/net/ethtool/features.c index c4d7a1f9366a..93d56e8921a1 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -42,9 +42,9 @@ static int features_prepare_data(const struct ethnl_req_info *req_base, struct net_device *dev = reply_base->dev; netdev_features_t all_features;
- ethnl_features_to_bitmap32(data->hw, dev->hw_features); - ethnl_features_to_bitmap32(data->wanted, dev->wanted_features); - ethnl_features_to_bitmap32(data->active, dev->features); + ethnl_features_to_bitmap32(data->hw, netdev_hw_features(dev)); + ethnl_features_to_bitmap32(data->wanted, netdev_wanted_features(dev)); + ethnl_features_to_bitmap32(data->active, netdev_active_features(dev)); ethnl_features_to_bitmap32(data->nochange, NETIF_F_NEVER_CHANGE); all_features = GENMASK_ULL(NETDEV_FEATURE_COUNT - 1, 0); ethnl_features_to_bitmap32(data->all, all_features); @@ -238,8 +238,8 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) dev = req_info.dev;
rtnl_lock(); - ethnl_features_to_bitmap(old_active, dev->features); - ethnl_features_to_bitmap(old_wanted, dev->wanted_features); + ethnl_features_to_bitmap(old_active, netdev_active_features(dev)); + ethnl_features_to_bitmap(old_wanted, netdev_wanted_features(dev)); ret = ethnl_parse_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT, tb[ETHTOOL_A_FEATURES_WANTED], netdev_features_strings, info->extack); @@ -256,13 +256,13 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) bitmap_andnot(new_wanted, old_wanted, req_mask, NETDEV_FEATURE_COUNT); bitmap_or(req_wanted, new_wanted, req_wanted, NETDEV_FEATURE_COUNT); if (!bitmap_equal(req_wanted, old_wanted, NETDEV_FEATURE_COUNT)) { - netdev_wanted_features_clear(dev, dev->hw_features); + netdev_wanted_features_clear(dev, netdev_hw_features(dev)); tmp = netdev_hw_features_and(dev, ethnl_bitmap_to_features(req_wanted)); netdev_wanted_features_set(dev, tmp); __netdev_update_features(dev); } - ethnl_features_to_bitmap(new_active, dev->features); + ethnl_features_to_bitmap(new_active, netdev_active_features(dev)); mod = !bitmap_equal(old_active, new_active, NETDEV_FEATURE_COUNT);
ret = 0; diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 9275c1b2a7f6..02c2741c0d6b 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -97,9 +97,9 @@ static int ethtool_get_features(struct net_device *dev, void __user *useraddr) BUILD_BUG_ON(ETHTOOL_DEV_FEATURE_WORDS * sizeof(u32) > sizeof(netdev_features_t));
for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) { - features[i].available = (u32)(dev->hw_features >> (32 * i)); - features[i].requested = (u32)(dev->wanted_features >> (32 * i)); - features[i].active = (u32)(dev->features >> (32 * i)); + features[i].available = (u32)(netdev_hw_features(dev) >> (32 * i)); + features[i].requested = (u32)(netdev_wanted_features(dev) >> (32 * i)); + features[i].active = (u32)(netdev_active_features(dev) >> (32 * i)); features[i].never_changed = (u32)(NETIF_F_NEVER_CHANGE >> (32 * i)); } @@ -155,7 +155,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
netdev_hw_features_andnot_r(dev, valid); if (tmp) { - netdev_features_mask(&valid, dev->hw_features); + netdev_features_mask(&valid, netdev_hw_features(dev)); ret |= ETHTOOL_F_UNSUPPORTED; }
@@ -164,7 +164,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) netdev_wanted_features_set(dev, tmp); __netdev_update_features(dev);
- tmp = netdev_wanted_features_xor(dev, dev->features); + tmp = netdev_wanted_features_xor(dev, netdev_active_features(dev)); if (netdev_features_intersects(tmp, valid)) ret |= ETHTOOL_F_WISH;
@@ -294,7 +294,7 @@ static int ethtool_set_one_feature(struct net_device *dev, return -EFAULT;
mask = ethtool_get_feature_mask(ethcmd); - netdev_features_mask(&mask, dev->hw_features); + netdev_features_mask(&mask, netdev_hw_features(dev)); if (!mask) return -EOPNOTSUPP;
@@ -2836,7 +2836,7 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr, if (rc < 0) goto out; } - old_features = dev->features; + old_features = netdev_active_features(dev);
switch (ethcmd) { case ETHTOOL_GSET: @@ -3051,7 +3051,7 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr, if (dev->ethtool_ops->complete) dev->ethtool_ops->complete(dev);
- if (old_features != dev->features) + if (old_features != netdev_active_features(dev)) netdev_features_change(dev); out: if (dev->dev.parent)
For the prototype of netdev_features_t is u64, and the number of netdevice feature bits is 64 now. So there is no space to introduce new feature bit. Change the prototype of netdev_features_t from u64 to structure below: typedef struct { DECLARE_BITMAP(bits, NETDEV_FEATURE_COUNT); } netdev_features_t;
Rewrite the netdev_features helpers to adapt with new prototype.
To avoid mistake using NETIF_F_XXX as NETIF_F_XXX_BIT as input macroes for above helpers, remove all the macroes of NETIF_F_XXX for single feature bit.
With the prototype is no longer u64, the implementation of print interface for netdev features(%pNF) is changed to bitmap. So does the implementation of net/ethtool/.
Signed-off-by: Jian Shen shenjian15@huawei.com --- include/linux/netdev_features.h | 87 +--------------- include/linux/netdev_features_helper.h | 133 ++++++++++++++++--------- include/linux/netdevice.h | 45 +++++---- lib/vsprintf.c | 11 +- net/core/dev.c | 30 +++--- net/ethtool/features.c | 84 +++++----------- net/ethtool/ioctl.c | 31 +++--- 7 files changed, 175 insertions(+), 246 deletions(-)
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 16b2313e1dec..4cc66b017bce 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -10,8 +10,6 @@ #include <linux/cache.h> #include <asm/byteorder.h>
-typedef u64 netdev_features_t; - struct netdev_feature_set { unsigned int cnt; unsigned short feature_bits[]; @@ -163,94 +161,11 @@ extern struct netdev_feature_set netif_f_gso_encap_feature_set; extern struct netdev_feature_set netif_f_xfrm_feature_set; extern struct netdev_feature_set netif_f_tls_feature_set;
-/* copy'n'paste compression ;) */ -#define __NETIF_F_BIT(bit) ((netdev_features_t)1 << (bit)) -#define __NETIF_F(name) __NETIF_F_BIT(NETIF_F_##name##_BIT) - -#define NETIF_F_FCOE_CRC __NETIF_F(FCOE_CRC) -#define NETIF_F_FCOE_MTU __NETIF_F(FCOE_MTU) -#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) -#define NETIF_F_HW_CSUM __NETIF_F(HW_CSUM) -#define NETIF_F_HW_VLAN_CTAG_FILTER __NETIF_F(HW_VLAN_CTAG_FILTER) -#define NETIF_F_HW_VLAN_CTAG_RX __NETIF_F(HW_VLAN_CTAG_RX) -#define NETIF_F_HW_VLAN_CTAG_TX __NETIF_F(HW_VLAN_CTAG_TX) -#define NETIF_F_IP_CSUM __NETIF_F(IP_CSUM) -#define NETIF_F_IPV6_CSUM __NETIF_F(IPV6_CSUM) -#define NETIF_F_LLTX __NETIF_F(LLTX) -#define NETIF_F_LOOPBACK __NETIF_F(LOOPBACK) -#define NETIF_F_LRO __NETIF_F(LRO) -#define NETIF_F_NETNS_LOCAL __NETIF_F(NETNS_LOCAL) -#define NETIF_F_NOCACHE_COPY __NETIF_F(NOCACHE_COPY) -#define NETIF_F_NTUPLE __NETIF_F(NTUPLE) -#define NETIF_F_RXCSUM __NETIF_F(RXCSUM) -#define NETIF_F_RXHASH __NETIF_F(RXHASH) -#define NETIF_F_SCTP_CRC __NETIF_F(SCTP_CRC) -#define NETIF_F_SG __NETIF_F(SG) -#define NETIF_F_TSO6 __NETIF_F(TSO6) -#define NETIF_F_TSO_ECN __NETIF_F(TSO_ECN) -#define NETIF_F_TSO __NETIF_F(TSO) -#define NETIF_F_VLAN_CHALLENGED __NETIF_F(VLAN_CHALLENGED) -#define NETIF_F_RXFCS __NETIF_F(RXFCS) -#define NETIF_F_RXALL __NETIF_F(RXALL) -#define NETIF_F_GSO_GRE __NETIF_F(GSO_GRE) -#define NETIF_F_GSO_GRE_CSUM __NETIF_F(GSO_GRE_CSUM) -#define NETIF_F_GSO_IPXIP4 __NETIF_F(GSO_IPXIP4) -#define NETIF_F_GSO_IPXIP6 __NETIF_F(GSO_IPXIP6) -#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) -#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM) -#define NETIF_F_TSO_MANGLEID __NETIF_F(TSO_MANGLEID) -#define NETIF_F_GSO_PARTIAL __NETIF_F(GSO_PARTIAL) -#define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM) -#define NETIF_F_GSO_SCTP __NETIF_F(GSO_SCTP) -#define NETIF_F_GSO_ESP __NETIF_F(GSO_ESP) -#define NETIF_F_GSO_UDP __NETIF_F(GSO_UDP) -#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) -#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX) -#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX) -#define NETIF_F_HW_L2FW_DOFFLOAD __NETIF_F(HW_L2FW_DOFFLOAD) -#define NETIF_F_HW_TC __NETIF_F(HW_TC) -#define NETIF_F_HW_ESP __NETIF_F(HW_ESP) -#define NETIF_F_HW_ESP_TX_CSUM __NETIF_F(HW_ESP_TX_CSUM) -#define NETIF_F_RX_UDP_TUNNEL_PORT __NETIF_F(RX_UDP_TUNNEL_PORT) -#define NETIF_F_HW_TLS_RECORD __NETIF_F(HW_TLS_RECORD) -#define NETIF_F_GSO_UDP_L4 __NETIF_F(GSO_UDP_L4) -#define NETIF_F_HW_TLS_TX __NETIF_F(HW_TLS_TX) -#define NETIF_F_HW_TLS_RX __NETIF_F(HW_TLS_RX) -#define NETIF_F_GRO_FRAGLIST __NETIF_F(GRO_FRAGLIST) -#define NETIF_F_GSO_FRAGLIST __NETIF_F(GSO_FRAGLIST) -#define NETIF_F_HW_MACSEC __NETIF_F(HW_MACSEC) -#define NETIF_F_GRO_UDP_FWD __NETIF_F(GRO_UDP_FWD) -#define NETIF_F_HW_HSR_TAG_INS __NETIF_F(HW_HSR_TAG_INS) -#define NETIF_F_HW_HSR_TAG_RM __NETIF_F(HW_HSR_TAG_RM) -#define NETIF_F_HW_HSR_FWD __NETIF_F(HW_HSR_FWD) -#define NETIF_F_HW_HSR_DUP __NETIF_F(HW_HSR_DUP) - -/* Finds the next feature with the highest number of the range of start till 0. - */ -static inline int find_next_netdev_feature(u64 feature, unsigned long start) -{ - /* like BITMAP_LAST_WORD_MASK() for u64 - * this sets the most significant 64 - start to 0. - */ - feature &= ~0ULL >> (-start & ((sizeof(feature) * 8) - 1)); - - return fls64(feature) - 1; -} - /* This goes for the MSB to the LSB through the set feature bits, * mask_addr should be a u64 and bit an int */ #define for_each_netdev_feature(mask_addr, bit) \ - for ((bit) = find_next_netdev_feature((mask_addr), \ - NETDEV_FEATURE_COUNT); \ - (bit) >= 0; \ - (bit) = find_next_netdev_feature((mask_addr), (bit) - 1)) + for_each_set_bit(bit, (unsigned long *)(mask_addr.bits), NETDEV_FEATURE_COUNT)
/* Features valid for ethtool to change */ /* = all defined minus driver/device-class-related */ diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h index 6b2a9080fdea..43103acc23f4 100644 --- a/include/linux/netdev_features_helper.h +++ b/include/linux/netdev_features_helper.h @@ -9,24 +9,24 @@
static inline void netdev_features_zero(netdev_features_t *dst) { - *dst = 0; + bitmap_zero(dst->bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_features_fill(netdev_features_t *dst) { - *dst = ~0ULL; + bitmap_fill(dst->bits, NETDEV_FEATURE_COUNT); }
static inline bool netdev_features_empty(const netdev_features_t src) { - return src == 0; + return bitmap_empty(src.bits, NETDEV_FEATURE_COUNT); }
/* helpers for netdev features '==' operation */ static inline bool netdev_features_equal(const netdev_features_t src1, const netdev_features_t src2) { - return src1 == src2; + return bitmap_equal(src1.bits, src2.bits, NETDEV_FEATURE_COUNT); }
/* active_feature prefer to netdev->features */ @@ -55,7 +55,10 @@ static inline bool netdev_features_equal(const netdev_features_t src1, static inline netdev_features_t netdev_features_and(const netdev_features_t a, const netdev_features_t b) { - return a & b; + netdev_features_t dst; + + bitmap_and(dst.bits, a.bits, b.bits, NETDEV_FEATURE_COUNT); + return dst; }
#define netdev_active_features_and(ndev, __features) \ @@ -84,63 +87,74 @@ static inline void netdev_features_mask(netdev_features_t *dst, const netdev_features_t features) { - *dst = netdev_features_and(*dst, features); + bitmap_and(dst->bits, dst->bits, features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_active_features_mask(struct net_device *ndev, const netdev_features_t features) { - ndev->features = netdev_active_features_and(ndev, features); + bitmap_and(ndev->features.bits, ndev->features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_features_mask(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_features = netdev_hw_features_and(ndev, features); + bitmap_and(ndev->hw_features.bits, ndev->hw_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_wanted_features_mask(struct net_device *ndev, const netdev_features_t features) { - ndev->wanted_features = netdev_wanted_features_and(ndev, features); + bitmap_and(ndev->wanted_features.bits, ndev->wanted_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_vlan_features_mask(struct net_device *ndev, const netdev_features_t features) { - ndev->vlan_features = netdev_vlan_features_and(ndev, features); + bitmap_and(ndev->vlan_features.bits, ndev->vlan_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_enc_features_mask(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_enc_features = netdev_hw_enc_features_and(ndev, features); + bitmap_and(ndev->hw_enc_features.bits, ndev->hw_enc_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_mpls_features_mask(struct net_device *ndev, const netdev_features_t features) { - ndev->mpls_features = netdev_mpls_features_and(ndev, features); + bitmap_and(ndev->mpls_features.bits, ndev->mpls_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_gso_partial_features_mask(struct net_device *ndev, const netdev_features_t features) { - ndev->gso_partial_features = netdev_mpls_features_and(ndev, features); + bitmap_and(ndev->gso_partial_features.bits, + ndev->gso_partial_features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
/* helpers for netdev features '|' operation */ static inline netdev_features_t netdev_features_or(const netdev_features_t a, const netdev_features_t b) { - return a | b; + netdev_features_t dst; + + bitmap_or(dst.bits, a.bits, b.bits, NETDEV_FEATURE_COUNT); + return dst; }
#define netdev_active_features_or(ndev, __features) \ @@ -168,63 +182,74 @@ netdev_features_or(const netdev_features_t a, const netdev_features_t b) static inline void netdev_features_set(netdev_features_t *dst, const netdev_features_t features) { - *dst = netdev_features_or(*dst, features); + bitmap_or(dst->bits, dst->bits, features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_active_features_set(struct net_device *ndev, const netdev_features_t features) { - ndev->features = netdev_active_features_or(ndev, features); + bitmap_or(ndev->features.bits, ndev->features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_features_set(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_features = netdev_hw_features_or(ndev, features); + bitmap_or(ndev->hw_features.bits, ndev->hw_features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
static inline void netdev_wanted_features_set(struct net_device *ndev, const netdev_features_t features) { - ndev->wanted_features = netdev_wanted_features_or(ndev, features); + bitmap_or(ndev->wanted_features.bits, ndev->wanted_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_vlan_features_set(struct net_device *ndev, const netdev_features_t features) { - ndev->vlan_features = netdev_vlan_features_or(ndev, features); + bitmap_or(ndev->vlan_features.bits, ndev->vlan_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_enc_features_set(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_enc_features = netdev_hw_enc_features_or(ndev, features); + bitmap_or(ndev->hw_enc_features.bits, ndev->hw_enc_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_mpls_features_set(struct net_device *ndev, const netdev_features_t features) { - ndev->mpls_features = netdev_mpls_features_or(ndev, features); + bitmap_or(ndev->mpls_features.bits, ndev->mpls_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_gso_partial_features_set(struct net_device *ndev, const netdev_features_t features) { - ndev->gso_partial_features = netdev_mpls_features_or(ndev, features); + bitmap_or(ndev->gso_partial_features.bits, + ndev->gso_partial_features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
/* helpers for netdev features '^' operation */ static inline netdev_features_t netdev_features_xor(const netdev_features_t a, const netdev_features_t b) { - return a ^ b; + netdev_features_t dst; + + bitmap_xor(dst.bits, a.bits, b.bits, NETDEV_FEATURE_COUNT); + return dst; }
#define netdev_active_features_xor(ndev, __features) \ @@ -259,57 +284,67 @@ static inline void netdev_active_features_toggle(struct net_device *ndev, const netdev_features_t features) { - ndev->features = netdev_active_features_xor(ndev, features); + bitmap_xor(ndev->features.bits, ndev->features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_features_toggle(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_features = netdev_hw_features_xor(ndev, features); + bitmap_xor(ndev->hw_features.bits, ndev->hw_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_wanted_features_toggle(struct net_device *ndev, const netdev_features_t features) { - ndev->wanted_features = netdev_wanted_features_xor(ndev, features); + bitmap_xor(ndev->wanted_features.bits, ndev->wanted_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_vlan_features_toggle(struct net_device *ndev, const netdev_features_t features) { - ndev->vlan_features = netdev_vlan_features_xor(ndev, features); + bitmap_xor(ndev->vlan_features.bits, ndev->vlan_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_enc_features_toggle(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_enc_features = netdev_hw_enc_features_xor(ndev, features); + bitmap_xor(ndev->hw_enc_features.bits, ndev->hw_enc_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_mpls_features_toggle(struct net_device *ndev, const netdev_features_t features) { - ndev->mpls_features = netdev_mpls_features_xor(ndev, features); + bitmap_xor(ndev->mpls_features.bits, ndev->mpls_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_gso_partial_features_toggle(struct net_device *ndev, const netdev_features_t features) { - ndev->gso_partial_features = - netdev_gso_partial_features_xor(ndev, features); + bitmap_xor(ndev->gso_partial_features.bits, + ndev->gso_partial_features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
/* helpers for netdev features '& ~' operation */ static inline netdev_features_t netdev_features_andnot(const netdev_features_t a, const netdev_features_t b) { - return a & ~b; + netdev_features_t dst; + + bitmap_andnot(dst.bits, a.bits, b.bits, NETDEV_FEATURE_COUNT); + return dst; }
#define netdev_active_features_andnot(ndev, __features) \ @@ -357,63 +392,71 @@ netdev_features_andnot(const netdev_features_t a, const netdev_features_t b) static inline void netdev_features_clear(netdev_features_t *dst, const netdev_features_t features) { - *dst = netdev_features_andnot(*dst, features); + bitmap_andnot(dst->bits, dst->bits, features.bits, + NETDEV_FEATURE_COUNT); }
static inline void netdev_active_features_clear(struct net_device *ndev, const netdev_features_t features) { - ndev->features = netdev_active_features_andnot(ndev, features); + bitmap_andnot(ndev->features.bits, ndev->features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_features_clear(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_features = netdev_hw_features_andnot(ndev, features); + bitmap_andnot(ndev->features.bits, ndev->features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
static inline void netdev_wanted_features_clear(struct net_device *ndev, const netdev_features_t features) { - ndev->wanted_features = netdev_wanted_features_andnot(ndev, features); + bitmap_andnot(ndev->wanted_features.bits, ndev->wanted_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_vlan_features_clear(struct net_device *ndev, const netdev_features_t features) { - ndev->vlan_features = netdev_vlan_features_andnot(ndev, features); + bitmap_andnot(ndev->vlan_features.bits, ndev->vlan_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_enc_features_clear(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_enc_features = netdev_hw_enc_features_andnot(ndev, features); + bitmap_andnot(ndev->hw_enc_features.bits, ndev->hw_enc_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_mpls_features_clear(struct net_device *ndev, const netdev_features_t features) { - ndev->mpls_features = netdev_mpls_features_andnot(ndev, features); + bitmap_andnot(ndev->mpls_features.bits, ndev->mpls_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_gso_partial_features_clear(struct net_device *ndev, const netdev_features_t features) { - ndev->gso_partial_features = - netdev_gso_partial_features_andnot(ndev, features); + bitmap_andnot(ndev->gso_partial_features.bits, + ndev->gso_partial_features.bits, features.bits, + NETDEV_FEATURE_COUNT); }
/* helpers for netdev features 'set bit' operation */ static inline void netdev_feature_add(int nr, netdev_features_t *src) { - *src |= __NETIF_F_BIT(nr); + __set_bit(nr, src->bits); }
#define netdev_active_feature_add(ndev, nr) \ @@ -472,7 +515,7 @@ netdev_features_set_array(const struct netdev_feature_set *set, /* helpers for netdev features 'clear bit' operation */ static inline void netdev_feature_del(int nr, netdev_features_t *src) { - *src &= ~__NETIF_F_BIT(nr); + __clear_bit(nr, src->bits); }
#define netdev_active_feature_del(ndev, nr) \ @@ -499,7 +542,7 @@ static inline void netdev_feature_del(int nr, netdev_features_t *src) static inline bool netdev_features_intersects(const netdev_features_t src1, const netdev_features_t src2) { - return (src1 & src2) > 0; + return bitmap_intersects(src1.bits, src2.bits, NETDEV_FEATURE_COUNT); }
#define netdev_active_features_intersects(ndev, __features) \ @@ -579,7 +622,7 @@ static inline void netdev_gso_partial_features_copy(struct net_device *ndev, static inline bool netdev_features_subset(const netdev_features_t src1, const netdev_features_t src2) { - return (src1 & src2) == src2; + return bitmap_subset(src1.bits, src2.bits, NETDEV_FEATURE_COUNT); }
static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 91983aede92c..0c1a19671c1e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -4869,30 +4869,31 @@ netdev_features_t netif_skb_features(struct sk_buff *skb);
static inline bool net_gso_ok(netdev_features_t features, int gso_type) { - netdev_features_t feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT; +#define GSO_INDEX(x) ((1ULL << (x)) >> NETIF_F_GSO_SHIFT) + netdev_features_t feature;
/* check flags correspondence */ - BUILD_BUG_ON(SKB_GSO_TCPV4 != (NETIF_F_TSO >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_DODGY != (NETIF_F_GSO_ROBUST >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_TCP_FIXEDID != (NETIF_F_TSO_MANGLEID >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_TCPV6 != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_GRE != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_IPXIP4 != (NETIF_F_GSO_IPXIP4 >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_IPXIP6 != (NETIF_F_GSO_IPXIP6 >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_SCTP != (NETIF_F_GSO_SCTP >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_ESP != (NETIF_F_GSO_ESP >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_UDP != (NETIF_F_GSO_UDP >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_UDP_L4 != (NETIF_F_GSO_UDP_L4 >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_FRAGLIST != (NETIF_F_GSO_FRAGLIST >> NETIF_F_GSO_SHIFT)); - - return (features & feature) == feature; + BUILD_BUG_ON(SKB_GSO_TCPV4 != GSO_INDEX(NETIF_F_TSO_BIT)); + BUILD_BUG_ON(SKB_GSO_DODGY != GSO_INDEX(NETIF_F_GSO_ROBUST_BIT)); + BUILD_BUG_ON(SKB_GSO_TCP_ECN != GSO_INDEX(NETIF_F_TSO_ECN_BIT)); + BUILD_BUG_ON(SKB_GSO_TCP_FIXEDID != GSO_INDEX(NETIF_F_TSO_MANGLEID_BIT)); + BUILD_BUG_ON(SKB_GSO_TCPV6 != GSO_INDEX(NETIF_F_TSO6_BIT)); + BUILD_BUG_ON(SKB_GSO_FCOE != GSO_INDEX(NETIF_F_FSO_BIT)); + BUILD_BUG_ON(SKB_GSO_GRE != GSO_INDEX(NETIF_F_GSO_GRE_BIT)); + BUILD_BUG_ON(SKB_GSO_GRE_CSUM != GSO_INDEX(NETIF_F_GSO_GRE_CSUM_BIT)); + BUILD_BUG_ON(SKB_GSO_IPXIP4 != GSO_INDEX(NETIF_F_GSO_IPXIP4_BIT)); + BUILD_BUG_ON(SKB_GSO_IPXIP6 != GSO_INDEX(NETIF_F_GSO_IPXIP6_BIT)); + BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != GSO_INDEX(NETIF_F_GSO_UDP_TUNNEL_BIT)); + BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != GSO_INDEX(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT)); + BUILD_BUG_ON(SKB_GSO_PARTIAL != GSO_INDEX(NETIF_F_GSO_PARTIAL_BIT)); + BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != GSO_INDEX(NETIF_F_GSO_TUNNEL_REMCSUM_BIT)); + BUILD_BUG_ON(SKB_GSO_SCTP != GSO_INDEX(NETIF_F_GSO_SCTP_BIT)); + BUILD_BUG_ON(SKB_GSO_ESP != GSO_INDEX(NETIF_F_GSO_ESP_BIT)); + BUILD_BUG_ON(SKB_GSO_UDP != GSO_INDEX(NETIF_F_GSO_UDP_BIT)); + BUILD_BUG_ON(SKB_GSO_UDP_L4 != GSO_INDEX(NETIF_F_GSO_UDP_L4_BIT)); + BUILD_BUG_ON(SKB_GSO_FRAGLIST != GSO_INDEX(NETIF_F_GSO_FRAGLIST_BIT)); + + return bitmap_subset(features.bits, feature.bits, NETDEV_FEATURE_COUNT); }
static inline bool skb_gso_ok(struct sk_buff *skb, netdev_features_t features) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 40d26a07a133..6660d897b8b4 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1753,25 +1753,24 @@ char *uuid_string(char *buf, char *end, const u8 *addr, }
static noinline_for_stack -char *netdev_bits(char *buf, char *end, const void *addr, +char *netdev_bits(char *buf, char *end, void *addr, struct printf_spec spec, const char *fmt) { - unsigned long long num; - int size; + unsigned long *bitmap;
if (check_pointer(&buf, end, addr, spec)) return buf;
switch (fmt[1]) { case 'F': - num = *(const netdev_features_t *)addr; - size = sizeof(netdev_features_t); + bitmap = *(netdev_features_t *)addr->bits; + spec->field_width = NETDEV_FEATURE_COUNT; break; default: return error_string(buf, end, "(%pN?)", spec); }
- return special_hex_number(buf, end, num, size); + return bitmap_string(buf, end, add->bits, spec, fmt); }
static noinline_for_stack diff --git a/net/core/dev.c b/net/core/dev.c index 0962935f478e..15880102d169 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9458,17 +9458,15 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower, struct net_device *upper, netdev_features_t features) { netdev_features_t upper_disables; - netdev_features_t feature; int feature_bit;
upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { - feature = __NETIF_F_BIT(feature_bit); - if (!netdev_wanted_features_intersects(upper, feature) && - netdev_features_intersects(features, feature)) { - netdev_dbg(lower, "Dropping feature %pNF, upper dev %s has it off.\n", - &feature, upper->name); - netdev_features_clear(&features, feature); + if (!netdev_wanted_feature_test(feature_bit, upper) && + netdev_feature_test(feature_bit, features)) { + netdev_dbg(lower, "Dropping feature bit %d, upper dev %s has it off.\n", + feature_bit, upper->name); + netdev_feature_del(feature_bit, &features); } }
@@ -9479,22 +9477,20 @@ static void netdev_sync_lower_features(struct net_device *upper, struct net_device *lower, netdev_features_t features) { netdev_features_t upper_disables; - netdev_features_t feature; int feature_bit;
upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { - feature = __NETIF_F_BIT(feature_bit); - if (!netdev_features_intersects(features, feature) && - netdev_active_features_intersects(lower, feature)) { - netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", - &feature, lower->name); - netdev_wanted_features_clear(lower, feature); + if (!netdev_feature_test(feature_bit, features) && + netdev_active_feature_test(lower, feature_bit)) { + netdev_dbg(upper, "Disabling feature bit %d on lower dev %s.\n", + feature_bit, lower->name); + netdev_wanted_feature_del(lower, feature_bit); __netdev_update_features(lower);
- if (unlikely(netdev_active_features_intersects(lower, feature))) - netdev_WARN(upper, "failed to disable %pNF on %s!\n", - &feature, lower->name); + if (unlikely(netdev_active_feature_test(lower, feature_bit))) + netdev_WARN(upper, "failed to disable feature bit %d on %s!\n", + feature_bit, lower->name); else netdev_features_change(lower); } diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 93d56e8921a1..37a6144dd2fb 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -28,10 +28,7 @@ const struct nla_policy ethnl_features_get_policy[] = {
static void ethnl_features_to_bitmap32(u32 *dest, netdev_features_t src) { - unsigned int i; - - for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; i++) - dest[i] = src >> (32 * i); + bitmap_to_arr32(dest, src.bits, ETHTOOL_DEV_FEATURE_WORDS); }
static int features_prepare_data(const struct ethnl_req_info *req_base, @@ -132,30 +129,6 @@ const struct nla_policy ethnl_features_set_policy[] = { [ETHTOOL_A_FEATURES_WANTED] = { .type = NLA_NESTED }, };
-static void ethnl_features_to_bitmap(unsigned long *dest, netdev_features_t val) -{ - const unsigned int words = BITS_TO_LONGS(NETDEV_FEATURE_COUNT); - unsigned int i; - - for (i = 0; i < words; i++) - dest[i] = (unsigned long)(val >> (i * BITS_PER_LONG)); -} - -static netdev_features_t ethnl_bitmap_to_features(unsigned long *src) -{ - const unsigned int nft_bits = sizeof(netdev_features_t) * BITS_PER_BYTE; - const unsigned int words = BITS_TO_LONGS(NETDEV_FEATURE_COUNT); - netdev_features_t ret; - unsigned int i; - - netdev_features_zero(&ret); - for (i = 0; i < words; i++) - netdev_features_set(&ret, - (netdev_features_t)(src[i]) << (i * BITS_PER_LONG)); - ret &= ~(netdev_features_t)0 >> (nft_bits - NETDEV_FEATURE_COUNT); - return ret; -} - static int features_send_reply(struct net_device *dev, struct genl_info *info, const unsigned long *wanted, const unsigned long *wanted_mask, @@ -212,18 +185,17 @@ static int features_send_reply(struct net_device *dev, struct genl_info *info,
int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) { - DECLARE_BITMAP(wanted_diff_mask, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(active_diff_mask, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(old_active, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(old_wanted, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(new_active, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(new_wanted, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(req_wanted, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(req_mask, NETDEV_FEATURE_COUNT); struct ethnl_req_info req_info = {}; struct nlattr **tb = info->attrs; + netdev_features_t wanted_diff_mask; + netdev_features_t active_diff_mask; + netdev_features_t old_active; + netdev_features_t old_wanted; + netdev_features_t new_active; + netdev_features_t new_wanted; + netdev_features_t req_wanted; + netdev_features_t req_mask; struct net_device *dev; - netdev_features_t tmp; bool mod; int ret;
@@ -238,47 +210,43 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) dev = req_info.dev;
rtnl_lock(); - ethnl_features_to_bitmap(old_active, netdev_active_features(dev)); - ethnl_features_to_bitmap(old_wanted, netdev_wanted_features(dev)); + old_active = netdev_active_features(dev); + old_wanted = netdev_wanted_features(dev); ret = ethnl_parse_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT, tb[ETHTOOL_A_FEATURES_WANTED], netdev_features_strings, info->extack); if (ret < 0) goto out_rtnl; - if (ethnl_bitmap_to_features(req_mask) & ~NETIF_F_ETHTOOL_BITS) { + if (!netdev_features_subset(NETIF_F_ETHTOOL_BITS, req_mask)) { GENL_SET_ERR_MSG(info, "attempt to change non-ethtool features"); ret = -EINVAL; goto out_rtnl; }
/* set req_wanted bits not in req_mask from old_wanted */ - bitmap_and(req_wanted, req_wanted, req_mask, NETDEV_FEATURE_COUNT); - bitmap_andnot(new_wanted, old_wanted, req_mask, NETDEV_FEATURE_COUNT); - bitmap_or(req_wanted, new_wanted, req_wanted, NETDEV_FEATURE_COUNT); - if (!bitmap_equal(req_wanted, old_wanted, NETDEV_FEATURE_COUNT)) { + netdev_features_set(&req_wanted, req_mask); + new_wanted = netdev_features_andnot(old_wanted, req_mask); + netdev_features_set(&req_wanted, new_wanted); + if (!netdev_features_equal(req_wanted, old_wanted)) { + netdev_features_t tmp; + netdev_wanted_features_clear(dev, netdev_hw_features(dev)); - tmp = netdev_hw_features_and(dev, - ethnl_bitmap_to_features(req_wanted)); + tmp = netdev_hw_features_and(dev, req_wanted); netdev_wanted_features_set(dev, tmp); __netdev_update_features(dev); } - ethnl_features_to_bitmap(new_active, netdev_active_features(dev)); - mod = !bitmap_equal(old_active, new_active, NETDEV_FEATURE_COUNT); + new_active = netdev_active_features(dev); + mod = !netdev_features_equal(old_active, new_active);
ret = 0; if (!(req_info.flags & ETHTOOL_FLAG_OMIT_REPLY)) { bool compact = req_info.flags & ETHTOOL_FLAG_COMPACT_BITSETS;
- bitmap_xor(wanted_diff_mask, req_wanted, new_active, - NETDEV_FEATURE_COUNT); - bitmap_xor(active_diff_mask, old_active, new_active, - NETDEV_FEATURE_COUNT); - bitmap_and(wanted_diff_mask, wanted_diff_mask, req_mask, - NETDEV_FEATURE_COUNT); - bitmap_and(req_wanted, req_wanted, wanted_diff_mask, - NETDEV_FEATURE_COUNT); - bitmap_and(new_active, new_active, active_diff_mask, - NETDEV_FEATURE_COUNT); + wanted_diff_mask = netdev_features_xor(req_wanted, new_active); + active_diff_mask = netdev_features_xor(old_active, new_active); + netdev_features_mask(&wanted_diff_mask, req_mask); + netdev_features_mask(&req_wanted, wanted_diff_mask); + netdev_features_mask(&new_active, active_diff_mask);
ret = features_send_reply(dev, info, req_wanted, wanted_diff_mask, new_active, diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 02c2741c0d6b..c4725c4e7f0f 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -89,6 +89,10 @@ static int ethtool_get_features(struct net_device *dev, void __user *useraddr) .size = ETHTOOL_DEV_FEATURE_WORDS, }; struct ethtool_get_features_block features[ETHTOOL_DEV_FEATURE_WORDS]; + u32 never_changed_arr[ETHTOOL_DEV_FEATURE_WORDS]; + u32 wanted_arr[ETHTOOL_DEV_FEATURE_WORDS]; + u32 active_arr[ETHTOOL_DEV_FEATURE_WORDS]; + u32 hw_arr[ETHTOOL_DEV_FEATURE_WORDS]; u32 __user *sizeaddr; u32 copy_size; int i; @@ -96,12 +100,15 @@ static int ethtool_get_features(struct net_device *dev, void __user *useraddr) /* in case feature bits run out again */ BUILD_BUG_ON(ETHTOOL_DEV_FEATURE_WORDS * sizeof(u32) > sizeof(netdev_features_t));
+ bitmap_to_arr32(hw_arr, netdev_hw_features(dev), NETDEV_FEATURE_COUNT); + bitmap_to_arr32(wanted_arr, netdev_wanted_features(dev), NETDEV_FEATURE_COUNT); + bitmap_to_arr32(active_arr, netdev_active_features(dev), NETDEV_FEATURE_COUNT); + bitmap_to_arr32(never_changed_arr, NETIF_F_NEVER_CHANGE, NETDEV_FEATURE_COUNT); for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) { - features[i].available = (u32)(netdev_hw_features(dev) >> (32 * i)); - features[i].requested = (u32)(netdev_wanted_features(dev) >> (32 * i)); - features[i].active = (u32)(netdev_active_features(dev) >> (32 * i)); - features[i].never_changed = - (u32)(NETIF_F_NEVER_CHANGE >> (32 * i)); + features[i].available = hw_arr[i]; + features[i].requested = wanted_arr[i]; + features[i].active = active_arr[i]; + features[i].never_changed = never_changed_arr[i]; }
sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size); @@ -125,6 +132,8 @@ 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]; + u32 wanted_arr[ETHTOOL_DEV_FEATURE_WORDS]; + u32 valid_arr[ETHTOOL_DEV_FEATURE_WORDS]; netdev_features_t wanted; netdev_features_t valid; netdev_features_t tmp; @@ -140,14 +149,12 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) if (copy_from_user(features, useraddr, sizeof(features))) return -EFAULT;
- netdev_features_zero(&wanted); - netdev_features_zero(&valid); for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) { - netdev_features_set(&valid, - (netdev_features_t)features[i].valid << (32 * i)); - netdev_features_set(&wanted, - (netdev_features_t)features[i].requested << (32 * i)); + valid_arr[i] = features[i].valid; + wanted_arr[i] = features[i].requested; } + bitmap_from_arr32(valid.bits, valid_arr, NETDEV_FEATURE_COUNT); + bitmap_from_arr32(wanted.bits, wanted_arr, NETDEV_FEATURE_COUNT);
tmp = netdev_features_andnot(valid, NETIF_F_ETHTOOL_BITS); if (tmp) @@ -365,7 +372,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) changed = netdev_active_features_xor(dev, features); netdev_features_mask(&changed, eth_all_features); tmp = netdev_hw_features_andnot_r(dev, changed); - if (tmp) + if (!netdev_features_empty(tmp)) return netdev_hw_features_intersects(dev, changed) ? -EINVAL : -EOPNOTSUPP;
netdev_wanted_features_clear(dev, changed);