netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap
@ 2022-08-10  3:05 Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features Jian Shen
                   ` (35 more replies)
  0 siblings, 36 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

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. [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. Serveal macroes remained temporarily
by some precompile dependency.[patch 36]

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~9]

Also, there are many features(e.g. NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK)
are used by several drivers, replaces them with global netdev features
variables, in order to simple the expressions.[patch 10~13]

As suggestion from Andrew Lunn, I wrote some semantic patches to do the
work(replacing the netdev features operator by helpers). To make the semantic
patches simple, I split the complex expressions of netdev_features to simple
logical operation. [patch 14~15]

For the prototype of netdev_features_t is no longer u64, so it's incorrect
to assigne 0 to it, use netdev_empty_features intead. [patch 16]

Some drivers defines macroes and functions wich use NETIF_F_XXX as parameter.
For all the macroes NETIF_F_XXX will be removed at last, so change these
macroes and functions to use NETIF_F_XXX_BIT. [patch 17~23]

With above preparation, then apply the semantic patches to do the expression
transition. For example, replace expression "ndev->hw_features |= NETIF_F_TSO;"
by "netdev_hw_feature_set(ndev, NETIF_F_TSO_BIT)". [patch 24~35]

With the prototype is no longer u64, the implementation of print interface
for netdev features(%pNF) is changed to bitmap. [patch 36]

I removed the netdev_features_copy and netdev_xxx_features() helpers in
this patchset. It make the expressions being more complex. For example,
expression "dev->features = dev->hw_features", it's too ugly to use
"netdev_active_features_copy(dev, netdev_hw_features(hw))". I will
try to find better way for this, avoiding the nic drivers to modify
netdev_features directly.

The former discussion please see [1][2][3][4][5].
[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/T/
[4]:https://www.spinics.net/lists/netdev/msg809293.html
[5]:https://www.spinics.net/lists/netdev/msg814349.html

ChangeLog:
V6->V7: 
Add netdev_feature_change helpers, remove netdev_features_copy
and netdev_xxx_features helpers.
Complete the treewide netdev features changes.
Suggestions from Alexander Lobakin:
refine the definition of DECLARE_NETDEV_FEATURE_SET, and remove
useless blank lines.
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 (36):
  net: introduce operation helpers for netdev features
  net: replace general features macroes with global netdev_features
    variables
  net: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET
  net: sfc: replace const features initialization with
    DECLARE_NETDEV_FEATURE_SET
  net: atlantic: replace const features initialization with
    NETDEV_FEATURE_SET
  iwlwifi: replace const features initialization with NETDEV_FEATURE_SET
  net: ethernet: mtk_eth_soc: replace const features initialization with
    NETDEV_FEATURE_SET
  ravb: replace const features initialization with NETDEV_FEATURE_SET
  test_bpf: replace const features initialization with
    NETDEV_FEATURE_SET
  treewide: replace NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK by
    netdev_csum_gso_features_mask
  treewide: replace NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM by
    netdev_ip_csum_features
  treewide: replace NETIF_F_TSO | NETIF_F_TSO6 by
    netdev_general_tso_features
  treewide: replace VLAN tag feature array by const vlan features
  net: simplify the netdev features expressions for xxx_gso_segment
  treewide: simplify the netdev features expression
  treewide: use replace features '0' by netdev_empty_features
  treewide: adjust features initialization
  net: mlx4: adjust the net device feature relative macroes
  net: mlx5e: adjust net device feature relative macroes
  net: mlxsw: adjust input parameter for function
    mlxsw_sp_handle_feature
  net: iavf: adjust net device features relative macroes
  net: core: adjust netdev_sync_xxx_features
  net: adjust the build check for net_gso_ok()
  treewide: use netdev_feature_add helpers
  treewide: use netdev_features_or/set helpers
  treewide: use netdev_feature_change helpers
  treewide: use netdev_feature_del helpers
  treewide: use netdev_features_andnot and netdev_features_clear helpers
  treewide: use netdev_features_xor helpers
  treewide: use netdev_feature_test helpers
  treewide: use netdev_features_intersects helpers
  net: use netdev_features_and and netdev_features_mask helpers
  treewide: use netdev_features_subset helpers
  treewide: use netdev_features_equal helpers
  treewide: use netdev_features_empty helpers
  net: redefine the prototype of netdev_features_t

 arch/um/drivers/vector_kern.c                 |   9 +-
 arch/um/drivers/vector_transports.c           |  49 +-
 drivers/firewire/net.c                        |   4 +-
 drivers/hsi/clients/ssi_protocol.c            |   2 +-
 drivers/infiniband/hw/hfi1/vnic_main.c        |   4 +-
 drivers/infiniband/ulp/ipoib/ipoib.h          |   1 +
 drivers/infiniband/ulp/ipoib/ipoib_cm.c       |   2 +-
 drivers/infiniband/ulp/ipoib/ipoib_ib.c       |   2 +-
 drivers/infiniband/ulp/ipoib/ipoib_main.c     |  21 +-
 drivers/infiniband/ulp/ipoib/ipoib_verbs.c    |   2 +-
 drivers/misc/sgi-xp/xpnet.c                   |   3 +-
 drivers/net/amt.c                             |  20 +-
 drivers/net/bareudp.c                         |  25 +-
 drivers/net/bonding/bond_main.c               | 101 ++-
 drivers/net/bonding/bond_options.c            |   9 +-
 drivers/net/caif/caif_serial.c                |   2 +-
 drivers/net/can/dev/dev.c                     |   4 +-
 drivers/net/dsa/xrs700x/xrs700x.c             |  15 +-
 drivers/net/dummy.c                           |  19 +-
 drivers/net/ethernet/3com/3c59x.c             |  10 +-
 drivers/net/ethernet/3com/typhoon.c           |  20 +-
 drivers/net/ethernet/adaptec/starfire.c       |  12 +-
 drivers/net/ethernet/aeroflex/greth.c         |  15 +-
 drivers/net/ethernet/alacritech/slicoss.c     |   6 +-
 drivers/net/ethernet/alteon/acenic.c          |  12 +-
 drivers/net/ethernet/altera/altera_tse_main.c |  10 +-
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  49 +-
 drivers/net/ethernet/amd/amd8111e.c           |   3 +-
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c      |  14 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |  56 +-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c     |  69 +-
 drivers/net/ethernet/apm/xgene-v2/main.c      |   4 +-
 drivers/net/ethernet/apm/xgene-v2/main.h      |   1 +
 .../net/ethernet/apm/xgene/xgene_enet_main.c  |  21 +-
 .../ethernet/aquantia/atlantic/aq_filters.c   |   8 +-
 .../net/ethernet/aquantia/atlantic/aq_hw.h    |   2 +-
 .../ethernet/aquantia/atlantic/aq_macsec.c    |   2 +-
 .../ethernet/aquantia/atlantic/aq_macsec.h    |   1 +
 .../net/ethernet/aquantia/atlantic/aq_main.c  |  89 ++-
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |  29 +-
 .../net/ethernet/aquantia/atlantic/aq_nic.h   |   6 +-
 .../net/ethernet/aquantia/atlantic/aq_ring.c  |   3 +-
 .../aquantia/atlantic/hw_atl/hw_atl_a0.c      |   8 +-
 .../aquantia/atlantic/hw_atl/hw_atl_b0.c      |  17 +-
 .../aquantia/atlantic/hw_atl2/hw_atl2.c       |  15 +-
 drivers/net/ethernet/asix/ax88796c_main.c     |  29 +-
 drivers/net/ethernet/atheros/alx/main.c       |  19 +-
 drivers/net/ethernet/atheros/atl1c/atl1c.h    |   1 +
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  34 +-
 drivers/net/ethernet/atheros/atl1e/atl1e.h    |   1 +
 .../net/ethernet/atheros/atl1e/atl1e_main.c   |  39 +-
 drivers/net/ethernet/atheros/atlx/atl1.c      |  24 +-
 drivers/net/ethernet/atheros/atlx/atl2.c      |  19 +-
 drivers/net/ethernet/atheros/atlx/atlx.c      |  13 +-
 drivers/net/ethernet/broadcom/b44.c           |   3 +-
 drivers/net/ethernet/broadcom/bcmsysport.c    |  34 +-
 drivers/net/ethernet/broadcom/bgmac.c         |   9 +-
 drivers/net/ethernet/broadcom/bnx2.c          |  50 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c   |  49 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  | 115 ++-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 158 ++--
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     |   6 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c  |   4 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c |   3 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c |   5 +-
 .../net/ethernet/broadcom/genet/bcmgenet.c    |  16 +-
 drivers/net/ethernet/broadcom/tg3.c           |  49 +-
 drivers/net/ethernet/brocade/bna/bnad.c       |  51 +-
 drivers/net/ethernet/cadence/macb_main.c      |  62 +-
 drivers/net/ethernet/calxeda/xgmac.c          |  25 +-
 .../net/ethernet/cavium/liquidio/lio_core.c   |   4 +-
 .../net/ethernet/cavium/liquidio/lio_main.c   | 137 ++--
 .../ethernet/cavium/liquidio/lio_vf_main.c    | 114 +--
 .../ethernet/cavium/liquidio/octeon_network.h |   4 +-
 .../net/ethernet/cavium/thunder/nicvf_main.c  |  51 +-
 .../ethernet/cavium/thunder/nicvf_queues.c    |   2 +-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  46 +-
 drivers/net/ethernet/chelsio/cxgb/sge.c       |   8 +-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  67 +-
 drivers/net/ethernet/chelsio/cxgb3/sge.c      |   6 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h    |   1 +
 .../net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c   |  16 +-
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   | 102 ++-
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.h |   2 +-
 drivers/net/ethernet/chelsio/cxgb4/sge.c      |   8 +-
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  56 +-
 drivers/net/ethernet/chelsio/cxgb4vf/sge.c    |   4 +-
 .../chelsio/inline_crypto/chtls/chtls_main.c  |   2 +-
 drivers/net/ethernet/cirrus/ep93xx_eth.c      |   7 +-
 drivers/net/ethernet/cisco/enic/enic_main.c   |  62 +-
 drivers/net/ethernet/cortina/gemini.c         |  29 +-
 drivers/net/ethernet/davicom/dm9000.c         |  20 +-
 drivers/net/ethernet/davicom/dm9051.c         |   2 +-
 drivers/net/ethernet/dnet.c                   |   3 +-
 drivers/net/ethernet/ec_bhf.c                 |   2 +-
 drivers/net/ethernet/emulex/benet/be_main.c   |  64 +-
 drivers/net/ethernet/engleder/tsnep_main.c    |   4 +-
 drivers/net/ethernet/ethoc.c                  |   3 +-
 drivers/net/ethernet/faraday/ftgmac100.c      |  40 +-
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  25 +-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |  43 +-
 .../ethernet/freescale/dpaa2/dpaa2-switch.c   |  10 +-
 .../ethernet/freescale/dpaa2/dpaa2-switch.h   |   1 +
 drivers/net/ethernet/freescale/enetc/enetc.c  |  26 +-
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  59 +-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  42 +-
 drivers/net/ethernet/freescale/fec_main.c     |  25 +-
 .../ethernet/freescale/fs_enet/fs_enet-main.c |   2 +-
 drivers/net/ethernet/freescale/gianfar.c      |  40 +-
 .../net/ethernet/freescale/gianfar_ethtool.c  |   7 +-
 .../ethernet/fungible/funeth/funeth_ktls.c    |   5 +-
 .../ethernet/fungible/funeth/funeth_main.c    |  55 +-
 .../net/ethernet/fungible/funeth/funeth_rx.c  |   4 +-
 drivers/net/ethernet/google/gve/gve_adminq.c  |   5 +-
 drivers/net/ethernet/google/gve/gve_main.c    |  26 +-
 drivers/net/ethernet/google/gve/gve_rx.c      |   4 +-
 drivers/net/ethernet/google/gve/gve_rx_dqo.c  |   4 +-
 drivers/net/ethernet/hisilicon/hix5hd2_gmac.c |   8 +-
 drivers/net/ethernet/hisilicon/hns/hns_enet.c |  62 +-
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   | 101 ++-
 .../ethernet/hisilicon/hns3/hns3_ethtool.c    |   4 +-
 .../net/ethernet/huawei/hinic/hinic_main.c    |  86 +-
 drivers/net/ethernet/huawei/hinic/hinic_rx.c  |   4 +-
 drivers/net/ethernet/ibm/ehea/ehea_main.c     |  34 +-
 drivers/net/ethernet/ibm/emac/core.c          |  10 +-
 drivers/net/ethernet/ibm/ibmveth.c            |  58 +-
 drivers/net/ethernet/ibm/ibmvnic.c            |  48 +-
 drivers/net/ethernet/intel/e100.c             |  20 +-
 drivers/net/ethernet/intel/e1000/e1000.h      |   1 +
 drivers/net/ethernet/intel/e1000/e1000_main.c |  71 +-
 drivers/net/ethernet/intel/e1000e/netdev.c    | 109 +--
 drivers/net/ethernet/intel/fm10k/fm10k.h      |   1 +
 drivers/net/ethernet/intel/fm10k/fm10k_main.c |   6 +-
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  51 +-
 drivers/net/ethernet/intel/fm10k/fm10k_pci.c  |  10 +-
 .../net/ethernet/intel/i40e/i40e_debugfs.c    |  12 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c   | 133 ++--
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   |   6 +-
 drivers/net/ethernet/intel/iavf/iavf.h        |   1 +
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 231 +++---
 drivers/net/ethernet/intel/iavf/iavf_txrx.c   |   8 +-
 .../net/ethernet/intel/iavf/iavf_virtchnl.c   |   4 +-
 drivers/net/ethernet/intel/ice/ice.h          |   1 +
 drivers/net/ethernet/intel/ice/ice_main.c     | 223 +++---
 drivers/net/ethernet/intel/ice/ice_repr.c     |   2 +-
 drivers/net/ethernet/intel/ice/ice_tc_lib.c   |   2 +-
 drivers/net/ethernet/intel/ice/ice_txrx_lib.c |   8 +-
 drivers/net/ethernet/intel/igb/igb_ethtool.c  |   2 +-
 drivers/net/ethernet/intel/igb/igb_main.c     | 141 ++--
 drivers/net/ethernet/intel/igbvf/netdev.c     |  93 ++-
 drivers/net/ethernet/intel/igc/igc_ethtool.c  |   2 +-
 drivers/net/ethernet/intel/igc/igc_mac.c      |   1 +
 drivers/net/ethernet/intel/igc/igc_main.c     | 127 +--
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  38 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe.h      |   1 +
 .../net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c   |   2 +-
 .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c  |   2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c |   6 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c  |   2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 231 +++---
 .../net/ethernet/intel/ixgbe/ixgbe_sriov.c    |   4 +-
 drivers/net/ethernet/intel/ixgbevf/ipsec.c    |  17 +-
 drivers/net/ethernet/intel/ixgbevf/ixgbevf.h  |   1 +
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 115 +--
 drivers/net/ethernet/jme.c                    |  50 +-
 drivers/net/ethernet/marvell/mv643xx_eth.c    |  13 +-
 drivers/net/ethernet/marvell/mvneta.c         |  21 +-
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  61 +-
 .../ethernet/marvell/octeon_ep/octep_main.c   |   6 +-
 .../marvell/octeontx2/nic/otx2_common.c       |  27 +-
 .../marvell/octeontx2/nic/otx2_ethtool.c      |   4 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  56 +-
 .../marvell/octeontx2/nic/otx2_txrx.c         |   6 +-
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  32 +-
 .../ethernet/marvell/prestera/prestera_main.c |   4 +-
 drivers/net/ethernet/marvell/skge.c           |  15 +-
 drivers/net/ethernet/marvell/sky2.c           |  66 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  74 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  12 +-
 .../net/ethernet/mellanox/mlx4/en_ethtool.c   |   4 +-
 drivers/net/ethernet/mellanox/mlx4/en_main.c  |   7 +-
 .../net/ethernet/mellanox/mlx4/en_netdev.c    | 170 ++--
 .../net/ethernet/mellanox/mlx4/en_resources.c |   4 +-
 drivers/net/ethernet/mellanox/mlx4/en_rx.c    |  14 +-
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h  |   5 +-
 .../mellanox/mlx5/core/en_accel/ipsec.c       |  16 +-
 .../mellanox/mlx5/core/en_accel/ipsec_rxtx.h  |   4 +-
 .../mellanox/mlx5/core/en_accel/ktls.c        |  10 +-
 .../net/ethernet/mellanox/mlx5/core/en_arfs.c |   4 +-
 .../ethernet/mellanox/mlx5/core/en_ethtool.c  |   2 +-
 .../net/ethernet/mellanox/mlx5/core/en_fs.c   |   2 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 215 ++---
 .../net/ethernet/mellanox/mlx5/core/en_rep.c  |  22 +-
 .../net/ethernet/mellanox/mlx5/core/en_rx.c   |   8 +-
 .../net/ethernet/mellanox/mlx5/core/en_tc.c   |   2 +-
 .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c |  22 +-
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  37 +-
 drivers/net/ethernet/micrel/ksz884x.c         |  15 +-
 drivers/net/ethernet/microchip/lan743x_main.c |   9 +-
 .../ethernet/microchip/lan966x/lan966x_fdma.c |   2 +-
 .../ethernet/microchip/lan966x/lan966x_main.c |   6 +-
 .../ethernet/microchip/sparx5/sparx5_fdma.c   |   2 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c |  21 +-
 drivers/net/ethernet/mscc/ocelot.c            |   2 +-
 drivers/net/ethernet/mscc/ocelot_net.c        |  23 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  36 +-
 drivers/net/ethernet/natsemi/ns83820.c        |  11 +-
 drivers/net/ethernet/neterion/s2io.c          |  34 +-
 .../net/ethernet/netronome/nfp/crypto/tls.c   |   8 +-
 drivers/net/ethernet/netronome/nfp/nfd3/dp.c  |   4 +-
 drivers/net/ethernet/netronome/nfp/nfdk/dp.c  |   4 +-
 drivers/net/ethernet/netronome/nfp/nfp_net.h  |   1 +
 .../ethernet/netronome/nfp/nfp_net_common.c   | 109 +--
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  48 +-
 drivers/net/ethernet/netronome/nfp/nfp_port.c |   3 +-
 drivers/net/ethernet/ni/nixge.c               |   4 +-
 drivers/net/ethernet/nvidia/forcedeth.c       |  57 +-
 .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  14 +-
 .../ethernet/oki-semi/pch_gbe/pch_gbe_param.c |   4 +-
 drivers/net/ethernet/pasemi/pasemi_mac.c      |  11 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 108 +--
 .../net/ethernet/pensando/ionic/ionic_txrx.c  |   6 +-
 .../ethernet/qlogic/netxen/netxen_nic_init.c  |   4 +-
 .../ethernet/qlogic/netxen/netxen_nic_main.c  |  50 +-
 .../net/ethernet/qlogic/qede/qede_ethtool.c   |   3 +-
 .../net/ethernet/qlogic/qede/qede_filter.c    |   8 +-
 drivers/net/ethernet/qlogic/qede/qede_fp.c    |   6 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c  |  81 +-
 drivers/net/ethernet/qlogic/qla3xxx.c         |   9 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  57 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_io.c    |   2 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_main.c  |  52 +-
 drivers/net/ethernet/qualcomm/emac/emac-mac.c |   4 +-
 drivers/net/ethernet/qualcomm/emac/emac.c     |  27 +-
 .../ethernet/qualcomm/rmnet/rmnet_map_data.c  |   7 +-
 .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c   |  14 +-
 drivers/net/ethernet/realtek/8139cp.c         |  38 +-
 drivers/net/ethernet/realtek/8139too.c        |  26 +-
 drivers/net/ethernet/realtek/r8169_main.c     |  70 +-
 drivers/net/ethernet/renesas/ravb.h           |   4 +-
 drivers/net/ethernet/renesas/ravb_main.c      |  39 +-
 drivers/net/ethernet/renesas/sh_eth.c         |  20 +-
 drivers/net/ethernet/rocker/rocker_main.c     |   4 +-
 .../net/ethernet/samsung/sxgbe/sxgbe_common.h |   7 +-
 .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |  24 +-
 drivers/net/ethernet/sfc/ef10.c               |  35 +-
 drivers/net/ethernet/sfc/ef100_netdev.c       |  15 +-
 drivers/net/ethernet/sfc/ef100_nic.c          |  33 +-
 drivers/net/ethernet/sfc/ef100_rep.c          |   4 +-
 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                |  72 +-
 drivers/net/ethernet/sfc/efx_common.c         |  28 +-
 drivers/net/ethernet/sfc/falcon/efx.c         |  62 +-
 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/mcdi_filters.c       |  15 +-
 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          |   5 +-
 drivers/net/ethernet/sfc/rx_common.h          |   4 +
 drivers/net/ethernet/sfc/siena/efx.c          |  56 +-
 drivers/net/ethernet/sfc/siena/efx.h          |   2 +
 drivers/net/ethernet/sfc/siena/efx_common.c   |  28 +-
 drivers/net/ethernet/sfc/siena/farch.c        |   2 +-
 .../net/ethernet/sfc/siena/mcdi_port_common.c |   2 +-
 drivers/net/ethernet/sfc/siena/net_driver.h   |   5 +-
 drivers/net/ethernet/sfc/siena/rx.c           |   2 +-
 drivers/net/ethernet/sfc/siena/rx_common.c    |   4 +-
 drivers/net/ethernet/sfc/siena/siena.c        |   3 +-
 drivers/net/ethernet/sfc/siena/tx_common.c    |   2 +-
 drivers/net/ethernet/sfc/tx_common.c          |   2 +-
 drivers/net/ethernet/sgi/ioc3-eth.c           |  15 +-
 drivers/net/ethernet/silan/sc92031.c          |  11 +-
 drivers/net/ethernet/socionext/netsec.c       |  13 +-
 drivers/net/ethernet/socionext/sni_ave.c      |   7 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_core.c |   2 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  53 +-
 .../stmicro/stmmac/stmmac_selftests.c         |   4 +-
 drivers/net/ethernet/sun/cassini.c            |   9 +-
 drivers/net/ethernet/sun/ldmvsw.c             |   7 +-
 drivers/net/ethernet/sun/niu.c                |  16 +-
 drivers/net/ethernet/sun/sungem.c             |  13 +-
 drivers/net/ethernet/sun/sunhme.c             |  15 +-
 drivers/net/ethernet/sun/sunvnet.c            |  10 +-
 drivers/net/ethernet/sun/sunvnet_common.c     |   4 +-
 .../net/ethernet/synopsys/dwc-xlgmac-common.c |  27 +-
 drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c |  14 +-
 .../net/ethernet/synopsys/dwc-xlgmac-net.c    |  30 +-
 drivers/net/ethernet/synopsys/dwc-xlgmac.h    |   1 +
 drivers/net/ethernet/tehuti/tehuti.c          |  27 +-
 drivers/net/ethernet/tehuti/tehuti.h          |   1 +
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  23 +-
 drivers/net/ethernet/ti/cpsw.c                |   7 +-
 drivers/net/ethernet/ti/cpsw_new.c            |  11 +-
 drivers/net/ethernet/ti/netcp_core.c          |   6 +-
 drivers/net/ethernet/toshiba/ps3_gelic_net.c  |  13 +-
 drivers/net/ethernet/toshiba/spider_net.c     |  11 +-
 drivers/net/ethernet/tundra/tsi108_eth.c      |   3 +-
 drivers/net/ethernet/via/via-rhine.c          |  11 +-
 drivers/net/ethernet/via/via-velocity.c       |  19 +-
 .../net/ethernet/wangxun/txgbe/txgbe_main.c   |   3 +-
 drivers/net/ethernet/wiznet/w5100.c           |   3 +-
 drivers/net/ethernet/wiznet/w5300.c           |   3 +-
 drivers/net/ethernet/xilinx/ll_temac_main.c   |   6 +-
 .../net/ethernet/xilinx/xilinx_axienet_main.c |   8 +-
 drivers/net/fjes/fjes_main.c                  |   3 +-
 drivers/net/geneve.c                          |  24 +-
 drivers/net/gtp.c                             |   2 +-
 drivers/net/hamradio/bpqether.c               |   4 +-
 drivers/net/hyperv/hyperv_net.h               |   5 +-
 drivers/net/hyperv/netvsc_bpf.c               |   2 +-
 drivers/net/hyperv/netvsc_drv.c               |  32 +-
 drivers/net/hyperv/rndis_filter.c             |  27 +-
 drivers/net/ifb.c                             |  27 +-
 drivers/net/ipa/ipa_modem.c                   |   4 +-
 drivers/net/ipvlan/ipvlan_main.c              |  83 +-
 drivers/net/ipvlan/ipvtap.c                   |  12 +-
 drivers/net/loopback.c                        |  25 +-
 drivers/net/macsec.c                          |  41 +-
 drivers/net/macvlan.c                         |  88 ++-
 drivers/net/macvtap.c                         |  12 +-
 drivers/net/net_failover.c                    |  46 +-
 drivers/net/netdevsim/ipsec.c                 |  13 +-
 drivers/net/netdevsim/netdev.c                |  19 +-
 drivers/net/netdevsim/netdevsim.h             |   1 +
 drivers/net/nlmon.c                           |  11 +-
 drivers/net/ntb_netdev.c                      |   4 +-
 drivers/net/ppp/ppp_generic.c                 |   3 +-
 drivers/net/rionet.c                          |   4 +-
 drivers/net/tap.c                             |  40 +-
 drivers/net/team/team.c                       |  67 +-
 drivers/net/thunderbolt.c                     |  14 +-
 drivers/net/tun.c                             |  57 +-
 drivers/net/usb/aqc111.c                      |  62 +-
 drivers/net/usb/aqc111.h                      |  14 -
 drivers/net/usb/ax88179_178a.c                |  23 +-
 drivers/net/usb/cdc-phonet.c                  |   3 +-
 drivers/net/usb/cdc_mbim.c                    |   4 +-
 drivers/net/usb/lan78xx.c                     |  34 +-
 drivers/net/usb/r8152.c                       |  81 +-
 drivers/net/usb/smsc75xx.c                    |  18 +-
 drivers/net/usb/smsc95xx.c                    |  17 +-
 drivers/net/veth.c                            |  72 +-
 drivers/net/virtio_net.c                      |  59 +-
 drivers/net/vmxnet3/vmxnet3_drv.c             |  82 +-
 drivers/net/vmxnet3/vmxnet3_ethtool.c         |  93 ++-
 drivers/net/vmxnet3/vmxnet3_int.h             |   1 +
 drivers/net/vrf.c                             |  20 +-
 drivers/net/vsockmon.c                        |  11 +-
 drivers/net/vxlan/vxlan_core.c                |  24 +-
 drivers/net/wireguard/device.c                |  24 +-
 drivers/net/wireless/ath/ath10k/mac.c         |   7 +-
 drivers/net/wireless/ath/ath11k/mac.c         |   4 +-
 drivers/net/wireless/ath/ath6kl/core.h        |   1 +
 drivers/net/wireless/ath/ath6kl/main.c        |  16 +-
 drivers/net/wireless/ath/ath6kl/txrx.c        |   4 +-
 drivers/net/wireless/ath/wil6210/netdev.c     |  16 +-
 .../broadcom/brcm80211/brcmfmac/core.c        |   5 +-
 drivers/net/wireless/intel/iwlwifi/cfg/1000.c |   2 +
 drivers/net/wireless/intel/iwlwifi/cfg/2000.c |   4 +
 .../net/wireless/intel/iwlwifi/cfg/22000.c    |   4 +-
 drivers/net/wireless/intel/iwlwifi/cfg/5000.c |   3 +
 drivers/net/wireless/intel/iwlwifi/cfg/6000.c |   7 +
 drivers/net/wireless/intel/iwlwifi/cfg/7000.c |   1 +
 drivers/net/wireless/intel/iwlwifi/cfg/8000.c |   2 +-
 drivers/net/wireless/intel/iwlwifi/cfg/9000.c |   2 +-
 .../net/wireless/intel/iwlwifi/dvm/mac80211.c |   8 +-
 .../net/wireless/intel/iwlwifi/iwl-config.h   |  15 +-
 drivers/net/wireless/intel/iwlwifi/iwl-drv.c  |  33 +
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |  15 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h  |   8 +
 drivers/net/wireless/intel/iwlwifi/mvm/ops.c  |  28 +
 drivers/net/wireless/intel/iwlwifi/mvm/rx.c   |   2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c |   2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c   |  11 +-
 .../net/wireless/mediatek/mt76/mt7615/init.c  |   4 +-
 .../net/wireless/mediatek/mt76/mt7915/init.c  |   4 +-
 .../net/wireless/mediatek/mt76/mt7921/init.c  |   4 +-
 drivers/net/wwan/t7xx/t7xx_netdev.c           |  16 +-
 drivers/net/xen-netback/interface.c           |  27 +-
 drivers/net/xen-netfront.c                    |  42 +-
 drivers/s390/net/qeth_core_main.c             | 109 +--
 drivers/s390/net/qeth_l2_main.c               |  34 +-
 drivers/s390/net/qeth_l3_main.c               |  37 +-
 drivers/scsi/fcoe/fcoe.c                      |  12 +-
 drivers/staging/octeon/ethernet.c             |   9 +-
 drivers/staging/qlge/qlge_main.c              |  47 +-
 drivers/usb/gadget/function/f_phonet.c        |   3 +-
 include/linux/if_vlan.h                       |  14 +-
 include/linux/netdev_features.h               | 221 +++---
 include/linux/netdev_features_helper.h        | 742 ++++++++++++++++++
 include/linux/netdevice.h                     | 110 +--
 include/linux/skbuff.h                        |   4 +-
 include/net/bonding.h                         |   5 +-
 include/net/ip_tunnels.h                      |   2 +-
 include/net/net_failover.h                    |   8 +-
 include/net/pkt_cls.h                         |   2 +-
 include/net/sock.h                            |   5 +-
 include/net/udp.h                             |   7 +-
 include/net/udp_tunnel.h                      |   8 +-
 include/net/vxlan.h                           |   2 +-
 lib/test_bpf.c                                |  42 +-
 lib/vsprintf.c                                |  11 +-
 net/8021q/vlan.c                              |   6 +-
 net/8021q/vlan.h                              |  18 +-
 net/8021q/vlan_core.c                         |   4 +-
 net/8021q/vlan_dev.c                          |  42 +-
 net/batman-adv/soft-interface.c               |   9 +-
 net/bridge/br_device.c                        |  27 +-
 net/bridge/br_if.c                            |   2 +-
 net/core/Makefile                             |   2 +-
 net/core/dev.c                                | 350 ++++++---
 net/core/netdev_features.c                    | 281 +++++++
 net/core/pktgen.c                             |   6 +-
 net/core/skbuff.c                             |  10 +-
 net/core/skmsg.c                              |   2 +-
 net/core/sock.c                               |  14 +-
 net/dccp/ipv4.c                               |   2 +-
 net/dccp/ipv6.c                               |   8 +-
 net/dsa/slave.c                               |  26 +-
 net/ethtool/features.c                        |  95 +--
 net/ethtool/ioctl.c                           | 133 ++--
 net/hsr/hsr_device.c                          |  21 +-
 net/hsr/hsr_forward.c                         |   8 +-
 net/hsr/hsr_framereg.c                        |   2 +-
 net/hsr/hsr_slave.c                           |   2 +-
 net/ieee802154/6lowpan/core.c                 |   3 +-
 net/ieee802154/core.c                         |  15 +-
 net/ipv4/af_inet.c                            |   4 +-
 net/ipv4/esp4_offload.c                       |  22 +-
 net/ipv4/gre_offload.c                        |   6 +-
 net/ipv4/ip_gre.c                             |  31 +-
 net/ipv4/ip_output.c                          |  19 +-
 net/ipv4/ip_tunnel.c                          |   3 +-
 net/ipv4/ip_vti.c                             |   3 +-
 net/ipv4/ipip.c                               |  21 +-
 net/ipv4/ipmr.c                               |   2 +-
 net/ipv4/tcp.c                                |   8 +-
 net/ipv4/tcp_ipv4.c                           |   2 +-
 net/ipv4/tcp_offload.c                        |   3 +-
 net/ipv4/udp_offload.c                        |  20 +-
 net/ipv6/af_inet6.c                           |   2 +-
 net/ipv6/esp6_offload.c                       |  16 +-
 net/ipv6/inet6_connection_sock.c              |   2 +-
 net/ipv6/ip6_gre.c                            |  21 +-
 net/ipv6/ip6_offload.c                        |   2 +-
 net/ipv6/ip6_output.c                         |  15 +-
 net/ipv6/ip6_tunnel.c                         |  23 +-
 net/ipv6/ip6mr.c                              |   3 +-
 net/ipv6/sit.c                                |  23 +-
 net/ipv6/tcp_ipv6.c                           |   2 +-
 net/ipv6/udp_offload.c                        |   2 +-
 net/l2tp/l2tp_eth.c                           |   2 +-
 net/mac80211/ieee80211_i.h                    |  13 +-
 net/mac80211/iface.c                          |   9 +-
 net/mac80211/main.c                           |  28 +-
 net/mac80211/tx.c                             |   2 +-
 net/mpls/mpls_gso.c                           |   3 +-
 net/netfilter/ipvs/ip_vs_proto_sctp.c         |   2 +-
 net/netfilter/nfnetlink_queue.c               |   2 +-
 net/nsh/nsh.c                                 |   5 +-
 net/openvswitch/datapath.c                    |   7 +-
 net/openvswitch/vport-internal_dev.c          |  21 +-
 net/phonet/pep-gprs.c                         |   4 +-
 net/sched/sch_cake.c                          |   2 +-
 net/sched/sch_netem.c                         |   2 +-
 net/sched/sch_taprio.c                        |   2 +-
 net/sched/sch_tbf.c                           |   3 +-
 net/sctp/offload.c                            |  12 +-
 net/sctp/output.c                             |   2 +-
 net/sunrpc/sunrpc.h                           |   2 +-
 net/tls/tls_device.c                          |   8 +-
 net/wireless/core.c                           |  15 +-
 net/xfrm/xfrm_device.c                        |  26 +-
 net/xfrm/xfrm_interface.c                     |  18 +-
 net/xfrm/xfrm_output.c                        |   5 +-
 481 files changed, 8116 insertions(+), 4331 deletions(-)
 create mode 100644 include/linux/netdev_features_helper.h
 create mode 100644 net/core/netdev_features.c

-- 
2.33.0


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  9:43   ` Alexander Lobakin
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 02/36] net: replace general features macroes with global netdev_features variables Jian Shen
                   ` (34 subsequent siblings)
  35 siblings, 1 reply; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Introduce a set of bitmap operation helpers for netdev features,
then we can use them to replace the logical operation with them.

The implementation of these helpers are based on the old prototype
of netdev_features_t is still u64. These helpers will be rewritten
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 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>
---
 include/linux/netdev_features.h        |  11 +
 include/linux/netdev_features_helper.h | 707 +++++++++++++++++++++++++
 include/linux/netdevice.h              |  45 +-
 net/8021q/vlan_dev.c                   |   1 +
 net/core/dev.c                         |   1 +
 5 files changed, 747 insertions(+), 18 deletions(-)
 create mode 100644 include/linux/netdev_features_helper.h

diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 7c2d77d75a88..9d434b4e6e6e 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -11,6 +11,17 @@
 
 typedef u64 netdev_features_t;
 
+struct netdev_feature_set {
+	unsigned int cnt;
+	unsigned short feature_bits[];
+};
+
+#define DECLARE_NETDEV_FEATURE_SET(name, features...)			\
+	const struct netdev_feature_set name = {			\
+		.cnt = sizeof((unsigned short[]){ features }) / sizeof(unsigned short),	\
+		.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..5423927d139b
--- /dev/null
+++ b/include/linux/netdev_features_helper.h
@@ -0,0 +1,707 @@
+/* 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;
+}
+
+/* active_feature prefer to netdev->features */
+#define netdev_active_features_zero(ndev) \
+		netdev_features_zero(&ndev->features)
+
+#define netdev_hw_features_zero(ndev) \
+		netdev_features_zero(&ndev->hw_features)
+
+#define netdev_wanted_features_zero(ndev) \
+		netdev_features_zero(&ndev->wanted_features)
+
+#define netdev_vlan_features_zero(ndev) \
+		netdev_features_zero(&ndev->vlan_features)
+
+#define netdev_hw_enc_features_zero(ndev) \
+		netdev_features_zero(&ndev->hw_enc_features)
+
+#define netdev_mpls_features_zero(ndev) \
+		netdev_features_zero(&ndev->mpls_features)
+
+#define netdev_gso_partial_features_zero(ndev) \
+		netdev_features_zero(&ndev->gso_partial_features)
+
+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;
+}
+
+#define netdev_active_features_empty(ndev) \
+		netdev_features_empty(ndev->features)
+
+#define netdev_hw_features_empty(ndev) \
+		netdev_features_empty(ndev->hw_features)
+
+#define netdev_wanted_features_empty(ndev) \
+		netdev_features_empty(ndev->wanted_features)
+
+#define netdev_vlan_features_empty(ndev) \
+		netdev_features_empty(ndev->vlan_features)
+
+#define netdev_hw_enc_features_empty(ndev) \
+		netdev_features_empty(ndev->hw_enc_features)
+
+#define netdev_mpls_features_empty(ndev) \
+		netdev_features_empty(ndev->mpls_features)
+
+#define netdev_gso_partial_features_empty(ndev) \
+		netdev_features_empty(ndev->gso_partial_features)
+
+/* helpers for netdev features '==' operation */
+static inline bool netdev_features_equal(const netdev_features_t src1,
+					 const netdev_features_t src2)
+{
+	return src1 == src2;
+}
+
+#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);
+}
+
+static inline void netdev_feature_change(int nr, netdev_features_t *src)
+{
+	if (*src & __NETIF_F_BIT(nr))
+		*src &= ~(__NETIF_F_BIT(nr));
+	else
+		*src |= __NETIF_F_BIT(nr);
+}
+
+#define netdev_active_feature_change(ndev, nr) \
+		netdev_feature_change(nr, &ndev->features)
+
+#define netdev_hw_feature_change(ndev, nr) \
+		netdev_feature_change(nr, &ndev->hw_features)
+
+#define netdev_wanted_feature_change(ndev, nr) \
+		netdev_feature_change(nr, &ndev->wanted_features)
+
+#define netdev_vlan_feature_change(ndev, nr) \
+		netdev_feature_change(nr, &ndev->vlan_features)
+
+#define netdev_hw_enc_feature_change(ndev, nr) \
+		netdev_feature_change(nr, &ndev->hw_enc_features)
+
+#define netdev_mpls_feature_change(ndev, nr) \
+		netdev_feature_change(nr, &ndev->mpls_features)
+
+#define netdev_gso_partial_feature_change(ndev, nr) \
+		netdev_feature_change(nr, &ndev->gso_partial_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)
+
+/* helpers for netdev features 'clear bit array' operation */
+static inline void
+netdev_features_clear_array(const struct netdev_feature_set *set,
+			    netdev_features_t *dst)
+{
+	int i;
+
+	for (i = 0; i < set->cnt; i++)
+		netdev_feature_del(set->feature_bits[i], dst);
+}
+
+#define netdev_active_features_clear_array(ndev, set) \
+		netdev_features_clear_array(set, &ndev->features)
+
+#define netdev_hw_features_clear_array(ndev, set) \
+		netdev_features_clear_array(set, &ndev->hw_features)
+
+#define netdev_wanted_features_clear_array(ndev, set) \
+		netdev_features_clear_array(set, &ndev->wanted_features)
+
+#define netdev_vlan_features_clear_array(ndev, set) \
+		netdev_features_clear_array(set, &ndev->vlan_features)
+
+#define netdev_hw_enc_features_clear_array(ndev, set) \
+		netdev_features_clear_array(set, &ndev->hw_enc_features)
+
+#define netdev_mpls_features_clear_array(ndev, set) \
+		netdev_features_set_array(set, &ndev->mpls_features)
+
+#define netdev_gso_partial_features_clear_array(ndev, set) \
+		netdev_features_clear_array(set, &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 1a3cb93c3dcc..1bd5dcbc884d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2335,6 +2335,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)
@@ -4832,24 +4859,6 @@ extern const struct kobj_ns_type_operations net_ns_type_operations;
 
 const char *netdev_drivername(const struct net_device *dev);
 
-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 035812b0461c..64ca07daf4ee 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 716df64fcfa5..45e80c84497f 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>
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 02/36] net: replace general features macroes with global netdev_features variables
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  9:58   ` Alexander Lobakin
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 03/36] net: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET Jian Shen
                   ` (33 subsequent siblings)
  35 siblings, 1 reply; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

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/hyperv/hyperv_net.h |   5 +-
 include/linux/netdev_features.h | 111 +++++++++----
 net/core/Makefile               |   2 +-
 net/core/dev.c                  |  83 ++++++++++
 net/core/netdev_features.c      | 281 ++++++++++++++++++++++++++++++++
 5 files changed, 441 insertions(+), 41 deletions(-)
 create mode 100644 net/core/netdev_features.c

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 25b38a374e3c..6336ed81fb8c 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -873,10 +873,7 @@ struct nvsp_message {
 #define NETVSC_RECEIVE_BUFFER_ID		0xcafe
 #define NETVSC_SEND_BUFFER_ID			0
 
-#define NETVSC_SUPPORTED_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | \
-				      NETIF_F_TSO | NETIF_F_IPV6_CSUM | \
-				      NETIF_F_TSO6 | NETIF_F_LRO | \
-				      NETIF_F_SG | NETIF_F_RXHASH)
+#define NETVSC_SUPPORTED_HW_FEATURES	netvsc_supported_hw_features
 
 #define VRSS_SEND_TAB_SIZE 16  /* must be power of 2 */
 #define VRSS_CHANNEL_MAX 64
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 9d434b4e6e6e..a005c781fabf 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;
@@ -112,6 +113,64 @@ 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_offload_features __ro_after_init;
+extern netdev_features_t netdev_stag_vlan_offload_features __ro_after_init;
+extern netdev_features_t netdev_vlan_offload_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_multi_tags_features_mask __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 netdev_features_t netdev_empty_features __ro_after_init;
+extern netdev_features_t netvsc_supported_hw_features __ro_after_init;
+extern const struct netdev_feature_set netif_f_never_change_feature_set;
+extern const struct netdev_feature_set netif_f_gso_feature_set_mask;
+extern const struct netdev_feature_set netif_f_ip_csum_feature_set;
+extern const struct netdev_feature_set netif_f_csum_feature_set_mask;
+extern const struct netdev_feature_set netif_f_general_tso_feature_set;
+extern const struct netdev_feature_set netif_f_all_tso_feature_set;
+extern const struct netdev_feature_set netif_f_tso_ecn_feature_set;
+extern const struct netdev_feature_set netif_f_all_fcoe_feature_set;
+extern const struct netdev_feature_set netif_f_gso_soft_feature_set;
+extern const struct netdev_feature_set netif_f_one_for_all_feature_set;
+extern const struct netdev_feature_set netif_f_all_for_all_feature_set;
+extern const struct netdev_feature_set netif_f_upper_disables_feature_set;
+extern const struct netdev_feature_set netif_f_soft_feature_set;
+extern const struct netdev_feature_set netif_f_soft_off_feature_set;
+extern const struct netdev_feature_set netif_f_tx_vlan_feature_set;
+extern const struct netdev_feature_set netif_f_rx_vlan_feature_set;
+extern const struct netdev_feature_set netif_f_vlan_filter_feature_set;
+extern const struct netdev_feature_set netif_f_ctag_vlan_feature_set;
+extern const struct netdev_feature_set netif_f_stag_vlan_feature_set;
+extern const struct netdev_feature_set netif_f_ctag_vlan_offload_feature_set;
+extern const struct netdev_feature_set netif_f_stag_vlan_offload_feature_set;
+extern const struct netdev_feature_set netif_f_multi_tags_feature_set_mask;
+extern const struct netdev_feature_set netif_f_gso_encap_feature_set;
+extern const struct netdev_feature_set netif_f_xfrm_feature_set;
+extern const struct netdev_feature_set netif_f_tls_feature_set;
+extern const struct netdev_feature_set netvsc_supported_hw_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)
@@ -203,73 +262,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 e8ce3bd283a6..360a101584c8 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -12,7 +12,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 45e80c84497f..9603bac63ffb 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>
@@ -11362,6 +11363,86 @@ static struct pernet_operations __net_initdata default_device_ops = {
 	.exit_batch = default_device_exit_batch,
 };
 
+static void __init netdev_features_init(void)
+{
+	netdev_features_t features;
+
+	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_gso_feature_set_mask,
+				  &netdev_gso_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_gso_encap_feature_set,
+				  &netdev_gso_encap_all_features);
+
+	netdev_csum_gso_features_mask =
+		netdev_features_or(netdev_gso_features_mask,
+				   netdev_csum_features_mask);
+
+	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_features_or(netdev_rx_vlan_features,
+						      netdev_tx_vlan_features);
+	netdev_features_set_array(&netif_f_ctag_vlan_offload_feature_set,
+				  &netdev_ctag_vlan_offload_features);
+	netdev_features_set_array(&netif_f_stag_vlan_offload_feature_set,
+				  &netdev_stag_vlan_offload_features);
+	netdev_vlan_offload_features =
+			netdev_features_or(netdev_ctag_vlan_offload_features,
+					   netdev_stag_vlan_offload_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_multi_tags_feature_set_mask,
+				  &netdev_multi_tags_features_mask);
+
+	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_features_set_array(&netif_f_never_change_feature_set,
+				  &netdev_never_change_features);
+	netdev_features_fill(&features);
+	netdev_ethtool_features =
+		netdev_features_andnot(features, netdev_never_change_features);
+
+	netdev_features_zero(&netdev_empty_features);
+
+	netdev_features_set_array(&netvsc_supported_hw_feature_set,
+				  &netvsc_supported_hw_features);
+}
+
 /*
  *	Initialize the DEV module. At boot time this walks the device list and
  *	unhooks any devices that fail to initialise (normally hardware not
@@ -11392,6 +11473,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..158c750ea7a2
--- /dev/null
+++ b/net/core/netdev_features.c
@@ -0,0 +1,281 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Network device features.
+ */
+
+#include <linux/netdev_features.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_offload_features __ro_after_init;
+EXPORT_SYMBOL_GPL(netdev_ctag_vlan_offload_features);
+
+netdev_features_t netdev_stag_vlan_offload_features __ro_after_init;
+EXPORT_SYMBOL_GPL(netdev_stag_vlan_offload_features);
+
+netdev_features_t netdev_vlan_offload_features __ro_after_init;
+EXPORT_SYMBOL_GPL(netdev_vlan_offload_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_multi_tags_features_mask __ro_after_init;
+EXPORT_SYMBOL_GPL(netdev_multi_tags_features_mask);
+
+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);
+
+netdev_features_t netdev_empty_features __ro_after_init;
+EXPORT_SYMBOL_GPL(netdev_empty_features);
+
+netdev_features_t netvsc_supported_hw_features __ro_after_init;
+EXPORT_SYMBOL_GPL(netvsc_supported_hw_features);
+
+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_BIT);
+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_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_offload_feature_set,
+			   NETIF_F_HW_VLAN_CTAG_TX_BIT,
+			   NETIF_F_HW_VLAN_CTAG_RX_BIT);
+EXPORT_SYMBOL_GPL(netif_f_ctag_vlan_offload_feature_set);
+
+DECLARE_NETDEV_FEATURE_SET(netif_f_stag_vlan_offload_feature_set,
+			   NETIF_F_HW_VLAN_STAG_TX_BIT,
+			   NETIF_F_HW_VLAN_STAG_RX_BIT);
+EXPORT_SYMBOL_GPL(netif_f_stag_vlan_offload_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,
+			   NETIF_F_HW_VLAN_CTAG_FILTER_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,
+			   NETIF_F_HW_VLAN_STAG_FILTER_BIT);
+EXPORT_SYMBOL_GPL(netif_f_stag_vlan_feature_set);
+
+DECLARE_NETDEV_FEATURE_SET(netif_f_multi_tags_feature_set_mask,
+			   NETIF_F_SG_BIT,
+			   NETIF_F_HIGHDMA_BIT,
+			   NETIF_F_HW_CSUM_BIT,
+			   NETIF_F_FRAGLIST_BIT,
+			   NETIF_F_HW_VLAN_CTAG_TX_BIT,
+			   NETIF_F_HW_VLAN_STAG_TX_BIT);
+EXPORT_SYMBOL_GPL(netif_f_multi_tags_feature_set_mask);
+
+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);
+
+DECLARE_NETDEV_FEATURE_SET(netvsc_supported_hw_feature_set,
+			   NETIF_F_RXCSUM_BIT,
+			   NETIF_F_IP_CSUM_BIT,
+			   NETIF_F_TSO_BIT,
+			   NETIF_F_IPV6_CSUM_BIT,
+			   NETIF_F_TSO6_BIT,
+			   NETIF_F_LRO_BIT,
+			   NETIF_F_SG_BIT,
+			   NETIF_F_RXHASH_BIT);
+EXPORT_SYMBOL_GPL(netvsc_supported_hw_feature_set);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 03/36] net: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 02/36] net: replace general features macroes with global netdev_features variables Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10 10:37   ` Alexander Lobakin
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 04/36] net: sfc: replace const features initialization " Jian Shen
                   ` (32 subsequent siblings)
  35 siblings, 1 reply; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

There are many netdev_features bits group used in drivers, replace them
with DECLARE_NETDEV_FEATURE_SET, prepare to remove all the NETIF_F_XXX
macroes.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 arch/um/drivers/vector_transports.c           |  49 +++++--
 drivers/infiniband/ulp/ipoib/ipoib.h          |   1 +
 drivers/infiniband/ulp/ipoib/ipoib_main.c     |   8 +-
 drivers/net/amt.c                             |  16 ++-
 drivers/net/bareudp.c                         |  21 ++-
 drivers/net/bonding/bond_main.c               |  48 +++++--
 drivers/net/dsa/xrs700x/xrs700x.c             |  15 +-
 drivers/net/dummy.c                           |  11 +-
 drivers/net/ethernet/3com/typhoon.c           |  18 ++-
 drivers/net/ethernet/aeroflex/greth.c         |   9 +-
 drivers/net/ethernet/alteon/acenic.c          |  10 +-
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  13 +-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c     |  59 ++++----
 .../net/ethernet/apm/xgene/xgene_enet_main.c  |  12 +-
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |  14 +-
 drivers/net/ethernet/asix/ax88796c_main.c     |  21 ++-
 drivers/net/ethernet/atheros/alx/main.c       |  15 +-
 drivers/net/ethernet/atheros/atl1c/atl1c.h    |   1 +
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  14 +-
 drivers/net/ethernet/atheros/atl1e/atl1e.h    |   1 +
 .../net/ethernet/atheros/atl1e/atl1e_main.c   |  10 +-
 drivers/net/ethernet/atheros/atlx/atl1.c      |  22 ++-
 drivers/net/ethernet/broadcom/bcmsysport.c    |  24 +++-
 drivers/net/ethernet/broadcom/bgmac.c         |   9 +-
 drivers/net/ethernet/broadcom/bnx2.c          |  14 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  83 ++++++++---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  54 +++++--
 .../net/ethernet/broadcom/genet/bcmgenet.c    |  10 +-
 drivers/net/ethernet/brocade/bna/bnad.c       |  39 +++--
 drivers/net/ethernet/calxeda/xgmac.c          |  15 +-
 .../net/ethernet/cavium/liquidio/lio_main.c   |  42 ++++--
 .../ethernet/cavium/liquidio/lio_vf_main.c    |  40 ++++--
 .../ethernet/cavium/liquidio/octeon_network.h |   4 +-
 .../net/ethernet/cavium/thunder/nicvf_main.c  |  27 +++-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  19 ++-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  29 +++-
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  68 ++++++---
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  39 ++++-
 drivers/net/ethernet/cirrus/ep93xx_eth.c      |   7 +-
 drivers/net/ethernet/cisco/enic/enic_main.c   |  19 ++-
 drivers/net/ethernet/cortina/gemini.c         |  22 ++-
 drivers/net/ethernet/emulex/benet/be_main.c   |  47 ++++--
 drivers/net/ethernet/faraday/ftgmac100.c      |  13 +-
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  14 +-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |  17 ++-
 .../ethernet/freescale/dpaa2/dpaa2-switch.c   |  10 +-
 .../ethernet/freescale/dpaa2/dpaa2-switch.h   |   1 +
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  42 ++++--
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  40 ++++--
 drivers/net/ethernet/freescale/fec_main.c     |  11 +-
 drivers/net/ethernet/freescale/gianfar.c      |  18 ++-
 .../ethernet/fungible/funeth/funeth_main.c    |  48 +++++--
 drivers/net/ethernet/google/gve/gve_main.c    |  21 +--
 drivers/net/ethernet/hisilicon/hns/hns_enet.c |  51 +++++--
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   |  40 ++++--
 .../net/ethernet/huawei/hinic/hinic_main.c    |  37 +++--
 drivers/net/ethernet/ibm/ehea/ehea_main.c     |  34 +++--
 drivers/net/ethernet/ibm/emac/core.c          |   7 +-
 drivers/net/ethernet/ibm/ibmveth.c            |  11 +-
 drivers/net/ethernet/ibm/ibmvnic.c            |   8 +-
 drivers/net/ethernet/intel/e1000/e1000.h      |   1 +
 drivers/net/ethernet/intel/e1000/e1000_main.c |  33 +++--
 drivers/net/ethernet/intel/e1000e/netdev.c    |  46 ++++--
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  37 +++--
 drivers/net/ethernet/intel/i40e/i40e_main.c   |  75 +++++-----
 drivers/net/ethernet/intel/iavf/iavf.h        |   1 +
 drivers/net/ethernet/intel/iavf/iavf_main.c   |  43 +++---
 drivers/net/ethernet/intel/ice/ice.h          |   1 +
 drivers/net/ethernet/intel/ice/ice_main.c     |  64 ++++++---
 drivers/net/ethernet/intel/igb/igb_main.c     |  74 ++++++----
 drivers/net/ethernet/intel/igbvf/netdev.c     |  76 ++++++----
 drivers/net/ethernet/intel/igc/igc_mac.c      |   1 +
 drivers/net/ethernet/intel/igc/igc_main.c     |  77 ++++++----
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  15 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 134 +++++++++++-------
 drivers/net/ethernet/intel/ixgbevf/ipsec.c    |  15 +-
 drivers/net/ethernet/intel/ixgbevf/ixgbevf.h  |   1 +
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |  87 +++++++-----
 drivers/net/ethernet/jme.c                    |  34 +++--
 drivers/net/ethernet/marvell/mv643xx_eth.c    |   9 +-
 drivers/net/ethernet/marvell/mvneta.c         |  12 +-
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  19 ++-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  17 ++-
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  17 ++-
 drivers/net/ethernet/marvell/skge.c           |   9 +-
 drivers/net/ethernet/marvell/sky2.c           |  19 ++-
 drivers/net/ethernet/mellanox/mlx4/en_main.c  |   1 +
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  75 ++++++----
 .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c |  20 +--
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  16 ++-
 drivers/net/ethernet/micrel/ksz884x.c         |   9 +-
 drivers/net/ethernet/microchip/lan743x_main.c |   9 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c |  15 +-
 drivers/net/ethernet/mscc/ocelot_net.c        |  14 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  11 +-
 drivers/net/ethernet/neterion/s2io.c          |  24 +++-
 drivers/net/ethernet/nvidia/forcedeth.c       |  10 +-
 .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  10 +-
 drivers/net/ethernet/pasemi/pasemi_mac.c      |  11 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   |  23 +--
 .../ethernet/qlogic/netxen/netxen_nic_main.c  |  11 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c  |  50 +++++--
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  29 ++--
 .../net/ethernet/qlogic/qlcnic/qlcnic_main.c  |  34 +++--
 drivers/net/ethernet/qualcomm/emac/emac.c     |  23 ++-
 .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c   |  12 +-
 drivers/net/ethernet/realtek/8139cp.c         |  23 ++-
 drivers/net/ethernet/realtek/8139too.c        |   8 +-
 drivers/net/ethernet/realtek/r8169_main.c     |  18 ++-
 .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |  15 +-
 drivers/net/ethernet/sfc/ef10.c               |  11 +-
 drivers/net/ethernet/sfc/ef100_netdev.c       |   9 +-
 drivers/net/ethernet/sfc/ef100_nic.c          |  15 +-
 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 +
 drivers/net/ethernet/sfc/siena/efx.c          |  22 ++-
 drivers/net/ethernet/sgi/ioc3-eth.c           |  13 +-
 drivers/net/ethernet/silan/sc92031.c          |  11 +-
 drivers/net/ethernet/socionext/netsec.c       |  11 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  11 +-
 drivers/net/ethernet/sun/ldmvsw.c             |   7 +-
 drivers/net/ethernet/sun/niu.c                |   9 +-
 drivers/net/ethernet/sun/sungem.c             |   9 +-
 drivers/net/ethernet/sun/sunvnet.c            |  10 +-
 drivers/net/ethernet/tehuti/tehuti.c          |  25 +++-
 drivers/net/ethernet/tehuti/tehuti.h          |   1 +
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  13 +-
 drivers/net/ethernet/ti/cpsw_new.c            |  11 +-
 drivers/net/ethernet/via/via-velocity.c       |  19 ++-
 drivers/net/geneve.c                          |  20 ++-
 drivers/net/hyperv/netvsc_drv.c               |  11 +-
 drivers/net/ifb.c                             |  20 ++-
 drivers/net/ipvlan/ipvlan_main.c              |  58 ++++++--
 drivers/net/ipvlan/ipvtap.c                   |  12 +-
 drivers/net/loopback.c                        |  25 ++--
 drivers/net/macsec.c                          |  22 ++-
 drivers/net/macvlan.c                         |  56 ++++++--
 drivers/net/macvtap.c                         |  12 +-
 drivers/net/net_failover.c                    |  23 +++
 drivers/net/netdevsim/ipsec.c                 |  13 +-
 drivers/net/netdevsim/netdev.c                |  14 +-
 drivers/net/netdevsim/netdevsim.h             |   1 +
 drivers/net/nlmon.c                           |  11 +-
 drivers/net/tap.c                             |  18 ++-
 drivers/net/team/team.c                       |  31 +++-
 drivers/net/thunderbolt.c                     |  11 +-
 drivers/net/tun.c                             |  28 +++-
 drivers/net/usb/aqc111.c                      |  38 ++++-
 drivers/net/usb/aqc111.h                      |  14 --
 drivers/net/usb/ax88179_178a.c                |  11 +-
 drivers/net/usb/lan78xx.c                     |   8 +-
 drivers/net/usb/r8152.c                       |  53 +++++--
 drivers/net/usb/smsc75xx.c                    |  10 +-
 drivers/net/veth.c                            |  27 ++--
 drivers/net/vmxnet3/vmxnet3_drv.c             |  36 +++--
 drivers/net/vmxnet3/vmxnet3_ethtool.c         |  35 +++--
 drivers/net/vmxnet3/vmxnet3_int.h             |   1 +
 drivers/net/vrf.c                             |  12 +-
 drivers/net/vsockmon.c                        |  11 +-
 drivers/net/vxlan/vxlan_core.c                |  20 ++-
 drivers/net/wireguard/device.c                |  20 ++-
 drivers/net/wireless/ath/wil6210/netdev.c     |  14 +-
 drivers/net/xen-netback/interface.c           |  14 +-
 drivers/net/xen-netfront.c                    |  20 ++-
 drivers/s390/net/qeth_l3_main.c               |  13 +-
 drivers/staging/qlge/qlge_main.c              |  21 +--
 include/net/bonding.h                         |   5 +-
 include/net/net_failover.h                    |   8 +-
 net/8021q/vlan_dev.c                          |  15 +-
 net/batman-adv/soft-interface.c               |   9 +-
 net/bridge/br_device.c                        |  25 +++-
 net/ethtool/ioctl.c                           |  17 ++-
 net/hsr/hsr_device.c                          |  13 +-
 net/ipv4/ip_gre.c                             |  19 +--
 net/ipv4/ipip.c                               |  19 ++-
 net/ipv6/ip6_gre.c                            |  15 +-
 net/ipv6/ip6_tunnel.c                         |  19 ++-
 net/ipv6/sit.c                                |  18 ++-
 net/mac80211/ieee80211_i.h                    |  13 +-
 net/mac80211/main.c                           |  24 ++++
 net/openvswitch/vport-internal_dev.c          |  13 +-
 net/xfrm/xfrm_interface.c                     |  16 ++-
 184 files changed, 2923 insertions(+), 1139 deletions(-)

diff --git a/arch/um/drivers/vector_transports.c b/arch/um/drivers/vector_transports.c
index 0794d23f07cb..bf43b554e5f2 100644
--- a/arch/um/drivers/vector_transports.c
+++ b/arch/um/drivers/vector_transports.c
@@ -397,6 +397,35 @@ static int build_l2tpv3_transport_data(struct vector_private *vp)
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(raw_hw_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_GRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(raw_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_GRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(hybrid_hw_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_GRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(hybrid_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_GRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(tap_hw_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_GRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(tap_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_GRO_BIT);
+
 static int build_raw_transport_data(struct vector_private *vp)
 {
 	if (uml_raw_enable_vnet_headers(vp->fds->rx_fd)) {
@@ -406,10 +435,8 @@ static int build_raw_transport_data(struct vector_private *vp)
 		vp->verify_header = &raw_verify_header;
 		vp->header_size = sizeof(struct virtio_net_hdr);
 		vp->rx_header_size = sizeof(struct virtio_net_hdr);
-		vp->dev->hw_features |= (NETIF_F_TSO | NETIF_F_GRO);
-		vp->dev->features |=
-			(NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
-				NETIF_F_TSO | NETIF_F_GRO);
+		netdev_hw_features_set_array(vp->dev, &raw_hw_feature_set);
+		netdev_active_features_set_array(vp->dev, &raw_feature_set);
 		netdev_info(
 			vp->dev,
 			"raw: using vnet headers for tso and tx/rx checksum"
@@ -425,11 +452,8 @@ static int build_hybrid_transport_data(struct vector_private *vp)
 		vp->verify_header = &raw_verify_header;
 		vp->header_size = sizeof(struct virtio_net_hdr);
 		vp->rx_header_size = sizeof(struct virtio_net_hdr);
-		vp->dev->hw_features |=
-			(NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
-		vp->dev->features |=
-			(NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
-				NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
+		netdev_hw_features_set_array(vp->dev, &hybrid_hw_feature_set);
+		netdev_active_features_set_array(vp->dev, &hybrid_feature_set);
 		netdev_info(
 			vp->dev,
 			"tap/raw hybrid: using vnet headers for tso and tx/rx checksum"
@@ -450,11 +474,8 @@ static int build_tap_transport_data(struct vector_private *vp)
 		vp->verify_header = &raw_verify_header;
 		vp->header_size = sizeof(struct virtio_net_hdr);
 		vp->rx_header_size = sizeof(struct virtio_net_hdr);
-		vp->dev->hw_features |=
-			(NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
-		vp->dev->features |=
-			(NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
-				NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
+		netdev_hw_features_set_array(vp->dev, &tap_hw_feature_set);
+		netdev_active_features_set_array(vp->dev, &tap_feature_set);
 		netdev_info(
 			vp->dev,
 			"tap: using vnet headers for tso and tx/rx checksum"
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 35e9c8a330e2..8f0cbaa4afdc 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -38,6 +38,7 @@
 #include <linux/list.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/workqueue.h>
 #include <linux/kref.h>
 #include <linux/if_infiniband.h>
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 2a8961b685c2..4d917762352f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -2104,6 +2104,10 @@ static const struct net_device_ops ipoib_netdev_default_pf = {
 	.ndo_stop		 = ipoib_ib_dev_stop_default,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(ipoib_feature_set,
+				  NETIF_F_VLAN_CHALLENGED_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 void ipoib_setup_common(struct net_device *dev)
 {
 	dev->header_ops		 = &ipoib_header_ops;
@@ -2119,8 +2123,8 @@ void ipoib_setup_common(struct net_device *dev)
 	dev->addr_len		 = INFINIBAND_ALEN;
 	dev->type		 = ARPHRD_INFINIBAND;
 	dev->tx_queue_len	 = ipoib_sendq_size * 2;
-	dev->features		 = (NETIF_F_VLAN_CHALLENGED	|
-				    NETIF_F_HIGHDMA);
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_array(dev, &ipoib_feature_set);
 	netif_keep_dst(dev);
 
 	memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN);
diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index 9a247eb7679c..f76013edd417 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -9,6 +9,7 @@
 #include <linux/jhash.h>
 #include <linux/if_tunnel.h>
 #include <linux/net.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/igmp.h>
 #include <linux/workqueue.h>
 #include <net/sch_generic.h>
@@ -3095,6 +3096,15 @@ static const struct net_device_ops amt_netdev_ops = {
 	.ndo_get_stats64        = dev_get_tstats64,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(amt_feature_set,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_NETNS_LOCAL_BIT);
+static DECLARE_NETDEV_FEATURE_SET(amt_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static void amt_link_setup(struct net_device *dev)
 {
 	dev->netdev_ops         = &amt_netdev_ops;
@@ -3107,12 +3117,10 @@ static void amt_link_setup(struct net_device *dev)
 	dev->hard_header_len	= 0;
 	dev->addr_len		= 0;
 	dev->priv_flags		|= IFF_NO_QUEUE;
-	dev->features		|= NETIF_F_LLTX;
 	dev->features		|= NETIF_F_GSO_SOFTWARE;
-	dev->features		|= NETIF_F_NETNS_LOCAL;
-	dev->hw_features	|= NETIF_F_SG | NETIF_F_HW_CSUM;
-	dev->hw_features	|= NETIF_F_FRAGLIST | NETIF_F_RXCSUM;
+	netdev_active_features_set_array(dev, &amt_feature_set);
 	dev->hw_features	|= NETIF_F_GSO_SOFTWARE;
+	netdev_hw_features_set_array(dev, &amt_hw_feature_set);
 	eth_hw_addr_random(dev);
 	eth_zero_addr(dev->broadcast);
 	ether_setup(dev);
diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
index 683203f87ae2..08b11ed436ad 100644
--- a/drivers/net/bareudp.c
+++ b/drivers/net/bareudp.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/etherdevice.h>
 #include <linux/hash.h>
+#include <linux/netdev_features_helper.h>
 #include <net/dst_metadata.h>
 #include <net/gro_cells.h>
 #include <net/rtnetlink.h>
@@ -536,18 +537,28 @@ static const struct device_type bareudp_type = {
 	.name = "bareudp",
 };
 
+static DECLARE_NETDEV_FEATURE_SET(bareudp_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_LLTX_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bareudp_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 /* Initialize the device structure. */
 static void bareudp_setup(struct net_device *dev)
 {
 	dev->netdev_ops = &bareudp_netdev_ops;
 	dev->needs_free_netdev = true;
 	SET_NETDEV_DEVTYPE(dev, &bareudp_type);
-	dev->features    |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST;
-	dev->features    |= NETIF_F_RXCSUM;
-	dev->features    |= NETIF_F_LLTX;
+	netdev_active_features_set_array(dev, &bareudp_feature_set);
 	dev->features    |= NETIF_F_GSO_SOFTWARE;
-	dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST;
-	dev->hw_features |= NETIF_F_RXCSUM;
+	netdev_hw_features_set_array(dev, &bareudp_hw_feature_set);
 	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
 	dev->hard_header_len = 0;
 	dev->addr_len = 0;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index e75acb14d066..a7783abec601 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -59,6 +59,7 @@
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/inetdevice.h>
 #include <linux/igmp.h>
 #include <linux/etherdevice.h>
@@ -254,6 +255,25 @@ static const struct flow_dissector_key flow_keys_bonding_keys[] = {
 
 static struct flow_dissector flow_keys_bonding __read_mostly;
 
+static DECLARE_NETDEV_FEATURE_SET(bond_vlan_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_LRO_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bond_enc_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bond_mpls_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT);
+
+static netdev_features_t bond_vlan_features __ro_after_init;
+static netdev_features_t bond_enc_features __ro_after_init;
+static netdev_features_t bond_mpls_features __ro_after_init;
 /*-------------------------- Forward declarations ---------------------------*/
 
 static int bond_init(struct net_device *bond_dev);
@@ -1421,16 +1441,11 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 	return features;
 }
 
-#define BOND_VLAN_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
-				 NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
-				 NETIF_F_HIGHDMA | NETIF_F_LRO)
+#define BOND_VLAN_FEATURES	bond_vlan_features
 
-#define BOND_ENC_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
-				 NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE)
-
-#define BOND_MPLS_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
-				 NETIF_F_GSO_SOFTWARE)
+#define BOND_ENC_FEATURES	bond_enc_features
 
+#define BOND_MPLS_FEATURES	bond_mpls_features
 
 static void bond_compute_features(struct bonding *bond)
 {
@@ -6195,6 +6210,21 @@ static int bond_check_params(struct bond_params *params)
 	return 0;
 }
 
+static void __init bond_netdev_features_init(void)
+{
+	bond_vlan_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&bond_vlan_feature_set,
+				  &bond_vlan_features);
+
+	bond_enc_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&bond_enc_feature_set,
+				  &bond_enc_features);
+
+	bond_mpls_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&bond_mpls_feature_set,
+				  &bond_mpls_features);
+}
+
 /* Called from registration process */
 static int bond_init(struct net_device *bond_dev)
 {
@@ -6355,6 +6385,8 @@ static int __init bonding_init(void)
 				ARRAY_SIZE(flow_keys_bonding_keys));
 
 	register_netdevice_notifier(&bond_netdev_notifier);
+
+	bond_netdev_features_init();
 out:
 	return res;
 err:
diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c
index 3887ed33c5fe..18f978461df5 100644
--- a/drivers/net/dsa/xrs700x/xrs700x.c
+++ b/drivers/net/dsa/xrs700x/xrs700x.c
@@ -9,15 +9,18 @@
 #include <linux/if_bridge.h>
 #include <linux/of_device.h>
 #include <linux/netdev_features.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_hsr.h>
 #include "xrs700x.h"
 #include "xrs700x_reg.h"
 
 #define XRS700X_MIB_INTERVAL msecs_to_jiffies(3000)
 
-#define XRS7000X_SUPPORTED_HSR_FEATURES \
-	(NETIF_F_HW_HSR_TAG_INS | NETIF_F_HW_HSR_TAG_RM | \
-	 NETIF_F_HW_HSR_FWD | NETIF_F_HW_HSR_DUP)
+static DECLARE_NETDEV_FEATURE_SET(xrs7000x_hsr_feature_set,
+				  NETIF_F_HW_HSR_TAG_INS_BIT,
+				  NETIF_F_HW_HSR_TAG_RM_BIT,
+				  NETIF_F_HW_HSR_FWD_BIT,
+				  NETIF_F_HW_HSR_DUP_BIT);
 
 #define XRS7003E_ID	0x100
 #define XRS7003F_ID	0x101
@@ -632,7 +635,8 @@ static int xrs700x_hsr_join(struct dsa_switch *ds, int port,
 	hsr_pair[1] = partner->index;
 	for (i = 0; i < ARRAY_SIZE(hsr_pair); i++) {
 		slave = dsa_to_port(ds, hsr_pair[i])->slave;
-		slave->features |= XRS7000X_SUPPORTED_HSR_FEATURES;
+		netdev_active_features_set_array(slave,
+						 &xrs7000x_hsr_feature_set);
 	}
 
 	return 0;
@@ -686,7 +690,8 @@ static int xrs700x_hsr_leave(struct dsa_switch *ds, int port,
 	hsr_pair[1] = partner->index;
 	for (i = 0; i < ARRAY_SIZE(hsr_pair); i++) {
 		slave = dsa_to_port(ds, hsr_pair[i])->slave;
-		slave->features &= ~XRS7000X_SUPPORTED_HSR_FEATURES;
+		netdev_active_features_clear_array(slave,
+						   &xrs7000x_hsr_feature_set);
 	}
 
 	return 0;
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index f82ad7419508..6f176774efbd 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/init.h>
@@ -110,6 +111,13 @@ static const struct ethtool_ops dummy_ethtool_ops = {
 	.get_ts_info		= ethtool_op_get_ts_info,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(dummy_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_LLTX_BIT);
+
 static void dummy_setup(struct net_device *dev)
 {
 	ether_setup(dev);
@@ -123,9 +131,8 @@ static void dummy_setup(struct net_device *dev)
 	dev->flags |= IFF_NOARP;
 	dev->flags &= ~IFF_MULTICAST;
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
-	dev->features	|= NETIF_F_SG | NETIF_F_FRAGLIST;
+	netdev_active_features_set_array(dev, &dummy_feature_set);
 	dev->features	|= NETIF_F_GSO_SOFTWARE;
-	dev->features	|= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
 	dev->features	|= NETIF_F_GSO_ENCAP_ALL;
 	dev->hw_features |= dev->features;
 	dev->hw_enc_features |= dev->features;
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index cad4f354cc76..cb7a4bb5cf74 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -108,6 +108,7 @@ static const int multicast_filter_limit = 32;
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/mm.h>
@@ -2286,6 +2287,15 @@ static const struct net_device_ops typhoon_netdev_ops = {
 	.ndo_set_mac_address	= eth_mac_addr,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(typhoon_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(typhoon_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static int
 typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -2476,10 +2486,10 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 * on the current 3XP firmware -- it does not respect the offload
 	 * settings -- so we only allow the user to toggle the TX processing.
 	 */
-	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-		NETIF_F_HW_VLAN_CTAG_TX;
-	dev->features = dev->hw_features |
-		NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_RXCSUM;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &typhoon_hw_feature_set);
+	dev->features = dev->hw_features;
+	netdev_active_features_set_array(dev, &typhoon_feature_set);
 
 	err = register_netdev(dev);
 	if (err < 0) {
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 447dc64a17e5..dca85429a0ea 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1336,6 +1336,11 @@ static int greth_mdio_init(struct greth_private *greth)
 	return ret;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(greth_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 /* Initialize the GRETH MAC */
 static int greth_of_probe(struct platform_device *ofdev)
 {
@@ -1483,8 +1488,8 @@ static int greth_of_probe(struct platform_device *ofdev)
 	GRETH_REGSAVE(regs->status, 0xFF);
 
 	if (greth->gbit_mac) {
-		dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_RXCSUM;
+		netdev_hw_features_zero(dev);
+		netdev_hw_features_set_array(dev, &greth_hw_feature_set);
 		dev->features = dev->hw_features | NETIF_F_HIGHDMA;
 		greth_netdev_ops.ndo_start_xmit = greth_start_xmit_gbit;
 	}
diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
index 22fe98555b24..4a16e176248c 100644
--- a/drivers/net/ethernet/alteon/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -55,6 +55,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
@@ -451,6 +452,12 @@ static const struct net_device_ops ace_netdev_ops = {
 	.ndo_change_mtu		= ace_change_mtu,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(acenic_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
 static int acenic_probe_one(struct pci_dev *pdev,
 			    const struct pci_device_id *id)
 {
@@ -469,8 +476,7 @@ static int acenic_probe_one(struct pci_dev *pdev,
 	ap->pdev = pdev;
 	ap->name = pci_name(pdev);
 
-	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-	dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_active_features_set_array(dev, &acenic_feature_set);
 
 	dev->watchdog_timeo = 5*HZ;
 	dev->min_mtu = 0;
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index 6a356a6cee15..ab102769965f 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -11,6 +11,7 @@
 #include <linux/ethtool.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/numa.h>
 #include <linux/pci.h>
 #include <linux/utsname.h>
@@ -4010,6 +4011,11 @@ static u32 ena_calc_max_io_queue_num(struct pci_dev *pdev,
 	return max_num_io_queues;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ena_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static void ena_set_dev_offloads(struct ena_com_dev_get_features_ctx *feat,
 				 struct net_device *netdev)
 {
@@ -4041,11 +4047,8 @@ static void ena_set_dev_offloads(struct ena_com_dev_get_features_ctx *feat,
 		ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV6_CSUM_MASK)
 		dev_features |= NETIF_F_RXCSUM;
 
-	netdev->features =
-		dev_features |
-		NETIF_F_SG |
-		NETIF_F_RXHASH |
-		NETIF_F_HIGHDMA;
+	netdev->features = dev_features;
+	netdev_active_features_set_array(netdev, &ena_feature_set);
 
 	netdev->hw_features |= netdev->features;
 	netdev->vlan_features |= netdev->features;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 0e8698928e4d..a5c4fb8aa676 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -118,6 +118,7 @@
 #include <linux/device.h>
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/io.h>
 #include <linux/notifier.h>
@@ -259,6 +260,34 @@ void xgbe_set_counts(struct xgbe_prv_data *pdata)
 	}
 }
 
+static DECLARE_NETDEV_FEATURE_SET(xgbe_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+static DECLARE_NETDEV_FEATURE_SET(xgbe_hw_enc_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(xgbe_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 int xgbe_config_netdev(struct xgbe_prv_data *pdata)
 {
 	struct net_device *netdev = pdata->netdev;
@@ -342,30 +371,16 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
 #endif
 
 	/* Set device features */
-	netdev->hw_features = NETIF_F_SG |
-			      NETIF_F_IP_CSUM |
-			      NETIF_F_IPV6_CSUM |
-			      NETIF_F_RXCSUM |
-			      NETIF_F_TSO |
-			      NETIF_F_TSO6 |
-			      NETIF_F_GRO |
-			      NETIF_F_HW_VLAN_CTAG_RX |
-			      NETIF_F_HW_VLAN_CTAG_TX |
-			      NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &xgbe_hw_feature_set);
 
 	if (pdata->hw_feat.rss)
 		netdev->hw_features |= NETIF_F_RXHASH;
 
 	if (pdata->hw_feat.vxn) {
-		netdev->hw_enc_features = NETIF_F_SG |
-					  NETIF_F_IP_CSUM |
-					  NETIF_F_IPV6_CSUM |
-					  NETIF_F_RXCSUM |
-					  NETIF_F_TSO |
-					  NETIF_F_TSO6 |
-					  NETIF_F_GRO |
-					  NETIF_F_GSO_UDP_TUNNEL |
-					  NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_hw_enc_features_zero(netdev);
+		netdev_hw_enc_features_set_array(netdev,
+						 &xgbe_hw_enc_feature_set);
 
 		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
 				       NETIF_F_GSO_UDP_TUNNEL_CSUM;
@@ -373,11 +388,7 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
 		netdev->udp_tunnel_nic_info = xgbe_get_udp_tunnel_info();
 	}
 
-	netdev->vlan_features |= NETIF_F_SG |
-				 NETIF_F_IP_CSUM |
-				 NETIF_F_IPV6_CSUM |
-				 NETIF_F_TSO |
-				 NETIF_F_TSO6;
+	netdev_vlan_features_set_array(netdev, &xgbe_vlan_feature_set);
 
 	netdev->features |= netdev->hw_features;
 	pdata->netdev_features = netdev->features;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 53dc8d5fede8..49a35bd4c16d 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/gpio.h>
+#include <linux/netdev_features_helper.h>
 #include "xgene_enet_main.h"
 #include "xgene_enet_hw.h"
 #include "xgene_enet_sgmac.h"
@@ -2012,6 +2013,12 @@ static const struct of_device_id xgene_enet_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, xgene_enet_of_match);
 
+static DECLARE_NETDEV_FEATURE_SET(xgene_vlan_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_SG_BIT);
+
 static int xgene_enet_probe(struct platform_device *pdev)
 {
 	struct net_device *ndev;
@@ -2034,10 +2041,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, pdata);
 	ndev->netdev_ops = &xgene_ndev_ops;
 	xgene_enet_set_ethtool_ops(ndev);
-	ndev->features |= NETIF_F_IP_CSUM |
-			  NETIF_F_GSO |
-			  NETIF_F_GRO |
-			  NETIF_F_SG;
+	netdev_active_features_set_array(ndev, &xgene_vlan_feature_set);
 
 	of_id = of_match_device(xgene_enet_of_match, &pdev->dev);
 	if (of_id) {
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index e11cc29d3264..2a726e6213b4 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -20,6 +20,7 @@
 
 #include <linux/moduleparam.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/timer.h>
 #include <linux/cpu.h>
@@ -368,6 +369,15 @@ int aq_nic_ndev_register(struct aq_nic_s *self)
 	return err;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(aq_nic_vlan_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 void aq_nic_ndev_init(struct aq_nic_s *self)
 {
 	const struct aq_hw_caps_s *aq_hw_caps = self->aq_nic_cfg.aq_hw_caps;
@@ -375,9 +385,7 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 
 	self->ndev->hw_features |= aq_hw_caps->hw_features;
 	self->ndev->features = aq_hw_caps->hw_features;
-	self->ndev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
-				     NETIF_F_RXHASH | NETIF_F_SG |
-				     NETIF_F_LRO | NETIF_F_TSO | NETIF_F_TSO6;
+	netdev_vlan_features_set_array(self->ndev, &aq_nic_vlan_feature_set);
 	self->ndev->gso_partial_features = NETIF_F_GSO_UDP_L4;
 	self->ndev->priv_flags = aq_hw_caps->hw_priv_flags;
 	self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c
index 6ba5b024a7be..9309d371b8da 100644
--- a/drivers/net/ethernet/asix/ax88796c_main.c
+++ b/drivers/net/ethernet/asix/ax88796c_main.c
@@ -19,6 +19,7 @@
 #include <linux/minmax.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/skbuff.h>
@@ -33,6 +34,11 @@ static int msg_enable = NETIF_MSG_PROBE |
 static const char *no_regs_list = "80018001,e1918001,8001a001,fc0d0000";
 unsigned long ax88796c_no_regs_mask[AX88796C_REGDUMP_LEN / (sizeof(unsigned long) * 8)];
 
+static DECLARE_NETDEV_FEATURE_SET(ax88796c_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+static netdev_features_t ax88796c_features __ro_after_init;
+
 module_param(msg_enable, int, 0444);
 MODULE_PARM_DESC(msg_enable, "Message mask (see linux/netdevice.h for bitmap)");
 
@@ -920,12 +926,12 @@ ax88796c_set_features(struct net_device *ndev, netdev_features_t features)
 	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
 	netdev_features_t changed = features ^ ndev->features;
 
-	if (!(changed & (NETIF_F_RXCSUM | NETIF_F_HW_CSUM)))
+	if (!(changed & ax88796c_features))
 		return 0;
 
 	ndev->features = features;
 
-	if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_CSUM))
+	if (changed & ax88796c_features)
 		ax88796c_set_csums(ax_local);
 
 	return 0;
@@ -1023,8 +1029,8 @@ static int ax88796c_probe(struct spi_device *spi)
 	ndev->irq = spi->irq;
 	ndev->netdev_ops = &ax88796c_netdev_ops;
 	ndev->ethtool_ops = &ax88796c_ethtool_ops;
-	ndev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
-	ndev->features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+	ndev->hw_features |= ax88796c_features;
+	ndev->features |= ax88796c_features;
 	ndev->needed_headroom = TX_OVERHEAD;
 	ndev->needed_tailroom = TX_EOP_SIZE;
 
@@ -1138,6 +1144,11 @@ static struct spi_driver ax88796c_spi_driver = {
 	.id_table = asix_id,
 };
 
+static void __init ax88796c_features_init(void)
+{
+	netdev_features_set_array(&ax88796c_feature_set, &ax88796c_features);
+}
+
 static __init int ax88796c_spi_init(void)
 {
 	int ret;
@@ -1150,6 +1161,8 @@ static __init int ax88796c_spi_init(void)
 		pr_err("Invalid bitmap description, masking all registers\n");
 	}
 
+	ax88796c_features_init();
+
 	return spi_register_driver(&ax88796c_spi_driver);
 }
 
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index a89b93cb4e26..7f5cb50f4b66 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -42,6 +42,7 @@
 #include <linux/aer.h>
 #include <linux/bitops.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <net/ip6_checksum.h>
 #include <linux/crc32.h>
@@ -1712,6 +1713,13 @@ static const struct net_device_ops alx_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(alx_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct net_device *netdev;
@@ -1821,11 +1829,8 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		}
 	}
 
-	netdev->hw_features = NETIF_F_SG |
-			      NETIF_F_HW_CSUM |
-			      NETIF_F_RXCSUM |
-			      NETIF_F_TSO |
-			      NETIF_F_TSO6;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &alx_hw_feature_set);
 
 	if (alx_get_perm_macaddr(hw, hw->perm_addr)) {
 		dev_warn(&pdev->dev,
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h
index 43d821fe7a54..6a1f8191a336 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ioport.h>
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index be4b1f8eef29..220253cec3c2 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2618,6 +2618,13 @@ static const struct net_device_ops atl1c_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(atl1c_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 {
 	SET_NETDEV_DEV(netdev, &pdev->dev);
@@ -2629,11 +2636,8 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	atl1c_set_ethtool_ops(netdev);
 
 	/* TODO: add when ready */
-	netdev->hw_features =	NETIF_F_SG		|
-				NETIF_F_HW_CSUM		|
-				NETIF_F_HW_VLAN_CTAG_RX	|
-				NETIF_F_TSO		|
-				NETIF_F_TSO6;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &atl1c_hw_feature_set);
 	netdev->features =	netdev->hw_features	|
 				NETIF_F_HW_VLAN_CTAG_TX;
 	return 0;
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e.h b/drivers/net/ethernet/atheros/atl1e/atl1e.h
index 9fcad783c939..007eef2cc9fc 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e.h
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e.h
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ioport.h>
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 57a51fb7746c..0aaca5a1f87c 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -2255,6 +2255,12 @@ static const struct net_device_ops atl1e_netdev_ops = {
 
 };
 
+static DECLARE_NETDEV_FEATURE_SET(atl1e_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
 static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 {
 	SET_NETDEV_DEV(netdev, &pdev->dev);
@@ -2269,8 +2275,8 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 			  (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
 	atl1e_set_ethtool_ops(netdev);
 
-	netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO |
-			      NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &atl1e_hw_feature_set);
 	netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_TX;
 	/* not enabled by default */
 	netdev->hw_features |= NETIF_F_RXALL | NETIF_F_RXFCS;
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index ff1fe09abf9f..c46d3e7ae89f 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -49,6 +49,7 @@
 #include <linux/module.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/pm.h>
@@ -2891,6 +2892,18 @@ static const struct net_device_ops atl1_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(atl1_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(atl1_hw_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
 /**
  * atl1_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -2987,12 +3000,11 @@ static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (err)
 		goto err_common;
 
-	netdev->features = NETIF_F_HW_CSUM;
-	netdev->features |= NETIF_F_SG;
-	netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
+	netdev_active_features_zero(netdev);
+	netdev_active_features_set_array(netdev, &atl1_feature_set);
 
-	netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO |
-			      NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &atl1_hw_feature_set);
 
 	/* is this valid? see atl1_setup_mac_ctrl() */
 	netdev->features |= NETIF_F_RXCSUM;
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 47fc8e6963d5..05a0c169e418 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/dsa/brcm.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
@@ -153,17 +154,25 @@ static void bcm_sysport_set_rx_csum(struct net_device *dev,
 	rxchk_writel(priv, reg, RXCHK_CONTROL);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(bcm_sysport_tx_csum_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+
 static void bcm_sysport_set_tx_csum(struct net_device *dev,
 				    netdev_features_t wanted)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
+	netdev_features_t tx_csum_features;
 	u32 reg;
 
+	netdev_features_zero(&tx_csum_features);
+	netdev_features_set_array(&bcm_sysport_tx_csum_feature_set,
+				  &tx_csum_features);
 	/* Hardware transmit checksum requires us to enable the Transmit status
 	 * block prepended to the packet contents
 	 */
-	priv->tsb_en = !!(wanted & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-				    NETIF_F_HW_VLAN_CTAG_TX));
+	priv->tsb_en = !!(wanted & tx_csum_features);
 	reg = tdma_readl(priv, TDMA_CONTROL);
 	if (priv->tsb_en)
 		reg |= tdma_control_bit(priv, TSB_EN);
@@ -2453,6 +2462,13 @@ static const struct of_device_id bcm_sysport_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, bcm_sysport_of_match);
 
+DECLARE_NETDEV_FEATURE_SET(bcm_feature_set,
+			   NETIF_F_RXCSUM_BIT,
+			   NETIF_F_HIGHDMA_BIT,
+			   NETIF_F_IP_CSUM_BIT,
+			   NETIF_F_IPV6_CSUM_BIT,
+			   NETIF_F_HW_VLAN_CTAG_TX_BIT);
+
 static int bcm_sysport_probe(struct platform_device *pdev)
 {
 	const struct bcm_sysport_hw_params *params;
@@ -2566,9 +2582,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
 	dev->netdev_ops = &bcm_sysport_netdev_ops;
 	netif_napi_add(dev, &priv->napi, bcm_sysport_poll, 64);
 
-	dev->features |= NETIF_F_RXCSUM | NETIF_F_HIGHDMA |
-			 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			 NETIF_F_HW_VLAN_CTAG_TX;
+	netdev_active_features_set_array(dev, &bcm_feature_set);
 	dev->hw_features |= dev->features;
 	dev->vlan_features |= dev->features;
 	dev->max_mtu = UMAC_MAX_MTU_SIZE;
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 2dfc1e32bbb3..523cadd48669 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -13,6 +13,7 @@
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
 #include <linux/bcm47xx_nvram.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
 #include <net/dsa.h>
@@ -1485,6 +1486,11 @@ struct bgmac *bgmac_alloc(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(bgmac_alloc);
 
+static DECLARE_NETDEV_FEATURE_SET(bgmac_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT);
+
 int bgmac_enet_probe(struct bgmac *bgmac)
 {
 	struct net_device *net_dev = bgmac->net_dev;
@@ -1535,7 +1541,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)
 		goto err_dma_free;
 	}
 
-	net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev_active_features_zero(net_dev);
+	netdev_active_features_set_array(net_dev, &bgmac_feature_set);
 	net_dev->hw_features = net_dev->features;
 	net_dev->vlan_features = net_dev->features;
 
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index b97ed9b5f685..0e779e5dee9a 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
@@ -8544,6 +8545,14 @@ static const struct net_device_ops bnx2_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(bnx2_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static int
 bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -8580,9 +8589,8 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	eth_hw_addr_set(dev, bp->mac_addr);
 
-	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
-		NETIF_F_TSO | NETIF_F_TSO_ECN |
-		NETIF_F_RXHASH | NETIF_F_RXCSUM;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &bnx2_hw_feature_set);
 
 	if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
 		dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 962253db25b8..845d31294667 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -32,6 +32,7 @@
 #include <linux/aer.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
@@ -13045,6 +13046,55 @@ static void bnx2x_disable_pcie_error_reporting(struct bnx2x *bp)
 	}
 }
 
+static DECLARE_NETDEV_FEATURE_SET(bnx2x_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_GRO_HW_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bnx2x_hw_gso_feature_set,
+				  NETIF_F_GSO_GRE_BIT,
+				  NETIF_F_GSO_GRE_CSUM_BIT,
+				  NETIF_F_GSO_IPXIP4_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bnx2x_hw_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GSO_IPXIP4_BIT,
+				  NETIF_F_GSO_GRE_BIT,
+				  NETIF_F_GSO_GRE_CSUM_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bnx2x_gso_partial_feature_set,
+				  NETIF_F_GSO_GRE_CSUM_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bnx2x_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 			  struct net_device *dev, unsigned long board_type)
 {
@@ -13197,34 +13247,23 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
-	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
-		NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO | NETIF_F_GRO_HW |
-		NETIF_F_RXHASH | NETIF_F_HW_VLAN_CTAG_TX;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &bnx2x_hw_feature_set);
 	if (!chip_is_e1x) {
-		dev->hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_GRE_CSUM |
-				    NETIF_F_GSO_IPXIP4 |
-				    NETIF_F_GSO_UDP_TUNNEL |
-				    NETIF_F_GSO_UDP_TUNNEL_CSUM |
-				    NETIF_F_GSO_PARTIAL;
-
-		dev->hw_enc_features =
-			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
-			NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
-			NETIF_F_GSO_IPXIP4 |
-			NETIF_F_GSO_GRE | NETIF_F_GSO_GRE_CSUM |
-			NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM |
-			NETIF_F_GSO_PARTIAL;
-
-		dev->gso_partial_features = NETIF_F_GSO_GRE_CSUM |
-					    NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_hw_features_set_array(dev, &bnx2x_hw_gso_feature_set);
+
+		netdev_hw_enc_features_zero(dev);
+		netdev_hw_enc_features_set_array(dev, &bnx2x_hw_enc_feature_set);
+
+		netdev_gso_partial_features_zero(dev);
+		netdev_gso_partial_features_set_array(dev, &bnx2x_gso_partial_feature_set);
 
 		if (IS_PF(bp))
 			dev->udp_tunnel_nic_info = &bnx2x_udp_tunnels;
 	}
 
-	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
+	netdev_vlan_features_zero(dev);
+	netdev_vlan_features_set_array(dev, &bnx2x_vlan_feature_set);
 
 	if (IS_PF(bp)) {
 		if (chip_is_e1x)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index ba0f1ffac507..825bf829b36a 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -20,6 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
@@ -13517,6 +13518,38 @@ void bnxt_print_device_info(struct bnxt *bp)
 	pcie_print_link_status(bp->pdev);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(bnxt_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_GRE_BIT,
+				  NETIF_F_GSO_IPXIP4_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_GSO_GRE_CSUM_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_GRO_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bnxt_hw_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_GRE_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_GSO_GRE_CSUM_BIT,
+				  NETIF_F_GSO_IPXIP4_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT);
+static DECLARE_NETDEV_FEATURE_SET(bnxt_gso_partial_feature_set,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_GSO_GRE_CSUM_BIT);
+
 static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct net_device *dev;
@@ -13594,27 +13627,18 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto init_err_pci_clean;
 	}
 
-	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
-			   NETIF_F_TSO | NETIF_F_TSO6 |
-			   NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
-			   NETIF_F_GSO_IPXIP4 |
-			   NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
-			   NETIF_F_GSO_PARTIAL | NETIF_F_RXHASH |
-			   NETIF_F_RXCSUM | NETIF_F_GRO;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &bnxt_hw_feature_set);
 
 	if (BNXT_SUPPORTS_TPA(bp))
 		dev->hw_features |= NETIF_F_LRO;
 
-	dev->hw_enc_features =
-			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
-			NETIF_F_TSO | NETIF_F_TSO6 |
-			NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
-			NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
-			NETIF_F_GSO_IPXIP4 | NETIF_F_GSO_PARTIAL;
+	netdev_hw_enc_features_zero(dev);
+	netdev_hw_enc_features_set_array(dev, &bnxt_hw_enc_feature_set);
 	dev->udp_tunnel_nic_info = &bnxt_udp_tunnels;
 
-	dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM |
-				    NETIF_F_GSO_GRE_CSUM;
+	netdev_gso_partial_features_zero(dev);
+	netdev_gso_partial_features_set_array(dev, &bnxt_gso_partial_feature_set);
 	dev->vlan_features = dev->hw_features | NETIF_F_HIGHDMA;
 	if (bp->fw_cap & BNXT_FW_CAP_VLAN_RX_STRIP)
 		dev->hw_features |= BNXT_HW_FEATURE_VLAN_ALL_RX;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 8309fb993cdb..0d41ae12e262 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -28,6 +28,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/inetdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -3969,6 +3970,12 @@ static const struct of_device_id bcmgenet_match[] = {
 };
 MODULE_DEVICE_TABLE(of, bcmgenet_match);
 
+static DECLARE_NETDEV_FEATURE_SET(bcmgenet_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static int bcmgenet_probe(struct platform_device *pdev)
 {
 	struct bcmgenet_platform_data *pd = pdev->dev.platform_data;
@@ -4025,8 +4032,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
 	priv->msg_enable = netif_msg_init(-1, GENET_MSG_DEFAULT);
 
 	/* Set default features */
-	dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
-			 NETIF_F_RXCSUM;
+	netdev_active_features_set_array(dev, &bcmgenet_feature_set);
 	dev->hw_features |= dev->features;
 	dev->vlan_features |= dev->features;
 
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 29dd0f93d6c0..786df1e64947 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -10,6 +10,7 @@
  */
 #include <linux/bitops.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <linux/etherdevice.h>
 #include <linux/in.h>
@@ -3417,22 +3418,40 @@ static const struct net_device_ops bnad_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(bnad_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bnad_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(bnad_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static void
 bnad_netdev_init(struct bnad *bnad)
 {
 	struct net_device *netdev = bnad->netdev;
 
-	netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_TX |
-		NETIF_F_HW_VLAN_CTAG_RX;
-
-	netdev->vlan_features = NETIF_F_SG | NETIF_F_HIGHDMA |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO6;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &bnad_hw_feature_set);
+	netdev_vlan_features_zero(netdev);
+	netdev_vlan_features_set_array(netdev, &bnad_vlan_feature_set);
 
-	netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER |
-			    NETIF_F_HIGHDMA;
+	netdev->features |= netdev->hw_features;
+	netdev_active_features_set_array(netdev, &bnad_feature_set);
 
 	netdev->mem_start = bnad->mmio_start;
 	netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1;
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 1281d1565ef8..415f61527650 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -14,6 +14,7 @@
 #include <linux/if.h>
 #include <linux/crc32.h>
 #include <linux/dma-mapping.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/slab.h>
 
 /* XGMAC Register definitions */
@@ -1682,6 +1683,14 @@ static const struct ethtool_ops xgmac_ethtool_ops = {
 	.get_link_ksettings = xgmac_ethtool_get_link_ksettings,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(xgmac_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(xgmac_csum_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 /**
  * xgmac_probe
  * @pdev: platform device pointer
@@ -1774,10 +1783,10 @@ static int xgmac_probe(struct platform_device *pdev)
 	if (device_can_wakeup(priv->device))
 		priv->wolopts = WAKE_MAGIC;	/* Magic Frame as default */
 
-	ndev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA;
+	netdev_hw_features_zero(ndev);
+	netdev_hw_features_set_array(ndev, &xgmac_hw_feature_set);
 	if (readl(priv->base + XGMAC_DMA_HW_FEATURE) & DMA_HW_FEAT_TXCOESEL)
-		ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-				     NETIF_F_RXCSUM;
+		netdev_hw_features_set_array(ndev, &xgmac_csum_feature_set);
 	ndev->features |= ndev->hw_features;
 	ndev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index bee35ce60171..9c9c8dee0c7b 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/firmware.h>
+#include <linux/netdev_features_helper.h>
 #include <net/vxlan.h>
 #include <linux/kthread.h>
 #include "liquidio_common.h"
@@ -3317,6 +3318,27 @@ static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf)
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(liquidio_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_LRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(liquidio_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_LRO_BIT);
+
 /**
  * setup_nic_devices - Setup network interfaces
  * @octeon_dev:  octeon device
@@ -3555,26 +3577,18 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 
 		if (OCTEON_CN23XX_PF(octeon_dev) ||
 		    OCTEON_CN6XXX(octeon_dev)) {
-			lio->dev_capability = NETIF_F_HIGHDMA
-					      | NETIF_F_IP_CSUM
-					      | NETIF_F_IPV6_CSUM
-					      | NETIF_F_SG | NETIF_F_RXCSUM
-					      | NETIF_F_GRO
-					      | NETIF_F_TSO | NETIF_F_TSO6
-					      | NETIF_F_LRO;
+			netdev_features_zero(&lio->dev_capability);
+			netdev_features_set_array(&liquidio_feature_set,
+						  &lio->dev_capability);
 		}
 		netif_set_tso_max_size(netdev, OCTNIC_GSO_MAX_SIZE);
 
 		/*  Copy of transmit encapsulation capabilities:
 		 *  TSO, TSO6, Checksums for this device
 		 */
-		lio->enc_dev_capability = NETIF_F_IP_CSUM
-					  | NETIF_F_IPV6_CSUM
-					  | NETIF_F_GSO_UDP_TUNNEL
-					  | NETIF_F_HW_CSUM | NETIF_F_SG
-					  | NETIF_F_RXCSUM
-					  | NETIF_F_TSO | NETIF_F_TSO6
-					  | NETIF_F_LRO;
+		netdev_features_zero(&lio->enc_dev_capability);
+		netdev_features_set_array(&liquidio_enc_feature_set,
+					  &lio->enc_dev_capability);
 
 		netdev->hw_enc_features = (lio->enc_dev_capability &
 					   ~NETIF_F_LRO);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index ac196883f07e..9e0c176ea7af 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/netdev_features_helper.h>
 #include <net/vxlan.h>
 #include "liquidio_common.h"
 #include "octeon_droq.h"
@@ -1926,6 +1927,27 @@ static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf)
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(lio_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_LRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(lio_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_LRO_BIT);
+
 /**
  * setup_nic_devices - Setup network interfaces
  * @octeon_dev:  octeon device
@@ -2088,24 +2110,16 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 
 		lio->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
-		lio->dev_capability = NETIF_F_HIGHDMA
-				      | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
-				      | NETIF_F_SG | NETIF_F_RXCSUM
-				      | NETIF_F_TSO | NETIF_F_TSO6
-				      | NETIF_F_GRO
-				      | NETIF_F_LRO;
+		netdev_features_zero(&lio->dev_capability);
+		netdev_features_set_array(&lio_feature_set, &lio->dev_capability);
 		netif_set_tso_max_size(netdev, OCTNIC_GSO_MAX_SIZE);
 
 		/* Copy of transmit encapsulation capabilities:
 		 * TSO, TSO6, Checksums for this device
 		 */
-		lio->enc_dev_capability = NETIF_F_IP_CSUM
-					  | NETIF_F_IPV6_CSUM
-					  | NETIF_F_GSO_UDP_TUNNEL
-					  | NETIF_F_HW_CSUM | NETIF_F_SG
-					  | NETIF_F_RXCSUM
-					  | NETIF_F_TSO | NETIF_F_TSO6
-					  | NETIF_F_LRO;
+		netdev_features_zero(&lio->enc_dev_capability);
+		netdev_features_set_array(&lio_enc_feature_set,
+					  &lio->enc_dev_capability);
 
 		netdev->hw_enc_features =
 		    (lio->enc_dev_capability & ~NETIF_F_LRO);
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
index ebe56bd8849b..61e5e5782f5b 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_network.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
@@ -147,13 +147,13 @@ struct lio {
 	u32 msg_enable;
 
 	/** Copy of Interface capabilities: TSO, TSO6, LRO, Chescksums . */
-	u64 dev_capability;
+	netdev_features_t dev_capability;
 
 	/* Copy of transmit encapsulation capabilities:
 	 * TSO, TSO6, Checksums for this device for Kernel
 	 * 3.10.0 onwards
 	 */
-	u64 enc_dev_capability;
+	netdev_features_t enc_dev_capability;
 
 	/** Copy of beacaon reg in phy */
 	u32 phy_beacon_val;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 768ea426d49f..c6923ecabb63 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -7,6 +7,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_vlan.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -2092,6 +2093,22 @@ static const struct net_device_ops nicvf_netdev_ops = {
 	.ndo_set_rx_mode        = nicvf_set_rx_mode,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(nicvf_hw_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(nicvf_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct device *dev = &pdev->dev;
@@ -2203,18 +2220,16 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (err)
 		goto err_unregister_interrupts;
 
-	netdev->hw_features = (NETIF_F_RXCSUM | NETIF_F_SG |
-			       NETIF_F_TSO | NETIF_F_GRO | NETIF_F_TSO6 |
-			       NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			       NETIF_F_HW_VLAN_CTAG_RX);
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &nicvf_hw_feature_set);
 
 	netdev->hw_features |= NETIF_F_RXHASH;
 
 	netdev->features |= netdev->hw_features;
 	netdev->hw_features |= NETIF_F_LOOPBACK;
 
-	netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM |
-				NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
+	netdev_vlan_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &nicvf_vlan_feature_set);
 
 	netdev->netdev_ops = &nicvf_netdev_ops;
 	netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index f4054d2553ea..44404b711e09 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -39,6 +39,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
 #include <linux/mii.h>
@@ -942,6 +943,18 @@ static const struct net_device_ops cxgb_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(cxgb_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(cxgb_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	unsigned long mmio_start, mmio_len;
@@ -1031,10 +1044,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev->mem_start = mmio_start;
 		netdev->mem_end = mmio_start + mmio_len - 1;
 		netdev->ml_priv = adapter;
-		netdev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_RXCSUM;
-		netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_RXCSUM | NETIF_F_LLTX | NETIF_F_HIGHDMA;
+		netdev_hw_features_set_array(netdev, &cxgb_hw_feature_set);
+		netdev_active_features_set_array(netdev, &cxgb_feature_set);
 
 		if (vlan_tso_capable(adapter)) {
 			netdev->features |=
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 174b1e156669..80f65f491b3f 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -37,6 +37,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
 #include <linux/mdio.h>
@@ -3199,15 +3200,29 @@ static void cxgb3_init_iscsi_mac(struct net_device *dev)
 	pi->iscsic.mac_addr[3] |= 0x80;
 }
 
-#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
-#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
-			NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
+static DECLARE_NETDEV_FEATURE_SET(cxgb_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(cxgb_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
 static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int i, err;
 	resource_size_t mmio_start, mmio_len;
 	const struct adapter_info *ai;
 	struct adapter *adapter = NULL;
+	netdev_features_t vlan_feat;
 	struct port_info *pi;
 
 	if (!cxgb3_wq) {
@@ -3303,11 +3318,13 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev->irq = pdev->irq;
 		netdev->mem_start = mmio_start;
 		netdev->mem_end = mmio_start + mmio_len - 1;
-		netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_hw_features_zero(netdev);
+		netdev_hw_features_set_array(netdev, &cxgb_hw_feature_set);
 		netdev->features |= netdev->hw_features |
 				    NETIF_F_HW_VLAN_CTAG_TX;
-		netdev->vlan_features |= netdev->features & VLAN_FEAT;
+		netdev_features_zero(&vlan_feat);
+		netdev_features_set_array(&cxgb_vlan_feature_set, &vlan_feat);
+		netdev->vlan_features |= netdev->features & vlan_feat;
 
 		netdev->features |= NETIF_F_HIGHDMA;
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index d0061921529f..f40e6964de89 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -50,6 +50,7 @@
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/aer.h>
 #include <linux/rtnetlink.h>
@@ -6205,10 +6206,41 @@ static void free_some_resources(struct adapter *adapter)
 		t4_fw_bye(adapter, adapter->pf);
 }
 
-#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | \
-		   NETIF_F_GSO_UDP_L4)
-#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
-		   NETIF_F_GRO | NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
+static DECLARE_NETDEV_FEATURE_SET(cxgb4_tso_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT);
+static DECLARE_NETDEV_FEATURE_SET(cxgb4_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(cxgb4_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_TC_BIT,
+				  NETIF_F_NTUPLE_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(cxgb4_hw_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(cxgb4_new_hw_feature_set,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_HW_TLS_RECORD_BIT);
+
 #define SEGMENT_SIZE 128
 
 static int t4_get_chip_type(struct adapter *adap, int ver)
@@ -6598,6 +6630,8 @@ static const struct xfrmdev_ops cxgb4_xfrmdev_ops = {
 
 static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+	netdev_features_t vlan_features;
+	netdev_features_t tso_features;
 	struct net_device *netdev;
 	struct adapter *adapter;
 	static int adap_idx = 1;
@@ -6809,30 +6843,26 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		pi->port_id = i;
 		netdev->irq = pdev->irq;
 
-		netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
-			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_GRO |
-			NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
-			NETIF_F_HW_TC | NETIF_F_NTUPLE | NETIF_F_HIGHDMA;
+		netdev_features_zero(&tso_features);
+		netdev_features_set_array(&cxgb4_tso_feature_set, &tso_features);
+		netdev->hw_features = tso_features;
+		netdev_hw_features_set_array(netdev, &cxgb4_hw_feature_set);
 
 		if (chip_ver > CHELSIO_T5) {
-			netdev->hw_enc_features |= NETIF_F_IP_CSUM |
-						   NETIF_F_IPV6_CSUM |
-						   NETIF_F_RXCSUM |
-						   NETIF_F_GSO_UDP_TUNNEL |
-						   NETIF_F_GSO_UDP_TUNNEL_CSUM |
-						   NETIF_F_TSO | NETIF_F_TSO6;
+			netdev_hw_enc_features_set_array(netdev,
+							 &cxgb4_hw_enc_feature_set);
 
-			netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
-					       NETIF_F_GSO_UDP_TUNNEL_CSUM |
-					       NETIF_F_HW_TLS_RECORD;
+			netdev_hw_features_set_array(netdev,
+						     &cxgb4_new_hw_feature_set);
 
 			if (adapter->rawf_cnt)
 				netdev->udp_tunnel_nic_info = &cxgb_udp_tunnels;
 		}
 
 		netdev->features |= netdev->hw_features;
-		netdev->vlan_features = netdev->features & VLAN_FEAT;
+		vlan_features = tso_features;
+		netdev_features_set_array(&cxgb4_vlan_feature_set, &vlan_features);
+		netdev->vlan_features = netdev->features & vlan_features;
 #if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
 		if (pi->adapter->params.crypto & FW_CAPS_CONFIG_TLS_HW) {
 			netdev->hw_features |= NETIF_F_HW_TLS_TX;
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index c2822e635f89..2d6e1b42b36b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -41,6 +41,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/debugfs.h>
 #include <linux/ethtool.h>
@@ -1921,9 +1922,26 @@ static void cxgb4vf_get_wol(struct net_device *dev,
 /*
  * TCP Segmentation Offload flags which we support.
  */
-#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
-#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
-		   NETIF_F_GRO | NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
+static DECLARE_NETDEV_FEATURE_SET(cxgb4vf_tso_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(cxgb4vf_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(cxgb4vf_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 static const struct ethtool_ops cxgb4vf_ethtool_ops = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
@@ -2895,6 +2913,8 @@ static unsigned int cxgb4vf_get_port_mask(struct adapter *adapter)
 static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 			     const struct pci_device_id *ent)
 {
+	netdev_features_t vlan_features;
+	netdev_features_t tso_features;
 	struct adapter *adapter;
 	struct net_device *netdev;
 	struct port_info *pi;
@@ -3067,11 +3087,16 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 		pi->xact_addr_filt = -1;
 		netdev->irq = pdev->irq;
 
-		netdev->hw_features = NETIF_F_SG | TSO_FLAGS | NETIF_F_GRO |
-			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
-			NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_features_zero(&tso_features);
+		netdev_features_set_array(&cxgb4vf_tso_feature_set,
+					  &tso_features);
+		netdev->hw_features = tso_features;
+		netdev_hw_features_set_array(netdev, &cxgb4vf_hw_feature_set);
 		netdev->features = netdev->hw_features | NETIF_F_HIGHDMA;
-		netdev->vlan_features = netdev->features & VLAN_FEAT;
+		vlan_features = tso_features;
+		netdev_features_set_array(&cxgb4vf_vlan_feature_set,
+					  &vlan_features);
+		netdev->vlan_features = netdev->features & vlan_features;
 
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 		netdev->min_mtu = 81;
diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c
index 21ba6e893072..8d631b2cba23 100644
--- a/drivers/net/ethernet/cirrus/ep93xx_eth.c
+++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/mii.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -738,6 +739,10 @@ static const struct net_device_ops ep93xx_netdev_ops = {
 	.ndo_set_mac_address	= eth_mac_addr,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(ep93xx_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+
 static struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data)
 {
 	struct net_device *dev;
@@ -751,7 +756,7 @@ static struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data)
 	dev->ethtool_ops = &ep93xx_ethtool_ops;
 	dev->netdev_ops = &ep93xx_netdev_ops;
 
-	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+	netdev_active_features_set_array(dev, &ep93xx_feature_set);
 
 	return dev;
 }
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 372fb7b3a282..276fa370ce50 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -27,6 +27,7 @@
 #include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
@@ -2665,6 +2666,15 @@ static void enic_iounmap(struct enic *enic)
 			iounmap(enic->bar[i].vaddr);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(enic_hw_enc_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+
 static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct device *dev = &pdev->dev;
@@ -2904,13 +2914,8 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		u64 patch_level;
 		u64 a1 = 0;
 
-		netdev->hw_enc_features |= NETIF_F_RXCSUM		|
-					   NETIF_F_TSO			|
-					   NETIF_F_TSO6			|
-					   NETIF_F_TSO_ECN		|
-					   NETIF_F_GSO_UDP_TUNNEL	|
-					   NETIF_F_HW_CSUM		|
-					   NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_hw_enc_features_set_array(netdev,
+						 &enic_hw_enc_feature_set);
 		netdev->hw_features |= netdev->hw_enc_features;
 		/* get bit mask from hw about supported offload bit level
 		 * BIT(0) = fw supports patch_level 0
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 9e6de2f968fa..d2b0296b426a 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -36,6 +36,7 @@
 #include <linux/ethtool.h>
 #include <linux/tcp.h>
 #include <linux/u64_stats_sync.h>
+#include <linux/netdev_features_helper.h>
 
 #include <linux/in.h>
 #include <linux/ip.h>
@@ -78,9 +79,16 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 			      GMAC0_SWTQ00_FIN_INT_BIT)
 #define GMAC0_IRQ4_8 (GMAC0_MIB_INT_BIT | GMAC0_RX_OVERRUN_INT_BIT)
 
-#define GMAC_OFFLOAD_FEATURES (NETIF_F_SG | NETIF_F_IP_CSUM | \
-		NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | \
-		NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
+static DECLARE_NETDEV_FEATURE_SET(gmac_offload_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO6_BIT);
+static netdev_features_t gmac_offload_features __ro_after_init;
+#define GMAC_OFFLOAD_FEATURES gmac_offload_features
 
 /**
  * struct gmac_queue_page - page buffer per-page info
@@ -2610,6 +2618,12 @@ static struct platform_driver gemini_ethernet_driver = {
 	.remove = gemini_ethernet_remove,
 };
 
+static void __init gmac_netdev_features_init(void)
+{
+	netdev_features_set_array(&gmac_offload_feature_set,
+				  &gmac_offload_features);
+}
+
 static int __init gemini_ethernet_module_init(void)
 {
 	int ret;
@@ -2624,6 +2638,8 @@ static int __init gemini_ethernet_module_init(void)
 		return ret;
 	}
 
+	gmac_netdev_features_init();
+
 	return 0;
 }
 module_init(gemini_ethernet_module_init);
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 414362febbb9..964e7d6111df 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -18,6 +18,7 @@
 #include <asm/div64.h>
 #include <linux/aer.h>
 #include <linux/if_bridge.h>
+#include <linux/netdev_features_helper.h>
 #include <net/busy_poll.h>
 #include <net/vxlan.h>
 
@@ -3967,6 +3968,13 @@ static void be_cancel_err_detection(struct be_adapter *adapter)
 	}
 }
 
+DECLARE_NETDEV_FEATURE_SET(be_hw_enc_feature_set,
+			   NETIF_F_IP_CSUM_BIT,
+			   NETIF_F_IPV6_CSUM_BIT,
+			   NETIF_F_TSO_BIT,
+			   NETIF_F_TSO6_BIT,
+			   NETIF_F_GSO_UDP_TUNNEL_BIT);
+
 /* VxLAN offload Notes:
  *
  * The stack defines tunnel offload flags (hw_enc_features) for IP and doesn't
@@ -3999,9 +4007,7 @@ static int be_vxlan_set_port(struct net_device *netdev, unsigned int table,
 	}
 	adapter->vxlan_port = ti->port;
 
-	netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-				   NETIF_F_TSO | NETIF_F_TSO6 |
-				   NETIF_F_GSO_UDP_TUNNEL;
+	netdev_hw_enc_features_set_array(netdev, &be_hw_enc_feature_set);
 
 	dev_info(dev, "Enabled VxLAN offloads for UDP port %d\n",
 		 be16_to_cpu(ti->port));
@@ -5182,23 +5188,40 @@ static const struct net_device_ops be_netdev_ops = {
 	.ndo_get_phys_port_id   = be_get_phys_port_id,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(be_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(be_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(be_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT);
+
 static void be_netdev_init(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 
-	netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
-		NETIF_F_GSO_UDP_TUNNEL |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
-		NETIF_F_HW_VLAN_CTAG_TX;
+	netdev_hw_features_set_array(netdev, &be_hw_feature_set);
 	if ((be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
 		netdev->hw_features |= NETIF_F_RXHASH;
 
-	netdev->features |= netdev->hw_features |
-		NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER |
-		NETIF_F_HIGHDMA;
+	netdev->features |= netdev->hw_features;
+	netdev_active_features_set_array(netdev, &be_feature_set);
 
-	netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev_vlan_features_set_array(netdev, &be_vlan_feature_set);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index c03663785a8d..8c95ad9df5e5 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1777,6 +1777,14 @@ static bool ftgmac100_has_child_node(struct device_node *np, const char *name)
 	return ret;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ftgmac100_hw_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+
 static int ftgmac100_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -1931,9 +1939,8 @@ static int ftgmac100_probe(struct platform_device *pdev)
 	priv->tx_q_entries = priv->new_tx_q_entries = DEF_TX_QUEUE_ENTRIES;
 
 	/* Base feature set */
-	netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
-		NETIF_F_GRO | NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_RX |
-		NETIF_F_HW_VLAN_CTAG_TX;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &ftgmac100_hw_feature_set);
 
 	if (priv->use_ncsi)
 		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 45634579adb6..545e2b1afad7 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -20,6 +20,7 @@
 #include <linux/udp.h>
 #include <linux/tcp.h>
 #include <linux/net.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
@@ -197,6 +198,14 @@ static int dpaa_rx_extra_headroom;
 #define dpaa_get_max_mtu()	\
 	(dpaa_max_frm - (VLAN_ETH_HLEN + ETH_FCS_LEN))
 
+static DECLARE_NETDEV_FEATURE_SET(dpaa_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static int dpaa_netdev_init(struct net_device *net_dev,
 			    const struct net_device_ops *dpaa_ops,
 			    u16 tx_timeout)
@@ -224,10 +233,7 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 	net_dev->min_mtu = ETH_MIN_MTU;
 	net_dev->max_mtu = dpaa_get_max_mtu();
 
-	net_dev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-				 NETIF_F_LLTX | NETIF_F_RXHASH);
-
-	net_dev->hw_features |= NETIF_F_SG | NETIF_F_HIGHDMA;
+	netdev_hw_features_set_array(net_dev, &dpaa_hw_feature_set);
 	/* The kernels enables GSO automatically, if we declare NETIF_F_SG.
 	 * For conformity, we'll still declare GSO explicitly.
 	 */
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index cd9ec80522e7..d3c51e1a7c82 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -9,6 +9,7 @@
 #include <linux/of_net.h>
 #include <linux/interrupt.h>
 #include <linux/msi.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/kthread.h>
 #include <linux/iommu.h>
 #include <linux/fsl/mc.h>
@@ -4327,6 +4328,16 @@ static int dpaa2_eth_set_mac_addr(struct dpaa2_eth_priv *priv)
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(dpaa2_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_HW_TC_BIT,
+				  NETIF_F_TSO_BIT);
+
 static int dpaa2_eth_netdev_init(struct net_device *net_dev)
 {
 	struct device *dev = net_dev->dev.parent;
@@ -4388,10 +4399,8 @@ static int dpaa2_eth_netdev_init(struct net_device *net_dev)
 	net_dev->priv_flags &= ~not_supported;
 
 	/* Features */
-	net_dev->features = NETIF_F_RXCSUM |
-			    NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			    NETIF_F_SG | NETIF_F_HIGHDMA |
-			    NETIF_F_LLTX | NETIF_F_HW_TC | NETIF_F_TSO;
+	netdev_active_features_zero(net_dev);
+	netdev_active_features_set_array(net_dev, &dpaa2_feature_set);
 	net_dev->gso_max_segs = DPAA2_ETH_ENQUEUE_MAX_FDS;
 	net_dev->hw_features = net_dev->features;
 
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index e507e9065214..87ae011633ba 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -3238,6 +3238,11 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(dpaa2_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_VLAN_STAG_FILTER_BIT,
+				  NETIF_F_HW_TC_BIT);
+
 static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
 				   u16 port_idx)
 {
@@ -3280,9 +3285,8 @@ static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
 	/* The DPAA2 switch's ingress path depends on the VLAN table,
 	 * thus we are not able to disable VLAN filtering.
 	 */
-	port_netdev->features = NETIF_F_HW_VLAN_CTAG_FILTER |
-				NETIF_F_HW_VLAN_STAG_FILTER |
-				NETIF_F_HW_TC;
+	netdev_active_features_zero(port_netdev);
+	netdev_active_features_set_array(port_netdev, &dpaa2_feature_set);
 
 	err = dpaa2_switch_port_init(port_priv, port_idx);
 	if (err)
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
index 0002dca4d417..e7d92ac769e9 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
@@ -11,6 +11,7 @@
 #define __ETHSW_H
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index c4a0e836d4f0..b8daac778c64 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -4,6 +4,7 @@
 #include <asm/unaligned.h>
 #include <linux/mdio.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/fsl/enetc_mdio.h>
 #include <linux/of_platform.h>
 #include <linux/of_mdio.h>
@@ -744,6 +745,31 @@ static const struct net_device_ops enetc_ndev_ops = {
 	.ndo_xdp_xmit		= enetc_xdp_xmit,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(enetc_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_LOOPBACK_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(enetc_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(enetc_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 				  const struct net_device_ops *ndev_ops)
 {
@@ -761,16 +787,12 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	ndev->watchdog_timeo = 5 * HZ;
 	ndev->max_mtu = ENETC_MAX_MTU;
 
-	ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
-			    NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK |
-			    NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
-	ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
-			 NETIF_F_HW_VLAN_CTAG_TX |
-			 NETIF_F_HW_VLAN_CTAG_RX |
-			 NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
-	ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
-			      NETIF_F_TSO | NETIF_F_TSO6;
+	netdev_hw_features_zero(ndev);
+	netdev_hw_features_set_array(ndev, &enetc_hw_feature_set);
+	netdev_active_features_zero(ndev);
+	netdev_active_features_set_array(ndev, &enetc_feature_set);
+	netdev_vlan_features_zero(ndev);
+	netdev_vlan_features_set_array(ndev, &enetc_vlan_feature_set);
 
 	if (si->num_rss)
 		ndev->hw_features |= NETIF_F_RXHASH;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 17924305afa2..a4eab1e1e590 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -2,6 +2,7 @@
 /* Copyright 2017-2019 NXP */
 
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include "enetc.h"
 
 #define ENETC_DRV_NAME_STR "ENETC VF driver"
@@ -103,6 +104,29 @@ static const struct net_device_ops enetc_ndev_ops = {
 	.ndo_setup_tc		= enetc_setup_tc,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(enetc_vf_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(enetc_vf_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(enetc_vf_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 				  const struct net_device_ops *ndev_ops)
 {
@@ -120,16 +144,12 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	ndev->watchdog_timeo = 5 * HZ;
 	ndev->max_mtu = ENETC_MAX_MTU;
 
-	ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
-			    NETIF_F_HW_VLAN_CTAG_TX |
-			    NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
-	ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
-			 NETIF_F_HW_VLAN_CTAG_TX |
-			 NETIF_F_HW_VLAN_CTAG_RX |
-			 NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
-	ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
-			      NETIF_F_TSO | NETIF_F_TSO6;
+	netdev_hw_features_zero(ndev);
+	netdev_hw_features_set_array(ndev, &enetc_vf_hw_feature_set);
+	netdev_active_features_zero(ndev);
+	netdev_active_features_set_array(ndev, &enetc_vf_feature_set);
+	netdev_vlan_features_zero(ndev);
+	netdev_vlan_features_set_array(ndev, &enetc_vf_vlan_feature_set);
 
 	if (si->num_rss)
 		ndev->hw_features |= NETIF_F_RXHASH;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index e8e2aa1e7f01..49850ee91d4e 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -33,6 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
@@ -3465,6 +3466,13 @@ static const unsigned short offset_des_active_txq[] = {
 	FEC_X_DES_ACTIVE_0, FEC_X_DES_ACTIVE_1, FEC_X_DES_ACTIVE_2
 };
 
+static DECLARE_NETDEV_FEATURE_SET(fec_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT);
+
  /*
   * XXX:  We need to clean up on failure exits here.
   *
@@ -3569,8 +3577,7 @@ static int fec_enet_init(struct net_device *ndev)
 		netif_set_tso_max_segs(ndev, FEC_MAX_TSO_SEGS);
 
 		/* enable hw accelerator */
-		ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
-				| NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO);
+		netdev_active_features_set_array(ndev, &fec_feature_set);
 		fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
 	}
 
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index e7bf1524b68e..72a1842794a7 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -67,6 +67,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/if_vlan.h>
@@ -3191,6 +3192,16 @@ static const struct net_device_ops gfar_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(gfar_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(gfar_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 /* Set up the ethernet device structure, private data,
  * and anything else we need before we start
  */
@@ -3239,10 +3250,9 @@ static int gfar_probe(struct platform_device *ofdev)
 	}
 
 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
-		dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
-				   NETIF_F_RXCSUM;
-		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG |
-				 NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
+		netdev_hw_features_zero(dev);
+		netdev_hw_features_set_array(dev, &gfar_hw_feature_set);
+		netdev_active_features_set_array(dev, &gfar_feature_set);
 	}
 
 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_main.c b/drivers/net/ethernet/fungible/funeth/funeth_main.c
index f247b7ad3a88..537daf19f7f6 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -9,6 +9,7 @@
 #include <linux/if_vlan.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/rtnetlink.h>
 #include <linux/inetdevice.h>
@@ -1354,14 +1355,6 @@ static const struct net_device_ops fun_netdev_ops = {
 	.ndo_get_devlink_port	= fun_get_devlink_port,
 };
 
-#define GSO_ENCAP_FLAGS (NETIF_F_GSO_GRE | NETIF_F_GSO_IPXIP4 | \
-			 NETIF_F_GSO_IPXIP6 | NETIF_F_GSO_UDP_TUNNEL | \
-			 NETIF_F_GSO_UDP_TUNNEL_CSUM)
-#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | \
-		   NETIF_F_GSO_UDP_L4)
-#define VLAN_FEAT (NETIF_F_SG | NETIF_F_HW_CSUM | TSO_FLAGS | \
-		   GSO_ENCAP_FLAGS | NETIF_F_HIGHDMA)
-
 static void fun_dflt_rss_indir(struct funeth_priv *fp, unsigned int nrx)
 {
 	unsigned int i;
@@ -1708,9 +1701,35 @@ int fun_change_num_queues(struct net_device *dev, unsigned int ntx,
 	return err;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(fun_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(fun_gso_encap_feature_set,
+				  NETIF_F_GSO_GRE_BIT,
+				  NETIF_F_GSO_IPXIP4_BIT,
+				  NETIF_F_GSO_IPXIP6_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(fun_tso_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(fun_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 {
+	netdev_features_t gso_encap_flags = netdev_empty_features;
+	netdev_features_t tso_flags = netdev_empty_features;
 	struct fun_dev *fdev = &ed->fdev;
+	netdev_features_t vlan_feat;
 	struct net_device *netdev;
 	struct funeth_priv *fp;
 	unsigned int ntx, nrx;
@@ -1763,14 +1782,19 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 	SET_NETDEV_DEV(netdev, fdev->dev);
 	netdev->netdev_ops = &fun_netdev_ops;
 
-	netdev->hw_features = NETIF_F_SG | NETIF_F_RXHASH | NETIF_F_RXCSUM;
+	netdev_features_set_array(&fun_gso_encap_feature_set, &gso_encap_flags);
+	netdev_features_set_array(&fun_tso_feature_set, &tso_flags);
+	vlan_feat = gso_encap_flags | tso_flags;
+	netdev_features_set_array(&fun_vlan_feature_set, &vlan_feat);
+
+	netdev_hw_features_set_array(netdev, &fun_hw_feature_set);
 	if (fp->port_caps & FUN_PORT_CAP_OFFLOADS)
-		netdev->hw_features |= NETIF_F_HW_CSUM | TSO_FLAGS;
+		netdev->hw_features |= NETIF_F_HW_CSUM | tso_flags;
 	if (fp->port_caps & FUN_PORT_CAP_ENCAP_OFFLOADS)
-		netdev->hw_features |= GSO_ENCAP_FLAGS;
+		netdev->hw_features |= gso_encap_flags;
 
 	netdev->features |= netdev->hw_features | NETIF_F_HIGHDMA;
-	netdev->vlan_features = netdev->features & VLAN_FEAT;
+	netdev->vlan_features = netdev->features & vlan_feat;
 	netdev->mpls_features = netdev->vlan_features;
 	netdev->hw_enc_features = netdev->hw_features;
 
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index 6cafee55efc3..357e2d9cd740 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -8,6 +8,7 @@
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
@@ -1528,6 +1529,16 @@ static void gve_write_version(u8 __iomem *driver_version_register)
 	writeb('\n', driver_version_register);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(gve_hw_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXHASH_BIT);
+
 static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int max_tx_queues, max_rx_queues;
@@ -1588,14 +1599,8 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 * Features might be set in other locations as well (such as
 	 * `gve_adminq_describe_device`).
 	 */
-	dev->hw_features = NETIF_F_HIGHDMA;
-	dev->hw_features |= NETIF_F_SG;
-	dev->hw_features |= NETIF_F_HW_CSUM;
-	dev->hw_features |= NETIF_F_TSO;
-	dev->hw_features |= NETIF_F_TSO6;
-	dev->hw_features |= NETIF_F_TSO_ECN;
-	dev->hw_features |= NETIF_F_RXCSUM;
-	dev->hw_features |= NETIF_F_RXHASH;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &gve_hw_feature_set);
 	dev->features = dev->hw_features;
 	dev->watchdog_timeo = 5 * HZ;
 	dev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index d94cc8c6681f..c7556817e6a4 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -13,6 +13,7 @@
 #include <linux/ipv6.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
 #include <linux/skbuff.h>
@@ -1791,6 +1792,11 @@ static int hns_nic_set_features(struct net_device *netdev,
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(hns_v1_off_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+
 static netdev_features_t hns_nic_fix_features(
 		struct net_device *netdev, netdev_features_t features)
 {
@@ -1798,8 +1804,7 @@ static netdev_features_t hns_nic_fix_features(
 
 	switch (priv->enet_ver) {
 	case AE_VERSION_1:
-		features &= ~(NETIF_F_TSO | NETIF_F_TSO6 |
-				NETIF_F_HW_VLAN_CTAG_FILTER);
+		netdev_features_clear_array(&hns_v1_off_feature_set, &features);
 		break;
 	default:
 		break;
@@ -2240,6 +2245,34 @@ static int hns_nic_notifier_action(struct notifier_block *nb,
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(hns_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_GRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(hns_vlan_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_GRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(hns_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_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);
+static DECLARE_NETDEV_FEATURE_SET(hns_v2_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_NTUPLE_BIT);
+
 static int hns_nic_dev_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -2323,21 +2356,15 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
 	ndev->netdev_ops = &hns_nic_netdev_ops;
 	hns_ethtool_set_ops(ndev);
 
-	ndev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
-		NETIF_F_GRO;
-	ndev->vlan_features |=
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
-	ndev->vlan_features |= NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO;
+	netdev_active_features_set_array(ndev, &hns_feature_set);
+	netdev_vlan_features_set_array(ndev, &hns_vlan_feature_set);
 
 	/* MTU range: 68 - 9578 (v1) or 9706 (v2) */
 	ndev->min_mtu = MAC_MIN_MTU;
 	switch (priv->enet_ver) {
 	case AE_VERSION_2:
-		ndev->features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_NTUPLE;
-		ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
-			NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6;
+		netdev_active_features_set_array(ndev, &hns_v2_feature_set);
+		netdev_hw_features_set_array(ndev, &hns_hw_feature_set);
 		ndev->vlan_features |= NETIF_F_TSO | NETIF_F_TSO6;
 		ndev->max_mtu = MAC_MAX_MTU_V2 -
 				(ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 35d70041b9e8..df3f46d7f217 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,42 @@ static struct pci_driver hns3_driver = {
 	.err_handler    = &hns3_err_handler,
 };
 
+static 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_BIT);
+static 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->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_active_features_set_array(netdev, &hns3_default_feature_set);
 
 	if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
 		netdev->features |= NETIF_F_GRO_HW;
@@ -3296,10 +3316,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/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index c23ee2ddbce3..b8db3b423a5b 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -13,6 +13,7 @@
 #include <linux/types.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/slab.h>
 #include <linux/if_vlan.h>
 #include <linux/semaphore.h>
@@ -916,21 +917,41 @@ static const struct net_device_ops hinicvf_netdev_ops = {
 	.ndo_set_features = hinic_set_features,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(hinic_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(hinic_hw_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+
 static void netdev_features_init(struct net_device *netdev)
 {
-	netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM |
-			      NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
-			      NETIF_F_RXCSUM | NETIF_F_LRO |
-			      NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
-			      NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &hinic_hw_feature_set);
 
 	netdev->vlan_features = netdev->hw_features;
 
 	netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
 
-	netdev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SCTP_CRC |
-				  NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN |
-				  NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_UDP_TUNNEL;
+	netdev_hw_enc_features_zero(netdev);
+	netdev_hw_enc_features_set_array(netdev, &hinic_hw_enc_feature_set);
 }
 
 static void hinic_refresh_nic_cfg(struct hinic_dev *nic_dev)
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index 5dc302880f5f..cc520574a710 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -2936,6 +2936,26 @@ static const struct net_device_ops ehea_netdev_ops = {
 	.ndo_tx_timeout		= ehea_tx_watchdog,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(ehea_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ehea_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ehea_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_IP_CSUM_BIT);
+
 static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 					 u32 logical_port_id,
 					 struct device_node *dn)
@@ -2993,14 +3013,12 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 	dev->netdev_ops = &ehea_netdev_ops;
 	ehea_set_ethtool_ops(dev);
 
-	dev->hw_features = NETIF_F_SG | NETIF_F_TSO |
-		      NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_CTAG_TX;
-	dev->features = NETIF_F_SG | NETIF_F_TSO |
-		      NETIF_F_HIGHDMA | NETIF_F_IP_CSUM |
-		      NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
-		      NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM;
-	dev->vlan_features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_HIGHDMA |
-			NETIF_F_IP_CSUM;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &ehea_hw_feature_set);
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_array(dev, &ehea_feature_set);
+	netdev_vlan_features_zero(dev);
+	netdev_vlan_features_set_array(dev, &ehea_vlan_feature_set);
 	dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
 	/* MTU range: 68 - 9022 */
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index fbea9f7efe8c..6b026ba0f262 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -3032,6 +3032,10 @@ static const struct net_device_ops emac_gige_netdev_ops = {
 	.ndo_change_mtu		= emac_change_mtu,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(emac_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT);
+
 static int emac_probe(struct platform_device *ofdev)
 {
 	struct net_device *ndev;
@@ -3171,7 +3175,8 @@ static int emac_probe(struct platform_device *ofdev)
 		goto err_detach_tah;
 
 	if (dev->tah_dev) {
-		ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG;
+		netdev_hw_features_zero(ndev);
+		netdev_hw_features_set_array(ndev, &emac_hw_feature_set);
 		ndev->features |= ndev->hw_features | NETIF_F_RXCSUM;
 	}
 	ndev->watchdog_timeo = 5 * HZ;
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 5c6a04d29f5b..b45b7ff892ef 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1623,6 +1623,11 @@ static const struct net_device_ops ibmveth_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(ibmveth_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 {
 	int rc, i, mac_len;
@@ -1681,10 +1686,8 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 	netdev->ethtool_ops = &netdev_ethtool_ops;
 	SET_NETDEV_DEV(netdev, &dev->dev);
 	netdev->hw_features = NETIF_F_SG;
-	if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL) {
-		netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-				       NETIF_F_RXCSUM;
-	}
+	if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL)
+		netdev_hw_features_set_array(netdev, &ibmveth_hw_feature_set);
 
 	netdev->features |= netdev->hw_features;
 
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 5ab7c0f81e9a..c0ae18a2b601 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4831,6 +4831,11 @@ static void send_query_ip_offload(struct ibmvnic_adapter *adapter)
 	ibmvnic_send_crq(adapter, &crq);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ibmvnic_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_GRO_BIT);
+
 static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 {
 	struct ibmvnic_control_ip_offload_buffer *ctrl_buf = &adapter->ip_offload_ctrl;
@@ -4870,7 +4875,8 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 		adapter->netdev->hw_features = 0;
 	}
 
-	adapter->netdev->hw_features = NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO;
+	netdev_hw_features_zero(adapter->netdev);
+	netdev_hw_features_set_array(adapter->netdev, &ibmvnic_hw_feature_set);
 
 	if (buf->tcp_ipv4_chksum || buf->udp_ipv4_chksum)
 		adapter->netdev->hw_features |= NETIF_F_IP_CSUM;
diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h
index 4817eb13ca6f..86bc74be959f 100644
--- a/drivers/net/ethernet/intel/e1000/e1000.h
+++ b/drivers/net/ethernet/intel/e1000/e1000.h
@@ -16,6 +16,7 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 23299fc56199..07670cabf19f 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -907,6 +907,22 @@ static int e1000_init_hw_struct(struct e1000_adapter *adapter,
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(e1000_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(e1000_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+static DECLARE_NETDEV_FEATURE_SET(e1000_hw_rx_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXALL_BIT,
+				  NETIF_F_RXFCS_BIT);
+static DECLARE_NETDEV_FEATURE_SET(e1000_vlan_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT);
+
 /**
  * e1000_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -1035,11 +1051,10 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 
 	if (hw->mac_type >= e1000_82543) {
-		netdev->hw_features = NETIF_F_SG |
-				   NETIF_F_HW_CSUM |
-				   NETIF_F_HW_VLAN_CTAG_RX;
-		netdev->features = NETIF_F_HW_VLAN_CTAG_TX |
-				   NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_hw_features_zero(netdev);
+		netdev_hw_features_set_array(netdev, &e1000_hw_feature_set);
+		netdev_active_features_zero(netdev);
+		netdev_active_features_set_array(netdev, &e1000_feature_set);
 	}
 
 	if ((hw->mac_type >= e1000_82544) &&
@@ -1049,18 +1064,14 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 
 	netdev->features |= netdev->hw_features;
-	netdev->hw_features |= (NETIF_F_RXCSUM |
-				NETIF_F_RXALL |
-				NETIF_F_RXFCS);
+	netdev_hw_features_set_array(netdev, &e1000_hw_rx_feature_set);
 
 	if (pci_using_dac) {
 		netdev->features |= NETIF_F_HIGHDMA;
 		netdev->vlan_features |= NETIF_F_HIGHDMA;
 	}
 
-	netdev->vlan_features |= (NETIF_F_TSO |
-				  NETIF_F_HW_CSUM |
-				  NETIF_F_SG);
+	netdev_vlan_features_set_array(netdev, &e1000_vlan_feature_set);
 
 	/* Do not set IFF_UNICAST_FLT for VMWare's 82545EM */
 	if (hw->device_id != E1000_DEV_ID_82545EM_COPPER ||
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 321f2a95ae3a..60b4c6ee5bd8 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -11,6 +11,7 @@
 #include <linux/pagemap.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/interrupt.h>
 #include <linux/tcp.h>
 #include <linux/ipv6.h>
@@ -7311,18 +7312,27 @@ static netdev_features_t e1000_fix_features(struct net_device *netdev,
 	return features;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(e1000_changable_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXFCS_BIT,
+				  NETIF_F_RXALL_BIT);
+
 static int e1000_set_features(struct net_device *netdev,
 			      netdev_features_t features)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changeable;
 
 	if (changed & (NETIF_F_TSO | NETIF_F_TSO6))
 		adapter->flags |= FLAG_TSO_FORCE;
 
-	if (!(changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX |
-			 NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_RXFCS |
-			 NETIF_F_RXALL)))
+	netdev_features_zero(&changeable);
+	netdev_features_set_array(&e1000_changable_feature_set, &changeable);
+	if (!(changed & changeable))
 		return 0;
 
 	if (changed & NETIF_F_RXFCS) {
@@ -7371,6 +7381,21 @@ static const struct net_device_ops e1000e_netdev_ops = {
 	.ndo_features_check	= passthru_features_check,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(e1000_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(e1000_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+
 /**
  * e1000_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -7523,14 +7548,8 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			 "PHY reset is blocked due to SOL/IDER session.\n");
 
 	/* Set initial default active device features */
-	netdev->features = (NETIF_F_SG |
-			    NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_VLAN_CTAG_TX |
-			    NETIF_F_TSO |
-			    NETIF_F_TSO6 |
-			    NETIF_F_RXHASH |
-			    NETIF_F_RXCSUM |
-			    NETIF_F_HW_CSUM);
+	netdev_active_features_zero(netdev);
+	netdev_active_features_set_array(netdev, &e1000_feature_set);
 
 	/* Set user-changeable features (subset of all device features) */
 	netdev->hw_features = netdev->features;
@@ -7541,10 +7560,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
 		netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
-	netdev->vlan_features |= (NETIF_F_SG |
-				  NETIF_F_TSO |
-				  NETIF_F_TSO6 |
-				  NETIF_F_HW_CSUM);
+	netdev_vlan_features_set_array(netdev, &e1000_vlan_feature_set);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 2cca9e84e31e..a42148582779 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -5,6 +5,7 @@
 #include <linux/vmalloc.h>
 #include <net/udp_tunnel.h>
 #include <linux/if_macvlan.h>
+#include <linux/netdev_features_helper.h>
 
 /**
  * fm10k_setup_tx_resources - allocate Tx resources (Descriptors)
@@ -1536,6 +1537,24 @@ static const struct net_device_ops fm10k_netdev_ops = {
 	.ndo_features_check	= fm10k_features_check,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(fm10k_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(fm10k_hw_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT);
+
 #define DEFAULT_DEBUG_LEVEL_SHIFT 3
 
 struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
@@ -1557,24 +1576,12 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
 	interface->msg_enable = BIT(DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
 
 	/* configure default features */
-	dev->features |= NETIF_F_IP_CSUM |
-			 NETIF_F_IPV6_CSUM |
-			 NETIF_F_SG |
-			 NETIF_F_TSO |
-			 NETIF_F_TSO6 |
-			 NETIF_F_TSO_ECN |
-			 NETIF_F_RXHASH |
-			 NETIF_F_RXCSUM;
+	netdev_active_features_set_array(dev, &fm10k_feature_set);
 
 	/* Only the PF can support VXLAN and NVGRE tunnel offloads */
 	if (info->mac == fm10k_mac_pf) {
-		dev->hw_enc_features = NETIF_F_IP_CSUM |
-				       NETIF_F_TSO |
-				       NETIF_F_TSO6 |
-				       NETIF_F_TSO_ECN |
-				       NETIF_F_GSO_UDP_TUNNEL |
-				       NETIF_F_IPV6_CSUM |
-				       NETIF_F_SG;
+		netdev_hw_enc_features_zero(dev);
+		netdev_hw_enc_features_set_array(dev, &fm10k_hw_enc_feature_set);
 
 		dev->features |= NETIF_F_GSO_UDP_TUNNEL;
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index b36bf9c3e1e4..69ac22c7e800 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -7,6 +7,7 @@
 #include <linux/bpf.h>
 #include <generated/utsrelease.h>
 #include <linux/crash_dump.h>
+#include <linux/netdev_features_helper.h>
 
 /* Local includes */
 #include "i40e.h"
@@ -13616,6 +13617,37 @@ static const struct net_device_ops i40e_netdev_ops = {
 	.ndo_dfwd_del_station	= i40e_fwd_del,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(i40e_hw_enc_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GSO_GRE_BIT,
+				  NETIF_F_GSO_GRE_CSUM_BIT,
+				  NETIF_F_GSO_PARTIAL_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_UDP_L4_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(i40e_gso_partial_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);
+static DECLARE_NETDEV_FEATURE_SET(i40e_mpls_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 /**
  * i40e_config_netdev - Setup the netdev flags
  * @vsi: the VSI being configured
@@ -13631,6 +13663,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	u8 broadcast[ETH_ALEN];
 	u8 mac_addr[ETH_ALEN];
 	int etherdev_size;
+	netdev_features_t gso_partial_features;
 	netdev_features_t hw_enc_features;
 	netdev_features_t hw_features;
 
@@ -13643,25 +13676,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	np = netdev_priv(netdev);
 	np->vsi = vsi;
 
-	hw_enc_features = NETIF_F_SG			|
-			  NETIF_F_HW_CSUM		|
-			  NETIF_F_HIGHDMA		|
-			  NETIF_F_SOFT_FEATURES		|
-			  NETIF_F_TSO			|
-			  NETIF_F_TSO_ECN		|
-			  NETIF_F_TSO6			|
-			  NETIF_F_GSO_GRE		|
-			  NETIF_F_GSO_GRE_CSUM		|
-			  NETIF_F_GSO_PARTIAL		|
-			  NETIF_F_GSO_IPXIP4		|
-			  NETIF_F_GSO_IPXIP6		|
-			  NETIF_F_GSO_UDP_TUNNEL	|
-			  NETIF_F_GSO_UDP_TUNNEL_CSUM	|
-			  NETIF_F_GSO_UDP_L4		|
-			  NETIF_F_SCTP_CRC		|
-			  NETIF_F_RXHASH		|
-			  NETIF_F_RXCSUM		|
-			  0;
+	hw_enc_features = NETIF_F_SOFT_FEATURES;
+	netdev_features_set_array(&i40e_hw_enc_feature_set, &hw_enc_features);
 
 	if (!(pf->hw_features & I40E_HW_OUTER_UDP_CSUM_CAPABLE))
 		netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
@@ -13675,22 +13691,15 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	/* record features VLANs can make use of */
 	netdev->vlan_features |= hw_enc_features | NETIF_F_TSO_MANGLEID;
 
-#define I40E_GSO_PARTIAL_FEATURES (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)
-
-	netdev->gso_partial_features = I40E_GSO_PARTIAL_FEATURES;
+	netdev_features_zero(&gso_partial_features);
+	netdev_features_set_array(&i40e_gso_partial_feature_set,
+				  &gso_partial_features);
+	netdev->gso_partial_features = gso_partial_features;
 	netdev->features |= NETIF_F_GSO_PARTIAL |
-			    I40E_GSO_PARTIAL_FEATURES;
+			    gso_partial_features;
 
-	netdev->mpls_features |= NETIF_F_SG;
-	netdev->mpls_features |= NETIF_F_HW_CSUM;
-	netdev->mpls_features |= NETIF_F_TSO;
-	netdev->mpls_features |= NETIF_F_TSO6;
-	netdev->mpls_features |= I40E_GSO_PARTIAL_FEATURES;
+	netdev_mpls_features_set_array(netdev, &i40e_mpls_feature_set);
+	netdev->mpls_features |= gso_partial_features;
 
 	/* enable macvlan offloads */
 	netdev->hw_features |= NETIF_F_HW_L2FW_DOFFLOAD;
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
index 3f6187c16424..5d033a16a95a 100644
--- a/drivers/net/ethernet/intel/iavf/iavf.h
+++ b/drivers/net/ethernet/intel/iavf/iavf.h
@@ -8,6 +8,7 @@
 #include <linux/pci.h>
 #include <linux/aer.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/ethtool.h>
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 45d097a164ad..55ab0229179f 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4585,6 +4585,26 @@ static int iavf_check_reset_complete(struct iavf_hw *hw)
 	return -EBUSY;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(iavf_hw_enc_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(iavf_gso_feature_set,
+				  NETIF_F_GSO_UDP_TUNNEL_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_CSUM_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT);
+
 /**
  * iavf_process_config - Process the config information we got from the PF
  * @adapter: board private structure
@@ -4600,31 +4620,14 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	netdev_features_t hw_enc_features;
 	netdev_features_t hw_features;
 
-	hw_enc_features = NETIF_F_SG			|
-			  NETIF_F_IP_CSUM		|
-			  NETIF_F_IPV6_CSUM		|
-			  NETIF_F_HIGHDMA		|
-			  NETIF_F_SOFT_FEATURES	|
-			  NETIF_F_TSO			|
-			  NETIF_F_TSO_ECN		|
-			  NETIF_F_TSO6			|
-			  NETIF_F_SCTP_CRC		|
-			  NETIF_F_RXHASH		|
-			  NETIF_F_RXCSUM		|
-			  0;
+	hw_enc_features = NETIF_F_SOFT_FEATURES;
+	netdev_features_set_array(&iavf_hw_enc_feature_set, &hw_enc_features);
 
 	/* advertise to stack only if offloads for encapsulated packets is
 	 * supported
 	 */
 	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ENCAP) {
-		hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL	|
-				   NETIF_F_GSO_GRE		|
-				   NETIF_F_GSO_GRE_CSUM		|
-				   NETIF_F_GSO_IPXIP4		|
-				   NETIF_F_GSO_IPXIP6		|
-				   NETIF_F_GSO_UDP_TUNNEL_CSUM	|
-				   NETIF_F_GSO_PARTIAL		|
-				   0;
+		netdev_features_set_array(&iavf_gso_feature_set, &hw_enc_features);
 
 		if (!(vfres->vf_cap_flags &
 		      VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM))
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index cc5b85afd437..b61c849845ee 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/compiler.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index eb40526ee179..34a859ecae0d 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3293,6 +3293,36 @@ static void ice_set_ops(struct net_device *netdev)
 	ice_set_ethtool_ops(netdev);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ice_safe_mode_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ice_dflt_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_NTUPLE_BIT,
+				  NETIF_F_RXHASH_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ice_csumo_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_IPV6_CSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ice_tso_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GSO_GRE_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_GRE_CSUM_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT,
+				  NETIF_F_GSO_IPXIP4_BIT,
+				  NETIF_F_GSO_IPXIP6_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ice_mpls_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 /**
  * ice_set_netdev_features - set features for the given netdev
  * @netdev: netdev instance
@@ -3308,20 +3338,18 @@ static void ice_set_netdev_features(struct net_device *netdev)
 
 	if (ice_is_safe_mode(pf)) {
 		/* safe mode */
-		netdev->features = NETIF_F_SG | NETIF_F_HIGHDMA;
+		netdev_active_features_zero(netdev);
+		netdev_active_features_set_array(netdev,
+						 &ice_safe_mode_feature_set);
 		netdev->hw_features = netdev->features;
 		return;
 	}
 
-	dflt_features = NETIF_F_SG	|
-			NETIF_F_HIGHDMA	|
-			NETIF_F_NTUPLE	|
-			NETIF_F_RXHASH;
+	netdev_features_zero(&dflt_features);
+	netdev_features_set_array(&ice_dflt_feature_set, &dflt_features);
 
-	csumo_features = NETIF_F_RXCSUM	  |
-			 NETIF_F_IP_CSUM  |
-			 NETIF_F_SCTP_CRC |
-			 NETIF_F_IPV6_CSUM;
+	netdev_features_zero(&csumo_features);
+	netdev_features_set_array(&ice_csumo_feature_set, &csumo_features);
 
 	vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER |
 			 NETIF_F_HW_VLAN_CTAG_TX     |
@@ -3331,17 +3359,8 @@ static void ice_set_netdev_features(struct net_device *netdev)
 	if (is_dvm_ena)
 		vlano_features |= NETIF_F_HW_VLAN_STAG_FILTER;
 
-	tso_features = NETIF_F_TSO			|
-		       NETIF_F_TSO_ECN			|
-		       NETIF_F_TSO6			|
-		       NETIF_F_GSO_GRE			|
-		       NETIF_F_GSO_UDP_TUNNEL		|
-		       NETIF_F_GSO_GRE_CSUM		|
-		       NETIF_F_GSO_UDP_TUNNEL_CSUM	|
-		       NETIF_F_GSO_PARTIAL		|
-		       NETIF_F_GSO_IPXIP4		|
-		       NETIF_F_GSO_IPXIP6		|
-		       NETIF_F_GSO_UDP_L4;
+	netdev_features_zero(&tso_features);
+	netdev_features_set_array(&ice_tso_feature_set, &tso_features);
 
 	netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM |
 					NETIF_F_GSO_GRE_CSUM;
@@ -3350,9 +3369,8 @@ static void ice_set_netdev_features(struct net_device *netdev)
 			      vlano_features | tso_features;
 
 	/* add support for HW_CSUM on packets with MPLS header */
-	netdev->mpls_features =  NETIF_F_HW_CSUM |
-				 NETIF_F_TSO     |
-				 NETIF_F_TSO6;
+	netdev_mpls_features_zero(netdev);
+	netdev_mpls_features_set_array(netdev, &ice_mpls_feature_set);
 
 	/* enable features */
 	netdev->features |= netdev->hw_features;
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index d8b836a85cc3..2fd8d8c94305 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -10,6 +10,7 @@
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/ipv6.h>
 #include <linux/slab.h>
 #include <net/checksum.h>
@@ -2500,6 +2501,20 @@ static int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 	return ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, flags);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(igb_l2_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(igb_l3_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 #define IGB_MAX_MAC_HDR_LEN	127
 #define IGB_MAX_NETWORK_HDR_LEN	511
 
@@ -2511,21 +2526,18 @@ igb_features_check(struct sk_buff *skb, struct net_device *dev,
 
 	/* Make certain the headers can be described by a context descriptor */
 	mac_hdr_len = skb_network_header(skb) - skb->data;
-	if (unlikely(mac_hdr_len > IGB_MAX_MAC_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_GSO_UDP_L4 |
-				    NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(mac_hdr_len > IGB_MAX_MAC_HDR_LEN)) {
+		netdev_features_clear_array(&igb_l2_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
-	if (unlikely(network_hdr_len >  IGB_MAX_NETWORK_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_GSO_UDP_L4 |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(network_hdr_len >  IGB_MAX_NETWORK_HDR_LEN)) {
+		netdev_features_clear_array(&igb_l3_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	/* We can only support IPV4 TSO in tunnels if we can mangle the
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
@@ -3144,6 +3156,21 @@ static s32 igb_init_i2c(struct igb_adapter *adapter)
 	return status;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(igb_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(igb_gso_partial_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);
+
 /**
  *  igb_probe - Device Initialization Routine
  *  @pdev: PCI device information struct
@@ -3164,6 +3191,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	s32 ret_val;
 	static int global_quad_port_a; /* global quad port a indication */
 	const struct e1000_info *ei = igb_info_tbl[ent->driver_data];
+	netdev_features_t gso_partial_features;
 	u8 part_str[E1000_PBANUM_LENGTH];
 	int err;
 
@@ -3268,12 +3296,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 * set by igb_sw_init so we should use an or instead of an
 	 * assignment.
 	 */
-	netdev->features |= NETIF_F_SG |
-			    NETIF_F_TSO |
-			    NETIF_F_TSO6 |
-			    NETIF_F_RXHASH |
-			    NETIF_F_RXCSUM |
-			    NETIF_F_HW_CSUM;
+	netdev_active_features_set_array(netdev, &igb_feature_set);
 
 	if (hw->mac.type >= e1000_82576)
 		netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_GSO_UDP_L4;
@@ -3281,15 +3304,10 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (hw->mac.type >= e1000_i350)
 		netdev->features |= NETIF_F_HW_TC;
 
-#define IGB_GSO_PARTIAL_FEATURES (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)
-
-	netdev->gso_partial_features = IGB_GSO_PARTIAL_FEATURES;
-	netdev->features |= NETIF_F_GSO_PARTIAL | IGB_GSO_PARTIAL_FEATURES;
+	netdev_features_zero(&gso_partial_features);
+	netdev_features_set_array(&igb_feature_set, &gso_partial_features);
+	netdev->gso_partial_features = gso_partial_features;
+	netdev->features |= NETIF_F_GSO_PARTIAL | gso_partial_features;
 
 	/* copy netdev features into list of user selectable features */
 	netdev->hw_features |= netdev->features |
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index f4e91db89fe5..362e26df28b0 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -11,6 +11,7 @@
 #include <linux/pagemap.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/tcp.h>
 #include <linux/ipv6.h>
 #include <linux/slab.h>
@@ -2615,6 +2616,18 @@ static int igbvf_set_features(struct net_device *netdev,
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(igbvf_l2_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(igbvf_l3_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 #define IGBVF_MAX_MAC_HDR_LEN		127
 #define IGBVF_MAX_NETWORK_HDR_LEN	511
 
@@ -2626,19 +2639,18 @@ igbvf_features_check(struct sk_buff *skb, struct net_device *dev,
 
 	/* Make certain the headers can be described by a context descriptor */
 	mac_hdr_len = skb_network_header(skb) - skb->data;
-	if (unlikely(mac_hdr_len > IGBVF_MAX_MAC_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(mac_hdr_len > IGBVF_MAX_MAC_HDR_LEN)) {
+		netdev_features_clear_array(&igbvf_l2_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
-	if (unlikely(network_hdr_len >  IGBVF_MAX_NETWORK_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(network_hdr_len >  IGBVF_MAX_NETWORK_HDR_LEN)) {
+		netdev_features_clear_array(&igbvf_l3_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	/* We can only support IPV4 TSO in tunnels if we can mangle the
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
@@ -2667,6 +2679,21 @@ static const struct net_device_ops igbvf_netdev_ops = {
 	.ndo_features_check	= igbvf_features_check,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(igbvf_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT);
+static DECLARE_NETDEV_FEATURE_SET(igbvf_gso_partial_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);
+
 /**
  * igbvf_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -2684,6 +2711,7 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct igbvf_adapter *adapter;
 	struct e1000_hw *hw;
 	const struct igbvf_info *ei = igbvf_info_tbl[ent->driver_data];
+	netdev_features_t gso_partial_features;
 	static int cards_found;
 	int err;
 
@@ -2758,23 +2786,15 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	adapter->bd_number = cards_found++;
 
-	netdev->hw_features = NETIF_F_SG |
-			      NETIF_F_TSO |
-			      NETIF_F_TSO6 |
-			      NETIF_F_RXCSUM |
-			      NETIF_F_HW_CSUM |
-			      NETIF_F_SCTP_CRC;
-
-#define IGBVF_GSO_PARTIAL_FEATURES (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)
-
-	netdev->gso_partial_features = IGBVF_GSO_PARTIAL_FEATURES;
-	netdev->hw_features |= NETIF_F_GSO_PARTIAL |
-			       IGBVF_GSO_PARTIAL_FEATURES;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &igbvf_hw_feature_set);
+
+	netdev_features_zero(&gso_partial_features);
+	netdev_features_set_array(&igbvf_gso_partial_feature_set,
+				  &gso_partial_features);
+
+	netdev->gso_partial_features = gso_partial_features;
+	netdev->hw_features |= NETIF_F_GSO_PARTIAL | gso_partial_features;
 
 	netdev->features = netdev->hw_features | NETIF_F_HIGHDMA;
 
diff --git a/drivers/net/ethernet/intel/igc/igc_mac.c b/drivers/net/ethernet/intel/igc/igc_mac.c
index a5c4b19d71a2..79e65b35ab3d 100644
--- a/drivers/net/ethernet/intel/igc/igc_mac.c
+++ b/drivers/net/ethernet/intel/igc/igc_mac.c
@@ -3,6 +3,7 @@
 
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/netdev_features_helper.h>
 
 #include "igc_mac.h"
 #include "igc_hw.h"
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index ebff0e04045d..e5b97822e191 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -9,6 +9,7 @@
 #include <linux/udp.h>
 #include <linux/ip.h>
 #include <linux/pm_runtime.h>
+#include <linux/netdev_features_helper.h>
 #include <net/pkt_sched.h>
 #include <linux/bpf_trace.h>
 #include <net/xdp_sock_drv.h>
@@ -4973,6 +4974,18 @@ static int igc_set_features(struct net_device *netdev,
 	return 1;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(igc_l2_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(igc_l3_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static netdev_features_t
 igc_features_check(struct sk_buff *skb, struct net_device *dev,
 		   netdev_features_t features)
@@ -4981,19 +4994,18 @@ igc_features_check(struct sk_buff *skb, struct net_device *dev,
 
 	/* Make certain the headers can be described by a context descriptor */
 	mac_hdr_len = skb_network_header(skb) - skb->data;
-	if (unlikely(mac_hdr_len > IGC_MAX_MAC_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(mac_hdr_len > IGC_MAX_MAC_HDR_LEN)) {
+		netdev_features_clear_array(&igc_l2_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
-	if (unlikely(network_hdr_len >  IGC_MAX_NETWORK_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(network_hdr_len >  IGC_MAX_NETWORK_HDR_LEN)) {
+		netdev_features_clear_array(&igc_l3_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	/* We can only support IPv4 TSO in tunnels if we can mangle the
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
@@ -6201,6 +6213,23 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg)
 	return value;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(igc_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_HW_TC_BIT);
+static DECLARE_NETDEV_FEATURE_SET(igc_gso_partial_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);
+
 /**
  * igc_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -6219,6 +6248,7 @@ static int igc_probe(struct pci_dev *pdev,
 	struct net_device *netdev;
 	struct igc_hw *hw;
 	const struct igc_info *ei = igc_info_tbl[ent->driver_data];
+	netdev_features_t gso_partial_features;
 	int err;
 
 	err = pci_enable_device_mem(pdev);
@@ -6299,24 +6329,13 @@ static int igc_probe(struct pci_dev *pdev,
 		goto err_sw_init;
 
 	/* Add supported features to the features list*/
-	netdev->features |= NETIF_F_SG;
-	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
-	netdev->features |= NETIF_F_TSO_ECN;
-	netdev->features |= NETIF_F_RXCSUM;
-	netdev->features |= NETIF_F_HW_CSUM;
-	netdev->features |= NETIF_F_SCTP_CRC;
-	netdev->features |= NETIF_F_HW_TC;
-
-#define IGC_GSO_PARTIAL_FEATURES (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)
-
-	netdev->gso_partial_features = IGC_GSO_PARTIAL_FEATURES;
-	netdev->features |= NETIF_F_GSO_PARTIAL | IGC_GSO_PARTIAL_FEATURES;
+	netdev_active_features_set_array(netdev, &igc_feature_set);
+
+	netdev_features_zero(&gso_partial_features);
+	netdev_features_set_array(&igc_gso_partial_feature_set,
+				  &gso_partial_features);
+	netdev->gso_partial_features = gso_partial_features;
+	netdev->features |= NETIF_F_GSO_PARTIAL | gso_partial_features;
 
 	/* setup the private structure */
 	err = igc_sw_init(adapter);
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 45be9a1ab6af..c3ae375f04dd 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -3,6 +3,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/netdev_features_helper.h>
 #include <linux/prefetch.h>
 #include "ixgb.h"
 
@@ -343,6 +344,13 @@ static const struct net_device_ops ixgb_netdev_ops = {
 	.ndo_set_features       = ixgb_set_features,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(ixgb_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
 /**
  * ixgb_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -428,11 +436,8 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (err)
 		goto err_sw_init;
 
-	netdev->hw_features = NETIF_F_SG |
-			   NETIF_F_TSO |
-			   NETIF_F_HW_CSUM |
-			   NETIF_F_HW_VLAN_CTAG_TX |
-			   NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &ixgb_hw_feature_set);
 	netdev->features = netdev->hw_features |
 			   NETIF_F_HW_VLAN_CTAG_FILTER;
 	netdev->hw_features |= NETIF_F_RXCSUM;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index d1e430b8c8aa..98db7c46e89c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
 #include <linux/in.h>
@@ -10210,6 +10211,20 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
 	kfree(accel);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ixgbe_l2_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ixgbe_l3_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 #define IXGBE_MAX_MAC_HDR_LEN		127
 #define IXGBE_MAX_NETWORK_HDR_LEN	511
 
@@ -10221,21 +10236,18 @@ ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
 
 	/* Make certain the headers can be described by a context descriptor */
 	mac_hdr_len = skb_network_header(skb) - skb->data;
-	if (unlikely(mac_hdr_len > IXGBE_MAX_MAC_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_GSO_UDP_L4 |
-				    NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(mac_hdr_len > IXGBE_MAX_MAC_HDR_LEN)) {
+		netdev_features_clear_array(&ixgbe_l2_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
-	if (unlikely(network_hdr_len >  IXGBE_MAX_NETWORK_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_GSO_UDP_L4 |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(network_hdr_len >  IXGBE_MAX_NETWORK_HDR_LEN)) {
+		netdev_features_clear_array(&ixgbe_l3_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	/* We can only support IPV4 TSO in tunnels if we can mangle the
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
@@ -10755,6 +10767,47 @@ static void ixgbe_set_fw_version(struct ixgbe_adapter *adapter)
 		 "0x%08x", nvm_ver.etk_id);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ixgbe_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ixgbe_gso_partial_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);
+#ifdef CONFIG_IXGBE_IPSEC
+static DECLARE_NETDEV_FEATURE_SET(ixgbe_esp_feature_set,
+				  NETIF_F_HW_ESP_BIT,
+				  NETIF_F_HW_ESP_TX_CSUM_BIT,
+				  NETIF_F_GSO_ESP_BIT);
+#endif
+static DECLARE_NETDEV_FEATURE_SET(ixgbe_hw_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_RXALL_BIT,
+				  NETIF_F_HW_L2FW_DOFFLOAD_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ixgbe_mpls_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+#ifdef IXGBE_FCOE
+static DECLARE_NETDEV_FEATURE_SET(ixgbe_fcoe_feature_set,
+				  NETIF_F_FSO_BIT,
+				  NETIF_F_FCOE_CRC_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ixgbe_vlan_fcoe_feature_set,
+				  NETIF_F_FSO_BIT,
+				  NETIF_F_FCOE_CRC_BIT,
+				  NETIF_F_FCOE_MTU_BIT);
+#endif
+
 /**
  * ixgbe_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -10772,6 +10825,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct ixgbe_adapter *adapter = NULL;
 	struct ixgbe_hw *hw;
 	const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data];
+	netdev_features_t gso_partial_features;
 	unsigned int indices = MAX_TX_QUEUES;
 	u8 part_str[IXGBE_PBANUM_LENGTH];
 	int i, err, expected_gts;
@@ -10958,42 +11012,27 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 skip_sriov:
 
 #endif
-	netdev->features = NETIF_F_SG |
-			   NETIF_F_TSO |
-			   NETIF_F_TSO6 |
-			   NETIF_F_RXHASH |
-			   NETIF_F_RXCSUM |
-			   NETIF_F_HW_CSUM;
-
-#define IXGBE_GSO_PARTIAL_FEATURES (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)
-
-	netdev->gso_partial_features = IXGBE_GSO_PARTIAL_FEATURES;
+	netdev_active_features_zero(netdev);
+	netdev_active_features_set_array(netdev, &ixgbe_feature_set);
+
+	netdev_features_zero(&gso_partial_features);
+	netdev_features_set_array(&ixgbe_gso_partial_feature_set,
+				  &gso_partial_features);
+
+	netdev->gso_partial_features = gso_partial_features;
 	netdev->features |= NETIF_F_GSO_PARTIAL |
-			    IXGBE_GSO_PARTIAL_FEATURES;
+			    gso_partial_features;
 
 	if (hw->mac.type >= ixgbe_mac_82599EB)
 		netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_GSO_UDP_L4;
 
 #ifdef CONFIG_IXGBE_IPSEC
-#define IXGBE_ESP_FEATURES	(NETIF_F_HW_ESP | \
-				 NETIF_F_HW_ESP_TX_CSUM | \
-				 NETIF_F_GSO_ESP)
-
 	if (adapter->ipsec)
-		netdev->features |= IXGBE_ESP_FEATURES;
+		netdev_active_features_set_array(netdev, &ixgbe_esp_feature_set);
 #endif
 	/* copy netdev features into list of user selectable features */
-	netdev->hw_features |= netdev->features |
-			       NETIF_F_HW_VLAN_CTAG_FILTER |
-			       NETIF_F_HW_VLAN_CTAG_RX |
-			       NETIF_F_HW_VLAN_CTAG_TX |
-			       NETIF_F_RXALL |
-			       NETIF_F_HW_L2FW_DOFFLOAD;
+	netdev->hw_features |= netdev->features;
+	netdev_hw_features_set_array(netdev, &ixgbe_hw_feature_set);
 
 	if (hw->mac.type >= ixgbe_mac_82599EB)
 		netdev->hw_features |= NETIF_F_NTUPLE |
@@ -11003,11 +11042,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
 	netdev->hw_enc_features |= netdev->vlan_features;
-	netdev->mpls_features |= NETIF_F_SG |
-				 NETIF_F_TSO |
-				 NETIF_F_TSO6 |
-				 NETIF_F_HW_CSUM;
-	netdev->mpls_features |= IXGBE_GSO_PARTIAL_FEATURES;
+	netdev_mpls_features_set_array(netdev, &ixgbe_mpls_feature_set);
+	netdev->mpls_features |= gso_partial_features;
 
 	/* set this bit last since it cannot be part of vlan_features */
 	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
@@ -11040,12 +11076,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		fcoe_l = min_t(int, IXGBE_FCRETA_SIZE, num_online_cpus());
 		adapter->ring_feature[RING_F_FCOE].limit = fcoe_l;
 
-		netdev->features |= NETIF_F_FSO |
-				    NETIF_F_FCOE_CRC;
-
-		netdev->vlan_features |= NETIF_F_FSO |
-					 NETIF_F_FCOE_CRC |
-					 NETIF_F_FCOE_MTU;
+		netdev_active_features_set_array(netdev, &ixgbe_fcoe_feature_set);
+		netdev_vlan_features_set_array(netdev, &ixgbe_vlan_fcoe_feature_set);
 	}
 #endif /* IXGBE_FCOE */
 	if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)
diff --git a/drivers/net/ethernet/intel/ixgbevf/ipsec.c b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
index 9984ebc62d78..82341ac13e62 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
@@ -612,6 +612,11 @@ void ixgbevf_ipsec_rx(struct ixgbevf_ring *rx_ring,
 	adapter->rx_ipsec++;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ixgbevf_esp_feature_set,
+				  NETIF_F_HW_ESP_BIT,
+				  NETIF_F_HW_ESP_TX_CSUM_BIT,
+				  NETIF_F_GSO_ESP_BIT);
+
 /**
  * ixgbevf_init_ipsec_offload - initialize registers for IPsec operation
  * @adapter: board private structure
@@ -651,12 +656,10 @@ void ixgbevf_init_ipsec_offload(struct ixgbevf_adapter *adapter)
 
 	adapter->netdev->xfrmdev_ops = &ixgbevf_xfrmdev_ops;
 
-#define IXGBEVF_ESP_FEATURES	(NETIF_F_HW_ESP | \
-				 NETIF_F_HW_ESP_TX_CSUM | \
-				 NETIF_F_GSO_ESP)
-
-	adapter->netdev->features |= IXGBEVF_ESP_FEATURES;
-	adapter->netdev->hw_enc_features |= IXGBEVF_ESP_FEATURES;
+	netdev_active_features_set_array(adapter->netdev,
+					 &ixgbevf_esp_feature_set);
+	netdev_hw_enc_features_set_array(adapter->netdev,
+					 &ixgbevf_esp_feature_set);
 
 	return;
 
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 149c733fcc2b..29bad7b3f573 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -9,6 +9,7 @@
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_vlan.h>
 #include <linux/u64_stats_sync.h>
 #include <net/xdp.h>
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 2f12fbe229c1..095159721a96 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
 #include <linux/in.h>
@@ -4396,6 +4397,18 @@ static void ixgbevf_get_stats(struct net_device *netdev,
 	rcu_read_unlock();
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ixgbevf_l2_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ixgbevf_l3_disable_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 #define IXGBEVF_MAX_MAC_HDR_LEN		127
 #define IXGBEVF_MAX_NETWORK_HDR_LEN	511
 
@@ -4407,19 +4420,18 @@ ixgbevf_features_check(struct sk_buff *skb, struct net_device *dev,
 
 	/* Make certain the headers can be described by a context descriptor */
 	mac_hdr_len = skb_network_header(skb) - skb->data;
-	if (unlikely(mac_hdr_len > IXGBEVF_MAX_MAC_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(mac_hdr_len > IXGBEVF_MAX_MAC_HDR_LEN)) {
+		netdev_features_clear_array(&ixgbevf_l2_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
-	if (unlikely(network_hdr_len >  IXGBEVF_MAX_NETWORK_HDR_LEN))
-		return features & ~(NETIF_F_HW_CSUM |
-				    NETIF_F_SCTP_CRC |
-				    NETIF_F_TSO |
-				    NETIF_F_TSO6);
+	if (unlikely(network_hdr_len >  IXGBEVF_MAX_NETWORK_HDR_LEN)) {
+		netdev_features_clear_array(&ixgbevf_l3_disable_feature_set,
+					    &features);
+		return features;
+	}
 
 	/* We can only support IPV4 TSO in tunnels if we can mangle the
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
@@ -4504,6 +4516,26 @@ static void ixgbevf_assign_netdev_ops(struct net_device *dev)
 	dev->watchdog_timeo = 5 * HZ;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ixgbevf_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ixgbevf_gso_partial_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);
+static DECLARE_NETDEV_FEATURE_SET(ixgbevf_mpls_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+
 /**
  * ixgbevf_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -4521,6 +4553,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct ixgbevf_adapter *adapter = NULL;
 	struct ixgbe_hw *hw = NULL;
 	const struct ixgbevf_info *ii = ixgbevf_info_tbl[ent->driver_data];
+	netdev_features_t gso_partial_features;
 	bool disable_dev = false;
 	int err;
 
@@ -4593,32 +4626,22 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_sw_init;
 	}
 
-	netdev->hw_features = NETIF_F_SG |
-			      NETIF_F_TSO |
-			      NETIF_F_TSO6 |
-			      NETIF_F_RXCSUM |
-			      NETIF_F_HW_CSUM |
-			      NETIF_F_SCTP_CRC;
-
-#define IXGBEVF_GSO_PARTIAL_FEATURES (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)
-
-	netdev->gso_partial_features = IXGBEVF_GSO_PARTIAL_FEATURES;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &ixgbevf_hw_feature_set);
+
+	netdev_features_zero(&gso_partial_features);
+	netdev_features_set_array(&ixgbevf_gso_partial_feature_set,
+				  &gso_partial_features);
+	netdev->gso_partial_features = gso_partial_features;
 	netdev->hw_features |= NETIF_F_GSO_PARTIAL |
-			       IXGBEVF_GSO_PARTIAL_FEATURES;
+			       gso_partial_features;
 
 	netdev->features = netdev->hw_features | NETIF_F_HIGHDMA;
 
 	netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
-	netdev->mpls_features |= NETIF_F_SG |
-				 NETIF_F_TSO |
-				 NETIF_F_TSO6 |
-				 NETIF_F_HW_CSUM;
-	netdev->mpls_features |= IXGBEVF_GSO_PARTIAL_FEATURES;
+
+	netdev_mpls_features_set_array(netdev, &ixgbevf_mpls_feature_set);
+	netdev->mpls_features |= gso_partial_features;
 	netdev->hw_enc_features |= netdev->vlan_features;
 
 	/* set this bit last since it cannot be part of vlan_features */
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index f43d6616bc0d..6db2f01468c5 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -2901,6 +2902,22 @@ static const struct net_device_ops jme_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(jme_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(jme_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
 static int
 jme_init_one(struct pci_dev *pdev,
 	     const struct pci_device_id *ent)
@@ -2955,19 +2972,10 @@ jme_init_one(struct pci_dev *pdev,
 	netdev->netdev_ops = &jme_netdev_ops;
 	netdev->ethtool_ops		= &jme_ethtool_ops;
 	netdev->watchdog_timeo		= TX_TIMEOUT;
-	netdev->hw_features		=	NETIF_F_IP_CSUM |
-						NETIF_F_IPV6_CSUM |
-						NETIF_F_SG |
-						NETIF_F_TSO |
-						NETIF_F_TSO6 |
-						NETIF_F_RXCSUM;
-	netdev->features		=	NETIF_F_IP_CSUM |
-						NETIF_F_IPV6_CSUM |
-						NETIF_F_SG |
-						NETIF_F_TSO |
-						NETIF_F_TSO6 |
-						NETIF_F_HW_VLAN_CTAG_TX |
-						NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &jme_hw_feature_set);
+	netdev_active_features_zero(netdev);
+	netdev_active_features_set_array(netdev, &jme_feature_set);
 	if (using_dac)
 		netdev->features	|=	NETIF_F_HIGHDMA;
 
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index b6be0552a6c1..e43fa3a2af17 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -38,6 +38,7 @@
 #include <linux/ethtool.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
@@ -3086,6 +3087,11 @@ static const struct net_device_ops mv643xx_eth_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(mv643xx_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT);
+
 static int mv643xx_eth_probe(struct platform_device *pdev)
 {
 	struct mv643xx_eth_platform_data *pd;
@@ -3200,7 +3206,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 	dev->watchdog_timeo = 2 * HZ;
 	dev->base_addr = 0;
 
-	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_array(dev, &mv643xx_feature_set);
 	dev->vlan_features = dev->features;
 
 	dev->features |= NETIF_F_RXCSUM;
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 0caa2df87c04..b097a857fe4e 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -22,6 +22,7 @@
 #include <linux/mbus.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -5377,6 +5378,13 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(mvneta_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 /* Device initialization routine */
 static int mvneta_probe(struct platform_device *pdev)
 {
@@ -5612,8 +5620,8 @@ static int mvneta_probe(struct platform_device *pdev)
 		}
 	}
 
-	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			NETIF_F_TSO | NETIF_F_RXCSUM;
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_array(dev, &mvneta_feature_set);
 	dev->hw_features |= dev->features;
 	dev->vlan_features |= dev->features;
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index b84128b549b4..38c5ab6a5126 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -10,6 +10,7 @@
 #include <linux/acpi.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/skbuff.h>
@@ -6653,6 +6654,16 @@ static bool mvpp2_use_acpi_compat_mode(struct fwnode_handle *port_fwnode)
 		!fwnode_get_named_child_node(port_fwnode, "fixed-link"));
 }
 
+static DECLARE_NETDEV_FEATURE_SET(mvpp2_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mvpp2_hw_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
 			    struct fwnode_handle *port_fwnode,
@@ -6846,11 +6857,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 		}
 	}
 
-	features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		   NETIF_F_TSO;
+	netdev_features_zero(&features);
+	netdev_features_set_array(&mvpp2_feature_set, &features);
 	dev->features = features | NETIF_F_RXCSUM;
-	dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO |
-			    NETIF_F_HW_VLAN_CTAG_FILTER;
+	dev->hw_features |= features;
+	netdev_hw_features_set_array(dev, &mvpp2_hw_feature_set);
 
 	if (mvpp22_rss_is_supported(port)) {
 		dev->hw_features |= NETIF_F_RXHASH;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 9376d0e62914..a228447cbb2e 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -15,6 +15,7 @@
 #include <net/ip.h>
 #include <linux/bpf.h>
 #include <linux/bpf_trace.h>
+#include <linux/netdev_features_helper.h>
 
 #include "otx2_reg.h"
 #include "otx2_common.h"
@@ -2550,6 +2551,16 @@ static void otx2_sriov_vfcfg_cleanup(struct otx2_nic *pf)
 	}
 }
 
+static DECLARE_NETDEV_FEATURE_SET(otx2_hw_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT);
+
 static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct device *dev = &pdev->dev;
@@ -2692,10 +2703,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	 */
 	pf->iommu_domain = iommu_get_domain_for_dev(dev);
 
-	netdev->hw_features = (NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
-			       NETIF_F_IPV6_CSUM | NETIF_F_RXHASH |
-			       NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
-			       NETIF_F_GSO_UDP_L4);
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &otx2_hw_feature_set);
 	netdev->features |= netdev->hw_features;
 
 	err = otx2_mcam_flow_init(pf);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 86653bb8e403..08c82c0d41a4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -7,6 +7,7 @@
 
 #include <linux/etherdevice.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/net_tstamp.h>
 
@@ -520,6 +521,16 @@ static int otx2vf_realloc_msix_vectors(struct otx2_nic *vf)
 	return otx2vf_register_mbox_intr(vf, false);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(otx2vf_hw_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT);
+
 static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int num_vec = pci_msix_vec_count(pdev);
@@ -637,10 +648,8 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	/* Assign default mac address */
 	otx2_get_mac_from_af(netdev);
 
-	netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
-			      NETIF_F_IPV6_CSUM | NETIF_F_RXHASH |
-			      NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
-			      NETIF_F_GSO_UDP_L4;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &otx2vf_hw_feature_set);
 	netdev->features = netdev->hw_features;
 	/* Support TSO on tag interface */
 	netdev->vlan_features |= netdev->features;
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index c1e985416c0e..8bdac1c90c0c 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/pci.h>
@@ -3806,6 +3807,10 @@ static const struct net_device_ops skge_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(skge_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT);
 
 /* Initialize network device */
 static struct net_device *skge_devinit(struct skge_hw *hw, int port,
@@ -3860,8 +3865,8 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 	if (is_genesis(hw))
 		timer_setup(&skge->link_timer, xm_link_timer, 0);
 	else {
-		dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
-		                   NETIF_F_RXCSUM;
+		netdev_hw_features_zero(dev);
+		netdev_hw_features_set_array(dev, &skge_hw_feature_set);
 		dev->features |= dev->hw_features;
 	}
 
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index bbea5458000b..e3b3b2c7aff3 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -1398,7 +1399,10 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	return err;
 }
 
-#define SKY2_VLAN_OFFLOADS (NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO)
+static DECLARE_NETDEV_FEATURE_SET(sky2_vlan_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT);
 
 static void sky2_vlan_mode(struct net_device *dev, netdev_features_t features)
 {
@@ -1417,13 +1421,13 @@ static void sky2_vlan_mode(struct net_device *dev, netdev_features_t features)
 		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
 			     TX_VLAN_TAG_ON);
 
-		dev->vlan_features |= SKY2_VLAN_OFFLOADS;
+		netdev_vlan_features_set_array(dev, &sky2_vlan_feature_set);
 	} else {
 		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
 			     TX_VLAN_TAG_OFF);
 
 		/* Can't do transmit offload of vlan without hw vlan */
-		dev->vlan_features &= ~SKY2_VLAN_OFFLOADS;
+		netdev_vlan_features_clear_array(dev, &sky2_vlan_feature_set);
 	}
 }
 
@@ -4587,6 +4591,11 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
   },
 };
 
+static DECLARE_NETDEV_FEATURE_SET(sky2_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT);
+
 /* Initialize network device */
 static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 					   int highmem, int wol)
@@ -4634,7 +4643,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 
 	sky2->port = port;
 
-	dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO;
+	netdev_hw_features_set_array(dev, &sky2_hw_feature_set);
 
 	if (highmem)
 		dev->features |= NETIF_F_HIGHDMA;
@@ -4646,7 +4655,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 	if (!(hw->flags & SKY2_HW_VLAN_BROKEN)) {
 		dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
 				    NETIF_F_HW_VLAN_CTAG_RX;
-		dev->vlan_features |= SKY2_VLAN_OFFLOADS;
+		netdev_vlan_features_set_array(dev, &sky2_vlan_feature_set);
 	}
 
 	dev->features |= dev->hw_features;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index f1259bdb1a29..edde15669886 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -35,6 +35,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/slab.h>
 
 #include <linux/mlx4/driver.h>
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index ca4b93a01034..594a650b6bdc 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -39,6 +39,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/hash.h>
+#include <linux/netdev_features_helper.h>
 #include <net/ip.h>
 #include <net/vxlan.h>
 #include <net/devlink.h>
@@ -3155,6 +3156,41 @@ void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev,
 	last_i += NUM_PHY_STATS;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(mlx4_gso_feature_set,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mlx4_hw_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mlx4_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mlx4_hw_feature_set1,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mlx4_hw_feature_set2,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXHASH_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mlx4_hw_feature_set3,
+				  NETIF_F_LOOPBACK_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mlx4_vlan_tag_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_STAG_TX_BIT,
+				  NETIF_F_HW_VLAN_STAG_RX_BIT);
+
 int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 			struct mlx4_en_port_profile *prof)
 {
@@ -3322,37 +3358,28 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	/*
 	 * Set driver features
 	 */
-	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &mlx4_hw_feature_set1);
 	if (mdev->LSO_support)
 		dev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
 
 	if (mdev->dev->caps.tunnel_offload_mode ==
 	    MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
-		dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
-				    NETIF_F_GSO_UDP_TUNNEL_CSUM |
-				    NETIF_F_GSO_PARTIAL;
-		dev->features    |= NETIF_F_GSO_UDP_TUNNEL |
-				    NETIF_F_GSO_UDP_TUNNEL_CSUM |
-				    NETIF_F_GSO_PARTIAL;
+		netdev_hw_features_set_array(dev, &mlx4_gso_feature_set);
+		netdev_active_features_set_array(dev, &mlx4_gso_feature_set);
 		dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
-		dev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-				       NETIF_F_RXCSUM |
-				       NETIF_F_TSO | NETIF_F_TSO6 |
-				       NETIF_F_GSO_UDP_TUNNEL |
-				       NETIF_F_GSO_UDP_TUNNEL_CSUM |
-				       NETIF_F_GSO_PARTIAL;
+		netdev_hw_enc_features_zero(dev);
+		netdev_hw_enc_features_set_array(dev, &mlx4_hw_enc_feature_set);
 
 		dev->udp_tunnel_nic_info = &mlx4_udp_tunnels;
 	}
 
 	dev->vlan_features = dev->hw_features;
 
-	dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_RXHASH;
-	dev->features = dev->hw_features | NETIF_F_HIGHDMA |
-			NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
-			NETIF_F_HW_VLAN_CTAG_FILTER;
-	dev->hw_features |= NETIF_F_LOOPBACK |
-			NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_features_set_array(dev, &mlx4_hw_feature_set2);
+	dev->features = dev->hw_features;
+	netdev_active_features_set_array(dev, &mlx4_feature_set);
+	netdev_hw_features_set_array(dev, &mlx4_hw_feature_set3);
 
 	if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN)) {
 		dev->features |= NETIF_F_HW_VLAN_STAG_RX |
@@ -3372,14 +3399,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 		err = mlx4_get_is_vlan_offload_disabled(mdev->dev, port,
 							&vlan_offload_disabled);
 		if (!err && vlan_offload_disabled) {
-			dev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
-					      NETIF_F_HW_VLAN_CTAG_RX |
-					      NETIF_F_HW_VLAN_STAG_TX |
-					      NETIF_F_HW_VLAN_STAG_RX);
-			dev->features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
-					   NETIF_F_HW_VLAN_CTAG_RX |
-					   NETIF_F_HW_VLAN_STAG_TX |
-					   NETIF_F_HW_VLAN_STAG_RX);
+			netdev_hw_features_clear_array(dev, &mlx4_vlan_tag_feature_set);
+			netdev_active_features_clear_array(dev, &mlx4_vlan_tag_feature_set);
 		}
 	} else {
 		if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN &&
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
index c02b7b08fb4c..d859b58c4c8b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -31,6 +31,7 @@
  */
 
 #include <rdma/ib_verbs.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/mlx5/fs.h>
 #include "en.h"
 #include "en/params.h"
@@ -72,6 +73,16 @@ static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev,
 	params->tunneled_offload_en = false;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(mlx5i_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXHASH_BIT);
+
 /* Called directly after IPoIB netdevice was created to initialize SW structs */
 int mlx5i_init(struct mlx5_core_dev *mdev, struct net_device *netdev)
 {
@@ -87,14 +98,7 @@ int mlx5i_init(struct mlx5_core_dev *mdev, struct net_device *netdev)
 	mlx5e_timestamp_init(priv);
 
 	/* netdev init */
-	netdev->hw_features    |= NETIF_F_SG;
-	netdev->hw_features    |= NETIF_F_IP_CSUM;
-	netdev->hw_features    |= NETIF_F_IPV6_CSUM;
-	netdev->hw_features    |= NETIF_F_GRO;
-	netdev->hw_features    |= NETIF_F_TSO;
-	netdev->hw_features    |= NETIF_F_TSO6;
-	netdev->hw_features    |= NETIF_F_RXCSUM;
-	netdev->hw_features    |= NETIF_F_RXHASH;
+	netdev_hw_features_set_array(netdev, &mlx5i_hw_feature_set);
 
 	netdev->netdev_ops = &mlx5i_netdev_ops;
 	netdev->ethtool_ops = &mlx5i_ethtool_ops;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 1e240cdd9cbd..a38ed21cfbdf 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -6,6 +6,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/slab.h>
@@ -1596,6 +1597,16 @@ static int mlxsw_sp_port_label_info_get(struct mlxsw_sp *mlxsw_sp,
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(mlxsw_feature_set,
+				  NETIF_F_NETNS_LOCAL_BIT,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_TC_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mlxsw_hw_feature_set,
+				  NETIF_F_HW_TC_BIT,
+				  NETIF_F_LOOPBACK_BIT);
+
 static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u16 local_port,
 				bool split,
 				struct mlxsw_sp_port_mapping *port_mapping)
@@ -1682,9 +1693,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u16 local_port,
 
 	netif_carrier_off(dev);
 
-	dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG |
-			 NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_TC;
-	dev->hw_features |= NETIF_F_HW_TC | NETIF_F_LOOPBACK;
+	netdev_active_features_set_array(dev, &mlxsw_feature_set);
+	netdev_hw_features_set_array(dev, &mlxsw_hw_feature_set);
 
 	dev->min_mtu = 0;
 	dev->max_mtu = ETH_MAX_MTU;
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 2b3eb5ed8233..07b6d0124d1a 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -26,6 +26,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/micrel_phy.h>
+#include <linux/netdev_features_helper.h>
 
 
 /* DMA Registers */
@@ -6686,6 +6687,11 @@ static int stp;
  */
 static int fast_aging;
 
+static DECLARE_NETDEV_FEATURE_SET(ksz_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 /**
  * netdev_init - initialize network device.
  * @dev:	Network device.
@@ -6705,7 +6711,8 @@ static int __init netdev_init(struct net_device *dev)
 	/* 500 ms timeout */
 	dev->watchdog_timeo = HZ / 2;
 
-	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_RXCSUM;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &ksz_hw_feature_set);
 
 	/*
 	 * Hardware does not really support IPv6 checksum generation, but
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index a9a1dea6d731..5f429b54bc30 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -4,6 +4,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/crc32.h>
 #include <linux/microchipphy.h>
@@ -3323,6 +3324,11 @@ static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
 	return ret;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(lan743x_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+
 /* lan743x_pcidev_probe - Device Initialization Routine
  * @pdev: PCI device information struct
  * @id: entry in lan743x_pci_tbl
@@ -3383,7 +3389,8 @@ static int lan743x_pcidev_probe(struct pci_dev *pdev,
 
 	adapter->netdev->netdev_ops = &lan743x_netdev_ops;
 	adapter->netdev->ethtool_ops = &lan743x_ethtool_ops;
-	adapter->netdev->features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM;
+	netdev_active_features_zero(adapter->netdev);
+	netdev_active_features_set_array(adapter->netdev, &lan743x_hw_feature_set);
 	adapter->netdev->hw_features = adapter->netdev->features;
 
 	/* carrier off reporting is important to ethtool even BEFORE open */
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 9259a74eca40..d2a424573d89 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2039,6 +2039,15 @@ int mana_detach(struct net_device *ndev, bool from_close)
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(mana_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXHASH_BIT);
+
 static int mana_probe_port(struct mana_context *ac, int port_idx,
 			   struct net_device **ndev_storage)
 {
@@ -2081,10 +2090,8 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
 
 	netdev_lockdep_set_classes(ndev);
 
-	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-	ndev->hw_features |= NETIF_F_RXCSUM;
-	ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
-	ndev->hw_features |= NETIF_F_RXHASH;
+	netdev_hw_features_zero(ndev);
+	netdev_hw_features_set_array(ndev, &mana_hw_feature_set);
 	ndev->features = ndev->hw_features;
 	ndev->vlan_features = 0;
 
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 5e6136e80282..0f88dac6920a 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -10,6 +10,7 @@
 
 #include <linux/dsa/ocelot.h>
 #include <linux/if_bridge.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of_net.h>
 #include <linux/phy/phy.h>
 #include <net/pkt_cls.h>
@@ -1809,6 +1810,14 @@ static int ocelot_port_phylink_create(struct ocelot *ocelot, int port,
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ocelot_hw_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_RXFCS_BIT,
+				  NETIF_F_HW_TC_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ocelot_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_TC_BIT);
+
 int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target,
 		      struct device_node *portnp)
 {
@@ -1833,9 +1842,8 @@ int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target,
 	dev->ethtool_ops = &ocelot_ethtool_ops;
 	dev->max_mtu = OCELOT_JUMBO_MTU;
 
-	dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXFCS |
-		NETIF_F_HW_TC;
-	dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_TC;
+	netdev_hw_features_set_array(dev, &ocelot_hw_feature_set);
+	netdev_active_features_set_array(dev, &ocelot_feature_set);
 
 	err = of_get_ethdev_address(portnp, dev);
 	if (err)
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 971dde8c3286..cffe22b5f5f3 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -42,6 +42,7 @@
 
 #include <linux/tcp.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <linux/string.h>
 #include <linux/module.h>
@@ -243,7 +244,7 @@ struct myri10ge_priv {
 	unsigned long serial_number;
 	int vendor_specific_offset;
 	int fw_multicast_support;
-	u32 features;
+	netdev_features_t features;
 	u32 max_tso6;
 	u32 read_dma;
 	u32 write_dma;
@@ -681,13 +682,19 @@ static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
 	return status;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(myri10ge_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT);
+
 static int myri10ge_get_firmware_capabilities(struct myri10ge_priv *mgp)
 {
 	struct myri10ge_cmd cmd;
 	int status;
 
 	/* probe for IPv6 TSO support */
-	mgp->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO;
+	netdev_features_zero(&mgp->features);
+	netdev_features_set_array(&myri10ge_feature_set, &mgp->features);
 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE,
 				   &cmd, 0);
 	if (status == 0) {
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 30f955efa830..79dd414f6e36 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -60,6 +60,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/mdio.h>
 #include <linux/skbuff.h>
@@ -7638,6 +7639,19 @@ static const struct net_device_ops s2io_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(s2io_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_SG_BIT);
+static DECLARE_NETDEV_FEATURE_SET(s2io_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 /**
  *  s2io_init_nic - Initialization of the adapter .
  *  @pdev : structure containing the PCI related information of the device.
@@ -7853,12 +7867,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	/*  Driver entry points */
 	dev->netdev_ops = &s2io_netdev_ops;
 	dev->ethtool_ops = &netdev_ethtool_ops;
-	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO6 |
-		NETIF_F_RXCSUM | NETIF_F_LRO;
-	dev->features |= dev->hw_features |
-		NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
-		NETIF_F_HIGHDMA;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &s2io_hw_feature_set);
+	dev->features |= dev->hw_features;
+	netdev_active_features_set_array(dev, &s2io_feature_set);
 	dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
 	INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
 	INIT_WORK(&sp->set_link_task, s2io_set_link);
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 5116badaf091..71c5363084e6 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -37,6 +37,7 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
@@ -5706,6 +5707,12 @@ static const struct net_device_ops nv_netdev_ops_optimized = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(nv_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
 	struct net_device *dev;
@@ -5811,8 +5818,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 
 	if (id->driver_data & DEV_HAS_CHECKSUM) {
 		np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
-		dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_SG |
-			NETIF_F_TSO | NETIF_F_RXCSUM;
+		netdev_hw_features_set_array(dev, &nv_hw_feature_set);
 	}
 
 	np->vlanctl_bits = 0;
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 46da937ad27f..8213d2300ff4 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -13,6 +13,7 @@
 #include <linux/gpio/machine.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/net_tstamp.h>
 #include <linux/ptp_classify.h>
 #include <linux/ptp_pch.h>
@@ -2463,6 +2464,11 @@ static void pch_gbe_remove(struct pci_dev *pdev)
 	free_netdev(netdev);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(pch_gbe_hw_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT);
+
 static int pch_gbe_probe(struct pci_dev *pdev,
 			  const struct pci_device_id *pci_id)
 {
@@ -2518,8 +2524,8 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 	netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
 	netif_napi_add(netdev, &adapter->napi,
 		       pch_gbe_napi_poll, NAPI_POLL_WEIGHT);
-	netdev->hw_features = NETIF_F_RXCSUM |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &pch_gbe_hw_feature_set);
 	netdev->features = netdev->hw_features;
 	pch_gbe_set_ethtool_ops(netdev);
 
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index f0ace3a0e85c..55437fd2de69 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -1672,6 +1672,13 @@ static const struct net_device_ops pasemi_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(pasemi_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_GSO_BIT);
+
 static int
 pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -1699,8 +1706,8 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
 
-	dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
-			NETIF_F_HIGHDMA | NETIF_F_GSO;
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_array(dev, &pasemi_feature_set);
 
 	mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
 	if (!mac->dma_pdev) {
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 1443f788ee37..4f2511f763dd 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -5,6 +5,7 @@
 #include <linux/printk.h>
 #include <linux/dynamic_debug.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
 #include <linux/rtnetlink.h>
@@ -1479,6 +1480,17 @@ static int ionic_set_nic_features(struct ionic_lif *lif,
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ionic_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_TSO_ECN_BIT);
+
 static int ionic_init_nic_features(struct ionic_lif *lif)
 {
 	struct net_device *netdev = lif->netdev;
@@ -1486,15 +1498,8 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
 	int err;
 
 	/* set up what we expect to support by default */
-	features = NETIF_F_HW_VLAN_CTAG_TX |
-		   NETIF_F_HW_VLAN_CTAG_RX |
-		   NETIF_F_HW_VLAN_CTAG_FILTER |
-		   NETIF_F_SG |
-		   NETIF_F_HW_CSUM |
-		   NETIF_F_RXCSUM |
-		   NETIF_F_TSO |
-		   NETIF_F_TSO6 |
-		   NETIF_F_TSO_ECN;
+	netdev_features_zero(&features);
+	netdev_features_set_array(&ionic_feature_set, &features);
 
 	if (lif->nxqs > 1)
 		features |= NETIF_F_RXHASH;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 4e6f00af17d9..72cbf78344b5 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -5,6 +5,7 @@
  * All rights reserved.
  */
 
+#include <linux/netdev_features_helper.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
@@ -1327,6 +1328,12 @@ netxen_nic_reset_context(struct netxen_adapter *adapter)
 	return err;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(netxen_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static int
 netxen_setup_netdev(struct netxen_adapter *adapter,
 		struct net_device *netdev)
@@ -1347,8 +1354,8 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
 
 	netdev->ethtool_ops = &netxen_nic_ethtool_ops;
 
-	netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-	                      NETIF_F_RXCSUM;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &netxen_hw_feature_set);
 
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 		netdev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index f56b679adb4b..04af61f4122a 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -20,6 +20,7 @@
 #include <asm/param.h>
 #include <linux/io.h>
 #include <linux/netdev_features.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/udp.h>
 #include <linux/tcp.h>
 #include <net/udp_tunnel.h>
@@ -820,6 +821,35 @@ static struct qede_dev *qede_alloc_etherdev(struct qed_dev *cdev,
 	return edev;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(qede_hw_feature_set,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_GRO_HW_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_TC_BIT);
+static DECLARE_NETDEV_FEATURE_SET(qede_hw_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(qede_vlan_feature_set,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(qede_feature_set,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+
 static void qede_init_ndev(struct qede_dev *edev)
 {
 	struct net_device *ndev = edev->ndev;
@@ -850,9 +880,8 @@ static void qede_init_ndev(struct qede_dev *edev)
 	ndev->priv_flags |= IFF_UNICAST_FLT;
 
 	/* user-changeble features */
-	hw_features = NETIF_F_GRO | NETIF_F_GRO_HW | NETIF_F_SG |
-		      NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		      NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_TC;
+	netdev_features_zero(&hw_features);
+	netdev_features_set_array(&qede_hw_feature_set, &hw_features);
 
 	if (edev->dev_info.common.b_arfs_capable)
 		hw_features |= NETIF_F_NTUPLE;
@@ -863,10 +892,8 @@ static void qede_init_ndev(struct qede_dev *edev)
 
 	if (udp_tunnel_enable || edev->dev_info.common.gre_enable) {
 		hw_features |= NETIF_F_TSO_ECN;
-		ndev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-					NETIF_F_SG | NETIF_F_TSO |
-					NETIF_F_TSO_ECN | NETIF_F_TSO6 |
-					NETIF_F_RXCSUM;
+		netdev_hw_enc_features_zero(ndev);
+		netdev_hw_enc_features_set_array(ndev, &qede_hw_enc_feature_set);
 	}
 
 	if (udp_tunnel_enable) {
@@ -884,11 +911,10 @@ static void qede_init_ndev(struct qede_dev *edev)
 					  NETIF_F_GSO_GRE_CSUM);
 	}
 
-	ndev->vlan_features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM |
-			      NETIF_F_HIGHDMA;
-	ndev->features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM |
-			 NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HIGHDMA |
-			 NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_TX;
+	ndev->vlan_features = hw_features;
+	netdev_vlan_features_set_array(ndev, &qede_vlan_feature_set);
+	ndev->features = hw_features;
+	netdev_active_features_set_array(ndev, &qede_feature_set);
 
 	ndev->hw_features = hw_features;
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 4b8bc46f55c2..2401cbc015f0 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <net/ip.h>
 #include <linux/bitops.h>
+#include <linux/netdev_features_helper.h>
 
 #include "qlcnic.h"
 #include "qlcnic_hdr.h"
@@ -1020,14 +1021,24 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
 	return rc;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(qlcnic_csum_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(qlcnic_changable_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
 					      netdev_features_t features)
 {
 	u32 offload_flags = adapter->offload_flags;
 
 	if (offload_flags & BIT_0) {
-		features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
-			    NETIF_F_IPV6_CSUM;
+		netdev_features_set_array(&qlcnic_csum_feature_set, &features);
 		adapter->rx_csum = 1;
 		if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
 			if (!(offload_flags & BIT_1))
@@ -1041,9 +1052,7 @@ static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
 				features |= NETIF_F_TSO6;
 		}
 	} else {
-		features &= ~(NETIF_F_RXCSUM |
-			      NETIF_F_IP_CSUM |
-			      NETIF_F_IPV6_CSUM);
+		netdev_features_clear_array(&qlcnic_csum_feature_set, &features);
 
 		if (QLCNIC_IS_TSO_CAPABLE(adapter))
 			features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
@@ -1057,6 +1066,7 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 	netdev_features_t features)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	netdev_features_t changeable;
 	netdev_features_t changed;
 
 	if (qlcnic_82xx_check(adapter) &&
@@ -1065,11 +1075,10 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 			features = qlcnic_process_flags(adapter, features);
 		} else {
 			changed = features ^ netdev->features;
-			features ^= changed & (NETIF_F_RXCSUM |
-					       NETIF_F_IP_CSUM |
-					       NETIF_F_IPV6_CSUM |
-					       NETIF_F_TSO |
-					       NETIF_F_TSO6);
+			netdev_features_zero(&changeable);
+			netdev_features_set_array(&qlcnic_changable_feature_set,
+						  &changeable);
+			features ^= changed & changeable;
 		}
 	}
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 28476b982bab..f8c043914d6a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -14,6 +14,7 @@
 #include <linux/inetdevice.h>
 #include <linux/aer.h>
 #include <linux/log2.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <net/vxlan.h>
 
@@ -2258,6 +2259,25 @@ static int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter,
 	return err;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(qlcnic_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(qlcnic_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(qlcnic_hw_enc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 int
 qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 {
@@ -2276,11 +2296,8 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 	netdev->ethtool_ops = (qlcnic_sriov_vf_check(adapter)) ?
 		&qlcnic_sriov_vf_ethtool_ops : &qlcnic_ethtool_ops;
 
-	netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
-			     NETIF_F_IPV6_CSUM | NETIF_F_GRO |
-			     NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HIGHDMA);
-	netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
-				  NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA);
+	netdev_active_features_set_array(netdev, &qlcnic_feature_set);
+	netdev_vlan_features_set_array(netdev, &qlcnic_vlan_feature_set);
 
 	if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
 		netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
@@ -2300,10 +2317,9 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 		netdev->features |= NETIF_F_GSO_UDP_TUNNEL;
 
 		/* encapsulation Tx offload supported by Adapter */
-		netdev->hw_enc_features = NETIF_F_IP_CSUM        |
-					  NETIF_F_GSO_UDP_TUNNEL |
-					  NETIF_F_TSO            |
-					  NETIF_F_TSO6;
+		netdev_vlan_features_zero(netdev);
+		netdev_vlan_features_set_array(netdev,
+					       &qlcnic_hw_enc_feature_set);
 	}
 
 	if (qlcnic_encap_rx_offload(adapter)) {
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index a55c52696d49..c302d50324fb 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -9,6 +9,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of.h>
 #include <linux/of_net.h>
 #include <linux/of_device.h>
@@ -590,6 +591,20 @@ static const struct acpi_device_id emac_acpi_match[] = {
 MODULE_DEVICE_TABLE(acpi, emac_acpi_match);
 #endif
 
+static DECLARE_NETDEV_FEATURE_SET(emac_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(emac_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static int emac_probe(struct platform_device *pdev)
 {
 	struct net_device *netdev;
@@ -665,13 +680,11 @@ static int emac_probe(struct platform_device *pdev)
 	}
 
 	/* set hw features */
-	netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
-			NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_RX |
-			NETIF_F_HW_VLAN_CTAG_TX;
+	netdev_active_features_zero(netdev);
+	netdev_active_features_set_array(netdev, &emac_feature_set);
 	netdev->hw_features = netdev->features;
 
-	netdev->vlan_features |= NETIF_F_SG | NETIF_F_HW_CSUM |
-				 NETIF_F_TSO | NETIF_F_TSO6;
+	netdev_vlan_features_set_array(netdev, &emac_vlan_feature_set);
 
 	/* MTU range: 46 - 9194 */
 	netdev->min_mtu = EMAC_MIN_ETH_FRAME_SIZE -
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
index 1b2119b1d48a..92215121428f 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
@@ -7,6 +7,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/if_arp.h>
+#include <linux/netdev_features_helper.h>
 #include <net/pkt_sched.h>
 #include "rmnet_config.h"
 #include "rmnet_handlers.h"
@@ -243,6 +244,12 @@ void rmnet_vnd_setup(struct net_device *rmnet_dev)
 	eth_random_addr(rmnet_dev->perm_addr);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(rmnet_hw_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_SG_BIT);
+
 /* Exposed API */
 
 int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev,
@@ -261,9 +268,8 @@ int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev,
 		return -EBUSY;
 	}
 
-	rmnet_dev->hw_features = NETIF_F_RXCSUM;
-	rmnet_dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-	rmnet_dev->hw_features |= NETIF_F_SG;
+	netdev_hw_features_zero(rmnet_dev);
+	netdev_hw_features_set_array(rmnet_dev, &rmnet_hw_feature_set);
 
 	priv->real_dev = real_dev;
 
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index e0feeec13da6..c5c2e491d251 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -58,6 +58,7 @@
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -1883,6 +1884,18 @@ static const struct net_device_ops cp_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(cp_default_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(cp_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct net_device *dev;
@@ -1990,16 +2003,14 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->ethtool_ops = &cp_ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
-	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-		NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_active_features_set_array(dev, &cp_default_feature_set);
 
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
 
-	dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-		NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
-	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-		NETIF_F_HIGHDMA;
+	netdev_hw_features_set_array(dev, &cp_default_feature_set);
+	netdev_vlan_features_zero(dev);
+	netdev_vlan_features_set_array(dev, &cp_vlan_feature_set);
 
 	/* MTU range: 60 - 4096 */
 	dev->min_mtu = CP_MIN_MTU;
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 15b40fd93cd2..3844a0f418ec 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -102,6 +102,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/delay.h>
@@ -940,6 +941,11 @@ static const struct net_device_ops rtl8139_netdev_ops = {
 	.ndo_set_features	= rtl8139_set_features,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(rtl8139_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static int rtl8139_init_one(struct pci_dev *pdev,
 			    const struct pci_device_id *ent)
 {
@@ -1008,7 +1014,7 @@ static int rtl8139_init_one(struct pci_dev *pdev,
 	 * through the use of skb_copy_and_csum_dev we enable these
 	 * features
 	 */
-	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;
+	netdev_active_features_set_array(dev, &rtl8139_feature_set);
 	dev->vlan_features = dev->features;
 
 	dev->hw_features |= NETIF_F_RXALL;
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 1b7fdb4f056b..b999f129490c 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -5298,6 +5299,16 @@ static bool rtl_aspm_is_safe(struct rtl8169_private *tp)
 	return false;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(rtl_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(rtl_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT);
+
 static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct rtl8169_private *tp;
@@ -5415,9 +5426,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netif_napi_add(dev, &tp->napi, rtl8169_poll, NAPI_POLL_WEIGHT);
 
-	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
-			   NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
-	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &rtl_hw_feature_set);
+	netdev_vlan_features_zero(dev);
+	netdev_vlan_features_set_array(dev, &rtl_vlan_feature_set);
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
 	/*
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index a1c10b61269b..30af142820c6 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/net_tstamp.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
 #include <linux/prefetch.h>
@@ -2050,6 +2051,15 @@ static int sxgbe_sw_reset(void __iomem *addr)
 	return 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(sxgbe_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GRO_BIT);
+
 /**
  * sxgbe_drv_probe
  * @device: device pointer
@@ -2105,9 +2115,8 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
 
 	ndev->netdev_ops = &sxgbe_netdev_ops;
 
-	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_RXCSUM | NETIF_F_TSO | NETIF_F_TSO6 |
-		NETIF_F_GRO;
+	netdev_hw_features_zero(ndev);
+	netdev_hw_features_set_array(ndev, &sxgbe_hw_feature_set);
 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
 	ndev->watchdog_timeo = msecs_to_jiffies(TX_TIMEO);
 
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index ee734b69150f..21db8af0fb73 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;
 }
 
+static 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_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index 17b9d37218cb..15f654e5ad0a 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -345,6 +345,11 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
 	efx->state = STATE_PROBED;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(ef100_vlan_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 int ef100_probe_netdev(struct efx_probe_data *probe_data)
 {
 	struct efx_nic *efx = &probe_data->efx;
@@ -370,8 +375,8 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
 	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);
 	netif_set_tso_max_segs(net_dev,
 			       ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT);
 	efx->mdio.dev = net_dev;
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 8061efdaf82c..819931161be9 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -150,6 +150,15 @@ static int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address)
 	return 0;
 }
 
+static 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);
+
 int efx_ef100_init_datapath_caps(struct efx_nic *efx)
 {
 	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V7_OUT_LEN);
@@ -188,10 +197,10 @@ 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;
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 153d68e29b8b..3baebaabdf32 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -985,6 +985,18 @@ static int efx_pci_probe_main(struct efx_nic *efx)
 	return rc;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(efx_active_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXALL_BIT);
+
+static 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;
@@ -1001,17 +1013,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 a63f40b09856..0240c7f5843a 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2853,6 +2853,12 @@ static int ef4_pci_probe_main(struct ef4_nic *efx)
 	return rc;
 }
 
+static 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,
@@ -2901,9 +2907,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 a2c7139f2b32..8ee0cc45e8ad 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 7ef823d7a89a..3ec44ed52933 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/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index 63d999e63960..050e1b0ad0cb 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/notifier.h>
@@ -967,6 +968,18 @@ static int efx_pci_probe_main(struct efx_nic *efx)
 	return rc;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(efx_active_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXALL_BIT);
+
+static 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;
@@ -983,17 +996,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/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index e2d009866a7b..84227eb0e3a4 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -825,6 +825,13 @@ static const struct net_device_ops ioc3_netdev_ops = {
 	.ndo_set_mac_address	= ioc3_set_mac_address,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(ioc_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(ioc_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static int ioc3eth_probe(struct platform_device *pdev)
 {
 	u32 sw_physid1, sw_physid2, vendor, model, rev;
@@ -926,8 +933,10 @@ static int ioc3eth_probe(struct platform_device *pdev)
 	dev->watchdog_timeo	= 5 * HZ;
 	dev->netdev_ops		= &ioc3_netdev_ops;
 	dev->ethtool_ops	= &ioc3_ethtool_ops;
-	dev->hw_features	= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
-	dev->features		= NETIF_F_IP_CSUM | NETIF_F_HIGHDMA;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &ioc_hw_feature_set);
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_array(dev, &ioc_feature_set);
 
 	sw_physid1 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID1);
 	sw_physid2 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID2);
diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c
index ff4197f5e46d..65b0b8574698 100644
--- a/drivers/net/ethernet/silan/sc92031.c
+++ b/drivers/net/ethernet/silan/sc92031.c
@@ -30,6 +30,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -1394,6 +1395,12 @@ static const struct net_device_ops sc92031_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(sc92031_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT);
+
 static int sc92031_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int err;
@@ -1437,8 +1444,8 @@ static int sc92031_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	/* faked with skb_copy_and_csum_dev */
-	dev->features = NETIF_F_SG | NETIF_F_HIGHDMA |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_array(dev, &sc92031_feature_set);
 
 	dev->netdev_ops		= &sc92031_netdev_ops;
 	dev->watchdog_timeo	= TX_TIMEOUT;
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index b0c5a44785fa..67fba95978b4 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -10,6 +10,7 @@
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/netlink.h>
 #include <linux/bpf.h>
 #include <linux/bpf_trace.h>
@@ -1975,6 +1976,13 @@ static int netsec_register_mdio(struct netsec_priv *priv, u32 phy_addr)
 	return ret;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(netsec_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT);
+
 static int netsec_probe(struct platform_device *pdev)
 {
 	struct resource *mmio_res, *eeprom_res;
@@ -2098,8 +2106,7 @@ static int netsec_probe(struct platform_device *pdev)
 	ndev->netdev_ops = &netsec_netdev_ops;
 	ndev->ethtool_ops = &netsec_ethtool_ops;
 
-	ndev->features |= NETIF_F_HIGHDMA | NETIF_F_RXCSUM | NETIF_F_GSO |
-				NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev_active_features_set_array(ndev, &netsec_feature_set);
 	ndev->hw_features = ndev->features;
 
 	priv->rx_cksum_offload_flag = true;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 070b5ef165eb..23b80ddad54d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -35,6 +35,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #endif /* CONFIG_DEBUG_FS */
+#include <linux/netdev_features_helper.h>
 #include <linux/net_tstamp.h>
 #include <linux/phylink.h>
 #include <linux/udp.h>
@@ -7026,6 +7027,12 @@ void stmmac_fpe_handshake(struct stmmac_priv *priv, bool enable)
 	}
 }
 
+static DECLARE_NETDEV_FEATURE_SET(stmmac_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 /**
  * stmmac_dvr_probe
  * @device: device pointer
@@ -7132,8 +7139,8 @@ int stmmac_dvr_probe(struct device *device,
 
 	ndev->netdev_ops = &stmmac_netdev_ops;
 
-	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			    NETIF_F_RXCSUM;
+	netdev_hw_features_zero(ndev);
+	netdev_hw_features_set_array(ndev, &stmmac_hw_feature_set);
 
 	ret = stmmac_tc_init(priv, priv);
 	if (!ret) {
diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c
index 0cd8493b810f..49fa25fa045b 100644
--- a/drivers/net/ethernet/sun/ldmvsw.c
+++ b/drivers/net/ethernet/sun/ldmvsw.c
@@ -223,6 +223,10 @@ static struct vnet *vsw_get_vnet(struct mdesc_handle *hp,
 	return vp;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(vsw_hw_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT);
+
 static struct net_device *vsw_alloc_netdev(u8 hwaddr[],
 					   struct vio_dev *vdev,
 					   u64 handle,
@@ -246,7 +250,8 @@ static struct net_device *vsw_alloc_netdev(u8 hwaddr[],
 	dev->ethtool_ops = &vsw_ethtool_ops;
 	dev->watchdog_timeo = VSW_TX_TIMEOUT;
 
-	dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &vsw_hw_feature_set);
 	dev->features = dev->hw_features;
 
 	/* MTU range: 68 - 65535 */
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index df70df29deea..f7fa28ba5d53 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -12,6 +12,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
@@ -9733,9 +9734,15 @@ static void niu_device_announce(struct niu *np)
 	}
 }
 
+static DECLARE_NETDEV_FEATURE_SET(niu_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXHASH_BIT);
+
 static void niu_set_basic_features(struct net_device *dev)
 {
-	dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXHASH;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &niu_hw_feature_set);
 	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
 }
 
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index a14591b41acb..42a7a6a5926f 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -29,6 +29,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/mii.h>
@@ -2843,6 +2844,11 @@ static const struct net_device_ops gem_netdev_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(gem_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	unsigned long gemreg_base, gemreg_len;
@@ -2989,7 +2995,8 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	pci_set_drvdata(pdev, dev);
 
 	/* We can do scatter/gather and HW checksum */
-	dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &gem_hw_feature_set);
 	dev->features = dev->hw_features;
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index da8119625cf3..0552fe23a397 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -281,6 +281,12 @@ static const struct net_device_ops vnet_ops = {
 #endif
 };
 
+static DECLARE_NETDEV_FEATURE_SET(vnet_hw_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT);
+
 static struct vnet *vnet_new(const u64 *local_mac,
 			     struct vio_dev *vdev)
 {
@@ -314,8 +320,8 @@ static struct vnet *vnet_new(const u64 *local_mac,
 	dev->ethtool_ops = &vnet_ethtool_ops;
 	dev->watchdog_timeo = VNET_TX_TIMEOUT;
 
-	dev->hw_features = NETIF_F_TSO | NETIF_F_GSO | NETIF_F_ALL_TSO |
-			   NETIF_F_HW_CSUM | NETIF_F_SG;
+	dev->hw_features = NETIF_F_ALL_TSO;
+	netdev_hw_features_set_array(dev, &vnet_hw_feature_set);
 	dev->features = dev->hw_features;
 
 	/* MTU range: 68 - 65535 */
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index 985073eba3bd..fd89439791ce 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -1862,6 +1862,21 @@ static const struct net_device_ops bdx_netdev_ops = {
 	.ndo_vlan_rx_kill_vid	= bdx_vlan_rx_kill_vid,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(bdx_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(bdx_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+
 /**
  * bdx_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -1976,13 +1991,11 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		/* these fields are used for info purposes only
 		 * so we can have them same for all ports of the board */
 		ndev->if_port = port;
-		ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO |
-		    NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
-		    NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM |
-		    NETIF_F_HIGHDMA;
+		netdev_active_features_zero(ndev);
+		netdev_active_features_set_array(ndev, &bdx_feature_set);
 
-		ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
-			NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_hw_features_zero(ndev);
+		netdev_hw_features_set_array(ndev, &bdx_hw_feature_set);
 
 	/************** priv ****************/
 		priv = nic->priv[port] = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/tehuti/tehuti.h b/drivers/net/ethernet/tehuti/tehuti.h
index 909e7296cecf..eef81f973233 100644
--- a/drivers/net/ethernet/tehuti/tehuti.h
+++ b/drivers/net/ethernet/tehuti/tehuti.h
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index f4a6b590a1e3..b390983861d8 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -14,6 +14,7 @@
 #include <linux/kmemleak.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/net_tstamp.h>
 #include <linux/of.h>
 #include <linux/of_mdio.h>
@@ -1932,6 +1933,12 @@ static void am65_cpsw_nuss_phylink_cleanup(struct am65_cpsw_common *common)
 	}
 }
 
+static DECLARE_NETDEV_FEATURE_SET(am65_cpsw_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HW_TC_BIT);
+
 static int
 am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 {
@@ -1966,10 +1973,8 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 
 	port->ndev->min_mtu = AM65_CPSW_MIN_PACKET_SIZE;
 	port->ndev->max_mtu = AM65_CPSW_MAX_PACKET_SIZE;
-	port->ndev->hw_features = NETIF_F_SG |
-				  NETIF_F_RXCSUM |
-				  NETIF_F_HW_CSUM |
-				  NETIF_F_HW_TC;
+	netdev_hw_features_zero(port->ndev);
+	netdev_hw_features_set_array(port->ndev, &am65_cpsw_hw_feature_set);
 	port->ndev->features = port->ndev->hw_features |
 			       NETIF_F_HW_VLAN_CTAG_FILTER;
 	port->ndev->vlan_features |=  NETIF_F_SG;
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index 353e58b22c51..fb9ba01138f1 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -13,6 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/if_ether.h>
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/phy/phy.h>
@@ -1359,6 +1360,12 @@ static void cpsw_remove_dt(struct cpsw_common *cpsw)
 	}
 }
 
+static DECLARE_NETDEV_FEATURE_SET(cpsw_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_NETNS_LOCAL_BIT,
+				  NETIF_F_HW_TC_BIT);
+
 static int cpsw_create_ports(struct cpsw_common *cpsw)
 {
 	struct cpsw_platform_data *data = &cpsw->data;
@@ -1403,9 +1410,7 @@ static int cpsw_create_ports(struct cpsw_common *cpsw)
 
 		cpsw->slaves[i].ndev = ndev;
 
-		ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
-				  NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_NETNS_LOCAL | NETIF_F_HW_TC;
-
+		netdev_active_features_set_array(ndev, &cpsw_feature_set);
 		ndev->netdev_ops = &cpsw_netdev_ops;
 		ndev->ethtool_ops = &cpsw_ethtool_ops;
 		SET_NETDEV_DEV(ndev, dev);
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index ff0c102cb578..06ac16f37bf5 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -45,6 +45,7 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
@@ -2748,6 +2749,16 @@ static u32 velocity_get_link(struct net_device *dev)
 	return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 1 : 0;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(velocity_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(velocity_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_IP_CSUM_BIT);
+
 /**
  *	velocity_probe - set up discovered velocity device
  *	@dev: PCI device
@@ -2848,11 +2859,9 @@ static int velocity_probe(struct device *dev, int irq,
 	netdev->ethtool_ops = &velocity_ethtool_ops;
 	netif_napi_add(netdev, &vptr->napi, velocity_poll, NAPI_POLL_WEIGHT);
 
-	netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
-			   NETIF_F_HW_VLAN_CTAG_TX;
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_TX |
-			NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX |
-			NETIF_F_IP_CSUM;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &velocity_hw_feature_set);
+	netdev_active_features_set_array(netdev, &velocity_feature_set);
 
 	/* MTU range: 64 - 9000 */
 	netdev->min_mtu = VELOCITY_MIN_MTU;
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 018d365f9deb..33a1554c7f83 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/etherdevice.h>
 #include <linux/hash.h>
+#include <linux/netdev_features_helper.h>
 #include <net/ipv6_stubs.h>
 #include <net/dst_metadata.h>
 #include <net/gro_cells.h>
@@ -1234,6 +1235,18 @@ static void geneve_offload_rx_ports(struct net_device *dev, bool push)
 	rcu_read_unlock();
 }
 
+static DECLARE_NETDEV_FEATURE_SET(geneve_feature_set,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(geneve_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 /* Initialize the device structure. */
 static void geneve_setup(struct net_device *dev)
 {
@@ -1245,13 +1258,10 @@ static void geneve_setup(struct net_device *dev)
 
 	SET_NETDEV_DEVTYPE(dev, &geneve_type);
 
-	dev->features    |= NETIF_F_LLTX;
-	dev->features    |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST;
-	dev->features    |= NETIF_F_RXCSUM;
+	netdev_active_features_set_array(dev, &geneve_feature_set);
 	dev->features    |= NETIF_F_GSO_SOFTWARE;
 
-	dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST;
-	dev->hw_features |= NETIF_F_RXCSUM;
+	netdev_hw_features_set_array(dev, &geneve_hw_feature_set);
 	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
 
 	/* MTU range: 68 - (something less than 65535) */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 15ebd5426604..6bf8d63132a1 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/inetdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/pci.h>
@@ -2450,6 +2451,11 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
 	return NOTIFY_OK;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(netvsc_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
 static int netvsc_probe(struct hv_device *dev,
 			const struct hv_vmbus_device_id *dev_id)
 {
@@ -2533,9 +2539,8 @@ static int netvsc_probe(struct hv_device *dev,
 		schedule_work(&nvdev->subchan_work);
 
 	/* hw_features computed in rndis_netdev_set_hwcaps() */
-	net->features = net->hw_features |
-		NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_TX |
-		NETIF_F_HW_VLAN_CTAG_RX;
+	net->features = net->hw_features;
+	netdev_active_features_set_array(net, &netvsc_feature_set);
 	net->vlan_features = net->features;
 
 	netdev_lockdep_set_classes(net);
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 1c64d5347b8e..92ffd1b9849b 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -288,10 +289,13 @@ static const struct ethtool_ops ifb_ethtool_ops = {
 	.get_ethtool_stats	= ifb_get_ethtool_stats,
 };
 
-#define IFB_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG  | NETIF_F_FRAGLIST	| \
-		      NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL	| \
-		      NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_TX		| \
-		      NETIF_F_HW_VLAN_STAG_TX)
+static DECLARE_NETDEV_FEATURE_SET(ifb_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_STAG_TX_BIT);
 
 static void ifb_dev_free(struct net_device *dev)
 {
@@ -309,6 +313,8 @@ static void ifb_dev_free(struct net_device *dev)
 
 static void ifb_setup(struct net_device *dev)
 {
+	netdev_features_t ifb_features;
+
 	/* Initialize the device structure. */
 	dev->netdev_ops = &ifb_netdev_ops;
 	dev->ethtool_ops = &ifb_ethtool_ops;
@@ -317,10 +323,12 @@ static void ifb_setup(struct net_device *dev)
 	ether_setup(dev);
 	dev->tx_queue_len = TX_Q_LIMIT;
 
-	dev->features |= IFB_FEATURES;
+	ifb_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev_features_set_array(&ifb_feature_set, &ifb_features);
+	dev->features |= ifb_features;
 	dev->hw_features |= dev->features;
 	dev->hw_enc_features |= dev->features;
-	dev->vlan_features |= IFB_FEATURES & ~(NETIF_F_HW_VLAN_CTAG_TX |
+	dev->vlan_features |= ifb_features & ~(NETIF_F_HW_VLAN_CTAG_TX |
 					       NETIF_F_HW_VLAN_STAG_TX);
 
 	dev->flags |= IFF_NOARP;
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 49ba8a50dfb1..b0d7a484fd39 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -3,9 +3,14 @@
  */
 
 #include <linux/ethtool.h>
+#include <linux/netdev_features_helper.h>
 
 #include "ipvlan.h"
 
+static netdev_features_t ipvlan_offload_features __ro_after_init;
+static netdev_features_t ipvlan_always_on_features __ro_after_init;
+static netdev_features_t ipvlan_features __ro_after_init;
+
 static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
 				struct netlink_ext_ack *extack)
 {
@@ -107,18 +112,30 @@ static void ipvlan_port_destroy(struct net_device *dev)
 	kfree(port);
 }
 
-#define IPVLAN_ALWAYS_ON_OFLOADS \
-	(NETIF_F_SG | NETIF_F_HW_CSUM | \
-	 NETIF_F_GSO_ROBUST | NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL)
-
-#define IPVLAN_ALWAYS_ON \
-	(IPVLAN_ALWAYS_ON_OFLOADS | NETIF_F_LLTX | NETIF_F_VLAN_CHALLENGED)
-
-#define IPVLAN_FEATURES \
-	(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
-	 NETIF_F_GSO | NETIF_F_ALL_TSO | NETIF_F_GSO_ROBUST | \
-	 NETIF_F_GRO | NETIF_F_RXCSUM | \
-	 NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)
+static DECLARE_NETDEV_FEATURE_SET(ipvlan_on_offload_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_GSO_ROBUST_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(ipvlan_always_on_feature_set,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_VLAN_CHALLENGED_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(ipvlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_GSO_ROBUST_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_VLAN_STAG_FILTER_BIT);
+
+#define IPVLAN_FEATURES			ipvlan_features
+#define IPVLAN_ALWAYS_ON_OFLOADS	ipvlan_offload_features
+#define IPVLAN_ALWAYS_ON		ipvlan_always_on_features
 
 	/* NETIF_F_GSO_ENCAP_ALL NETIF_F_GSO_SOFTWARE Newly added */
 
@@ -1018,6 +1035,21 @@ static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
 };
 #endif
 
+static void __init ipvlan_features_init(void)
+{
+	ipvlan_offload_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev_features_set_array(&ipvlan_on_offload_feature_set,
+				  &ipvlan_offload_features);
+
+	ipvlan_always_on_features = ipvlan_offload_features;
+	netdev_features_set_array(&ipvlan_always_on_feature_set,
+				  &ipvlan_always_on_features);
+
+	ipvlan_features = NETIF_F_ALL_TSO;
+	netdev_features_set_array(&ipvlan_feature_set,
+				  &ipvlan_features);
+}
+
 static int __init ipvlan_init_module(void)
 {
 	int err;
@@ -1042,6 +1074,8 @@ static int __init ipvlan_init_module(void)
 		goto error;
 	}
 
+	ipvlan_features_init();
+
 	return 0;
 error:
 	unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
diff --git a/drivers/net/ipvlan/ipvtap.c b/drivers/net/ipvlan/ipvtap.c
index ef02f2cf5ce1..c6d95576ad40 100644
--- a/drivers/net/ipvlan/ipvtap.c
+++ b/drivers/net/ipvlan/ipvtap.c
@@ -18,14 +18,18 @@
 #include <linux/idr.h>
 #include <linux/fs.h>
 #include <linux/uio.h>
+#include <linux/netdev_features_helper.h>
 
 #include <net/net_namespace.h>
 #include <net/rtnetlink.h>
 #include <net/sock.h>
 #include <linux/virtio_net.h>
 
-#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
-		      NETIF_F_TSO6)
+static DECLARE_NETDEV_FEATURE_SET(tun_offload_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
 
 static dev_t ipvtap_major;
 static struct cdev ipvtap_cdev;
@@ -86,7 +90,9 @@ static int ipvtap_newlink(struct net *src_net, struct net_device *dev,
 	/* Since macvlan supports all offloads by default, make
 	 * tap support all offloads also.
 	 */
-	vlantap->tap.tap_features = TUN_OFFLOADS;
+	netdev_features_zero(&vlantap->tap.tap_features);
+	netdev_features_set_array(&tun_offload_feature_set,
+				  &vlantap->tap.tap_features);
 	vlantap->tap.count_tx_dropped = ipvtap_count_tx_dropped;
 	vlantap->tap.update_features =	ipvtap_update_features;
 	vlantap->tap.count_rx_dropped = ipvtap_count_rx_dropped;
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 14e8d04cb434..308c8674e3ad 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -41,6 +41,7 @@
 
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -160,6 +161,18 @@ static const struct net_device_ops loopback_ops = {
 	.ndo_set_mac_address = eth_mac_addr,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(lp_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_NETNS_LOCAL_BIT,
+				  NETIF_F_VLAN_CHALLENGED_BIT,
+				  NETIF_F_LOOPBACK_BIT);
+
 static void gen_lo_setup(struct net_device *dev,
 			 unsigned int mtu,
 			 const struct ethtool_ops *eth_ops,
@@ -176,16 +189,8 @@ static void gen_lo_setup(struct net_device *dev,
 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
 	netif_keep_dst(dev);
 	dev->hw_features	= NETIF_F_GSO_SOFTWARE;
-	dev->features		= NETIF_F_SG | NETIF_F_FRAGLIST
-		| NETIF_F_GSO_SOFTWARE
-		| NETIF_F_HW_CSUM
-		| NETIF_F_RXCSUM
-		| NETIF_F_SCTP_CRC
-		| NETIF_F_HIGHDMA
-		| NETIF_F_LLTX
-		| NETIF_F_NETNS_LOCAL
-		| NETIF_F_VLAN_CHALLENGED
-		| NETIF_F_LOOPBACK;
+	dev->features		= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set_array(dev, &lp_feature_set);
 	dev->ethtool_ops	= eth_ops;
 	dev->header_ops		= hdr_ops;
 	dev->netdev_ops		= dev_ops;
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index f1683ce6b561..ca7f01d33483 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -12,6 +12,7 @@
 #include <crypto/aead.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/rtnetlink.h>
 #include <linux/refcount.h>
 #include <net/genetlink.h>
@@ -3420,15 +3421,20 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
 	return ret;
 }
 
-#define SW_MACSEC_FEATURES \
-	(NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
+static netdev_features_t macsec_no_inherit_features __ro_after_init;
+static netdev_features_t sw_macsec_features __ro_after_init;
+static DECLARE_NETDEV_FEATURE_SET(sw_macsec_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_FRAGLIST_BIT);
+#define SW_MACSEC_FEATURES sw_macsec_features
 
 /* If h/w offloading is enabled, use real device features save for
  *   VLAN_FEATURES - they require additional ops
  *   HW_MACSEC - no reason to report it
  */
 #define REAL_DEV_FEATURES(dev) \
-	((dev)->features & ~(NETIF_F_VLAN_FEATURES | NETIF_F_HW_MACSEC))
+	((dev)->features & ~macsec_no_inherit_features)
 
 static int macsec_dev_init(struct net_device *dev)
 {
@@ -4351,6 +4357,14 @@ static struct notifier_block macsec_notifier = {
 	.notifier_call = macsec_notify,
 };
 
+static void __init macsec_features_init(void)
+{
+	netdev_features_set_array(&sw_macsec_feature_set, &sw_macsec_features);
+
+	macsec_no_inherit_features = NETIF_F_VLAN_FEATURES;
+	macsec_no_inherit_features |= NETIF_F_HW_MACSEC;
+}
+
 static int __init macsec_init(void)
 {
 	int err;
@@ -4368,6 +4382,8 @@ static int __init macsec_init(void)
 	if (err)
 		goto rtnl;
 
+	macsec_features_init();
+
 	return 0;
 
 rtnl:
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 1080d6ebff63..d9a20c0341c6 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -19,6 +19,7 @@
 #include <linux/rculist.h>
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/net_tstamp.h>
 #include <linux/ethtool.h>
@@ -67,6 +68,10 @@ struct macvlan_skb_cb {
 
 #define MACVLAN_SKB_CB(__skb) ((struct macvlan_skb_cb *)&((__skb)->cb[0]))
 
+static netdev_features_t macvlan_offload_features __ro_after_init;
+static netdev_features_t macvlan_always_on_features __ro_after_init;
+static netdev_features_t macvlan_features __ro_after_init;
+
 static void macvlan_port_destroy(struct net_device *dev);
 static void update_port_bc_queue_len(struct macvlan_port *port);
 
@@ -868,17 +873,30 @@ static int macvlan_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  */
 static struct lock_class_key macvlan_netdev_addr_lock_key;
 
-#define ALWAYS_ON_OFFLOADS \
-	(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \
-	 NETIF_F_GSO_ROBUST | NETIF_F_GSO_ENCAP_ALL)
-
-#define ALWAYS_ON_FEATURES (ALWAYS_ON_OFFLOADS | NETIF_F_LLTX)
-
-#define MACVLAN_FEATURES \
-	(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
-	 NETIF_F_GSO | NETIF_F_TSO | NETIF_F_LRO | \
-	 NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \
-	 NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)
+static DECLARE_NETDEV_FEATURE_SET(macvlan_on_offload_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_GSO_ROBUST_BIT);
+static DECLARE_NETDEV_FEATURE_SET(macvlan_always_on_feature_set,
+				  NETIF_F_LLTX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(macvlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_VLAN_STAG_FILTER_BIT);
+
+#define MACVLAN_FEATURES	macvlan_features
+#define ALWAYS_ON_OFFLOADS	macvlan_offload_features
+#define ALWAYS_ON_FEATURES	macvlan_always_on_features
 
 #define MACVLAN_STATE_MASK \
 	((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
@@ -1813,6 +1831,20 @@ static struct notifier_block macvlan_notifier_block __read_mostly = {
 	.notifier_call	= macvlan_device_event,
 };
 
+static void __init macvlan_features_init(void)
+{
+	macvlan_offload_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev_features_set_array(&macvlan_on_offload_feature_set,
+				  &macvlan_offload_features);
+
+	macvlan_always_on_features = macvlan_offload_features;
+	netdev_features_set_array(&macvlan_always_on_feature_set,
+				  &macvlan_always_on_features);
+
+	netdev_features_set_array(&macvlan_feature_set,
+				  &macvlan_features);
+}
+
 static int __init macvlan_init_module(void)
 {
 	int err;
@@ -1822,6 +1854,8 @@ static int __init macvlan_init_module(void)
 	err = macvlan_link_register(&macvlan_link_ops);
 	if (err < 0)
 		goto err1;
+
+	macvlan_features_init();
 	return 0;
 err1:
 	unregister_netdevice_notifier(&macvlan_notifier_block);
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index cecf8c63096c..03ee8c8f9ee7 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -18,6 +18,7 @@
 #include <linux/idr.h>
 #include <linux/fs.h>
 #include <linux/uio.h>
+#include <linux/netdev_features_helper.h>
 
 #include <net/net_namespace.h>
 #include <net/rtnetlink.h>
@@ -49,8 +50,11 @@ static struct class macvtap_class = {
 };
 static struct cdev macvtap_cdev;
 
-#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
-		      NETIF_F_TSO6)
+static DECLARE_NETDEV_FEATURE_SET(tun_offload_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
 
 static void macvtap_count_tx_dropped(struct tap_dev *tap)
 {
@@ -90,7 +94,9 @@ static int macvtap_newlink(struct net *src_net, struct net_device *dev,
 	/* Since macvlan supports all offloads by default, make
 	 * tap support all offloads also.
 	 */
-	vlantap->tap.tap_features = TUN_OFFLOADS;
+	netdev_features_zero(&vlantap->tap.tap_features);
+	netdev_features_set_array(&tun_offload_feature_set,
+				  &vlantap->tap.tap_features);
 
 	/* Register callbacks for rx/tx drops accounting and updating
 	 * net_device features
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index 21a0435c02de..d6c2082d0993 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -15,6 +15,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/module.h>
@@ -27,6 +28,19 @@
 #include <uapi/linux/if_arp.h>
 #include <net/net_failover.h>
 
+static netdev_features_t failover_vlan_features __ro_after_init;
+static netdev_features_t failover_enc_features __ro_after_init;
+static DECLARE_NETDEV_FEATURE_SET(failover_vlan_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_LRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(failover_enc_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static bool net_failover_xmit_ready(struct net_device *dev)
 {
 	return netif_running(dev) && netif_carrier_ok(dev);
@@ -823,9 +837,18 @@ void net_failover_destroy(struct failover *failover)
 }
 EXPORT_SYMBOL_GPL(net_failover_destroy);
 
+static __init void net_failover_features_init(void)
+{
+	netdev_features_set_array(&failover_vlan_feature_set,
+				  &failover_vlan_features);
+	netdev_features_set_array(&failover_enc_feature_set,
+				  &failover_enc_features);
+}
+
 static __init int
 net_failover_init(void)
 {
+	net_failover_features_init();
 	return 0;
 }
 module_init(net_failover_init);
diff --git a/drivers/net/netdevsim/ipsec.c b/drivers/net/netdevsim/ipsec.c
index 386336a38f34..ad0b5bf06f49 100644
--- a/drivers/net/netdevsim/ipsec.c
+++ b/drivers/net/netdevsim/ipsec.c
@@ -272,16 +272,17 @@ bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb)
 	return true;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(nsim_esp_feature_set,
+				  NETIF_F_HW_ESP_BIT,
+				  NETIF_F_HW_ESP_TX_CSUM_BIT,
+				  NETIF_F_GSO_ESP_BIT);
+
 void nsim_ipsec_init(struct netdevsim *ns)
 {
 	ns->netdev->xfrmdev_ops = &nsim_xfrmdev_ops;
 
-#define NSIM_ESP_FEATURES	(NETIF_F_HW_ESP | \
-				 NETIF_F_HW_ESP_TX_CSUM | \
-				 NETIF_F_GSO_ESP)
-
-	ns->netdev->features |= NSIM_ESP_FEATURES;
-	ns->netdev->hw_enc_features |= NSIM_ESP_FEATURES;
+	netdev_active_features_set_array(ns->netdev, &nsim_esp_feature_set);
+	netdev_hw_enc_features_set_array(ns->netdev, &nsim_esp_feature_set);
 
 	ns->ipsec.pfile = debugfs_create_file("ipsec", 0400,
 					      ns->nsim_dev_port->ddir, ns,
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index e470e3398abc..ad687b14dda3 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/slab.h>
 #include <net/netlink.h>
 #include <net/pkt_cls.h>
@@ -278,6 +279,13 @@ static const struct net_device_ops nsim_vf_netdev_ops = {
 	.ndo_get_devlink_port	= nsim_get_devlink_port,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(nsim_feature_set,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT);
+
 static void nsim_setup(struct net_device *dev)
 {
 	ether_setup(dev);
@@ -288,11 +296,7 @@ static void nsim_setup(struct net_device *dev)
 	dev->flags &= ~IFF_MULTICAST;
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE |
 			   IFF_NO_QUEUE;
-	dev->features |= NETIF_F_HIGHDMA |
-			 NETIF_F_SG |
-			 NETIF_F_FRAGLIST |
-			 NETIF_F_HW_CSUM |
-			 NETIF_F_TSO;
+	netdev_active_features_set_array(dev, &nsim_feature_set);
 	dev->hw_features |= NETIF_F_HW_TC;
 	dev->max_mtu = ETH_MAX_MTU;
 }
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 7d8ed8d8df5c..cf020a685530 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/u64_stats_sync.h>
 #include <net/devlink.h>
 #include <net/udp_tunnel.h>
diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c
index 5e19a6839dea..2ccfaf04b429 100644
--- a/drivers/net/nlmon.c
+++ b/drivers/net/nlmon.c
@@ -3,6 +3,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/netlink.h>
 #include <net/net_namespace.h>
 #include <linux/if_arp.h>
@@ -80,6 +81,12 @@ static const struct net_device_ops nlmon_ops = {
 	.ndo_get_stats64 = nlmon_get_stats64,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(nlmon_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_LLTX_BIT);
+
 static void nlmon_setup(struct net_device *dev)
 {
 	dev->type = ARPHRD_NETLINK;
@@ -89,8 +96,8 @@ static void nlmon_setup(struct net_device *dev)
 	dev->ethtool_ops = &nlmon_ethtool_ops;
 	dev->needs_free_netdev = true;
 
-	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
-			NETIF_F_HIGHDMA | NETIF_F_LLTX;
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_array(dev, &nlmon_feature_set);
 	dev->flags = IFF_NOARP;
 
 	/* That's rather a softlimit here, which, of course,
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index c3d42062559d..7b1c1e724c43 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -17,6 +17,7 @@
 #include <linux/idr.h>
 #include <linux/fs.h>
 #include <linux/uio.h>
+#include <linux/netdev_features_helper.h>
 
 #include <net/net_namespace.h>
 #include <net/rtnetlink.h>
@@ -116,8 +117,13 @@ struct major_info {
 
 static const struct proto_ops tap_socket_ops;
 
-#define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
-#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG | NETIF_F_FRAGLIST)
+static DECLARE_NETDEV_FEATURE_SET(tap_rx_offload_feature_set,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_LRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(tap_feature_set,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT);
 
 static struct tap_dev *tap_dev_get_rcu(const struct net_device *dev)
 {
@@ -321,7 +327,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
 	struct net_device *dev = skb->dev;
 	struct tap_dev *tap;
 	struct tap_queue *q;
-	netdev_features_t features = TAP_FEATURES;
+	netdev_features_t features;
 	enum skb_drop_reason drop_reason;
 
 	tap = tap_dev_get_rcu(dev);
@@ -334,6 +340,8 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
 
 	skb_push(skb, ETH_HLEN);
 
+	netdev_features_zero(&features);
+	netdev_features_set_array(&tap_feature_set, &features);
 	/* Apply the forward feature mask so that we perform segmentation
 	 * according to users wishes.  This only works if VNET_HDR is
 	 * enabled.
@@ -966,9 +974,9 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
 	 * user-space will not receive TSO frames.
 	 */
 	if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6))
-		features |= RX_OFFLOADS;
+		netdev_features_set_array(&tap_rx_offload_feature_set, &features);
 	else
-		features &= ~RX_OFFLOADS;
+		netdev_features_clear_array(&tap_rx_offload_feature_set, &features);
 
 	/* tap_features are the same as features on tun/tap and
 	 * reflect user expectations.
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index aac133a1e27a..452d414dff62 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -15,6 +15,7 @@
 #include <linux/ctype.h>
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/netpoll.h>
 #include <linux/if_vlan.h>
 #include <linux/if_arp.h>
@@ -980,12 +981,20 @@ static void team_port_disable(struct team *team,
 	team_lower_state_changed(port);
 }
 
-#define TEAM_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
-			    NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
-			    NETIF_F_HIGHDMA | NETIF_F_LRO)
-
-#define TEAM_ENC_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
-				 NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE)
+static DECLARE_NETDEV_FEATURE_SET(team_vlan_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_LRO_BIT);
+static DECLARE_NETDEV_FEATURE_SET(team_enc_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static netdev_features_t team_vlan_features __ro_after_init;
+static netdev_features_t team_enc_features __ro_after_init;
+#define TEAM_VLAN_FEATURES	team_vlan_features
+#define TEAM_ENC_FEATURES	team_enc_features
 
 static void __team_compute_features(struct team *team)
 {
@@ -2875,6 +2884,13 @@ static void team_nl_fini(void)
 	genl_unregister_family(&team_nl_family);
 }
 
+static void __init team_features_init(void)
+{
+	team_vlan_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&team_vlan_feature_set, &team_vlan_features);
+	team_enc_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&team_enc_feature_set, &team_enc_features);
+}
 
 /******************
  * Change checkers
@@ -3031,7 +3047,6 @@ static struct notifier_block team_notifier_block __read_mostly = {
 	.notifier_call = team_device_event,
 };
 
-
 /***********************
  * Module init and exit
  ***********************/
@@ -3050,6 +3065,8 @@ static int __init team_module_init(void)
 	if (err)
 		goto err_nl_init;
 
+	team_features_init();
+
 	return 0;
 
 err_nl_init:
diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c
index ff5d0e98a088..baed53386606 100644
--- a/drivers/net/thunderbolt.c
+++ b/drivers/net/thunderbolt.c
@@ -14,6 +14,7 @@
 #include <linux/jhash.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/rtnetlink.h>
 #include <linux/sizes.h>
 #include <linux/thunderbolt.h>
@@ -1217,6 +1218,12 @@ static void tbnet_generate_mac(struct net_device *dev)
 	eth_hw_addr_set(dev, addr);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(tbnet_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT);
+
 static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id)
 {
 	struct tb_xdomain *xd = tb_service_parent(svc);
@@ -1259,8 +1266,8 @@ static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id)
 	 * we need to announce support for most of the offloading
 	 * features here.
 	 */
-	dev->hw_features = NETIF_F_SG | NETIF_F_ALL_TSO | NETIF_F_GRO |
-			   NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	dev->hw_features = NETIF_F_ALL_TSO;
+	netdev_hw_features_set_array(dev, &tbnet_hw_feature_set);
 	dev->features = dev->hw_features | NETIF_F_HIGHDMA;
 	dev->hard_header_len += sizeof(struct thunderbolt_ip_frame_header);
 
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 259b2b84b2b3..d34d930a3029 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -43,6 +43,7 @@
 #include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/miscdevice.h>
 #include <linux/ethtool.h>
@@ -171,6 +172,19 @@ struct tun_prog {
 	struct bpf_prog *prog;
 };
 
+static netdev_features_t tun_user_features __ro_after_init;
+static DECLARE_NETDEV_FEATURE_SET(tun_user_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(tun_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_STAG_TX_BIT);
+#define TUN_USER_FEATURES	tun_user_features
+
 /* Since the socket were moved to tun_file, to preserve the behavior of persist
  * device, socket filter, sndbuf and vnet header size were restore when the
  * file were attached to a persist device.
@@ -184,8 +198,6 @@ struct tun_struct {
 
 	struct net_device	*dev;
 	netdev_features_t	set_features;
-#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
-			  NETIF_F_TSO6)
 
 	int			align;
 	int			vnet_hdr_sz;
@@ -989,9 +1001,8 @@ static int tun_net_init(struct net_device *dev)
 
 	tun_flow_init(tun);
 
-	dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
-			   TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
-			   NETIF_F_HW_VLAN_STAG_TX;
+	dev->hw_features = TUN_USER_FEATURES;
+	netdev_hw_features_set_array(dev, &tun_hw_feature_set);
 	dev->features = dev->hw_features | NETIF_F_LLTX;
 	dev->vlan_features = dev->features &
 			     ~(NETIF_F_HW_VLAN_CTAG_TX |
@@ -3668,6 +3679,11 @@ static struct notifier_block tun_notifier_block __read_mostly = {
 	.notifier_call	= tun_device_event,
 };
 
+static void __init tun_features_init(void)
+{
+	netdev_features_set_array(&tun_user_feature_set, &tun_user_features);
+}
+
 static int __init tun_init(void)
 {
 	int ret = 0;
@@ -3692,6 +3708,8 @@ static int __init tun_init(void)
 		goto err_notifier;
 	}
 
+	tun_features_init();
+
 	return  0;
 
 err_notifier:
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 3020e81159d0..d55be54264f8 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -9,6 +9,7 @@
 
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
@@ -22,6 +23,31 @@
 
 #define DRIVER_NAME "aqc111"
 
+/* Feature. ********************************************/
+DECLARE_NETDEV_FEATURE_SET(aq_support_feature_set,
+			   NETIF_F_SG_BIT,
+			   NETIF_F_IP_CSUM_BIT,
+			   NETIF_F_IPV6_CSUM_BIT,
+			   NETIF_F_RXCSUM_BIT,
+			   NETIF_F_TSO_BIT,
+			   NETIF_F_HW_VLAN_CTAG_TX_BIT,
+			   NETIF_F_HW_VLAN_CTAG_RX_BIT);
+
+DECLARE_NETDEV_FEATURE_SET(aq_support_hw_feature_set,
+			   NETIF_F_SG_BIT,
+			   NETIF_F_IP_CSUM_BIT,
+			   NETIF_F_IPV6_CSUM_BIT,
+			   NETIF_F_RXCSUM_BIT,
+			   NETIF_F_TSO_BIT,
+			   NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+
+DECLARE_NETDEV_FEATURE_SET(aq_support_vlan_feature_set,
+			   NETIF_F_SG_BIT,
+			   NETIF_F_IP_CSUM_BIT,
+			   NETIF_F_IPV6_CSUM_BIT,
+			   NETIF_F_RXCSUM_BIT,
+			   NETIF_F_TSO_BIT);
+
 static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
 				u16 index, u16 size, void *data)
 {
@@ -731,9 +757,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	if (usb_device_no_sg_constraint(dev->udev))
 		dev->can_dma_sg = 1;
 
-	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
-	dev->net->features |= AQ_SUPPORT_FEATURE;
-	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
+	netdev_hw_features_set_array(dev->net, &aq_support_hw_feature_set);
+	netdev_active_features_set_array(dev->net, &aq_support_feature_set);
+	netdev_vlan_features_set_array(dev->net, &aq_support_vlan_feature_set);
 
 	netif_set_tso_max_size(dev->net, 65535);
 
@@ -996,9 +1022,9 @@ static int aqc111_reset(struct usbnet *dev)
 	if (usb_device_no_sg_constraint(dev->udev))
 		dev->can_dma_sg = 1;
 
-	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
-	dev->net->features |= AQ_SUPPORT_FEATURE;
-	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
+	netdev_hw_features_set_array(dev->net, &aq_support_hw_feature_set);
+	netdev_active_features_set_array(dev->net, &aq_support_feature_set);
+	netdev_vlan_features_set_array(dev->net, &aq_support_vlan_feature_set);
 
 	/* Power up ethernet PHY */
 	aqc111_data->phy_cfg = AQ_PHY_POWER_EN;
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index b562db4da337..ebc23df8295f 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -24,20 +24,6 @@
 #define AQ_USB_PHY_SET_TIMEOUT		10000
 #define AQ_USB_SET_TIMEOUT		4000
 
-/* Feature. ********************************************/
-#define AQ_SUPPORT_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
-				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
-				 NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX |\
-				 NETIF_F_HW_VLAN_CTAG_RX)
-
-#define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
-				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
-				 NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_FILTER)
-
-#define AQ_SUPPORT_VLAN_FEATURE (NETIF_F_SG | NETIF_F_IP_CSUM |\
-				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
-				 NETIF_F_TSO)
-
 /* SFR Reg. ********************************************/
 
 #define SFR_GENERAL_STATUS		0x03
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 0ad468a00064..67c4bce50df2 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -13,6 +13,7 @@
 #include <linux/usb/usbnet.h>
 #include <uapi/linux/mdio.h>
 #include <linux/mdio.h>
+#include <linux/netdev_features_helper.h>
 
 #define AX88179_PHY_ID				0x03
 #define AX_EEPROM_LEN				0x100
@@ -1265,6 +1266,13 @@ static void ax88179_get_mac_addr(struct usbnet *dev)
 			  dev->net->dev_addr);
 }
 
+DECLARE_NETDEV_FEATURE_SET(ax88179_feature_set,
+			   NETIF_F_SG_BIT,
+			   NETIF_F_IP_CSUM_BIT,
+			   NETIF_F_IPV6_CSUM_BIT,
+			   NETIF_F_RXCSUM_BIT,
+			   NETIF_F_TSO_BIT);
+
 static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	struct ax88179_data *ax179_data;
@@ -1291,8 +1299,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
 	dev->mii.phy_id = 0x03;
 	dev->mii.supports_gmii = 1;
 
-	dev->net->features |= NETIF_F_SG | NETIF_F_IP_CSUM |
-			      NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO;
+	netdev_active_features_set_array(dev->net, &ax88179_feature_set);
 
 	dev->net->hw_features |= dev->net->features;
 
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 3226ab33afae..b3c01bee9504 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/microchipphy.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/phy_fixed.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
@@ -3430,6 +3431,11 @@ lan78xx_start_xmit(struct sk_buff *skb, struct net_device *net)
 	return NETDEV_TX_OK;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(lan78xx_tso_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_SG_BIT);
+
 static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
 {
 	struct lan78xx_priv *pdata = NULL;
@@ -3465,7 +3471,7 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
 		dev->net->features |= NETIF_F_RXCSUM;
 
 	if (DEFAULT_TSO_CSUM_ENABLE)
-		dev->net->features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG;
+		netdev_active_features_set_array(dev->net, &lan78xx_tso_feature_set);
 
 	if (DEFAULT_VLAN_RX_OFFLOAD)
 		dev->net->features |= NETIF_F_HW_VLAN_CTAG_RX;
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 0f6efaabaa32..5e11eaab71f5 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
@@ -2095,6 +2096,11 @@ static struct tx_agg *r8152_get_tx_agg(struct r8152 *tp)
 	return agg;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(r8152_csum_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO6_BIT);
+
 /* r8152_csum_workaround()
  * The hw limits the value of the transport offset. When the offset is out of
  * range, calculate the checksum by sw.
@@ -2107,7 +2113,7 @@ static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb,
 		struct sk_buff *segs, *seg, *next;
 		struct sk_buff_head seg_list;
 
-		features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
+		netdev_features_clear_array(&r8152_csum_feature_set, &features);
 		segs = skb_gso_segment(skb, features);
 		if (IS_ERR(segs) || !segs)
 			goto drop;
@@ -9576,6 +9582,35 @@ u8 rtl8152_get_version(struct usb_interface *intf)
 }
 EXPORT_SYMBOL_GPL(rtl8152_get_version);
 
+static DECLARE_NETDEV_FEATURE_SET(r8152_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(r8152_hw_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+static DECLARE_NETDEV_FEATURE_SET(r8152_vlan_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static bool rtl8152_supports_lenovo_macpassthru(struct usb_device *udev)
 {
 	int parent_vendor_id = le16_to_cpu(udev->parent->descriptor.idVendor);
@@ -9662,17 +9697,11 @@ static int rtl8152_probe(struct usb_interface *intf,
 	netdev->netdev_ops = &rtl8152_netdev_ops;
 	netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
 
-	netdev->features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
-			    NETIF_F_TSO | NETIF_F_FRAGLIST | NETIF_F_IPV6_CSUM |
-			    NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_VLAN_CTAG_TX;
-	netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
-			      NETIF_F_TSO | NETIF_F_FRAGLIST |
-			      NETIF_F_IPV6_CSUM | NETIF_F_TSO6 |
-			      NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX;
-	netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-				NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
-				NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+	netdev_active_features_set_array(netdev, &r8152_feature_set);
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &r8152_hw_feature_set);
+	netdev_vlan_features_zero(netdev);
+	netdev_vlan_features_set_array(netdev, &r8152_vlan_feature_set);
 
 	if (tp->version == RTL_VER_01) {
 		netdev->features &= ~NETIF_F_RXCSUM;
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 95de452ff4da..34b79291e159 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/kmod.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -1445,6 +1446,11 @@ static const struct net_device_ops smsc75xx_netdev_ops = {
 	.ndo_set_features	= smsc75xx_set_features,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(smsc75xx_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	struct smsc75xx_priv *pdata = NULL;
@@ -1478,8 +1484,8 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
 	if (DEFAULT_RX_CSUM_ENABLE)
 		dev->net->features |= NETIF_F_RXCSUM;
 
-	dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-				NETIF_F_RXCSUM;
+	netdev_hw_features_zero(dev->net);
+	netdev_hw_features_set_array(dev->net, &smsc75xx_hw_feature_set);
 
 	ret = smsc75xx_wait_ready(dev, 0);
 	if (ret < 0) {
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 2cb833b3006a..6de15832dafe 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/slab.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
@@ -1620,14 +1621,22 @@ static const struct net_device_ops veth_netdev_ops = {
 	.ndo_get_peer_dev	= veth_peer_dev,
 };
 
-#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HW_CSUM | \
-		       NETIF_F_RXCSUM | NETIF_F_SCTP_CRC | NETIF_F_HIGHDMA | \
-		       NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL | \
-		       NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | \
-		       NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_VLAN_STAG_RX )
+static DECLARE_NETDEV_FEATURE_SET(veth_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_STAG_TX_BIT,
+				  NETIF_F_HW_VLAN_STAG_RX_BIT);
 
 static void veth_setup(struct net_device *dev)
 {
+	netdev_features_t veth_features;
+
 	ether_setup(dev);
 
 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
@@ -1637,8 +1646,10 @@ static void veth_setup(struct net_device *dev)
 
 	dev->netdev_ops = &veth_netdev_ops;
 	dev->ethtool_ops = &veth_ethtool_ops;
+	veth_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev_features_set_array(&veth_feature_set, &veth_features);
 	dev->features |= NETIF_F_LLTX;
-	dev->features |= VETH_FEATURES;
+	dev->features |= veth_features;
 	dev->vlan_features = dev->features &
 			     ~(NETIF_F_HW_VLAN_CTAG_TX |
 			       NETIF_F_HW_VLAN_STAG_TX |
@@ -1648,8 +1659,8 @@ static void veth_setup(struct net_device *dev)
 	dev->priv_destructor = veth_dev_free;
 	dev->max_mtu = ETH_MAX_MTU;
 
-	dev->hw_features = VETH_FEATURES;
-	dev->hw_enc_features = VETH_FEATURES;
+	dev->hw_features = veth_features;
+	dev->hw_enc_features = veth_features;
 	dev->mpls_features = NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE;
 	netif_set_tso_max_size(dev, GSO_MAX_SIZE);
 }
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 53b3b241e027..b2f3fb5a29d5 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3301,26 +3301,42 @@ vmxnet3_change_mtu(struct net_device *netdev, int new_mtu)
 	return err;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(vmxnet3_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(vmxnet3_hw_enc_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 static void
 vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
 
-	netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
-		NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
-		NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_TSO | NETIF_F_TSO6 |
-		NETIF_F_LRO | NETIF_F_HIGHDMA;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &vmxnet3_hw_feature_set);
 
 	if (VMXNET3_VERSION_GE_4(adapter)) {
 		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
 				NETIF_F_GSO_UDP_TUNNEL_CSUM;
-
-		netdev->hw_enc_features = NETIF_F_SG | NETIF_F_RXCSUM |
-			NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
-			NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_TSO | NETIF_F_TSO6 |
-			NETIF_F_LRO | NETIF_F_GSO_UDP_TUNNEL |
-			NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_hw_enc_features_zero(netdev);
+		netdev_hw_enc_features_set_array(netdev,
+						 &vmxnet3_hw_enc_feature_set);
 	}
 
 	if (VMXNET3_VERSION_GE_7(adapter)) {
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index e2034adc3a1a..25b3243a9630 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -298,15 +298,35 @@ netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
 	return features;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(vmxnet3_hw_enc_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_LRO_BIT);
+
+static DECLARE_NETDEV_FEATURE_SET(vmxnet3_hw_enc_feature_set2,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_BIT,
+				  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+
 static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_features_t features)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
 	if (VMXNET3_VERSION_GE_4(adapter)) {
-		netdev->hw_enc_features |= NETIF_F_SG | NETIF_F_RXCSUM |
-			NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
-			NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_TSO | NETIF_F_TSO6 |
-			NETIF_F_LRO;
+		netdev_hw_enc_features_set_array(netdev,
+						 &vmxnet3_hw_enc_feature_set);
 		if (features & NETIF_F_GSO_UDP_TUNNEL)
 			netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
 		if (features & NETIF_F_GSO_UDP_TUNNEL_CSUM)
@@ -364,11 +384,8 @@ static void vmxnet3_disable_encap_offloads(struct net_device *netdev)
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
 	if (VMXNET3_VERSION_GE_4(adapter)) {
-		netdev->hw_enc_features &= ~(NETIF_F_SG | NETIF_F_RXCSUM |
-			NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
-			NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_TSO | NETIF_F_TSO6 |
-			NETIF_F_LRO | NETIF_F_GSO_UDP_TUNNEL |
-			NETIF_F_GSO_UDP_TUNNEL_CSUM);
+		netdev_hw_enc_features_clear_array(netdev,
+						   &vmxnet3_hw_enc_feature_set2);
 	}
 	if (VMXNET3_VERSION_GE_7(adapter)) {
 		unsigned long flags;
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 3367db23aa13..d42f997efa4a 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -31,6 +31,7 @@
 #include <linux/ethtool.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/compiler.h>
 #include <linux/slab.h>
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 5df7a0abc39d..7ad145f832cc 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ip.h>
 #include <linux/init.h>
@@ -1664,6 +1665,14 @@ static int vrf_add_fib_rules(const struct net_device *dev)
 	return err;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(vrf_offload_feature_set,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SCTP_CRC_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 static void vrf_setup(struct net_device *dev)
 {
 	ether_setup(dev);
@@ -1688,8 +1697,7 @@ static void vrf_setup(struct net_device *dev)
 
 	/* enable offload features */
 	dev->features   |= NETIF_F_GSO_SOFTWARE;
-	dev->features   |= NETIF_F_RXCSUM | NETIF_F_HW_CSUM | NETIF_F_SCTP_CRC;
-	dev->features   |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA;
+	netdev_active_features_set_array(dev, &vrf_offload_feature_set);
 
 	dev->hw_features = dev->features;
 	dev->hw_enc_features = dev->features;
diff --git a/drivers/net/vsockmon.c b/drivers/net/vsockmon.c
index b1bb1b04b664..a5cee59ea872 100644
--- a/drivers/net/vsockmon.c
+++ b/drivers/net/vsockmon.c
@@ -3,6 +3,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
+#include <linux/netdev_features_helper.h>
 #include <net/rtnetlink.h>
 #include <net/sock.h>
 #include <net/af_vsock.h>
@@ -97,6 +98,12 @@ static const struct ethtool_ops vsockmon_ethtool_ops = {
 	.get_link = always_on,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(vsockmon_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_LLTX_BIT);
+
 static void vsockmon_setup(struct net_device *dev)
 {
 	dev->type = ARPHRD_VSOCKMON;
@@ -106,8 +113,8 @@ static void vsockmon_setup(struct net_device *dev)
 	dev->ethtool_ops = &vsockmon_ethtool_ops;
 	dev->needs_free_netdev = true;
 
-	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
-			NETIF_F_HIGHDMA | NETIF_F_LLTX;
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_array(dev, &vsockmon_feature_set);
 
 	dev->flags = IFF_NOARP;
 
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 90811ab851fd..0076b12b6bae 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -15,6 +15,7 @@
 #include <linux/igmp.h>
 #include <linux/if_ether.h>
 #include <linux/ethtool.h>
+#include <linux/netdev_features_helper.h>
 #include <net/arp.h>
 #include <net/ndisc.h>
 #include <net/gro.h>
@@ -3153,6 +3154,18 @@ static void vxlan_offload_rx_ports(struct net_device *dev, bool push)
 	spin_unlock(&vn->sock_lock);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(vxlan_feature_set,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(vxlan_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 /* Initialize the device structure. */
 static void vxlan_setup(struct net_device *dev)
 {
@@ -3165,14 +3178,11 @@ static void vxlan_setup(struct net_device *dev)
 	dev->needs_free_netdev = true;
 	SET_NETDEV_DEVTYPE(dev, &vxlan_type);
 
-	dev->features	|= NETIF_F_LLTX;
-	dev->features	|= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST;
-	dev->features   |= NETIF_F_RXCSUM;
+	netdev_active_features_set_array(dev, &vxlan_feature_set);
 	dev->features   |= NETIF_F_GSO_SOFTWARE;
 
 	dev->vlan_features = dev->features;
-	dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST;
-	dev->hw_features |= NETIF_F_RXCSUM;
+	netdev_hw_features_set_array(dev, &vxlan_hw_feature_set);
 	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
 	netif_keep_dst(dev);
 	dev->priv_flags |= IFF_NO_QUEUE | IFF_CHANGE_PROTO_DOWN;
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index aa9a7a5970fd..aeed694110d4 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -15,6 +15,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/inetdevice.h>
 #include <linux/if_arp.h>
 #include <linux/icmp.h>
@@ -271,14 +272,19 @@ static void wg_destruct(struct net_device *dev)
 
 static const struct device_type device_type = { .name = KBUILD_MODNAME };
 
+static DECLARE_NETDEV_FEATURE_SET(wg_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+
 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 |
-				    NETIF_F_SG | NETIF_F_GSO |
-				    NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA };
 	const int overhead = MESSAGE_MINIMUM_LENGTH + sizeof(struct udphdr) +
 			     max(sizeof(struct ipv6hdr), sizeof(struct iphdr));
+	netdev_features_t wg_netdev_features;
 
 	dev->netdev_ops = &netdev_ops;
 	dev->header_ops = &ip_tunnel_header_ops;
@@ -290,9 +296,11 @@ 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;
+	wg_netdev_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&wg_feature_set, &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/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 87a88f26233e..c2012c4e0084 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/rtnetlink.h>
 #include "wil6210.h"
 #include "txrx.h"
@@ -294,6 +295,14 @@ static u8 wil_vif_find_free_mid(struct wil6210_priv *wil)
 	return U8_MAX;
 }
 
+static DECLARE_NETDEV_FEATURE_SET(wil_hw_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 struct wil6210_vif *
 wil_vif_alloc(struct wil6210_priv *wil, const char *name,
 	      unsigned char name_assign_type, enum nl80211_iftype iftype)
@@ -335,9 +344,8 @@ wil_vif_alloc(struct wil6210_priv *wil, const char *name,
 	ndev->netdev_ops = &wil_netdev_ops;
 	wil_set_ethtoolops(ndev);
 	ndev->ieee80211_ptr = wdev;
-	ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
-			    NETIF_F_SG | NETIF_F_GRO |
-			    NETIF_F_TSO | NETIF_F_TSO6;
+	netdev_hw_features_zero(ndev);
+	netdev_hw_features_set_array(ndev, &wil_hw_feature_set);
 
 	ndev->features |= ndev->hw_features;
 	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index fb32ae82d9b0..989328168e1c 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -33,6 +33,7 @@
 #include <linux/kthread.h>
 #include <linux/sched/task.h>
 #include <linux/ethtool.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
 #include <linux/vmalloc.h>
@@ -476,6 +477,14 @@ static const struct net_device_ops xenvif_netdev_ops = {
 	.ndo_validate_addr   = eth_validate_addr,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(xenvif_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_FRAGLIST_BIT);
+
 struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 			    unsigned int handle)
 {
@@ -522,9 +531,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 	INIT_LIST_HEAD(&vif->fe_mcast_addr);
 
 	dev->netdev_ops	= &xenvif_netdev_ops;
-	dev->hw_features = NETIF_F_SG |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_FRAGLIST;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_array(dev, &xenvif_hw_feature_set);
 	dev->features = dev->hw_features | NETIF_F_RXCSUM;
 	dev->ethtool_ops = &xenvif_ethtool_ops;
 
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 27a11cc08c61..d4833794cec0 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -1703,6 +1704,16 @@ static void xennet_free_netdev(struct net_device *netdev)
 	free_netdev(netdev);
 }
 
+static DECLARE_NETDEV_FEATURE_SET(xennet_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_GSO_ROBUST_BIT);
+static DECLARE_NETDEV_FEATURE_SET(xennet_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
 static struct net_device *xennet_create_dev(struct xenbus_device *dev)
 {
 	int err;
@@ -1728,11 +1739,10 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
 
 	netdev->netdev_ops	= &xennet_netdev_ops;
 
-	netdev->features        = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
-				  NETIF_F_GSO_ROBUST;
-	netdev->hw_features	= NETIF_F_SG |
-				  NETIF_F_IPV6_CSUM |
-				  NETIF_F_TSO | NETIF_F_TSO6;
+	netdev_active_features_zero(netdev);
+	netdev_active_features_set_array(netdev, &xennet_feature_set);
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_array(netdev, &xennet_hw_feature_set);
 
 	/*
          * Assume that all hw features are available for now. This set
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 8d44bce0477a..8628599ed692 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1854,6 +1854,11 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
 	.ndo_neigh_setup	= qeth_l3_neigh_setup,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(qeth_l3_feature_set,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT);
+
 static int qeth_l3_setup_netdev(struct qeth_card *card)
 {
 	struct net_device *dev = card->dev;
@@ -1868,10 +1873,10 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 
 		if (!IS_VM_NIC(card)) {
 			card->dev->features |= NETIF_F_SG;
-			card->dev->hw_features |= NETIF_F_TSO |
-				NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
-			card->dev->vlan_features |= NETIF_F_TSO |
-				NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
+			netdev_hw_features_set_array(card->dev,
+						     &qeth_l3_feature_set);
+			netdev_vlan_features_set_array(card->dev,
+						       &qeth_l3_feature_set);
 		}
 
 		if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index 6cd7fc9589c3..a3576a11443d 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -31,6 +31,7 @@
 #include <linux/if_arp.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/if_vlan.h>
@@ -4533,6 +4534,16 @@ static void qlge_timer(struct timer_list *t)
 
 static const struct devlink_ops qlge_devlink_ops;
 
+static DECLARE_NETDEV_FEATURE_SET(qlge_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO_ECN_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_RXCSUM_BIT);
+
 static int qlge_probe(struct pci_dev *pdev,
 		      const struct pci_device_id *pci_entry)
 {
@@ -4567,14 +4578,8 @@ static int qlge_probe(struct pci_dev *pdev,
 		goto netdev_free;
 
 	SET_NETDEV_DEV(ndev, &pdev->dev);
-	ndev->hw_features = NETIF_F_SG |
-		NETIF_F_IP_CSUM |
-		NETIF_F_TSO |
-		NETIF_F_TSO_ECN |
-		NETIF_F_HW_VLAN_CTAG_TX |
-		NETIF_F_HW_VLAN_CTAG_RX |
-		NETIF_F_HW_VLAN_CTAG_FILTER |
-		NETIF_F_RXCSUM;
+	netdev_hw_features_zero(ndev);
+	netdev_hw_features_set_array(ndev, &qlge_hw_feature_set);
 	ndev->features = ndev->hw_features;
 	ndev->vlan_features = ndev->hw_features;
 	/* vlan gets same features (except vlan filter) */
diff --git a/include/net/bonding.h b/include/net/bonding.h
index 6e78d657aa05..cfad04d40bf2 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -89,10 +89,9 @@
 #define bond_for_each_slave_rcu(bond, pos, iter) \
 	netdev_for_each_lower_private_rcu((bond)->dev, pos, iter)
 
-#define BOND_XFRM_FEATURES (NETIF_F_HW_ESP | NETIF_F_HW_ESP_TX_CSUM | \
-			    NETIF_F_GSO_ESP)
+#define BOND_XFRM_FEATURES netdev_xfrm_features
 
-#define BOND_TLS_FEATURES (NETIF_F_HW_TLS_TX | NETIF_F_HW_TLS_RX)
+#define BOND_TLS_FEATURES netdev_tls_features
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 extern atomic_t netpoll_block_tx;
diff --git a/include/net/net_failover.h b/include/net/net_failover.h
index b12a1c469d1c..781d1de8a190 100644
--- a/include/net/net_failover.h
+++ b/include/net/net_failover.h
@@ -30,11 +30,7 @@ struct net_failover_info {
 struct failover *net_failover_create(struct net_device *standby_dev);
 void net_failover_destroy(struct failover *failover);
 
-#define FAILOVER_VLAN_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
-				 NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
-				 NETIF_F_HIGHDMA | NETIF_F_LRO)
-
-#define FAILOVER_ENC_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
-				 NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
+#define FAILOVER_VLAN_FEATURES	failover_vlan_features
+#define FAILOVER_ENC_FEATURES	failover_enc_features
 
 #endif /* _NET_FAILOVER_H */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 64ca07daf4ee..75d12ff0d146 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -550,6 +550,13 @@ static struct device_type vlan_type = {
 
 static const struct net_device_ops vlan_netdev_ops;
 
+static DECLARE_NETDEV_FEATURE_SET(vlan_hw_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_SCTP_CRC_BIT);
+
 static int vlan_dev_init(struct net_device *dev)
 {
 	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
@@ -567,11 +574,9 @@ static int vlan_dev_init(struct net_device *dev)
 	if (vlan->flags & VLAN_FLAG_BRIDGE_BINDING)
 		dev->state |= (1 << __LINK_STATE_NOCARRIER);
 
-	dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG |
-			   NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE |
-			   NETIF_F_GSO_ENCAP_ALL |
-			   NETIF_F_HIGHDMA | NETIF_F_SCTP_CRC |
-			   NETIF_F_ALL_FCOE;
+	dev->hw_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	dev->hw_features |= NETIF_F_ALL_FCOE;
+	netdev_hw_features_set_array(dev, &vlan_hw_feature_set);
 
 	dev->features |= dev->hw_features | NETIF_F_LLTX;
 	netif_inherit_tso_max(dev, real_dev);
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 0f5c0679b55a..1a958b279489 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -24,6 +24,7 @@
 #include <linux/list.h>
 #include <linux/lockdep.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/netlink.h>
 #include <linux/percpu.h>
 #include <linux/random.h>
@@ -992,6 +993,11 @@ static void batadv_softif_free(struct net_device *dev)
 	rcu_barrier();
 }
 
+static DECLARE_NETDEV_FEATURE_SET(batadv_feature_set,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_NETNS_LOCAL_BIT,
+				  NETIF_F_LLTX_BIT);
+
 /**
  * batadv_softif_init_early() - early stage initialization of soft interface
  * @dev: registered network device to modify
@@ -1003,8 +1009,7 @@ static void batadv_softif_init_early(struct net_device *dev)
 	dev->netdev_ops = &batadv_netdev_ops;
 	dev->needs_free_netdev = true;
 	dev->priv_destructor = batadv_softif_free;
-	dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_NETNS_LOCAL;
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_features_set_array(dev, &batadv_feature_set);
 	dev->priv_flags |= IFF_NO_QUEUE;
 
 	/* can't call min_mtu, because the needed variables
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 58a4f70e01e3..8f78e6d297b8 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -9,6 +9,7 @@
 
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/netpoll.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -18,8 +19,11 @@
 #include <linux/uaccess.h>
 #include "br_private.h"
 
-#define COMMON_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | \
-			 NETIF_F_GSO_MASK | NETIF_F_HW_CSUM)
+static DECLARE_NETDEV_FEATURE_SET(br_common_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_CSUM_BIT);
 
 const struct nf_br_ops __rcu *nf_br_ops __read_mostly;
 EXPORT_SYMBOL_GPL(nf_br_ops);
@@ -479,9 +483,16 @@ static struct device_type br_type = {
 	.name	= "bridge",
 };
 
+static DECLARE_NETDEV_FEATURE_SET(br_feature_set,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_NETNS_LOCAL_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_STAG_TX_BIT);
+
 void br_dev_setup(struct net_device *dev)
 {
 	struct net_bridge *br = netdev_priv(dev);
+	netdev_features_t common_features;
 
 	eth_hw_addr_random(dev);
 	ether_setup(dev);
@@ -492,11 +503,13 @@ void br_dev_setup(struct net_device *dev)
 	SET_NETDEV_DEVTYPE(dev, &br_type);
 	dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE;
 
-	dev->features = COMMON_FEATURES | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL |
-			NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
-	dev->hw_features = COMMON_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
+	common_features = NETIF_F_GSO_MASK;
+	netdev_features_set_array(&br_common_feature_set, &common_features);
+	dev->features = common_features;
+	netdev_active_features_set_array(dev, &br_feature_set);
+	dev->hw_features = common_features | NETIF_F_HW_VLAN_CTAG_TX |
 			   NETIF_F_HW_VLAN_STAG_TX;
-	dev->vlan_features = COMMON_FEATURES;
+	dev->vlan_features = common_features;
 
 	br->dev = dev;
 	spin_lock_init(&br->lock);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 6a7308de192d..2ed9277a873e 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)
+
+static 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(&eth_all_features);
+	netdev_features_set_array(&ethtool_all_feature_set, &eth_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;
 
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index 6ffef47e9be5..ab1c4dfa25b7 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
@@ -435,6 +436,13 @@ static struct hsr_proto_ops prp_ops = {
 	.update_san_info = prp_update_san_info,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(hsr_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT);
+
 void hsr_dev_setup(struct net_device *dev)
 {
 	eth_hw_addr_random(dev);
@@ -448,9 +456,8 @@ void hsr_dev_setup(struct net_device *dev)
 
 	dev->needs_free_netdev = true;
 
-	dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
-			   NETIF_F_GSO_MASK | NETIF_F_HW_CSUM |
-			   NETIF_F_HW_VLAN_CTAG_TX;
+	dev->hw_features = NETIF_F_GSO_MASK;
+	netdev_hw_features_set_array(dev, &hsr_hw_feature_set);
 
 	dev->features = dev->hw_features;
 
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 5c58e21f724e..fbdf3713245f 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -15,6 +15,7 @@
 #include <linux/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/in.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
@@ -935,10 +936,11 @@ static const struct net_device_ops ipgre_netdev_ops = {
 	.ndo_tunnel_ctl		= ipgre_tunnel_ctl,
 };
 
-#define GRE_FEATURES (NETIF_F_SG |		\
-		      NETIF_F_FRAGLIST |	\
-		      NETIF_F_HIGHDMA |		\
-		      NETIF_F_HW_CSUM)
+static DECLARE_NETDEV_FEATURE_SET(gre_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_CSUM_BIT);
 
 static void ipgre_tunnel_setup(struct net_device *dev)
 {
@@ -959,8 +961,9 @@ static void __gre_tunnel_init(struct net_device *dev)
 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
 	dev->needed_headroom = tunnel->hlen + sizeof(tunnel->parms.iph);
 
-	dev->features		|= GRE_FEATURES | NETIF_F_LLTX;
-	dev->hw_features	|= GRE_FEATURES;
+	netdev_active_features_set_array(dev, &gre_feature_set);
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
+	netdev_hw_features_set_array(dev, &gre_feature_set);
 
 	flags = tunnel->parms.o_flags;
 
@@ -1300,8 +1303,8 @@ static int erspan_tunnel_init(struct net_device *dev)
 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
 		       erspan_hdr_len(tunnel->erspan_ver);
 
-	dev->features		|= GRE_FEATURES;
-	dev->hw_features	|= GRE_FEATURES;
+	netdev_active_features_set_array(dev, &gre_feature_set);
+	netdev_hw_features_set_array(dev, &gre_feature_set);
 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
 	netif_keep_dst(dev);
 
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 123ea63a04cb..66b2deb4ddff 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -94,6 +94,7 @@
 #include <linux/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/in.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
@@ -354,14 +355,16 @@ static const struct net_device_ops ipip_netdev_ops = {
 	.ndo_tunnel_ctl	= ipip_tunnel_ctl,
 };
 
-#define IPIP_FEATURES (NETIF_F_SG |		\
-		       NETIF_F_FRAGLIST |	\
-		       NETIF_F_HIGHDMA |	\
-		       NETIF_F_GSO_SOFTWARE |	\
-		       NETIF_F_HW_CSUM)
+static DECLARE_NETDEV_FEATURE_SET(ipip_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_CSUM_BIT);
 
 static void ipip_tunnel_setup(struct net_device *dev)
 {
+	netdev_features_t ipip_features;
+
 	dev->netdev_ops		= &ipip_netdev_ops;
 	dev->header_ops		= &ip_tunnel_header_ops;
 
@@ -371,8 +374,10 @@ static void ipip_tunnel_setup(struct net_device *dev)
 	dev->features		|= NETIF_F_LLTX;
 	netif_keep_dst(dev);
 
-	dev->features		|= IPIP_FEATURES;
-	dev->hw_features	|= IPIP_FEATURES;
+	ipip_features		= NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&ipip_feature_set, &ipip_features);
+	dev->features		|= ipip_features;
+	dev->hw_features	|= ipip_features;
 	ip_tunnel_setup(dev, ipip_net_id);
 }
 
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 80cb50d459e4..b91a001077af 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -15,6 +15,7 @@
 #include <linux/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/in.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
@@ -1464,18 +1465,20 @@ static void ip6gre_tunnel_setup(struct net_device *dev)
 	eth_random_addr(dev->perm_addr);
 }
 
-#define GRE6_FEATURES (NETIF_F_SG |		\
-		       NETIF_F_FRAGLIST |	\
-		       NETIF_F_HIGHDMA |	\
-		       NETIF_F_HW_CSUM)
+static DECLARE_NETDEV_FEATURE_SET(gre_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_CSUM_BIT);
 
 static void ip6gre_tnl_init_features(struct net_device *dev)
 {
 	struct ip6_tnl *nt = netdev_priv(dev);
 	__be16 flags;
 
-	dev->features		|= GRE6_FEATURES | NETIF_F_LLTX;
-	dev->hw_features	|= GRE6_FEATURES;
+	netdev_active_features_set_array(dev, &gre_feature_set);
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
+	netdev_hw_features_set_array(dev, &gre_feature_set);
 
 	flags = nt->parms.o_flags;
 
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 3fda5634578c..da8eccfd1849 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -27,6 +27,7 @@
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_arp.h>
 #include <linux/icmpv6.h>
 #include <linux/init.h>
@@ -1813,11 +1814,11 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
 	.ndo_get_iflink = ip6_tnl_get_iflink,
 };
 
-#define IPXIPX_FEATURES (NETIF_F_SG |		\
-			 NETIF_F_FRAGLIST |	\
-			 NETIF_F_HIGHDMA |	\
-			 NETIF_F_GSO_SOFTWARE |	\
-			 NETIF_F_HW_CSUM)
+static DECLARE_NETDEV_FEATURE_SET(ipxipx_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_CSUM_BIT);
 
 /**
  * ip6_tnl_dev_setup - setup virtual tunnel device
@@ -1829,6 +1830,8 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
 
 static void ip6_tnl_dev_setup(struct net_device *dev)
 {
+	netdev_features_t ipxipx_features;
+
 	dev->netdev_ops = &ip6_tnl_netdev_ops;
 	dev->header_ops = &ip_tunnel_header_ops;
 	dev->needs_free_netdev = true;
@@ -1840,8 +1843,10 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
 	dev->features |= NETIF_F_LLTX;
 	netif_keep_dst(dev);
 
-	dev->features		|= IPXIPX_FEATURES;
-	dev->hw_features	|= IPXIPX_FEATURES;
+	ipxipx_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&ipxipx_feature_set, &ipxipx_features);
+	dev->features		|= ipxipx_features;
+	dev->hw_features	|= ipxipx_features;
 
 	/* This perm addr will be used as interface identifier by IPv6 */
 	dev->addr_assign_type = NET_ADDR_RANDOM;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 6b73b7a5f175..9e4c02fd379c 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -24,6 +24,7 @@
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_arp.h>
 #include <linux/icmp.h>
 #include <linux/slab.h>
@@ -1407,16 +1408,17 @@ static void ipip6_dev_free(struct net_device *dev)
 	free_percpu(dev->tstats);
 }
 
-#define SIT_FEATURES (NETIF_F_SG	   | \
-		      NETIF_F_FRAGLIST	   | \
-		      NETIF_F_HIGHDMA	   | \
-		      NETIF_F_GSO_SOFTWARE | \
-		      NETIF_F_HW_CSUM)
+static DECLARE_NETDEV_FEATURE_SET(sit_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_CSUM_BIT);
 
 static void ipip6_tunnel_setup(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+	netdev_features_t sit_features;
 
 	dev->netdev_ops		= &ipip6_netdev_ops;
 	dev->header_ops		= &ip_tunnel_header_ops;
@@ -1430,9 +1432,11 @@ static void ipip6_tunnel_setup(struct net_device *dev)
 	dev->flags		= IFF_NOARP;
 	netif_keep_dst(dev);
 	dev->addr_len		= 4;
+	sit_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&sit_feature_set, &sit_features);
 	dev->features		|= NETIF_F_LLTX;
-	dev->features		|= SIT_FEATURES;
-	dev->hw_features	|= SIT_FEATURES;
+	dev->features		|= sit_features;
+	dev->hw_features	|= sit_features;
 }
 
 static int ipip6_tunnel_init(struct net_device *dev)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e192e1ec0261..c40217911ff4 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
 #include <linux/types.h>
@@ -1902,13 +1903,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 /* color change handling */
 void ieee80211_color_change_finalize_work(struct work_struct *work);
 
+extern netdev_features_t mac80211_tx_features __ro_after_init;
+extern netdev_features_t mac80211_rx_features __ro_after_init;
+extern netdev_features_t mac80211_supported_features __ro_after_init;
 /* interface handling */
-#define MAC80211_SUPPORTED_FEATURES_TX	(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
-					 NETIF_F_HW_CSUM | NETIF_F_SG | \
-					 NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE)
-#define MAC80211_SUPPORTED_FEATURES_RX	(NETIF_F_RXCSUM)
-#define MAC80211_SUPPORTED_FEATURES	(MAC80211_SUPPORTED_FEATURES_TX | \
-					 MAC80211_SUPPORTED_FEATURES_RX)
+#define MAC80211_SUPPORTED_FEATURES_TX	mac80211_rx_features
+#define MAC80211_SUPPORTED_FEATURES_RX	mac80211_rx_features
+#define MAC80211_SUPPORTED_FEATURES	mac80211_supported_features
 
 int ieee80211_iface_init(void);
 void ieee80211_iface_exit(void);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 5b1c47ed0cc0..00d8f3bce563 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -33,6 +33,18 @@
 #include "led.h"
 #include "debugfs.h"
 
+static DECLARE_NETDEV_FEATURE_SET(mac80211_tx_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_HIGHDMA_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mac80211_rx_feature_set,
+				  NETIF_F_RXCSUM_BIT);
+netdev_features_t mac80211_tx_features __ro_after_init;
+netdev_features_t mac80211_rx_features __ro_after_init;
+netdev_features_t mac80211_supported_features __ro_after_init;
+
 void ieee80211_configure_filter(struct ieee80211_local *local)
 {
 	u64 mc;
@@ -1527,6 +1539,16 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(ieee80211_free_hw);
 
+static void __init ieee80211_features_init(void)
+{
+	mac80211_tx_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&mac80211_tx_feature_set,
+				  &mac80211_tx_features);
+	netdev_features_set_array(&mac80211_rx_feature_set,
+				  &mac80211_rx_features);
+	mac80211_supported_features = mac80211_tx_features | mac80211_rx_features;
+}
+
 static int __init ieee80211_init(void)
 {
 	struct sk_buff *skb;
@@ -1544,6 +1566,8 @@ static int __init ieee80211_init(void)
 	if (ret)
 		goto err_netdev;
 
+	ieee80211_features_init();
+
 	return 0;
  err_netdev:
 	rc80211_minstrel_exit();
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 5b2ee9c1c00b..1e401624908b 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -6,6 +6,7 @@
 #include <linux/if_vlan.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/skbuff.h>
@@ -92,6 +93,13 @@ static struct rtnl_link_ops internal_dev_link_ops __read_mostly = {
 	.kind = "openvswitch",
 };
 
+static DECLARE_NETDEV_FEATURE_SET(ovs_feature_set,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HIGHDMA_BIT,
+				  NETIF_F_HW_CSUM_BIT);
+
 static void do_setup(struct net_device *netdev)
 {
 	ether_setup(netdev);
@@ -108,9 +116,8 @@ static void do_setup(struct net_device *netdev)
 	netdev->ethtool_ops = &internal_dev_ethtool_ops;
 	netdev->rtnl_link_ops = &internal_dev_link_ops;
 
-	netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST |
-			   NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
-			   NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev->features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev_active_features_set_array(netdev, &ovs_feature_set);
 
 	netdev->vlan_features = netdev->features;
 	netdev->hw_enc_features = netdev->features;
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 5113fa0fbcee..d80bff81b346 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -20,6 +20,7 @@
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_link.h>
 #include <linux/if_arp.h>
 #include <linux/icmpv6.h>
@@ -572,15 +573,16 @@ static void xfrmi_dev_setup(struct net_device *dev)
 	eth_broadcast_addr(dev->broadcast);
 }
 
-#define XFRMI_FEATURES (NETIF_F_SG |		\
-			NETIF_F_FRAGLIST |	\
-			NETIF_F_GSO_SOFTWARE |	\
-			NETIF_F_HW_CSUM)
+static DECLARE_NETDEV_FEATURE_SET(xfrmi_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HW_CSUM_BIT);
 
 static int xfrmi_dev_init(struct net_device *dev)
 {
 	struct xfrm_if *xi = netdev_priv(dev);
 	struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
+	netdev_features_t xfrmi_features;
 	int err;
 
 	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
@@ -593,9 +595,11 @@ static int xfrmi_dev_init(struct net_device *dev)
 		return err;
 	}
 
+	xfrmi_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_array(&xfrmi_feature_set, &xfrmi_features);
 	dev->features |= NETIF_F_LLTX;
-	dev->features |= XFRMI_FEATURES;
-	dev->hw_features |= XFRMI_FEATURES;
+	dev->features |= xfrmi_features;
+	dev->hw_features |= xfrmi_features;
 
 	if (phydev) {
 		dev->needed_headroom = phydev->needed_headroom;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 04/36] net: sfc: replace const features initialization with DECLARE_NETDEV_FEATURE_SET
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (2 preceding siblings ...)
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 03/36] net: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 05/36] net: atlantic: replace const features initialization with NETDEV_FEATURE_SET Jian Shen
                   ` (31 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

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 refer 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_netdev.c      |  6 ++--
 drivers/net/ethernet/sfc/ef100_nic.c         |  9 ++---
 drivers/net/ethernet/sfc/efx.c               | 36 ++++++++++++++++++--
 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/efx.c         | 20 +++++++++--
 drivers/net/ethernet/sfc/siena/efx.h         |  2 ++
 drivers/net/ethernet/sfc/siena/net_driver.h  |  2 +-
 drivers/net/ethernet/sfc/siena/rx_common.c   |  2 +-
 drivers/net/ethernet/sfc/siena/siena.c       |  3 +-
 16 files changed, 99 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 21db8af0fb73..5e0d21475574 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -4033,13 +4033,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,
@@ -4140,7 +4133,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 |
@@ -4278,7 +4271,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_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index 15f654e5ad0a..cbe9fda5464f 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -372,9 +372,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
 	efx->net_dev = net_dev;
 	SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
 
-	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);
 	netif_set_tso_max_segs(net_dev,
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 819931161be9..a19a8df568f9 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -1173,16 +1173,11 @@ void ef100_remove(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_main,
-	.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,
@@ -1271,7 +1266,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,
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 3baebaabdf32..897a0113e257 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1013,9 +1013,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))
@@ -1296,6 +1296,36 @@ static struct pci_driver efx_pci_driver = {
 #endif
 };
 
+static 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);
+static 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);
+
+netdev_features_t ef10_offload_features __ro_after_init;
+netdev_features_t ef100_offload_features __ro_after_init;
+
+static void __init 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);
+}
+
 /**************************************************************************
  *
  * Kernel module interface
@@ -1324,6 +1354,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 0240c7f5843a..8692dc18efff 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -1689,7 +1689,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;
 
@@ -2904,7 +2904,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);
@@ -3168,6 +3168,25 @@ static struct pci_driver ef4_pci_driver = {
 	.err_handler	= &ef4_err_handlers,
 };
 
+static DECLARE_NETDEV_FEATURE_SET(falcon_b0_offload_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_NTUPLE_BIT);
+
+static 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 __init 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
@@ -3198,6 +3217,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 8ee0cc45e8ad..f04b66b62840 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 3ec44ed52933..4b0ae2353f3f 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1546,7 +1546,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 4826e6a7e4ce..ab83fd836031 100644
--- a/drivers/net/ethernet/sfc/rx_common.c
+++ b/drivers/net/ethernet/sfc/rx_common.c
@@ -798,7 +798,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/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index 050e1b0ad0cb..4829f66a47e7 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -996,9 +996,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))
@@ -1270,6 +1270,20 @@ static struct pci_driver efx_pci_driver = {
 #endif
 };
 
+static 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 siena_offload_features __ro_after_init;
+
+static void __init efx_features_init(void)
+{
+	netdev_features_set_array(&siena_offload_feature_set,
+				  &siena_offload_features);
+}
+
 /**************************************************************************
  *
  * Kernel module interface
@@ -1300,6 +1314,8 @@ static int __init efx_init_module(void)
 	if (rc < 0)
 		goto err_pci;
 
+	efx_features_init();
+
 	return 0;
 
  err_pci:
diff --git a/drivers/net/ethernet/sfc/siena/efx.h b/drivers/net/ethernet/sfc/siena/efx.h
index 27d1d3f19cae..6f1768a75ee8 100644
--- a/drivers/net/ethernet/sfc/siena/efx.h
+++ b/drivers/net/ethernet/sfc/siena/efx.h
@@ -12,6 +12,8 @@
 #include "net_driver.h"
 #include "filter.h"
 
+extern netdev_features_t siena_offload_features __ro_after_init;
+
 /* TX */
 void efx_siena_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue);
 netdev_tx_t efx_siena_hard_start_xmit(struct sk_buff *skb,
diff --git a/drivers/net/ethernet/sfc/siena/net_driver.h b/drivers/net/ethernet/sfc/siena/net_driver.h
index ff7bbc325952..331af932e56d 100644
--- a/drivers/net/ethernet/sfc/siena/net_driver.h
+++ b/drivers/net/ethernet/sfc/siena/net_driver.h
@@ -1473,7 +1473,7 @@ struct efx_nic_type {
 	bool option_descriptors;
 	unsigned int min_interrupt_mode;
 	unsigned int timer_period_max;
-	netdev_features_t offload_features;
+	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/siena/rx_common.c b/drivers/net/ethernet/sfc/siena/rx_common.c
index 4579f43484c3..be17b8676fff 100644
--- a/drivers/net/ethernet/sfc/siena/rx_common.c
+++ b/drivers/net/ethernet/sfc/siena/rx_common.c
@@ -805,7 +805,7 @@ int efx_siena_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/siena/siena.c b/drivers/net/ethernet/sfc/siena/siena.c
index a44c8fa25748..a92cf1bef772 100644
--- a/drivers/net/ethernet/sfc/siena/siena.c
+++ b/drivers/net/ethernet/sfc/siena/siena.c
@@ -1099,8 +1099,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 |
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 05/36] net: atlantic: replace const features initialization with NETDEV_FEATURE_SET
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (3 preceding siblings ...)
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 04/36] net: sfc: replace const features initialization " Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 06/36] iwlwifi: " Jian Shen
                   ` (30 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The atlantic driver use netdev_features in global structure
initialization. Changed the its netdev_features_t memeber
to netdev_features_t *, and make it refer to a netdev_features_t
global variables.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 .../net/ethernet/aquantia/atlantic/aq_hw.h    |  2 +-
 .../net/ethernet/aquantia/atlantic/aq_main.c  | 58 ++++++++++++++++++-
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |  6 +-
 .../net/ethernet/aquantia/atlantic/aq_nic.h   |  6 +-
 .../aquantia/atlantic/hw_atl/hw_atl_a0.c      |  8 +--
 .../aquantia/atlantic/hw_atl/hw_atl_b0.c      | 15 +----
 .../aquantia/atlantic/hw_atl2/hw_atl2.c       | 15 +----
 7 files changed, 69 insertions(+), 41 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
index dbd284660135..b4ee2625fbba 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -43,7 +43,7 @@ enum aq_tc_mode {
 
 /* NIC H/W capabilities */
 struct aq_hw_caps_s {
-	u64 hw_features;
+	const netdev_features_t *hw_features;
 	u64 link_speed_msk;
 	unsigned int hw_priv_flags;
 	u32 media_type;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
index 88595863d8bc..71acce12baec 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -17,6 +17,7 @@
 #include "aq_vec.h"
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/module.h>
 #include <linux/ip.h>
 #include <linux/udp.h>
@@ -36,6 +37,49 @@ static const struct net_device_ops aq_ndev_ops;
 
 static struct workqueue_struct *aq_ndev_wq;
 
+static DECLARE_NETDEV_FEATURE_SET(hw_atl2_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_NTUPLE_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT,
+				  NETIF_F_HW_TC_BIT);
+static DECLARE_NETDEV_FEATURE_SET(hw_atl_a0_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_NTUPLE_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+static DECLARE_NETDEV_FEATURE_SET(hw_atl_b0_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_RXHASH_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_LRO_BIT,
+				  NETIF_F_NTUPLE_BIT,
+				  NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_GSO_UDP_L4_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT,
+				  NETIF_F_HW_TC_BIT);
+
+netdev_features_t hw_atl2_features __ro_after_init;
+netdev_features_t hw_atl_a0_features __ro_after_init;
+netdev_features_t hw_atl_b0_features __ro_after_init;
+
 void aq_ndev_schedule_work(struct work_struct *work)
 {
 	queue_work(aq_ndev_wq, work);
@@ -184,7 +228,7 @@ static int aq_ndev_set_features(struct net_device *ndev,
 
 	aq_cfg->features = features;
 
-	if (aq_cfg->aq_hw_caps->hw_features & NETIF_F_LRO) {
+	if (*aq_cfg->aq_hw_caps->hw_features & NETIF_F_LRO) {
 		is_lro = features & NETIF_F_LRO;
 
 		if (aq_cfg->is_lro != is_lro) {
@@ -511,6 +555,16 @@ static const struct net_device_ops aq_ndev_ops = {
 	.ndo_xdp_xmit = aq_xdp_xmit,
 };
 
+static void __init aq_features_init(void)
+{
+	netdev_features_set_array(&hw_atl2_feature_set,
+				  &hw_atl2_features);
+	netdev_features_set_array(&hw_atl_a0_feature_set,
+				  &hw_atl_a0_features);
+	netdev_features_set_array(&hw_atl_b0_feature_set,
+				  &hw_atl_b0_features);
+}
+
 static int __init aq_ndev_init_module(void)
 {
 	int ret;
@@ -527,6 +581,8 @@ static int __init aq_ndev_init_module(void)
 		return ret;
 	}
 
+	aq_features_init();
+
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 2a726e6213b4..a8de1fb20a3f 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -145,7 +145,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
 		cfg->link_irq_vec = 0;
 
 	cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk;
-	cfg->features = cfg->aq_hw_caps->hw_features;
+	cfg->features = *cfg->aq_hw_caps->hw_features;
 	cfg->is_vlan_rx_strip = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_RX);
 	cfg->is_vlan_tx_insert = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_TX);
 	cfg->is_vlan_force_promisc = true;
@@ -383,8 +383,8 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 	const struct aq_hw_caps_s *aq_hw_caps = self->aq_nic_cfg.aq_hw_caps;
 	struct aq_nic_cfg_s *aq_nic_cfg = &self->aq_nic_cfg;
 
-	self->ndev->hw_features |= aq_hw_caps->hw_features;
-	self->ndev->features = aq_hw_caps->hw_features;
+	self->ndev->hw_features |= *aq_hw_caps->hw_features;
+	self->ndev->features = *aq_hw_caps->hw_features;
 	netdev_vlan_features_set_array(self->ndev, &aq_nic_vlan_feature_set);
 	self->ndev->gso_partial_features = NETIF_F_GSO_UDP_L4;
 	self->ndev->priv_flags = aq_hw_caps->hw_priv_flags;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
index 935ba889bd9a..cf9ac3084e3f 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
@@ -26,6 +26,10 @@ struct aq_macsec_cfg;
 struct aq_ptp_s;
 enum aq_rx_filter_type;
 
+extern netdev_features_t hw_atl2_features __ro_after_init;
+extern netdev_features_t hw_atl_a0_features __ro_after_init;
+extern netdev_features_t hw_atl_b0_features __ro_after_init;
+
 enum aq_fc_mode {
 	AQ_NIC_FC_OFF = 0,
 	AQ_NIC_FC_TX,
@@ -40,7 +44,7 @@ struct aq_fc_info {
 
 struct aq_nic_cfg_s {
 	const struct aq_hw_caps_s *aq_hw_caps;
-	u64 features;
+	netdev_features_t features;
 	u32 rxds;		/* rx ring size, descriptors # */
 	u32 txds;		/* tx ring size, descriptors # */
 	u32 vecs;		/* allocated rx/tx vectors */
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
index 9dfd68f0fda9..539e90af7615 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
@@ -34,13 +34,7 @@
 	.txhwb_alignment = 4096U,		     \
 	.tx_rings = HW_ATL_A0_TX_RINGS,		     \
 	.rx_rings = HW_ATL_A0_RX_RINGS,		     \
-	.hw_features = NETIF_F_HW_CSUM |	     \
-			NETIF_F_RXHASH |	     \
-			NETIF_F_RXCSUM |	     \
-			NETIF_F_SG |		     \
-			NETIF_F_TSO |		     \
-			NETIF_F_NTUPLE |	     \
-			NETIF_F_HW_VLAN_CTAG_FILTER, \
+	.hw_features = &hw_atl_a0_features,          \
 	.hw_priv_flags = IFF_UNICAST_FLT,	     \
 	.flow_control = true,			     \
 	.mtu = HW_ATL_A0_MTU_JUMBO,		     \
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
index 54e70f07b573..0ba71726238a 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -36,20 +36,7 @@
 	.txhwb_alignment = 4096U,	  \
 	.tx_rings = HW_ATL_B0_TX_RINGS,   \
 	.rx_rings = HW_ATL_B0_RX_RINGS,   \
-	.hw_features = NETIF_F_HW_CSUM |  \
-			NETIF_F_RXCSUM |  \
-			NETIF_F_RXHASH |  \
-			NETIF_F_SG |      \
-			NETIF_F_TSO |     \
-			NETIF_F_TSO6 |    \
-			NETIF_F_LRO |     \
-			NETIF_F_NTUPLE |  \
-			NETIF_F_HW_VLAN_CTAG_FILTER | \
-			NETIF_F_HW_VLAN_CTAG_RX |     \
-			NETIF_F_HW_VLAN_CTAG_TX |     \
-			NETIF_F_GSO_UDP_L4      |     \
-			NETIF_F_GSO_PARTIAL |         \
-			NETIF_F_HW_TC,                \
+	.hw_features = &hw_atl_b0_features, \
 	.hw_priv_flags = IFF_UNICAST_FLT, \
 	.flow_control = true,		  \
 	.mtu = HW_ATL_B0_MTU_JUMBO,	  \
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c
index 5dfc751572ed..34613222e9ff 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c
@@ -37,20 +37,7 @@ static int hw_atl2_act_rslvr_table_set(struct aq_hw_s *self, u8 location,
 	.txhwb_alignment = 4096U,	  \
 	.tx_rings = HW_ATL2_TX_RINGS,   \
 	.rx_rings = HW_ATL2_RX_RINGS,   \
-	.hw_features = NETIF_F_HW_CSUM |  \
-			NETIF_F_RXCSUM |  \
-			NETIF_F_RXHASH |  \
-			NETIF_F_SG |      \
-			NETIF_F_TSO |     \
-			NETIF_F_TSO6 |    \
-			NETIF_F_LRO |     \
-			NETIF_F_NTUPLE |  \
-			NETIF_F_HW_VLAN_CTAG_FILTER | \
-			NETIF_F_HW_VLAN_CTAG_RX |     \
-			NETIF_F_HW_VLAN_CTAG_TX |     \
-			NETIF_F_GSO_UDP_L4      |     \
-			NETIF_F_GSO_PARTIAL     |     \
-			NETIF_F_HW_TC,                \
+	.hw_features = &hw_atl2_features, \
 	.hw_priv_flags = IFF_UNICAST_FLT, \
 	.flow_control = true,		  \
 	.mtu = HW_ATL2_MTU_JUMBO,	  \
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 06/36] iwlwifi: replace const features initialization with NETDEV_FEATURE_SET
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (4 preceding siblings ...)
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 05/36] net: atlantic: replace const features initialization with NETDEV_FEATURE_SET Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 07/36] net: ethernet: mtk_eth_soc: " Jian Shen
                   ` (29 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The iwlwifi driver use netdev_features in global structure
initialization. Changed the its netdev_features_t memeber
to netdev_features_t *, and make it refer to a netdev_features_t
global variables.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/wireless/intel/iwlwifi/cfg/1000.c |  2 ++
 drivers/net/wireless/intel/iwlwifi/cfg/2000.c |  4 +++
 .../net/wireless/intel/iwlwifi/cfg/22000.c    |  4 +--
 drivers/net/wireless/intel/iwlwifi/cfg/5000.c |  3 ++
 drivers/net/wireless/intel/iwlwifi/cfg/6000.c |  7 ++++
 drivers/net/wireless/intel/iwlwifi/cfg/7000.c |  1 +
 drivers/net/wireless/intel/iwlwifi/cfg/8000.c |  2 +-
 drivers/net/wireless/intel/iwlwifi/cfg/9000.c |  2 +-
 .../net/wireless/intel/iwlwifi/iwl-config.h   | 15 +++++----
 drivers/net/wireless/intel/iwlwifi/iwl-drv.c  | 33 +++++++++++++++++++
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h  |  8 +++++
 drivers/net/wireless/intel/iwlwifi/mvm/ops.c  | 28 ++++++++++++++++
 13 files changed, 99 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
index 116defb15afb..6d172f4d085c 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
@@ -67,6 +67,7 @@ static const struct iwl_eeprom_params iwl1000_eeprom_params = {
 	.trans.device_family = IWL_DEVICE_FAMILY_1000,		\
 	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
 	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_1000_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl1000_base_params,		\
@@ -91,6 +92,7 @@ const struct iwl_cfg iwl1000_bg_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_100,		\
 	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
 	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_1000_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl1000_base_params,		\
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
index ab2038a3fbe2..1757e823d883 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
@@ -93,6 +93,7 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
 	.trans.device_family = IWL_DEVICE_FAMILY_2000,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_2000_EEPROM_VERSION,			\
 	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,		\
 	.trans.base_params = &iwl2000_base_params,		\
@@ -119,6 +120,7 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_2030,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl2030_base_params,		\
@@ -138,6 +140,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_105,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl2000_base_params,		\
@@ -164,6 +167,7 @@ const struct iwl_cfg iwl105_bgn_d_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_135,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl2030_base_params,		\
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 8ff967edc8f0..a1e953c99254 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -175,7 +175,7 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
 	.dccm2_len = IWL_22000_DCCM2_LEN,				\
 	.smem_offset = IWL_22000_SMEM_OFFSET,				\
 	.smem_len = IWL_22000_SMEM_LEN,					\
-	.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,		\
+	.features = &iwl_dev_22000_comm_features,			\
 	.apmg_not_supported = true,					\
 	.trans.mq_rx_supported = true,					\
 	.vht_mu_mimo_supported = true,					\
@@ -252,7 +252,7 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
 	.dccm2_len = IWL_22000_DCCM2_LEN,				\
 	.smem_offset = IWL_22000_SMEM_OFFSET,				\
 	.smem_len = IWL_22000_SMEM_LEN,					\
-	.features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,	\
+	.features = &iwl_dev_bz_comm_features,				\
 	.apmg_not_supported = true,					\
 	.trans.mq_rx_supported = true,					\
 	.vht_mu_mimo_supported = true,					\
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
index e2e23d2bc1fe..8efd018e5e2a 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
@@ -65,6 +65,7 @@ static const struct iwl_eeprom_params iwl5000_eeprom_params = {
 	.trans.device_family = IWL_DEVICE_FAMILY_5000,		\
 	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
 	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_5000_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl5000_base_params,		\
@@ -111,6 +112,7 @@ const struct iwl_cfg iwl5350_agn_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_5000,
 	.max_inst_size = IWLAGN_RTC_INST_SIZE,
 	.max_data_size = IWLAGN_RTC_DATA_SIZE,
+	.features = &netdev_empty_features,
 	.nvm_ver = EEPROM_5050_EEPROM_VERSION,
 	.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,
 	.trans.base_params = &iwl5000_base_params,
@@ -127,6 +129,7 @@ const struct iwl_cfg iwl5350_agn_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_5150,		\
 	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
 	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_5050_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl5000_base_params,		\
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
index 20929e59c2f4..a682eaf35142 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
@@ -114,6 +114,7 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = {
 	.trans.device_family = IWL_DEVICE_FAMILY_6005,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_6005_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl6000_g2_base_params,		\
@@ -167,6 +168,7 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_6030,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_6030_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl6000_g2_base_params,		\
@@ -202,6 +204,7 @@ const struct iwl_cfg iwl6030_2bg_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_6030,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_6030_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl6000_g2_base_params,		\
@@ -254,6 +257,7 @@ const struct iwl_cfg iwl130_bg_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_6000i,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.valid_tx_ant = ANT_BC,		/* .cfg overwrite */	\
 	.valid_rx_ant = ANT_BC,		/* .cfg overwrite */	\
 	.nvm_ver = EEPROM_6000_EEPROM_VERSION,		\
@@ -285,6 +289,7 @@ const struct iwl_cfg iwl6000i_2bg_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_6050,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.valid_tx_ant = ANT_AB,		/* .cfg overwrite */	\
 	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */	\
 	.nvm_ver = EEPROM_6050_EEPROM_VERSION,		\
@@ -312,6 +317,7 @@ const struct iwl_cfg iwl6050_2abg_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_6150,		\
 	.max_inst_size = IWL60_RTC_INST_SIZE,			\
 	.max_data_size = IWL60_RTC_DATA_SIZE,			\
+	.features = &netdev_empty_features,			\
 	.nvm_ver = EEPROM_6150_EEPROM_VERSION,		\
 	.nvm_calib_ver = EEPROM_6150_TX_POWER_VERSION,	\
 	.trans.base_params = &iwl6050_base_params,		\
@@ -338,6 +344,7 @@ const struct iwl_cfg iwl6000_3agn_cfg = {
 	.trans.device_family = IWL_DEVICE_FAMILY_6000,
 	.max_inst_size = IWL60_RTC_INST_SIZE,
 	.max_data_size = IWL60_RTC_DATA_SIZE,
+	.features = &netdev_empty_features,
 	.nvm_ver = EEPROM_6000_EEPROM_VERSION,
 	.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,
 	.trans.base_params = &iwl6000_base_params,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
index b24dc5523a52..1bbad301118a 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
@@ -92,6 +92,7 @@ static const struct iwl_ht_params iwl7000_ht_params = {
 #define IWL_DEVICE_7000_COMMON					\
 	.trans.device_family = IWL_DEVICE_FAMILY_7000,		\
 	.trans.base_params = &iwl7000_base_params,		\
+	.features = &netdev_empty_features,			\
 	.led_mode = IWL_LED_RF_STATE,				\
 	.nvm_hw_section_num = 0,				\
 	.non_shared_ant = ANT_A,				\
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
index a6454287d506..7535832599e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
@@ -81,7 +81,7 @@ static const struct iwl_tt_params iwl8000_tt_params = {
 	.trans.base_params = &iwl8000_base_params,			\
 	.led_mode = IWL_LED_RF_STATE,					\
 	.nvm_hw_section_num = 10,					\
-	.features = NETIF_F_RXCSUM,					\
+	.features = &iwl_dev_8000_comm_features,			\
 	.non_shared_ant = ANT_A,					\
 	.dccm_offset = IWL8260_DCCM_OFFSET,				\
 	.dccm_len = IWL8260_DCCM_LEN,					\
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
index 7a7ca06d46c1..0a89c6fb8048 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
@@ -84,7 +84,7 @@ static const struct iwl_tt_params iwl9000_tt_params = {
 	.dccm2_len = IWL9000_DCCM2_LEN,					\
 	.smem_offset = IWL9000_SMEM_OFFSET,				\
 	.smem_len = IWL9000_SMEM_LEN,					\
-	.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,		\
+	.features = &iwl_dev_9000_comm_features,			\
 	.thermal_params = &iwl9000_tt_params,				\
 	.apmg_not_supported = true,					\
 	.num_rbds = 512,						\
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index f5b556a103e8..fbec4e130e88 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -82,12 +82,13 @@ enum iwl_nvm_type {
 #define IWL_MAX_WD_TIMEOUT	120000
 
 #define IWL_DEFAULT_MAX_TX_POWER 22
-#define IWL_TX_CSUM_NETIF_FLAGS (NETIF_F_IPV6_CSUM | NETIF_F_IP_CSUM |\
-				 NETIF_F_TSO | NETIF_F_TSO6)
-#define IWL_TX_CSUM_NETIF_FLAGS_BZ (NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6)
-#define IWL_CSUM_NETIF_FLAGS_MASK (IWL_TX_CSUM_NETIF_FLAGS | \
-				   IWL_TX_CSUM_NETIF_FLAGS_BZ | \
-				   NETIF_F_RXCSUM)
+
+extern netdev_features_t iwl_tx_csum_features __ro_after_init;
+extern netdev_features_t iwl_tx_csum_bz_features __ro_after_init;
+extern netdev_features_t iwl_dev_22000_comm_features __ro_after_init;
+extern netdev_features_t iwl_dev_bz_comm_features __ro_after_init;
+extern netdev_features_t iwl_dev_8000_comm_features __ro_after_init;
+extern netdev_features_t iwl_dev_9000_comm_features __ro_after_init;
 
 /* Antenna presence definitions */
 #define	ANT_NONE	0x0
@@ -371,7 +372,7 @@ struct iwl_cfg {
 	enum iwl_nvm_type nvm_type;
 	u32 max_data_size;
 	u32 max_inst_size;
-	netdev_features_t features;
+	const netdev_features_t *features;
 	u32 dccm_offset;
 	u32 dccm_len;
 	u32 dccm2_offset;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index a2203f661321..f55ecfc51272 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -8,6 +8,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/firmware.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/vmalloc.h>
 
 #include "iwl-drv.h"
@@ -89,6 +90,22 @@ static struct iwlwifi_opmode_table {
 
 #define IWL_DEFAULT_SCAN_CHANNELS 40
 
+static DECLARE_NETDEV_FEATURE_SET(iwl_tx_csum_feature_set,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(iwl_tx_csum_bz_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+netdev_features_t iwl_tx_csum_features __ro_after_init;
+netdev_features_t iwl_tx_csum_bz_features __ro_after_init;
+netdev_features_t iwl_dev_22000_comm_features __ro_after_init;
+netdev_features_t iwl_dev_bz_comm_features __ro_after_init;
+netdev_features_t iwl_dev_8000_comm_features __ro_after_init;
+netdev_features_t iwl_dev_9000_comm_features __ro_after_init;
+
 /*
  * struct fw_sec: Just for the image parsing process.
  * For the fw storage we are using struct fw_desc.
@@ -1829,6 +1846,20 @@ void iwl_opmode_deregister(const char *name)
 }
 IWL_EXPORT_SYMBOL(iwl_opmode_deregister);
 
+static void __init iwl_features_init(void)
+{
+	netdev_features_set_array(&iwl_tx_csum_feature_set,
+				  &iwl_tx_csum_features);
+	netdev_features_set_array(&iwl_tx_csum_bz_feature_set,
+				  &iwl_tx_csum_bz_features);
+	iwl_dev_22000_comm_features = iwl_tx_csum_features;
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, &iwl_dev_22000_comm_features);
+	iwl_dev_bz_comm_features = iwl_tx_csum_bz_features;
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, &iwl_dev_bz_comm_features);
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, &iwl_dev_8000_comm_features);
+	iwl_dev_9000_comm_features = iwl_dev_22000_comm_features;
+}
+
 static int __init iwl_drv_init(void)
 {
 	int i, err;
@@ -1847,6 +1878,8 @@ static int __init iwl_drv_init(void)
 	if (err)
 		goto cleanup_debugfs;
 
+	iwl_features_init();
+
 	return 0;
 
 cleanup_debugfs:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 5eb28f8ee87e..9a5abb7958b6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -611,7 +611,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 		hw->wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
 	}
 
-	hw->netdev_features |= mvm->cfg->features;
+	hw->netdev_features |= *mvm->cfg->features;
 	if (!iwl_mvm_is_csum_supported(mvm))
 		hw->netdev_features &= ~IWL_CSUM_NETIF_FLAGS_MASK;
 
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index bf35e130c876..a50d85b7050b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -73,6 +73,14 @@
 
 extern const struct ieee80211_ops iwl_mvm_hw_ops;
 
+extern netdev_features_t mvm_tx_csum_features __ro_after_init;
+extern netdev_features_t mvm_tx_csum_bz_features __ro_after_init;
+extern netdev_features_t mvm_csum_features_mask __ro_after_init;
+
+#define IWL_TX_CSUM_NETIF_FLAGS mvm_tx_csum_features
+#define IWL_TX_CSUM_NETIF_FLAGS_BZ mvm_tx_csum_bz_features
+#define IWL_CSUM_NETIF_FLAGS_MASK mvm_csum_features_mask
+
 /**
  * struct iwl_mvm_mod_params - module parameters for iwlmvm
  * @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted.
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index db43c8a83a31..e5832f1e6b79 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/rtnetlink.h>
 #include <linux/vmalloc.h>
 #include <net/mac80211.h>
@@ -50,6 +51,31 @@ module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, 0444);
 MODULE_PARM_DESC(power_scheme,
 		 "power management scheme: 1-active, 2-balanced, 3-low power, default: 2");
 
+static DECLARE_NETDEV_FEATURE_SET(mvm_tx_csum_feature_set,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mvm_tx_csum_bz_feature_set,
+				  NETIF_F_HW_CSUM_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT);
+
+netdev_features_t mvm_tx_csum_features __ro_after_init;
+netdev_features_t mvm_tx_csum_bz_features __ro_after_init;
+netdev_features_t mvm_csum_features_mask __ro_after_init;
+
+static void __init iwl_mvm_features_init(void)
+{
+	netdev_features_set_array(&mvm_tx_csum_feature_set,
+				  &mvm_tx_csum_features);
+	netdev_features_set_array(&mvm_tx_csum_bz_feature_set,
+				  &mvm_tx_csum_bz_features);
+	mvm_csum_features_mask = netdev_features_or(mvm_tx_csum_features,
+						    mvm_tx_csum_bz_features);
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, &mvm_csum_features_mask);
+}
+
 /*
  * module init and exit functions
  */
@@ -67,6 +93,8 @@ static int __init iwl_mvm_init(void)
 	if (ret)
 		pr_err("Unable to register MVM op_mode: %d\n", ret);
 
+	iwl_mvm_features_init();
+
 	return ret;
 }
 module_init(iwl_mvm_init);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 07/36] net: ethernet: mtk_eth_soc: replace const features initialization with NETDEV_FEATURE_SET
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (5 preceding siblings ...)
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 06/36] iwlwifi: " Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 08/36] ravb: " Jian Shen
                   ` (28 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The mediatek driver 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/mediatek/mtk_eth_soc.c | 46 +++++++++++++++++----
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 +-----
 2 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index d9426b01f462..92c1de636128 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -161,6 +161,23 @@ static const char * const mtk_clks_source_name[] = {
 	"sgmii_ck", "eth2pll", "wocpu0", "wocpu1", "netsys0", "netsys1"
 };
 
+static DECLARE_NETDEV_FEATURE_SET(mtk_hw_feature_set,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_TSO_BIT,
+				  NETIF_F_TSO6_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_HW_TC_BIT);
+static DECLARE_NETDEV_FEATURE_SET(mtk_mt7628_hw_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static netdev_features_t mtk_hw_features __ro_after_init;
+static netdev_features_t mtk_mt7628_hw_features __ro_after_init;
+static netdev_features_t mtk_empty_features __ro_after_init;
+
 void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
 {
 	__raw_writel(val, eth->base + reg);
@@ -3362,6 +3379,14 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
 	return 0;
 }
 
+static void __init mtk_features_init(void)
+{
+	netdev_features_set_array(&mtk_hw_feature_set, &mtk_hw_features);
+	netdev_features_set_array(&mtk_mt7628_hw_feature_set,
+				  &mtk_mt7628_hw_features);
+	netdev_features_zero(&mtk_empty_features);
+}
+
 static int __init mtk_init(struct net_device *dev)
 {
 	struct mtk_mac *mac = netdev_priv(dev);
@@ -3376,6 +3401,8 @@ static int __init mtk_init(struct net_device *dev)
 			dev->dev_addr);
 	}
 
+	mtk_features_init();
+
 	return 0;
 }
 
@@ -3868,13 +3895,13 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 	eth->netdev[id]->netdev_ops = &mtk_netdev_ops;
 	eth->netdev[id]->base_addr = (unsigned long)eth->base;
 
-	eth->netdev[id]->hw_features = eth->soc->hw_features;
+	eth->netdev[id]->hw_features = *eth->soc->hw_features;
 	if (eth->hwlro)
 		eth->netdev[id]->hw_features |= NETIF_F_LRO;
 
-	eth->netdev[id]->vlan_features = eth->soc->hw_features &
+	eth->netdev[id]->vlan_features = *eth->soc->hw_features &
 		~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
-	eth->netdev[id]->features |= eth->soc->hw_features;
+	eth->netdev[id]->features |= *eth->soc->hw_features;
 	eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
 
 	eth->netdev[id]->irq = eth->irq[0];
@@ -4170,7 +4197,7 @@ static int mtk_remove(struct platform_device *pdev)
 static const struct mtk_soc_data mt2701_data = {
 	.reg_map = &mtk_reg_map,
 	.caps = MT7623_CAPS | MTK_HWLRO,
-	.hw_features = MTK_HW_FEATURES,
+	.hw_features = &mtk_hw_features,
 	.required_clks = MT7623_CLKS_BITMAP,
 	.required_pctl = true,
 	.txrx = {
@@ -4186,7 +4213,7 @@ static const struct mtk_soc_data mt2701_data = {
 static const struct mtk_soc_data mt7621_data = {
 	.reg_map = &mtk_reg_map,
 	.caps = MT7621_CAPS,
-	.hw_features = MTK_HW_FEATURES,
+	.hw_features = &mtk_hw_features,
 	.required_clks = MT7621_CLKS_BITMAP,
 	.required_pctl = false,
 	.offload_version = 2,
@@ -4204,7 +4231,7 @@ static const struct mtk_soc_data mt7622_data = {
 	.reg_map = &mtk_reg_map,
 	.ana_rgc3 = 0x2028,
 	.caps = MT7622_CAPS | MTK_HWLRO,
-	.hw_features = MTK_HW_FEATURES,
+	.hw_features = &mtk_hw_features,
 	.required_clks = MT7622_CLKS_BITMAP,
 	.required_pctl = false,
 	.offload_version = 2,
@@ -4221,7 +4248,7 @@ static const struct mtk_soc_data mt7622_data = {
 static const struct mtk_soc_data mt7623_data = {
 	.reg_map = &mtk_reg_map,
 	.caps = MT7623_CAPS | MTK_HWLRO,
-	.hw_features = MTK_HW_FEATURES,
+	.hw_features = &mtk_hw_features,
 	.required_clks = MT7623_CLKS_BITMAP,
 	.required_pctl = true,
 	.offload_version = 2,
@@ -4239,7 +4266,7 @@ static const struct mtk_soc_data mt7629_data = {
 	.reg_map = &mtk_reg_map,
 	.ana_rgc3 = 0x128,
 	.caps = MT7629_CAPS | MTK_HWLRO,
-	.hw_features = MTK_HW_FEATURES,
+	.hw_features = &mtk_hw_features,
 	.required_clks = MT7629_CLKS_BITMAP,
 	.required_pctl = false,
 	.txrx = {
@@ -4256,6 +4283,7 @@ static const struct mtk_soc_data mt7986_data = {
 	.reg_map = &mt7986_reg_map,
 	.ana_rgc3 = 0x128,
 	.caps = MT7986_CAPS,
+	.hw_features = &mtk_empty_features,
 	.required_clks = MT7986_CLKS_BITMAP,
 	.required_pctl = false,
 	.txrx = {
@@ -4271,7 +4299,7 @@ static const struct mtk_soc_data mt7986_data = {
 static const struct mtk_soc_data rt5350_data = {
 	.reg_map = &mt7628_reg_map,
 	.caps = MT7628_CAPS,
-	.hw_features = MTK_HW_FEATURES_MT7628,
+	.hw_features = &mtk_mt7628_hw_features,
 	.required_clks = MT7628_CLKS_BITMAP,
 	.required_pctl = false,
 	.txrx = {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7405c97cda66..9620240885aa 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -11,6 +11,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of_net.h>
 #include <linux/u64_stats_sync.h>
 #include <linux/refcount.h>
@@ -40,15 +41,6 @@
 				 NETIF_MSG_IFUP | \
 				 NETIF_MSG_RX_ERR | \
 				 NETIF_MSG_TX_ERR)
-#define MTK_HW_FEATURES		(NETIF_F_IP_CSUM | \
-				 NETIF_F_RXCSUM | \
-				 NETIF_F_HW_VLAN_CTAG_TX | \
-				 NETIF_F_HW_VLAN_CTAG_RX | \
-				 NETIF_F_SG | NETIF_F_TSO | \
-				 NETIF_F_TSO6 | \
-				 NETIF_F_IPV6_CSUM |\
-				 NETIF_F_HW_TC)
-#define MTK_HW_FEATURES_MT7628	(NETIF_F_SG | NETIF_F_RXCSUM)
 #define NEXT_DESP_IDX(X, Y)	(((X) + 1) & ((Y) - 1))
 
 #define MTK_PP_HEADROOM		XDP_PACKET_HEADROOM
@@ -977,7 +969,7 @@ struct mtk_soc_data {
 	u32		required_clks;
 	bool		required_pctl;
 	u8		offload_version;
-	netdev_features_t hw_features;
+	const netdev_features_t *hw_features;
 	struct {
 		u32	txd_size;
 		u32	rxd_size;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 08/36] ravb: replace const features initialization with NETDEV_FEATURE_SET
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (6 preceding siblings ...)
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 07/36] net: ethernet: mtk_eth_soc: " Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 09/36] test_bpf: " Jian Shen
                   ` (27 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The ravb driver use netdev_features in global structure
initialization. Changed the its netdev_features_t memeber
to netdev_features_t *, and make it refer to a netdev_features_t
global variables.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/renesas/ravb.h      |  4 ++--
 drivers/net/ethernet/renesas/ravb_main.c | 27 +++++++++++++++++-------
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index b980bce763d3..efd3c32b9e46 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -1014,8 +1014,8 @@ struct ravb_hw_info {
 	void (*emac_init)(struct net_device *ndev);
 	const char (*gstrings_stats)[ETH_GSTRING_LEN];
 	size_t gstrings_size;
-	netdev_features_t net_hw_features;
-	netdev_features_t net_features;
+	const netdev_features_t *net_hw_features;
+	const netdev_features_t *net_features;
 	int stats_len;
 	size_t max_rx_len;
 	u32 tccr_mask;
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index b357ac4c56c5..b38f689c3683 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -50,6 +50,9 @@ static const char *ravb_tx_irqs[NUM_TX_QUEUE] = {
 	"ch19", /* RAVB_NC */
 };
 
+static netdev_features_t ravb_default_features;
+static netdev_features_t ravb_empty_features;
+
 void ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear,
 		 u32 set)
 {
@@ -2422,8 +2425,8 @@ static const struct ravb_hw_info ravb_gen3_hw_info = {
 	.emac_init = ravb_emac_init_rcar,
 	.gstrings_stats = ravb_gstrings_stats,
 	.gstrings_size = sizeof(ravb_gstrings_stats),
-	.net_hw_features = NETIF_F_RXCSUM,
-	.net_features = NETIF_F_RXCSUM,
+	.net_hw_features = &ravb_default_features,
+	.net_features = &ravb_default_features,
 	.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
 	.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
 	.tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3,
@@ -2448,8 +2451,8 @@ static const struct ravb_hw_info ravb_gen2_hw_info = {
 	.emac_init = ravb_emac_init_rcar,
 	.gstrings_stats = ravb_gstrings_stats,
 	.gstrings_size = sizeof(ravb_gstrings_stats),
-	.net_hw_features = NETIF_F_RXCSUM,
-	.net_features = NETIF_F_RXCSUM,
+	.net_hw_features = &ravb_default_features,
+	.net_features = &ravb_default_features,
 	.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
 	.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
 	.tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3,
@@ -2471,8 +2474,8 @@ static const struct ravb_hw_info ravb_rzv2m_hw_info = {
 	.emac_init = ravb_emac_init_rcar,
 	.gstrings_stats = ravb_gstrings_stats,
 	.gstrings_size = sizeof(ravb_gstrings_stats),
-	.net_hw_features = NETIF_F_RXCSUM,
-	.net_features = NETIF_F_RXCSUM,
+	.net_hw_features = &ravb_default_features,
+	.net_features = &ravb_default_features,
 	.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
 	.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
 	.tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3,
@@ -2496,6 +2499,8 @@ static const struct ravb_hw_info gbeth_hw_info = {
 	.emac_init = ravb_emac_init_gbeth,
 	.gstrings_stats = ravb_gstrings_stats_gbeth,
 	.gstrings_size = sizeof(ravb_gstrings_stats_gbeth),
+	.net_hw_features = &ravb_empty_features,
+	.net_features = &ravb_empty_features,
 	.stats_len = ARRAY_SIZE(ravb_gstrings_stats_gbeth),
 	.max_rx_len = ALIGN(GBETH_RX_BUFF_MAX, RAVB_ALIGN),
 	.tccr_mask = TCCR_TSRQ0,
@@ -2610,6 +2615,11 @@ static void ravb_set_delay_mode(struct net_device *ndev)
 	ravb_modify(ndev, APSR, APSR_RDM | APSR_TDM, set);
 }
 
+static void ravb_features_init(void)
+{
+	ravb_default_features |= NETIF_F_RXCSUM;
+}
+
 static int ravb_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -2639,8 +2649,9 @@ static int ravb_probe(struct platform_device *pdev)
 
 	info = of_device_get_match_data(&pdev->dev);
 
-	ndev->features = info->net_features;
-	ndev->hw_features = info->net_hw_features;
+	ravb_features_init();
+	ndev->features = *info->net_features;
+	ndev->hw_features = *info->net_hw_features;
 
 	reset_control_deassert(rstc);
 	pm_runtime_enable(&pdev->dev);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 09/36] test_bpf: replace const features initialization with NETDEV_FEATURE_SET
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (7 preceding siblings ...)
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 08/36] ravb: " Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 10/36] treewide: replace NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK by netdev_csum_gso_features_mask Jian Shen
                   ` (26 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The test_bpf uses netdev_features in global structure
initialization. Changed the its netdev_features_t memeber
to netdev_features_t *, and make it refer to a netdev_features_t
global variables.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 lib/test_bpf.c | 42 +++++++++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 9 deletions(-)

diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 5820704165a6..5ba5e9064903 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -13,6 +13,7 @@
 #include <linux/bpf.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_vlan.h>
 #include <linux/random.h>
 #include <linux/highmem.h>
@@ -14718,27 +14719,48 @@ static __init struct sk_buff *build_test_skb_linear_no_head_frag(void)
 struct skb_segment_test {
 	const char *descr;
 	struct sk_buff *(*build_skb)(void);
-	netdev_features_t features;
+	const netdev_features_t *features;
 };
 
+static DECLARE_NETDEV_FEATURE_SET(gso_frags_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_GSO_PARTIAL_BIT,
+				  NETIF_F_IP_CSUM_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT);
+static DECLARE_NETDEV_FEATURE_SET(gso_linear_feature_set,
+				  NETIF_F_SG_BIT,
+				  NETIF_F_FRAGLIST_BIT,
+				  NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				  NETIF_F_GSO_BIT,
+				  NETIF_F_LLTX_BIT,
+				  NETIF_F_GRO_BIT,
+				  NETIF_F_IPV6_CSUM_BIT,
+				  NETIF_F_RXCSUM_BIT,
+				  NETIF_F_HW_VLAN_STAG_TX_BIT);
+static netdev_features_t gso_frags_features __ro_after_init;
+static netdev_features_t gso_linear_feature_features __ro_after_init;
+
 static struct skb_segment_test skb_segment_tests[] __initconst = {
 	{
 		.descr = "gso_with_rx_frags",
 		.build_skb = build_test_skb,
-		.features = NETIF_F_SG | NETIF_F_GSO_PARTIAL | NETIF_F_IP_CSUM |
-			    NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM
+		.features = &gso_frags_features
 	},
 	{
 		.descr = "gso_linear_no_head_frag",
 		.build_skb = build_test_skb_linear_no_head_frag,
-		.features = NETIF_F_SG | NETIF_F_FRAGLIST |
-			    NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_GSO |
-			    NETIF_F_LLTX | NETIF_F_GRO |
-			    NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
-			    NETIF_F_HW_VLAN_STAG_TX
+		.features = &gso_linear_feature_features
 	}
 };
 
+static void __init test_skb_features_init(void)
+{
+	netdev_features_set_array(&gso_frags_feature_set, &gso_frags_features);
+	netdev_features_set_array(&gso_linear_feature_set,
+				  &gso_linear_feature_features);
+}
+
 static __init int test_skb_segment_single(const struct skb_segment_test *test)
 {
 	struct sk_buff *skb, *segs;
@@ -14750,7 +14772,7 @@ static __init int test_skb_segment_single(const struct skb_segment_test *test)
 		goto done;
 	}
 
-	segs = skb_segment(skb, test->features);
+	segs = skb_segment(skb, *test->features);
 	if (!IS_ERR(segs)) {
 		kfree_skb_list(segs);
 		ret = 0;
@@ -14764,6 +14786,8 @@ static __init int test_skb_segment(void)
 {
 	int i, err_cnt = 0, pass_cnt = 0;
 
+	test_skb_features_init();
+
 	for (i = 0; i < ARRAY_SIZE(skb_segment_tests); i++) {
 		const struct skb_segment_test *test = &skb_segment_tests[i];
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 10/36] treewide: replace NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK by netdev_csum_gso_features_mask
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (8 preceding siblings ...)
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 09/36] test_bpf: " Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 11/36] treewide: replace NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM by netdev_ip_csum_features Jian Shen
                   ` (25 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the expression "NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK" by
netdev_csum_gso_features_mask, make it simple to use netdev
features helpers later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c                   | 2 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c             | 2 +-
 drivers/net/ethernet/cisco/enic/enic_main.c                 | 2 +-
 drivers/net/ethernet/emulex/benet/be_main.c                 | 2 +-
 drivers/net/ethernet/hisilicon/hns3/hns3_enet.c             | 2 +-
 drivers/net/ethernet/intel/fm10k/fm10k_netdev.c             | 2 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c                 | 2 +-
 drivers/net/ethernet/intel/iavf/iavf_main.c                 | 2 +-
 drivers/net/ethernet/intel/ice/ice_main.c                   | 2 +-
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c              | 2 +-
 .../net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h   | 4 ++--
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c           | 2 +-
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c         | 4 ++--
 drivers/net/ethernet/qlogic/qede/qede_fp.c                  | 5 ++---
 drivers/net/ethernet/sfc/efx_common.c                       | 5 ++---
 drivers/net/ethernet/sfc/siena/efx_common.c                 | 5 ++---
 drivers/net/usb/r8152.c                                     | 2 +-
 drivers/net/vmxnet3/vmxnet3_ethtool.c                       | 6 +++---
 include/net/vxlan.h                                         | 2 +-
 net/core/dev.c                                              | 2 +-
 20 files changed, 27 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 825bf829b36a..37e2018fd875 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11393,7 +11393,7 @@ static netdev_features_t bnxt_features_check(struct sk_buff *skb,
 			return features;
 		break;
 	}
-	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	return features & ~netdev_csum_gso_features_mask;
 }
 
 int bnxt_dbg_hwrm_rd_reg(struct bnxt *bp, u32 reg_off, u16 num_words,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index f40e6964de89..7e61049247b9 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3850,7 +3850,7 @@ static netdev_features_t cxgb_features_check(struct sk_buff *skb,
 		return features;
 
 	/* Offload is not supported for this encapsulated packet */
-	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	return features & ~netdev_csum_gso_features_mask;
 }
 
 static netdev_features_t cxgb_fix_features(struct net_device *dev,
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 276fa370ce50..d999b3af2f8a 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -295,7 +295,7 @@ static netdev_features_t enic_features_check(struct sk_buff *skb,
 	return features;
 
 out:
-	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	return features & ~netdev_csum_gso_features_mask;
 }
 
 int enic_is_dynamic(struct enic *enic)
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 964e7d6111df..22af4232329e 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5126,7 +5126,7 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
 		sizeof(struct udphdr) + sizeof(struct vxlanhdr) ||
 	    !adapter->vxlan_port ||
 	    udp_hdr(skb)->dest != adapter->vxlan_port)
-		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+		return features & ~netdev_csum_gso_features_mask;
 
 	return features;
 }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index df3f46d7f217..dccb20072d28 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;
 }
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index a42148582779..513ec9e7f037 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1512,7 +1512,7 @@ static netdev_features_t fm10k_features_check(struct sk_buff *skb,
 	if (!skb->encapsulation || fm10k_tx_encap_offload(skb))
 		return features;
 
-	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	return features & ~netdev_csum_gso_features_mask;
 }
 
 static const struct net_device_ops fm10k_netdev_ops = {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 69ac22c7e800..007931b7fcd0 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13237,7 +13237,7 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
 
 	return features;
 out_err:
-	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	return features & ~netdev_csum_gso_features_mask;
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 55ab0229179f..afea95a58fbd 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4306,7 +4306,7 @@ static netdev_features_t iavf_features_check(struct sk_buff *skb,
 
 	return features;
 out_err:
-	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	return features & ~netdev_csum_gso_features_mask;
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 34a859ecae0d..81d8e3057808 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -8944,7 +8944,7 @@ ice_features_check(struct sk_buff *skb,
 
 	return features;
 out_rm_features:
-	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	return features & ~netdev_csum_gso_features_mask;
 }
 
 static const struct net_device_ops ice_netdev_safe_mode_ops = {
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 594a650b6bdc..be5197b5efc4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2695,7 +2695,7 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
 		if (!priv->vxlan_port ||
 		    (ip_hdr(skb)->version != 4) ||
 		    (udp_hdr(skb)->dest != priv->vxlan_port))
-			features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+			features &= ~netdev_csum_gso_features_mask;
 	}
 
 	return features;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
index 0ae4e12ce528..f0f6251a5d87 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
@@ -121,7 +121,7 @@ mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features)
 
 	/* Disable CSUM and GSO for software IPsec */
 out_disable:
-	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	return features & ~netdev_csum_gso_features_mask;
 }
 
 static inline bool
@@ -161,7 +161,7 @@ static inline bool mlx5e_ipsec_eseg_meta(struct mlx5_wqe_eth_seg *eseg)
 static inline bool mlx5_ipsec_is_rx_flow(struct mlx5_cqe64 *cqe) { return false; }
 static inline netdev_features_t
 mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features)
-{ return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); }
+{ return features & ~netdev_csum_gso_features_mask; }
 
 static inline bool
 mlx5e_ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index d858667736a3..c32468f81500 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4465,7 +4465,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
 
 out:
 	/* Disable CSUM and GSO if the udp dport is not offloaded by HW */
-	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	return features & ~netdev_csum_gso_features_mask;
 }
 
 netdev_features_t mlx5e_features_check(struct sk_buff *skb,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index cf4d6f1129fa..b9bade6cd50e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1806,7 +1806,7 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
 		l4_hdr = ipv6_hdr(skb)->nexthdr;
 		break;
 	default:
-		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+		return features & ~netdev_csum_gso_features_mask;
 	}
 
 	if (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
@@ -1815,7 +1815,7 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
 	    (l4_hdr == IPPROTO_UDP &&
 	     (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
 	      sizeof(struct udphdr) + sizeof(struct vxlanhdr))))
-		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+		return features & ~netdev_csum_gso_features_mask;
 
 	return features;
 }
diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c
index 7c2af482192d..a6f28549f4b4 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -1790,13 +1790,12 @@ netdev_features_t qede_features_check(struct sk_buff *skb,
 			     skb_transport_header(skb)) > hdrlen ||
 			     (ntohs(udp_hdr(skb)->dest) != vxln_port &&
 			      ntohs(udp_hdr(skb)->dest) != gnv_port))
-				return features & ~(NETIF_F_CSUM_MASK |
-						    NETIF_F_GSO_MASK);
+				return features & ~netdev_csum_gso_features_mask;
 		} else if (l4_proto == IPPROTO_IPIP) {
 			/* IPIP tunnels are unknown to the device or at least unsupported natively,
 			 * offloads for them can't be done trivially, so disable them for such skb.
 			 */
-			return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+			return features & ~netdev_csum_gso_features_mask;
 		}
 	}
 
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index a929a1aaba92..b6e0e4855821 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -1365,10 +1365,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/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 954daf464abb..ef00f1d87876 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -1378,10 +1378,9 @@ netdev_features_t efx_siena_features_check(struct sk_buff *skb,
 			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/usb/r8152.c b/drivers/net/usb/r8152.c
index 5e11eaab71f5..218e10ee5442 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2768,7 +2768,7 @@ rtl8152_features_check(struct sk_buff *skb, struct net_device *dev,
 
 	if ((mss || skb->ip_summed == CHECKSUM_PARTIAL) &&
 	    skb_transport_offset(skb) > max_offset)
-		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+		features &= ~netdev_csum_gso_features_mask;
 	else if ((skb->len + sizeof(struct tx_desc)) > agg_buf_sz)
 		features &= ~NETIF_F_GSO_MASK;
 
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 25b3243a9630..abc2aeb0559e 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -277,7 +277,7 @@ netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
 			l4_proto = ipv6_hdr(skb)->nexthdr;
 			break;
 		default:
-			return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+			return features & ~netdev_csum_gso_features_mask;
 		}
 
 		switch (l4_proto) {
@@ -288,11 +288,11 @@ netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
 			if (port != GENEVE_UDP_PORT &&
 			    port != IANA_VXLAN_UDP_PORT &&
 			    port != VXLAN_UDP_PORT) {
-				return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+				return features & ~netdev_csum_gso_features_mask;
 			}
 			break;
 		default:
-			return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+			return features & ~netdev_csum_gso_features_mask;
 		}
 	}
 	return features;
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index bca5b01af247..60a8675976c2 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -373,7 +373,7 @@ static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
 	      sizeof(struct udphdr) + sizeof(struct vxlanhdr)) ||
 	     (skb->ip_summed != CHECKSUM_NONE &&
 	      !can_checksum_protocol(features, inner_eth_hdr(skb)->h_proto))))
-		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+		return features & ~netdev_csum_gso_features_mask;
 
 	return features;
 }
diff --git a/net/core/dev.c b/net/core/dev.c
index 9603bac63ffb..7e600c69abe5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3487,7 +3487,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;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 11/36] treewide: replace NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM by netdev_ip_csum_features
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (9 preceding siblings ...)
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 10/36] treewide: replace NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK by netdev_csum_gso_features_mask Jian Shen
@ 2022-08-10  3:05 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 12/36] treewide: replace NETIF_F_TSO | NETIF_F_TSO6 by netdev_general_tso_features Jian Shen
                   ` (24 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:05 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the expression "NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM" by
netdev_ip_csum_features, make it simple to use netdev features
helpers later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 arch/um/drivers/vector_kern.c                        |  2 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c             |  2 +-
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c     |  6 +++---
 drivers/net/ethernet/hisilicon/hns3/hns3_enet.c      |  2 +-
 drivers/net/ethernet/ibm/ibmvnic.c                   |  3 +--
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c      | 11 +++++------
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c  |  6 +++---
 drivers/net/ethernet/netronome/nfp/nfp_net_repr.c    |  5 +++--
 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c |  3 +--
 drivers/net/ethernet/sfc/ef10.c                      |  2 +-
 drivers/net/ethernet/synopsys/dwc-xlgmac-common.c    |  6 ++----
 drivers/net/usb/smsc75xx.c                           |  2 +-
 include/linux/netdev_features_helper.h               |  4 ++--
 include/net/udp.h                                    |  2 +-
 net/8021q/vlan_dev.c                                 |  2 +-
 net/core/dev.c                                       | 10 +++++-----
 16 files changed, 32 insertions(+), 36 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 548265312743..1d59522a50d8 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1339,7 +1339,7 @@ static void vector_net_tx_timeout(struct net_device *dev, unsigned int txqueue)
 static netdev_features_t vector_fix_features(struct net_device *dev,
 	netdev_features_t features)
 {
-	features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
+	features &= ~netdev_ip_csum_features;
 	return features;
 }
 
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index f342bb853189..135c6e95b6f1 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2203,7 +2203,7 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 		features |= vxlan_base;
 	}
 
-	if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
+	if (features & netdev_ip_csum_features) {
 		if (!(features & NETIF_F_GSO_UDP_TUNNEL_CSUM)) {
 			netdev_notice(netdev,
 				      "forcing tx udp tunnel checksumming on\n");
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index d3c51e1a7c82..8248e10717b9 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -2440,8 +2440,8 @@ static int dpaa2_eth_set_features(struct net_device *net_dev,
 			return err;
 	}
 
-	if (changed & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
-		enable = !!(features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM));
+	if (changed & netdev_ip_csum_features) {
+		enable = !!(features & netdev_ip_csum_features);
 		err = dpaa2_eth_set_tx_csum(priv, enable);
 		if (err)
 			return err;
@@ -4700,7 +4700,7 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
 		goto err_csum;
 
 	err = dpaa2_eth_set_tx_csum(priv,
-				    !!(net_dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)));
+				    !!(net_dev->features & netdev_ip_csum_features));
 	if (err)
 		goto err_csum;
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index dccb20072d28..3213322fcb08 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -3304,7 +3304,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;
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index c0ae18a2b601..43f12a96cf90 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4884,8 +4884,7 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 	if (buf->tcp_ipv6_chksum || buf->udp_ipv6_chksum)
 		adapter->netdev->hw_features |= NETIF_F_IPV6_CSUM;
 
-	if ((adapter->netdev->features &
-	    (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
+	if ((adapter->netdev->features & netdev_ip_csum_features))
 		adapter->netdev->hw_features |= NETIF_F_RXCSUM;
 
 	if (buf->large_tx_ipv4)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 38c5ab6a5126..d693c6580e27 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1266,7 +1266,7 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
 static void mvpp2_set_hw_csum(struct mvpp2_port *port,
 			      enum mvpp2_bm_pool_log_num new_long_pool)
 {
-	const netdev_features_t csums = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	const netdev_features_t csums = netdev_ip_csum_features;
 
 	/* Update L4 checksum when jumbo enable/disable on port.
 	 * Only port 0 supports hardware checksum offload due to
@@ -1341,12 +1341,11 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
 
 		/* Update L4 checksum when jumbo enable/disable on port */
 		if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
-			dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-			dev->hw_features &= ~(NETIF_F_IP_CSUM |
-					      NETIF_F_IPV6_CSUM);
+			dev->features &= ~netdev_ip_csum_features;
+			dev->hw_features &= ~netdev_ip_csum_features;
 		} else {
-			dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-			dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+			dev->features |= netdev_ip_csum_features;
+			dev->hw_features |= netdev_ip_csum_features;
 		}
 	}
 
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index b9bade6cd50e..1ab570715dfb 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1678,8 +1678,8 @@ static int nfp_net_set_features(struct net_device *netdev,
 			new_ctrl &= ~NFP_NET_CFG_CTRL_RXCSUM_ANY;
 	}
 
-	if (changed & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
-		if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))
+	if (changed & netdev_ip_csum_features) {
+		if (features & netdev_ip_csum_features)
 			new_ctrl |= NFP_NET_CFG_CTRL_TXCSUM;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_TXCSUM;
@@ -2357,7 +2357,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 		nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY;
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_TXCSUM) {
-		netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+		netdev->hw_features |= netdev_ip_csum_features;
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_TXCSUM;
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_GATHER) {
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 8b77582bdfa0..e63788a66ff7 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"
@@ -243,7 +244,7 @@ nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
 	lower_dev = repr->dst->u.port_info.lower_dev;
 
 	lower_features = lower_dev->features;
-	if (lower_features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))
+	if (lower_features & netdev_ip_csum_features)
 		lower_features |= NETIF_F_HW_CSUM;
 
 	features = netdev_intersect_features(features, lower_features);
@@ -344,7 +345,7 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 	if (repr_cap & NFP_NET_CFG_CTRL_RXCSUM_ANY)
 		netdev->hw_features |= NETIF_F_RXCSUM;
 	if (repr_cap & NFP_NET_CFG_CTRL_TXCSUM)
-		netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+		netdev->hw_features |= netdev_ip_csum_features;
 	if (repr_cap & NFP_NET_CFG_CTRL_GATHER)
 		netdev->hw_features |= NETIF_F_SG;
 	if ((repr_cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
index ba194698cc14..0b06f9875b56 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
@@ -437,8 +437,7 @@ static void rmnet_map_v4_checksum_uplink_packet(struct sk_buff *skb,
 	ul_header = (struct rmnet_map_ul_csum_header *)
 		    skb_push(skb, sizeof(struct rmnet_map_ul_csum_header));
 
-	if (unlikely(!(orig_dev->features &
-		     (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))))
+	if (unlikely(!(orig_dev->features & netdev_ip_csum_features)))
 		goto sw_csum;
 
 	if (skb->ip_summed != CHECKSUM_PARTIAL)
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 5e0d21475574..064d6f224af8 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;
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
index 5c9b6c90942b..c5c53269c2f8 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
@@ -182,11 +182,9 @@ static int xlgmac_init(struct xlgmac_pdata *pdata)
 		netdev->hw_features = NETIF_F_TSO;
 		netdev->hw_features |= NETIF_F_TSO6;
 		netdev->hw_features |= NETIF_F_SG;
-		netdev->hw_features |= NETIF_F_IP_CSUM;
-		netdev->hw_features |= NETIF_F_IPV6_CSUM;
+		netdev->hw_features |= netdev_ip_csum_features;
 	} else if (pdata->hw_feat.tx_coe) {
-		netdev->hw_features = NETIF_F_IP_CSUM;
-		netdev->hw_features |= NETIF_F_IPV6_CSUM;
+		netdev->hw_features = netdev_ip_csum_features;
 	}
 
 	if (pdata->hw_feat.rx_coe) {
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 34b79291e159..8aa7a0417476 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1479,7 +1479,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
 	INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write);
 
 	if (DEFAULT_TX_CSUM_ENABLE)
-		dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+		dev->net->features |= netdev_ip_csum_features;
 
 	if (DEFAULT_RX_CSUM_ENABLE)
 		dev->net->features |= NETIF_F_RXCSUM;
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h
index 5423927d139b..e096786e4b7a 100644
--- a/include/linux/netdev_features_helper.h
+++ b/include/linux/netdev_features_helper.h
@@ -690,9 +690,9 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
 {
 	if ((f1 ^ f2) & 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;
diff --git a/include/net/udp.h b/include/net/udp.h
index 5ee88ddf79c3..13887234a241 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -464,7 +464,7 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk,
 	 * asks for the final checksum values
 	 */
 	if (!inet_get_convert_csum(sk))
-		features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+		features |= netdev_ip_csum_features;
 
 	/* UDP segmentation expects packets of type CHECKSUM_PARTIAL or
 	 * CHECKSUM_NONE in __udp_gso_segment. UDP GRO indeed builds partial
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 75d12ff0d146..3af719812f00 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -660,7 +660,7 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
 	/* Add HW_CSUM setting to preserve user ability to control
 	 * checksum offload on the vlan device.
 	 */
-	if (lower_features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
+	if (lower_features & netdev_ip_csum_features)
 		lower_features |= NETIF_F_HW_CSUM;
 	features = netdev_intersect_features(features, lower_features);
 	features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE);
diff --git a/net/core/dev.c b/net/core/dev.c
index 7e600c69abe5..ae2c44624732 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3642,7 +3642,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):
@@ -9608,9 +9608,9 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
 {
 	/* 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. */
@@ -9685,8 +9685,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) {
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 12/36] treewide: replace NETIF_F_TSO | NETIF_F_TSO6 by netdev_general_tso_features
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (10 preceding siblings ...)
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 11/36] treewide: replace NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM by netdev_ip_csum_features Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 13/36] treewide: replace VLAN tag feature array by const vlan features Jian Shen
                   ` (23 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the expression "NETIF_F_TSO | NETIF_F_TSO6" by
netdev_general_tso_features, make it simple to use netdev
features helpers later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/atheros/alx/main.c              |  2 +-
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c      |  2 +-
 drivers/net/ethernet/broadcom/tg3.c                  |  2 +-
 drivers/net/ethernet/cisco/enic/enic_main.c          |  7 ++++---
 drivers/net/ethernet/hisilicon/hns/hns_enet.c        |  9 ++++-----
 drivers/net/ethernet/ibm/ibmveth.c                   |  9 ++++-----
 drivers/net/ethernet/intel/e1000e/netdev.c           | 11 ++++-------
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c       |  2 +-
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c  |  6 +++---
 drivers/net/ethernet/netronome/nfp/nfp_net_repr.c    |  2 +-
 drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c |  4 ++--
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c       |  2 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c     |  4 ++--
 drivers/net/ethernet/realtek/r8169_main.c            |  3 ++-
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c    |  2 +-
 drivers/net/ethernet/synopsys/dwc-xlgmac-common.c    |  3 +--
 drivers/net/tap.c                                    |  2 +-
 drivers/net/virtio_net.c                             |  4 ++--
 drivers/s390/net/qeth_l2_main.c                      |  2 +-
 drivers/s390/net/qeth_l3_main.c                      |  2 +-
 20 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 7f5cb50f4b66..2de5fb1ab3de 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -1102,7 +1102,7 @@ static netdev_features_t alx_fix_features(struct net_device *netdev,
 					  netdev_features_t features)
 {
 	if (netdev->mtu > ALX_MAX_TSO_PKT_SIZE)
-		features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+		features &= ~netdev_general_tso_features;
 
 	return features;
 }
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 220253cec3c2..1d54ee4f6147 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -521,7 +521,7 @@ static netdev_features_t atl1c_fix_features(struct net_device *netdev,
 
 	if (hw->nic_type != athr_mt) {
 		if (netdev->mtu > MAX_TSO_FRAME_SIZE)
-			features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+			features &= ~netdev_general_tso_features;
 	}
 
 	return features;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index db1e9d810b41..116b379031e2 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -7877,7 +7877,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
 	}
 
 	segs = skb_gso_segment(skb, tp->dev->features &
-				    ~(NETIF_F_TSO | NETIF_F_TSO6));
+				    ~netdev_general_tso_features);
 	if (IS_ERR(segs) || !segs)
 		goto tg3_tso_bug_end;
 
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index d999b3af2f8a..afed961f2334 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2903,9 +2903,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 	if (ENIC_SETTING(enic, TXCSUM))
 		netdev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM;
-	if (ENIC_SETTING(enic, TSO))
-		netdev->hw_features |= NETIF_F_TSO |
-			NETIF_F_TSO6 | NETIF_F_TSO_ECN;
+	if (ENIC_SETTING(enic, TSO)) {
+		netdev->hw_features |= netdev_general_tso_features;
+		netdev->hw_features |= NETIF_F_TSO_ECN;
+	}
 	if (ENIC_SETTING(enic, RSS))
 		netdev->hw_features |= NETIF_F_RXHASH;
 	if (ENIC_SETTING(enic, RXCSUM))
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index c7556817e6a4..3a5a2adba3a2 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1773,11 +1773,11 @@ static int hns_nic_set_features(struct net_device *netdev,
 
 	switch (priv->enet_ver) {
 	case AE_VERSION_1:
-		if (features & (NETIF_F_TSO | NETIF_F_TSO6))
+		if (features & netdev_general_tso_features)
 			netdev_info(netdev, "enet v1 do not support tso!\n");
 		break;
 	default:
-		if (features & (NETIF_F_TSO | NETIF_F_TSO6)) {
+		if (features & netdev_general_tso_features) {
 			priv->ops.fill_desc = fill_tso_desc;
 			priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tso;
 			/* The chip only support 7*4096 */
@@ -2166,8 +2166,7 @@ static void hns_nic_set_priv_ops(struct net_device *netdev)
 		priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tx;
 	} else {
 		priv->ops.get_rxd_bnum = get_v2rx_desc_bnum;
-		if ((netdev->features & NETIF_F_TSO) ||
-		    (netdev->features & NETIF_F_TSO6)) {
+		if (netdev->features & netdev_general_tso_features) {
 			priv->ops.fill_desc = fill_tso_desc;
 			priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tso;
 			/* This chip only support 7*4096 */
@@ -2365,7 +2364,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
 	case AE_VERSION_2:
 		netdev_active_features_set_array(ndev, &hns_v2_feature_set);
 		netdev_hw_features_set_array(ndev, &hns_hw_feature_set);
-		ndev->vlan_features |= NETIF_F_TSO | NETIF_F_TSO6;
+		ndev->vlan_features |= netdev_general_tso_features;
 		ndev->max_mtu = MAC_MAX_MTU_V2 -
 				(ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
 		break;
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index b45b7ff892ef..32ad4087a43d 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -872,7 +872,7 @@ static int ibmveth_set_tso(struct net_device *dev, u32 data)
 					   set_attr, clr_attr, &ret_attr);
 
 			if (data == 1)
-				dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+				dev->features &= ~netdev_general_tso_features;
 			rc1 = -EIO;
 
 		} else {
@@ -901,7 +901,7 @@ static int ibmveth_set_features(struct net_device *dev,
 {
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
 	int rx_csum = !!(features & NETIF_F_RXCSUM);
-	int large_send = !!(features & (NETIF_F_TSO | NETIF_F_TSO6));
+	int large_send = !!(features & netdev_general_tso_features);
 	int rc1 = 0, rc2 = 0;
 
 	if (rx_csum != adapter->rx_csum) {
@@ -915,8 +915,7 @@ static int ibmveth_set_features(struct net_device *dev,
 	if (large_send != adapter->large_send) {
 		rc2 = ibmveth_set_tso(dev, large_send);
 		if (rc2 && !adapter->large_send)
-			dev->features =
-				features & ~(NETIF_F_TSO | NETIF_F_TSO6);
+			dev->features = features & ~netdev_general_tso_features;
 	}
 
 	return rc1 ? rc1 : rc2;
@@ -1696,7 +1695,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 	/* If running older firmware, TSO should not be enabled by default */
 	if (ret == H_SUCCESS && (ret_attr & IBMVETH_ILLAN_LRG_SND_SUPPORT) &&
 	    !old_large_send) {
-		netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
+		netdev->hw_features |= netdev_general_tso_features;
 		netdev->features |= netdev->hw_features;
 	} else {
 		netdev->hw_features |= NETIF_F_TSO;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 60b4c6ee5bd8..7ef3e3e56dfa 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -5302,20 +5302,17 @@ static void e1000_watchdog_task(struct work_struct *work)
 				case SPEED_10:
 				case SPEED_100:
 					e_info("10/100 speed: disabling TSO\n");
-					netdev->features &= ~NETIF_F_TSO;
-					netdev->features &= ~NETIF_F_TSO6;
+					netdev->features &= ~netdev_general_tso_features;
 					break;
 				case SPEED_1000:
-					netdev->features |= NETIF_F_TSO;
-					netdev->features |= NETIF_F_TSO6;
+					netdev->features |= netdev_general_tso_features;
 					break;
 				default:
 					/* oops */
 					break;
 				}
 				if (hw->mac.type == e1000_pch_spt) {
-					netdev->features &= ~NETIF_F_TSO;
-					netdev->features &= ~NETIF_F_TSO6;
+					netdev->features &= ~netdev_general_tso_features;
 				}
 			}
 
@@ -7327,7 +7324,7 @@ static int e1000_set_features(struct net_device *netdev,
 	netdev_features_t changed = features ^ netdev->features;
 	netdev_features_t changeable;
 
-	if (changed & (NETIF_F_TSO | NETIF_F_TSO6))
+	if (changed & netdev_general_tso_features)
 		adapter->flags |= FLAG_TSO_FORCE;
 
 	netdev_features_zero(&changeable);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index be5197b5efc4..019dbd5ae79f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3361,7 +3361,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_array(dev, &mlx4_hw_feature_set1);
 	if (mdev->LSO_support)
-		dev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
+		dev->hw_features |= netdev_general_tso_features;
 
 	if (mdev->dev->caps.tunnel_offload_mode ==
 	    MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 1ab570715dfb..bcf89fe69cc4 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1685,8 +1685,8 @@ static int nfp_net_set_features(struct net_device *netdev,
 			new_ctrl &= ~NFP_NET_CFG_CTRL_TXCSUM;
 	}
 
-	if (changed & (NETIF_F_TSO | NETIF_F_TSO6)) {
-		if (features & (NETIF_F_TSO | NETIF_F_TSO6))
+	if (changed & netdev_general_tso_features) {
+		if (features & netdev_general_tso_features)
 			new_ctrl |= nn->cap & NFP_NET_CFG_CTRL_LSO2 ?:
 					      NFP_NET_CFG_CTRL_LSO;
 		else
@@ -2366,7 +2366,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 	}
 	if ((nn->cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
 	    nn->cap & NFP_NET_CFG_CTRL_LSO2) {
-		netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
+		netdev->hw_features |= netdev_general_tso_features;
 		nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_LSO2 ?:
 					 NFP_NET_CFG_CTRL_LSO;
 	}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index e63788a66ff7..3e670133e27a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -350,7 +350,7 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 		netdev->hw_features |= NETIF_F_SG;
 	if ((repr_cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
 	    repr_cap & NFP_NET_CFG_CTRL_LSO2)
-		netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
+		netdev->hw_features |= netdev_general_tso_features;
 	if (repr_cap & NFP_NET_CFG_CTRL_RSS_ANY)
 		netdev->hw_features |= NETIF_F_RXHASH;
 	if (repr_cap & NFP_NET_CFG_CTRL_VXLAN) {
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 72cbf78344b5..993d0ee6db01 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1881,8 +1881,8 @@ netxen_tso_check(struct net_device *netdev,
 		vlan_oob = 1;
 	}
 
-	if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
-			skb_shinfo(skb)->gso_size > 0) {
+	if ((netdev->features & netdev_general_tso_features) &&
+	    skb_shinfo(skb)->gso_size > 0) {
 
 		hdr_len = skb_tcp_all_headers(skb);
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 2401cbc015f0..7039925bc566 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1055,7 +1055,7 @@ static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
 		netdev_features_clear_array(&qlcnic_csum_feature_set, &features);
 
 		if (QLCNIC_IS_TSO_CAPABLE(adapter))
-			features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+			features &= ~netdev_general_tso_features;
 		adapter->rx_csum = 0;
 	}
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index f8c043914d6a..4c19fc626385 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2300,8 +2300,8 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 	netdev_vlan_features_set_array(netdev, &qlcnic_vlan_feature_set);
 
 	if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
-		netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
-		netdev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
+		netdev->features |= netdev_general_tso_features;
+		netdev->vlan_features |= netdev_general_tso_features;
 	}
 
 	if (qlcnic_vlan_tx_check(adapter))
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index b999f129490c..55f67e0c1280 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5451,7 +5451,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 * enable them. Use at own risk!
 	 */
 	if (rtl_chip_supports_csum_v2(tp)) {
-		dev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6;
+		dev->hw_features |= NETIF_F_SG;
+		dev->hw_features |= netdev_general_tso_features;
 		netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2);
 		netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V2);
 	} else {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 23b80ddad54d..0fb2070f592a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7148,7 +7148,7 @@ int stmmac_dvr_probe(struct device *device,
 	}
 
 	if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
-		ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
+		ndev->hw_features |= netdev_general_tso_features;
 		if (priv->plat->has_gmac4)
 			ndev->hw_features |= NETIF_F_GSO_UDP_L4;
 		priv->tso = true;
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
index c5c53269c2f8..68b4bc10c8a9 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
@@ -179,8 +179,7 @@ static int xlgmac_init(struct xlgmac_pdata *pdata)
 
 	/* Set device features */
 	if (pdata->hw_feat.tso) {
-		netdev->hw_features = NETIF_F_TSO;
-		netdev->hw_features |= NETIF_F_TSO6;
+		netdev->hw_features = netdev_general_tso_features;
 		netdev->hw_features |= NETIF_F_SG;
 		netdev->hw_features |= netdev_ip_csum_features;
 	} else if (pdata->hw_feat.tx_coe) {
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 7b1c1e724c43..7d5446500d67 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -973,7 +973,7 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
 	 * When user space turns off TSO, we turn off GSO/LRO so that
 	 * user-space will not receive TSO frames.
 	 */
-	if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6))
+	if (feature_mask & netdev_general_tso_features)
 		netdev_features_set_array(&tap_rx_offload_feature_set, &features);
 	else
 		netdev_features_clear_array(&tap_rx_offload_feature_set, &features);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index ec8e1b3108c3..c40d80f25809 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3515,8 +3515,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 			dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
 
 		if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
-			dev->hw_features |= NETIF_F_TSO
-				| NETIF_F_TSO_ECN | NETIF_F_TSO6;
+			dev->hw_features |= netdev_general_tso_features;
+			dev->hw_features |= NETIF_F_TSO_ECN;
 		}
 		/* Individual feature bits: what can host handle? */
 		if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4))
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 2d4436cbcb47..83950ce159f9 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1126,7 +1126,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
 		card->dev->vlan_features |= NETIF_F_TSO6;
 	}
 
-	if (card->dev->hw_features & (NETIF_F_TSO | NETIF_F_TSO6)) {
+	if (card->dev->hw_features & netdev_general_tso_features) {
 		card->dev->needed_headroom = sizeof(struct qeth_hdr_tso);
 		netif_keep_dst(card->dev);
 		netif_set_tso_max_size(card->dev,
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 8628599ed692..639c05a175ba 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1911,7 +1911,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 				NETIF_F_HW_VLAN_CTAG_RX;
 
 	netif_keep_dst(card->dev);
-	if (card->dev->hw_features & (NETIF_F_TSO | NETIF_F_TSO6))
+	if (card->dev->hw_features & netdev_general_tso_features)
 		netif_set_tso_max_size(card->dev,
 				       PAGE_SIZE * (QETH_MAX_BUFFER_ELEMENTS(card) - 1));
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 13/36] treewide: replace VLAN tag feature array by const vlan features
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (11 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 12/36] treewide: replace NETIF_F_TSO | NETIF_F_TSO6 by netdev_general_tso_features Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 14/36] net: simplify the netdev features expressions for xxx_gso_segment Jian Shen
                   ` (22 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the vlan features relative expressions by
const vlan features, make it simple to use netdev
features helpers later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/bonding/bond_main.c               |  5 ++-
 drivers/net/ethernet/amd/amd8111e.c           |  2 +-
 drivers/net/ethernet/atheros/atlx/atl2.c      |  2 +-
 drivers/net/ethernet/broadcom/bnx2.c          |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     |  6 ++--
 drivers/net/ethernet/broadcom/tg3.c           |  4 +--
 .../net/ethernet/cavium/liquidio/lio_main.c   |  4 +--
 .../ethernet/cavium/liquidio/lio_vf_main.c    |  4 +--
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  4 +--
 drivers/net/ethernet/cisco/enic/enic_main.c   |  2 +-
 drivers/net/ethernet/freescale/gianfar.c      |  3 +-
 .../net/ethernet/freescale/gianfar_ethtool.c  |  3 +-
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  4 +--
 drivers/net/ethernet/intel/i40e/i40e_main.c   |  4 +--
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 32 +++++++-----------
 drivers/net/ethernet/intel/ice/ice_main.c     | 33 +++++++------------
 drivers/net/ethernet/intel/igb/igb_main.c     | 11 +++----
 drivers/net/ethernet/intel/igbvf/netdev.c     |  4 +--
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |  4 +--
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |  4 +--
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  6 ++--
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  3 +-
 drivers/net/ethernet/marvell/sky2.c           |  5 ++-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  2 +-
 .../ethernet/microchip/lan966x/lan966x_main.c |  3 +-
 drivers/net/ethernet/natsemi/ns83820.c        |  2 +-
 drivers/net/ethernet/nvidia/forcedeth.c       | 10 +++---
 drivers/net/ethernet/qualcomm/emac/emac.c     |  2 +-
 .../net/ethernet/samsung/sxgbe/sxgbe_common.h |  7 +---
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  8 ++---
 drivers/net/ethernet/via/via-rhine.c          |  4 +--
 drivers/net/ifb.c                             |  3 +-
 drivers/net/net_failover.c                    |  4 +--
 drivers/net/team/team.c                       |  7 ++--
 drivers/net/tun.c                             |  4 +--
 drivers/net/veth.c                            |  6 +---
 drivers/net/vmxnet3/vmxnet3_drv.c             |  3 +-
 drivers/s390/net/qeth_l3_main.c               |  3 +-
 drivers/staging/qlge/qlge_main.c              |  4 +--
 include/linux/if_vlan.h                       |  4 +--
 net/bridge/br_device.c                        |  3 +-
 net/core/dev.c                                |  3 +-
 net/openvswitch/vport-internal_dev.c          |  2 +-
 43 files changed, 80 insertions(+), 155 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a7783abec601..ca23f18fa7fc 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1499,8 +1499,7 @@ static void bond_compute_features(struct bonding *bond)
 done:
 	bond_dev->vlan_features = vlan_features;
 	bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
-				    NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_HW_VLAN_STAG_TX;
+				    netdev_tx_vlan_features;
 #ifdef CONFIG_XFRM_OFFLOAD
 	bond_dev->hw_enc_features |= xfrm_features;
 #endif /* CONFIG_XFRM_OFFLOAD */
@@ -5772,7 +5771,7 @@ void bond_setup(struct net_device *bond_dev)
 
 	bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
 	bond_dev->features |= bond_dev->hw_features;
-	bond_dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
+	bond_dev->features |= netdev_tx_vlan_features;
 #ifdef CONFIG_XFRM_OFFLOAD
 	bond_dev->hw_features |= BOND_XFRM_FEATURES;
 	/* Only enable XFRM features if this is an active-backup config */
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
index 5d1baa01360f..d94d982357b1 100644
--- a/drivers/net/ethernet/amd/amd8111e.c
+++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -1791,7 +1791,7 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 #if AMD8111E_VLAN_TAG_USED
-	dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+	dev->features |= netdev_ctag_vlan_offload_features;
 #endif
 
 	lp = netdev_priv(dev);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index bbc4d7b08a49..1d647c4d1d44 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1390,7 +1390,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_sw_init;
 
 	netdev->hw_features = NETIF_F_HW_VLAN_CTAG_RX;
-	netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
+	netdev->features |= netdev_ctag_vlan_offload_features;
 
 	/* Init PHY as early as possible due to power saving issue  */
 	atl2_phy_init(&adapter->hw);
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 0e779e5dee9a..4a03b8c9f37a 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8596,7 +8596,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
 
 	dev->vlan_features = dev->hw_features;
-	dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+	dev->hw_features |= netdev_ctag_vlan_offload_features;
 	dev->features |= dev->hw_features;
 	dev->priv_flags |= IFF_UNICAST_FLT;
 	dev->min_mtu = MIN_ETHERNET_PACKET_SIZE;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 075c6206325c..04c8ce4fae73 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -2193,10 +2193,8 @@ struct bnxt {
 #define BNXT_TX_STATS_EXT_OFFSET(counter)		\
 	(offsetof(struct tx_port_stats_ext, counter) / 8)
 
-#define BNXT_HW_FEATURE_VLAN_ALL_RX				\
-	(NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)
-#define BNXT_HW_FEATURE_VLAN_ALL_TX				\
-	(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX)
+#define BNXT_HW_FEATURE_VLAN_ALL_RX	netdev_rx_vlan_features
+#define BNXT_HW_FEATURE_VLAN_ALL_TX	netdev_tx_vlan_features
 
 #define I2C_DEV_ADDR_A0				0xa0
 #define I2C_DEV_ADDR_A2				0xa2
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 116b379031e2..3a7bb3db4e47 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17752,8 +17752,8 @@ static int tg3_init_one(struct pci_dev *pdev,
 			features |= NETIF_F_TSO_ECN;
 	}
 
-	dev->features |= features | NETIF_F_HW_VLAN_CTAG_TX |
-			 NETIF_F_HW_VLAN_CTAG_RX;
+	dev->features |= features;
+	dev->features |= netdev_ctag_vlan_offload_features;
 	dev->vlan_features |= features;
 
 	/*
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 9c9c8dee0c7b..b5a963c9dc03 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3599,9 +3599,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 
 		netdev->vlan_features = lio->dev_capability;
 		/* Add any unchangeable hw features */
-		lio->dev_capability |=  NETIF_F_HW_VLAN_CTAG_FILTER |
-					NETIF_F_HW_VLAN_CTAG_RX |
-					NETIF_F_HW_VLAN_CTAG_TX;
+		lio->dev_capability |= netdev_ctag_vlan_features;
 
 		netdev->features = (lio->dev_capability & ~NETIF_F_LRO);
 
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 9e0c176ea7af..23524066fa9a 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -2127,9 +2127,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 
 		netdev->vlan_features = lio->dev_capability;
 		/* Add any unchangeable hw features */
-		lio->dev_capability |= NETIF_F_HW_VLAN_CTAG_FILTER |
-				       NETIF_F_HW_VLAN_CTAG_RX |
-				       NETIF_F_HW_VLAN_CTAG_TX;
+		lio->dev_capability |= netdev_ctag_vlan_features;
 
 		netdev->features = (lio->dev_capability & ~NETIF_F_LRO);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 44404b711e09..eabb2a782d12 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -1048,9 +1048,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_active_features_set_array(netdev, &cxgb_feature_set);
 
 		if (vlan_tso_capable(adapter)) {
-			netdev->features |=
-				NETIF_F_HW_VLAN_CTAG_TX |
-				NETIF_F_HW_VLAN_CTAG_RX;
+			netdev->features |= netdev_ctag_vlan_offload_features;
 			netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
 
 			/* T204: disable TSO */
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index afed961f2334..061375f34d5d 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2894,7 +2894,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->watchdog_timeo = 2 * HZ;
 	enic_set_ethtool_ops(netdev);
 
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+	netdev->features |= netdev_ctag_vlan_offload_features;
 	if (ENIC_SETTING(enic, LOOP)) {
 		netdev->features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 		enic->loop_enable = 1;
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 72a1842794a7..d9b1928d1987 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -3256,8 +3256,7 @@ static int gfar_probe(struct platform_device *ofdev)
 	}
 
 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
-		dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_HW_VLAN_CTAG_RX;
+		dev->hw_features |= netdev_ctag_vlan_offload_features;
 		dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
 	}
 
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 81fb68730138..b4b1b7b7143f 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -511,8 +511,7 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features)
 	struct gfar_private *priv = netdev_priv(dev);
 	int err = 0;
 
-	if (!(changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
-			 NETIF_F_RXCSUM)))
+	if (!(changed & (netdev_ctag_vlan_offload_features | NETIF_F_RXCSUM)))
 		return 0;
 
 	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 513ec9e7f037..2e0e7bc100e8 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1601,9 +1601,7 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
 	 * insertion or stripping on the hardware since it is contained
 	 * in the FTAG and not in the frame itself.
 	 */
-	dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
-			 NETIF_F_HW_VLAN_CTAG_RX |
-			 NETIF_F_HW_VLAN_CTAG_FILTER;
+	dev->features |= netdev_ctag_vlan_features;
 
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 007931b7fcd0..b905eced9d91 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13704,9 +13704,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	/* enable macvlan offloads */
 	netdev->hw_features |= NETIF_F_HW_L2FW_DOFFLOAD;
 
-	hw_features = hw_enc_features		|
-		      NETIF_F_HW_VLAN_CTAG_TX	|
-		      NETIF_F_HW_VLAN_CTAG_RX;
+	hw_features = hw_enc_features | netdev_ctag_vlan_offload_features;
 
 	if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
 		hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index afea95a58fbd..efbd889eea1a 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2125,20 +2125,20 @@ iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
 	 * ETH_P_8021Q so an ethertype is specified if disabling insertion and
 	 * stripping.
 	 */
-	if (features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX))
+	if (features & netdev_stag_vlan_offload_features)
 		vlan_ethertype = ETH_P_8021AD;
-	else if (features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX))
+	else if (features & netdev_ctag_vlan_offload_features)
 		vlan_ethertype = ETH_P_8021Q;
-	else if (prev_features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX))
+	else if (prev_features & netdev_stag_vlan_offload_features)
 		vlan_ethertype = ETH_P_8021AD;
-	else if (prev_features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX))
+	else if (prev_features & netdev_ctag_vlan_offload_features)
 		vlan_ethertype = ETH_P_8021Q;
 	else
 		vlan_ethertype = ETH_P_8021Q;
 
-	if (!(features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_CTAG_RX)))
+	if (!(features & netdev_rx_vlan_features))
 		enable_stripping = false;
-	if (!(features & (NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_VLAN_CTAG_TX)))
+	if (!(features & netdev_tx_vlan_features))
 		enable_insertion = false;
 
 	if (VLAN_ALLOWED(adapter)) {
@@ -4226,10 +4226,7 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
 	return 0;
 }
 
-#define NETIF_VLAN_OFFLOAD_FEATURES	(NETIF_F_HW_VLAN_CTAG_RX | \
-					 NETIF_F_HW_VLAN_CTAG_TX | \
-					 NETIF_F_HW_VLAN_STAG_RX | \
-					 NETIF_F_HW_VLAN_STAG_TX)
+#define NETIF_VLAN_OFFLOAD_FEATURES	netdev_vlan_offload_features
 
 /**
  * iavf_set_features - set the netdev feature flags
@@ -4326,8 +4323,7 @@ iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter)
 
 	/* Enable VLAN features if supported */
 	if (VLAN_ALLOWED(adapter)) {
-		hw_features |= (NETIF_F_HW_VLAN_CTAG_TX |
-				NETIF_F_HW_VLAN_CTAG_RX);
+		hw_features |= netdev_ctag_vlan_offload_features;
 	} else if (VLAN_V2_ALLOWED(adapter)) {
 		struct virtchnl_vlan_caps *vlan_v2_caps =
 			&adapter->vlan_v2_caps;
@@ -4387,8 +4383,7 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 		return features;
 
 	if (VLAN_ALLOWED(adapter)) {
-		features |= NETIF_F_HW_VLAN_CTAG_FILTER |
-			NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX;
+		features |= netdev_ctag_vlan_features;
 	} else if (VLAN_V2_ALLOWED(adapter)) {
 		struct virtchnl_vlan_caps *vlan_v2_caps =
 			&adapter->vlan_v2_caps;
@@ -4517,15 +4512,12 @@ iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
 					      NETIF_F_HW_VLAN_STAG_FILTER))
 		requested_features &= ~NETIF_F_HW_VLAN_STAG_FILTER;
 
-	if ((requested_features &
-	     (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX)) &&
-	    (requested_features &
-	     (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX)) &&
+	if ((requested_features & netdev_ctag_vlan_offload_features) &&
+	    (requested_features & netdev_stag_vlan_offload_features) &&
 	    adapter->vlan_v2_caps.offloads.ethertype_match ==
 	    VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION) {
 		netdev_warn(adapter->netdev, "cannot support CTAG and STAG VLAN stripping and/or insertion simultaneously since CTAG and STAG offloads are mutually exclusive, clearing STAG offload settings\n");
-		requested_features &= ~(NETIF_F_HW_VLAN_STAG_RX |
-					NETIF_F_HW_VLAN_STAG_TX);
+		requested_features &= ~netdev_stag_vlan_offload_features;
 	}
 
 	return requested_features;
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 81d8e3057808..5c9333da4dfc 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3351,9 +3351,7 @@ static void ice_set_netdev_features(struct net_device *netdev)
 	netdev_features_zero(&csumo_features);
 	netdev_features_set_array(&ice_csumo_feature_set, &csumo_features);
 
-	vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER |
-			 NETIF_F_HW_VLAN_CTAG_TX     |
-			 NETIF_F_HW_VLAN_CTAG_RX;
+	vlano_features = netdev_ctag_vlan_features;
 
 	/* Enable CTAG/STAG filtering by default in Double VLAN Mode (DVM) */
 	if (is_dvm_ena)
@@ -3390,8 +3388,7 @@ static void ice_set_netdev_features(struct net_device *netdev)
 	 * ice_fix_features() ndo callback.
 	 */
 	if (is_dvm_ena)
-		netdev->hw_features |= NETIF_F_HW_VLAN_STAG_RX |
-			NETIF_F_HW_VLAN_STAG_TX;
+		netdev->hw_features |= netdev_stag_vlan_offload_features;
 }
 
 /**
@@ -5730,13 +5727,9 @@ ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
 	return err;
 }
 
-#define NETIF_VLAN_OFFLOAD_FEATURES	(NETIF_F_HW_VLAN_CTAG_RX | \
-					 NETIF_F_HW_VLAN_CTAG_TX | \
-					 NETIF_F_HW_VLAN_STAG_RX | \
-					 NETIF_F_HW_VLAN_STAG_TX)
+#define NETIF_VLAN_OFFLOAD_FEATURES	netdev_vlan_offload_features
 
-#define NETIF_VLAN_FILTERING_FEATURES	(NETIF_F_HW_VLAN_CTAG_FILTER | \
-					 NETIF_F_HW_VLAN_STAG_FILTER)
+#define NETIF_VLAN_FILTERING_FEATURES	netdev_vlan_filter_features
 
 /**
  * ice_fix_features - fix the netdev features flags based on device limitations
@@ -5814,11 +5807,10 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 		}
 	}
 
-	if ((features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX)) &&
-	    (features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX))) {
+	if ((features & netdev_ctag_vlan_offload_features) &&
+	    (features & netdev_stag_vlan_offload_features)) {
 		netdev_warn(netdev, "cannot support CTAG and STAG VLAN stripping and/or insertion simultaneously since CTAG and STAG offloads are mutually exclusive, clearing STAG offload settings\n");
-		features &= ~(NETIF_F_HW_VLAN_STAG_RX |
-			      NETIF_F_HW_VLAN_STAG_TX);
+		features &= ~netdev_stag_vlan_offload_features;
 	}
 
 	return features;
@@ -5843,14 +5835,14 @@ ice_set_vlan_offload_features(struct ice_vsi *vsi, netdev_features_t features)
 
 	vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
 
-	if (features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX))
+	if (features & netdev_stag_vlan_offload_features)
 		vlan_ethertype = ETH_P_8021AD;
-	else if (features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX))
+	else if (features & netdev_ctag_vlan_offload_features)
 		vlan_ethertype = ETH_P_8021Q;
 
-	if (!(features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_CTAG_RX)))
+	if (!(features & netdev_rx_vlan_features))
 		enable_stripping = false;
-	if (!(features & (NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_VLAN_CTAG_TX)))
+	if (!(features & netdev_tx_vlan_features))
 		enable_insertion = false;
 
 	if (enable_stripping)
@@ -5886,8 +5878,7 @@ ice_set_vlan_filtering_features(struct ice_vsi *vsi, netdev_features_t features)
 	/* support Single VLAN Mode (SVM) and Double VLAN Mode (DVM) by checking
 	 * if either bit is set
 	 */
-	if (features &
-	    (NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER))
+	if (features & netdev_vlan_filter_features)
 		err = vlan_ops->ena_rx_filtering(vsi);
 	else
 		err = vlan_ops->dis_rx_filtering(vsi);
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 2fd8d8c94305..578663a47c93 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3310,10 +3310,9 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->features |= NETIF_F_GSO_PARTIAL | gso_partial_features;
 
 	/* copy netdev features into list of user selectable features */
-	netdev->hw_features |= netdev->features |
-			       NETIF_F_HW_VLAN_CTAG_RX |
-			       NETIF_F_HW_VLAN_CTAG_TX |
-			       NETIF_F_RXALL;
+	netdev->hw_features |= netdev->features;
+	netdev->hw_features |= netdev_ctag_vlan_offload_features;
+	netdev->hw_features |= NETIF_F_RXALL;
 
 	if (hw->mac.type >= e1000_i350)
 		netdev->hw_features |= NETIF_F_NTUPLE;
@@ -3325,9 +3324,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->hw_enc_features |= netdev->vlan_features;
 
 	/* set this bit last since it cannot be part of vlan_features */
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
-			    NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_VLAN_CTAG_TX;
+	netdev->features |= netdev_ctag_vlan_features;
 
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 362e26df28b0..07c725474e32 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2803,9 +2803,7 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->hw_enc_features |= netdev->vlan_features;
 
 	/* set this bit last since it cannot be part of vlan_features */
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
-			    NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_VLAN_CTAG_TX;
+	netdev->features |= netdev_ctag_vlan_features;
 
 	/* MTU range: 68 - 9216 */
 	netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 98db7c46e89c..db008c8281ed 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -11046,9 +11046,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->mpls_features |= gso_partial_features;
 
 	/* set this bit last since it cannot be part of vlan_features */
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
-			    NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_VLAN_CTAG_TX;
+	netdev->features |= netdev_ctag_vlan_features;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 095159721a96..d46ab40b2b98 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4645,9 +4645,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->hw_enc_features |= netdev->vlan_features;
 
 	/* set this bit last since it cannot be part of vlan_features */
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
-			    NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_VLAN_CTAG_TX;
+	netdev->features |= netdev_ctag_vlan_features;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index a228447cbb2e..172c715415fa 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -2719,11 +2719,9 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	/* Support TSO on tag interface */
 	netdev->vlan_features |= netdev->features;
-	netdev->hw_features  |= NETIF_F_HW_VLAN_CTAG_TX |
-				NETIF_F_HW_VLAN_STAG_TX;
+	netdev->hw_features  |= netdev_tx_vlan_features;
 	if (pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX |
-				       NETIF_F_HW_VLAN_STAG_RX;
+		netdev->hw_features |= netdev_rx_vlan_features;
 	netdev->features |= netdev->hw_features;
 
 	/* HW supports tc offload but mutually exclusive with n-tuple filters */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 08c82c0d41a4..9aa8fe79bb2b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -653,8 +653,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	netdev->features = netdev->hw_features;
 	/* Support TSO on tag interface */
 	netdev->vlan_features |= netdev->features;
-	netdev->hw_features  |= NETIF_F_HW_VLAN_CTAG_TX |
-				NETIF_F_HW_VLAN_STAG_TX;
+	netdev->hw_features  |= netdev_tx_vlan_features;
 	netdev->features |= netdev->hw_features;
 
 	netdev->hw_features |= NETIF_F_NTUPLE;
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index e3b3b2c7aff3..c9a4b1db43eb 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4346,7 +4346,7 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features)
 	if (changed & NETIF_F_RXHASH)
 		rx_set_rss(dev, features);
 
-	if (changed & (NETIF_F_HW_VLAN_CTAG_TX|NETIF_F_HW_VLAN_CTAG_RX))
+	if (changed & netdev_ctag_vlan_offload_features)
 		sky2_vlan_mode(dev, features);
 
 	return 0;
@@ -4653,8 +4653,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 		dev->hw_features |= NETIF_F_RXHASH;
 
 	if (!(hw->flags & SKY2_HW_VLAN_BROKEN)) {
-		dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_HW_VLAN_CTAG_RX;
+		dev->hw_features |= netdev_ctag_vlan_offload_features;
 		netdev_vlan_features_set_array(dev, &sky2_vlan_feature_set);
 	}
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 92c1de636128..e412cc11ed58 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3900,7 +3900,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 		eth->netdev[id]->hw_features |= NETIF_F_LRO;
 
 	eth->netdev[id]->vlan_features = *eth->soc->hw_features &
-		~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
+		~netdev_ctag_vlan_offload_features;
 	eth->netdev[id]->features |= *eth->soc->hw_features;
 	eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
 
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index 1d6e3b641b2e..738eaa88279a 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -753,8 +753,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
 
 	dev->netdev_ops = &lan966x_port_netdev_ops;
 	dev->ethtool_ops = &lan966x_ethtool_ops;
-	dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
-			 NETIF_F_HW_VLAN_STAG_TX;
+	dev->features |= netdev_tx_vlan_features;
 	dev->needed_headroom = IFH_LEN * sizeof(u32);
 
 	eth_hw_addr_gen(dev, lan966x->base_mac, p + 1);
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index 49ea130c9067..dba583d60d8e 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -2149,7 +2149,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
 
 #ifdef NS83820_VLAN_ACCEL_SUPPORT
 	/* We also support hardware vlan acceleration */
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+	ndev->features |= netdev_ctag_vlan_offload_features;
 #endif
 
 	if (using_dac) {
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 71c5363084e6..5b957cdc118e 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4931,7 +4931,7 @@ static netdev_features_t nv_fix_features(struct net_device *dev,
 	netdev_features_t features)
 {
 	/* vlan is dependent on rx checksum offload */
-	if (features & (NETIF_F_HW_VLAN_CTAG_TX|NETIF_F_HW_VLAN_CTAG_RX))
+	if (features & netdev_ctag_vlan_offload_features)
 		features |= NETIF_F_RXCSUM;
 
 	return features;
@@ -4985,7 +4985,7 @@ static int nv_set_features(struct net_device *dev, netdev_features_t features)
 		spin_unlock_irq(&np->lock);
 	}
 
-	if (changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX))
+	if (changed & netdev_ctag_vlan_offload_features)
 		nv_vlan_mode(dev, features);
 
 	return 0;
@@ -5824,8 +5824,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 	np->vlanctl_bits = 0;
 	if (id->driver_data & DEV_HAS_VLAN) {
 		np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE;
-		dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX |
-				    NETIF_F_HW_VLAN_CTAG_TX;
+		dev->hw_features |= netdev_ctag_vlan_offload_features;
 	}
 
 	dev->features |= dev->hw_features;
@@ -6127,8 +6126,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 		 dev->features & NETIF_F_HIGHDMA ? "highdma " : "",
 		 dev->features & (NETIF_F_IP_CSUM | NETIF_F_SG) ?
 			"csum " : "",
-		 dev->features & (NETIF_F_HW_VLAN_CTAG_RX |
-				  NETIF_F_HW_VLAN_CTAG_TX) ?
+		 dev->features & netdev_ctag_vlan_offload_features ?
 			"vlan " : "",
 		 dev->features & (NETIF_F_LOOPBACK) ?
 			"loopback " : "",
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index c302d50324fb..15ffa63415e1 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -182,7 +182,7 @@ static int emac_set_features(struct net_device *netdev,
 	/* We only need to reprogram the hardware if the VLAN tag features
 	 * have changed, and if it's already running.
 	 */
-	if (!(changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX)))
+	if (!(changed & netdev_ctag_vlan_offload_features))
 		return 0;
 
 	if (!netif_running(netdev))
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
index 0f45107db8dd..1cdd996cfd48 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
@@ -151,12 +151,7 @@ enum dma_irq_status {
 	handle_rx	= BIT(5),
 };
 
-#define NETIF_F_HW_VLAN_ALL     (NETIF_F_HW_VLAN_CTAG_RX |	\
-				 NETIF_F_HW_VLAN_STAG_RX |	\
-				 NETIF_F_HW_VLAN_CTAG_TX |	\
-				 NETIF_F_HW_VLAN_STAG_TX |	\
-				 NETIF_F_HW_VLAN_CTAG_FILTER |	\
-				 NETIF_F_HW_VLAN_STAG_FILTER)
+#define NETIF_F_HW_VLAN_ALL     netdev_all_vlan_features
 
 /* MMC control defines */
 #define SXGBE_MMC_CTRL_CNT_FRZ  0x00000008
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 0fb2070f592a..6ddacc6a7f7a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7198,11 +7198,9 @@ int stmmac_dvr_probe(struct device *device,
 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
 #ifdef STMMAC_VLAN_TAG_USED
 	/* Both mac100 and gmac support receive VLAN tag detection */
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX;
-	if (priv->dma_cap.vlhash) {
-		ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-		ndev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
-	}
+	ndev->features |= netdev_rx_vlan_features;
+	if (priv->dma_cap.vlhash)
+		ndev->features |= netdev_vlan_filter_features;
 	if (priv->dma_cap.vlins) {
 		ndev->features |= NETIF_F_HW_VLAN_CTAG_TX;
 		if (priv->dma_cap.dvlan)
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 509c5e9b29df..1d795114c264 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -971,9 +971,7 @@ static int rhine_init_one_common(struct device *hwdev, u32 quirks,
 		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
 	if (rp->quirks & rqMgmt)
-		dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
-				 NETIF_F_HW_VLAN_CTAG_RX |
-				 NETIF_F_HW_VLAN_CTAG_FILTER;
+		dev->features |= netdev_ctag_vlan_features;
 
 	/* dev->name not defined before register_netdev()! */
 	rc = register_netdev(dev);
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 92ffd1b9849b..656a54a9f6e8 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -328,8 +328,7 @@ static void ifb_setup(struct net_device *dev)
 	dev->features |= ifb_features;
 	dev->hw_features |= dev->features;
 	dev->hw_enc_features |= dev->features;
-	dev->vlan_features |= ifb_features & ~(NETIF_F_HW_VLAN_CTAG_TX |
-					       NETIF_F_HW_VLAN_STAG_TX);
+	dev->vlan_features |= ifb_features & ~netdev_tx_vlan_features;
 
 	dev->flags |= IFF_NOARP;
 	dev->flags &= ~IFF_MULTICAST;
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index d6c2082d0993..50033364b2bd 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -755,9 +755,7 @@ struct failover *net_failover_create(struct net_device *standby_dev)
 	failover_dev->features |= NETIF_F_NETNS_LOCAL;
 
 	failover_dev->hw_features = FAILOVER_VLAN_FEATURES |
-				    NETIF_F_HW_VLAN_CTAG_TX |
-				    NETIF_F_HW_VLAN_CTAG_RX |
-				    NETIF_F_HW_VLAN_CTAG_FILTER;
+				    netdev_ctag_vlan_features;
 
 	failover_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
 	failover_dev->features |= failover_dev->hw_features;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 452d414dff62..eec3c8112d3f 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1024,9 +1024,8 @@ static void __team_compute_features(struct team *team)
 	rcu_read_unlock();
 
 	team->dev->vlan_features = vlan_features;
-	team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
-				     NETIF_F_HW_VLAN_CTAG_TX |
-				     NETIF_F_HW_VLAN_STAG_TX;
+	team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL;
+	team->dev->hw_enc_features |= netdev_tx_vlan_features;
 	team->dev->hard_header_len = max_hard_header_len;
 
 	team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
@@ -2191,7 +2190,7 @@ static void team_setup(struct net_device *dev)
 
 	dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
 	dev->features |= dev->hw_features;
-	dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
+	dev->features |= netdev_tx_vlan_features;
 }
 
 static int team_newlink(struct net *src_net, struct net_device *dev,
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index d34d930a3029..194757bbd2b3 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1004,9 +1004,7 @@ static int tun_net_init(struct net_device *dev)
 	dev->hw_features = TUN_USER_FEATURES;
 	netdev_hw_features_set_array(dev, &tun_hw_feature_set);
 	dev->features = dev->hw_features | NETIF_F_LLTX;
-	dev->vlan_features = dev->features &
-			     ~(NETIF_F_HW_VLAN_CTAG_TX |
-			       NETIF_F_HW_VLAN_STAG_TX);
+	dev->vlan_features = dev->features & ~netdev_tx_vlan_features;
 
 	tun->flags = (tun->flags & ~TUN_FEATURES) |
 		      (ifr->ifr_flags & TUN_FEATURES);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 6de15832dafe..5978baef9695 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1650,11 +1650,7 @@ static void veth_setup(struct net_device *dev)
 	netdev_features_set_array(&veth_feature_set, &veth_features);
 	dev->features |= NETIF_F_LLTX;
 	dev->features |= veth_features;
-	dev->vlan_features = dev->features &
-			     ~(NETIF_F_HW_VLAN_CTAG_TX |
-			       NETIF_F_HW_VLAN_STAG_TX |
-			       NETIF_F_HW_VLAN_CTAG_RX |
-			       NETIF_F_HW_VLAN_STAG_RX);
+	dev->vlan_features = dev->features & ~netdev_vlan_offload_features;
 	dev->needs_free_netdev = true;
 	dev->priv_destructor = veth_dev_free;
 	dev->max_mtu = ETH_MAX_MTU;
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index b2f3fb5a29d5..ede0a87ca982 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3388,8 +3388,7 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 	}
 
 	netdev->vlan_features = netdev->hw_features &
-				~(NETIF_F_HW_VLAN_CTAG_TX |
-				  NETIF_F_HW_VLAN_CTAG_RX);
+				~netdev_ctag_vlan_offload_features;
 	netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
 }
 
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 639c05a175ba..f7b30abac5e9 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1907,8 +1907,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 		return -ENODEV;
 
 	card->dev->needed_headroom = headroom;
-	card->dev->features |=	NETIF_F_HW_VLAN_CTAG_TX |
-				NETIF_F_HW_VLAN_CTAG_RX;
+	card->dev->features |= netdev_ctag_vlan_offload_features;
 
 	netif_keep_dst(card->dev);
 	if (card->dev->hw_features & netdev_general_tso_features)
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index a3576a11443d..89ce268d9d81 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -4583,9 +4583,7 @@ static int qlge_probe(struct pci_dev *pdev,
 	ndev->features = ndev->hw_features;
 	ndev->vlan_features = ndev->hw_features;
 	/* vlan gets same features (except vlan filter) */
-	ndev->vlan_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER |
-				 NETIF_F_HW_VLAN_CTAG_TX |
-				 NETIF_F_HW_VLAN_CTAG_RX);
+	ndev->vlan_features &= ~netdev_ctag_vlan_features;
 
 	if (test_bit(QL_DMA64, &qdev->flags))
 		ndev->features |= NETIF_F_HIGHDMA;
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index e00c4ee81ff7..890ea73b4ffb 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -741,9 +741,7 @@ static inline netdev_features_t vlan_features_check(struct sk_buff *skb,
 		 * sure that only devices supporting NETIF_F_HW_CSUM will
 		 * have checksum offloading support.
 		 */
-		features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
-			    NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX |
-			    NETIF_F_HW_VLAN_STAG_TX;
+		features &= netdev_multi_tags_features_mask;
 	}
 
 	return features;
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 8f78e6d297b8..1d5e13e2acb8 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -507,8 +507,7 @@ void br_dev_setup(struct net_device *dev)
 	netdev_features_set_array(&br_common_feature_set, &common_features);
 	dev->features = common_features;
 	netdev_active_features_set_array(dev, &br_feature_set);
-	dev->hw_features = common_features | NETIF_F_HW_VLAN_CTAG_TX |
-			   NETIF_F_HW_VLAN_STAG_TX;
+	dev->hw_features = common_features | netdev_tx_vlan_features;
 	dev->vlan_features = common_features;
 
 	br->dev = dev;
diff --git a/net/core/dev.c b/net/core/dev.c
index ae2c44624732..101a9d63d2fc 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3565,8 +3565,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
 	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);
+						     netdev_tx_vlan_features);
 
 	if (dev->netdev_ops->ndo_features_check)
 		features &= dev->netdev_ops->ndo_features_check(skb, dev,
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 1e401624908b..0459fe97ddd9 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -121,7 +121,7 @@ static void do_setup(struct net_device *netdev)
 
 	netdev->vlan_features = netdev->features;
 	netdev->hw_enc_features = netdev->features;
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
+	netdev->features |= netdev_tx_vlan_features;
 	netdev->hw_features = netdev->features & ~NETIF_F_LLTX;
 
 	eth_hw_addr_random(netdev);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 14/36] net: simplify the netdev features expressions for xxx_gso_segment
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (12 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 13/36] treewide: replace VLAN tag feature array by const vlan features Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 15/36] treewide: simplify the netdev features expression Jian Shen
                   ` (21 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The xxx_gso_segment functions use netdev_features as input
parameters. There are soma features handling for this parameter.
Simplify these expreesions, so it can be replaced by netdev
features helpers later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 4 +++-
 drivers/net/ethernet/sfc/siena/tx_common.c       | 2 +-
 drivers/net/ethernet/sfc/tx_common.c             | 2 +-
 drivers/net/ethernet/sun/sunvnet_common.c        | 4 +++-
 drivers/net/wireguard/device.c                   | 2 +-
 net/core/dev.c                                   | 5 +++--
 net/ipv4/tcp_offload.c                           | 3 ++-
 net/mac80211/tx.c                                | 2 +-
 net/netfilter/nfnetlink_queue.c                  | 2 +-
 net/nsh/nsh.c                                    | 4 +++-
 net/openvswitch/datapath.c                       | 4 +++-
 net/sctp/offload.c                               | 9 +++++++--
 net/xfrm/xfrm_device.c                           | 3 ++-
 net/xfrm/xfrm_output.c                           | 2 +-
 14 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index cffe22b5f5f3..e1a5e80e1704 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -2898,10 +2898,12 @@ static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
 {
 	struct sk_buff *segs, *curr, *next;
 	struct myri10ge_priv *mgp = netdev_priv(dev);
+	netdev_features_t features = dev->features;
 	struct myri10ge_slice_state *ss;
 	netdev_tx_t status;
 
-	segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
+	features &= ~NETIF_F_TSO6;
+	segs = skb_gso_segment(skb, features);
 	if (IS_ERR(segs))
 		goto drop;
 
diff --git a/drivers/net/ethernet/sfc/siena/tx_common.c b/drivers/net/ethernet/sfc/siena/tx_common.c
index 93a32d61944f..60c7b72be822 100644
--- a/drivers/net/ethernet/sfc/siena/tx_common.c
+++ b/drivers/net/ethernet/sfc/siena/tx_common.c
@@ -433,7 +433,7 @@ int efx_siena_tx_tso_fallback(struct efx_tx_queue *tx_queue,
 {
 	struct sk_buff *segments, *next;
 
-	segments = skb_gso_segment(skb, 0);
+	segments = skb_gso_segment(skb, netdev_empty_features);
 	if (IS_ERR(segments))
 		return PTR_ERR(segments);
 
diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c
index 67e789b96c43..4d0c4d3a2231 100644
--- a/drivers/net/ethernet/sfc/tx_common.c
+++ b/drivers/net/ethernet/sfc/tx_common.c
@@ -450,7 +450,7 @@ int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
 {
 	struct sk_buff *segments, *next;
 
-	segments = skb_gso_segment(skb, 0);
+	segments = skb_gso_segment(skb, netdev_empty_features);
 	if (IS_ERR(segments))
 		return PTR_ERR(segments);
 
diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c
index 80fde5f06fce..f8aced92d2a9 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.c
+++ b/drivers/net/ethernet/sun/sunvnet_common.c
@@ -1228,6 +1228,7 @@ vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb,
 	int status;
 	int gso_size, gso_type, gso_segs;
 	int hlen = skb_transport_header(skb) - skb_mac_header(skb);
+	netedv_features_t features = dev->features;
 	int proto = IPPROTO_IP;
 
 	if (skb->protocol == htons(ETH_P_IP))
@@ -1274,7 +1275,8 @@ vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb,
 		skb_shinfo(skb)->gso_size = datalen;
 		skb_shinfo(skb)->gso_segs = gso_segs;
 	}
-	segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO);
+	features &= ~NETIF_F_TSO;
+	segs = skb_gso_segment(skb, features);
 	if (IS_ERR(segs))
 		goto out_dropped;
 
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index aeed694110d4..f78f910e113e 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -175,7 +175,7 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (!skb_is_gso(skb)) {
 		skb_mark_not_on_list(skb);
 	} else {
-		struct sk_buff *segs = skb_gso_segment(skb, 0);
+		struct sk_buff *segs = skb_gso_segment(skb, netdev_empty_features);
 
 		if (IS_ERR(segs)) {
 			ret = PTR_ERR(segs);
diff --git a/net/core/dev.c b/net/core/dev.c
index 101a9d63d2fc..7a57d8b4f307 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3395,10 +3395,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;
 	}
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 30abde86db45..3f3c158a5ac5 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -82,7 +82,8 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
 	if (unlikely(skb->len <= mss))
 		goto out;
 
-	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+	features |= NETIF_F_GSO_ROBUST;
+	if (skb_gso_ok(skb, features)) {
 		/* Packet is from an untrusted source, reset gso_segs. */
 
 		skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 45df9932d0ba..c8753e61e76e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4168,7 +4168,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 	if (skb_is_gso(skb)) {
 		struct sk_buff *segs;
 
-		segs = skb_gso_segment(skb, 0);
+		segs = skb_gso_segment(skb, netdev_empty_features);
 		if (IS_ERR(segs)) {
 			goto out_free;
 		} else if (segs) {
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 87a9009d5234..40d95d227805 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -812,7 +812,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
 		return __nfqnl_enqueue_packet(net, queue, entry);
 
 	nf_bridge_adjust_skb_data(skb);
-	segs = skb_gso_segment(skb, 0);
+	segs = skb_gso_segment(skb, netdev_empty_features);
 	/* Does not use PTR_ERR to limit the number of error codes that can be
 	 * returned by nf_queue.  For instance, callers rely on -ESRCH to
 	 * mean 'ignore this hook'.
diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
index e9ca007718b7..ba98ac8e31c8 100644
--- a/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -76,6 +76,7 @@ EXPORT_SYMBOL_GPL(nsh_pop);
 static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
 				       netdev_features_t features)
 {
+	netdev_features_t tmp = netdev_empty_features;
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int nsh_len, mac_len;
 	__be16 proto;
@@ -104,7 +105,8 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
 	skb->mac_len = proto == htons(ETH_P_TEB) ? ETH_HLEN : 0;
 	skb->protocol = proto;
 
-	features &= NETIF_F_SG;
+	tmp |= NETIF_F_SG;
+	features &= tmp;
 	segs = skb_mac_gso_segment(skb, features);
 	if (IS_ERR_OR_NULL(segs)) {
 		skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len,
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 7e8a39a35627..0780c418a971 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -318,13 +318,15 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
 			     const struct dp_upcall_info *upcall_info,
 			     uint32_t cutlen)
 {
+	netdev_features_t features = netdev_empty_features;
 	unsigned int gso_type = skb_shinfo(skb)->gso_type;
 	struct sw_flow_key later_key;
 	struct sk_buff *segs, *nskb;
 	int err;
 
 	BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_GSO_CB_OFFSET);
-	segs = __skb_gso_segment(skb, NETIF_F_SG, false);
+	features |= NETIF_F_SG;
+	segs = __skb_gso_segment(skb, features, false);
 	if (IS_ERR(segs))
 		return PTR_ERR(segs);
 	if (segs == NULL)
diff --git a/net/sctp/offload.c b/net/sctp/offload.c
index eb874e3c399a..1433fcc0977d 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -39,6 +39,7 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
 					netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	netdev_features_t tmp = features;
 	struct sctphdr *sh;
 
 	if (!skb_is_gso_sctp(skb))
@@ -50,7 +51,8 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
 
 	__skb_pull(skb, sizeof(*sh));
 
-	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+	tmp |= NETIF_F_GSO_ROBUST;
+	if (skb_gso_ok(skb, tmp)) {
 		/* Packet is from an untrusted source, reset gso_segs. */
 		struct skb_shared_info *pinfo = skb_shinfo(skb);
 		struct sk_buff *frag_iter;
@@ -68,7 +70,10 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
 		goto out;
 	}
 
-	segs = skb_segment(skb, (features | NETIF_F_HW_CSUM) & ~NETIF_F_SG);
+	tmp = features;
+	tmp |= NETIF_F_HW_CSUM;
+	tmp &= ~NETIF_F_SG;
+	segs = skb_segment(skb, tmp);
 	if (IS_ERR(segs))
 		goto out;
 
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 637ca8838436..96ffd287ae9a 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -138,7 +138,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 		struct sk_buff *segs;
 
 		/* Packet got rerouted, fixup features and segment it. */
-		esp_features = esp_features & ~(NETIF_F_HW_ESP | NETIF_F_GSO_ESP);
+		esp_features &= ~NETIF_F_HW_ESP;
+		esp_features &= ~NETIF_F_GSO_ESP;
 
 		segs = skb_gso_segment(skb, esp_features);
 		if (IS_ERR(segs)) {
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 555ab35cd119..85be950abae9 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -622,7 +622,7 @@ static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb
 
 	BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_GSO_CB_OFFSET);
 	BUILD_BUG_ON(sizeof(*IP6CB(skb)) > SKB_GSO_CB_OFFSET);
-	segs = skb_gso_segment(skb, 0);
+	segs = skb_gso_segment(skb, netdev_empty_features);
 	kfree_skb(skb);
 	if (IS_ERR(segs))
 		return PTR_ERR(segs);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 15/36] treewide: simplify the netdev features expression
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (13 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 14/36] net: simplify the netdev features expressions for xxx_gso_segment Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 16/36] treewide: use replace features '0' by netdev_empty_features Jian Shen
                   ` (20 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

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>
---
 drivers/infiniband/ulp/ipoib/ipoib_main.c     |  9 ++--
 drivers/net/bonding/bond_main.c               | 10 ++--
 drivers/net/ethernet/3com/3c59x.c             |  3 +-
 drivers/net/ethernet/adaptec/starfire.c       |  9 ++--
 drivers/net/ethernet/aeroflex/greth.c         |  3 +-
 drivers/net/ethernet/altera/altera_tse_main.c |  3 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |  3 +-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c     |  4 +-
 drivers/net/ethernet/apm/xgene-v2/main.c      |  4 +-
 .../net/ethernet/apm/xgene/xgene_enet_main.c  |  3 +-
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  5 +-
 .../net/ethernet/atheros/atl1e/atl1e_main.c   |  6 ++-
 drivers/net/ethernet/broadcom/bnx2.c          | 16 ++++--
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c   |  6 ++-
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  9 ++--
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 24 ++++++---
 drivers/net/ethernet/broadcom/tg3.c           |  4 +-
 drivers/net/ethernet/cadence/macb_main.c      | 21 +++++---
 .../net/ethernet/cavium/liquidio/lio_main.c   | 10 ++--
 .../ethernet/cavium/liquidio/lio_vf_main.c    | 10 ++--
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  7 +--
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  6 ++-
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  3 +-
 drivers/net/ethernet/cisco/enic/enic_main.c   |  6 ++-
 drivers/net/ethernet/cortina/gemini.c         |  3 +-
 drivers/net/ethernet/davicom/dm9000.c         |  3 +-
 drivers/net/ethernet/faraday/ftgmac100.c      |  6 ++-
 drivers/net/ethernet/freescale/gianfar.c      |  3 +-
 .../net/ethernet/freescale/gianfar_ethtool.c  |  3 +-
 .../ethernet/fungible/funeth/funeth_main.c    |  9 ++--
 drivers/net/ethernet/hisilicon/hix5hd2_gmac.c |  3 +-
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   |  9 ++--
 .../net/ethernet/huawei/hinic/hinic_main.c    |  3 +-
 drivers/net/ethernet/ibm/emac/core.c          |  3 +-
 drivers/net/ethernet/ibm/ibmveth.c            |  8 +--
 drivers/net/ethernet/ibm/ibmvnic.c            |  8 +--
 drivers/net/ethernet/intel/e100.c             |  2 +-
 drivers/net/ethernet/intel/e1000/e1000_main.c |  2 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c   | 16 +++---
 drivers/net/ethernet/intel/iavf/iavf_main.c   |  9 ++--
 drivers/net/ethernet/intel/ice/ice_main.c     | 27 ++++++----
 drivers/net/ethernet/intel/igb/igb_main.c     | 14 +++--
 drivers/net/ethernet/intel/igbvf/netdev.c     |  9 ++--
 drivers/net/ethernet/intel/igc/igc_main.c     |  8 +--
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  6 +--
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 29 ++++++-----
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 10 ++--
 drivers/net/ethernet/jme.c                    |  6 ++-
 drivers/net/ethernet/marvell/mvneta.c         |  3 +-
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  3 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  3 +-
 .../ethernet/marvell/prestera/prestera_main.c |  3 +-
 drivers/net/ethernet/marvell/sky2.c           |  4 +-
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  4 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 36 ++++++-------
 drivers/net/ethernet/mscc/ocelot_net.c        |  2 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  9 ++--
 drivers/net/ethernet/neterion/s2io.c          |  4 +-
 .../ethernet/netronome/nfp/nfp_net_common.c   |  7 +--
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  6 ++-
 drivers/net/ethernet/netronome/nfp/nfp_port.c |  2 +-
 drivers/net/ethernet/nvidia/forcedeth.c       |  2 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   |  3 +-
 .../ethernet/qlogic/netxen/netxen_nic_main.c  | 10 ++--
 drivers/net/ethernet/qlogic/qede/qede_main.c  | 15 +++---
 drivers/net/ethernet/qlogic/qla3xxx.c         |  6 ++-
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  3 +-
 drivers/net/ethernet/realtek/8139cp.c         |  3 +-
 drivers/net/ethernet/realtek/8139too.c        |  2 +-
 drivers/net/ethernet/realtek/r8169_main.c     |  9 ++--
 drivers/net/ethernet/rocker/rocker_main.c     |  3 +-
 .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |  3 +-
 drivers/net/ethernet/sfc/ef10.c               |  3 +-
 drivers/net/ethernet/sfc/efx.c                |  7 ++-
 drivers/net/ethernet/sfc/efx_common.c         | 11 ++--
 drivers/net/ethernet/sfc/falcon/efx.c         | 12 +++--
 drivers/net/ethernet/sfc/siena/efx.c          |  3 +-
 drivers/net/ethernet/sfc/siena/efx_common.c   |  7 +--
 drivers/net/ethernet/socionext/sni_ave.c      |  6 ++-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  3 +-
 drivers/net/ethernet/sun/cassini.c            |  6 ++-
 drivers/net/ethernet/sun/niu.c                |  3 +-
 drivers/net/ethernet/sun/sunhme.c             | 12 +++--
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  4 +-
 drivers/net/ethernet/ti/cpsw.c                |  6 ++-
 drivers/net/ethernet/toshiba/ps3_gelic_net.c  |  3 +-
 drivers/net/ethernet/toshiba/spider_net.c     |  6 ++-
 drivers/net/ethernet/via/via-rhine.c          |  6 ++-
 drivers/net/hyperv/rndis_filter.c             |  7 ++-
 drivers/net/ifb.c                             |  3 +-
 drivers/net/ipvlan/ipvlan_main.c              |  9 +++-
 drivers/net/macsec.c                          | 10 ++--
 drivers/net/macvlan.c                         | 13 +++--
 drivers/net/netdevsim/netdev.c                |  2 +-
 drivers/net/team/team.c                       |  6 +--
 drivers/net/tun.c                             |  8 ++-
 drivers/net/usb/cdc_mbim.c                    |  3 +-
 drivers/net/usb/smsc95xx.c                    |  3 +-
 drivers/net/veth.c                            |  6 ++-
 drivers/net/virtio_net.c                      | 16 ++++--
 drivers/net/vmxnet3/vmxnet3_drv.c             | 11 ++--
 drivers/net/vmxnet3/vmxnet3_ethtool.c         | 18 ++++---
 drivers/net/wireless/ath/ath6kl/main.c        |  9 ++--
 .../net/wireless/intel/iwlwifi/dvm/mac80211.c |  6 ++-
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |  6 ++-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c   |  5 +-
 drivers/net/xen-netback/interface.c           |  3 +-
 drivers/staging/octeon/ethernet.c             |  6 ++-
 include/linux/netdev_features_helper.h        |  7 ++-
 net/8021q/vlan.h                              | 17 ++++---
 net/8021q/vlan_dev.c                          | 14 +++--
 net/core/dev.c                                | 51 +++++++++++++------
 net/core/pktgen.c                             |  6 ++-
 net/core/skbuff.c                             |  2 +-
 net/core/sock.c                               |  3 +-
 net/dccp/ipv6.c                               |  5 +-
 net/dsa/slave.c                               |  9 ++--
 net/ethtool/features.c                        |  4 +-
 net/ethtool/ioctl.c                           | 47 ++++++++++++-----
 net/ipv4/esp4_offload.c                       | 16 +++---
 net/ipv4/ip_output.c                          |  3 +-
 net/ipv4/udp_offload.c                        |  6 +--
 net/ipv6/esp6_offload.c                       | 14 ++---
 net/ipv6/ip6_output.c                         |  3 +-
 net/mac80211/iface.c                          |  6 ++-
 net/openvswitch/vport-internal_dev.c          |  3 +-
 net/tls/tls_device.c                          |  2 +-
 net/xfrm/xfrm_device.c                        | 10 ++--
 128 files changed, 641 insertions(+), 363 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 4d917762352f..b69b918b2c39 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -218,8 +218,10 @@ static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_featu
 {
 	struct ipoib_dev_priv *priv = ipoib_priv(dev);
 
-	if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags))
-		features &= ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
+	if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags)) {
+		features &= ~NETIF_F_IP_CSUM;
+		features &= ~NETIF_F_TSO;
+	}
 
 	return features;
 }
@@ -1853,7 +1855,8 @@ static void ipoib_set_dev_features(struct ipoib_dev_priv *priv)
 	priv->kernel_caps = priv->ca->attrs.kernel_cap_flags;
 
 	if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
-		priv->dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+		priv->dev->hw_features |= NETIF_F_IP_CSUM;
+		priv->dev->hw_features |= NETIF_F_RXCSUM;
 
 		if (priv->kernel_caps & IBK_UD_TSO)
 			priv->dev->hw_features |= NETIF_F_TSO;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index ca23f18fa7fc..edbeaac3f678 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1498,8 +1498,8 @@ static void bond_compute_features(struct bonding *bond)
 
 done:
 	bond_dev->vlan_features = vlan_features;
-	bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
-				    netdev_tx_vlan_features;
+	bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL;
+	bond_dev->hw_enc_features |= netdev_tx_vlan_features;
 #ifdef CONFIG_XFRM_OFFLOAD
 	bond_dev->hw_enc_features |= xfrm_features;
 #endif /* CONFIG_XFRM_OFFLOAD */
@@ -5765,9 +5765,9 @@ void bond_setup(struct net_device *bond_dev)
 	/* Don't allow bond devices to change network namespaces. */
 	bond_dev->features |= NETIF_F_NETNS_LOCAL;
 
-	bond_dev->hw_features = BOND_VLAN_FEATURES |
-				NETIF_F_HW_VLAN_CTAG_RX |
-				NETIF_F_HW_VLAN_CTAG_FILTER;
+	bond_dev->hw_features = BOND_VLAN_FEATURES;
+	bond_dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+	bond_dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
 	bond_dev->features |= bond_dev->hw_features;
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index ccf07667aa5e..900435ea2c10 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -1448,7 +1448,8 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
 		if (card_idx < MAX_UNITS &&
 		    ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) ||
 				hw_checksums[card_idx] == 1)) {
-			dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+			dev->features |= NETIF_F_IP_CSUM;
+			dev->features |= NETIF_F_SG;
 		}
 	} else
 		dev->netdev_ops =  &vortex_netdev_ops;
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index 8f0a6b9c518e..f19be1f78848 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -684,12 +684,15 @@ static int starfire_init_one(struct pci_dev *pdev,
 
 #ifdef ZEROCOPY
 	/* Starfire can do TCP/UDP checksumming */
-	if (enable_hw_cksum)
-		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+	if (enable_hw_cksum) {
+		dev->features |= NETIF_F_IP_CSUM;
+		dev->features |= NETIF_F_SG;
+	}
 #endif /* ZEROCOPY */
 
 #ifdef VLAN_SUPPORT
-	dev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER;
+	dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+	dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 #endif /* VLAN_RX_KILL_VID */
 #ifdef ADDR_64BITS
 	dev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index dca85429a0ea..8a2c87778e96 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1490,7 +1490,8 @@ static int greth_of_probe(struct platform_device *ofdev)
 	if (greth->gbit_mac) {
 		netdev_hw_features_zero(dev);
 		netdev_hw_features_set_array(dev, &greth_hw_feature_set);
-		dev->features = dev->hw_features | NETIF_F_HIGHDMA;
+		dev->features = dev->hw_features;
+		dev->features |= NETIF_F_HIGHDMA;
 		greth_netdev_ops.ndo_start_xmit = greth_start_xmit_gbit;
 	}
 
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 8c5828582c21..6dea777c8b98 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -1557,7 +1557,8 @@ static int altera_tse_probe(struct platform_device *pdev)
 	 * so it is turned off
 	 */
 	ndev->hw_features &= ~NETIF_F_SG;
-	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+	ndev->features |= ndev->hw_features;
+	ndev->features |=  NETIF_F_HIGHDMA;
 
 	/* VLAN offloading of tagging, stripping and filtering is not
 	 * supported by hardware, but driver will accommodate the
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 135c6e95b6f1..ce0e2fa3eb63 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2183,7 +2183,8 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
 	netdev_features_t vxlan_base;
 
-	vxlan_base = NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RX_UDP_TUNNEL_PORT;
+	vxlan_base = NETIF_F_GSO_UDP_TUNNEL;
+	vxlan_base |= NETIF_F_RX_UDP_TUNNEL_PORT;
 
 	if (!pdata->hw_feat.vxn)
 		return features;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index a5c4fb8aa676..f08f983cc13a 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -382,8 +382,8 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
 		netdev_hw_enc_features_set_array(netdev,
 						 &xgbe_hw_enc_feature_set);
 
-		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
-				       NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 
 		netdev->udp_tunnel_nic_info = xgbe_get_udp_tunnel_info();
 	}
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c
index d022b6db9e06..739110c9f836 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -648,8 +648,8 @@ static int xge_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, pdata);
 	ndev->netdev_ops = &xgene_ndev_ops;
 
-	ndev->features |= NETIF_F_GSO |
-			  NETIF_F_GRO;
+	ndev->features |= NETIF_F_GSO;
+	ndev->features |= NETIF_F_GRO;
 
 	ret = xge_get_resources(pdata);
 	if (ret)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 49a35bd4c16d..65bba455a69f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -2069,7 +2069,8 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	spin_lock_init(&pdata->mac_lock);
 
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
-		ndev->features |= NETIF_F_TSO | NETIF_F_RXCSUM;
+		ndev->features |= NETIF_F_TSO;
+		ndev->features |= NETIF_F_RXCSUM;
 		spin_lock_init(&pdata->mss_lock);
 	}
 	ndev->hw_features = ndev->features;
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 1d54ee4f6147..a9c7b29aadf8 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2638,8 +2638,9 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	/* TODO: add when ready */
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &atl1c_hw_feature_set);
-	netdev->features =	netdev->hw_features	|
-				NETIF_F_HW_VLAN_CTAG_TX;
+	netdev->features = netdev->hw_features;
+	netdev->features |= NETIF_F_HW_VLAN_CTAG_TX;
+
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 0aaca5a1f87c..d615afd95091 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -2277,9 +2277,11 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &atl1e_hw_feature_set);
-	netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_TX;
+	netdev->features = netdev->hw_features;
+	netdev->features |= NETIF_F_HW_VLAN_CTAG_TX;
 	/* not enabled by default */
-	netdev->hw_features |= NETIF_F_RXALL | NETIF_F_RXFCS;
+	netdev->hw_features |= NETIF_F_RXALL;
+	netdev->hw_features |= NETIF_F_RXFCS;
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 4a03b8c9f37a..bd548249c2f2 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -7754,10 +7754,14 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
 	struct bnx2 *bp = netdev_priv(dev);
 
 	/* TSO with VLAN tag won't work with current firmware */
-	if (features & NETIF_F_HW_VLAN_CTAG_TX)
-		dev->vlan_features |= (dev->hw_features & NETIF_F_ALL_TSO);
-	else
+	if (features & NETIF_F_HW_VLAN_CTAG_TX) {
+		netdev_features_t tso;
+
+		tso = dev->hw_features & NETIF_F_ALL_TSO;
+		dev->vlan_features |= tso;
+	} else {
 		dev->vlan_features &= ~NETIF_F_ALL_TSO;
+	}
 
 	if ((!!(features & NETIF_F_HW_VLAN_CTAG_RX) !=
 	    !!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) &&
@@ -8592,8 +8596,10 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_array(dev, &bnx2_hw_feature_set);
 
-	if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
-		dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+	if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+		dev->hw_features |= NETIF_F_IPV6_CSUM;
+		dev->hw_features |= NETIF_F_TSO6;
+	}
 
 	dev->vlan_features = dev->hw_features;
 	dev->hw_features |= netdev_ctag_vlan_offload_features;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 712b5595bc39..e68d77d9ae50 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4912,12 +4912,14 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
 		 */
 		if (!(features & NETIF_F_RXCSUM) && !bp->disable_tpa) {
 			features &= ~NETIF_F_RXCSUM;
-			features |= dev->features & NETIF_F_RXCSUM;
+			if (dev->features & NETIF_F_RXCSUM)
+				features |= NETIF_F_RXCSUM;
 		}
 
 		if (changed & NETIF_F_LOOPBACK) {
 			features &= ~NETIF_F_LOOPBACK;
-			features |= dev->features & NETIF_F_LOOPBACK;
+			if (dev->features & NETIF_F_LOOPBACK)
+				features |= NETIF_F_LOOPBACK;
 		}
 	}
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 845d31294667..1986fde63919 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12350,8 +12350,10 @@ static int bnx2x_init_bp(struct bnx2x *bp)
 
 	/* Set TPA flags */
 	if (bp->disable_tpa) {
-		bp->dev->hw_features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
-		bp->dev->features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
+		bp->dev->hw_features &= ~NETIF_F_LRO;
+		bp->dev->hw_features &= ~NETIF_F_GRO_HW;
+		bp->dev->features &= ~NETIF_F_LRO;
+		bp->dev->features &= ~NETIF_F_GRO_HW;
 	}
 
 	if (CHIP_IS_E1(bp))
@@ -13275,7 +13277,8 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 	 * getting a response to CHANNEL_TLV_ACQUIRE from PF.
 	 */
 
-	dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX;
+	dev->features |= dev->hw_features;
+	dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
 	dev->features |= NETIF_F_HIGHDMA;
 	if (dev->features & NETIF_F_LRO)
 		dev->features &= ~NETIF_F_GRO_HW;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 37e2018fd875..150630a2b207 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11179,11 +11179,15 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 	if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp))
 		features &= ~NETIF_F_NTUPLE;
 
-	if (bp->flags & BNXT_FLAG_NO_AGG_RINGS)
-		features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
+	if (bp->flags & BNXT_FLAG_NO_AGG_RINGS) {
+		features &= ~NETIF_F_LRO;
+		features &= ~NETIF_F_GRO_HW;
+	}
 
-	if (!(bp->flags & BNXT_FLAG_TPA))
-		features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
+	if (!(bp->flags & BNXT_FLAG_TPA)) {
+		features &= ~NETIF_F_LRO;
+		features &= ~NETIF_F_GRO_HW;
+	}
 
 	if (!(features & NETIF_F_GRO))
 		features &= ~NETIF_F_GRO_HW;
@@ -13271,8 +13275,10 @@ static int bnxt_get_dflt_rings(struct bnxt *bp, int *max_rx, int *max_tx,
 			return rc;
 		}
 		bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
-		bp->dev->hw_features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
-		bp->dev->features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
+		bp->dev->hw_features &= ~NETIF_F_LRO;
+		bp->dev->hw_features &= ~NETIF_F_GRO_HW;
+		bp->dev->features &= ~NETIF_F_LRO;
+		bp->dev->features &= ~NETIF_F_GRO_HW;
 		bnxt_set_ring_params(bp);
 	}
 
@@ -13639,14 +13645,16 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev_gso_partial_features_zero(dev);
 	netdev_gso_partial_features_set_array(dev, &bnxt_gso_partial_feature_set);
-	dev->vlan_features = dev->hw_features | NETIF_F_HIGHDMA;
+	dev->vlan_features = dev->hw_features;
+	dev->vlan_features |= NETIF_F_HIGHDMA;
 	if (bp->fw_cap & BNXT_FW_CAP_VLAN_RX_STRIP)
 		dev->hw_features |= BNXT_HW_FEATURE_VLAN_ALL_RX;
 	if (bp->fw_cap & BNXT_FW_CAP_VLAN_TX_INSERT)
 		dev->hw_features |= BNXT_HW_FEATURE_VLAN_ALL_TX;
 	if (BNXT_SUPPORTS_TPA(bp))
 		dev->hw_features |= NETIF_F_GRO_HW;
-	dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
+	dev->features |= dev->hw_features;
+	dev->features |= NETIF_F_HIGHDMA;
 	if (dev->features & NETIF_F_GRO_HW)
 		dev->features &= ~NETIF_F_LRO;
 	dev->priv_flags |= IFF_UNICAST_FLT;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 3a7bb3db4e47..72a9b1f38cab 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17725,7 +17725,9 @@ static int tg3_init_one(struct pci_dev *pdev,
 	 * to hardware bugs.
 	 */
 	if (tg3_chip_rev_id(tp) != CHIPREV_ID_5700_B0) {
-		features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+		features |= NETIF_F_SG;
+		features |= NETIF_F_IP_CSUM;
+		features |= NETIF_F_RXCSUM;
 
 		if (tg3_flag(tp, 5755_PLUS))
 			features |= NETIF_F_IPV6_CSUM;
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 494fe961a49d..4cac5e3a1929 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -82,7 +82,6 @@ struct sifive_fu540_macb_mgmt {
 #define GEM_MAX_TX_LEN		(unsigned int)(0x3FC0)
 
 #define GEM_MTU_MIN_SIZE	ETH_MIN_MTU
-#define MACB_NETIF_LSO		NETIF_F_TSO
 
 #define MACB_WOL_HAS_MAGIC_PACKET	(0x1 << 0)
 #define MACB_WOL_ENABLED		(0x1 << 1)
@@ -2148,8 +2147,10 @@ static netdev_features_t macb_features_check(struct sk_buff *skb,
 	 * When software supplies two or more payload buffers all payload buffers
 	 * apart from the last must be a multiple of 8 bytes in size.
 	 */
-	if (!IS_ALIGNED(skb_headlen(skb) - hdrlen, MACB_TX_LEN_ALIGN))
-		return features & ~MACB_NETIF_LSO;
+	if (!IS_ALIGNED(skb_headlen(skb) - hdrlen, MACB_TX_LEN_ALIGN)) {
+		features &= ~NETIF_F_TSO;
+		return features;
+	}
 
 	nr_frags = skb_shinfo(skb)->nr_frags;
 	/* No need to check last fragment */
@@ -2157,8 +2158,10 @@ static netdev_features_t macb_features_check(struct sk_buff *skb,
 	for (f = 0; f < nr_frags; f++) {
 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
 
-		if (!IS_ALIGNED(skb_frag_size(frag), MACB_TX_LEN_ALIGN))
-			return features & ~MACB_NETIF_LSO;
+		if (!IS_ALIGNED(skb_frag_size(frag), MACB_TX_LEN_ALIGN)) {
+			features &= ~NETIF_F_TSO;
+			return features;
+		}
 	}
 	return features;
 }
@@ -4052,11 +4055,13 @@ static int macb_init(struct platform_device *pdev)
 
 	/* Check LSO capability */
 	if (GEM_BFEXT(PBUF_LSO, gem_readl(bp, DCFG6)))
-		dev->hw_features |= MACB_NETIF_LSO;
+		dev->hw_features |= NETIF_F_TSO;
 
 	/* Checksum offload is only available on gem with packet buffer */
-	if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE))
-		dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+	if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE)) {
+		dev->hw_features |= NETIF_F_HW_CSUM;
+		dev->hw_features |= NETIF_F_RXCSUM;
+	}
 	if (bp->caps & MACB_CAPS_SG_DISABLED)
 		dev->hw_features &= ~NETIF_F_SG;
 	dev->features = dev->hw_features;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index b5a963c9dc03..3271b8e9b392 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3590,8 +3590,8 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 		netdev_features_set_array(&liquidio_enc_feature_set,
 					  &lio->enc_dev_capability);
 
-		netdev->hw_enc_features = (lio->enc_dev_capability &
-					   ~NETIF_F_LRO);
+		netdev->hw_enc_features = lio->enc_dev_capability;
+		netdev->hw_enc_features &= ~NETIF_F_LRO;
 
 		netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
 
@@ -3601,12 +3601,12 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 		/* Add any unchangeable hw features */
 		lio->dev_capability |= netdev_ctag_vlan_features;
 
-		netdev->features = (lio->dev_capability & ~NETIF_F_LRO);
+		netdev->features = lio->dev_capability;
+		netdev->features &= ~NETIF_F_LRO;
 
 		netdev->hw_features = lio->dev_capability;
 		/*HW_VLAN_RX and HW_VLAN_FILTER is always on*/
-		netdev->hw_features = netdev->hw_features &
-			~NETIF_F_HW_VLAN_CTAG_RX;
+		netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 
 		/* MTU range: 68 - 16000 */
 		netdev->min_mtu = LIO_MIN_MTU_SIZE;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 23524066fa9a..688a6c4931b9 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -1850,9 +1850,10 @@ static netdev_features_t liquidio_fix_features(struct net_device *netdev,
 static int liquidio_set_features(struct net_device *netdev,
 				 netdev_features_t features)
 {
+	netdev_features_t changed = netdev->features ^ features;
 	struct lio *lio = netdev_priv(netdev);
 
-	if (!((netdev->features ^ features) & NETIF_F_LRO))
+	if (!(changed & NETIF_F_LRO))
 		return 0;
 
 	if ((features & NETIF_F_LRO) && (lio->dev_capability & NETIF_F_LRO))
@@ -2121,15 +2122,16 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 		netdev_features_set_array(&lio_enc_feature_set,
 					  &lio->enc_dev_capability);
 
-		netdev->hw_enc_features =
-		    (lio->enc_dev_capability & ~NETIF_F_LRO);
+		netdev->hw_enc_features = lio->enc_dev_capability;
+		netdev->hw_enc_features &= ~NETIF_F_LRO;
 		netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
 
 		netdev->vlan_features = lio->dev_capability;
 		/* Add any unchangeable hw features */
 		lio->dev_capability |= netdev_ctag_vlan_features;
 
-		netdev->features = (lio->dev_capability & ~NETIF_F_LRO);
+		netdev->features = lio->dev_capability;
+		netdev->features &= ~NETIF_F_LRO;
 
 		netdev->hw_features = lio->dev_capability;
 		netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 80f65f491b3f..7bbec0a182c3 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3320,11 +3320,12 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev->mem_end = mmio_start + mmio_len - 1;
 		netdev_hw_features_zero(netdev);
 		netdev_hw_features_set_array(netdev, &cxgb_hw_feature_set);
-		netdev->features |= netdev->hw_features |
-				    NETIF_F_HW_VLAN_CTAG_TX;
+		netdev->features |= netdev->hw_features;
+		netdev->features |= NETIF_F_HW_VLAN_CTAG_TX;
 		netdev_features_zero(&vlan_feat);
 		netdev_features_set_array(&cxgb_vlan_feature_set, &vlan_feat);
-		netdev->vlan_features |= netdev->features & vlan_feat;
+		vlan_feat &= netdev->features;
+		netdev->vlan_features |= vlan_feat;
 
 		netdev->features |= NETIF_F_HIGHDMA;
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 7e61049247b9..4df2af4c2e05 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1283,8 +1283,10 @@ static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 	err = t4_set_rxmode(pi->adapter, pi->adapter->mbox, pi->viid,
 			    pi->viid_mirror, -1, -1, -1, -1,
 			    !!(features & NETIF_F_HW_VLAN_CTAG_RX), true);
-	if (unlikely(err))
-		dev->features = features ^ NETIF_F_HW_VLAN_CTAG_RX;
+	if (unlikely(err)) {
+		dev->features = features;
+		dev->features ^= NETIF_F_HW_VLAN_CTAG_RX;
+	}
 	return err;
 }
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 2d6e1b42b36b..0d1d361fc246 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -3092,7 +3092,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 					  &tso_features);
 		netdev->hw_features = tso_features;
 		netdev_hw_features_set_array(netdev, &cxgb4vf_hw_feature_set);
-		netdev->features = netdev->hw_features | NETIF_F_HIGHDMA;
+		netdev->features = netdev->hw_features;
+		netdev->features |= NETIF_F_HIGHDMA;
 		vlan_features = tso_features;
 		netdev_features_set_array(&cxgb4vf_vlan_feature_set,
 					  &vlan_features);
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 061375f34d5d..4f851d446716 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2901,8 +2901,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		enic->loop_tag = enic->config.loop_tag;
 		dev_info(dev, "loopback tag=0x%04x\n", enic->loop_tag);
 	}
-	if (ENIC_SETTING(enic, TXCSUM))
-		netdev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+	if (ENIC_SETTING(enic, TXCSUM)) {
+		netdev->hw_features |= NETIF_F_SG;
+		netdev->hw_features |= NETIF_F_HW_CSUM;
+	}
 	if (ENIC_SETTING(enic, TSO)) {
 		netdev->hw_features |= netdev_general_tso_features;
 		netdev->hw_features |= NETIF_F_TSO_ECN;
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index d2b0296b426a..dcadafd7cdaa 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -2471,7 +2471,8 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
 	gmac_clear_hw_stats(netdev);
 
 	netdev->hw_features = GMAC_OFFLOAD_FEATURES;
-	netdev->features |= GMAC_OFFLOAD_FEATURES | NETIF_F_GRO;
+	netdev->features |= GMAC_OFFLOAD_FEATURES;
+	netdev->features |= NETIF_F_GRO;
 	/* We can handle jumbo frames up to 10236 bytes so, let's accept
 	 * payloads of 10236 bytes minus VLAN and ethernet header
 	 */
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 0985ab216566..363490713825 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -1644,7 +1644,8 @@ dm9000_probe(struct platform_device *pdev)
 
 	/* dm9000a/b are capable of hardware checksum offload */
 	if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) {
-		ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
+		ndev->hw_features = NETIF_F_RXCSUM;
+		ndev->hw_features |= NETIF_F_IP_CSUM;
 		ndev->features |= ndev->hw_features;
 	}
 
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 8c95ad9df5e5..3cdc5d827f14 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1953,8 +1953,10 @@ static int ftgmac100_probe(struct platform_device *pdev)
 	if (priv->use_ncsi && of_device_is_compatible(np, "aspeed,ast2600-mac"))
 		netdev->hw_features &= ~NETIF_F_HW_CSUM;
 
-	if (np && of_get_property(np, "no-hw-checksum", NULL))
-		netdev->hw_features &= ~(NETIF_F_HW_CSUM | NETIF_F_RXCSUM);
+	if (np && of_get_property(np, "no-hw-checksum", NULL)) {
+		netdev->hw_features &= ~NETIF_F_HW_CSUM;
+		netdev->hw_features &= ~NETIF_F_RXCSUM;
+	}
 	netdev->features |= netdev->hw_features;
 
 	/* register network device */
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index d9b1928d1987..dcf30e6dd012 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -161,7 +161,8 @@ static void gfar_rx_offload_en(struct gfar_private *priv)
 	/* set this when rx hw offload (TOE) functions are being used */
 	priv->uses_rxfcb = 0;
 
-	if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX))
+	if (priv->ndev->features & NETIF_F_RXCSUM ||
+	    priv->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
 		priv->uses_rxfcb = 1;
 
 	if (priv->hwts_rx_en || priv->rx_filer_enable)
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index b4b1b7b7143f..8c541070ffe0 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -511,7 +511,8 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features)
 	struct gfar_private *priv = netdev_priv(dev);
 	int err = 0;
 
-	if (!(changed & (netdev_ctag_vlan_offload_features | NETIF_F_RXCSUM)))
+	if (!(changed & netdev_ctag_vlan_offload_features) &&
+	    !(changed & NETIF_F_RXCSUM))
 		return 0;
 
 	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_main.c b/drivers/net/ethernet/fungible/funeth/funeth_main.c
index 537daf19f7f6..4bfc6dab65f4 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1788,12 +1788,15 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 	netdev_features_set_array(&fun_vlan_feature_set, &vlan_feat);
 
 	netdev_hw_features_set_array(netdev, &fun_hw_feature_set);
-	if (fp->port_caps & FUN_PORT_CAP_OFFLOADS)
-		netdev->hw_features |= NETIF_F_HW_CSUM | tso_flags;
+	if (fp->port_caps & FUN_PORT_CAP_OFFLOADS) {
+		netdev->hw_features |= NETIF_F_HW_CSUM;
+		netdev->hw_features |= tso_flags;
+	}
 	if (fp->port_caps & FUN_PORT_CAP_ENCAP_OFFLOADS)
 		netdev->hw_features |= gso_encap_flags;
 
-	netdev->features |= netdev->hw_features | NETIF_F_HIGHDMA;
+	netdev->features |= netdev->hw_features;
+	netdev->features |= NETIF_F_HIGHDMA;
 	netdev->vlan_features = netdev->features & vlan_feat;
 	netdev->mpls_features = netdev->vlan_features;
 	netdev->hw_enc_features = netdev->hw_features;
diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
index d7e62eca050f..69579d94f4d5 100644
--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
@@ -1236,7 +1236,8 @@ static int hix5hd2_dev_probe(struct platform_device *pdev)
 	if (HAS_CAP_TSO(priv->hw_cap))
 		ndev->hw_features |= NETIF_F_SG;
 
-	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+	ndev->features |= ndev->hw_features;
+	ndev->features |= NETIF_F_HIGHDMA;
 	ndev->vlan_features |= ndev->features;
 
 	ret = hix5hd2_init_hw_desc_queue(priv);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 3213322fcb08..c59026807723 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;
 
-	if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) {
+	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);
 		if (ret)
@@ -3284,6 +3284,7 @@ static void hns3_set_default_feature(struct net_device *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;
 
@@ -3319,9 +3320,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/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index b8db3b423a5b..80d14a014d2d 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -948,7 +948,8 @@ static void netdev_features_init(struct net_device *netdev)
 
 	netdev->vlan_features = netdev->hw_features;
 
-	netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev->features = netdev->hw_features;
+	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	netdev_hw_enc_features_zero(netdev);
 	netdev_hw_enc_features_set_array(netdev, &hinic_hw_enc_feature_set);
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 6b026ba0f262..17b5e0806aa6 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -3177,7 +3177,8 @@ static int emac_probe(struct platform_device *ofdev)
 	if (dev->tah_dev) {
 		netdev_hw_features_zero(ndev);
 		netdev_hw_features_set_array(ndev, &emac_hw_feature_set);
-		ndev->features |= ndev->hw_features | NETIF_F_RXCSUM;
+		ndev->features |= ndev->hw_features;
+		ndev->features |= NETIF_F_RXCSUM;
 	}
 	ndev->watchdog_timeo = 5 * HZ;
 	if (emac_phy_supports_gige(dev->phy_mode)) {
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 32ad4087a43d..3533ae7c92f7 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -906,10 +906,10 @@ static int ibmveth_set_features(struct net_device *dev,
 
 	if (rx_csum != adapter->rx_csum) {
 		rc1 = ibmveth_set_csum_offload(dev, rx_csum);
-		if (rc1 && !adapter->rx_csum)
-			dev->features =
-				features & ~(NETIF_F_CSUM_MASK |
-					     NETIF_F_RXCSUM);
+		if (rc1 && !adapter->rx_csum) {
+			dev->features = features & ~NETIF_F_CSUM_MASK;
+			dev->features &= ~NETIF_F_RXCSUM;
+		}
 	}
 
 	if (large_send != adapter->large_send) {
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 43f12a96cf90..598f5b9d9025 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4900,10 +4900,10 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 		/* disable features no longer supported */
 		adapter->netdev->features &= adapter->netdev->hw_features;
 		/* turn on features now supported if previously enabled */
-		tmp = (old_hw_features ^ adapter->netdev->hw_features) &
-			adapter->netdev->hw_features;
-		adapter->netdev->features |=
-				tmp & adapter->netdev->wanted_features;
+		tmp = old_hw_features ^ adapter->netdev->hw_features;
+		tmp &= adapter->netdev->hw_features;
+		tmp &= adapter->netdev->wanted_features;
+		adapter->netdev->features |= tmp;
 	}
 
 	memset(&crq, 0, sizeof(crq));
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 11a884aa5082..2809f6c0f69a 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2805,7 +2805,7 @@ static int e100_set_features(struct net_device *netdev,
 	struct nic *nic = netdev_priv(netdev);
 	netdev_features_t changed = features ^ netdev->features;
 
-	if (!(changed & (NETIF_F_RXFCS | NETIF_F_RXALL)))
+	if (!(changed & NETIF_F_RXFCS && changed & NETIF_F_RXALL))
 		return 0;
 
 	netdev->features = features;
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 07670cabf19f..9564fdef837d 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -810,7 +810,7 @@ static int e1000_set_features(struct net_device *netdev,
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		e1000_vlan_mode(netdev, features);
 
-	if (!(changed & (NETIF_F_RXCSUM | NETIF_F_RXALL)))
+	if (!(changed & NETIF_F_RXCSUM && changed & NETIF_F_RXALL))
 		return 0;
 
 	netdev->features = features;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index b905eced9d91..d7d628af7435 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13689,14 +13689,15 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	netdev->hw_enc_features |= hw_enc_features;
 
 	/* record features VLANs can make use of */
-	netdev->vlan_features |= hw_enc_features | NETIF_F_TSO_MANGLEID;
+	netdev->vlan_features |= hw_enc_features;
+	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
 
 	netdev_features_zero(&gso_partial_features);
 	netdev_features_set_array(&i40e_gso_partial_feature_set,
 				  &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->features |= NETIF_F_GSO_PARTIAL |
-			    gso_partial_features;
+	netdev->features |= NETIF_F_GSO_PARTIAL;
+	netdev->features |= gso_partial_features;
 
 	netdev_mpls_features_set_array(netdev, &i40e_mpls_feature_set);
 	netdev->mpls_features |= gso_partial_features;
@@ -13706,12 +13707,15 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 
 	hw_features = hw_enc_features | netdev_ctag_vlan_offload_features;
 
-	if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
-		hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;
+	if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) {
+		hw_features |= NETIF_F_NTUPLE;
+		hw_features |= NETIF_F_HW_TC;
+	}
 
 	netdev->hw_features |= hw_features;
 
-	netdev->features |= hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev->features |= hw_features;
+	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 	netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
 
 	netdev->features &= ~NETIF_F_HW_TC;
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index efbd889eea1a..95dd5a16b553 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4631,7 +4631,8 @@ int iavf_process_config(struct iavf_adapter *adapter)
 		netdev->hw_enc_features |= hw_enc_features;
 	}
 	/* record features VLANs can make use of */
-	netdev->vlan_features |= hw_enc_features | NETIF_F_TSO_MANGLEID;
+	netdev->vlan_features |= hw_enc_features;
+	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
 
 	/* Write features and hw_features separately to avoid polluting
 	 * with, or dropping, features that are set when we registered.
@@ -4647,10 +4648,12 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_USO)
 		hw_features |= NETIF_F_GSO_UDP_L4;
 
-	netdev->hw_features |= hw_features | hw_vlan_features;
+	netdev->hw_features |= hw_features;
+	netdev->hw_features |= hw_vlan_features;
 	vlan_features = iavf_get_netdev_vlan_features(adapter);
 
-	netdev->features |= hw_features | vlan_features;
+	netdev->features |= hw_features;
+	netdev->features |= vlan_features;
 
 	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
 		netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 5c9333da4dfc..107caaac78ea 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3360,11 +3360,12 @@ static void ice_set_netdev_features(struct net_device *netdev)
 	netdev_features_zero(&tso_features);
 	netdev_features_set_array(&ice_tso_feature_set, &tso_features);
 
-	netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM |
-					NETIF_F_GSO_GRE_CSUM;
+	netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+	netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
 	/* set features that user can change */
-	netdev->hw_features = dflt_features | csumo_features |
-			      vlano_features | tso_features;
+	netdev->hw_features = dflt_features | csumo_features;
+	netdev->hw_features |= vlano_features;
+	netdev->hw_features |= tso_features;
 
 	/* add support for HW_CSUM on packets with MPLS header */
 	netdev_mpls_features_zero(netdev);
@@ -3377,10 +3378,12 @@ static void ice_set_netdev_features(struct net_device *netdev)
 	netdev->hw_features |= NETIF_F_LOOPBACK;
 
 	/* encap and VLAN devices inherit default, csumo and tso features */
-	netdev->hw_enc_features |= dflt_features | csumo_features |
-				   tso_features;
-	netdev->vlan_features |= dflt_features | csumo_features |
-				 tso_features;
+	netdev->hw_enc_features |= dflt_features;
+	netdev->hw_enc_features |= csumo_features;
+	netdev->hw_enc_features |= tso_features;
+	netdev->vlan_features |= dflt_features;
+	netdev->vlan_features |= csumo_features;
+	netdev->vlan_features |= tso_features;
 
 	/* advertise support but don't enable by default since only one type of
 	 * VLAN offload can be enabled at a time (i.e. CTAG or STAG). When one
@@ -5897,14 +5900,15 @@ ice_set_vlan_filtering_features(struct ice_vsi *vsi, netdev_features_t features)
 static int
 ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 {
-	netdev_features_t current_vlan_features, requested_vlan_features;
+	netdev_features_t current_vlan_features, requested_vlan_features, diff;
 	struct ice_netdev_priv *np = netdev_priv(netdev);
 	struct ice_vsi *vsi = np->vsi;
 	int err;
 
 	current_vlan_features = netdev->features & NETIF_VLAN_OFFLOAD_FEATURES;
 	requested_vlan_features = features & NETIF_VLAN_OFFLOAD_FEATURES;
-	if (current_vlan_features ^ requested_vlan_features) {
+	diff = current_vlan_features ^ requested_vlan_features;
+	if (diff) {
 		err = ice_set_vlan_offload_features(vsi, features);
 		if (err)
 			return err;
@@ -5913,7 +5917,8 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 	current_vlan_features = netdev->features &
 		NETIF_VLAN_FILTERING_FEATURES;
 	requested_vlan_features = features & NETIF_VLAN_FILTERING_FEATURES;
-	if (current_vlan_features ^ requested_vlan_features) {
+	diff = current_vlan_features ^ requested_vlan_features;
+	if (diff) {
 		err = ice_set_vlan_filtering_features(vsi, features);
 		if (err)
 			return err;
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 578663a47c93..3d0af1c6d13e 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2455,7 +2455,7 @@ static int igb_set_features(struct net_device *netdev,
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		igb_vlan_mode(netdev, features);
 
-	if (!(changed & (NETIF_F_RXALL | NETIF_F_NTUPLE)))
+	if (!(changed & NETIF_F_RXALL) && !(changed & NETIF_F_NTUPLE))
 		return 0;
 
 	if (!(features & NETIF_F_NTUPLE)) {
@@ -3298,8 +3298,10 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 */
 	netdev_active_features_set_array(netdev, &igb_feature_set);
 
-	if (hw->mac.type >= e1000_82576)
-		netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_GSO_UDP_L4;
+	if (hw->mac.type >= e1000_82576) {
+		netdev->features |= NETIF_F_SCTP_CRC;
+		netdev->features |= NETIF_F_GSO_UDP_L4;
+	}
 
 	if (hw->mac.type >= e1000_i350)
 		netdev->features |= NETIF_F_HW_TC;
@@ -3307,7 +3309,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_features_zero(&gso_partial_features);
 	netdev_features_set_array(&igb_feature_set, &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->features |= NETIF_F_GSO_PARTIAL | gso_partial_features;
+	netdev->features |= NETIF_F_GSO_PARTIAL;
+	netdev->features |= gso_partial_features;
 
 	/* copy netdev features into list of user selectable features */
 	netdev->hw_features |= netdev->features;
@@ -3319,7 +3322,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev->features |= NETIF_F_HIGHDMA;
 
-	netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
+	netdev->vlan_features |= netdev->features;
+	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
 	netdev->mpls_features |= NETIF_F_HW_CSUM;
 	netdev->hw_enc_features |= netdev->vlan_features;
 
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 07c725474e32..6994f573fadf 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2794,11 +2794,14 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				  &gso_partial_features);
 
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->hw_features |= NETIF_F_GSO_PARTIAL | gso_partial_features;
+	netdev->hw_features |= NETIF_F_GSO_PARTIAL;
+	netdev->hw_features |= gso_partial_features;
 
-	netdev->features = netdev->hw_features | NETIF_F_HIGHDMA;
+	netdev->features = netdev->hw_features;
+	netdev->features |= NETIF_F_HIGHDMA;
 
-	netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
+	netdev->vlan_features |= netdev->features;
+	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
 	netdev->mpls_features |= NETIF_F_HW_CSUM;
 	netdev->hw_enc_features |= netdev->vlan_features;
 
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index e5b97822e191..805243e7c4cb 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4958,7 +4958,7 @@ static int igc_set_features(struct net_device *netdev,
 		igc_vlan_mode(netdev, features);
 
 	/* Add VLAN support */
-	if (!(changed & (NETIF_F_RXALL | NETIF_F_NTUPLE)))
+	if (!(changed & NETIF_F_RXALL) && !(changed & NETIF_F_NTUPLE))
 		return 0;
 
 	if (!(features & NETIF_F_NTUPLE))
@@ -6335,7 +6335,8 @@ static int igc_probe(struct pci_dev *pdev,
 	netdev_features_set_array(&igc_gso_partial_feature_set,
 				  &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->features |= NETIF_F_GSO_PARTIAL | gso_partial_features;
+	netdev->features |= NETIF_F_GSO_PARTIAL;
+	netdev->features |= gso_partial_features;
 
 	/* setup the private structure */
 	err = igc_sw_init(adapter);
@@ -6350,7 +6351,8 @@ static int igc_probe(struct pci_dev *pdev,
 
 	netdev->features |= NETIF_F_HIGHDMA;
 
-	netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
+	netdev->vlan_features |= netdev->features;
+	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
 	netdev->mpls_features |= NETIF_F_HW_CSUM;
 	netdev->hw_enc_features |= netdev->vlan_features;
 
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index c3ae375f04dd..d23b7a10d62f 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -313,7 +313,7 @@ ixgb_set_features(struct net_device *netdev, netdev_features_t features)
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed = features ^ netdev->features;
 
-	if (!(changed & (NETIF_F_RXCSUM|NETIF_F_HW_VLAN_CTAG_RX)))
+	if (!(changed & NETIF_F_RXCSUM) && !(changed & NETIF_F_HW_VLAN_CTAG_RX))
 		return 0;
 
 	adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
@@ -438,8 +438,8 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &ixgb_hw_feature_set);
-	netdev->features = netdev->hw_features |
-			   NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev->features = netdev->hw_features;
+	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 	netdev->hw_features |= NETIF_F_RXCSUM;
 
 	netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index db008c8281ed..0b6b5cfa84df 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -8828,7 +8828,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 #ifdef IXGBE_FCOE
 	/* setup tx offload for FCoE */
 	if ((protocol == htons(ETH_P_FCOE)) &&
-	    (tx_ring->netdev->features & (NETIF_F_FSO | NETIF_F_FCOE_CRC))) {
+	    (tx_ring->netdev->features & NETIF_F_FSO ||
+	     tx_ring->netdev->features & NETIF_F_FCOE_CRC)) {
 		tso = ixgbe_fso(tx_ring, first, &hdr_len);
 		if (tso < 0)
 			goto out_drop;
@@ -9884,7 +9885,7 @@ static int ixgbe_set_features(struct net_device *netdev,
 		    adapter->rx_itr_setting > IXGBE_MIN_RSC_ITR) {
 			adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
 			need_reset = true;
-		} else if ((changed ^ features) & NETIF_F_LRO) {
+		} else if ((changed & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
 			e_info(probe, "rx-usecs set too low, "
 			       "disabling RSC\n");
 		}
@@ -9930,8 +9931,8 @@ static int ixgbe_set_features(struct net_device *netdev,
 		ixgbe_reset_l2fw_offload(adapter);
 	else if (need_reset)
 		ixgbe_do_reset(netdev);
-	else if (changed & (NETIF_F_HW_VLAN_CTAG_RX |
-			    NETIF_F_HW_VLAN_CTAG_FILTER))
+	else if (changed & NETIF_F_HW_VLAN_CTAG_RX ||
+		 changed & NETIF_F_HW_VLAN_CTAG_FILTER)
 		ixgbe_set_rx_mode(netdev);
 
 	return 1;
@@ -11020,11 +11021,13 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				  &gso_partial_features);
 
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->features |= NETIF_F_GSO_PARTIAL |
-			    gso_partial_features;
+	netdev->features |= NETIF_F_GSO_PARTIAL;
+	netdev->features |= gso_partial_features;
 
-	if (hw->mac.type >= ixgbe_mac_82599EB)
-		netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_GSO_UDP_L4;
+	if (hw->mac.type >= ixgbe_mac_82599EB) {
+		netdev->features |= NETIF_F_SCTP_CRC;
+		netdev->features |= NETIF_F_GSO_UDP_L4;
+	}
 
 #ifdef CONFIG_IXGBE_IPSEC
 	if (adapter->ipsec)
@@ -11034,13 +11037,15 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->hw_features |= netdev->features;
 	netdev_hw_features_set_array(netdev, &ixgbe_hw_feature_set);
 
-	if (hw->mac.type >= ixgbe_mac_82599EB)
-		netdev->hw_features |= NETIF_F_NTUPLE |
-				       NETIF_F_HW_TC;
+	if (hw->mac.type >= ixgbe_mac_82599EB) {
+		netdev->hw_features |= NETIF_F_NTUPLE;
+		netdev->hw_features |= NETIF_F_HW_TC;
+	}
 
 	netdev->features |= NETIF_F_HIGHDMA;
 
-	netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
+	netdev->vlan_features |= netdev->features;
+	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
 	netdev->hw_enc_features |= netdev->vlan_features;
 	netdev_mpls_features_set_array(netdev, &ixgbe_mpls_feature_set);
 	netdev->mpls_features |= gso_partial_features;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index d46ab40b2b98..db20be0b4fb1 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4633,12 +4633,14 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_features_set_array(&ixgbevf_gso_partial_feature_set,
 				  &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->hw_features |= NETIF_F_GSO_PARTIAL |
-			       gso_partial_features;
+	netdev->hw_features |= NETIF_F_GSO_PARTIAL;
+	netdev->hw_features |= gso_partial_features;
 
-	netdev->features = netdev->hw_features | NETIF_F_HIGHDMA;
+	netdev->features = netdev->hw_features;
+	netdev->features |= NETIF_F_HIGHDMA;
 
-	netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
+	netdev->vlan_features |= netdev->features;
+	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
 
 	netdev_mpls_features_set_array(netdev, &ixgbevf_mpls_feature_set);
 	netdev->mpls_features |= gso_partial_features;
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 6db2f01468c5..96f2402f6cb4 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2664,8 +2664,10 @@ jme_set_msglevel(struct net_device *netdev, u32 value)
 static netdev_features_t
 jme_fix_features(struct net_device *netdev, netdev_features_t features)
 {
-	if (netdev->mtu > 1900)
-		features &= ~(NETIF_F_ALL_TSO | NETIF_F_CSUM_MASK);
+	if (netdev->mtu > 1900) {
+		features &= ~NETIF_F_ALL_TSO;
+		features &= ~NETIF_F_CSUM_MASK;
+	}
 	return features;
 }
 
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index b097a857fe4e..3b9c7257622d 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -3848,7 +3848,8 @@ static netdev_features_t mvneta_fix_features(struct net_device *dev,
 	struct mvneta_port *pp = netdev_priv(dev);
 
 	if (pp->tx_csum_limit && dev->mtu > pp->tx_csum_limit) {
-		features &= ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
+		features &= ~NETIF_F_IP_CSUM;
+		features &= ~NETIF_F_TSO;
 		netdev_info(dev,
 			    "Disable IP checksum for MTU greater than %dB\n",
 			    pp->tx_csum_limit);
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index d693c6580e27..8aa5dd6cce91 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -6858,7 +6858,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 
 	netdev_features_zero(&features);
 	netdev_features_set_array(&mvpp2_feature_set, &features);
-	dev->features = features | NETIF_F_RXCSUM;
+	dev->features = features;
+	dev->features |= NETIF_F_RXCSUM;
 	dev->hw_features |= features;
 	netdev_hw_features_set_array(dev, &mvpp2_hw_feature_set);
 
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 172c715415fa..888fb6dde97b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -2728,7 +2728,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (pf->flags & OTX2_FLAG_TC_FLOWER_SUPPORT)
 		netdev->hw_features |= NETIF_F_HW_TC;
 
-	netdev->hw_features |= NETIF_F_LOOPBACK | NETIF_F_RXALL;
+	netdev->hw_features |= NETIF_F_LOOPBACK;
+	netdev->hw_features |= NETIF_F_RXALL;
 
 	netif_set_tso_max_segs(netdev, OTX2_MAX_GSO_SEGS);
 	netdev->watchdog_timeo = OTX2_TX_TIMEOUT;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c
index ede3e53b9790..23dde8129492 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
@@ -622,7 +622,8 @@ static int prestera_port_create(struct prestera_switch *sw, u32 id)
 	if (err)
 		goto err_dl_port_register;
 
-	dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_HW_TC;
+	dev->features |= NETIF_F_NETNS_LOCAL;
+	dev->features |= NETIF_F_HW_TC;
 	dev->netdev_ops = &prestera_netdev_ops;
 	dev->ethtool_ops = &prestera_ethtool_ops;
 	SET_NETDEV_DEV(dev, sw->dev->dev);
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index c9a4b1db43eb..98574f083375 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4316,7 +4316,9 @@ static netdev_features_t sky2_fix_features(struct net_device *dev,
 	 */
 	if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) {
 		netdev_info(dev, "checksum offload not possible with jumbo frames\n");
-		features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_CSUM_MASK);
+		features &= ~NETIF_F_TSO;
+		features &= ~NETIF_F_SG;
+		features &= ~NETIF_F_CSUM_MASK;
 	}
 
 	/* Some hardware requires receive checksum for RSS to work. */
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 019dbd5ae79f..c73fcb4a15f3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3382,8 +3382,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	netdev_hw_features_set_array(dev, &mlx4_hw_feature_set3);
 
 	if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN)) {
-		dev->features |= NETIF_F_HW_VLAN_STAG_RX |
-			NETIF_F_HW_VLAN_STAG_FILTER;
+		dev->features |= NETIF_F_HW_VLAN_STAG_RX;
+		dev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
 		dev->hw_features |= NETIF_F_HW_VLAN_STAG_RX;
 	}
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index c32468f81500..3c8d059c8484 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4921,31 +4921,31 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 	}
 
 	if (mlx5_vxlan_allowed(mdev->vxlan) || mlx5_geneve_tx_allowed(mdev)) {
-		netdev->hw_features     |= NETIF_F_GSO_UDP_TUNNEL |
-					   NETIF_F_GSO_UDP_TUNNEL_CSUM;
-		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL |
-					   NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev->hw_features     |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev->hw_features     |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 		netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
-		netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL |
-					 NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 	}
 
 	if (mlx5e_tunnel_proto_supported_tx(mdev, IPPROTO_GRE)) {
-		netdev->hw_features     |= NETIF_F_GSO_GRE |
-					   NETIF_F_GSO_GRE_CSUM;
-		netdev->hw_enc_features |= NETIF_F_GSO_GRE |
-					   NETIF_F_GSO_GRE_CSUM;
-		netdev->gso_partial_features |= NETIF_F_GSO_GRE |
-						NETIF_F_GSO_GRE_CSUM;
+		netdev->hw_features     |= NETIF_F_GSO_GRE;
+		netdev->hw_features     |= NETIF_F_GSO_GRE_CSUM;
+		netdev->hw_enc_features |= NETIF_F_GSO_GRE;
+		netdev->hw_enc_features |= NETIF_F_GSO_GRE_CSUM;
+		netdev->gso_partial_features |= NETIF_F_GSO_GRE;
+		netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
 	}
 
 	if (mlx5e_tunnel_proto_supported_tx(mdev, IPPROTO_IPIP)) {
-		netdev->hw_features |= NETIF_F_GSO_IPXIP4 |
-				       NETIF_F_GSO_IPXIP6;
-		netdev->hw_enc_features |= NETIF_F_GSO_IPXIP4 |
-					   NETIF_F_GSO_IPXIP6;
-		netdev->gso_partial_features |= NETIF_F_GSO_IPXIP4 |
-						NETIF_F_GSO_IPXIP6;
+		netdev->hw_features |= NETIF_F_GSO_IPXIP4;
+		netdev->hw_features |= NETIF_F_GSO_IPXIP6;
+		netdev->hw_enc_features |= NETIF_F_GSO_IPXIP4;
+		netdev->hw_enc_features |= NETIF_F_GSO_IPXIP6;
+		netdev->gso_partial_features |= NETIF_F_GSO_IPXIP4;
+		netdev->gso_partial_features |= NETIF_F_GSO_IPXIP6;
 	}
 
 	netdev->gso_partial_features             |= NETIF_F_GSO_UDP_L4;
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 0f88dac6920a..353a25f001e7 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -843,7 +843,7 @@ static int ocelot_set_features(struct net_device *dev,
 	struct ocelot *ocelot = priv->port.ocelot;
 	int port = priv->port.index;
 
-	if ((dev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
+	if ((dev->features & NETIF_F_HW_TC) && !(features & NETIF_F_HW_TC) &&
 	    priv->tc.offload_cnt) {
 		netdev_err(dev,
 			   "Cannot disable HW TC offload while offloads active\n");
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index e1a5e80e1704..2a4e49122b5c 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -1289,8 +1289,7 @@ myri10ge_vlan_rx(struct net_device *dev, void *addr, struct sk_buff *skb)
 	va = addr;
 	va += MXGEFW_PAD;
 	veh = (struct vlan_ethhdr *)va;
-	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
-	    NETIF_F_HW_VLAN_CTAG_RX &&
+	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
 	    veh->h_vlan_proto == htons(ETH_P_8021Q)) {
 		/* fixup csum if needed */
 		if (skb->ip_summed == CHECKSUM_COMPLETE) {
@@ -3868,12 +3867,14 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->mtu = myri10ge_initial_mtu;
 
 	netdev->netdev_ops = &myri10ge_netdev_ops;
-	netdev->hw_features = mgp->features | NETIF_F_RXCSUM;
+	netdev->hw_features = mgp->features;
+	netdev->hw_features |= NETIF_F_RXCSUM;
 
 	/* fake NETIF_F_HW_VLAN_CTAG_RX for good GRO performance */
 	netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
 
-	netdev->features = netdev->hw_features | NETIF_F_HIGHDMA;
+	netdev->features = netdev->hw_features;
+	netdev->features |= NETIF_F_HIGHDMA;
 
 	netdev->vlan_features |= mgp->features;
 	if (mgp->fw_ver_tiny < 37)
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 79dd414f6e36..8b3def9866d0 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -6571,9 +6571,9 @@ static void s2io_ethtool_get_strings(struct net_device *dev,
 static int s2io_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct s2io_nic *sp = netdev_priv(dev);
-	netdev_features_t changed = (features ^ dev->features) & NETIF_F_LRO;
+	netdev_features_t changed = features ^ dev->features;
 
-	if (changed && netif_running(dev)) {
+	if (changed & NETIF_F_LRO && netif_running(dev)) {
 		int rc;
 
 		s2io_stop_all_tx_queue(sp);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index bcf89fe69cc4..29611221990f 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2374,9 +2374,10 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 		netdev->hw_features |= NETIF_F_RXHASH;
 	if (nn->cap & NFP_NET_CFG_CTRL_VXLAN) {
 		if (nn->cap & NFP_NET_CFG_CTRL_LSO) {
-			netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
-					       NETIF_F_GSO_UDP_TUNNEL_CSUM |
-					       NETIF_F_GSO_PARTIAL;
+			netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+			netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+			netdev->hw_features |= NETIF_F_GSO_PARTIAL;
+
 			netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
 		}
 		netdev->udp_tunnel_nic_info = &nfp_udp_tunnels;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 3e670133e27a..48da1da1c704 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -240,6 +240,7 @@ nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
 	netdev_features_t old_features = features;
 	netdev_features_t lower_features;
 	struct net_device *lower_dev;
+	netdev_features_t tmp;
 
 	lower_dev = repr->dst->u.port_info.lower_dev;
 
@@ -248,7 +249,10 @@ nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
 		lower_features |= NETIF_F_HW_CSUM;
 
 	features = netdev_intersect_features(features, lower_features);
-	features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_HW_TC);
+	tmp = NETIF_F_SOFT_FEATURES;
+	tmp |= NETIF_F_HW_TC;
+	tmp &= old_features;
+	features |= tmp;
 	features |= NETIF_F_LLTX;
 
 	return features;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c
index 4f2308570dcf..c224707f763f 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c
@@ -66,7 +66,7 @@ int nfp_port_set_features(struct net_device *netdev, netdev_features_t features)
 	if (!port)
 		return 0;
 
-	if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
+	if ((netdev->features & NETIF_F_HW_TC) && !(features & NETIF_F_HW_TC) &&
 	    port->tc_offload_cnt) {
 		netdev_err(netdev, "Cannot disable HW TC offload while offloads active\n");
 		return -EBUSY;
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 5b957cdc118e..a8a8d59dd008 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -6124,7 +6124,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 
 	dev_info(&pci_dev->dev, "%s%s%s%s%s%s%s%s%s%s%sdesc-v%u\n",
 		 dev->features & NETIF_F_HIGHDMA ? "highdma " : "",
-		 dev->features & (NETIF_F_IP_CSUM | NETIF_F_SG) ?
+		 (dev->features & NETIF_F_IP_CSUM || dev->features & NETIF_F_SG) ?
 			"csum " : "",
 		 dev->features & netdev_ctag_vlan_offload_features ?
 			"vlan " : "",
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 4f2511f763dd..8459002574fc 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1547,7 +1547,8 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
 
 	netdev->hw_features |= netdev->hw_enc_features;
 	netdev->features |= netdev->hw_features;
-	netdev->vlan_features |= netdev->features & ~NETIF_F_VLAN_FEATURES;
+	features = netdev->features & ~NETIF_F_VLAN_FEATURES;
+	netdev->vlan_features |= features;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT |
 			      IFF_LIVE_ADDR_CHANGE;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 993d0ee6db01..1c3b06599b37 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -536,9 +536,11 @@ static int netxen_set_features(struct net_device *dev,
 	netdev_features_t features)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
+	netdev_features_t changed;
 	int hw_lro;
 
-	if (!((dev->features ^ features) & NETIF_F_LRO))
+	changed = dev->features ^ features;
+	if (!(changed & NETIF_F_LRO))
 		return 0;
 
 	hw_lro = (features & NETIF_F_LRO) ? NETXEN_NIC_LRO_ENABLED
@@ -1357,8 +1359,10 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &netxen_hw_feature_set);
 
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		netdev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+		netdev->hw_features |= NETIF_F_IPV6_CSUM;
+		netdev->hw_features |= NETIF_F_TSO6;
+	}
 
 	netdev->vlan_features |= netdev->hw_features;
 
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 04af61f4122a..b37a045f09d6 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -897,18 +897,19 @@ static void qede_init_ndev(struct qede_dev *edev)
 	}
 
 	if (udp_tunnel_enable) {
-		hw_features |= (NETIF_F_GSO_UDP_TUNNEL |
-				NETIF_F_GSO_UDP_TUNNEL_CSUM);
-		ndev->hw_enc_features |= (NETIF_F_GSO_UDP_TUNNEL |
-					  NETIF_F_GSO_UDP_TUNNEL_CSUM);
+		hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+		hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		ndev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
+		ndev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 
 		qede_set_udp_tunnels(edev);
 	}
 
 	if (edev->dev_info.common.gre_enable) {
-		hw_features |= (NETIF_F_GSO_GRE | NETIF_F_GSO_GRE_CSUM);
-		ndev->hw_enc_features |= (NETIF_F_GSO_GRE |
-					  NETIF_F_GSO_GRE_CSUM);
+		hw_features |= NETIF_F_GSO_GRE;
+		hw_features |= NETIF_F_GSO_GRE_CSUM;
+		ndev->hw_enc_features |= NETIF_F_GSO_GRE;
+		ndev->hw_enc_features |= NETIF_F_GSO_GRE_CSUM;
 	}
 
 	ndev->vlan_features = hw_features;
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 06f4d9a9e938..fe823b03736b 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -3795,8 +3795,10 @@ static int ql3xxx_probe(struct pci_dev *pdev,
 	qdev->msg_enable = netif_msg_init(debug, default_msg);
 
 	ndev->features |= NETIF_F_HIGHDMA;
-	if (qdev->device_id == QL3032_DEVICE_ID)
-		ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+	if (qdev->device_id == QL3032_DEVICE_ID) {
+		ndev->features |= NETIF_F_IP_CSUM;
+		ndev->features |= NETIF_F_SG;
+	}
 
 	qdev->mem_map_registers = pci_ioremap_bar(pdev, 1);
 	if (!qdev->mem_map_registers) {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 7039925bc566..9bb1b9d53d96 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1078,7 +1078,8 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 			netdev_features_zero(&changeable);
 			netdev_features_set_array(&qlcnic_changable_feature_set,
 						  &changeable);
-			features ^= changed & changeable;
+			changed &= changeable;
+			features ^= changed;
 		}
 	}
 
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index c5c2e491d251..1a4e97594238 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1461,10 +1461,11 @@ static void cp_set_msglevel(struct net_device *dev, u32 value)
 
 static int cp_set_features(struct net_device *dev, netdev_features_t features)
 {
+	netdev_features_t changed = dev->features ^ features;
 	struct cp_private *cp = netdev_priv(dev);
 	unsigned long flags;
 
-	if (!((dev->features ^ features) & NETIF_F_RXCSUM))
+	if (!(changed & NETIF_F_RXCSUM))
 		return 0;
 
 	spin_lock_irqsave(&cp->lock, flags);
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 3844a0f418ec..fb4437f4ae35 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -905,7 +905,7 @@ static int rtl8139_set_features(struct net_device *dev, netdev_features_t featur
 	netdev_features_t changed = features ^ dev->features;
 	void __iomem *ioaddr = tp->mmio_addr;
 
-	if (!(changed & (NETIF_F_RXALL)))
+	if (!(changed & NETIF_F_RXALL))
 		return 0;
 
 	spin_lock_irqsave(&tp->lock, flags);
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 55f67e0c1280..ef8b13d342f5 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1446,8 +1446,10 @@ static netdev_features_t rtl8169_fix_features(struct net_device *dev,
 		features &= ~NETIF_F_ALL_TSO;
 
 	if (dev->mtu > ETH_DATA_LEN &&
-	    tp->mac_version > RTL_GIGA_MAC_VER_06)
-		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_ALL_TSO);
+	    tp->mac_version > RTL_GIGA_MAC_VER_06) {
+		features &= ~NETIF_F_CSUM_MASK;
+		features &= ~NETIF_F_ALL_TSO;
+	}
 
 	return features;
 }
@@ -5456,7 +5458,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2);
 		netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V2);
 	} else {
-		dev->hw_features |= NETIF_F_SG | NETIF_F_TSO;
+		dev->hw_features |= NETIF_F_SG;
+		dev->hw_features |= NETIF_F_TSO;
 		netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V1);
 		netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V1);
 	}
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index fc83ec23bd1d..2a16201ce0cf 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2578,7 +2578,8 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
 		       NAPI_POLL_WEIGHT);
 	rocker_carrier_init(rocker_port);
 
-	dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_SG;
+	dev->features |= NETIF_F_NETNS_LOCAL;
+	dev->features |= NETIF_F_SG;
 
 	/* MTU range: 68 - 9000 */
 	dev->min_mtu = ROCKER_PORT_MIN_MTU;
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 30af142820c6..7963a9aeafe0 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -2117,7 +2117,8 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
 
 	netdev_hw_features_zero(ndev);
 	netdev_hw_features_set_array(ndev, &sxgbe_hw_feature_set);
-	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+	ndev->features |= ndev->hw_features;
+	ndev->features |= NETIF_F_HIGHDMA;
 	ndev->watchdog_timeo = msecs_to_jiffies(TX_TIMEO);
 
 	/* assign filtering support */
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 064d6f224af8..dd8e278f8d8d 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -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 897a0113e257..4c802cd087fc 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1001,6 +1001,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;
@@ -1015,7 +1016,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))
@@ -1024,7 +1026,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 b6e0e4855821..c3a29d4169c9 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -213,10 +213,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 = 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;
@@ -225,8 +227,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.
 		 */
@@ -1364,7 +1367,7 @@ 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);
+				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;
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c
index 8692dc18efff..0b6dbd33410e 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2182,17 +2182,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.
 		 */
@@ -2904,8 +2907,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/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index 4829f66a47e7..6887ba4c9806 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -998,7 +998,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))
diff --git a/drivers/net/ethernet/sfc/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index ef00f1d87876..4c0f915dba82 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -212,10 +212,11 @@ void efx_siena_set_rx_mode(struct net_device *net_dev)
 int efx_siena_set_features(struct net_device *net_dev, netdev_features_t data)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
+	netdev_features_t features;
 	int rc;
 
 	/* If disabling RX n-tuple filtering, clear existing filters */
-	if (net_dev->features & ~data & NETIF_F_NTUPLE) {
+	if ((net_dev->features & NETIF_F_NTUPLE) && !(data & NETIF_F_NTUPLE)) {
 		rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
 		if (rc)
 			return rc;
@@ -224,8 +225,8 @@ int efx_siena_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)) {
+	features = net_dev->features ^ data;
+	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) || (features & NETIF_F_RXFCS)) {
 		/* efx_siena_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/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c
index f0c8de2c6075..c3aead3d052b 100644
--- a/drivers/net/ethernet/socionext/sni_ave.c
+++ b/drivers/net/ethernet/socionext/sni_ave.c
@@ -1594,8 +1594,10 @@ static int ave_probe(struct platform_device *pdev)
 	ndev->ethtool_ops = &ave_ethtool_ops;
 	SET_NETDEV_DEV(ndev, dev);
 
-	ndev->features    |= (NETIF_F_IP_CSUM | NETIF_F_RXCSUM);
-	ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_RXCSUM);
+	ndev->features    |= NETIF_F_IP_CSUM;
+	ndev->features    |= NETIF_F_RXCSUM;
+	ndev->hw_features |= NETIF_F_IP_CSUM;
+	ndev->hw_features |= NETIF_F_RXCSUM;
 
 	ndev->max_mtu = AVE_MAX_ETHFRAME - (ETH_HLEN + ETH_FCS_LEN);
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 6ddacc6a7f7a..8f227d5f2199 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7194,7 +7194,8 @@ int stmmac_dvr_probe(struct device *device,
 		}
 	}
 
-	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+	ndev->features |= ndev->hw_features;
+	ndev->features |= NETIF_F_HIGHDMA;
 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
 #ifdef STMMAC_VLAN_TAG_USED
 	/* Both mac100 and gmac support receive VLAN tag detection */
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index 0b08b0e085e8..bf899125b1ef 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -5056,8 +5056,10 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->dma = 0;
 
 	/* Cassini features. */
-	if ((cp->cas_flags & CAS_FLAG_NO_HW_CSUM) == 0)
-		dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+	if ((cp->cas_flags & CAS_FLAG_NO_HW_CSUM) == 0) {
+		dev->features |= NETIF_F_HW_CSUM;
+		dev->features |= NETIF_F_SG;
+	}
 
 	dev->features |= NETIF_F_HIGHDMA;
 
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index f7fa28ba5d53..6a37026e02b6 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9743,7 +9743,8 @@ static void niu_set_basic_features(struct net_device *dev)
 {
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_array(dev, &niu_hw_feature_set);
-	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+	dev->features |= dev->hw_features;
+	dev->features |= NETIF_F_RXCSUM;
 }
 
 static int niu_pci_init_one(struct pci_dev *pdev,
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index 8594ee839628..f8868f79ee95 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2784,8 +2784,10 @@ static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
 	dev->ethtool_ops = &hme_ethtool_ops;
 
 	/* Happy Meal can do it all... */
-	dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
-	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+	dev->hw_features = NETIF_F_SG;
+	dev->hw_features |= NETIF_F_HW_CSUM;
+	dev->features |= dev->hw_features;
+	dev->features |= NETIF_F_RXCSUM;
 
 	hp->irq = op->archdata.irqs[0];
 
@@ -3104,8 +3106,10 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
 	dev->ethtool_ops = &hme_ethtool_ops;
 
 	/* Happy Meal can do it all... */
-	dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
-	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+	dev->hw_features = NETIF_F_SG;
+	dev->hw_features |= NETIF_F_HW_CSUM;
+	dev->features |= dev->hw_features;
+	dev->features |= NETIF_F_RXCSUM;
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
 	/* Hook up PCI register/descriptor accessors. */
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index b390983861d8..2347a3df30cd 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1975,8 +1975,8 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 	port->ndev->max_mtu = AM65_CPSW_MAX_PACKET_SIZE;
 	netdev_hw_features_zero(port->ndev);
 	netdev_hw_features_set_array(port->ndev, &am65_cpsw_hw_feature_set);
-	port->ndev->features = port->ndev->hw_features |
-			       NETIF_F_HW_VLAN_CTAG_FILTER;
+	port->ndev->features = port->ndev->hw_features;
+	port->ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 	port->ndev->vlan_features |=  NETIF_F_SG;
 	port->ndev->netdev_ops = &am65_cpsw_nuss_netdev_ops;
 	port->ndev->ethtool_ops = &am65_cpsw_ethtool_ops_slave;
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index ed66c4d4d830..7e12c6a77d30 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1456,7 +1456,8 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
 
 	priv_sl2->emac_port = 1;
 	cpsw->slaves[1].ndev = ndev;
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX;
+	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_ops;
@@ -1633,7 +1634,8 @@ static int cpsw_probe(struct platform_device *pdev)
 
 	cpsw->slaves[0].ndev = ndev;
 
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX;
+	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_ops;
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 3dbfb1b20649..5def0b3bf8ef 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -1461,7 +1461,8 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
 	int status;
 	u64 v1, v2;
 
-	netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+	netdev->hw_features = NETIF_F_IP_CSUM;
+	netdev->hw_features |= NETIF_F_RXCSUM;
 
 	netdev->features = NETIF_F_IP_CSUM;
 	if (GELIC_CARD_RX_CSUM_DEFAULT)
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index bc4914c758ad..e2e0e18fcdc8 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -2275,10 +2275,12 @@ spider_net_setup_netdev(struct spider_net_card *card)
 
 	spider_net_setup_netdev_ops(netdev);
 
-	netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
+	netdev->hw_features = NETIF_F_RXCSUM;
+	netdev->hw_features |= NETIF_F_IP_CSUM;
 	if (SPIDER_NET_RX_CSUM_DEFAULT)
 		netdev->features |= NETIF_F_RXCSUM;
-	netdev->features |= NETIF_F_IP_CSUM | NETIF_F_LLTX;
+	netdev->features |= NETIF_F_IP_CSUM;
+	netdev->features |= NETIF_F_LLTX;
 	/* some time: NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
 	 *		NETIF_F_HW_VLAN_CTAG_FILTER
 	 */
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 1d795114c264..3c8631f9925d 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -967,8 +967,10 @@ static int rhine_init_one_common(struct device *hwdev, u32 quirks,
 
 	netif_napi_add(dev, &rp->napi, rhine_napipoll, 64);
 
-	if (rp->quirks & rqRhineI)
-		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
+	if (rp->quirks & rqRhineI) {
+		dev->features |= NETIF_F_SG;
+		dev->features |= NETIF_F_HW_CSUM;
+	}
 
 	if (rp->quirks & rqMgmt)
 		dev->features |= netdev_ctag_vlan_features;
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 6da36cb8af80..456563b6b242 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_vlan.h>
 #include <linux/nls.h>
 #include <linux/vmalloc.h>
@@ -1350,6 +1351,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	struct ndis_offload hwcaps;
 	struct ndis_offload_params offloads;
 	unsigned int gso_max_size = GSO_LEGACY_MAX_SIZE;
+	netdev_features_t features;
 	int ret;
 
 	/* Find HW offload capabilities */
@@ -1429,7 +1431,10 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	/* In case some hw_features disappeared we need to remove them from
 	 * net->features list as they're no longer supported.
 	 */
-	net->features &= ~NETVSC_SUPPORTED_HW_FEATURES | net->hw_features;
+	netdev_features_fill(&features);
+	features &= ~NETVSC_SUPPORTED_HW_FEATURES;
+	features |= net->hw_features;
+	net->features &= features;
 
 	netif_set_tso_max_size(net, gso_max_size);
 
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 656a54a9f6e8..370f3fa59587 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -328,7 +328,8 @@ static void ifb_setup(struct net_device *dev)
 	dev->features |= ifb_features;
 	dev->hw_features |= dev->features;
 	dev->hw_enc_features |= dev->features;
-	dev->vlan_features |= ifb_features & ~netdev_tx_vlan_features;
+	ifb_features &= ~netdev_tx_vlan_features;
+	dev->vlan_features |= ifb_features;
 
 	dev->flags |= IFF_NOARP;
 	dev->flags &= ~IFF_MULTICAST;
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index b0d7a484fd39..0078ecfe8838 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -254,13 +254,18 @@ static netdev_features_t ipvlan_fix_features(struct net_device *dev,
 					     netdev_features_t features)
 {
 	struct ipvl_dev *ipvlan = netdev_priv(dev);
+	netdev_features_t tmp;
 
 	features |= NETIF_F_ALL_FOR_ALL;
-	features &= (ipvlan->sfeatures | ~IPVLAN_FEATURES);
+	netdev_features_fill(&tmp);
+	tmp &= ~IPVLAN_FEATURES;
+	tmp |= ipvlan->sfeatures;
+	features &= tmp;
 	features = netdev_increment_features(ipvlan->phy_dev->features,
 					     features, features);
 	features |= IPVLAN_ALWAYS_ON;
-	features &= (IPVLAN_FEATURES | IPVLAN_ALWAYS_ON);
+	tmp = IPVLAN_FEATURES | IPVLAN_ALWAYS_ON;
+	features &= tmp;
 
 	return features;
 }
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index ca7f01d33483..41e17d737d33 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3456,7 +3456,8 @@ static int macsec_dev_init(struct net_device *dev)
 		dev->features = REAL_DEV_FEATURES(real_dev);
 	} else {
 		dev->features = real_dev->features & SW_MACSEC_FEATURES;
-		dev->features |= NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE;
+		dev->features |= NETIF_F_LLTX;
+		dev->features |= NETIF_F_GSO_SOFTWARE;
 	}
 
 	dev->needed_headroom = real_dev->needed_headroom +
@@ -3488,12 +3489,15 @@ static netdev_features_t macsec_fix_features(struct net_device *dev,
 {
 	struct macsec_dev *macsec = macsec_priv(dev);
 	struct net_device *real_dev = macsec->real_dev;
+	netdev_features_t tmp;
 
 	if (macsec_is_offloaded(macsec))
 		return REAL_DEV_FEATURES(real_dev);
 
-	features &= (real_dev->features & SW_MACSEC_FEATURES) |
-		    NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES;
+	tmp = real_dev->features & SW_MACSEC_FEATURES;
+	tmp |= NETIF_F_GSO_SOFTWARE;
+	tmp |= NETIF_F_SOFT_FEATURES;
+	features &= tmp;
 	features |= NETIF_F_LLTX;
 
 	return features;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index d9a20c0341c6..aac040522ee9 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1099,15 +1099,22 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	netdev_features_t lowerdev_features = vlan->lowerdev->features;
 	netdev_features_t mask;
+	netdev_features_t tmp;
 
 	features |= NETIF_F_ALL_FOR_ALL;
-	features &= (vlan->set_features | ~MACVLAN_FEATURES);
+	netdev_features_fill(&tmp);
+	tmp &= ~MACVLAN_FEATURES;
+	tmp |= vlan->set_features;
+	features &= tmp;
 	mask = features;
 
-	lowerdev_features &= (features | ~NETIF_F_LRO);
+	tmp = features;
+	tmp &= ~NETIF_F_LRO;
+	lowerdev_features &= tmp;
 	features = netdev_increment_features(lowerdev_features, features, mask);
 	features |= ALWAYS_ON_FEATURES;
-	features &= (ALWAYS_ON_FEATURES | MACVLAN_FEATURES);
+	tmp = ALWAYS_ON_FEATURES | MACVLAN_FEATURES;
+	features &= tmp;
 
 	return features;
 }
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index ad687b14dda3..d501c7c58f70 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -233,7 +233,7 @@ nsim_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct netdevsim *ns = netdev_priv(dev);
 
-	if ((dev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC))
+	if ((dev->features & NETIF_F_HW_TC) && !(features & NETIF_F_HW_TC))
 		return nsim_bpf_disable_tc(ns);
 
 	return 0;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index eec3c8112d3f..4c999e18d4a1 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2184,9 +2184,9 @@ static void team_setup(struct net_device *dev)
 	/* Don't allow team devices to change network namespaces. */
 	dev->features |= NETIF_F_NETNS_LOCAL;
 
-	dev->hw_features = TEAM_VLAN_FEATURES |
-			   NETIF_F_HW_VLAN_CTAG_RX |
-			   NETIF_F_HW_VLAN_CTAG_FILTER;
+	dev->hw_features = TEAM_VLAN_FEATURES;
+	dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+	dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
 	dev->features |= dev->hw_features;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 194757bbd2b3..322956768815 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1003,7 +1003,8 @@ static int tun_net_init(struct net_device *dev)
 
 	dev->hw_features = TUN_USER_FEATURES;
 	netdev_hw_features_set_array(dev, &tun_hw_feature_set);
-	dev->features = dev->hw_features | NETIF_F_LLTX;
+	dev->features = dev->hw_features;
+	dev->features |= NETIF_F_LLTX;
 	dev->vlan_features = dev->features & ~netdev_tx_vlan_features;
 
 	tun->flags = (tun->flags & ~TUN_FEATURES) |
@@ -1174,8 +1175,11 @@ static netdev_features_t tun_net_fix_features(struct net_device *dev,
 	netdev_features_t features)
 {
 	struct tun_struct *tun = netdev_priv(dev);
+	netdev_features_t tmp1, tmp2;
 
-	return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
+	tmp1 = features & tun->set_features;
+	tmp2 = features & ~TUN_USER_FEATURES;
+	return tmp1 | tmp2;
 }
 
 static void tun_set_headroom(struct net_device *dev, int new_hr)
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index c89639381eca..29451eb7263b 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -185,7 +185,8 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
 	dev->net->flags |= IFF_NOARP;
 
 	/* no need to put the VLAN tci in the packet headers */
-	dev->net->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_FILTER;
+	dev->net->features |= NETIF_F_HW_VLAN_CTAG_TX;
+	dev->net->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	/* monitor VLAN additions and removals */
 	dev->net->netdev_ops = &cdc_mbim_netdev_ops;
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index bfb58c91db04..10cf0a68980e 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1085,7 +1085,8 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 	if (DEFAULT_RX_CSUM_ENABLE)
 		dev->net->features |= NETIF_F_RXCSUM;
 
-	dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+	dev->net->hw_features = NETIF_F_IP_CSUM;
+	dev->net->hw_features |= NETIF_F_RXCSUM;
 	set_bit(EVENT_NO_IP_ALIGN, &dev->flags);
 
 	smsc95xx_init_mac_address(dev);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 5978baef9695..805056a246cc 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -307,7 +307,8 @@ static bool veth_skb_is_eligible_for_gro(const struct net_device *dev,
 {
 	return !(dev->features & NETIF_F_ALL_TSO) ||
 		(skb->destructor == sock_wfree &&
-		 rcv->features & (NETIF_F_GRO_FRAGLIST | NETIF_F_GRO_UDP_FWD));
+		 (rcv->features & NETIF_F_GRO_FRAGLIST ||
+		  rcv->features & NETIF_F_GRO_UDP_FWD));
 }
 
 static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -1657,7 +1658,8 @@ static void veth_setup(struct net_device *dev)
 
 	dev->hw_features = veth_features;
 	dev->hw_enc_features = veth_features;
-	dev->mpls_features = NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE;
+	dev->mpls_features = NETIF_F_GSO_SOFTWARE;
+	dev->mpls_features |= NETIF_F_HW_CSUM;
 	netif_set_tso_max_size(dev, GSO_MAX_SIZE);
 }
 
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index c40d80f25809..3d8f4da73bd7 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3510,9 +3510,12 @@ static int virtnet_probe(struct virtio_device *vdev)
 	/* Do we support "hardware" checksums? */
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
 		/* This opens up the world of extra features. */
-		dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG;
-		if (csum)
-			dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+		dev->hw_features |= NETIF_F_HW_CSUM;
+		dev->hw_features |= NETIF_F_SG;
+		if (csum) {
+			dev->features |= NETIF_F_HW_CSUM;
+			dev->features |= NETIF_F_SG;
+		}
 
 		if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
 			dev->hw_features |= netdev_general_tso_features;
@@ -3528,8 +3531,11 @@ static int virtnet_probe(struct virtio_device *vdev)
 
 		dev->features |= NETIF_F_GSO_ROBUST;
 
-		if (gso)
-			dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
+		if (gso) {
+			netdev_features_t tmp = dev->hw_features & NETIF_F_ALL_TSO;
+
+			dev->features |= tmp;
+		}
 		/* (!csum && gso) case will be fixed by register_netdev() */
 	}
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index ede0a87ca982..9f8a074eab03 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2592,8 +2592,8 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
 	if (adapter->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
 		devRead->misc.uptFeatures |= UPT1_F_RXVLAN;
 
-	if (adapter->netdev->features & (NETIF_F_GSO_UDP_TUNNEL |
-					 NETIF_F_GSO_UDP_TUNNEL_CSUM))
+	if (adapter->netdev->features & NETIF_F_GSO_UDP_TUNNEL ||
+	    adapter->netdev->features & NETIF_F_GSO_UDP_TUNNEL_CSUM)
 		devRead->misc.uptFeatures |= UPT1_F_RXINNEROFLD;
 
 	devRead->misc.mtu = cpu_to_le32(adapter->netdev->mtu);
@@ -3332,8 +3332,8 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 	netdev_hw_features_set_array(netdev, &vmxnet3_hw_feature_set);
 
 	if (VMXNET3_VERSION_GE_4(adapter)) {
-		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
-				NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 		netdev_hw_enc_features_zero(netdev);
 		netdev_hw_enc_features_set_array(netdev,
 						 &vmxnet3_hw_enc_feature_set);
@@ -3389,7 +3389,8 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 
 	netdev->vlan_features = netdev->hw_features &
 				~netdev_ctag_vlan_offload_features;
-	netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev->features = netdev->hw_features;
+	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 }
 
 
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index abc2aeb0559e..3ed93302084a 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -410,12 +410,18 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	unsigned long flags;
 	netdev_features_t changed = features ^ netdev->features;
-	netdev_features_t tun_offload_mask = NETIF_F_GSO_UDP_TUNNEL |
-					     NETIF_F_GSO_UDP_TUNNEL_CSUM;
-	u8 udp_tun_enabled = (netdev->features & tun_offload_mask) != 0;
-
-	if (changed & (NETIF_F_RXCSUM | NETIF_F_LRO |
-		       NETIF_F_HW_VLAN_CTAG_RX | tun_offload_mask)) {
+	netdev_features_t tun_offload_mask;
+	u8 udp_tun_enabled;
+
+	netdev_features_zero(&tun_offload_mask);
+	tun_offload_mask |= NETIF_F_GSO_UDP_TUNNEL;
+	tun_offload_mask |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+	udp_tun_enabled = (netdev->features & tun_offload_mask) != 0;
+
+	if (changed & NETIF_F_RXCSUM ||
+	    changed & NETIF_F_LRO ||
+	    changed & NETIF_F_HW_VLAN_CTAG_RX ||
+	    changed & tun_offload_mask) {
 		if (features & NETIF_F_RXCSUM)
 			adapter->shared->devRead.misc.uptFeatures |=
 			UPT1_F_RXCSUM;
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index d3aa9e7a37c2..8c57cd413e79 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1143,7 +1143,8 @@ static int ath6kl_set_features(struct net_device *dev,
 							 vif->fw_vif_idx,
 							 ar->rx_meta_ver, 0, 0);
 		if (err) {
-			dev->features = features | NETIF_F_RXCSUM;
+			dev->features = features;
+			dev->features |= NETIF_F_RXCSUM;
 			return err;
 		}
 	}
@@ -1304,8 +1305,10 @@ void init_netdev(struct net_device *dev)
 					ATH6KL_HTC_ALIGN_BYTES, 4);
 
 	if (!test_bit(ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
-		      ar->fw_capabilities))
-		dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+		      ar->fw_capabilities)) {
+		dev->hw_features |= NETIF_F_IP_CSUM;
+		dev->hw_features |= NETIF_F_RXCSUM;
+	}
 
 	return;
 }
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
index f4070fddc8c7..5f0bba0cfdf6 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
@@ -96,8 +96,10 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
 	ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
 	ieee80211_hw_set(hw, WANT_MONITOR_VIF);
 
-	if (priv->trans->max_skb_frags)
-		hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
+	if (priv->trans->max_skb_frags) {
+		hw->netdev_features = NETIF_F_HIGHDMA;
+		hw->netdev_features |= NETIF_F_SG;
+	}
 
 	hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
 	hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 9a5abb7958b6..5fbeb262a90b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -318,8 +318,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 	if (mvm->trans->num_rx_queues > 1)
 		ieee80211_hw_set(hw, USES_RSS);
 
-	if (mvm->trans->max_skb_frags)
-		hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
+	if (mvm->trans->max_skb_frags) {
+		hw->netdev_features = NETIF_F_HIGHDMA;
+		hw->netdev_features |= NETIF_F_SG;
+	}
 
 	hw->queues = IEEE80211_NUM_ACS;
 	hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index f9e08b339e0c..3283c346fbe7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -887,9 +887,12 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
 	unsigned int mss = skb_shinfo(skb)->gso_size;
 	unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len;
 	u16 snap_ip_tcp, pad;
-	netdev_features_t netdev_flags = NETIF_F_CSUM_MASK | NETIF_F_SG;
+	netdev_features_t netdev_flags;
 	u8 tid;
 
+	netdev_flags = NETIF_F_CSUM_MASK;
+	netdev_flags |= NETIF_F_SG;
+
 	snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) +
 		tcp_hdrlen(skb);
 
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 989328168e1c..8c37a65d8d06 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -533,7 +533,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 	dev->netdev_ops	= &xenvif_netdev_ops;
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_array(dev, &xenvif_hw_feature_set);
-	dev->features = dev->hw_features | NETIF_F_RXCSUM;
+	dev->features = dev->hw_features;
+	dev->features |= NETIF_F_RXCSUM;
 	dev->ethtool_ops = &xenvif_ethtool_ops;
 
 	dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index f662739137b5..0811ff9452f7 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -421,8 +421,10 @@ int cvm_oct_common_init(struct net_device *dev)
 	    (always_use_pow || strstr(pow_send_list, dev->name)))
 		priv->queue = -1;
 
-	if (priv->queue != -1)
-		dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+	if (priv->queue != -1) {
+		dev->features |= NETIF_F_SG;
+		dev->features |= NETIF_F_IP_CSUM;
+	}
 
 	/* We do our own locking, Linux doesn't need to */
 	dev->features |= NETIF_F_LLTX;
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h
index e096786e4b7a..772401f25a81 100644
--- a/include/linux/netdev_features_helper.h
+++ b/include/linux/netdev_features_helper.h
@@ -688,7 +688,7 @@ 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) {
+	if ((f1 & NETIF_F_HW_CSUM) != (f2 & NETIF_F_HW_CSUM)) {
 		if (f1 & NETIF_F_HW_CSUM)
 			f1 |= netdev_ip_csum_features;
 		else
@@ -701,7 +701,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/8021q/vlan.h b/net/8021q/vlan.h
index 5eaf38875554..60b5e401e346 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -5,6 +5,7 @@
 #include <linux/if_vlan.h>
 #include <linux/u64_stats_sync.h>
 #include <linux/list.h>
+#include <linux/netdev_features_helper.h>
 
 /* if this changes, algorithm will have to be reworked because this
  * depends on completely exhausting the VLAN identifier space.  Thus
@@ -107,13 +108,17 @@ static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)
 {
 	netdev_features_t ret;
 
-	ret = real_dev->hw_enc_features &
-	      (NETIF_F_CSUM_MASK | NETIF_F_GSO_SOFTWARE |
-	       NETIF_F_GSO_ENCAP_ALL);
+	ret = NETIF_F_CSUM_MASK | NETIF_F_GSO_SOFTWARE;
+	ret |= NETIF_F_GSO_ENCAP_ALL;
+	ret &= real_dev->hw_enc_features;
 
-	if ((ret & NETIF_F_GSO_ENCAP_ALL) && (ret & NETIF_F_CSUM_MASK))
-		return (ret & ~NETIF_F_CSUM_MASK) | NETIF_F_HW_CSUM;
-	return 0;
+	if ((ret & NETIF_F_GSO_ENCAP_ALL) && (ret & NETIF_F_CSUM_MASK)) {
+		ret &= ~NETIF_F_CSUM_MASK;
+		ret |= NETIF_F_HW_CSUM;
+		return ret;
+	}
+	netdev_features_zero(&ret);
+	return ret;
 }
 
 #define vlan_group_for_each_dev(grp, i, dev) \
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 3af719812f00..ab2847fa938d 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -578,7 +578,8 @@ static int vlan_dev_init(struct net_device *dev)
 	dev->hw_features |= NETIF_F_ALL_FCOE;
 	netdev_hw_features_set_array(dev, &vlan_hw_feature_set);
 
-	dev->features |= dev->hw_features | NETIF_F_LLTX;
+	dev->features |= dev->hw_features;
+	dev->features |= NETIF_F_LLTX;
 	netif_inherit_tso_max(dev, real_dev);
 	if (dev->features & NETIF_F_VLAN_FEATURES)
 		netdev_warn(real_dev, "VLAN features are set incorrectly.  Q-in-Q configurations may not work correctly.\n");
@@ -652,10 +653,11 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
 	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
 	netdev_features_t old_features = features;
 	netdev_features_t lower_features;
+	netdev_features_t tmp;
 
-	lower_features = netdev_intersect_features((real_dev->vlan_features |
-						    NETIF_F_RXCSUM),
-						   real_dev->features);
+	tmp = real_dev->vlan_features;
+	tmp |= NETIF_F_RXCSUM;
+	lower_features = netdev_intersect_features(tmp, real_dev->features);
 
 	/* Add HW_CSUM setting to preserve user ability to control
 	 * checksum offload on the vlan device.
@@ -663,7 +665,9 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
 	if (lower_features & netdev_ip_csum_features)
 		lower_features |= NETIF_F_HW_CSUM;
 	features = netdev_intersect_features(features, lower_features);
-	features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE);
+	tmp = NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE;
+	tmp &= old_features;
+	features |= tmp;
 	features |= NETIF_F_LLTX;
 
 	return features;
diff --git a/net/core/dev.c b/net/core/dev.c
index 7a57d8b4f307..2a0f31c66dea 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3552,6 +3552,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);
@@ -3563,16 +3564,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 |
-						     netdev_tx_vlan_features);
+	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);
 }
@@ -9606,6 +9607,8 @@ 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 & netdev_ip_csum_features)) {
@@ -9637,7 +9640,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. */
@@ -10007,8 +10012,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");
@@ -10025,7 +10030,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) {
@@ -10058,7 +10064,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.
 	 */
@@ -11147,16 +11154,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/core/pktgen.c b/net/core/pktgen.c
index 88906ba6d9a7..198d94f2e8f0 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2963,7 +2963,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 
 	if (!(pkt_dev->flags & F_UDPCSUM)) {
 		skb->ip_summed = CHECKSUM_NONE;
-	} else if (odev->features & (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM)) {
+	} else if (odev->features & NETIF_F_HW_CSUM ||
+		   odev->features & NETIF_F_IP_CSUM) {
 		skb->ip_summed = CHECKSUM_PARTIAL;
 		skb->csum = 0;
 		udp4_hwcsum(skb, iph->saddr, iph->daddr);
@@ -3098,7 +3099,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 
 	if (!(pkt_dev->flags & F_UDPCSUM)) {
 		skb->ip_summed = CHECKSUM_NONE;
-	} else if (odev->features & (NETIF_F_HW_CSUM | NETIF_F_IPV6_CSUM)) {
+	} else if (odev->features & NETIF_F_HW_CSUM ||
+		   odev->features & NETIF_F_IPV6_CSUM) {
 		skb->ip_summed = CHECKSUM_PARTIAL;
 		skb->csum_start = skb_transport_header(skb) - skb->head;
 		skb->csum_offset = offsetof(struct udphdr, check);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 974bbbbe7138..955d7640dde6 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4312,7 +4312,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
 		unsigned short gso_size = skb_shinfo(head_skb)->gso_size;
 
 		/* Update type to add partial and then remove dodgy if set */
-		type |= (features & NETIF_F_GSO_PARTIAL) / NETIF_F_GSO_PARTIAL * SKB_GSO_PARTIAL;
+		type |= (features & NETIF_F_GSO_PARTIAL) ? 0 : SKB_GSO_PARTIAL;
 		type &= ~SKB_GSO_DODGY;
 
 		/* Update GSO info and prepare to start updating headers on
diff --git a/net/core/sock.c b/net/core/sock.c
index 4cb957d934a2..3127552e8989 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2326,7 +2326,8 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 		if (dst->header_len && !xfrm_dst_offload_ok(dst)) {
 			sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
 		} else {
-			sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
+			sk->sk_route_caps |= NETIF_F_SG;
+			sk->sk_route_caps |= NETIF_F_HW_CSUM;
 			/* pairs with the WRITE_ONCE() in netif_set_gso_max_size() */
 			sk->sk_gso_max_size = READ_ONCE(dst->dev->gso_max_size);
 			sk_trim_gso_size(sk);
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index fd44638ec16b..53fa477d20ab 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -489,8 +489,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
 	 */
 
 	ip6_dst_store(newsk, dst, NULL, NULL);
-	newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM |
-						      NETIF_F_TSO);
+	newsk->sk_route_caps = dst->dev->features;
+	newsk->sk_route_caps &= ~NETIF_F_IP_CSUM;
+	newsk->sk_route_caps &= ~NETIF_F_TSO;
 	newdp6 = (struct dccp6_sock *)newsk;
 	newinet = inet_sk(newsk);
 	newinet->pinet6 = &newdp6->inet6;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index ad6a6663feeb..a7e831bc5632 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2287,11 +2287,14 @@ void dsa_slave_setup_tagger(struct net_device *slave)
 
 	p->xmit = cpu_dp->tag_ops->xmit;
 
-	slave->features = master->vlan_features | NETIF_F_HW_TC;
+	slave->features = master->vlan_features;
+	slave->features |= NETIF_F_HW_TC;
 	slave->hw_features |= NETIF_F_HW_TC;
 	slave->features |= NETIF_F_LLTX;
-	if (slave->needed_tailroom)
-		slave->features &= ~(NETIF_F_SG | NETIF_F_FRAGLIST);
+	if (slave->needed_tailroom) {
+		slave->features &= ~NETIF_F_SG;
+		slave->features &= ~NETIF_F_FRAGLIST;
+	}
 	if (ds->needs_standalone_vlan_filtering)
 		slave->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 }
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 2ed9277a873e..8f32e4f06bfb 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(&ethtool_all_feature_set, &eth_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);
 
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 935026f4c807..2931b3385bc9 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -218,13 +218,15 @@ static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
 	skb->encap_hdr_csum = 1;
 
 	if ((!(skb->dev->gso_partial_features & NETIF_F_HW_ESP) &&
-	     !(features & NETIF_F_HW_ESP)) || x->xso.dev != skb->dev)
-		esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK |
-					    NETIF_F_SCTP_CRC);
-	else if (!(features & NETIF_F_HW_ESP_TX_CSUM) &&
-		 !(skb->dev->gso_partial_features & NETIF_F_HW_ESP_TX_CSUM))
-		esp_features = features & ~(NETIF_F_CSUM_MASK |
-					    NETIF_F_SCTP_CRC);
+	     !(features & NETIF_F_HW_ESP)) || x->xso.dev != skb->dev) {
+		esp_features = features & ~NETIF_F_CSUM_MASK;
+		esp_features &= ~NETIF_F_SG;
+		esp_features &= ~NETIF_F_SCTP_CRC;
+	} else if (!(features & NETIF_F_HW_ESP_TX_CSUM) &&
+		 !(skb->dev->gso_partial_features & NETIF_F_HW_ESP_TX_CSUM)) {
+		esp_features = features & ~NETIF_F_CSUM_MASK;
+		esp_features  &= ~NETIF_F_SCTP_CRC;
+	}
 
 	xo->flags |= XFRM_GSO_SEGMENT;
 
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index d7bd1daf022b..9ca2620de9ea 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1012,7 +1012,8 @@ static int __ip_append_data(struct sock *sk,
 	 */
 	if (transhdrlen &&
 	    length + fragheaderlen <= mtu &&
-	    rt->dst.dev->features & (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM) &&
+	    (rt->dst.dev->features & NETIF_F_HW_CSUM ||
+	     rt->dst.dev->features & NETIF_F_IP_CSUM) &&
 	    (!(flags & MSG_MORE) || cork->gso_size) &&
 	    (!exthdrlen || (rt->dst.dev->features & NETIF_F_HW_ESP_TX_CSUM)))
 		csummode = CHECKSUM_PARTIAL;
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 6d1a4bec2614..0486dbe58390 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -64,9 +64,9 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 	/* Try to offload checksum if possible */
 	offload_csum = !!(need_csum &&
 			  !need_ipsec &&
-			  (skb->dev->features &
-			   (is_ipv6 ? (NETIF_F_HW_CSUM | NETIF_F_IPV6_CSUM) :
-				      (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM))));
+			  (skb->dev->features & NETIF_F_HW_CSUM ||
+			   (is_ipv6 ? (skb->dev->features & NETIF_F_IPV6_CSUM) :
+				      (skb->dev->features & NETIF_F_IP_CSUM))));
 
 	features &= skb->dev->hw_enc_features;
 	if (need_csum)
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 3a293838a91d..95b5c26abad5 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -256,12 +256,14 @@ static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
 
 	skb->encap_hdr_csum = 1;
 
-	if (!(features & NETIF_F_HW_ESP) || x->xso.dev != skb->dev)
-		esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK |
-					    NETIF_F_SCTP_CRC);
-	else if (!(features & NETIF_F_HW_ESP_TX_CSUM))
-		esp_features = features & ~(NETIF_F_CSUM_MASK |
-					    NETIF_F_SCTP_CRC);
+	if (!(features & NETIF_F_HW_ESP) || x->xso.dev != skb->dev) {
+		esp_features = features & ~NETIF_F_CSUM_MASK;
+		esp_features &= ~NETIF_F_SG;
+		esp_features &= ~NETIF_F_SCTP_CRC;
+	} else if (!(features & NETIF_F_HW_ESP_TX_CSUM)) {
+		esp_features = features & ~NETIF_F_CSUM_MASK;
+		esp_features  &= ~NETIF_F_SCTP_CRC;
+	}
 
 	xo->flags |= XFRM_GSO_SEGMENT;
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 897ca4f9b791..f8fca2a3af3a 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1539,7 +1539,8 @@ static int __ip6_append_data(struct sock *sk,
 	    headersize == sizeof(struct ipv6hdr) &&
 	    length <= mtu - headersize &&
 	    (!(flags & MSG_MORE) || cork->gso_size) &&
-	    rt->dst.dev->features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
+	    (rt->dst.dev->features & NETIF_F_IPV6_CSUM ||
+	     rt->dst.dev->features & NETIF_F_HW_CSUM))
 		csummode = CHECKSUM_PARTIAL;
 
 	if ((flags & MSG_ZEROCOPY) && length) {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 95b58c5cac07..bd0c2073828c 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -2391,13 +2391,15 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 	ieee80211_setup_sdata(sdata, type);
 
 	if (ndev) {
+		netdev_features_t tmp;
+
 		ndev->ieee80211_ptr->use_4addr = params->use_4addr;
 		if (type == NL80211_IFTYPE_STATION)
 			sdata->u.mgd.use_4addr = params->use_4addr;
 
 		ndev->features |= local->hw.netdev_features;
-		ndev->hw_features |= ndev->features &
-					MAC80211_SUPPORTED_FEATURES_TX;
+		tmp = ndev->features & MAC80211_SUPPORTED_FEATURES_TX;
+		ndev->hw_features |= tmp;
 
 		netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
 
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 0459fe97ddd9..522457207275 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -122,7 +122,8 @@ static void do_setup(struct net_device *netdev)
 	netdev->vlan_features = netdev->features;
 	netdev->hw_enc_features = netdev->features;
 	netdev->features |= netdev_tx_vlan_features;
-	netdev->hw_features = netdev->features & ~NETIF_F_LLTX;
+	netdev->hw_features = netdev->features;
+	netdev->hw_features &= ~NETIF_F_LLTX;
 
 	eth_hw_addr_random(netdev);
 }
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index e3e6cf75aa03..7e57a67ecce3 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -1403,7 +1403,7 @@ static int tls_dev_event(struct notifier_block *this, unsigned long event,
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
 	if (!dev->tlsdev_ops &&
-	    !(dev->features & (NETIF_F_HW_TLS_RX | NETIF_F_HW_TLS_TX)))
+	    !(dev->features & netdev_tls_features))
 		return NOTIFY_DONE;
 
 	switch (event) {
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 96ffd287ae9a..06b94053097e 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -112,8 +112,11 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 	if (!xo || (xo->flags & XFRM_XMIT))
 		return skb;
 
-	if (!(features & NETIF_F_HW_ESP))
-		esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK);
+	if (!(features & NETIF_F_HW_ESP)) {
+		esp_features = features;
+		esp_features &= ~NETIF_F_SG;
+		esp_features &= ~NETIF_F_CSUM_MASK;
+	}
 
 	sp = skb_sec_path(skb);
 	x = sp->xvec[sp->len - 1];
@@ -379,7 +382,8 @@ static int xfrm_api_check(struct net_device *dev)
 	       dev->xfrmdev_ops->xdo_dev_state_delete)))
 		return NOTIFY_BAD;
 #else
-	if (dev->features & (NETIF_F_HW_ESP | NETIF_F_HW_ESP_TX_CSUM))
+	if (dev->features & NETIF_F_HW_ESP ||
+	    dev->features & NETIF_F_HW_ESP_TX_CSUM)
 		return NOTIFY_BAD;
 #endif
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 16/36] treewide: use replace features '0' by netdev_empty_features
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (14 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 15/36] treewide: simplify the netdev features expression Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10 10:48   ` Alexander Lobakin
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 17/36] treewide: adjust features initialization Jian Shen
                   ` (19 subsequent siblings)
  35 siblings, 1 reply; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

For the prototype of netdev_features_t will be changed from
u64 to bitmap, so it's unable to assignment with 0 directly.
Replace it with netdev_empty_features.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/hsi/clients/ssi_protocol.c             | 2 +-
 drivers/net/caif/caif_serial.c                 | 2 +-
 drivers/net/ethernet/amazon/ena/ena_netdev.c   | 2 +-
 drivers/net/ethernet/broadcom/b44.c            | 2 +-
 drivers/net/ethernet/broadcom/tg3.c            | 2 +-
 drivers/net/ethernet/dnet.c                    | 2 +-
 drivers/net/ethernet/ec_bhf.c                  | 2 +-
 drivers/net/ethernet/emulex/benet/be_main.c    | 2 +-
 drivers/net/ethernet/ethoc.c                   | 2 +-
 drivers/net/ethernet/huawei/hinic/hinic_main.c | 5 +++--
 drivers/net/ethernet/ibm/ibmvnic.c             | 6 +++---
 drivers/net/ethernet/intel/iavf/iavf_main.c    | 9 +++++----
 drivers/net/ethernet/microsoft/mana/mana_en.c  | 2 +-
 drivers/net/ethernet/sfc/ef10.c                | 2 +-
 drivers/net/tap.c                              | 2 +-
 drivers/net/tun.c                              | 2 +-
 drivers/net/usb/cdc-phonet.c                   | 3 ++-
 drivers/net/usb/lan78xx.c                      | 2 +-
 drivers/s390/net/qeth_core_main.c              | 2 +-
 drivers/usb/gadget/function/f_phonet.c         | 3 ++-
 net/dccp/ipv4.c                                | 2 +-
 net/dccp/ipv6.c                                | 2 +-
 net/ethtool/features.c                         | 2 +-
 net/ethtool/ioctl.c                            | 6 ++++--
 net/ipv4/af_inet.c                             | 2 +-
 net/ipv4/tcp.c                                 | 2 +-
 net/ipv4/tcp_ipv4.c                            | 2 +-
 net/ipv6/af_inet6.c                            | 2 +-
 net/ipv6/inet6_connection_sock.c               | 2 +-
 net/ipv6/tcp_ipv6.c                            | 2 +-
 net/openvswitch/datapath.c                     | 2 +-
 31 files changed, 44 insertions(+), 38 deletions(-)

diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c
index 21f11a5b965b..c7f3dae91e36 100644
--- a/drivers/hsi/clients/ssi_protocol.c
+++ b/drivers/hsi/clients/ssi_protocol.c
@@ -1057,7 +1057,7 @@ static void ssip_pn_setup(struct net_device *dev)
 {
 	static const u8 addr = PN_MEDIA_SOS;
 
-	dev->features		= 0;
+	dev->features		= netdev_empty_features;
 	dev->netdev_ops		= &ssip_pn_ops;
 	dev->type		= ARPHRD_PHONET;
 	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 688075859ae4..1fca20f97e8f 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -398,7 +398,7 @@ static void caifdev_setup(struct net_device *dev)
 {
 	struct ser_device *serdev = netdev_priv(dev);
 
-	dev->features = 0;
+	dev->features = netdev_empty_features;
 	dev->netdev_ops = &netdev_ops;
 	dev->type = ARPHRD_CAIF;
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index ab102769965f..f77a930367ce 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -4019,7 +4019,7 @@ static DECLARE_NETDEV_FEATURE_SET(ena_feature_set,
 static void ena_set_dev_offloads(struct ena_com_dev_get_features_ctx *feat,
 				 struct net_device *netdev)
 {
-	netdev_features_t dev_features = 0;
+	netdev_features_t dev_features = netdev_empty_features;
 
 	/* Set offload features */
 	if (feat->offload.tx &
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index e5857e88c207..075bdded8e45 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2359,7 +2359,7 @@ static int b44_init_one(struct ssb_device *sdev,
 	SET_NETDEV_DEV(dev, sdev->dev);
 
 	/* No interesting netdevice features in this card... */
-	dev->features |= 0;
+	dev->features |= netdev_empty_features;
 
 	bp = netdev_priv(dev);
 	bp->sdev = sdev;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 72a9b1f38cab..f4a455f8743b 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17550,13 +17550,13 @@ static void tg3_init_coal(struct tg3 *tp)
 static int tg3_init_one(struct pci_dev *pdev,
 				  const struct pci_device_id *ent)
 {
+	netdev_features_t features = netdev_empty_features;
 	struct net_device *dev;
 	struct tg3 *tp;
 	int i, err;
 	u32 sndmbx, rcvmbx, intmbx;
 	char str[40];
 	u64 dma_mask, persist_dma_mask;
-	netdev_features_t features = 0;
 	u8 addr[ETH_ALEN] __aligned(2);
 
 	err = pci_enable_device(pdev);
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index 92462ed87bc4..7f4dcea2cd87 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -763,7 +763,7 @@ static int dnet_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	/* TODO: Actually, we have some interesting features... */
-	dev->features |= 0;
+	dev->features |= netdev_empty_features;
 
 	bp = netdev_priv(dev);
 	bp->dev = dev;
diff --git a/drivers/net/ethernet/ec_bhf.c b/drivers/net/ethernet/ec_bhf.c
index 46e3a05e9582..44e90e06fdab 100644
--- a/drivers/net/ethernet/ec_bhf.c
+++ b/drivers/net/ethernet/ec_bhf.c
@@ -525,7 +525,7 @@ static int ec_bhf_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	pci_set_drvdata(dev, net_dev);
 	SET_NETDEV_DEV(net_dev, &dev->dev);
 
-	net_dev->features = 0;
+	net_dev->features = netdev_empty_features;
 	net_dev->flags |= IFF_NOARP;
 
 	net_dev->netdev_ops = &ec_bhf_netdev_ops;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 22af4232329e..fefacd5530e2 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -4029,7 +4029,7 @@ static int be_vxlan_unset_port(struct net_device *netdev, unsigned int table,
 	adapter->flags &= ~BE_FLAGS_VXLAN_OFFLOADS;
 	adapter->vxlan_port = 0;
 
-	netdev->hw_enc_features = 0;
+	netdev->hw_enc_features = netdev_empty_features;
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 437c5acfe222..3ced63aaa6cb 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -1220,7 +1220,7 @@ static int ethoc_probe(struct platform_device *pdev)
 	/* setup the net_device structure */
 	netdev->netdev_ops = &ethoc_netdev_ops;
 	netdev->watchdog_timeo = ETHOC_TIMEOUT;
-	netdev->features |= 0;
+	netdev->features |= netdev_empty_features;
 	netdev->ethtool_ops = &ethoc_ethtool_ops;
 
 	/* setup NAPI */
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 80d14a014d2d..93d4b019a4d1 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -1073,8 +1073,8 @@ static int set_features(struct hinic_dev *nic_dev,
 			netdev_features_t features, bool force_change)
 {
 	netdev_features_t changed = force_change ? ~0 : pre_features ^ features;
+	netdev_features_t failed_features = netdev_empty_features;
 	u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
-	netdev_features_t failed_features = 0;
 	int ret = 0;
 	int err = 0;
 
@@ -1295,7 +1295,8 @@ static int nic_dev_init(struct pci_dev *pdev)
 				HINIC_MGMT_MSG_CMD_LINK_ERR_EVENT,
 				nic_dev, link_err_event);
 
-	err = set_features(nic_dev, 0, nic_dev->netdev->features, true);
+	err = set_features(nic_dev, netdev_empty_features,
+			   nic_dev->netdev->features, true);
 	if (err)
 		goto err_set_features;
 
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 598f5b9d9025..0ceecd372b7e 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4840,8 +4840,8 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 {
 	struct ibmvnic_control_ip_offload_buffer *ctrl_buf = &adapter->ip_offload_ctrl;
 	struct ibmvnic_query_ip_offload_buffer *buf = &adapter->ip_offload_buf;
+	netdev_features_t old_hw_features = netdev_emtpy_features;
 	struct device *dev = &adapter->vdev->dev;
-	netdev_features_t old_hw_features = 0;
 	union ibmvnic_crq crq;
 
 	adapter->ip_offload_ctrl_tok =
@@ -4872,7 +4872,7 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 
 	if (adapter->state != VNIC_PROBING) {
 		old_hw_features = adapter->netdev->hw_features;
-		adapter->netdev->hw_features = 0;
+		adapter->netdev->hw_features = netdev_empty_features;
 	}
 
 	netdev_hw_features_zero(adapter->netdev);
@@ -4895,7 +4895,7 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 	if (adapter->state == VNIC_PROBING) {
 		adapter->netdev->features |= adapter->netdev->hw_features;
 	} else if (old_hw_features != adapter->netdev->hw_features) {
-		netdev_features_t tmp = 0;
+		netdev_features_t tmp = netdev_empty_features;
 
 		/* disable features no longer supported */
 		adapter->netdev->features &= adapter->netdev->hw_features;
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 95dd5a16b553..d4a2776381c3 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2595,7 +2595,8 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
 
 	if (VLAN_V2_ALLOWED(adapter))
 		/* request initial VLAN offload settings */
-		iavf_set_vlan_offload_features(adapter, 0, netdev->features);
+		iavf_set_vlan_offload_features(adapter, netdev_empty_features,
+					       netdev->features);
 
 	return;
 err_mem:
@@ -3151,7 +3152,7 @@ static void iavf_adminq_task(struct work_struct *work)
 			/* Request VLAN offload settings */
 			if (VLAN_V2_ALLOWED(adapter))
 				iavf_set_vlan_offload_features
-					(adapter, 0, netdev->features);
+					(adapter, netdev_empty_features, netdev->features);
 
 			iavf_set_queue_vlan_tag_loc(adapter);
 		}
@@ -4316,7 +4317,7 @@ static netdev_features_t iavf_features_check(struct sk_buff *skb,
 static netdev_features_t
 iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter)
 {
-	netdev_features_t hw_features = 0;
+	netdev_features_t hw_features = netdev_empty_features;
 
 	if (!adapter->vf_res || !adapter->vf_res->vf_cap_flags)
 		return hw_features;
@@ -4377,7 +4378,7 @@ iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter)
 static netdev_features_t
 iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 {
-	netdev_features_t features = 0;
+	netdev_features_t features = netdev_empty_features;
 
 	if (!adapter->vf_res || !adapter->vf_res->vf_cap_flags)
 		return features;
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index d2a424573d89..29bb41fdcdcd 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2093,7 +2093,7 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
 	netdev_hw_features_zero(ndev);
 	netdev_hw_features_set_array(ndev, &mana_hw_feature_set);
 	ndev->features = ndev->hw_features;
-	ndev->vlan_features = 0;
+	ndev->vlan_features = netdev_empty_features;
 
 	err = register_netdev(ndev);
 	if (err) {
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index dd8e278f8d8d..2f908bf1f019 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1310,7 +1310,7 @@ static 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 = netdev_empty_features;
 	int rc;
 
 	if (nic_data->must_check_datapath_caps) {
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 7d5446500d67..53865533d7a9 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -944,7 +944,7 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
 {
 	struct tap_dev *tap;
 	netdev_features_t features;
-	netdev_features_t feature_mask = 0;
+	netdev_features_t feature_mask = netdev_empty_features;
 
 	tap = rtnl_dereference(q->tap);
 	if (!tap)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 322956768815..661391e9399b 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -2865,7 +2865,7 @@ static void tun_get_iff(struct tun_struct *tun, struct ifreq *ifr)
  * privs required. */
 static int set_offload(struct tun_struct *tun, unsigned long arg)
 {
-	netdev_features_t features = 0;
+	netdev_features_t features = netdev_empty_features;
 
 	if (arg & TUN_F_CSUM) {
 		features |= NETIF_F_HW_CSUM;
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index ad5121e9cf5d..8c5116ed7278 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -14,6 +14,7 @@
 #include <linux/usb.h>
 #include <linux/usb/cdc.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_arp.h>
 #include <linux/if_phonet.h>
 #include <linux/phonet.h>
@@ -277,7 +278,7 @@ static void usbpn_setup(struct net_device *dev)
 {
 	const u8 addr = PN_MEDIA_USB;
 
-	dev->features		= 0;
+	dev->features		= netdev_empty_features;
 	dev->netdev_ops		= &usbpn_ops;
 	dev->header_ops		= &phonet_header_ops;
 	dev->type		= ARPHRD_PHONET;
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index b3c01bee9504..1c67cfb9bdb8 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -3462,7 +3462,7 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
 
 	INIT_WORK(&pdata->set_vlan, lan78xx_deferred_vlan_write);
 
-	dev->net->features = 0;
+	dev->net->features = netdev_empty_features;
 
 	if (DEFAULT_TX_CSUM_ENABLE)
 		dev->net->features |= NETIF_F_HW_CSUM;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 35d4b398c197..1ee35c5cb0bd 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6938,7 +6938,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 	/* Traffic with local next-hop is not eligible for some offloads: */
 	if (skb->ip_summed == CHECKSUM_PARTIAL &&
 	    READ_ONCE(card->options.isolation) != ISOLATION_MODE_FWD) {
-		netdev_features_t restricted = 0;
+		netdev_features_t restricted = netdev_empty_features;
 
 		if (skb_is_gso(skb) && !netif_needs_gso(skb, features))
 			restricted |= NETIF_F_ALL_TSO;
diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c
index 0bebbdf3f213..a540bf98441f 100644
--- a/drivers/usb/gadget/function/f_phonet.c
+++ b/drivers/usb/gadget/function/f_phonet.c
@@ -14,6 +14,7 @@
 #include <linux/device.h>
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_ether.h>
 #include <linux/if_phonet.h>
 #include <linux/if_arp.h>
@@ -269,7 +270,7 @@ static void pn_net_setup(struct net_device *dev)
 {
 	const u8 addr = PN_MEDIA_USB;
 
-	dev->features		= 0;
+	dev->features		= netdev_empty_features;
 	dev->type		= ARPHRD_PHONET;
 	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
 	dev->mtu		= PHONET_DEV_MTU;
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index da6e3b20cd75..3a017cecc6d3 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -137,7 +137,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	 */
 	dccp_set_state(sk, DCCP_CLOSED);
 	ip_rt_put(rt);
-	sk->sk_route_caps = 0;
+	sk->sk_route_caps = netdev_empty_features;
 	inet->inet_dport = 0;
 	goto out;
 }
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 53fa477d20ab..84fdb991bee5 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -971,7 +971,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	__sk_dst_reset(sk);
 failure:
 	inet->inet_dport = 0;
-	sk->sk_route_caps = 0;
+	sk->sk_route_caps = netdev_empty_features;
 	return err;
 }
 
diff --git a/net/ethtool/features.c b/net/ethtool/features.c
index 67a837d44491..38efdab960ba 100644
--- a/net/ethtool/features.c
+++ b/net/ethtool/features.c
@@ -144,7 +144,7 @@ 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 = netdev_empty_features;
 	unsigned int i;
 
 	for (i = 0; i < words; i++)
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 8f32e4f06bfb..7674629773a1 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_empty_features;
+	netdev_features_t valid = netdev_empty_features;
 	netdev_features_t tmp;
 	int i, ret = 0;
 
@@ -332,8 +333,9 @@ 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 features = netdev_empty_features;
 	netdev_features_t eth_all_features;
+	netdev_features_t changed;
 	netdev_features_t tmp;
 
 	if (data & ~ETH_ALL_FLAGS)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 3ca0cc467886..ad3bea716358 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1297,7 +1297,7 @@ int inet_sk_rebuild_header(struct sock *sk)
 		err = PTR_ERR(rt);
 
 		/* Routing failed... */
-		sk->sk_route_caps = 0;
+		sk->sk_route_caps = netdev_empty_features;
 		/*
 		 * Other protocols have to map its equivalent state to TCP_SYN_SENT.
 		 * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 970e9a2cca4a..df10a1e5027c 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1193,7 +1193,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 		if (err) {
 			tcp_set_state(sk, TCP_CLOSE);
 			inet->inet_dport = 0;
-			sk->sk_route_caps = 0;
+			sk->sk_route_caps = netdev_empty_features;
 		}
 	}
 	flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 0c83780dc9bf..0d1459b52fc9 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -324,7 +324,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	 */
 	tcp_set_state(sk, TCP_CLOSE);
 	ip_rt_put(rt);
-	sk->sk_route_caps = 0;
+	sk->sk_route_caps = netdev_empty_features;
 	inet->inet_dport = 0;
 	return err;
 }
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 2ce0c44d0081..eacac47c9fda 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -846,7 +846,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
 
 		dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
 		if (IS_ERR(dst)) {
-			sk->sk_route_caps = 0;
+			sk->sk_route_caps = netdev_empty_features;
 			sk->sk_err_soft = -PTR_ERR(dst);
 			return PTR_ERR(dst);
 		}
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 5a9f4d722f35..52209f42d18a 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -121,7 +121,7 @@ int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused
 	dst = inet6_csk_route_socket(sk, &fl6);
 	if (IS_ERR(dst)) {
 		sk->sk_err_soft = -PTR_ERR(dst);
-		sk->sk_route_caps = 0;
+		sk->sk_route_caps = netdev_empty_features;
 		kfree_skb(skb);
 		return PTR_ERR(dst);
 	}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index e54eee80ce5f..c60e1f714b79 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -342,7 +342,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	tcp_set_state(sk, TCP_CLOSE);
 failure:
 	inet->inet_dport = 0;
-	sk->sk_route_caps = 0;
+	sk->sk_route_caps = netdev_empty_features;
 	return err;
 }
 
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 0780c418a971..73571e1393fc 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -437,7 +437,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 
 	/* Complete checksum if needed */
 	if (skb->ip_summed == CHECKSUM_PARTIAL &&
-	    (err = skb_csum_hwoffload_help(skb, 0)))
+	    (err = skb_csum_hwoffload_help(skb, netdev_empty_features)))
 		goto out;
 
 	/* Older versions of OVS user space enforce alignment of the last
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 17/36] treewide: adjust features initialization
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (15 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 16/36] treewide: use replace features '0' by netdev_empty_features Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10 10:58   ` Alexander Lobakin
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 18/36] net: mlx4: adjust the net device feature relative macroes Jian Shen
                   ` (18 subsequent siblings)
  35 siblings, 1 reply; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

There are many direclty single bit assignment to netdev features.
Adjust these expressions, so can use netdev features helpers later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 arch/um/drivers/vector_kern.c                       | 5 ++++-
 drivers/firewire/net.c                              | 4 +++-
 drivers/infiniband/hw/hfi1/vnic_main.c              | 4 +++-
 drivers/misc/sgi-xp/xpnet.c                         | 3 ++-
 drivers/net/can/dev/dev.c                           | 4 +++-
 drivers/net/ethernet/alacritech/slicoss.c           | 4 +++-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c            | 4 +++-
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c     | 3 ++-
 drivers/net/ethernet/atheros/atlx/atl2.c            | 4 +++-
 drivers/net/ethernet/cadence/macb_main.c            | 4 +++-
 drivers/net/ethernet/davicom/dm9000.c               | 4 +++-
 drivers/net/ethernet/engleder/tsnep_main.c          | 4 +++-
 drivers/net/ethernet/ibm/ibmveth.c                  | 3 ++-
 drivers/net/ethernet/marvell/octeon_ep/octep_main.c | 4 +++-
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c      | 3 ++-
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c   | 4 +++-
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 7 +++++--
 drivers/net/ethernet/netronome/nfp/nfp_net_repr.c   | 3 ++-
 drivers/net/ethernet/ni/nixge.c                     | 4 +++-
 drivers/net/ethernet/renesas/sh_eth.c               | 6 ++++--
 drivers/net/ethernet/sun/sunhme.c                   | 7 +++++--
 drivers/net/ethernet/toshiba/ps3_gelic_net.c        | 6 ++++--
 drivers/net/ethernet/toshiba/spider_net.c           | 3 ++-
 drivers/net/ethernet/tundra/tsi108_eth.c            | 3 ++-
 drivers/net/ethernet/xilinx/ll_temac_main.c         | 4 +++-
 drivers/net/ethernet/xilinx/xilinx_axienet_main.c   | 4 +++-
 drivers/net/hamradio/bpqether.c                     | 4 +++-
 drivers/net/hyperv/netvsc_drv.c                     | 3 ++-
 drivers/net/ipa/ipa_modem.c                         | 4 +++-
 drivers/net/ntb_netdev.c                            | 4 +++-
 drivers/net/rionet.c                                | 4 +++-
 drivers/net/tap.c                                   | 2 +-
 drivers/net/thunderbolt.c                           | 3 ++-
 drivers/net/usb/smsc95xx.c                          | 4 +++-
 drivers/net/virtio_net.c                            | 4 +++-
 drivers/net/wireless/ath/ath10k/mac.c               | 7 +++++--
 drivers/net/wireless/ath/ath11k/mac.c               | 4 +++-
 drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c   | 4 +++-
 drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c   | 4 +++-
 drivers/net/wireless/mediatek/mt76/mt7615/init.c    | 4 +++-
 drivers/net/wireless/mediatek/mt76/mt7915/init.c    | 4 +++-
 drivers/net/wireless/mediatek/mt76/mt7921/init.c    | 4 +++-
 drivers/net/wwan/t7xx/t7xx_netdev.c                 | 4 +++-
 drivers/s390/net/qeth_core_main.c                   | 7 +++++--
 include/net/udp.h                                   | 4 +++-
 net/phonet/pep-gprs.c                               | 4 +++-
 46 files changed, 138 insertions(+), 52 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 1d59522a50d8..d797758850e1 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1628,7 +1628,10 @@ static void vector_eth_configure(
 		.bpf			= NULL
 	});
 
-	dev->features = dev->hw_features = (NETIF_F_SG | NETIF_F_FRAGLIST);
+	netdev_active_features_zero(dev);
+	dev->features |= NETIF_F_SG;
+	dev->features |= NETIF_F_FRAGLIST;
+	dev->features = dev->hw_features;
 	INIT_WORK(&vp->reset_tx, vector_reset_tx);
 
 	timer_setup(&vp->tl, vector_timer_expire, 0);
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index af22be84034b..e73c8793599b 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -24,6 +24,7 @@
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -1374,7 +1375,8 @@ static void fwnet_init_dev(struct net_device *net)
 	net->netdev_ops		= &fwnet_netdev_ops;
 	net->watchdog_timeo	= 2 * HZ;
 	net->flags		= IFF_BROADCAST | IFF_MULTICAST;
-	net->features		= NETIF_F_HIGHDMA;
+	netdev_active_features_zero(net);
+	net->features		|= NETIF_F_HIGHDMA;
 	net->addr_len		= FWNET_ALEN;
 	net->hard_header_len	= FWNET_HLEN;
 	net->type		= ARPHRD_IEEE1394;
diff --git a/drivers/infiniband/hw/hfi1/vnic_main.c b/drivers/infiniband/hw/hfi1/vnic_main.c
index 3650fababf25..52f805909ce3 100644
--- a/drivers/infiniband/hw/hfi1/vnic_main.c
+++ b/drivers/infiniband/hw/hfi1/vnic_main.c
@@ -588,7 +588,9 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device,
 	rn->free_rdma_netdev = hfi1_vnic_free_rn;
 	rn->set_id = hfi1_vnic_set_vesw_id;
 
-	netdev->features = NETIF_F_HIGHDMA | NETIF_F_SG;
+	netdev_active_features_zero(netdev);
+	netdev->features |= NETIF_F_HIGHDMA;
+	netdev->features |= NETIF_F_SG;
 	netdev->hw_features = netdev->features;
 	netdev->vlan_features = netdev->features;
 	netdev->watchdog_timeo = msecs_to_jiffies(HFI_TX_TIMEOUT_MS);
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 50644f83e78c..8547652c7b59 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -569,7 +569,8 @@ xpnet_init(void)
 	 * report an error if the data is not retrievable and the
 	 * packet will be dropped.
 	 */
-	xpnet_device->features = NETIF_F_HW_CSUM;
+	netdev_active_features_zero(xpnet_device);
+	xpnet_device->features |= NETIF_F_HW_CSUM;
 
 	result = register_netdev(xpnet_device);
 	if (result != 0) {
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index c1956b1e9faf..4243e65b2c68 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -7,6 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_arp.h>
 #include <linux/workqueue.h>
 #include <linux/can.h>
@@ -221,7 +222,8 @@ void can_setup(struct net_device *dev)
 
 	/* New-style flags. */
 	dev->flags = IFF_NOARP;
-	dev->features = NETIF_F_HW_CSUM;
+	netdev_active_features_zero(dev);
+	dev->features |= NETIF_F_HW_CSUM;
 }
 
 /* Allocate and setup space for the CAN network device */
diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c
index ce353b0c02a3..a52e3bc855e4 100644
--- a/drivers/net/ethernet/alacritech/slicoss.c
+++ b/drivers/net/ethernet/alacritech/slicoss.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
 #include <linux/crc32.h>
@@ -1778,7 +1779,8 @@ static int slic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	pci_set_drvdata(pdev, dev);
 	dev->irq = pdev->irq;
 	dev->netdev_ops = &slic_netdev_ops;
-	dev->hw_features = NETIF_F_RXCSUM;
+	netdev_hw_features_zero(dev);
+	dev->hw_features |= NETIF_F_RXCSUM;
 	dev->features |= dev->hw_features;
 
 	dev->ethtool_ops = &slic_ethtool_ops;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index ce0e2fa3eb63..eb0b205b49af 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -121,6 +121,7 @@
 #include <linux/interrupt.h>
 #include <linux/clk.h>
 #include <linux/if_ether.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <net/vxlan.h>
@@ -2183,7 +2184,8 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
 	netdev_features_t vxlan_base;
 
-	vxlan_base = NETIF_F_GSO_UDP_TUNNEL;
+	netdev_features_zero(&vxlan_base);
+	vxlan_base |= NETIF_F_GSO_UDP_TUNNEL;
 	vxlan_base |= NETIF_F_RX_UDP_TUNNEL_PORT;
 
 	if (!pdata->hw_feat.vxn)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index a8de1fb20a3f..e2fe6f2507d3 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -386,7 +386,8 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 	self->ndev->hw_features |= *aq_hw_caps->hw_features;
 	self->ndev->features = *aq_hw_caps->hw_features;
 	netdev_vlan_features_set_array(self->ndev, &aq_nic_vlan_feature_set);
-	self->ndev->gso_partial_features = NETIF_F_GSO_UDP_L4;
+	netdev_gso_partial_features_zero(self->ndev);
+	self->ndev->gso_partial_features |= NETIF_F_GSO_UDP_L4;
 	self->ndev->priv_flags = aq_hw_caps->hw_priv_flags;
 	self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 1d647c4d1d44..15df55325aae 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -22,6 +22,7 @@
 #include <linux/mii.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/pm.h>
@@ -1389,7 +1390,8 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (err)
 		goto err_sw_init;
 
-	netdev->hw_features = NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_features_zero(netdev);
+	netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
 	netdev->features |= netdev_ctag_vlan_offload_features;
 
 	/* Init PHY as early as possible due to power saving issue  */
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 4cac5e3a1929..1f84d3bc42c9 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -21,6 +21,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
@@ -4051,7 +4052,8 @@ static int macb_init(struct platform_device *pdev)
 	}
 
 	/* Set features */
-	dev->hw_features = NETIF_F_SG;
+	netdev_hw_features_zero(dev);
+	dev->hw_features |= NETIF_F_SG;
 
 	/* Check LSO capability */
 	if (GEM_BFEXT(PBUF_LSO, gem_readl(bp, DCFG6)))
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 363490713825..fec097064e52 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
 #include <linux/skbuff.h>
@@ -1644,7 +1645,8 @@ dm9000_probe(struct platform_device *pdev)
 
 	/* dm9000a/b are capable of hardware checksum offload */
 	if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) {
-		ndev->hw_features = NETIF_F_RXCSUM;
+		netdev_hw_features_zero(ndev);
+		ndev->hw_features |= NETIF_F_RXCSUM;
 		ndev->hw_features |= NETIF_F_IP_CSUM;
 		ndev->features |= ndev->hw_features;
 	}
diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index cb069a0af7b9..8e58b36a826d 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -24,6 +24,7 @@
 #include <linux/of_mdio.h>
 #include <linux/interrupt.h>
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/phy.h>
 #include <linux/iopoll.h>
 
@@ -1224,7 +1225,8 @@ static int tsnep_probe(struct platform_device *pdev)
 
 	netdev->netdev_ops = &tsnep_netdev_ops;
 	netdev->ethtool_ops = &tsnep_ethtool_ops;
-	netdev->features = NETIF_F_SG;
+	netdev_active_features_zero(netdev);
+	netdev->features |= NETIF_F_SG;
 	netdev->hw_features = netdev->features;
 
 	/* carrier off reporting is important to ethtool even BEFORE open */
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 3533ae7c92f7..c59bbbcd094e 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1684,7 +1684,8 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 	netdev->netdev_ops = &ibmveth_netdev_ops;
 	netdev->ethtool_ops = &netdev_ethtool_ops;
 	SET_NETDEV_DEV(netdev, &dev->dev);
-	netdev->hw_features = NETIF_F_SG;
+	netdev_hw_features_zero(netdev);
+	netdev->hw_features |= NETIF_F_SG;
 	if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL)
 		netdev_hw_features_set_array(netdev, &ibmveth_hw_feature_set);
 
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index 97f080c66dd4..42973668ca53 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -10,6 +10,7 @@
 #include <linux/pci.h>
 #include <linux/aer.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/vmalloc.h>
@@ -1064,7 +1065,8 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	octep_set_ethtool_ops(netdev);
 	netif_carrier_off(netdev);
 
-	netdev->hw_features = NETIF_F_SG;
+	netdev_hw_features_zero(netdev);
+	netdev->hw_features |= NETIF_F_SG;
 	netdev->features |= netdev->hw_features;
 	netdev->min_mtu = OCTEP_MIN_MTU;
 	netdev->max_mtu = OCTEP_MAX_MTU;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index c73fcb4a15f3..37abb1ed9bd4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3367,7 +3367,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	    MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
 		netdev_hw_features_set_array(dev, &mlx4_gso_feature_set);
 		netdev_active_features_set_array(dev, &mlx4_gso_feature_set);
-		dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_gso_partial_features_zero(dev);
+		dev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 		netdev_hw_enc_features_zero(dev);
 		netdev_hw_enc_features_set_array(dev, &mlx4_hw_enc_feature_set);
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 3c8d059c8484..e516a2805c0d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -37,6 +37,7 @@
 #include <linux/bpf.h>
 #include <linux/if_bridge.h>
 #include <linux/filter.h>
+#include <linux/netdev_features_helper.h>
 #include <net/page_pool.h>
 #include <net/xdp_sock_drv.h>
 #include "eswitch.h"
@@ -4925,7 +4926,8 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 		netdev->hw_features     |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
 		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
-		netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_gso_partial_features_zero(netdev);
+		netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 		netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL;
 		netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 	}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 29611221990f..e306b58b643c 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
 #include <linux/ip.h>
@@ -2351,7 +2352,8 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 	if (nn->cap & NFP_NET_CFG_CTRL_LIVE_ADDR)
 		netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
-	netdev->hw_features = NETIF_F_HIGHDMA;
+	netdev_hw_features_zero(netdev);
+	netdev->hw_features |= NETIF_F_HIGHDMA;
 	if (nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY) {
 		netdev->hw_features |= NETIF_F_RXCSUM;
 		nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY;
@@ -2378,7 +2380,8 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 			netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 			netdev->hw_features |= NETIF_F_GSO_PARTIAL;
 
-			netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
+			netdev_gso_partial_features_zero(netdev);
+			netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
 		}
 		netdev->udp_tunnel_nic_info = &nfp_udp_tunnels;
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_VXLAN;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 48da1da1c704..66f0a9de53ad 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -345,7 +345,8 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 	if (repr_cap & NFP_NET_CFG_CTRL_LIVE_ADDR)
 		netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
-	netdev->hw_features = NETIF_F_HIGHDMA;
+	netdev_hw_features_zero(netdev);
+	netdev->hw_features |= NETIF_F_HIGHDMA;
 	if (repr_cap & NFP_NET_CFG_CTRL_RXCSUM_ANY)
 		netdev->hw_features |= NETIF_F_RXCSUM;
 	if (repr_cap & NFP_NET_CFG_CTRL_TXCSUM)
diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c
index 4b3482ce90a1..f70feffbf2ba 100644
--- a/drivers/net/ethernet/ni/nixge.c
+++ b/drivers/net/ethernet/ni/nixge.c
@@ -7,6 +7,7 @@
 #include <linux/etherdevice.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of_address.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
@@ -1274,7 +1275,8 @@ static int nixge_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, ndev);
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
-	ndev->features = NETIF_F_SG;
+	netdev_active_features_zero(ndev);
+	ndev->features |= NETIF_F_SG;
 	ndev->netdev_ops = &nixge_netdev_ops;
 	ndev->ethtool_ops = &nixge_ethtool_ops;
 
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 67ade78fb767..d42adef5a143 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/mdio-bitbang.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
@@ -3291,8 +3292,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 	ndev->min_mtu = ETH_MIN_MTU;
 
 	if (mdp->cd->rx_csum) {
-		ndev->features = NETIF_F_RXCSUM;
-		ndev->hw_features = NETIF_F_RXCSUM;
+		netdev_active_features_zero(ndev);
+		ndev->features |= NETIF_F_RXCSUM;
+		ndev->hw_features = ndev->features;
 	}
 
 	/* set function */
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index f8868f79ee95..f9fcca2adcf4 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -31,6 +31,7 @@
 #include <linux/random.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/mm.h>
@@ -2784,7 +2785,8 @@ static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
 	dev->ethtool_ops = &hme_ethtool_ops;
 
 	/* Happy Meal can do it all... */
-	dev->hw_features = NETIF_F_SG;
+	netdev_hw_features_zero(dev);
+	dev->hw_features |= NETIF_F_SG;
 	dev->hw_features |= NETIF_F_HW_CSUM;
 	dev->features |= dev->hw_features;
 	dev->features |= NETIF_F_RXCSUM;
@@ -3106,7 +3108,8 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
 	dev->ethtool_ops = &hme_ethtool_ops;
 
 	/* Happy Meal can do it all... */
-	dev->hw_features = NETIF_F_SG;
+	netdev_hw_features_zero(dev);
+	dev->hw_features |= NETIF_F_SG;
 	dev->hw_features |= NETIF_F_HW_CSUM;
 	dev->features |= dev->hw_features;
 	dev->features |= NETIF_F_RXCSUM;
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 5def0b3bf8ef..45c0cb3c9a48 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -1461,10 +1461,12 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
 	int status;
 	u64 v1, v2;
 
-	netdev->hw_features = NETIF_F_IP_CSUM;
+	netdev_hw_features_zero(netdev);
+	netdev->hw_features |= NETIF_F_IP_CSUM;
 	netdev->hw_features |= NETIF_F_RXCSUM;
 
-	netdev->features = NETIF_F_IP_CSUM;
+	netdev_active_features_zero(netdev);
+	netdev->features |= NETIF_F_IP_CSUM;
 	if (GELIC_CARD_RX_CSUM_DEFAULT)
 		netdev->features |= NETIF_F_RXCSUM;
 
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index e2e0e18fcdc8..03dc5fb10a2b 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -2275,7 +2275,8 @@ spider_net_setup_netdev(struct spider_net_card *card)
 
 	spider_net_setup_netdev_ops(netdev);
 
-	netdev->hw_features = NETIF_F_RXCSUM;
+	netdev_hw_features_zero(netdev);
+	netdev->hw_features |= NETIF_F_RXCSUM;
 	netdev->hw_features |= NETIF_F_IP_CSUM;
 	if (SPIDER_NET_RX_CSUM_DEFAULT)
 		netdev->features |= NETIF_F_RXCSUM;
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index 5251fc324221..785f4f3bd0ee 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1610,7 +1610,8 @@ tsi108_init_one(struct platform_device *pdev)
 	 * a new function skb_csum_dev() in net/core/skbuff.c).
 	 */
 
-	dev->features = NETIF_F_HIGHDMA;
+	netdev_active_features_zero(dev);
+	dev->features |= NETIF_F_HIGHDMA;
 
 	spin_lock_init(&data->txlock);
 	spin_lock_init(&data->misclock);
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 3f6b9dfca095..e3299bb3a1e6 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -33,6 +33,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_ether.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -1395,7 +1396,8 @@ static int temac_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ndev);
 	SET_NETDEV_DEV(ndev, &pdev->dev);
-	ndev->features = NETIF_F_SG;
+	netdev_active_features_zero(ndev);
+	ndev->features |= NETIF_F_SG;
 	ndev->netdev_ops = &temac_netdev_ops;
 	ndev->ethtool_ops = &temac_ethtool_ops;
 #if 0
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 1760930ec0c4..cac3437991ae 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -27,6 +27,7 @@
 #include <linux/etherdevice.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/of_platform.h>
@@ -1835,7 +1836,8 @@ static int axienet_probe(struct platform_device *pdev)
 
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 	ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
-	ndev->features = NETIF_F_SG;
+	netdev_active_features_zero(ndev);
+	ndev->features |= NETIF_F_SG;
 	ndev->netdev_ops = &axienet_netdev_ops;
 	ndev->ethtool_ops = &axienet_ethtool_ops;
 
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 30af0081e2be..3b5d82b09675 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -60,6 +60,7 @@
 #include <net/ax25.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
@@ -458,7 +459,8 @@ static void bpq_setup(struct net_device *dev)
 	dev->needs_free_netdev = true;
 
 	dev->flags      = 0;
-	dev->features	= NETIF_F_LLTX;	/* Allow recursion */
+	netdev_active_features_zero(dev);
+	dev->features	|= NETIF_F_LLTX;	/* Allow recursion */
 
 #if IS_ENABLED(CONFIG_AX25)
 	dev->header_ops      = &ax25_header_ops;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 6bf8d63132a1..b83a966b73db 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1163,7 +1163,8 @@ static void netvsc_init_settings(struct net_device *dev)
 	ndc->speed = SPEED_UNKNOWN;
 	ndc->duplex = DUPLEX_FULL;
 
-	dev->features = NETIF_F_LRO;
+	netdev_active_features_zero(dev);
+	dev->features |= NETIF_F_LRO;
 }
 
 static int netvsc_get_link_ksettings(struct net_device *dev,
diff --git a/drivers/net/ipa/ipa_modem.c b/drivers/net/ipa/ipa_modem.c
index c8b1c4d9c507..b7d16d16d523 100644
--- a/drivers/net/ipa/ipa_modem.c
+++ b/drivers/net/ipa/ipa_modem.c
@@ -7,6 +7,7 @@
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <linux/if_rmnet.h>
 #include <linux/etherdevice.h>
@@ -223,7 +224,8 @@ static void ipa_modem_netdev_setup(struct net_device *netdev)
 	netdev->needed_headroom = sizeof(struct rmnet_map_header);
 	netdev->needed_tailroom = IPA_NETDEV_TAILROOM;
 	netdev->watchdog_timeo = IPA_NETDEV_TIMEOUT * HZ;
-	netdev->hw_features = NETIF_F_SG;
+	netdev_hw_features_zero(netdev);
+	netdev->hw_features |= NETIF_F_SG;
 }
 
 /** ipa_modem_suspend() - suspend callback
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index 80bdc07f2cd3..2075e0b9f175 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -50,6 +50,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/ntb.h>
 #include <linux/ntb_transport.h>
@@ -420,7 +421,8 @@ static int ntb_netdev_probe(struct device *client_dev)
 	dev = netdev_priv(ndev);
 	dev->ndev = ndev;
 	dev->pdev = pdev;
-	ndev->features = NETIF_F_HIGHDMA;
+	netdev_active_features_zero(ndev);
+	ndev->features |= NETIF_F_HIGHDMA;
 
 	ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 39e61e07e489..9f0175b73fd7 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -16,6 +16,7 @@
 #include <linux/rio_ids.h>
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/crc32.h>
@@ -515,7 +516,8 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
 	/* MTU range: 68 - 4082 */
 	ndev->min_mtu = ETH_MIN_MTU;
 	ndev->max_mtu = RIONET_MAX_MTU;
-	ndev->features = NETIF_F_LLTX;
+	netdev_active_features_zero(ndev);
+	ndev->features |= NETIF_F_LLTX;
 	SET_NETDEV_DEV(ndev, &mport->dev);
 	ndev->ethtool_ops = &rionet_ethtool_ops;
 
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 53865533d7a9..496de424121e 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -953,7 +953,7 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
 	features = tap->dev->features;
 
 	if (arg & TUN_F_CSUM) {
-		feature_mask = NETIF_F_HW_CSUM;
+		feature_mask |= NETIF_F_HW_CSUM;
 
 		if (arg & (TUN_F_TSO4 | TUN_F_TSO6)) {
 			if (arg & TUN_F_TSO_ECN)
diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c
index baed53386606..5fad8f09d69f 100644
--- a/drivers/net/thunderbolt.c
+++ b/drivers/net/thunderbolt.c
@@ -1268,7 +1268,8 @@ static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id)
 	 */
 	dev->hw_features = NETIF_F_ALL_TSO;
 	netdev_hw_features_set_array(dev, &tbnet_hw_feature_set);
-	dev->features = dev->hw_features | NETIF_F_HIGHDMA;
+	dev->features = dev->hw_features;
+	dev->features |= NETIF_F_HIGHDMA;
 	dev->hard_header_len += sizeof(struct thunderbolt_ip_frame_header);
 
 	netif_napi_add(dev, &net->napi, tbnet_poll, NAPI_POLL_WEIGHT);
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 10cf0a68980e..d7c8b9d6ba29 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/kmod.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -1085,7 +1086,8 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 	if (DEFAULT_RX_CSUM_ENABLE)
 		dev->net->features |= NETIF_F_RXCSUM;
 
-	dev->net->hw_features = NETIF_F_IP_CSUM;
+	netdev_hw_features_zero(dev->net);
+	dev->net->hw_features |= NETIF_F_IP_CSUM;
 	dev->net->hw_features |= NETIF_F_RXCSUM;
 	set_bit(EVENT_NO_IP_ALIGN, &dev->flags);
 
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 3d8f4da73bd7..4fb30d9534f4 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -5,6 +5,7 @@
  */
 //#define DEBUG
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/module.h>
@@ -3502,7 +3503,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 	dev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE |
 			   IFF_TX_SKB_NO_LINEAR;
 	dev->netdev_ops = &virtnet_netdev;
-	dev->features = NETIF_F_HIGHDMA;
+	netdev_active_features_zero(dev);
+	dev->features |= NETIF_F_HIGHDMA;
 
 	dev->ethtool_ops = &virtnet_ethtool_ops;
 	SET_NETDEV_DEV(dev, &vdev->dev);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 9dd3b8fba4b0..4d9cd3df3095 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -13,6 +13,7 @@
 #include <linux/acpi.h>
 #include <linux/of.h>
 #include <linux/bitfield.h>
+#include <linux/netdev_features_helper.h>
 
 #include "hif.h"
 #include "core.h"
@@ -10210,8 +10211,10 @@ int ath10k_mac_register(struct ath10k *ar)
 	if (ar->hw_params.dynamic_sar_support)
 		ar->hw->wiphy->sar_capa = &ath10k_sar_capa;
 
-	if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
-		ar->hw->netdev_features = NETIF_F_HW_CSUM;
+	if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+		netdev_features_zero(&ar->hw->netdev_features);
+		ar->hw->netdev_features |= NETIF_F_HW_CSUM;
+	}
 
 	if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
 		/* Init ath dfs pattern detector */
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 7e91e347c9ff..2b78b47e0a90 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -8,6 +8,7 @@
 #include <linux/etherdevice.h>
 #include <linux/bitfield.h>
 #include <linux/inetdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <net/if_inet6.h>
 #include <net/ipv6.h>
 
@@ -8895,7 +8896,8 @@ static int __ath11k_mac_register(struct ath11k *ar)
 	ath11k_reg_init(ar);
 
 	if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
-		ar->hw->netdev_features = NETIF_F_HW_CSUM;
+		netdev_features_zero(&ar->hw->netdev_features);
+		ar->hw->netdev_features |= NETIF_F_HW_CSUM;
 		ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
 		ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
 	}
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
index 5f0bba0cfdf6..53c41f48ecf8 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 
@@ -97,7 +98,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
 	ieee80211_hw_set(hw, WANT_MONITOR_VIF);
 
 	if (priv->trans->max_skb_frags) {
-		hw->netdev_features = NETIF_F_HIGHDMA;
+		netdev_features_zero(&hw->netdev_features);
+		hw->netdev_features |= NETIF_F_HIGHDMA;
 		hw->netdev_features |= NETIF_F_SG;
 	}
 
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 5fbeb262a90b..1c6bb3317a30 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -8,6 +8,7 @@
 #include <linux/slab.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ip.h>
 #include <linux/if_arp.h>
@@ -319,7 +320,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 		ieee80211_hw_set(hw, USES_RSS);
 
 	if (mvm->trans->max_skb_frags) {
-		hw->netdev_features = NETIF_F_HIGHDMA;
+		netdev_features_zero(&hw->netdev_features);
+		hw->netdev_features |= NETIF_F_HIGHDMA;
 		hw->netdev_features |= NETIF_F_SG;
 	}
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 07a1fea94f66..bc2e309d45ed 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -10,6 +10,7 @@
 #include <linux/etherdevice.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/netdev_features_helper.h>
 #include "mt7615.h"
 #include "mac.h"
 #include "mcu.h"
@@ -366,7 +367,8 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
 	hw->max_rates = 3;
 	hw->max_report_rates = 7;
 	hw->max_rate_tries = 11;
-	hw->netdev_features = NETIF_F_RXCSUM;
+	netdev_features_zero(&hw->netdev_features);
+	hw->netdev_features |= NETIF_F_RXCSUM;
 
 	hw->radiotap_timestamp.units_pos =
 		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index cc2aac86bcfb..bc35271f41da 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -4,6 +4,7 @@
 #include <linux/etherdevice.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/thermal.h>
 #include "mt7915.h"
 #include "mac.h"
@@ -329,7 +330,8 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
 	hw->queues = 4;
 	hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
 	hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
-	hw->netdev_features = NETIF_F_RXCSUM;
+	netdev_features_zero(&hw->netdev_features);
+	hw->netdev_features |= NETIF_F_RXCSUM;
 
 	hw->radiotap_timestamp.units_pos =
 		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index cd960e23770f..7824ee8e29cc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -2,6 +2,7 @@
 /* Copyright (C) 2020 MediaTek Inc. */
 
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include "mt7921.h"
 #include "mac.h"
 #include "mcu.h"
@@ -54,7 +55,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
 	hw->queues = 4;
 	hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
 	hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
-	hw->netdev_features = NETIF_F_RXCSUM;
+	netdev_features_zero(&hw->netdev_features);
+	hw->netdev_features |= NETIF_F_RXCSUM;
 
 	hw->radiotap_timestamp.units_pos =
 		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
diff --git a/drivers/net/wwan/t7xx/t7xx_netdev.c b/drivers/net/wwan/t7xx/t7xx_netdev.c
index c6b6547f2c6f..52a77a224a64 100644
--- a/drivers/net/wwan/t7xx/t7xx_netdev.c
+++ b/drivers/net/wwan/t7xx/t7xx_netdev.c
@@ -25,6 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/netdev_features.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
@@ -172,7 +173,8 @@ static void t7xx_ccmni_wwan_setup(struct net_device *dev)
 
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
 
-	dev->features = NETIF_F_VLAN_CHALLENGED;
+	netdev_active_features_zero(dev);
+	dev->features |= NETIF_F_VLAN_CHALLENGED;
 
 	dev->features |= NETIF_F_SG;
 	dev->hw_features |= NETIF_F_SG;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 1ee35c5cb0bd..1a903161c46c 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6839,8 +6839,11 @@ static void qeth_check_restricted_features(struct qeth_card *card,
 					   netdev_features_t changed,
 					   netdev_features_t actual)
 {
-	netdev_features_t ipv6_features = NETIF_F_TSO6;
-	netdev_features_t ipv4_features = NETIF_F_TSO;
+	netdev_features_t ipv6_features = netdev_empty_features;
+	netdev_features_t ipv4_features = netdev_empty_features;
+
+	ipv6_features |= NETIF_F_TSO6;
+	ipv4_features |= NETIF_F_TSO;
 
 	if (!card->info.has_lp2lp_cso_v6)
 		ipv6_features |= NETIF_F_IPV6_CSUM;
diff --git a/include/net/udp.h b/include/net/udp.h
index 13887234a241..46d7527cae38 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -457,9 +457,11 @@ void udpv6_encap_enable(void);
 static inline struct sk_buff *udp_rcv_segment(struct sock *sk,
 					      struct sk_buff *skb, bool ipv4)
 {
-	netdev_features_t features = NETIF_F_SG;
+	netdev_features_t features = netdev_empty_features;
 	struct sk_buff *segs;
 
+	features |= NETIF_F_SG;
+
 	/* Avoid csum recalculation by skb_segment unless userspace explicitly
 	 * asks for the final checksum values
 	 */
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index 1f5df0432d37..0b09b1ba0c05 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -11,6 +11,7 @@
 
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/if_ether.h>
 #include <linux/if_arp.h>
 #include <net/sock.h>
@@ -212,7 +213,8 @@ static const struct net_device_ops gprs_netdev_ops = {
 
 static void gprs_setup(struct net_device *dev)
 {
-	dev->features		= NETIF_F_FRAGLIST;
+	netdev_active_features_zero(dev);
+	dev->features		|= NETIF_F_FRAGLIST;
 	dev->type		= ARPHRD_PHONET_PIPE;
 	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
 	dev->mtu		= GPRS_DEFAULT_MTU;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 18/36] net: mlx4: adjust the net device feature relative macroes
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (16 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 17/36] treewide: adjust features initialization Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 19/36] net: mlx5e: adjust " Jian Shen
                   ` (17 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The macro DEV_FEATURE_CHANGED use NETIF_F_XXX as parameter,
change it to use NETIF_F_XXX_BIT instead, for all the macroes
NETIF_F_XXX will be removed.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 .../net/ethernet/mellanox/mlx4/en_netdev.c    | 22 +++++++++----------
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h  |  5 +++--
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 37abb1ed9bd4..5791f48367ef 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2522,13 +2522,13 @@ static int mlx4_en_set_features(struct net_device *netdev,
 	bool reset = false;
 	int ret = 0;
 
-	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_RXFCS)) {
+	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_RXFCS_BIT)) {
 		en_info(priv, "Turn %s RX-FCS\n",
 			(features & NETIF_F_RXFCS) ? "ON" : "OFF");
 		reset = true;
 	}
 
-	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_RXALL)) {
+	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_RXALL_BIT)) {
 		u8 ignore_fcs_value = (features & NETIF_F_RXALL) ? 1 : 0;
 
 		en_info(priv, "Turn %s RX-ALL\n",
@@ -2539,21 +2539,21 @@ static int mlx4_en_set_features(struct net_device *netdev,
 			return ret;
 	}
 
-	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_CTAG_RX)) {
+	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
 		en_info(priv, "Turn %s RX vlan strip offload\n",
 			(features & NETIF_F_HW_VLAN_CTAG_RX) ? "ON" : "OFF");
 		reset = true;
 	}
 
-	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_CTAG_TX))
+	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_CTAG_TX_BIT))
 		en_info(priv, "Turn %s TX vlan strip offload\n",
 			(features & NETIF_F_HW_VLAN_CTAG_TX) ? "ON" : "OFF");
 
-	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_STAG_TX))
+	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_STAG_TX_BIT))
 		en_info(priv, "Turn %s TX S-VLAN strip offload\n",
 			(features & NETIF_F_HW_VLAN_STAG_TX) ? "ON" : "OFF");
 
-	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_LOOPBACK)) {
+	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_LOOPBACK_BIT)) {
 		en_info(priv, "Turn %s loopback\n",
 			(features & NETIF_F_LOOPBACK) ? "ON" : "OFF");
 		mlx4_en_update_loopback_state(netdev, features);
@@ -3526,11 +3526,11 @@ int mlx4_en_reset_config(struct net_device *dev,
 
 	if (priv->hwtstamp_config.tx_type == ts_config.tx_type &&
 	    priv->hwtstamp_config.rx_filter == ts_config.rx_filter &&
-	    !DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX) &&
-	    !DEV_FEATURE_CHANGED(dev, features, NETIF_F_RXFCS))
+	    !DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
+	    !DEV_FEATURE_CHANGED(dev, features, NETIF_F_RXFCS_BIT))
 		return 0; /* Nothing to change */
 
-	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	    (features & NETIF_F_HW_VLAN_CTAG_RX) &&
 	    (priv->hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE)) {
 		en_warn(priv, "Can't turn ON rx vlan offload while time-stamping rx filter is ON\n");
@@ -3557,7 +3557,7 @@ int mlx4_en_reset_config(struct net_device *dev,
 
 	mlx4_en_safe_replace_resources(priv, tmp);
 
-	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX)) {
+	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
 		if (features & NETIF_F_HW_VLAN_CTAG_RX)
 			dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
 		else
@@ -3572,7 +3572,7 @@ int mlx4_en_reset_config(struct net_device *dev,
 			dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 	}
 
-	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_RXFCS)) {
+	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_RXFCS_BIT)) {
 		if (features & NETIF_F_RXFCS)
 			dev->features |= NETIF_F_RXFCS;
 		else
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index e132ff4c82f2..29b0ac52c6a9 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -774,8 +774,9 @@ void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv);
 void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
 void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev);
 
-#define DEV_FEATURE_CHANGED(dev, new_features, feature) \
-	((dev->features & feature) ^ (new_features & feature))
+#define DEV_FEATURE_CHANGED(dev, new_features, feature_bit) \
+	(netdev_active_feature_test(dev, feature_bit) != \
+	 netdev_feature_test(feature_bit, new_features))
 
 int mlx4_en_moderation_update(struct mlx4_en_priv *priv);
 int mlx4_en_reset_config(struct net_device *dev,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 19/36] net: mlx5e: adjust net device feature relative macroes
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (17 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 18/36] net: mlx4: adjust the net device feature relative macroes Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 20/36] net: mlxsw: adjust input parameter for function mlxsw_sp_handle_feature Jian Shen
                   ` (16 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The macroes MLX5E_SET_FEATURE and MLX5E_HANDLE_FEATURE use
NETIF_F_XXX as parameter directly, change it to NETIF_F_XXX_BIT,
for all the NETIF_F_XXX macroes will be removed later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 40 ++++++++++---------
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index e516a2805c0d..f702ba4da89a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3593,9 +3593,9 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
 #define MLX5E_SET_FEATURE(features, feature, enable)	\
 	do {						\
 		if (enable)				\
-			*features |= feature;		\
+			netdev_feature_add(feature, features);	\
 		else					\
-			*features &= ~feature;		\
+			netdev_feature_del(feature, features);	\
 	} while (0)
 
 typedef int (*mlx5e_feature_handler)(struct net_device *netdev, bool enable);
@@ -3835,21 +3835,21 @@ static int set_feature_arfs(struct net_device *netdev, bool enable)
 
 static int mlx5e_handle_feature(struct net_device *netdev,
 				netdev_features_t *features,
-				netdev_features_t feature,
+				unsigned short feature_bit,
 				mlx5e_feature_handler feature_handler)
 {
 	netdev_features_t changes = *features ^ netdev->features;
-	bool enable = !!(*features & feature);
+	bool enable = netdev_feature_test(feature_bit, *features);
 	int err;
 
-	if (!(changes & feature))
+	if (!netdev_feature_test(feature_bit, changes))
 		return 0;
 
 	err = feature_handler(netdev, enable);
 	if (err) {
-		MLX5E_SET_FEATURE(features, feature, !enable);
-		netdev_err(netdev, "%s feature %pNF failed, err %d\n",
-			   enable ? "Enable" : "Disable", &feature, err);
+		MLX5E_SET_FEATURE(features, feature_bit, !enable);
+		netdev_err(netdev, "%s feature bit %u failed, err %d\n",
+			   enable ? "Enable" : "Disable", feature_bit, err);
 		return err;
 	}
 
@@ -3861,21 +3861,23 @@ int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
 	netdev_features_t oper_features = features;
 	int err = 0;
 
-#define MLX5E_HANDLE_FEATURE(feature, handler) \
-	mlx5e_handle_feature(netdev, &oper_features, feature, handler)
+#define MLX5E_HANDLE_FEATURE(feature_bit, handler) \
+	mlx5e_handle_feature(netdev, &oper_features, feature_bit, handler)
 
-	err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro);
-	err |= MLX5E_HANDLE_FEATURE(NETIF_F_GRO_HW, set_feature_hw_gro);
-	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER,
+	err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO_BIT, set_feature_lro);
+	err |= MLX5E_HANDLE_FEATURE(NETIF_F_GRO_HW_BIT, set_feature_hw_gro);
+	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				    set_feature_cvlan_filter);
-	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_TC, set_feature_hw_tc);
-	err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXALL, set_feature_rx_all);
-	err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXFCS, set_feature_rx_fcs);
-	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_RX, set_feature_rx_vlan);
+	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_TC_BIT, set_feature_hw_tc);
+	err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXALL_BIT, set_feature_rx_all);
+	err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXFCS_BIT, set_feature_rx_fcs);
+	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				    set_feature_rx_vlan);
 #ifdef CONFIG_MLX5_EN_ARFS
-	err |= MLX5E_HANDLE_FEATURE(NETIF_F_NTUPLE, set_feature_arfs);
+	err |= MLX5E_HANDLE_FEATURE(NETIF_F_NTUPLE_BIT, set_feature_arfs);
 #endif
-	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_TLS_RX, mlx5e_ktls_set_feature_rx);
+	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_TLS_RX_BIT,
+				    mlx5e_ktls_set_feature_rx);
 
 	if (err) {
 		netdev->features = oper_features;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 20/36] net: mlxsw: adjust input parameter for function mlxsw_sp_handle_feature
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (18 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 19/36] net: mlx5e: adjust " Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 21/36] net: iavf: adjust net device features relative macroes Jian Shen
                   ` (15 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function mlxsw_sp_handle_feature() use NETIF_F_XXX as input
parameter directly, change it to use NETIF_F_XXX_BIT, for all
the NETIF_F_XXX macroes will be removed later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index a38ed21cfbdf..19fbde6bd1a8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1217,27 +1217,27 @@ typedef int (*mlxsw_sp_feature_handler)(struct net_device *dev, bool enable);
 
 static int mlxsw_sp_handle_feature(struct net_device *dev,
 				   netdev_features_t wanted_features,
-				   netdev_features_t feature,
+				   int feature_bit,
 				   mlxsw_sp_feature_handler feature_handler)
 {
 	netdev_features_t changes = wanted_features ^ dev->features;
-	bool enable = !!(wanted_features & feature);
+	bool enable = netdev_feature_test(feature_bit, wanted_features);
 	int err;
 
-	if (!(changes & feature))
+	if (!netdev_feature_test(feature_bit, changes))
 		return 0;
 
 	err = feature_handler(dev, enable);
 	if (err) {
-		netdev_err(dev, "%s feature %pNF failed, err %d\n",
-			   enable ? "Enable" : "Disable", &feature, err);
+		netdev_err(dev, "%s feature bit %d failed, err %d\n",
+			   enable ? "Enable" : "Disable", feature_bit, err);
 		return err;
 	}
 
 	if (enable)
-		dev->features |= feature;
+		netdev_active_feature_add(dev, feature_bit);
 	else
-		dev->features &= ~feature;
+		netdev_active_feature_del(dev, feature_bit);
 
 	return 0;
 }
@@ -1247,9 +1247,9 @@ static int mlxsw_sp_set_features(struct net_device *dev,
 	netdev_features_t oper_features = dev->features;
 	int err = 0;
 
-	err |= mlxsw_sp_handle_feature(dev, features, NETIF_F_HW_TC,
+	err |= mlxsw_sp_handle_feature(dev, features, NETIF_F_HW_TC_BIT,
 				       mlxsw_sp_feature_hw_tc);
-	err |= mlxsw_sp_handle_feature(dev, features, NETIF_F_LOOPBACK,
+	err |= mlxsw_sp_handle_feature(dev, features, NETIF_F_LOOPBACK_BIT,
 				       mlxsw_sp_feature_loopback);
 
 	if (err) {
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 21/36] net: iavf: adjust net device features relative macroes
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (19 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 20/36] net: mlxsw: adjust input parameter for function mlxsw_sp_handle_feature Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 22/36] net: core: adjust netdev_sync_xxx_features Jian Shen
                   ` (14 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The macro IAVF_NETDEV_VLAN_FEATURE_ALLOWED use NETIF_F_XXX as
parameter directly, change it to use NETIF_F_XXX_BIT, for all
the macroes NETIF_F_XXX will be removed later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/intel/iavf/iavf_main.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index d4a2776381c3..1f9884539807 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4467,8 +4467,8 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 }
 
 #define IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested, allowed, feature_bit) \
-	(!(((requested) & (feature_bit)) && \
-	   !((allowed) & (feature_bit))))
+	(!(netdev_feature_test(feature_bit, requested) && \
+	   !netdev_feature_test(feature_bit, allowed)))
 
 /**
  * iavf_fix_netdev_vlan_features - fix NETDEV VLAN features based on support
@@ -4486,31 +4486,31 @@ iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
-					      NETIF_F_HW_VLAN_CTAG_TX))
+					      NETIF_F_HW_VLAN_CTAG_TX_BIT))
 		requested_features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
-					      NETIF_F_HW_VLAN_CTAG_RX))
+					      NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		requested_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
-					      NETIF_F_HW_VLAN_STAG_TX))
+					      NETIF_F_HW_VLAN_STAG_TX_BIT))
 		requested_features &= ~NETIF_F_HW_VLAN_STAG_TX;
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
-					      NETIF_F_HW_VLAN_STAG_RX))
+					      NETIF_F_HW_VLAN_STAG_RX_BIT))
 		requested_features &= ~NETIF_F_HW_VLAN_STAG_RX;
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
-					      NETIF_F_HW_VLAN_CTAG_FILTER))
+					      NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		requested_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
-					      NETIF_F_HW_VLAN_STAG_FILTER))
+					      NETIF_F_HW_VLAN_STAG_FILTER_BIT))
 		requested_features &= ~NETIF_F_HW_VLAN_STAG_FILTER;
 
 	if ((requested_features & netdev_ctag_vlan_offload_features) &&
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 22/36] net: core: adjust netdev_sync_xxx_features
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (20 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 21/36] net: iavf: adjust net device features relative macroes Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 23/36] net: adjust the build check for net_gso_ok() Jian Shen
                   ` (13 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The functions netdev_sync_upper_features() and
netdev_sync_lower_features() use NETIF_F_XXX as input parameter
directly, change them to use NETIF_F_XXX_BIT, for all macroes
NETIF_F_XXX will be removed later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 net/core/dev.c | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 2a0f31c66dea..74b6315449a7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9564,16 +9564,14 @@ 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 feature;
 	int feature_bit;
 
 	for_each_netdev_feature(upper_disables, feature_bit) {
-		feature = __NETIF_F_BIT(feature_bit);
-		if (!(upper->wanted_features & feature)
-		    && (features & feature)) {
-			netdev_dbg(lower, "Dropping feature %pNF, upper dev %s has it off.\n",
-				   &feature, upper->name);
-			features &= ~feature;
+		if (!netdev_wanted_feature_test(upper, feature_bit) &&
+		    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);
 		}
 	}
 
@@ -9584,20 +9582,19 @@ 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 feature;
 	int feature_bit;
 
 	for_each_netdev_feature(upper_disables, feature_bit) {
-		feature = __NETIF_F_BIT(feature_bit);
-		if (!(features & feature) && (lower->features & feature)) {
-			netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n",
-				   &feature, lower->name);
-			lower->wanted_features &= ~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(lower->features & 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);
 		}
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 23/36] net: adjust the build check for net_gso_ok()
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (21 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 22/36] net: core: adjust netdev_sync_xxx_features Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10 11:09   ` Alexander Lobakin
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 24/36] treewide: use netdev_feature_add helpers Jian Shen
                   ` (12 subsequent siblings)
  35 siblings, 1 reply; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Introduce macro GSO_INDEX(x) to replace the NETIF_F_XXX
feature shift check, for all the macroes NETIF_F_XXX will
be remove later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 include/linux/netdevice.h | 40 ++++++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1bd5dcbc884d..b01af2a3838d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4886,28 +4886,30 @@ netdev_features_t netif_skb_features(struct sk_buff *skb);
 
 static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 {
+#define GSO_INDEX(x)	((1ULL << (x)) >> NETIF_F_GSO_SHIFT)
+
 	netdev_features_t feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT;
 
 	/* 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));
+	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 (features & feature) == feature;
 }
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 24/36] treewide: use netdev_feature_add helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (22 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 23/36] net: adjust the build check for net_gso_ok() Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 25/36] treewide: use netdev_features_or/set helpers Jian Shen
                   ` (11 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '|' and '|=' operations of single feature bit by
netdev_feature_add helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 arch/um/drivers/vector_kern.c                 |   4 +-
 drivers/firewire/net.c                        |   2 +-
 drivers/infiniband/hw/hfi1/vnic_main.c        |   4 +-
 drivers/infiniband/ulp/ipoib/ipoib_main.c     |   6 +-
 drivers/infiniband/ulp/ipoib/ipoib_verbs.c    |   2 +-
 drivers/misc/sgi-xp/xpnet.c                   |   2 +-
 drivers/net/bonding/bond_main.c               |   8 +-
 drivers/net/can/dev/dev.c                     |   2 +-
 drivers/net/ethernet/3com/3c59x.c             |   5 +-
 drivers/net/ethernet/adaptec/starfire.c       |  11 +-
 drivers/net/ethernet/aeroflex/greth.c         |   2 +-
 drivers/net/ethernet/alacritech/slicoss.c     |   2 +-
 drivers/net/ethernet/alteon/acenic.c          |   2 +-
 drivers/net/ethernet/altera/altera_tse_main.c |   5 +-
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  14 +--
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |   9 +-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c     |   6 +-
 drivers/net/ethernet/apm/xgene-v2/main.c      |   4 +-
 drivers/net/ethernet/apm/xgene-v2/main.h      |   1 +
 .../net/ethernet/apm/xgene/xgene_enet_main.c  |   4 +-
 .../ethernet/aquantia/atlantic/aq_macsec.c    |   2 +-
 .../ethernet/aquantia/atlantic/aq_macsec.h    |   1 +
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |   2 +-
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |   4 +-
 .../net/ethernet/atheros/atl1e/atl1e_main.c   |   8 +-
 drivers/net/ethernet/atheros/atlx/atl1.c      |   2 +-
 drivers/net/ethernet/atheros/atlx/atl2.c      |   4 +-
 drivers/net/ethernet/atheros/atlx/atlx.c      |   2 +-
 drivers/net/ethernet/broadcom/bnx2.c          |   6 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c   |   6 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  15 ++-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  12 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c  |   4 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c |   3 +-
 drivers/net/ethernet/broadcom/tg3.c           |  19 +--
 drivers/net/ethernet/cadence/macb_main.c      |  10 +-
 .../net/ethernet/cavium/liquidio/lio_main.c   |   3 +-
 .../net/ethernet/cavium/thunder/nicvf_main.c  |   4 +-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  10 +-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |   9 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h    |   1 +
 .../net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c   |   8 +-
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |   6 +-
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |   4 +-
 drivers/net/ethernet/cisco/enic/enic_main.c   |  14 +--
 drivers/net/ethernet/cortina/gemini.c         |   2 +-
 drivers/net/ethernet/davicom/dm9000.c         |   4 +-
 drivers/net/ethernet/emulex/benet/be_main.c   |   2 +-
 drivers/net/ethernet/engleder/tsnep_main.c    |   2 +-
 drivers/net/ethernet/faraday/ftgmac100.c      |   2 +-
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |   4 +-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |   3 +-
 .../net/ethernet/freescale/enetc/enetc_pf.c   |   6 +-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |   2 +-
 drivers/net/ethernet/freescale/fec_main.c     |   2 +-
 .../ethernet/freescale/fs_enet/fs_enet-main.c |   2 +-
 drivers/net/ethernet/freescale/gianfar.c      |   2 +-
 .../ethernet/fungible/funeth/funeth_ktls.c    |   5 +-
 .../ethernet/fungible/funeth/funeth_main.c    |   4 +-
 drivers/net/ethernet/google/gve/gve_adminq.c  |   3 +-
 drivers/net/ethernet/hisilicon/hix5hd2_gmac.c |   5 +-
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   |  17 +--
 .../net/ethernet/huawei/hinic/hinic_main.c    |  12 +-
 drivers/net/ethernet/ibm/emac/core.c          |   2 +-
 drivers/net/ethernet/ibm/ibmveth.c            |   8 +-
 drivers/net/ethernet/ibm/ibmvnic.c            |  13 +-
 drivers/net/ethernet/intel/e100.c             |   7 +-
 drivers/net/ethernet/intel/e1000/e1000_main.c |   8 +-
 drivers/net/ethernet/intel/e1000e/netdev.c    |  13 +-
 drivers/net/ethernet/intel/fm10k/fm10k.h      |   1 +
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   |   4 +-
 drivers/net/ethernet/intel/fm10k/fm10k_pci.c  |   7 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c   |  19 +--
 drivers/net/ethernet/intel/iavf/iavf_main.c   |  66 +++++++----
 .../net/ethernet/intel/iavf/iavf_virtchnl.c   |   2 +-
 drivers/net/ethernet/intel/ice/ice_main.c     |  15 ++-
 drivers/net/ethernet/intel/ice/ice_repr.c     |   2 +-
 drivers/net/ethernet/intel/igb/igb_main.c     |  20 ++--
 drivers/net/ethernet/intel/igbvf/netdev.c     |   8 +-
 drivers/net/ethernet/intel/igc/igc_main.c     |  16 +--
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |   8 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe.h      |   1 +
 drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c |   2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |  18 +--
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |   6 +-
 drivers/net/ethernet/jme.c                    |   4 +-
 drivers/net/ethernet/marvell/mv643xx_eth.c    |   2 +-
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |   6 +-
 .../ethernet/marvell/octeon_ep/octep_main.c   |   2 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  10 +-
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |   6 +-
 .../ethernet/marvell/prestera/prestera_main.c |   5 +-
 drivers/net/ethernet/marvell/skge.c           |   2 +-
 drivers/net/ethernet/marvell/sky2.c           |   8 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |   4 +-
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  31 +++--
 .../mellanox/mlx5/core/en_accel/ipsec.c       |  16 +--
 .../mellanox/mlx5/core/en_accel/ktls.c        |   6 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 112 +++++++++---------
 .../net/ethernet/mellanox/mlx5/core/en_rep.c  |  20 ++--
 drivers/net/ethernet/micrel/ksz884x.c         |   2 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |   8 +-
 drivers/net/ethernet/natsemi/ns83820.c        |   7 +-
 .../net/ethernet/netronome/nfp/crypto/tls.c   |   8 +-
 drivers/net/ethernet/netronome/nfp/nfp_net.h  |   1 +
 .../ethernet/netronome/nfp/nfp_net_common.c   |  32 ++---
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  34 +++---
 drivers/net/ethernet/ni/nixge.c               |   2 +-
 drivers/net/ethernet/nvidia/forcedeth.c       |   7 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   |  37 +++---
 .../ethernet/qlogic/netxen/netxen_nic_main.c  |  12 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c  |  22 ++--
 drivers/net/ethernet/qlogic/qla3xxx.c         |   7 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |   5 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_main.c  |  11 +-
 .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c   |   2 +-
 drivers/net/ethernet/realtek/8139cp.c         |   6 +-
 drivers/net/ethernet/realtek/8139too.c        |   4 +-
 drivers/net/ethernet/realtek/r8169_main.c     |  14 +--
 drivers/net/ethernet/renesas/ravb_main.c      |   3 +-
 drivers/net/ethernet/renesas/sh_eth.c         |   5 +-
 drivers/net/ethernet/rocker/rocker_main.c     |   5 +-
 .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |   2 +-
 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 +-
 drivers/net/ethernet/sfc/siena/efx.c          |   4 +-
 drivers/net/ethernet/socionext/sni_ave.c      |   9 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  15 +--
 drivers/net/ethernet/sun/cassini.c            |   7 +-
 drivers/net/ethernet/sun/niu.c                |   4 +-
 drivers/net/ethernet/sun/sungem.c             |   2 +-
 drivers/net/ethernet/sun/sunhme.c             |  12 +-
 .../net/ethernet/synopsys/dwc-xlgmac-common.c |  14 +--
 drivers/net/ethernet/synopsys/dwc-xlgmac.h    |   1 +
 drivers/net/ethernet/tehuti/tehuti.c          |   2 +-
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |   4 +-
 drivers/net/ethernet/ti/cpsw.c                |   9 +-
 drivers/net/ethernet/ti/netcp_core.c          |   6 +-
 drivers/net/ethernet/toshiba/ps3_gelic_net.c  |  10 +-
 drivers/net/ethernet/toshiba/spider_net.c     |  10 +-
 drivers/net/ethernet/tundra/tsi108_eth.c      |   2 +-
 drivers/net/ethernet/via/via-rhine.c          |   5 +-
 .../net/ethernet/wangxun/txgbe/txgbe_main.c   |   3 +-
 drivers/net/ethernet/wiznet/w5100.c           |   3 +-
 drivers/net/ethernet/wiznet/w5300.c           |   3 +-
 drivers/net/ethernet/xilinx/ll_temac_main.c   |   4 +-
 .../net/ethernet/xilinx/xilinx_axienet_main.c |   6 +-
 drivers/net/fjes/fjes_main.c                  |   3 +-
 drivers/net/gtp.c                             |   2 +-
 drivers/net/hamradio/bpqether.c               |   2 +-
 drivers/net/hyperv/netvsc_drv.c               |   2 +-
 drivers/net/hyperv/rndis_filter.c             |  16 +--
 drivers/net/ipa/ipa_modem.c                   |   2 +-
 drivers/net/macsec.c                          |   7 +-
 drivers/net/macvlan.c                         |   2 +-
 drivers/net/net_failover.c                    |   4 +-
 drivers/net/netdevsim/netdev.c                |   2 +-
 drivers/net/ntb_netdev.c                      |   2 +-
 drivers/net/ppp/ppp_generic.c                 |   3 +-
 drivers/net/rionet.c                          |   2 +-
 drivers/net/tap.c                             |  11 +-
 drivers/net/team/team.c                       |  10 +-
 drivers/net/thunderbolt.c                     |   2 +-
 drivers/net/tun.c                             |  12 +-
 drivers/net/usb/cdc_mbim.c                    |   5 +-
 drivers/net/usb/lan78xx.c                     |  10 +-
 drivers/net/usb/smsc75xx.c                    |   2 +-
 drivers/net/usb/smsc95xx.c                    |   8 +-
 drivers/net/veth.c                            |   9 +-
 drivers/net/virtio_net.c                      |  31 ++---
 drivers/net/vmxnet3/vmxnet3_drv.c             |  10 +-
 drivers/net/vmxnet3/vmxnet3_ethtool.c         |  10 +-
 drivers/net/vrf.c                             |   6 +-
 drivers/net/wireguard/device.c                |   2 +-
 drivers/net/wireless/ath/ath10k/mac.c         |   2 +-
 drivers/net/wireless/ath/ath11k/mac.c         |   2 +-
 drivers/net/wireless/ath/ath6kl/core.h        |   1 +
 drivers/net/wireless/ath/ath6kl/main.c        |   6 +-
 .../broadcom/brcm80211/brcmfmac/core.c        |   3 +-
 .../net/wireless/intel/iwlwifi/dvm/mac80211.c |   4 +-
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |   4 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c   |   3 +-
 .../net/wireless/mediatek/mt76/mt7615/init.c  |   2 +-
 .../net/wireless/mediatek/mt76/mt7915/init.c  |   2 +-
 .../net/wireless/mediatek/mt76/mt7921/init.c  |   2 +-
 drivers/net/wwan/t7xx/t7xx_netdev.c           |  14 +--
 drivers/net/xen-netback/interface.c           |   2 +-
 drivers/s390/net/qeth_core_main.c             |  23 ++--
 drivers/s390/net/qeth_l2_main.c               |  32 ++---
 drivers/s390/net/qeth_l3_main.c               |  12 +-
 drivers/staging/octeon/ethernet.c             |   7 +-
 drivers/staging/qlge/qlge_main.c              |   2 +-
 include/net/udp.h                             |   3 +-
 net/8021q/vlan.h                              |   2 +-
 net/8021q/vlan_dev.c                          |   8 +-
 net/core/dev.c                                |  26 ++--
 net/core/sock.c                               |   7 +-
 net/dsa/slave.c                               |  13 +-
 net/ethtool/ioctl.c                           |  24 ++--
 net/hsr/hsr_device.c                          |   6 +-
 net/ieee802154/6lowpan/core.c                 |   3 +-
 net/ieee802154/core.c                         |   9 +-
 net/ipv4/ip_tunnel.c                          |   3 +-
 net/ipv4/ip_vti.c                             |   3 +-
 net/ipv4/ipip.c                               |   2 +-
 net/ipv4/ipmr.c                               |   2 +-
 net/ipv4/tcp_offload.c                        |   2 +-
 net/ipv4/udp_offload.c                        |   4 +-
 net/ipv6/ip6_gre.c                            |   2 +-
 net/ipv6/ip6_tunnel.c                         |   4 +-
 net/ipv6/ip6mr.c                              |   3 +-
 net/ipv6/sit.c                                |   5 +-
 net/ipv6/udp_offload.c                        |   2 +-
 net/l2tp/l2tp_eth.c                           |   2 +-
 net/nsh/nsh.c                                 |   3 +-
 net/openvswitch/datapath.c                    |   3 +-
 net/openvswitch/vport-internal_dev.c          |   2 +-
 net/phonet/pep-gprs.c                         |   2 +-
 net/sctp/offload.c                            |   5 +-
 net/wireless/core.c                           |   9 +-
 net/xfrm/xfrm_interface.c                     |   2 +-
 224 files changed, 902 insertions(+), 763 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index d797758850e1..9bd68d8dd410 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1629,8 +1629,8 @@ static void vector_eth_configure(
 	});
 
 	netdev_active_features_zero(dev);
-	dev->features |= NETIF_F_SG;
-	dev->features |= NETIF_F_FRAGLIST;
+	netdev_active_feature_add(dev, NETIF_F_SG_BIT);
+	netdev_active_feature_add(dev, NETIF_F_FRAGLIST_BIT);
 	dev->features = dev->hw_features;
 	INIT_WORK(&vp->reset_tx, vector_reset_tx);
 
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index e73c8793599b..58a01d2cfed4 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -1376,7 +1376,7 @@ static void fwnet_init_dev(struct net_device *net)
 	net->watchdog_timeo	= 2 * HZ;
 	net->flags		= IFF_BROADCAST | IFF_MULTICAST;
 	netdev_active_features_zero(net);
-	net->features		|= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(net, NETIF_F_HIGHDMA_BIT);
 	net->addr_len		= FWNET_ALEN;
 	net->hard_header_len	= FWNET_HLEN;
 	net->type		= ARPHRD_IEEE1394;
diff --git a/drivers/infiniband/hw/hfi1/vnic_main.c b/drivers/infiniband/hw/hfi1/vnic_main.c
index 52f805909ce3..634876741a7b 100644
--- a/drivers/infiniband/hw/hfi1/vnic_main.c
+++ b/drivers/infiniband/hw/hfi1/vnic_main.c
@@ -589,8 +589,8 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device,
 	rn->set_id = hfi1_vnic_set_vesw_id;
 
 	netdev_active_features_zero(netdev);
-	netdev->features |= NETIF_F_HIGHDMA;
-	netdev->features |= NETIF_F_SG;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
+	netdev_active_feature_add(netdev, NETIF_F_SG_BIT);
 	netdev->hw_features = netdev->features;
 	netdev->vlan_features = netdev->features;
 	netdev->watchdog_timeo = msecs_to_jiffies(HFI_TX_TIMEOUT_MS);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index b69b918b2c39..fe18d7819d3c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1855,11 +1855,11 @@ static void ipoib_set_dev_features(struct ipoib_dev_priv *priv)
 	priv->kernel_caps = priv->ca->attrs.kernel_cap_flags;
 
 	if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
-		priv->dev->hw_features |= NETIF_F_IP_CSUM;
-		priv->dev->hw_features |= NETIF_F_RXCSUM;
+		netdev_hw_feature_add(priv->dev, NETIF_F_IP_CSUM_BIT);
+		netdev_hw_feature_add(priv->dev, NETIF_F_RXCSUM_BIT);
 
 		if (priv->kernel_caps & IBK_UD_TSO)
-			priv->dev->hw_features |= NETIF_F_TSO;
+			netdev_hw_feature_add(priv->dev, NETIF_F_TSO_BIT);
 
 		priv->dev->features |= priv->dev->hw_features;
 	}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 368e5d77416d..cd9ac35ac65a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -234,7 +234,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
 	priv->rx_wr.sg_list = priv->rx_sge;
 
 	if (init_attr.cap.max_send_sge > 1)
-		dev->features |= NETIF_F_SG;
+		netdev_active_feature_add(dev, NETIF_F_SG_BIT);
 
 	priv->max_send_sge = init_attr.cap.max_send_sge;
 
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 8547652c7b59..46bfc19d5020 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -570,7 +570,7 @@ xpnet_init(void)
 	 * packet will be dropped.
 	 */
 	netdev_active_features_zero(xpnet_device);
-	xpnet_device->features |= NETIF_F_HW_CSUM;
+	netdev_active_feature_add(xpnet_device, NETIF_F_HW_CSUM_BIT);
 
 	result = register_netdev(xpnet_device);
 	if (result != 0) {
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index edbeaac3f678..f117f63e2879 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5753,7 +5753,7 @@ void bond_setup(struct net_device *bond_dev)
 #endif /* CONFIG_XFRM_OFFLOAD */
 
 	/* don't acquire bond device's netif_tx_lock when transmitting */
-	bond_dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(bond_dev, NETIF_F_LLTX_BIT);
 
 	/* By default, we declare the bond to be fully
 	 * VLAN hardware accelerated capable. Special
@@ -5763,11 +5763,11 @@ void bond_setup(struct net_device *bond_dev)
 	 */
 
 	/* Don't allow bond devices to change network namespaces. */
-	bond_dev->features |= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(bond_dev, NETIF_F_NETNS_LOCAL_BIT);
 
 	bond_dev->hw_features = BOND_VLAN_FEATURES;
-	bond_dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
-	bond_dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_hw_feature_add(bond_dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
+	netdev_hw_feature_add(bond_dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
 	bond_dev->features |= bond_dev->hw_features;
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 4243e65b2c68..6752b381f72d 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -223,7 +223,7 @@ void can_setup(struct net_device *dev)
 	/* New-style flags. */
 	dev->flags = IFF_NOARP;
 	netdev_active_features_zero(dev);
-	dev->features |= NETIF_F_HW_CSUM;
+	netdev_active_feature_add(dev, NETIF_F_HW_CSUM_BIT);
 }
 
 /* Allocate and setup space for the CAN network device */
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 900435ea2c10..d816cb6f22ab 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -82,6 +82,7 @@ static int vortex_debug = 1;
 #include <linux/mii.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -1448,8 +1449,8 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
 		if (card_idx < MAX_UNITS &&
 		    ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) ||
 				hw_checksums[card_idx] == 1)) {
-			dev->features |= NETIF_F_IP_CSUM;
-			dev->features |= NETIF_F_SG;
+			netdev_active_feature_add(dev, NETIF_F_IP_CSUM_BIT);
+			netdev_active_feature_add(dev, NETIF_F_SG_BIT);
 		}
 	} else
 		dev->netdev_ops =  &vortex_netdev_ops;
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index f19be1f78848..51e51e4d5e7a 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -33,6 +33,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -685,17 +686,17 @@ static int starfire_init_one(struct pci_dev *pdev,
 #ifdef ZEROCOPY
 	/* Starfire can do TCP/UDP checksumming */
 	if (enable_hw_cksum) {
-		dev->features |= NETIF_F_IP_CSUM;
-		dev->features |= NETIF_F_SG;
+		netdev_active_feature_add(dev, NETIF_F_IP_CSUM_BIT);
+		netdev_active_feature_add(dev, NETIF_F_SG_BIT);
 	}
 #endif /* ZEROCOPY */
 
 #ifdef VLAN_SUPPORT
-	dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
-	dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_active_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
+	netdev_active_feature_add(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 #endif /* VLAN_RX_KILL_VID */
 #ifdef ADDR_64BITS
-	dev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 #endif /* ADDR_64BITS */
 
 	/* Serial EEPROM reads are hidden by the hardware. */
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 8a2c87778e96..ee4165257dfe 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1491,7 +1491,7 @@ static int greth_of_probe(struct platform_device *ofdev)
 		netdev_hw_features_zero(dev);
 		netdev_hw_features_set_array(dev, &greth_hw_feature_set);
 		dev->features = dev->hw_features;
-		dev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 		greth_netdev_ops.ndo_start_xmit = greth_start_xmit_gbit;
 	}
 
diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c
index a52e3bc855e4..a8989c1146bb 100644
--- a/drivers/net/ethernet/alacritech/slicoss.c
+++ b/drivers/net/ethernet/alacritech/slicoss.c
@@ -1780,7 +1780,7 @@ static int slic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->irq = pdev->irq;
 	dev->netdev_ops = &slic_netdev_ops;
 	netdev_hw_features_zero(dev);
-	dev->hw_features |= NETIF_F_RXCSUM;
+	netdev_hw_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	dev->features |= dev->hw_features;
 
 	dev->ethtool_ops = &slic_ethtool_ops;
diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
index 4a16e176248c..bd306d707dbf 100644
--- a/drivers/net/ethernet/alteon/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -595,7 +595,7 @@ static int acenic_probe_one(struct pci_dev *pdev,
 	}
 	ap->name = dev->name;
 
-	dev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	pci_set_drvdata(pdev, dev);
 
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 6dea777c8b98..64f9ee8581ce 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/mii.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of_device.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
@@ -1558,13 +1559,13 @@ static int altera_tse_probe(struct platform_device *pdev)
 	 */
 	ndev->hw_features &= ~NETIF_F_SG;
 	ndev->features |= ndev->hw_features;
-	ndev->features |=  NETIF_F_HIGHDMA;
+	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 
 	/* VLAN offloading of tagging, stripping and filtering is not
 	 * supported by hardware, but driver will accommodate the
 	 * extra 4-byte VLAN tag for processing by upper layers
 	 */
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	/* setup NAPI interface */
 	netif_napi_add(ndev, &priv->napi, tse_poll, NAPI_POLL_WEIGHT);
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index f77a930367ce..202b10c77408 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -4024,28 +4024,28 @@ static void ena_set_dev_offloads(struct ena_com_dev_get_features_ctx *feat,
 	/* Set offload features */
 	if (feat->offload.tx &
 		ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_PART_MASK)
-		dev_features |= NETIF_F_IP_CSUM;
+		netdev_feature_add(NETIF_F_IP_CSUM_BIT, &dev_features);
 
 	if (feat->offload.tx &
 		ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV6_CSUM_PART_MASK)
-		dev_features |= NETIF_F_IPV6_CSUM;
+		netdev_feature_add(NETIF_F_IPV6_CSUM_BIT, &dev_features);
 
 	if (feat->offload.tx & ENA_ADMIN_FEATURE_OFFLOAD_DESC_TSO_IPV4_MASK)
-		dev_features |= NETIF_F_TSO;
+		netdev_feature_add(NETIF_F_TSO_BIT, &dev_features);
 
 	if (feat->offload.tx & ENA_ADMIN_FEATURE_OFFLOAD_DESC_TSO_IPV6_MASK)
-		dev_features |= NETIF_F_TSO6;
+		netdev_feature_add(NETIF_F_TSO6_BIT, &dev_features);
 
 	if (feat->offload.tx & ENA_ADMIN_FEATURE_OFFLOAD_DESC_TSO_ECN_MASK)
-		dev_features |= NETIF_F_TSO_ECN;
+		netdev_feature_add(NETIF_F_TSO_ECN_BIT, &dev_features);
 
 	if (feat->offload.rx_supported &
 		ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV4_CSUM_MASK)
-		dev_features |= NETIF_F_RXCSUM;
+		netdev_feature_add(NETIF_F_RXCSUM_BIT, &dev_features);
 
 	if (feat->offload.rx_supported &
 		ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV6_CSUM_MASK)
-		dev_features |= NETIF_F_RXCSUM;
+		netdev_feature_add(NETIF_F_RXCSUM_BIT, &dev_features);
 
 	netdev->features = dev_features;
 	netdev_active_features_set_array(netdev, &ena_feature_set);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index eb0b205b49af..4ee601db53cd 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2185,8 +2185,8 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 	netdev_features_t vxlan_base;
 
 	netdev_features_zero(&vxlan_base);
-	vxlan_base |= NETIF_F_GSO_UDP_TUNNEL;
-	vxlan_base |= NETIF_F_RX_UDP_TUNNEL_PORT;
+	netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_BIT, &vxlan_base);
+	netdev_feature_add(NETIF_F_RX_UDP_TUNNEL_PORT_BIT, &vxlan_base);
 
 	if (!pdata->hw_feat.vxn)
 		return features;
@@ -2196,7 +2196,7 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 	    !(features & NETIF_F_GSO_UDP_TUNNEL)) {
 		netdev_notice(netdev,
 			      "forcing tx udp tunnel support\n");
-		features |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_BIT, &features);
 	}
 
 	/* Can't do one without doing the other */
@@ -2210,7 +2210,8 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 		if (!(features & NETIF_F_GSO_UDP_TUNNEL_CSUM)) {
 			netdev_notice(netdev,
 				      "forcing tx udp tunnel checksumming on\n");
-			features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+			netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+					   &features);
 		}
 	} else {
 		if (features & NETIF_F_GSO_UDP_TUNNEL_CSUM) {
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index f08f983cc13a..e6a050b6bdee 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -375,15 +375,15 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
 	netdev_hw_features_set_array(netdev, &xgbe_hw_feature_set);
 
 	if (pdata->hw_feat.rss)
-		netdev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 
 	if (pdata->hw_feat.vxn) {
 		netdev_hw_enc_features_zero(netdev);
 		netdev_hw_enc_features_set_array(netdev,
 						 &xgbe_hw_enc_feature_set);
 
-		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
-		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 		netdev->udp_tunnel_nic_info = xgbe_get_udp_tunnel_info();
 	}
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c
index 739110c9f836..ceabdad21e17 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -648,8 +648,8 @@ static int xge_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, pdata);
 	ndev->netdev_ops = &xgene_ndev_ops;
 
-	ndev->features |= NETIF_F_GSO;
-	ndev->features |= NETIF_F_GRO;
+	netdev_active_feature_add(ndev, NETIF_F_GSO_BIT);
+	netdev_active_feature_add(ndev, NETIF_F_GRO_BIT);
 
 	ret = xge_get_resources(pdata);
 	if (ret)
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.h b/drivers/net/ethernet/apm/xgene-v2/main.h
index b3985a7be59d..e53e72719716 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.h
+++ b/drivers/net/ethernet/apm/xgene-v2/main.h
@@ -17,6 +17,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of_platform.h>
 #include <linux/of_net.h>
 #include <linux/of_mdio.h>
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 65bba455a69f..78c86e6be7a0 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -2069,8 +2069,8 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	spin_lock_init(&pdata->mac_lock);
 
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
-		ndev->features |= NETIF_F_TSO;
-		ndev->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(ndev, NETIF_F_TSO_BIT);
+		netdev_active_feature_add(ndev, NETIF_F_RXCSUM_BIT);
 		spin_lock_init(&pdata->mss_lock);
 	}
 	ndev->hw_features = ndev->features;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
index 02058fe79f52..f77b090c9fc2 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
@@ -1490,7 +1490,7 @@ int aq_macsec_init(struct aq_nic_s *nic)
 	if (!nic->macsec_cfg)
 		return -ENOMEM;
 
-	nic->ndev->features |= NETIF_F_HW_MACSEC;
+	netdev_active_feature_add(nic->ndev, NETIF_F_HW_MACSEC_BIT);
 	nic->ndev->macsec_ops = &aq_macsec_ops;
 
 	return 0;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h
index a47e2710487e..ffedc6850e1a 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h
@@ -7,6 +7,7 @@
 #define AQ_MACSEC_H
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #if IS_ENABLED(CONFIG_MACSEC)
 
 #include "net/macsec.h"
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index e2fe6f2507d3..5d6eaefb8391 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -387,7 +387,7 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 	self->ndev->features = *aq_hw_caps->hw_features;
 	netdev_vlan_features_set_array(self->ndev, &aq_nic_vlan_feature_set);
 	netdev_gso_partial_features_zero(self->ndev);
-	self->ndev->gso_partial_features |= NETIF_F_GSO_UDP_L4;
+	netdev_gso_partial_feature_add(self->ndev, NETIF_F_GSO_UDP_L4_BIT);
 	self->ndev->priv_flags = aq_hw_caps->hw_priv_flags;
 	self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index a9c7b29aadf8..01ab8bec3d4d 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -515,7 +515,7 @@ static netdev_features_t atl1c_fix_features(struct net_device *netdev,
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -2639,7 +2639,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &atl1c_hw_feature_set);
 	netdev->features = netdev->hw_features;
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_TX;
+	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index d615afd95091..1e275e1006b3 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -390,7 +390,7 @@ static netdev_features_t atl1e_fix_features(struct net_device *netdev,
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -2278,10 +2278,10 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &atl1e_hw_feature_set);
 	netdev->features = netdev->hw_features;
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_TX;
+	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 	/* not enabled by default */
-	netdev->hw_features |= NETIF_F_RXALL;
-	netdev->hw_features |= NETIF_F_RXFCS;
+	netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_RXFCS_BIT);
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index c46d3e7ae89f..92ea741cc16c 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -3007,7 +3007,7 @@ static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_set_array(netdev, &atl1_hw_feature_set);
 
 	/* is this valid? see atl1_setup_mac_ctrl() */
-	netdev->features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
 	/* MTU range: 42 - 10218 */
 	netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 15df55325aae..e47f6325cfba 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -380,7 +380,7 @@ static netdev_features_t atl2_fix_features(struct net_device *netdev,
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -1391,7 +1391,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_sw_init;
 
 	netdev_hw_features_zero(netdev);
-	netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	netdev->features |= netdev_ctag_vlan_offload_features;
 
 	/* Init PHY as early as possible due to power saving issue  */
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index e8cfbf4ff1b5..199b190ae23a 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -245,7 +245,7 @@ static netdev_features_t atlx_fix_features(struct net_device *netdev,
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index bd548249c2f2..a47dd8ae6e8d 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8217,7 +8217,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 
 	/* Configure DMA attributes. */
 	if (dma_set_mask(&pdev->dev, dma_mask) == 0) {
-		dev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 		rc = dma_set_coherent_mask(&pdev->dev, persist_dma_mask);
 		if (rc) {
 			dev_err(&pdev->dev,
@@ -8597,8 +8597,8 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_set_array(dev, &bnx2_hw_feature_set);
 
 	if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
-		dev->hw_features |= NETIF_F_IPV6_CSUM;
-		dev->hw_features |= NETIF_F_TSO6;
+		netdev_hw_feature_add(dev, NETIF_F_IPV6_CSUM_BIT);
+		netdev_hw_feature_add(dev, NETIF_F_TSO6_BIT);
 	}
 
 	dev->vlan_features = dev->hw_features;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index e68d77d9ae50..a1f3f6552101 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4913,13 +4913,15 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
 		if (!(features & NETIF_F_RXCSUM) && !bp->disable_tpa) {
 			features &= ~NETIF_F_RXCSUM;
 			if (dev->features & NETIF_F_RXCSUM)
-				features |= NETIF_F_RXCSUM;
+				netdev_feature_add(NETIF_F_RXCSUM_BIT,
+						   &features);
 		}
 
 		if (changed & NETIF_F_LOOPBACK) {
 			features &= ~NETIF_F_LOOPBACK;
 			if (dev->features & NETIF_F_LOOPBACK)
-				features |= NETIF_F_LOOPBACK;
+				netdev_feature_add(NETIF_F_LOOPBACK_BIT,
+						   &features);
 		}
 	}
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 1986fde63919..fe618561b712 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13271,20 +13271,21 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 		if (chip_is_e1x)
 			bp->accept_any_vlan = true;
 		else
-			dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+			netdev_hw_feature_add(dev,
+					      NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	}
 	/* For VF we'll know whether to enable VLAN filtering after
 	 * getting a response to CHANNEL_TLV_ACQUIRE from PF.
 	 */
 
 	dev->features |= dev->hw_features;
-	dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
-	dev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
+	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (dev->features & NETIF_F_LRO)
 		dev->features &= ~NETIF_F_GRO_HW;
 
 	/* Add Loopback capability to the device */
-	dev->hw_features |= NETIF_F_LOOPBACK;
+	netdev_hw_feature_add(dev, NETIF_F_LOOPBACK_BIT);
 
 #ifdef BCM_DCBNL
 	dev->dcbnl_ops = &bnx2x_dcbnl_ops;
@@ -13999,8 +14000,10 @@ static int bnx2x_init_one(struct pci_dev *pdev,
 #ifdef CONFIG_BNX2X_SRIOV
 		/* VF with OLD Hypervisor or old PF do not support filtering */
 		if (bp->acquire_resp.pfdev_info.pf_cap & PFVF_CAP_VLAN_FILTER) {
-			dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-			dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+			netdev_hw_feature_add(dev,
+					      NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+			netdev_active_feature_add(dev,
+						  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 		}
 #endif
 	}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 150630a2b207..a45a5c5684ca 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -12266,10 +12266,10 @@ static void bnxt_set_dflt_rfs(struct bnxt *bp)
 	dev->features &= ~NETIF_F_NTUPLE;
 	bp->flags &= ~BNXT_FLAG_RFS;
 	if (bnxt_rfs_supported(bp)) {
-		dev->hw_features |= NETIF_F_NTUPLE;
+		netdev_hw_feature_add(dev, NETIF_F_NTUPLE_BIT);
 		if (bnxt_rfs_capable(bp)) {
 			bp->flags |= BNXT_FLAG_RFS;
-			dev->features |= NETIF_F_NTUPLE;
+			netdev_active_feature_add(dev, NETIF_F_NTUPLE_BIT);
 		}
 	}
 }
@@ -13637,7 +13637,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_set_array(dev, &bnxt_hw_feature_set);
 
 	if (BNXT_SUPPORTS_TPA(bp))
-		dev->hw_features |= NETIF_F_LRO;
+		netdev_hw_feature_add(dev, NETIF_F_LRO_BIT);
 
 	netdev_hw_enc_features_zero(dev);
 	netdev_hw_enc_features_set_array(dev, &bnxt_hw_enc_feature_set);
@@ -13646,15 +13646,15 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_gso_partial_features_zero(dev);
 	netdev_gso_partial_features_set_array(dev, &bnxt_gso_partial_feature_set);
 	dev->vlan_features = dev->hw_features;
-	dev->vlan_features |= NETIF_F_HIGHDMA;
+	netdev_vlan_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (bp->fw_cap & BNXT_FW_CAP_VLAN_RX_STRIP)
 		dev->hw_features |= BNXT_HW_FEATURE_VLAN_ALL_RX;
 	if (bp->fw_cap & BNXT_FW_CAP_VLAN_TX_INSERT)
 		dev->hw_features |= BNXT_HW_FEATURE_VLAN_ALL_TX;
 	if (BNXT_SUPPORTS_TPA(bp))
-		dev->hw_features |= NETIF_F_GRO_HW;
+		netdev_hw_feature_add(dev, NETIF_F_GRO_HW_BIT);
 	dev->features |= dev->hw_features;
-	dev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (dev->features & NETIF_F_GRO_HW)
 		dev->features &= ~NETIF_F_LRO;
 	dev->priv_flags |= IFF_UNICAST_FLT;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index d8afcf8d6b30..3c1a46ed3979 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -2052,8 +2052,8 @@ int bnxt_init_tc(struct bnxt *bp)
 		goto destroy_decap_table;
 
 	tc_info->enabled = true;
-	bp->dev->hw_features |= NETIF_F_HW_TC;
-	bp->dev->features |= NETIF_F_HW_TC;
+	netdev_hw_feature_add(bp->dev, NETIF_F_HW_TC_BIT);
+	netdev_active_feature_add(bp->dev, NETIF_F_HW_TC_BIT);
 	bp->tc_info = tc_info;
 
 	/* init indirect block notifications */
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
index f53387ed0167..9dd199dffb59 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
 #include <linux/bpf.h>
@@ -425,7 +426,7 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
 		bnxt_get_max_rings(bp, &rx, &tx, true);
 		if (rx > 1) {
 			bp->flags &= ~BNXT_FLAG_NO_AGG_RINGS;
-			bp->dev->hw_features |= NETIF_F_LRO;
+			netdev_hw_feature_add(bp->dev, NETIF_F_LRO_BIT);
 		}
 	}
 	bp->tx_nr_rings_xdp = tx_xdp;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index f4a455f8743b..ad927bc15d12 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -36,6 +36,7 @@
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -17700,7 +17701,7 @@ static int tg3_init_one(struct pci_dev *pdev,
 	if (dma_mask > DMA_BIT_MASK(32)) {
 		err = dma_set_mask(&pdev->dev, dma_mask);
 		if (!err) {
-			features |= NETIF_F_HIGHDMA;
+			netdev_feature_add(NETIF_F_HIGHDMA_BIT, &features);
 			err = dma_set_coherent_mask(&pdev->dev,
 						    persist_dma_mask);
 			if (err < 0) {
@@ -17725,12 +17726,12 @@ static int tg3_init_one(struct pci_dev *pdev,
 	 * to hardware bugs.
 	 */
 	if (tg3_chip_rev_id(tp) != CHIPREV_ID_5700_B0) {
-		features |= NETIF_F_SG;
-		features |= NETIF_F_IP_CSUM;
-		features |= NETIF_F_RXCSUM;
+		netdev_feature_add(NETIF_F_SG_BIT, &features);
+		netdev_feature_add(NETIF_F_IP_CSUM_BIT, &features);
+		netdev_feature_add(NETIF_F_RXCSUM_BIT, &features);
 
 		if (tg3_flag(tp, 5755_PLUS))
-			features |= NETIF_F_IPV6_CSUM;
+			netdev_feature_add(NETIF_F_IPV6_CSUM_BIT, &features);
 	}
 
 	/* TSO is on by default on chips that support hardware TSO.
@@ -17741,17 +17742,17 @@ static int tg3_init_one(struct pci_dev *pdev,
 	     tg3_flag(tp, HW_TSO_2) ||
 	     tg3_flag(tp, HW_TSO_3)) &&
 	    (features & NETIF_F_IP_CSUM))
-		features |= NETIF_F_TSO;
+		netdev_feature_add(NETIF_F_TSO_BIT, &features);
 	if (tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3)) {
 		if (features & NETIF_F_IPV6_CSUM)
-			features |= NETIF_F_TSO6;
+			netdev_feature_add(NETIF_F_TSO6_BIT, &features);
 		if (tg3_flag(tp, HW_TSO_3) ||
 		    tg3_asic_rev(tp) == ASIC_REV_5761 ||
 		    (tg3_asic_rev(tp) == ASIC_REV_5784 &&
 		     tg3_chip_rev(tp) != CHIPREV_5784_AX) ||
 		    tg3_asic_rev(tp) == ASIC_REV_5785 ||
 		    tg3_asic_rev(tp) == ASIC_REV_57780)
-			features |= NETIF_F_TSO_ECN;
+			netdev_feature_add(NETIF_F_TSO_ECN_BIT, &features);
 	}
 
 	dev->features |= features;
@@ -17766,7 +17767,7 @@ static int tg3_init_one(struct pci_dev *pdev,
 	if (tg3_asic_rev(tp) != ASIC_REV_5780 &&
 	    !tg3_flag(tp, CPMU_PRESENT))
 		/* Add the loopback capability */
-		features |= NETIF_F_LOOPBACK;
+		netdev_feature_add(NETIF_F_LOOPBACK_BIT, &features);
 
 	dev->hw_features |= features;
 	dev->priv_flags |= IFF_UNICAST_FLT;
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 1f84d3bc42c9..22553f3d69d6 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -4053,16 +4053,16 @@ static int macb_init(struct platform_device *pdev)
 
 	/* Set features */
 	netdev_hw_features_zero(dev);
-	dev->hw_features |= NETIF_F_SG;
+	netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
 
 	/* Check LSO capability */
 	if (GEM_BFEXT(PBUF_LSO, gem_readl(bp, DCFG6)))
-		dev->hw_features |= NETIF_F_TSO;
+		netdev_hw_feature_add(dev, NETIF_F_TSO_BIT);
 
 	/* Checksum offload is only available on gem with packet buffer */
 	if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE)) {
-		dev->hw_features |= NETIF_F_HW_CSUM;
-		dev->hw_features |= NETIF_F_RXCSUM;
+		netdev_hw_feature_add(dev, NETIF_F_HW_CSUM_BIT);
+		netdev_hw_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	}
 	if (bp->caps & MACB_CAPS_SG_DISABLED)
 		dev->hw_features &= ~NETIF_F_SG;
@@ -4084,7 +4084,7 @@ static int macb_init(struct platform_device *pdev)
 			reg = GEM_BFINS(ETHTCMP, (uint16_t)ETH_P_IP, reg);
 			gem_writel_n(bp, ETHT, SCRT2_ETHT, reg);
 			/* Filtering is supported in hw but don't enable it in kernel now */
-			dev->hw_features |= NETIF_F_NTUPLE;
+			netdev_hw_feature_add(dev, NETIF_F_NTUPLE_BIT);
 			/* init Rx flow definitions */
 			bp->rx_fs_list.count = 0;
 			spin_lock_init(&bp->rx_fs_lock);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 3271b8e9b392..fafd248977ed 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3595,7 +3595,8 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 
 		netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
 
-		lio->dev_capability |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_BIT,
+				   &lio->dev_capability);
 
 		netdev->vlan_features = lio->dev_capability;
 		/* Add any unchangeable hw features */
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index c6923ecabb63..e806eb803dd5 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -2223,10 +2223,10 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &nicvf_hw_feature_set);
 
-	netdev->hw_features |= NETIF_F_RXHASH;
+	netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 
 	netdev->features |= netdev->hw_features;
-	netdev->hw_features |= NETIF_F_LOOPBACK;
+	netdev_hw_feature_add(netdev, NETIF_F_LOOPBACK_BIT);
 
 	netdev_vlan_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &nicvf_vlan_feature_set);
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index eabb2a782d12..3174489477bc 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -871,7 +871,7 @@ static netdev_features_t t1_fix_features(struct net_device *dev,
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -1049,12 +1049,14 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 		if (vlan_tso_capable(adapter)) {
 			netdev->features |= netdev_ctag_vlan_offload_features;
-			netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+			netdev_hw_feature_add(netdev,
+					      NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 			/* T204: disable TSO */
 			if (!(is_T2(adapter)) || bi->port_number != 4) {
-				netdev->hw_features |= NETIF_F_TSO;
-				netdev->features |= NETIF_F_TSO;
+				netdev_hw_feature_add(netdev, NETIF_F_TSO_BIT);
+				netdev_active_feature_add(netdev,
+							  NETIF_F_TSO_BIT);
 			}
 		}
 
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 7bbec0a182c3..35daa61d3c4f 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -2242,7 +2242,8 @@ static int cxgb_siocdevprivate(struct net_device *dev,
 
 		if (t.lro >= 0) {
 			if (t.lro)
-				dev->wanted_features |= NETIF_F_GRO;
+				netdev_wanted_feature_add(dev,
+							  NETIF_F_GRO_BIT);
 			else
 				dev->wanted_features &= ~NETIF_F_GRO;
 			netdev_update_features(dev);
@@ -2594,7 +2595,7 @@ static netdev_features_t cxgb_fix_features(struct net_device *dev,
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -3321,13 +3322,13 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_hw_features_zero(netdev);
 		netdev_hw_features_set_array(netdev, &cxgb_hw_feature_set);
 		netdev->features |= netdev->hw_features;
-		netdev->features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 		netdev_features_zero(&vlan_feat);
 		netdev_features_set_array(&cxgb_vlan_feature_set, &vlan_feat);
 		vlan_feat &= netdev->features;
 		netdev->vlan_features |= vlan_feat;
 
-		netdev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 		netdev->netdev_ops = &cxgb_netdev_ops;
 		netdev->ethtool_ops = &cxgb_ethtool_ops;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 5657ac8cfca0..1eb84a126153 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -43,6 +43,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
index 33b2c0c45509..a885f8d96e2f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
@@ -79,10 +79,10 @@ int cxgb_fcoe_enable(struct net_device *netdev)
 
 	dev_info(adap->pdev_dev, "Enabling FCoE offload features\n");
 
-	netdev->features |= NETIF_F_FCOE_CRC;
-	netdev->vlan_features |= NETIF_F_FCOE_CRC;
-	netdev->features |= NETIF_F_FCOE_MTU;
-	netdev->vlan_features |= NETIF_F_FCOE_MTU;
+	netdev_active_feature_add(netdev, NETIF_F_FCOE_CRC_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_FCOE_CRC_BIT);
+	netdev_active_feature_add(netdev, NETIF_F_FCOE_MTU_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_FCOE_MTU_BIT);
 
 	netdev_features_change(netdev);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 4df2af4c2e05..e5f29203a496 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6867,7 +6867,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev->vlan_features = netdev->features & vlan_features;
 #if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
 		if (pi->adapter->params.crypto & FW_CAPS_CONFIG_TLS_HW) {
-			netdev->hw_features |= NETIF_F_HW_TLS_TX;
+			netdev_hw_feature_add(netdev, NETIF_F_HW_TLS_TX_BIT);
 			netdev->tlsdev_ops = &cxgb4_ktls_ops;
 			/* initialize the refcount */
 			refcount_set(&pi->adapter->chcr_ktls.ktls_refcount, 0);
@@ -6875,8 +6875,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 #endif /* CONFIG_CHELSIO_TLS_DEVICE */
 #if IS_ENABLED(CONFIG_CHELSIO_IPSEC_INLINE)
 		if (pi->adapter->params.crypto & FW_CAPS_CONFIG_IPSEC_INLINE) {
-			netdev->hw_enc_features |= NETIF_F_HW_ESP;
-			netdev->features |= NETIF_F_HW_ESP;
+			netdev_hw_enc_feature_add(netdev, NETIF_F_HW_ESP_BIT);
+			netdev_active_feature_add(netdev, NETIF_F_HW_ESP_BIT);
 			netdev->xfrmdev_ops = &cxgb4_xfrmdev_ops;
 		}
 #endif /* CONFIG_CHELSIO_IPSEC_INLINE */
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 0d1d361fc246..a96a45e8e805 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -1182,7 +1182,7 @@ static netdev_features_t cxgb4vf_fix_features(struct net_device *dev,
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -3093,7 +3093,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 		netdev->hw_features = tso_features;
 		netdev_hw_features_set_array(netdev, &cxgb4vf_hw_feature_set);
 		netdev->features = netdev->hw_features;
-		netdev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 		vlan_features = tso_features;
 		netdev_features_set_array(&cxgb4vf_vlan_feature_set,
 					  &vlan_features);
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 4f851d446716..77379e284cb9 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2902,17 +2902,17 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev_info(dev, "loopback tag=0x%04x\n", enic->loop_tag);
 	}
 	if (ENIC_SETTING(enic, TXCSUM)) {
-		netdev->hw_features |= NETIF_F_SG;
-		netdev->hw_features |= NETIF_F_HW_CSUM;
+		netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
 	}
 	if (ENIC_SETTING(enic, TSO)) {
 		netdev->hw_features |= netdev_general_tso_features;
-		netdev->hw_features |= NETIF_F_TSO_ECN;
+		netdev_hw_feature_add(netdev, NETIF_F_TSO_ECN_BIT);
 	}
 	if (ENIC_SETTING(enic, RSS))
-		netdev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 	if (ENIC_SETTING(enic, RXCSUM))
-		netdev->hw_features |= NETIF_F_RXCSUM;
+		netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 	if (ENIC_SETTING(enic, VXLAN)) {
 		u64 patch_level;
 		u64 a1 = 0;
@@ -2956,11 +2956,11 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->vlan_features |= netdev->features;
 
 #ifdef CONFIG_RFS_ACCEL
-	netdev->hw_features |= NETIF_F_NTUPLE;
+	netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
 #endif
 
 	if (using_dac)
-		netdev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index dcadafd7cdaa..09e2dc3bd280 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -2472,7 +2472,7 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
 
 	netdev->hw_features = GMAC_OFFLOAD_FEATURES;
 	netdev->features |= GMAC_OFFLOAD_FEATURES;
-	netdev->features |= NETIF_F_GRO;
+	netdev_active_feature_add(netdev, NETIF_F_GRO_BIT);
 	/* We can handle jumbo frames up to 10236 bytes so, let's accept
 	 * payloads of 10236 bytes minus VLAN and ethernet header
 	 */
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index fec097064e52..c90d8be25be5 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -1646,8 +1646,8 @@ dm9000_probe(struct platform_device *pdev)
 	/* dm9000a/b are capable of hardware checksum offload */
 	if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) {
 		netdev_hw_features_zero(ndev);
-		ndev->hw_features |= NETIF_F_RXCSUM;
-		ndev->hw_features |= NETIF_F_IP_CSUM;
+		netdev_hw_feature_add(ndev, NETIF_F_RXCSUM_BIT);
+		netdev_hw_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
 		ndev->features |= ndev->hw_features;
 	}
 
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index fefacd5530e2..0a29313e167a 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5216,7 +5216,7 @@ static void be_netdev_init(struct net_device *netdev)
 
 	netdev_hw_features_set_array(netdev, &be_hw_feature_set);
 	if ((be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
-		netdev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 
 	netdev->features |= netdev->hw_features;
 	netdev_active_features_set_array(netdev, &be_feature_set);
diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index 8e58b36a826d..66de80f58025 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -1226,7 +1226,7 @@ static int tsnep_probe(struct platform_device *pdev)
 	netdev->netdev_ops = &tsnep_netdev_ops;
 	netdev->ethtool_ops = &tsnep_ethtool_ops;
 	netdev_active_features_zero(netdev);
-	netdev->features |= NETIF_F_SG;
+	netdev_active_feature_add(netdev, NETIF_F_SG_BIT);
 	netdev->hw_features = netdev->features;
 
 	/* carrier off reporting is important to ethtool even BEFORE open */
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 3cdc5d827f14..c286e0039851 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1943,7 +1943,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
 	netdev_hw_features_set_array(netdev, &ftgmac100_hw_feature_set);
 
 	if (priv->use_ncsi)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	/* AST2400  doesn't have working HW checksum generation */
 	if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac")))
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 545e2b1afad7..c0cd9b14ef72 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -237,8 +237,8 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 	/* The kernels enables GSO automatically, if we declare NETIF_F_SG.
 	 * For conformity, we'll still declare GSO explicitly.
 	 */
-	net_dev->features |= NETIF_F_GSO;
-	net_dev->features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(net_dev, NETIF_F_GSO_BIT);
+	netdev_active_feature_add(net_dev, NETIF_F_RXCSUM_BIT);
 
 	net_dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 	/* we do not want shared skbs on TX */
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 8248e10717b9..40c24fa45506 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -4405,7 +4405,8 @@ static int dpaa2_eth_netdev_init(struct net_device *net_dev)
 	net_dev->hw_features = net_dev->features;
 
 	if (priv->dpni_attrs.vlan_filter_entries)
-		net_dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_hw_feature_add(net_dev,
+				      NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index b8daac778c64..897932f08672 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -795,14 +795,14 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	netdev_vlan_features_set_array(ndev, &enetc_vlan_feature_set);
 
 	if (si->num_rss)
-		ndev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(ndev, NETIF_F_RXHASH_BIT);
 
 	ndev->priv_flags |= IFF_UNICAST_FLT;
 
 	if (si->hw_features & ENETC_SI_F_PSFP && !enetc_psfp_enable(priv)) {
 		priv->active_offloads |= ENETC_F_QCI;
-		ndev->features |= NETIF_F_HW_TC;
-		ndev->hw_features |= NETIF_F_HW_TC;
+		netdev_active_feature_add(ndev, NETIF_F_HW_TC_BIT);
+		netdev_hw_feature_add(ndev, NETIF_F_HW_TC_BIT);
 	}
 
 	/* pick up primary MAC address from SI */
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index a4eab1e1e590..cf1eb325c640 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -152,7 +152,7 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 	netdev_vlan_features_set_array(ndev, &enetc_vf_vlan_feature_set);
 
 	if (si->num_rss)
-		ndev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(ndev, NETIF_F_RXHASH_BIT);
 
 	/* pick up primary MAC address from SI */
 	enetc_load_primary_mac_addr(&si->hw, ndev);
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 49850ee91d4e..c656c9744305 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3571,7 +3571,7 @@ static int fec_enet_init(struct net_device *ndev)
 
 	if (fep->quirks & FEC_QUIRK_HAS_VLAN)
 		/* enable hw VLAN support */
-		ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	if (fep->quirks & FEC_QUIRK_HAS_CSUM) {
 		netif_set_tso_max_segs(ndev, FEC_MAX_TSO_SEGS);
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index b3dae17e067e..f87512990c93 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1027,7 +1027,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
 
 	netif_carrier_off(ndev);
 
-	ndev->features |= NETIF_F_SG;
+	netdev_active_feature_add(ndev, NETIF_F_SG_BIT);
 
 	ret = register_netdev(ndev);
 	if (ret)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index dcf30e6dd012..26861683f699 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -3258,7 +3258,7 @@ static int gfar_probe(struct platform_device *ofdev)
 
 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
 		dev->hw_features |= netdev_ctag_vlan_offload_features;
-		dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_active_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	}
 
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_ktls.c b/drivers/net/ethernet/fungible/funeth/funeth_ktls.c
index f871def70d70..4d572a86ac86 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_ktls.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_ktls.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
 
+#include <linux/netdev_features_helper.h>
 #include "funeth.h"
 #include "funeth_ktls.h"
 
@@ -140,8 +141,8 @@ int fun_ktls_init(struct net_device *netdev)
 
 	fp->ktls_id = netdev->dev_port;
 	netdev->tlsdev_ops = &fun_ktls_ops;
-	netdev->hw_features |= NETIF_F_HW_TLS_TX;
-	netdev->features |= NETIF_F_HW_TLS_TX;
+	netdev_hw_feature_add(netdev, NETIF_F_HW_TLS_TX_BIT);
+	netdev_active_feature_add(netdev, NETIF_F_HW_TLS_TX_BIT);
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_main.c b/drivers/net/ethernet/fungible/funeth/funeth_main.c
index 4bfc6dab65f4..fd981e357f2f 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1789,14 +1789,14 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 
 	netdev_hw_features_set_array(netdev, &fun_hw_feature_set);
 	if (fp->port_caps & FUN_PORT_CAP_OFFLOADS) {
-		netdev->hw_features |= NETIF_F_HW_CSUM;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
 		netdev->hw_features |= tso_flags;
 	}
 	if (fp->port_caps & FUN_PORT_CAP_ENCAP_OFFLOADS)
 		netdev->hw_features |= gso_encap_flags;
 
 	netdev->features |= netdev->hw_features;
-	netdev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 	netdev->vlan_features = netdev->features & vlan_feat;
 	netdev->mpls_features = netdev->vlan_features;
 	netdev->hw_enc_features = netdev->hw_features;
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index f7621ab672b9..b8de076f079d 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include "gve.h"
 #include "gve_adminq.h"
@@ -765,7 +766,7 @@ int gve_adminq_describe_device(struct gve_priv *priv)
 		err = gve_set_desc_cnt(priv, descriptor);
 	} else {
 		/* DQO supports LRO. */
-		priv->dev->hw_features |= NETIF_F_LRO;
+		netdev_hw_feature_add(priv->dev, NETIF_F_LRO_BIT);
 		err = gve_set_desc_cnt_dqo(priv, descriptor, dev_op_dqo_rda);
 	}
 	if (err)
diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
index 69579d94f4d5..bf79258b4904 100644
--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
@@ -6,6 +6,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/platform_device.h>
 #include <linux/of_device.h>
 #include <linux/of_net.h>
@@ -1234,10 +1235,10 @@ static int hix5hd2_dev_probe(struct platform_device *pdev)
 	SET_NETDEV_DEV(ndev, dev);
 
 	if (HAS_CAP_TSO(priv->hw_cap))
-		ndev->hw_features |= NETIF_F_SG;
+		netdev_hw_feature_add(ndev, NETIF_F_SG_BIT);
 
 	ndev->features |= ndev->hw_features;
-	ndev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 	ndev->vlan_features |= ndev->features;
 
 	ret = hix5hd2_init_hw_desc_queue(priv);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index c59026807723..e67a30738a2d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -3288,30 +3288,31 @@ 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_active_features_set_array(netdev, &hns3_default_feature_set);
 
 	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))
@@ -3324,7 +3325,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/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 93d4b019a4d1..4e49e2c4b409 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -949,7 +949,7 @@ static void netdev_features_init(struct net_device *netdev)
 	netdev->vlan_features = netdev->hw_features;
 
 	netdev->features = netdev->hw_features;
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	netdev_hw_enc_features_zero(netdev);
 	netdev_hw_enc_features_set_array(netdev, &hinic_hw_enc_feature_set);
@@ -1083,7 +1083,7 @@ static int set_features(struct hinic_dev *nic_dev,
 					 HINIC_TSO_ENABLE : HINIC_TSO_DISABLE);
 		if (ret) {
 			err = ret;
-			failed_features |= NETIF_F_TSO;
+			netdev_feature_add(NETIF_F_TSO_BIT, &failed_features);
 		}
 	}
 
@@ -1091,7 +1091,8 @@ static int set_features(struct hinic_dev *nic_dev,
 		ret = hinic_set_rx_csum_offload(nic_dev, csum_en);
 		if (ret) {
 			err = ret;
-			failed_features |= NETIF_F_RXCSUM;
+			netdev_feature_add(NETIF_F_RXCSUM_BIT,
+					   &failed_features);
 		}
 	}
 
@@ -1102,7 +1103,7 @@ static int set_features(struct hinic_dev *nic_dev,
 					     HINIC_LRO_MAX_WQE_NUM_DEFAULT);
 		if (ret) {
 			err = ret;
-			failed_features |= NETIF_F_LRO;
+			netdev_feature_add(NETIF_F_LRO_BIT, &failed_features);
 		}
 	}
 
@@ -1112,7 +1113,8 @@ static int set_features(struct hinic_dev *nic_dev,
 						   NETIF_F_HW_VLAN_CTAG_RX));
 		if (ret) {
 			err = ret;
-			failed_features |= NETIF_F_HW_VLAN_CTAG_RX;
+			netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+					   &failed_features);
 		}
 	}
 
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 17b5e0806aa6..5e8d43e04b53 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -3178,7 +3178,7 @@ static int emac_probe(struct platform_device *ofdev)
 		netdev_hw_features_zero(ndev);
 		netdev_hw_features_set_array(ndev, &emac_hw_feature_set);
 		ndev->features |= ndev->hw_features;
-		ndev->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(ndev, NETIF_F_RXCSUM_BIT);
 	}
 	ndev->watchdog_timeo = 5 * HZ;
 	if (emac_phy_supports_gige(dev->phy_mode)) {
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index c59bbbcd094e..9d5b99ce60c2 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1685,7 +1685,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 	netdev->ethtool_ops = &netdev_ethtool_ops;
 	SET_NETDEV_DEV(netdev, &dev->dev);
 	netdev_hw_features_zero(netdev);
-	netdev->hw_features |= NETIF_F_SG;
+	netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
 	if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL)
 		netdev_hw_features_set_array(netdev, &ibmveth_hw_feature_set);
 
@@ -1699,14 +1699,14 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 		netdev->hw_features |= netdev_general_tso_features;
 		netdev->features |= netdev->hw_features;
 	} else {
-		netdev->hw_features |= NETIF_F_TSO;
+		netdev_hw_feature_add(netdev, NETIF_F_TSO_BIT);
 	}
 
 	adapter->is_active_trunk = false;
 	if (ret == H_SUCCESS && (ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK)) {
 		adapter->is_active_trunk = true;
-		netdev->hw_features |= NETIF_F_FRAGLIST;
-		netdev->features |= NETIF_F_FRAGLIST;
+		netdev_hw_feature_add(netdev, NETIF_F_FRAGLIST_BIT);
+		netdev_active_feature_add(netdev, NETIF_F_FRAGLIST_BIT);
 	}
 
 	netdev->min_mtu = IBMVETH_MIN_MTU;
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 0ceecd372b7e..5b757634973d 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4879,18 +4879,18 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 	netdev_hw_features_set_array(adapter->netdev, &ibmvnic_hw_feature_set);
 
 	if (buf->tcp_ipv4_chksum || buf->udp_ipv4_chksum)
-		adapter->netdev->hw_features |= NETIF_F_IP_CSUM;
+		netdev_hw_feature_add(adapter->netdev, NETIF_F_IP_CSUM_BIT);
 
 	if (buf->tcp_ipv6_chksum || buf->udp_ipv6_chksum)
-		adapter->netdev->hw_features |= NETIF_F_IPV6_CSUM;
+		netdev_hw_feature_add(adapter->netdev, NETIF_F_IPV6_CSUM_BIT);
 
 	if ((adapter->netdev->features & netdev_ip_csum_features))
-		adapter->netdev->hw_features |= NETIF_F_RXCSUM;
+		netdev_hw_feature_add(adapter->netdev, NETIF_F_RXCSUM_BIT);
 
 	if (buf->large_tx_ipv4)
-		adapter->netdev->hw_features |= NETIF_F_TSO;
+		netdev_hw_feature_add(adapter->netdev, NETIF_F_TSO_BIT);
 	if (buf->large_tx_ipv6)
-		adapter->netdev->hw_features |= NETIF_F_TSO6;
+		netdev_hw_feature_add(adapter->netdev, NETIF_F_TSO6_BIT);
 
 	if (adapter->state == VNIC_PROBING) {
 		adapter->netdev->features |= adapter->netdev->hw_features;
@@ -5409,7 +5409,8 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq,
 		adapter->vlan_header_insertion =
 		    be64_to_cpu(crq->query_capability.number);
 		if (adapter->vlan_header_insertion)
-			netdev->features |= NETIF_F_HW_VLAN_STAG_TX;
+			netdev_active_feature_add(netdev,
+						  NETIF_F_HW_VLAN_STAG_TX_BIT);
 		netdev_dbg(netdev, "vlan_header_insertion = %lld\n",
 			   adapter->vlan_header_insertion);
 		break;
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 2809f6c0f69a..960411b8d77c 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -138,6 +138,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/mii.h>
 #include <linux/if_vlan.h>
@@ -2837,9 +2838,9 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (!(netdev = alloc_etherdev(sizeof(struct nic))))
 		return -ENOMEM;
 
-	netdev->hw_features |= NETIF_F_RXFCS;
+	netdev_hw_feature_add(netdev, NETIF_F_RXFCS_BIT);
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
-	netdev->hw_features |= NETIF_F_RXALL;
+	netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
 
 	netdev->netdev_ops = &e100_netdev_ops;
 	netdev->ethtool_ops = &e100_ethtool_ops;
@@ -2896,7 +2897,7 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	/* D100 MAC doesn't allow rx of vlan packets with normal MTU */
 	if (nic->mac < mac_82558_D101_A4)
-		netdev->features |= NETIF_F_VLAN_CHALLENGED;
+		netdev_active_feature_add(netdev, NETIF_F_VLAN_CHALLENGED_BIT);
 
 	/* locks must be initialized before calling hw_reset */
 	spin_lock_init(&nic->cb_lock);
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 9564fdef837d..ea3a958a8945 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -794,7 +794,7 @@ static netdev_features_t e1000_fix_features(struct net_device *netdev,
 	 * enable/disable make sure Tx flag is always in same state as Rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -1059,7 +1059,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	if ((hw->mac_type >= e1000_82544) &&
 	   (hw->mac_type != e1000_82547))
-		netdev->hw_features |= NETIF_F_TSO;
+		netdev_hw_feature_add(netdev, NETIF_F_TSO_BIT);
 
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 
@@ -1067,8 +1067,8 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_set_array(netdev, &e1000_hw_rx_feature_set);
 
 	if (pci_using_dac) {
-		netdev->features |= NETIF_F_HIGHDMA;
-		netdev->vlan_features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
+		netdev_vlan_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 	}
 
 	netdev_vlan_features_set_array(netdev, &e1000_vlan_feature_set);
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 7ef3e3e56dfa..439fb2110c55 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -7302,7 +7302,7 @@ static netdev_features_t e1000_fix_features(struct net_device *netdev,
 	 * enable/disable make sure Tx flag is always in same state as Rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -7550,19 +7550,20 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	/* Set user-changeable features (subset of all device features) */
 	netdev->hw_features = netdev->features;
-	netdev->hw_features |= NETIF_F_RXFCS;
+	netdev_hw_feature_add(netdev, NETIF_F_RXFCS_BIT);
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
-	netdev->hw_features |= NETIF_F_RXALL;
+	netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
 
 	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
-		netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_active_feature_add(netdev,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	netdev_vlan_features_set_array(netdev, &e1000_vlan_feature_set);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
-	netdev->features |= NETIF_F_HIGHDMA;
-	netdev->vlan_features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	/* MTU range: 68 - max_hw_frame_size */
 	netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h
index 6119a4108838..fc00769f4a01 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k.h
@@ -7,6 +7,7 @@
 #include <linux/types.h>
 #include <linux/etherdevice.h>
 #include <linux/cpumask.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
 #include <linux/pci.h>
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 2e0e7bc100e8..e51f05bfaa1d 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1583,7 +1583,7 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
 		netdev_hw_enc_features_zero(dev);
 		netdev_hw_enc_features_set_array(dev, &fm10k_hw_enc_feature_set);
 
-		dev->features |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev_active_feature_add(dev, NETIF_F_GSO_UDP_TUNNEL_BIT);
 
 		dev->udp_tunnel_nic_info = &fm10k_udp_tunnels;
 	}
@@ -1592,7 +1592,7 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
 	hw_features = dev->features;
 
 	/* allow user to enable L2 forwarding acceleration */
-	hw_features |= NETIF_F_HW_L2FW_DOFFLOAD;
+	netdev_feature_add(NETIF_F_HW_L2FW_DOFFLOAD_BIT, &hw_features);
 
 	/* configure VLAN features */
 	dev->vlan_features |= dev->features;
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index b473cb7d7c57..d5be43c80c14 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -307,7 +307,8 @@ static int fm10k_handle_reset(struct fm10k_intfc *interface)
 		if (hw->mac.vlan_override)
 			netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 		else
-			netdev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+			netdev_active_feature_add(netdev,
+						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	}
 
 	err = netif_running(netdev) ? fm10k_open(netdev) : 0;
@@ -2010,8 +2011,8 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
 
 	/* update netdev with DMA restrictions */
 	if (dma_get_mask(&pdev->dev) > DMA_BIT_MASK(32)) {
-		netdev->features |= NETIF_F_HIGHDMA;
-		netdev->vlan_features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
+		netdev_vlan_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 	}
 
 	/* reset and initialize the hardware so it is in a known state */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d7d628af7435..0eb64901e3e1 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13680,43 +13680,44 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	netdev_features_set_array(&i40e_hw_enc_feature_set, &hw_enc_features);
 
 	if (!(pf->hw_features & I40E_HW_OUTER_UDP_CSUM_CAPABLE))
-		netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_gso_partial_feature_add(netdev,
+					       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 	netdev->udp_tunnel_nic_info = &pf->udp_tunnel_nic;
 
-	netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
+	netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_GRE_CSUM_BIT);
 
 	netdev->hw_enc_features |= hw_enc_features;
 
 	/* record features VLANs can make use of */
 	netdev->vlan_features |= hw_enc_features;
-	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
+	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 
 	netdev_features_zero(&gso_partial_features);
 	netdev_features_set_array(&i40e_gso_partial_feature_set,
 				  &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->features |= NETIF_F_GSO_PARTIAL;
+	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev->features |= gso_partial_features;
 
 	netdev_mpls_features_set_array(netdev, &i40e_mpls_feature_set);
 	netdev->mpls_features |= gso_partial_features;
 
 	/* enable macvlan offloads */
-	netdev->hw_features |= NETIF_F_HW_L2FW_DOFFLOAD;
+	netdev_hw_feature_add(netdev, NETIF_F_HW_L2FW_DOFFLOAD_BIT);
 
 	hw_features = hw_enc_features | netdev_ctag_vlan_offload_features;
 
 	if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) {
-		hw_features |= NETIF_F_NTUPLE;
-		hw_features |= NETIF_F_HW_TC;
+		netdev_feature_add(NETIF_F_NTUPLE_BIT, &hw_features);
+		netdev_feature_add(NETIF_F_HW_TC_BIT, &hw_features);
 	}
 
 	netdev->hw_features |= hw_features;
 
 	netdev->features |= hw_features;
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-	netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
+	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+	netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 
 	netdev->features &= ~NETIF_F_HW_TC;
 
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 1f9884539807..19b79755ddda 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4337,31 +4337,37 @@ iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter)
 		    stripping_support->outer & VIRTCHNL_VLAN_TOGGLE) {
 			if (stripping_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100)
-				hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+						   &hw_features);
 			if (stripping_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_88A8)
-				hw_features |= NETIF_F_HW_VLAN_STAG_RX;
+				netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT,
+						   &hw_features);
 		} else if (stripping_support->inner !=
 			   VIRTCHNL_VLAN_UNSUPPORTED &&
 			   stripping_support->inner & VIRTCHNL_VLAN_TOGGLE) {
 			if (stripping_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100)
-				hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+						   &hw_features);
 		}
 
 		if (insertion_support->outer != VIRTCHNL_VLAN_UNSUPPORTED &&
 		    insertion_support->outer & VIRTCHNL_VLAN_TOGGLE) {
 			if (insertion_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100)
-				hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT,
+						   &hw_features);
 			if (insertion_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_88A8)
-				hw_features |= NETIF_F_HW_VLAN_STAG_TX;
+				netdev_feature_add(NETIF_F_HW_VLAN_STAG_TX_BIT,
+						   &hw_features);
 		} else if (insertion_support->inner &&
 			   insertion_support->inner & VIRTCHNL_VLAN_TOGGLE) {
 			if (insertion_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100)
-				hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT,
+						   &hw_features);
 		}
 	}
 
@@ -4404,17 +4410,20 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 			if (stripping_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
-				features |= NETIF_F_HW_VLAN_CTAG_RX;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+						   &features);
 			else if (stripping_support->outer &
 				 VIRTCHNL_VLAN_ETHERTYPE_88A8 &&
 				 ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8)
-				features |= NETIF_F_HW_VLAN_STAG_RX;
+				netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT,
+						   &features);
 		} else if (stripping_support->inner !=
 			   VIRTCHNL_VLAN_UNSUPPORTED) {
 			if (stripping_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
-				features |= NETIF_F_HW_VLAN_CTAG_RX;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+						   &features);
 		}
 
 		/* give priority to outer insertion and don't support both outer
@@ -4424,17 +4433,20 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 			if (insertion_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
-				features |= NETIF_F_HW_VLAN_CTAG_TX;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT,
+						   &features);
 			else if (insertion_support->outer &
 				 VIRTCHNL_VLAN_ETHERTYPE_88A8 &&
 				 ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8)
-				features |= NETIF_F_HW_VLAN_STAG_TX;
+				netdev_feature_add(NETIF_F_HW_VLAN_STAG_TX_BIT,
+						   &features);
 		} else if (insertion_support->inner !=
 			   VIRTCHNL_VLAN_UNSUPPORTED) {
 			if (insertion_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
-				features |= NETIF_F_HW_VLAN_CTAG_TX;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT,
+						   &features);
 		}
 
 		/* give priority to outer filtering and don't bother if both
@@ -4445,21 +4457,25 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 			if (filtering_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
-				features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+						   &features);
 			if (filtering_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_88A8 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8)
-				features |= NETIF_F_HW_VLAN_STAG_FILTER;
+				netdev_feature_add(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
+						   &features);
 		} else if (filtering_support->inner !=
 			   VIRTCHNL_VLAN_UNSUPPORTED) {
 			if (filtering_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
-				features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+						   &features);
 			if (filtering_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_88A8 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8)
-				features |= NETIF_F_HW_VLAN_STAG_FILTER;
+				netdev_feature_add(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
+						   &features);
 		}
 	}
 
@@ -4624,16 +4640,17 @@ int iavf_process_config(struct iavf_adapter *adapter)
 
 		if (!(vfres->vf_cap_flags &
 		      VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM))
-			netdev->gso_partial_features |=
-				NETIF_F_GSO_UDP_TUNNEL_CSUM;
+			netdev_gso_partial_feature_add(netdev,
+						       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
-		netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
-		netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
+		netdev_gso_partial_feature_add(netdev,
+					       NETIF_F_GSO_GRE_CSUM_BIT);
+		netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 		netdev->hw_enc_features |= hw_enc_features;
 	}
 	/* record features VLANs can make use of */
 	netdev->vlan_features |= hw_enc_features;
-	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
+	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 
 	/* Write features and hw_features separately to avoid polluting
 	 * with, or dropping, features that are set when we registered.
@@ -4645,9 +4662,9 @@ int iavf_process_config(struct iavf_adapter *adapter)
 
 	/* Enable cloud filter if ADQ is supported */
 	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ)
-		hw_features |= NETIF_F_HW_TC;
+		netdev_feature_add(NETIF_F_HW_TC_BIT, &hw_features);
 	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_USO)
-		hw_features |= NETIF_F_GSO_UDP_L4;
+		netdev_feature_add(NETIF_F_GSO_UDP_L4_BIT, &hw_features);
 
 	netdev->hw_features |= hw_features;
 	netdev->hw_features |= hw_vlan_features;
@@ -4657,7 +4674,8 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	netdev->features |= vlan_features;
 
 	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
-		netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_active_feature_add(netdev,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
index 15ee85dc33bd..56bca0d7b0f5 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -1878,7 +1878,7 @@ static void iavf_netdev_features_vlan_strip_set(struct net_device *netdev,
 						const bool enable)
 {
 	if (enable)
-		netdev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	else
 		netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 }
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 107caaac78ea..d0ecd7f3302a 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3355,13 +3355,15 @@ static void ice_set_netdev_features(struct net_device *netdev)
 
 	/* Enable CTAG/STAG filtering by default in Double VLAN Mode (DVM) */
 	if (is_dvm_ena)
-		vlano_features |= NETIF_F_HW_VLAN_STAG_FILTER;
+		netdev_feature_add(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
+				   &vlano_features);
 
 	netdev_features_zero(&tso_features);
 	netdev_features_set_array(&ice_tso_feature_set, &tso_features);
 
-	netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
-	netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
+	netdev_gso_partial_feature_add(netdev,
+				       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+	netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_GRE_CSUM_BIT);
 	/* set features that user can change */
 	netdev->hw_features = dflt_features | csumo_features;
 	netdev->hw_features |= vlano_features;
@@ -3374,8 +3376,8 @@ static void ice_set_netdev_features(struct net_device *netdev)
 	/* enable features */
 	netdev->features |= netdev->hw_features;
 
-	netdev->hw_features |= NETIF_F_HW_TC;
-	netdev->hw_features |= NETIF_F_LOOPBACK;
+	netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_LOOPBACK_BIT);
 
 	/* encap and VLAN devices inherit default, csumo and tso features */
 	netdev->hw_enc_features |= dflt_features;
@@ -5806,7 +5808,8 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 				netdev_warn(netdev, "cannot support requested 802.1ad filtering setting in SVM mode\n");
 
 			if (req_vlan_fltr & NETIF_F_HW_VLAN_CTAG_FILTER)
-				features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+						   &features);
 		}
 	}
 
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index 0dac67cd9c77..d685d608ce16 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -276,7 +276,7 @@ ice_repr_reg_netdev(struct net_device *netdev)
 	netdev->netdev_ops = &ice_repr_netdev_ops;
 	ice_set_ethtool_repr_ops(netdev);
 
-	netdev->hw_features |= NETIF_F_HW_TC;
+	netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 
 	netif_carrier_off(netdev);
 	netif_tx_stop_all_queues(netdev);
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 3d0af1c6d13e..14e391e4bc23 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2439,7 +2439,7 @@ static netdev_features_t igb_fix_features(struct net_device *netdev,
 	 * enable/disable make sure Tx flag is always in same state as Rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -3299,32 +3299,32 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_active_features_set_array(netdev, &igb_feature_set);
 
 	if (hw->mac.type >= e1000_82576) {
-		netdev->features |= NETIF_F_SCTP_CRC;
-		netdev->features |= NETIF_F_GSO_UDP_L4;
+		netdev_active_feature_add(netdev, NETIF_F_SCTP_CRC_BIT);
+		netdev_active_feature_add(netdev, NETIF_F_GSO_UDP_L4_BIT);
 	}
 
 	if (hw->mac.type >= e1000_i350)
-		netdev->features |= NETIF_F_HW_TC;
+		netdev_active_feature_add(netdev, NETIF_F_HW_TC_BIT);
 
 	netdev_features_zero(&gso_partial_features);
 	netdev_features_set_array(&igb_feature_set, &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->features |= NETIF_F_GSO_PARTIAL;
+	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev->features |= gso_partial_features;
 
 	/* copy netdev features into list of user selectable features */
 	netdev->hw_features |= netdev->features;
 	netdev->hw_features |= netdev_ctag_vlan_offload_features;
-	netdev->hw_features |= NETIF_F_RXALL;
+	netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
 
 	if (hw->mac.type >= e1000_i350)
-		netdev->hw_features |= NETIF_F_NTUPLE;
+		netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
 
-	netdev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev->vlan_features |= netdev->features;
-	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
-	netdev->mpls_features |= NETIF_F_HW_CSUM;
+	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
+	netdev_mpls_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
 	netdev->hw_enc_features |= netdev->vlan_features;
 
 	/* set this bit last since it cannot be part of vlan_features */
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 6994f573fadf..55685206eac1 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2794,15 +2794,15 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				  &gso_partial_features);
 
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->hw_features |= NETIF_F_GSO_PARTIAL;
+	netdev_hw_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev->hw_features |= gso_partial_features;
 
 	netdev->features = netdev->hw_features;
-	netdev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev->vlan_features |= netdev->features;
-	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
-	netdev->mpls_features |= NETIF_F_HW_CSUM;
+	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
+	netdev_mpls_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
 	netdev->hw_enc_features |= netdev->vlan_features;
 
 	/* set this bit last since it cannot be part of vlan_features */
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 805243e7c4cb..f53175a80606 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4941,7 +4941,7 @@ static netdev_features_t igc_fix_features(struct net_device *netdev,
 	 * enable/disable make sure Tx flag is always in same state as Rx.
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
@@ -6335,7 +6335,7 @@ static int igc_probe(struct pci_dev *pdev,
 	netdev_features_set_array(&igc_gso_partial_feature_set,
 				  &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->features |= NETIF_F_GSO_PARTIAL;
+	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev->features |= gso_partial_features;
 
 	/* setup the private structure */
@@ -6344,16 +6344,16 @@ static int igc_probe(struct pci_dev *pdev,
 		goto err_sw_init;
 
 	/* copy netdev features into list of user selectable features */
-	netdev->hw_features |= NETIF_F_NTUPLE;
-	netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
-	netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	netdev->hw_features |= netdev->features;
 
-	netdev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev->vlan_features |= netdev->features;
-	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
-	netdev->mpls_features |= NETIF_F_HW_CSUM;
+	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
+	netdev_mpls_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
 	netdev->hw_enc_features |= netdev->vlan_features;
 
 	/* MTU range: 68 - 9216 */
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index d23b7a10d62f..7630db8cc290 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -439,11 +439,11 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &ixgb_hw_feature_set);
 	netdev->features = netdev->hw_features;
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-	netdev->hw_features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
-	netdev->features |= NETIF_F_HIGHDMA;
-	netdev->vlan_features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	/* MTU range: 68 - 16114 */
 	netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 5369a97ff5ec..6b16a124b047 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -8,6 +8,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/cpumask.h>
 #include <linux/aer.h>
 #include <linux/if_vlan.h>
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index 0fcd82036d4e..603a910aa611 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -858,7 +858,7 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
 
 	/* enable FCoE and notify stack */
 	adapter->flags |= IXGBE_FLAG_FCOE_ENABLED;
-	netdev->features |= NETIF_F_FCOE_MTU;
+	netdev_active_feature_add(netdev, NETIF_F_FCOE_MTU_BIT);
 	netdev_features_change(netdev);
 
 	/* release existing queues and reallocate them */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 0b6b5cfa84df..40228bff5e82 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -11021,12 +11021,12 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				  &gso_partial_features);
 
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->features |= NETIF_F_GSO_PARTIAL;
+	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev->features |= gso_partial_features;
 
 	if (hw->mac.type >= ixgbe_mac_82599EB) {
-		netdev->features |= NETIF_F_SCTP_CRC;
-		netdev->features |= NETIF_F_GSO_UDP_L4;
+		netdev_active_feature_add(netdev, NETIF_F_SCTP_CRC_BIT);
+		netdev_active_feature_add(netdev, NETIF_F_GSO_UDP_L4_BIT);
 	}
 
 #ifdef CONFIG_IXGBE_IPSEC
@@ -11038,14 +11038,14 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_set_array(netdev, &ixgbe_hw_feature_set);
 
 	if (hw->mac.type >= ixgbe_mac_82599EB) {
-		netdev->hw_features |= NETIF_F_NTUPLE;
-		netdev->hw_features |= NETIF_F_HW_TC;
+		netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 	}
 
-	netdev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev->vlan_features |= netdev->features;
-	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
+	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 	netdev->hw_enc_features |= netdev->vlan_features;
 	netdev_mpls_features_set_array(netdev, &ixgbe_mpls_feature_set);
 	netdev->mpls_features |= gso_partial_features;
@@ -11084,9 +11084,9 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 #endif /* IXGBE_FCOE */
 	if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)
-		netdev->hw_features |= NETIF_F_LRO;
+		netdev_hw_feature_add(netdev, NETIF_F_LRO_BIT);
 	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
-		netdev->features |= NETIF_F_LRO;
+		netdev_active_feature_add(netdev, NETIF_F_LRO_BIT);
 
 	if (ixgbe_check_fw_error(adapter)) {
 		err = -EIO;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index db20be0b4fb1..79d2400b03df 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4633,14 +4633,14 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_features_set_array(&ixgbevf_gso_partial_feature_set,
 				  &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
-	netdev->hw_features |= NETIF_F_GSO_PARTIAL;
+	netdev_hw_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev->hw_features |= gso_partial_features;
 
 	netdev->features = netdev->hw_features;
-	netdev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev->vlan_features |= netdev->features;
-	netdev->vlan_features |= NETIF_F_TSO_MANGLEID;
+	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 
 	netdev_mpls_features_set_array(netdev, &ixgbevf_mpls_feature_set);
 	netdev->mpls_features |= gso_partial_features;
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 96f2402f6cb4..fbc3467a36ce 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2979,7 +2979,7 @@ jme_init_one(struct pci_dev *pdev,
 	netdev_active_features_zero(netdev);
 	netdev_active_features_set_array(netdev, &jme_feature_set);
 	if (using_dac)
-		netdev->features	|=	NETIF_F_HIGHDMA;
+		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	/* MTU range: 1280 - 9202*/
 	netdev->min_mtu = IPV6_MIN_MTU;
@@ -3042,7 +3042,7 @@ jme_init_one(struct pci_dev *pdev,
 	jme->reg_gpreg1 = GPREG1_DEFAULT;
 
 	if (jme->reg_rxmcs & RXMCS_CHECKSUM)
-		netdev->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
 	/*
 	 * Get Max Read Req Size from PCI Config Space
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index e43fa3a2af17..b91318551538 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -3210,7 +3210,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 	netdev_active_features_set_array(dev, &mv643xx_feature_set);
 	dev->vlan_features = dev->features;
 
-	dev->features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	dev->hw_features = dev->features;
 
 	dev->priv_flags |= IFF_UNICAST_FLT;
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 8aa5dd6cce91..ce17ed4b8828 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -6859,13 +6859,13 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 	netdev_features_zero(&features);
 	netdev_features_set_array(&mvpp2_feature_set, &features);
 	dev->features = features;
-	dev->features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	dev->hw_features |= features;
 	netdev_hw_features_set_array(dev, &mvpp2_hw_feature_set);
 
 	if (mvpp22_rss_is_supported(port)) {
-		dev->hw_features |= NETIF_F_RXHASH;
-		dev->features |= NETIF_F_NTUPLE;
+		netdev_hw_feature_add(dev, NETIF_F_RXHASH_BIT);
+		netdev_active_feature_add(dev, NETIF_F_NTUPLE_BIT);
 	}
 
 	if (!port->priv->percpu_pools)
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index 42973668ca53..bde76afe991d 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -1066,7 +1066,7 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netif_carrier_off(netdev);
 
 	netdev_hw_features_zero(netdev);
-	netdev->hw_features |= NETIF_F_SG;
+	netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
 	netdev->features |= netdev->hw_features;
 	netdev->min_mtu = OCTEP_MIN_MTU;
 	netdev->max_mtu = OCTEP_MAX_MTU;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 888fb6dde97b..fc61e17b300f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1858,7 +1858,7 @@ static netdev_features_t otx2_fix_features(struct net_device *dev,
 					   netdev_features_t features)
 {
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
-		features |= NETIF_F_HW_VLAN_STAG_RX;
+		netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_STAG_RX;
 
@@ -2712,7 +2712,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto err_ptp_destroy;
 
 	if (pf->flags & OTX2_FLAG_NTUPLE_SUPPORT)
-		netdev->hw_features |= NETIF_F_NTUPLE;
+		netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
 
 	if (pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT)
 		netdev->priv_flags |= IFF_UNICAST_FLT;
@@ -2726,10 +2726,10 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	/* HW supports tc offload but mutually exclusive with n-tuple filters */
 	if (pf->flags & OTX2_FLAG_TC_FLOWER_SUPPORT)
-		netdev->hw_features |= NETIF_F_HW_TC;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 
-	netdev->hw_features |= NETIF_F_LOOPBACK;
-	netdev->hw_features |= NETIF_F_RXALL;
+	netdev_hw_feature_add(netdev, NETIF_F_LOOPBACK_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
 
 	netif_set_tso_max_segs(netdev, OTX2_MAX_GSO_SEGS);
 	netdev->watchdog_timeo = OTX2_TX_TIMEOUT;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 9aa8fe79bb2b..d75a09f291b0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -656,9 +656,9 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	netdev->hw_features  |= netdev_tx_vlan_features;
 	netdev->features |= netdev->hw_features;
 
-	netdev->hw_features |= NETIF_F_NTUPLE;
-	netdev->hw_features |= NETIF_F_RXALL;
-	netdev->hw_features |= NETIF_F_HW_TC;
+	netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 
 	netif_set_tso_max_segs(netdev, OTX2_MAX_GSO_SEGS);
 	netdev->watchdog_timeo = OTX2_TX_TIMEOUT;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c
index 23dde8129492..29e0e30c252b 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
@@ -6,6 +6,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/netdev_features.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of.h>
 #include <linux/of_net.h>
 #include <linux/if_vlan.h>
@@ -622,8 +623,8 @@ static int prestera_port_create(struct prestera_switch *sw, u32 id)
 	if (err)
 		goto err_dl_port_register;
 
-	dev->features |= NETIF_F_NETNS_LOCAL;
-	dev->features |= NETIF_F_HW_TC;
+	netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
+	netdev_active_feature_add(dev, NETIF_F_HW_TC_BIT);
 	dev->netdev_ops = &prestera_netdev_ops;
 	dev->ethtool_ops = &prestera_ethtool_ops;
 	SET_NETDEV_DEV(dev, sw->dev->dev);
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 8bdac1c90c0c..9f16ade3e439 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3834,7 +3834,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 	dev->max_mtu = ETH_JUMBO_MTU;
 
 	if (highmem)
-		dev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	skge = netdev_priv(dev);
 	netif_napi_add(dev, &skge->napi, skge_poll, NAPI_POLL_WEIGHT);
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 98574f083375..01e9893f73bb 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4326,7 +4326,7 @@ static netdev_features_t sky2_fix_features(struct net_device *dev,
 	     !(features & NETIF_F_RXCSUM) &&
 	     (sky2->hw->flags & SKY2_HW_RSS_CHKSUM)) {
 		netdev_info(dev, "receive hashing forces receive checksum\n");
-		features |= NETIF_F_RXCSUM;
+		netdev_feature_add(NETIF_F_RXCSUM_BIT, &features);
 	}
 
 	return features;
@@ -4626,7 +4626,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 	/* Auto speed and flow control */
 	sky2->flags = SKY2_FLAG_AUTO_SPEED | SKY2_FLAG_AUTO_PAUSE;
 	if (hw->chip_id != CHIP_ID_YUKON_XL)
-		dev->hw_features |= NETIF_F_RXCSUM;
+		netdev_hw_feature_add(dev, NETIF_F_RXCSUM_BIT);
 
 	sky2->flow_mode = FC_BOTH;
 
@@ -4648,11 +4648,11 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 	netdev_hw_features_set_array(dev, &sky2_hw_feature_set);
 
 	if (highmem)
-		dev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	/* Enable receive hashing unless hardware is known broken */
 	if (!(hw->flags & SKY2_HW_RSS_BROKEN))
-		dev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(dev, NETIF_F_RXHASH_BIT);
 
 	if (!(hw->flags & SKY2_HW_VLAN_BROKEN)) {
 		dev->hw_features |= netdev_ctag_vlan_offload_features;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index e412cc11ed58..0043f387449f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2716,7 +2716,7 @@ static netdev_features_t mtk_fix_features(struct net_device *dev,
 		if (ip_cnt) {
 			netdev_info(dev, "RX flow is programmed, LRO should keep on\n");
 
-			features |= NETIF_F_LRO;
+			netdev_feature_add(NETIF_F_LRO_BIT, &features);
 		}
 	}
 
@@ -3897,7 +3897,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 
 	eth->netdev[id]->hw_features = *eth->soc->hw_features;
 	if (eth->hwlro)
-		eth->netdev[id]->hw_features |= NETIF_F_LRO;
+		netdev_hw_feature_add(eth->netdev[id], NETIF_F_LRO_BIT);
 
 	eth->netdev[id]->vlan_features = *eth->soc->hw_features &
 		~netdev_ctag_vlan_offload_features;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 5791f48367ef..080b5450e3a8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2508,7 +2508,7 @@ static netdev_features_t mlx4_en_fix_features(struct net_device *netdev,
 	 */
 	if (features & NETIF_F_HW_VLAN_CTAG_RX &&
 	    !(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN))
-		features |= NETIF_F_HW_VLAN_STAG_RX;
+		netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT, &features);
 	else
 		features &= ~NETIF_F_HW_VLAN_STAG_RX;
 
@@ -3368,7 +3368,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 		netdev_hw_features_set_array(dev, &mlx4_gso_feature_set);
 		netdev_active_features_set_array(dev, &mlx4_gso_feature_set);
 		netdev_gso_partial_features_zero(dev);
-		dev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_gso_partial_feature_add(dev, NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 		netdev_hw_enc_features_zero(dev);
 		netdev_hw_enc_features_set_array(dev, &mlx4_hw_enc_feature_set);
 
@@ -3383,9 +3383,10 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	netdev_hw_features_set_array(dev, &mlx4_hw_feature_set3);
 
 	if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN)) {
-		dev->features |= NETIF_F_HW_VLAN_STAG_RX;
-		dev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
-		dev->hw_features |= NETIF_F_HW_VLAN_STAG_RX;
+		netdev_active_feature_add(dev, NETIF_F_HW_VLAN_STAG_RX_BIT);
+		netdev_active_feature_add(dev,
+					  NETIF_F_HW_VLAN_STAG_FILTER_BIT);
+		netdev_hw_feature_add(dev, NETIF_F_HW_VLAN_STAG_RX_BIT);
 	}
 
 	if (mlx4_is_slave(mdev->dev)) {
@@ -3394,7 +3395,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 
 		err = get_phv_bit(mdev->dev, port, &phv);
 		if (!err && phv) {
-			dev->hw_features |= NETIF_F_HW_VLAN_STAG_TX;
+			netdev_hw_feature_add(dev,
+					      NETIF_F_HW_VLAN_STAG_TX_BIT);
 			priv->pflags |= MLX4_EN_PRIV_FLAGS_PHV;
 		}
 		err = mlx4_get_is_vlan_offload_disabled(mdev->dev, port,
@@ -3407,19 +3409,20 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 		if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN &&
 		    !(mdev->dev->caps.flags2 &
 		      MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN))
-			dev->hw_features |= NETIF_F_HW_VLAN_STAG_TX;
+			netdev_hw_feature_add(dev,
+					      NETIF_F_HW_VLAN_STAG_TX_BIT);
 	}
 
 	if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP)
-		dev->hw_features |= NETIF_F_RXFCS;
+		netdev_hw_feature_add(dev, NETIF_F_RXFCS_BIT);
 
 	if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_IGNORE_FCS)
-		dev->hw_features |= NETIF_F_RXALL;
+		netdev_hw_feature_add(dev, NETIF_F_RXALL_BIT);
 
 	if (mdev->dev->caps.steering_mode ==
 	    MLX4_STEERING_MODE_DEVICE_MANAGED &&
 	    mdev->dev->caps.dmfs_high_steer_mode != MLX4_STEERING_DMFS_A0_STATIC)
-		dev->hw_features |= NETIF_F_NTUPLE;
+		netdev_hw_feature_add(dev, NETIF_F_NTUPLE_BIT);
 
 	if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
 		dev->priv_flags |= IFF_UNICAST_FLT;
@@ -3559,7 +3562,8 @@ int mlx4_en_reset_config(struct net_device *dev,
 
 	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
 		if (features & NETIF_F_HW_VLAN_CTAG_RX)
-			dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+			netdev_active_feature_add(dev,
+						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 		else
 			dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 	} else if (ts_config.rx_filter == HWTSTAMP_FILTER_NONE) {
@@ -3567,14 +3571,15 @@ int mlx4_en_reset_config(struct net_device *dev,
 		 * to the latest wanted state
 		 */
 		if (dev->wanted_features & NETIF_F_HW_VLAN_CTAG_RX)
-			dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+			netdev_active_feature_add(dev,
+						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 		else
 			dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 	}
 
 	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_RXFCS_BIT)) {
 		if (features & NETIF_F_RXFCS)
-			dev->features |= NETIF_F_RXFCS;
+			netdev_active_feature_add(dev, NETIF_F_RXFCS_BIT);
 		else
 			dev->features &= ~NETIF_F_RXFCS;
 	}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
index 2a8fd7020622..12b6101a50d2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
@@ -448,25 +448,25 @@ void mlx5e_ipsec_build_netdev(struct mlx5e_priv *priv)
 
 	mlx5_core_info(mdev, "mlx5e: IPSec ESP acceleration enabled\n");
 	netdev->xfrmdev_ops = &mlx5e_ipsec_xfrmdev_ops;
-	netdev->features |= NETIF_F_HW_ESP;
-	netdev->hw_enc_features |= NETIF_F_HW_ESP;
+	netdev_active_feature_add(netdev, NETIF_F_HW_ESP_BIT);
+	netdev_hw_enc_feature_add(netdev, NETIF_F_HW_ESP_BIT);
 
 	if (!MLX5_CAP_ETH(mdev, swp_csum)) {
 		mlx5_core_dbg(mdev, "mlx5e: SWP checksum not supported\n");
 		return;
 	}
 
-	netdev->features |= NETIF_F_HW_ESP_TX_CSUM;
-	netdev->hw_enc_features |= NETIF_F_HW_ESP_TX_CSUM;
+	netdev_active_feature_add(netdev, NETIF_F_HW_ESP_TX_CSUM_BIT);
+	netdev_hw_enc_feature_add(netdev, NETIF_F_HW_ESP_TX_CSUM_BIT);
 
 	if (!MLX5_CAP_ETH(mdev, swp_lso)) {
 		mlx5_core_dbg(mdev, "mlx5e: ESP LSO not supported\n");
 		return;
 	}
 
-	netdev->gso_partial_features |= NETIF_F_GSO_ESP;
+	netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_ESP_BIT);
 	mlx5_core_dbg(mdev, "mlx5e: ESP GSO capability turned on\n");
-	netdev->features |= NETIF_F_GSO_ESP;
-	netdev->hw_features |= NETIF_F_GSO_ESP;
-	netdev->hw_enc_features |= NETIF_F_GSO_ESP;
+	netdev_active_feature_add(netdev, NETIF_F_GSO_ESP_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_GSO_ESP_BIT);
+	netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_ESP_BIT);
 }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
index 30a70d139046..885c85dbfe73 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
@@ -101,12 +101,12 @@ void mlx5e_ktls_build_netdev(struct mlx5e_priv *priv)
 		return;
 
 	if (mlx5e_is_ktls_tx(mdev)) {
-		netdev->hw_features |= NETIF_F_HW_TLS_TX;
-		netdev->features    |= NETIF_F_HW_TLS_TX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TLS_TX_BIT);
+		netdev_active_feature_add(netdev, NETIF_F_HW_TLS_TX_BIT);
 	}
 
 	if (mlx5e_is_ktls_rx(mdev))
-		netdev->hw_features |= NETIF_F_HW_TLS_RX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TLS_RX_BIT);
 
 	netdev->tlsdev_ops = &mlx5e_ktls_ops;
 }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index f702ba4da89a..ddedeac29935 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4882,22 +4882,22 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 
 	netdev->ethtool_ops	  = &mlx5e_ethtool_ops;
 
-	netdev->vlan_features    |= NETIF_F_SG;
-	netdev->vlan_features    |= NETIF_F_HW_CSUM;
-	netdev->vlan_features    |= NETIF_F_GRO;
-	netdev->vlan_features    |= NETIF_F_TSO;
-	netdev->vlan_features    |= NETIF_F_TSO6;
-	netdev->vlan_features    |= NETIF_F_RXCSUM;
-	netdev->vlan_features    |= NETIF_F_RXHASH;
-	netdev->vlan_features    |= NETIF_F_GSO_PARTIAL;
-
-	netdev->mpls_features    |= NETIF_F_SG;
-	netdev->mpls_features    |= NETIF_F_HW_CSUM;
-	netdev->mpls_features    |= NETIF_F_TSO;
-	netdev->mpls_features    |= NETIF_F_TSO6;
-
-	netdev->hw_enc_features  |= NETIF_F_HW_VLAN_CTAG_TX;
-	netdev->hw_enc_features  |= NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_vlan_feature_add(netdev, NETIF_F_SG_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_GRO_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_TSO_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_TSO6_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_RXCSUM_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_RXHASH_BIT);
+	netdev_vlan_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
+
+	netdev_mpls_feature_add(netdev, NETIF_F_SG_BIT);
+	netdev_mpls_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
+	netdev_mpls_feature_add(netdev, NETIF_F_TSO_BIT);
+	netdev_mpls_feature_add(netdev, NETIF_F_TSO6_BIT);
+
+	netdev_hw_enc_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
+	netdev_hw_enc_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	/* Tunneled LRO is not supported in the driver, and the same RQs are
 	 * shared between inner and outer TIRs, so the driver can't disable LRO
@@ -4908,64 +4908,68 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 	    !MLX5_CAP_ETH(mdev, tunnel_lro_vxlan) &&
 	    !MLX5_CAP_ETH(mdev, tunnel_lro_gre) &&
 	    mlx5e_check_fragmented_striding_rq_cap(mdev))
-		netdev->vlan_features    |= NETIF_F_LRO;
+		netdev_vlan_feature_add(netdev, NETIF_F_LRO_BIT);
 
 	netdev->hw_features       = netdev->vlan_features;
-	netdev->hw_features      |= NETIF_F_HW_VLAN_CTAG_TX;
-	netdev->hw_features      |= NETIF_F_HW_VLAN_CTAG_RX;
-	netdev->hw_features      |= NETIF_F_HW_VLAN_CTAG_FILTER;
-	netdev->hw_features      |= NETIF_F_HW_VLAN_STAG_TX;
+	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_STAG_TX_BIT);
 
 	if (mlx5e_tunnel_any_tx_proto_supported(mdev)) {
-		netdev->hw_enc_features |= NETIF_F_HW_CSUM;
-		netdev->hw_enc_features |= NETIF_F_TSO;
-		netdev->hw_enc_features |= NETIF_F_TSO6;
-		netdev->hw_enc_features |= NETIF_F_GSO_PARTIAL;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
+		netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_BIT);
+		netdev_hw_enc_feature_add(netdev, NETIF_F_TSO6_BIT);
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	}
 
 	if (mlx5_vxlan_allowed(mdev->vxlan) || mlx5_geneve_tx_allowed(mdev)) {
-		netdev->hw_features     |= NETIF_F_GSO_UDP_TUNNEL;
-		netdev->hw_features     |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
-		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
-		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT);
+		netdev_hw_enc_feature_add(netdev,
+					  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 		netdev_gso_partial_features_zero(netdev);
-		netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
-		netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL;
-		netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_gso_partial_feature_add(netdev,
+					       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+		netdev_vlan_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT);
+		netdev_vlan_feature_add(netdev,
+					NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	}
 
 	if (mlx5e_tunnel_proto_supported_tx(mdev, IPPROTO_GRE)) {
-		netdev->hw_features     |= NETIF_F_GSO_GRE;
-		netdev->hw_features     |= NETIF_F_GSO_GRE_CSUM;
-		netdev->hw_enc_features |= NETIF_F_GSO_GRE;
-		netdev->hw_enc_features |= NETIF_F_GSO_GRE_CSUM;
-		netdev->gso_partial_features |= NETIF_F_GSO_GRE;
-		netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_GRE_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_GRE_CSUM_BIT);
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_GRE_BIT);
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_GRE_CSUM_BIT);
+		netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_GRE_BIT);
+		netdev_gso_partial_feature_add(netdev,
+					       NETIF_F_GSO_GRE_CSUM_BIT);
 	}
 
 	if (mlx5e_tunnel_proto_supported_tx(mdev, IPPROTO_IPIP)) {
-		netdev->hw_features |= NETIF_F_GSO_IPXIP4;
-		netdev->hw_features |= NETIF_F_GSO_IPXIP6;
-		netdev->hw_enc_features |= NETIF_F_GSO_IPXIP4;
-		netdev->hw_enc_features |= NETIF_F_GSO_IPXIP6;
-		netdev->gso_partial_features |= NETIF_F_GSO_IPXIP4;
-		netdev->gso_partial_features |= NETIF_F_GSO_IPXIP6;
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_IPXIP4_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_IPXIP6_BIT);
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_IPXIP4_BIT);
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_IPXIP6_BIT);
+		netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_IPXIP4_BIT);
+		netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_IPXIP6_BIT);
 	}
 
-	netdev->gso_partial_features             |= NETIF_F_GSO_UDP_L4;
-	netdev->hw_features                      |= NETIF_F_GSO_UDP_L4;
-	netdev->features                         |= NETIF_F_GSO_UDP_L4;
+	netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_UDP_L4_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_GSO_UDP_L4_BIT);
+	netdev_active_feature_add(netdev, NETIF_F_GSO_UDP_L4_BIT);
 
 	mlx5_query_port_fcs(mdev, &fcs_supported, &fcs_enabled);
 
 	if (fcs_supported)
-		netdev->hw_features |= NETIF_F_RXALL;
+		netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
 
 	if (MLX5_CAP_ETH(mdev, scatter_fcs))
-		netdev->hw_features |= NETIF_F_RXFCS;
+		netdev_hw_feature_add(netdev, NETIF_F_RXFCS_BIT);
 
 	if (mlx5_qos_is_supported(mdev))
-		netdev->hw_features |= NETIF_F_HW_TC;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 
 	netdev->features          = netdev->hw_features;
 
@@ -4982,15 +4986,15 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 	    FT_CAP(identified_miss_table_mode) &&
 	    FT_CAP(flow_table_modify)) {
 #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
-		netdev->hw_features      |= NETIF_F_HW_TC;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 #endif
 #ifdef CONFIG_MLX5_EN_ARFS
-		netdev->hw_features	 |= NETIF_F_NTUPLE;
+		netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
 #endif
 	}
 
-	netdev->features         |= NETIF_F_HIGHDMA;
-	netdev->features         |= NETIF_F_HW_VLAN_STAG_FILTER;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
+	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_STAG_FILTER_BIT);
 
 	netdev->priv_flags       |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 4c1599de652c..3ee785091aa7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -677,18 +677,18 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev,
 	netdev->watchdog_timeo    = 15 * HZ;
 
 #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
-	netdev->hw_features    |= NETIF_F_HW_TC;
+	netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 #endif
-	netdev->hw_features    |= NETIF_F_SG;
-	netdev->hw_features    |= NETIF_F_IP_CSUM;
-	netdev->hw_features    |= NETIF_F_IPV6_CSUM;
-	netdev->hw_features    |= NETIF_F_GRO;
-	netdev->hw_features    |= NETIF_F_TSO;
-	netdev->hw_features    |= NETIF_F_TSO6;
-	netdev->hw_features    |= NETIF_F_RXCSUM;
+	netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_IP_CSUM_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_IPV6_CSUM_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_GRO_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_TSO_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_TSO6_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
 	netdev->features |= netdev->hw_features;
-	netdev->features |= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(netdev, NETIF_F_NETNS_LOCAL_BIT);
 }
 
 static int mlx5e_init_rep(struct mlx5_core_dev *mdev,
@@ -1082,7 +1082,7 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
 	mlx5e_rep_neigh_init(rpriv);
 	mlx5e_rep_bridge_init(priv);
 
-	netdev->wanted_features |= NETIF_F_HW_TC;
+	netdev_wanted_feature_add(netdev, NETIF_F_HW_TC_BIT);
 
 	rtnl_lock();
 	if (netif_running(netdev))
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 07b6d0124d1a..f421f48cb135 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -6718,7 +6718,7 @@ static int __init netdev_init(struct net_device *dev)
 	 * Hardware does not really support IPv6 checksum generation, but
 	 * driver actually runs faster with this on.
 	 */
-	dev->hw_features |= NETIF_F_IPV6_CSUM;
+	netdev_hw_feature_add(dev, NETIF_F_IPV6_CSUM_BIT);
 
 	dev->features |= dev->hw_features;
 
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 2a4e49122b5c..83a3ad14c79f 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -699,7 +699,7 @@ static int myri10ge_get_firmware_capabilities(struct myri10ge_priv *mgp)
 				   &cmd, 0);
 	if (status == 0) {
 		mgp->max_tso6 = cmd.data0;
-		mgp->features |= NETIF_F_TSO6;
+		netdev_feature_add(NETIF_F_TSO6_BIT, &mgp->features);
 	}
 
 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0);
@@ -3868,13 +3868,13 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev->netdev_ops = &myri10ge_netdev_ops;
 	netdev->hw_features = mgp->features;
-	netdev->hw_features |= NETIF_F_RXCSUM;
+	netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
 	/* fake NETIF_F_HW_VLAN_CTAG_RX for good GRO performance */
-	netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	netdev->features = netdev->hw_features;
-	netdev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev->vlan_features |= mgp->features;
 	if (mgp->fw_ver_tiny < 37)
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index dba583d60d8e..a5db6ccdb2df 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -87,6 +87,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
@@ -2142,8 +2143,8 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
 	ns83820_getmac(dev, ndev);
 
 	/* Yes, we support dumb IP checksum on transmit */
-	ndev->features |= NETIF_F_SG;
-	ndev->features |= NETIF_F_IP_CSUM;
+	netdev_active_feature_add(ndev, NETIF_F_SG_BIT);
+	netdev_active_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
 
 	ndev->min_mtu = 0;
 
@@ -2155,7 +2156,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
 	if (using_dac) {
 		printk(KERN_INFO "%s: using 64 bit addressing.\n",
 			ndev->name);
-		ndev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 	}
 
 	printk(KERN_INFO "%s: ns83820 v" VERSION ": DP83820 v%u.%u: %pM io=0x%08lx irq=%d f=%s\n",
diff --git a/drivers/net/ethernet/netronome/nfp/crypto/tls.c b/drivers/net/ethernet/netronome/nfp/crypto/tls.c
index 78368e71ce83..96a7a9d69e28 100644
--- a/drivers/net/ethernet/netronome/nfp/crypto/tls.c
+++ b/drivers/net/ethernet/netronome/nfp/crypto/tls.c
@@ -587,12 +587,12 @@ int nfp_net_tls_init(struct nfp_net *nn)
 		return err;
 
 	if (nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK_RX) {
-		netdev->hw_features |= NETIF_F_HW_TLS_RX;
-		netdev->features |= NETIF_F_HW_TLS_RX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TLS_RX_BIT);
+		netdev_active_feature_add(netdev, NETIF_F_HW_TLS_RX_BIT);
 	}
 	if (nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK_TX) {
-		netdev->hw_features |= NETIF_F_HW_TLS_TX;
-		netdev->features |= NETIF_F_HW_TLS_TX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TLS_TX_BIT);
+		netdev_active_feature_add(netdev, NETIF_F_HW_TLS_TX_BIT);
 	}
 
 	netdev->tlsdev_ops = &nfp_net_tls_ops;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index a101ff30a1ae..f1f1aaacbf54 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <linux/dim.h>
 #include <linux/io-64-nonatomic-hi-lo.h>
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index e306b58b643c..0b2e6dfa0ac2 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2353,9 +2353,9 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 		netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
 	netdev_hw_features_zero(netdev);
-	netdev->hw_features |= NETIF_F_HIGHDMA;
+	netdev_hw_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 	if (nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY) {
-		netdev->hw_features |= NETIF_F_RXCSUM;
+		netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 		nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY;
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_TXCSUM) {
@@ -2363,7 +2363,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_TXCSUM;
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_GATHER) {
-		netdev->hw_features |= NETIF_F_SG;
+		netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_GATHER;
 	}
 	if ((nn->cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
@@ -2373,22 +2373,25 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 					 NFP_NET_CFG_CTRL_LSO;
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_RSS_ANY)
-		netdev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 	if (nn->cap & NFP_NET_CFG_CTRL_VXLAN) {
 		if (nn->cap & NFP_NET_CFG_CTRL_LSO) {
-			netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
-			netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
-			netdev->hw_features |= NETIF_F_GSO_PARTIAL;
+			netdev_hw_feature_add(netdev,
+					      NETIF_F_GSO_UDP_TUNNEL_BIT);
+			netdev_hw_feature_add(netdev,
+					      NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+			netdev_hw_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 
 			netdev_gso_partial_features_zero(netdev);
-			netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+			netdev_gso_partial_feature_add(netdev,
+						       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 		}
 		netdev->udp_tunnel_nic_info = &nfp_udp_tunnels;
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_VXLAN;
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_NVGRE) {
 		if (nn->cap & NFP_NET_CFG_CTRL_LSO)
-			netdev->hw_features |= NETIF_F_GSO_GRE;
+			netdev_hw_feature_add(netdev, NETIF_F_GSO_GRE_BIT);
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_NVGRE;
 	}
 	if (nn->cap & (NFP_NET_CFG_CTRL_VXLAN | NFP_NET_CFG_CTRL_NVGRE))
@@ -2397,7 +2400,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 	netdev->vlan_features = netdev->hw_features;
 
 	if (nn->cap & NFP_NET_CFG_CTRL_RXVLAN_ANY) {
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 		nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_RXVLAN_V2 ?:
 			       NFP_NET_CFG_CTRL_RXVLAN;
 	}
@@ -2405,24 +2408,25 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 		if (nn->cap & NFP_NET_CFG_CTRL_LSO2) {
 			nn_warn(nn, "Device advertises both TSO2 and TXVLAN. Refusing to enable TXVLAN.\n");
 		} else {
-			netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
+			netdev_hw_feature_add(netdev,
+					      NETIF_F_HW_VLAN_CTAG_TX_BIT);
 			nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_TXVLAN_V2 ?:
 				       NFP_NET_CFG_CTRL_TXVLAN;
 		}
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_CTAG_FILTER) {
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_CTAG_FILTER;
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_RXQINQ) {
-		netdev->hw_features |= NETIF_F_HW_VLAN_STAG_RX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_STAG_RX_BIT);
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
 	}
 
 	netdev->features = netdev->hw_features;
 
 	if (nfp_app_has_tc(nn->app) && nn->port)
-		netdev->hw_features |= NETIF_F_HW_TC;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 
 	/* C-Tag strip and S-Tag strip can't be supported simultaneously,
 	 * so enable C-Tag strip and disable S-Tag strip by default.
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 66f0a9de53ad..a193d87c7e39 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -246,14 +246,14 @@ nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
 
 	lower_features = lower_dev->features;
 	if (lower_features & netdev_ip_csum_features)
-		lower_features |= NETIF_F_HW_CSUM;
+		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &lower_features);
 
 	features = netdev_intersect_features(features, lower_features);
 	tmp = NETIF_F_SOFT_FEATURES;
-	tmp |= NETIF_F_HW_TC;
+	netdev_feature_add(NETIF_F_HW_TC_BIT, &tmp);
 	tmp &= old_features;
 	features |= tmp;
-	features |= NETIF_F_LLTX;
+	netdev_feature_add(NETIF_F_LLTX_BIT, &features);
 
 	return features;
 }
@@ -346,25 +346,26 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 		netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
 	netdev_hw_features_zero(netdev);
-	netdev->hw_features |= NETIF_F_HIGHDMA;
+	netdev_hw_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 	if (repr_cap & NFP_NET_CFG_CTRL_RXCSUM_ANY)
-		netdev->hw_features |= NETIF_F_RXCSUM;
+		netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 	if (repr_cap & NFP_NET_CFG_CTRL_TXCSUM)
 		netdev->hw_features |= netdev_ip_csum_features;
 	if (repr_cap & NFP_NET_CFG_CTRL_GATHER)
-		netdev->hw_features |= NETIF_F_SG;
+		netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
 	if ((repr_cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
 	    repr_cap & NFP_NET_CFG_CTRL_LSO2)
 		netdev->hw_features |= netdev_general_tso_features;
 	if (repr_cap & NFP_NET_CFG_CTRL_RSS_ANY)
-		netdev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 	if (repr_cap & NFP_NET_CFG_CTRL_VXLAN) {
 		if (repr_cap & NFP_NET_CFG_CTRL_LSO)
-			netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+			netdev_hw_feature_add(netdev,
+					      NETIF_F_GSO_UDP_TUNNEL_BIT);
 	}
 	if (repr_cap & NFP_NET_CFG_CTRL_NVGRE) {
 		if (repr_cap & NFP_NET_CFG_CTRL_LSO)
-			netdev->hw_features |= NETIF_F_GSO_GRE;
+			netdev_hw_feature_add(netdev, NETIF_F_GSO_GRE_BIT);
 	}
 	if (repr_cap & (NFP_NET_CFG_CTRL_VXLAN | NFP_NET_CFG_CTRL_NVGRE))
 		netdev->hw_enc_features = netdev->hw_features;
@@ -372,17 +373,18 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 	netdev->vlan_features = netdev->hw_features;
 
 	if (repr_cap & NFP_NET_CFG_CTRL_RXVLAN_ANY)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	if (repr_cap & NFP_NET_CFG_CTRL_TXVLAN_ANY) {
 		if (repr_cap & NFP_NET_CFG_CTRL_LSO2)
 			netdev_warn(netdev, "Device advertises both TSO2 and TXVLAN. Refusing to enable TXVLAN.\n");
 		else
-			netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
+			netdev_hw_feature_add(netdev,
+					      NETIF_F_HW_VLAN_CTAG_TX_BIT);
 	}
 	if (repr_cap & NFP_NET_CFG_CTRL_CTAG_FILTER)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	if (repr_cap & NFP_NET_CFG_CTRL_RXQINQ)
-		netdev->hw_features |= NETIF_F_HW_VLAN_STAG_RX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_STAG_RX_BIT);
 
 	netdev->features = netdev->hw_features;
 
@@ -393,11 +395,11 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 	netif_set_tso_max_segs(netdev, NFP_NET_LSO_MAX_SEGS);
 
 	netdev->priv_flags |= IFF_NO_QUEUE | IFF_DISABLE_NETPOLL;
-	netdev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(netdev, NETIF_F_LLTX_BIT);
 
 	if (nfp_app_has_tc(app)) {
-		netdev->features |= NETIF_F_HW_TC;
-		netdev->hw_features |= NETIF_F_HW_TC;
+		netdev_active_feature_add(netdev, NETIF_F_HW_TC_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 	}
 
 	err = nfp_app_repr_init(app, netdev);
diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c
index f70feffbf2ba..5ead88eb3385 100644
--- a/drivers/net/ethernet/ni/nixge.c
+++ b/drivers/net/ethernet/ni/nixge.c
@@ -1276,7 +1276,7 @@ static int nixge_probe(struct platform_device *pdev)
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
 	netdev_active_features_zero(ndev);
-	ndev->features |= NETIF_F_SG;
+	netdev_active_feature_add(ndev, NETIF_F_SG_BIT);
 	ndev->netdev_ops = &nixge_netdev_ops;
 	ndev->ethtool_ops = &nixge_ethtool_ops;
 
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index a8a8d59dd008..5adc4f02f36f 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4932,7 +4932,7 @@ static netdev_features_t nv_fix_features(struct net_device *dev,
 {
 	/* vlan is dependent on rx checksum offload */
 	if (features & netdev_ctag_vlan_offload_features)
-		features |= NETIF_F_RXCSUM;
+		netdev_feature_add(NETIF_F_RXCSUM_BIT, &features);
 
 	return features;
 }
@@ -5800,7 +5800,8 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 				dev_info(&pci_dev->dev,
 					 "64-bit DMA failed, using 32-bit addressing\n");
 			else
-				dev->features |= NETIF_F_HIGHDMA;
+				netdev_active_feature_add(dev,
+							  NETIF_F_HIGHDMA_BIT);
 		}
 	} else if (id->driver_data & DEV_HAS_LARGEDESC) {
 		/* packet format 2: supports jumbo frames */
@@ -5830,7 +5831,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 	dev->features |= dev->hw_features;
 
 	/* Add loopback capability to the device. */
-	dev->hw_features |= NETIF_F_LOOPBACK;
+	netdev_hw_feature_add(dev, NETIF_F_LOOPBACK_BIT);
 
 	/* MTU range: 64 - 1500 or 9100 */
 	dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 8459002574fc..2d1c6d591baa 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1502,48 +1502,49 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
 	netdev_features_set_array(&ionic_feature_set, &features);
 
 	if (lif->nxqs > 1)
-		features |= NETIF_F_RXHASH;
+		netdev_feature_add(NETIF_F_RXHASH_BIT, &features);
 
 	err = ionic_set_nic_features(lif, features);
 	if (err)
 		return err;
 
 	/* tell the netdev what we actually can support */
-	netdev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
-		netdev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
-		netdev->hw_features |= NETIF_F_SG;
+		netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
 
 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
-		netdev->hw_enc_features |= NETIF_F_HW_CSUM;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
-		netdev->hw_enc_features |= NETIF_F_RXCSUM;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TSO)
-		netdev->hw_enc_features |= NETIF_F_TSO;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
-		netdev->hw_enc_features |= NETIF_F_TSO6;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_TSO6_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
-		netdev->hw_enc_features |= NETIF_F_TSO_ECN;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_ECN_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
-		netdev->hw_enc_features |= NETIF_F_GSO_GRE;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_GRE_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
-		netdev->hw_enc_features |= NETIF_F_GSO_GRE_CSUM;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_GRE_CSUM_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
-		netdev->hw_enc_features |= NETIF_F_GSO_IPXIP4;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_IPXIP4_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
-		netdev->hw_enc_features |= NETIF_F_GSO_IPXIP6;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_IPXIP6_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
-		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT);
 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
-		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_hw_enc_feature_add(netdev,
+					  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 	netdev->hw_features |= netdev->hw_enc_features;
 	netdev->features |= netdev->hw_features;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 1c3b06599b37..b4c56b023122 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1360,22 +1360,22 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
 	netdev_hw_features_set_array(netdev, &netxen_hw_feature_set);
 
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
-		netdev->hw_features |= NETIF_F_IPV6_CSUM;
-		netdev->hw_features |= NETIF_F_TSO6;
+		netdev_hw_feature_add(netdev, NETIF_F_IPV6_CSUM_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_TSO6_BIT);
 	}
 
 	netdev->vlan_features |= netdev->hw_features;
 
 	if (adapter->pci_using_dac) {
-		netdev->features |= NETIF_F_HIGHDMA;
-		netdev->vlan_features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
+		netdev_vlan_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 	}
 
 	if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 
 	if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)
-		netdev->hw_features |= NETIF_F_LRO;
+		netdev_hw_feature_add(netdev, NETIF_F_LRO_BIT);
 
 	netdev->features |= netdev->hw_features;
 
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index b37a045f09d6..64ba47a8629b 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -884,32 +884,34 @@ static void qede_init_ndev(struct qede_dev *edev)
 	netdev_features_set_array(&qede_hw_feature_set, &hw_features);
 
 	if (edev->dev_info.common.b_arfs_capable)
-		hw_features |= NETIF_F_NTUPLE;
+		netdev_feature_add(NETIF_F_NTUPLE_BIT, &hw_features);
 
 	if (edev->dev_info.common.vxlan_enable ||
 	    edev->dev_info.common.geneve_enable)
 		udp_tunnel_enable = true;
 
 	if (udp_tunnel_enable || edev->dev_info.common.gre_enable) {
-		hw_features |= NETIF_F_TSO_ECN;
+		netdev_feature_add(NETIF_F_TSO_ECN_BIT, &hw_features);
 		netdev_hw_enc_features_zero(ndev);
 		netdev_hw_enc_features_set_array(ndev, &qede_hw_enc_feature_set);
 	}
 
 	if (udp_tunnel_enable) {
-		hw_features |= NETIF_F_GSO_UDP_TUNNEL;
-		hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
-		ndev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
-		ndev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_BIT, &hw_features);
+		netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+				   &hw_features);
+		netdev_hw_enc_feature_add(ndev, NETIF_F_GSO_UDP_TUNNEL_BIT);
+		netdev_hw_enc_feature_add(ndev,
+					  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 		qede_set_udp_tunnels(edev);
 	}
 
 	if (edev->dev_info.common.gre_enable) {
-		hw_features |= NETIF_F_GSO_GRE;
-		hw_features |= NETIF_F_GSO_GRE_CSUM;
-		ndev->hw_enc_features |= NETIF_F_GSO_GRE;
-		ndev->hw_enc_features |= NETIF_F_GSO_GRE_CSUM;
+		netdev_feature_add(NETIF_F_GSO_GRE_BIT, &hw_features);
+		netdev_feature_add(NETIF_F_GSO_GRE_CSUM_BIT, &hw_features);
+		netdev_hw_enc_feature_add(ndev, NETIF_F_GSO_GRE_BIT);
+		netdev_hw_enc_feature_add(ndev, NETIF_F_GSO_GRE_CSUM_BIT);
 	}
 
 	ndev->vlan_features = hw_features;
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index fe823b03736b..c9da4a9f204d 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -26,6 +26,7 @@
 #include <linux/if_arp.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>
@@ -3794,10 +3795,10 @@ static int ql3xxx_probe(struct pci_dev *pdev,
 
 	qdev->msg_enable = netif_msg_init(debug, default_msg);
 
-	ndev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 	if (qdev->device_id == QL3032_DEVICE_ID) {
-		ndev->features |= NETIF_F_IP_CSUM;
-		ndev->features |= NETIF_F_SG;
+		netdev_active_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
+		netdev_active_feature_add(ndev, NETIF_F_SG_BIT);
 	}
 
 	qdev->mem_map_registers = pci_ioremap_bar(pdev, 1);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 9bb1b9d53d96..fc51958cd77a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1044,12 +1044,13 @@ static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
 			if (!(offload_flags & BIT_1))
 				features &= ~NETIF_F_TSO;
 			else
-				features |= NETIF_F_TSO;
+				netdev_feature_add(NETIF_F_TSO_BIT, &features);
 
 			if (!(offload_flags & BIT_2))
 				features &= ~NETIF_F_TSO6;
 			else
-				features |= NETIF_F_TSO6;
+				netdev_feature_add(NETIF_F_TSO6_BIT,
+						   &features);
 		}
 	} else {
 		netdev_features_clear_array(&qlcnic_csum_feature_set, &features);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 4c19fc626385..d768cee19d3a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2305,16 +2305,17 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 	}
 
 	if (qlcnic_vlan_tx_check(adapter))
-		netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX);
+		netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 
 	if (qlcnic_sriov_vf_check(adapter))
-		netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_active_feature_add(netdev,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
-		netdev->features |= NETIF_F_LRO;
+		netdev_active_feature_add(netdev, NETIF_F_LRO_BIT);
 
 	if (qlcnic_encap_tx_offload(adapter)) {
-		netdev->features |= NETIF_F_GSO_UDP_TUNNEL;
+		netdev_active_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT);
 
 		/* encapsulation Tx offload supported by Adapter */
 		netdev_vlan_features_zero(netdev);
@@ -2323,7 +2324,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 	}
 
 	if (qlcnic_encap_rx_offload(adapter)) {
-		netdev->hw_enc_features |= NETIF_F_RXCSUM;
+		netdev_hw_enc_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
 		netdev->udp_tunnel_nic_info = &qlcnic_udp_tunnels;
 	}
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
index 92215121428f..3d288e1a8d46 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
@@ -237,7 +237,7 @@ void rmnet_vnd_setup(struct net_device *rmnet_dev)
 	rmnet_dev->needs_free_netdev = true;
 	rmnet_dev->ethtool_ops = &rmnet_ethtool_ops;
 
-	rmnet_dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(rmnet_dev, NETIF_F_LLTX_BIT);
 
 	/* This perm addr will be used as interface identifier by IPv6 */
 	rmnet_dev->addr_assign_type = NET_ADDR_RANDOM;
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 1a4e97594238..778c75b76950 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1978,8 +1978,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	cp->cpcmd = (pci_using_dac ? PCIDAC : 0) |
 		    PCIMulRW | RxChkSum | CpRxOn | CpTxOn;
 
-	dev->features |= NETIF_F_RXCSUM;
-	dev->hw_features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
+	netdev_hw_feature_add(dev, NETIF_F_RXCSUM_BIT);
 
 	regs = ioremap(pciaddr, CP_REGS_SIZE);
 	if (!regs) {
@@ -2007,7 +2007,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_active_features_set_array(dev, &cp_default_feature_set);
 
 	if (pci_using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	netdev_hw_features_set_array(dev, &cp_default_feature_set);
 	netdev_vlan_features_zero(dev);
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index fb4437f4ae35..7af89f43c4ca 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -1017,8 +1017,8 @@ static int rtl8139_init_one(struct pci_dev *pdev,
 	netdev_active_features_set_array(dev, &rtl8139_feature_set);
 	dev->vlan_features = dev->features;
 
-	dev->hw_features |= NETIF_F_RXALL;
-	dev->hw_features |= NETIF_F_RXFCS;
+	netdev_hw_feature_add(dev, NETIF_F_RXALL_BIT);
+	netdev_hw_feature_add(dev, NETIF_F_RXFCS_BIT);
 
 	/* MTU range: 68 - 1770 */
 	dev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index ef8b13d342f5..ded5fef309be 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5403,7 +5403,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	if (sizeof(dma_addr_t) > 4 && tp->mac_version >= RTL_GIGA_MAC_VER_18 &&
 	    !dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
-		dev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	rtl_init_rxcfg(tp);
 
@@ -5443,7 +5443,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 
 	if (rtl_chip_supports_csum_v2(tp))
-		dev->hw_features |= NETIF_F_IPV6_CSUM;
+		netdev_hw_feature_add(dev, NETIF_F_IPV6_CSUM_BIT);
 
 	dev->features |= dev->hw_features;
 
@@ -5453,19 +5453,19 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 * enable them. Use at own risk!
 	 */
 	if (rtl_chip_supports_csum_v2(tp)) {
-		dev->hw_features |= NETIF_F_SG;
+		netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
 		dev->hw_features |= netdev_general_tso_features;
 		netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2);
 		netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V2);
 	} else {
-		dev->hw_features |= NETIF_F_SG;
-		dev->hw_features |= NETIF_F_TSO;
+		netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
+		netdev_hw_feature_add(dev, NETIF_F_TSO_BIT);
 		netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V1);
 		netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V1);
 	}
 
-	dev->hw_features |= NETIF_F_RXALL;
-	dev->hw_features |= NETIF_F_RXFCS;
+	netdev_hw_feature_add(dev, NETIF_F_RXALL_BIT);
+	netdev_hw_feature_add(dev, NETIF_F_RXFCS_BIT);
 
 	/* configure chip for default features */
 	rtl8169_set_features(dev, dev->features);
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index b38f689c3683..333a6aba78a2 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -20,6 +20,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/net_tstamp.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
@@ -2617,7 +2618,7 @@ static void ravb_set_delay_mode(struct net_device *ndev)
 
 static void ravb_features_init(void)
 {
-	ravb_default_features |= NETIF_F_RXCSUM;
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, &ravb_default_features);
 }
 
 static int ravb_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index d42adef5a143..79cdd0b8d2e7 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -3293,7 +3293,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 
 	if (mdp->cd->rx_csum) {
 		netdev_active_features_zero(ndev);
-		ndev->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(ndev, NETIF_F_RXCSUM_BIT);
 		ndev->hw_features = ndev->features;
 	}
 
@@ -3346,7 +3346,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 			goto out_release;
 		}
 		mdp->port = port;
-		ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_active_feature_add(ndev,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 		/* Need to init only the first port of the two sharing a TSU */
 		if (port == 0) {
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 2a16201ce0cf..021e93a08baf 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -15,6 +15,7 @@
 #include <linux/sort.h>
 #include <linux/random.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <linux/socket.h>
 #include <linux/etherdevice.h>
@@ -2578,8 +2579,8 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
 		       NAPI_POLL_WEIGHT);
 	rocker_carrier_init(rocker_port);
 
-	dev->features |= NETIF_F_NETNS_LOCAL;
-	dev->features |= NETIF_F_SG;
+	netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
+	netdev_active_feature_add(dev, NETIF_F_SG_BIT);
 
 	/* MTU range: 68 - 9000 */
 	dev->min_mtu = ROCKER_PORT_MIN_MTU;
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 7963a9aeafe0..0a664cc7739e 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -2118,7 +2118,7 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
 	netdev_hw_features_zero(ndev);
 	netdev_hw_features_set_array(ndev, &sxgbe_hw_feature_set);
 	ndev->features |= ndev->hw_features;
-	ndev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 	ndev->watchdog_timeo = msecs_to_jiffies(TX_TIMEO);
 
 	/* assign filtering support */
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 2f908bf1f019..2e0a096b5967 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)
@@ -1367,7 +1367,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 a19a8df568f9..f40766137540 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -207,7 +207,8 @@ 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 9aae0d8b713f..4a3cbc1c50ec 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 4c802cd087fc..9feb3295ccaa 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1018,7 +1018,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;
@@ -1079,7 +1079,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
 	*probe_ptr = probe_data;
 	efx->net_dev = 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 0b6dbd33410e..6fab0c10b78d 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2885,7 +2885,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);
@@ -2908,8 +2908,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/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index 6887ba4c9806..4a3d2be92a12 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -1000,7 +1000,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;
@@ -1051,7 +1051,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/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c
index c3aead3d052b..b3e9c5125195 100644
--- a/drivers/net/ethernet/socionext/sni_ave.c
+++ b/drivers/net/ethernet/socionext/sni_ave.c
@@ -15,6 +15,7 @@
 #include <linux/mii.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of_net.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
@@ -1594,10 +1595,10 @@ static int ave_probe(struct platform_device *pdev)
 	ndev->ethtool_ops = &ave_ethtool_ops;
 	SET_NETDEV_DEV(ndev, dev);
 
-	ndev->features    |= NETIF_F_IP_CSUM;
-	ndev->features    |= NETIF_F_RXCSUM;
-	ndev->hw_features |= NETIF_F_IP_CSUM;
-	ndev->hw_features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
+	netdev_active_feature_add(ndev, NETIF_F_RXCSUM_BIT);
+	netdev_hw_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
+	netdev_hw_feature_add(ndev, NETIF_F_RXCSUM_BIT);
 
 	ndev->max_mtu = AVE_MAX_ETHFRAME - (ETH_HLEN + ETH_FCS_LEN);
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 8f227d5f2199..c85941528096 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7144,19 +7144,19 @@ int stmmac_dvr_probe(struct device *device,
 
 	ret = stmmac_tc_init(priv, priv);
 	if (!ret) {
-		ndev->hw_features |= NETIF_F_HW_TC;
+		netdev_hw_feature_add(ndev, NETIF_F_HW_TC_BIT);
 	}
 
 	if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
 		ndev->hw_features |= netdev_general_tso_features;
 		if (priv->plat->has_gmac4)
-			ndev->hw_features |= NETIF_F_GSO_UDP_L4;
+			netdev_hw_feature_add(ndev, NETIF_F_GSO_UDP_L4_BIT);
 		priv->tso = true;
 		dev_info(priv->device, "TSO feature enabled\n");
 	}
 
 	if (priv->dma_cap.sphen && !priv->plat->sph_disable) {
-		ndev->hw_features |= NETIF_F_GRO;
+		netdev_hw_feature_add(ndev, NETIF_F_GRO_BIT);
 		priv->sph_cap = true;
 		priv->sph = priv->sph_cap;
 		dev_info(priv->device, "SPH feature enabled\n");
@@ -7195,7 +7195,7 @@ int stmmac_dvr_probe(struct device *device,
 	}
 
 	ndev->features |= ndev->hw_features;
-	ndev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
 #ifdef STMMAC_VLAN_TAG_USED
 	/* Both mac100 and gmac support receive VLAN tag detection */
@@ -7203,9 +7203,10 @@ int stmmac_dvr_probe(struct device *device,
 	if (priv->dma_cap.vlhash)
 		ndev->features |= netdev_vlan_filter_features;
 	if (priv->dma_cap.vlins) {
-		ndev->features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 		if (priv->dma_cap.dvlan)
-			ndev->features |= NETIF_F_HW_VLAN_STAG_TX;
+			netdev_active_feature_add(ndev,
+						  NETIF_F_HW_VLAN_STAG_TX_BIT);
 	}
 #endif
 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
@@ -7217,7 +7218,7 @@ int stmmac_dvr_probe(struct device *device,
 		priv->rss.table[i] = ethtool_rxfh_indir_default(i, rxq);
 
 	if (priv->dma_cap.rssen && priv->plat->rss_en)
-		ndev->features |= NETIF_F_RXHASH;
+		netdev_active_feature_add(ndev, NETIF_F_RXHASH_BIT);
 
 	/* MTU range: 46 - hw-specific max */
 	ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index bf899125b1ef..d77aa6dd6931 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -71,6 +71,7 @@
 #include <linux/dma-mapping.h>
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -5057,11 +5058,11 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	/* Cassini features. */
 	if ((cp->cas_flags & CAS_FLAG_NO_HW_CSUM) == 0) {
-		dev->features |= NETIF_F_HW_CSUM;
-		dev->features |= NETIF_F_SG;
+		netdev_active_feature_add(dev, NETIF_F_HW_CSUM_BIT);
+		netdev_active_feature_add(dev, NETIF_F_SG_BIT);
 	}
 
-	dev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	/* MTU range: 60 - varies or 9000 */
 	dev->min_mtu = CAS_MIN_MTU;
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index 6a37026e02b6..41398fa580c2 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9744,7 +9744,7 @@ static void niu_set_basic_features(struct net_device *dev)
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_array(dev, &niu_hw_feature_set);
 	dev->features |= dev->hw_features;
-	dev->features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 }
 
 static int niu_pci_init_one(struct pci_dev *pdev,
@@ -9810,7 +9810,7 @@ static int niu_pci_init_one(struct pci_dev *pdev,
 
 	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
 	if (!err)
-		dev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (err) {
 		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
 		if (err) {
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 42a7a6a5926f..ef90119e1636 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -2999,7 +2999,7 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_set_array(dev, &gem_hw_feature_set);
 	dev->features = dev->hw_features;
 	if (pci_using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	/* MTU range: 68 - 1500 (Jumbo mode is broken) */
 	dev->min_mtu = GEM_MIN_MTU;
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index f9fcca2adcf4..5eaf7c40a0ad 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2786,10 +2786,10 @@ static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
 
 	/* Happy Meal can do it all... */
 	netdev_hw_features_zero(dev);
-	dev->hw_features |= NETIF_F_SG;
-	dev->hw_features |= NETIF_F_HW_CSUM;
+	netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
+	netdev_hw_feature_add(dev, NETIF_F_HW_CSUM_BIT);
 	dev->features |= dev->hw_features;
-	dev->features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 
 	hp->irq = op->archdata.irqs[0];
 
@@ -3109,10 +3109,10 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
 
 	/* Happy Meal can do it all... */
 	netdev_hw_features_zero(dev);
-	dev->hw_features |= NETIF_F_SG;
-	dev->hw_features |= NETIF_F_HW_CSUM;
+	netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
+	netdev_hw_feature_add(dev, NETIF_F_HW_CSUM_BIT);
 	dev->features |= dev->hw_features;
-	dev->features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
 	/* Hook up PCI register/descriptor accessors. */
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
index 68b4bc10c8a9..f15e8768526d 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
@@ -180,27 +180,27 @@ static int xlgmac_init(struct xlgmac_pdata *pdata)
 	/* Set device features */
 	if (pdata->hw_feat.tso) {
 		netdev->hw_features = netdev_general_tso_features;
-		netdev->hw_features |= NETIF_F_SG;
+		netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
 		netdev->hw_features |= netdev_ip_csum_features;
 	} else if (pdata->hw_feat.tx_coe) {
 		netdev->hw_features = netdev_ip_csum_features;
 	}
 
 	if (pdata->hw_feat.rx_coe) {
-		netdev->hw_features |= NETIF_F_RXCSUM;
-		netdev->hw_features |= NETIF_F_GRO;
+		netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_GRO_BIT);
 	}
 
 	if (pdata->hw_feat.rss)
-		netdev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 
 	netdev->vlan_features |= netdev->hw_features;
 
-	netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	if (pdata->hw_feat.sa_vlan_ins)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 	if (pdata->hw_feat.vlhash)
-		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	netdev->features |= netdev->hw_features;
 	pdata->netdev_features = netdev->features;
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac.h b/drivers/net/ethernet/synopsys/dwc-xlgmac.h
index a848e10f3ea4..baab47cb15aa 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac.h
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac.h
@@ -20,6 +20,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/workqueue.h>
 #include <linux/phy.h>
 #include <linux/if_vlan.h>
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index fd89439791ce..839e169c607d 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -2032,7 +2032,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		 * set multicast list callback has to use priv->tx_lock.
 		 */
 #ifdef BDX_LLTX
-		ndev->features |= NETIF_F_LLTX;
+		netdev_active_feature_add(ndev, NETIF_F_LLTX_BIT);
 #endif
 		/* MTU range: 60 - 16384 */
 		ndev->min_mtu = ETH_ZLEN;
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 2347a3df30cd..fb32c1f045e6 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1976,8 +1976,8 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 	netdev_hw_features_zero(port->ndev);
 	netdev_hw_features_set_array(port->ndev, &am65_cpsw_hw_feature_set);
 	port->ndev->features = port->ndev->hw_features;
-	port->ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-	port->ndev->vlan_features |=  NETIF_F_SG;
+	netdev_active_feature_add(port->ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+	netdev_vlan_feature_add(port->ndev, NETIF_F_SG_BIT);
 	port->ndev->netdev_ops = &am65_cpsw_nuss_netdev_ops;
 	port->ndev->ethtool_ops = &am65_cpsw_ethtool_ops_slave;
 
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 7e12c6a77d30..0f8f7b1bf841 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -17,6 +17,7 @@
 #include <linux/if_ether.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/phy/phy.h>
@@ -1456,8 +1457,8 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
 
 	priv_sl2->emac_port = 1;
 	cpsw->slaves[1].ndev = ndev;
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+	netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_ops;
@@ -1634,8 +1635,8 @@ static int cpsw_probe(struct platform_device *pdev)
 
 	cpsw->slaves[0].ndev = ndev;
 
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+	netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_ops;
diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c
index b15d44261e76..9a513869ab66 100644
--- a/drivers/net/ethernet/ti/netcp_core.c
+++ b/drivers/net/ethernet/ti/netcp_core.c
@@ -1975,10 +1975,10 @@ static int netcp_create_interface(struct netcp_device *netcp_device,
 		return -ENOMEM;
 	}
 
-	ndev->features |= NETIF_F_SG;
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_active_feature_add(ndev, NETIF_F_SG_BIT);
+	netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	ndev->hw_features = ndev->features;
-	ndev->vlan_features |=  NETIF_F_SG;
+	netdev_vlan_feature_add(ndev, NETIF_F_SG_BIT);
 
 	/* MTU range: 68 - 9486 */
 	ndev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 45c0cb3c9a48..78c817b3e88c 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -1462,13 +1462,13 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
 	u64 v1, v2;
 
 	netdev_hw_features_zero(netdev);
-	netdev->hw_features |= NETIF_F_IP_CSUM;
-	netdev->hw_features |= NETIF_F_RXCSUM;
+	netdev_hw_feature_add(netdev, NETIF_F_IP_CSUM_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
 	netdev_active_features_zero(netdev);
-	netdev->features |= NETIF_F_IP_CSUM;
+	netdev_active_feature_add(netdev, NETIF_F_IP_CSUM_BIT);
 	if (GELIC_CARD_RX_CSUM_DEFAULT)
-		netdev->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
 	status = lv1_net_control(bus_id(card), dev_id(card),
 				 GELIC_LV1_GET_MAC_ADDRESS,
@@ -1488,7 +1488,7 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
 		 * As vlan is internally used,
 		 * we can not receive vlan packets
 		 */
-		netdev->features |= NETIF_F_VLAN_CHALLENGED;
+		netdev_active_feature_add(netdev, NETIF_F_VLAN_CHALLENGED_BIT);
 	}
 
 	/* MTU range: 64 - 1518 */
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index 03dc5fb10a2b..6267c414d356 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -2276,12 +2276,12 @@ spider_net_setup_netdev(struct spider_net_card *card)
 	spider_net_setup_netdev_ops(netdev);
 
 	netdev_hw_features_zero(netdev);
-	netdev->hw_features |= NETIF_F_RXCSUM;
-	netdev->hw_features |= NETIF_F_IP_CSUM;
+	netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
+	netdev_hw_feature_add(netdev, NETIF_F_IP_CSUM_BIT);
 	if (SPIDER_NET_RX_CSUM_DEFAULT)
-		netdev->features |= NETIF_F_RXCSUM;
-	netdev->features |= NETIF_F_IP_CSUM;
-	netdev->features |= NETIF_F_LLTX;
+		netdev_active_feature_add(netdev, NETIF_F_RXCSUM_BIT);
+	netdev_active_feature_add(netdev, NETIF_F_IP_CSUM_BIT);
+	netdev_active_feature_add(netdev, NETIF_F_LLTX_BIT);
 	/* some time: NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
 	 *		NETIF_F_HW_VLAN_CTAG_FILTER
 	 */
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index 785f4f3bd0ee..4cdb0ee494ad 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1611,7 +1611,7 @@ tsi108_init_one(struct platform_device *pdev)
 	 */
 
 	netdev_active_features_zero(dev);
-	dev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	spin_lock_init(&data->txlock);
 	spin_lock_init(&data->misclock);
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 3c8631f9925d..adc8a3de10ff 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -99,6 +99,7 @@ static const int multicast_filter_limit = 32;
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
@@ -968,8 +969,8 @@ static int rhine_init_one_common(struct device *hwdev, u32 quirks,
 	netif_napi_add(dev, &rp->napi, rhine_napipoll, 64);
 
 	if (rp->quirks & rqRhineI) {
-		dev->features |= NETIF_F_SG;
-		dev->features |= NETIF_F_HW_CSUM;
+		netdev_active_feature_add(dev, NETIF_F_SG_BIT);
+		netdev_active_feature_add(dev, NETIF_F_HW_CSUM_BIT);
 	}
 
 	if (rp->quirks & rqMgmt)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index d3b9f73ecba4..0b8d4fc47729 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/string.h>
 #include <linux/aer.h>
 #include <linux/etherdevice.h>
@@ -116,7 +117,7 @@ static int txgbe_probe(struct pci_dev *pdev,
 		goto err_pci_release_regions;
 	}
 
-	netdev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	pci_set_drvdata(pdev, adapter);
 
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index acd78120e53c..85bcaf07f18f 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/wiznet.h>
@@ -1138,7 +1139,7 @@ int w5100_probe(struct device *dev, const struct w5100_ops *ops,
 	/* This chip doesn't support VLAN packets with normal MTU,
 	 * so disable VLAN for this device.
 	 */
-	ndev->features |= NETIF_F_VLAN_CHALLENGED;
+	netdev_active_feature_add(ndev, NETIF_F_VLAN_CHALLENGED_BIT);
 
 	err = register_netdev(ndev);
 	if (err < 0)
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index 773f8c77909a..551ba8637843 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/wiznet.h>
@@ -608,7 +609,7 @@ static int w5300_probe(struct platform_device *pdev)
 	/* This chip doesn't support VLAN packets with normal MTU,
 	 * so disable VLAN for this device.
 	 */
-	ndev->features |= NETIF_F_VLAN_CHALLENGED;
+	netdev_active_feature_add(ndev, NETIF_F_VLAN_CHALLENGED_BIT);
 
 	err = register_netdev(ndev);
 	if (err < 0)
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index e3299bb3a1e6..d7f015b3abe4 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -1397,7 +1397,7 @@ static int temac_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, ndev);
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 	netdev_active_features_zero(ndev);
-	ndev->features |= NETIF_F_SG;
+	netdev_active_feature_add(ndev, NETIF_F_SG_BIT);
 	ndev->netdev_ops = &temac_netdev_ops;
 	ndev->ethtool_ops = &temac_ethtool_ops;
 #if 0
@@ -1483,7 +1483,7 @@ static int temac_probe(struct platform_device *pdev)
 	}
 	if (lp->temac_features & TEMAC_FEATURE_TX_CSUM)
 		/* Can checksum TCP/UDP over IPv4. */
-		ndev->features |= NETIF_F_IP_CSUM;
+		netdev_active_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
 
 	/* Defaults for IRQ delay/coalescing setup.  These are
 	 * configuration values, so does not belong in device-tree.
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index cac3437991ae..d24625640520 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1837,7 +1837,7 @@ static int axienet_probe(struct platform_device *pdev)
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 	ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
 	netdev_active_features_zero(ndev);
-	ndev->features |= NETIF_F_SG;
+	netdev_active_feature_add(ndev, NETIF_F_SG_BIT);
 	ndev->netdev_ops = &axienet_netdev_ops;
 	ndev->ethtool_ops = &axienet_ethtool_ops;
 
@@ -1903,14 +1903,14 @@ static int axienet_probe(struct platform_device *pdev)
 				XAE_FEATURE_PARTIAL_TX_CSUM;
 			lp->features |= XAE_FEATURE_PARTIAL_TX_CSUM;
 			/* Can checksum TCP/UDP over IPv4. */
-			ndev->features |= NETIF_F_IP_CSUM;
+			netdev_active_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
 			break;
 		case 2:
 			lp->csum_offload_on_tx_path =
 				XAE_FEATURE_FULL_TX_CSUM;
 			lp->features |= XAE_FEATURE_FULL_TX_CSUM;
 			/* Can checksum TCP/UDP over IPv4. */
-			ndev->features |= NETIF_F_IP_CSUM;
+			netdev_active_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
 			break;
 		default:
 			lp->csum_offload_on_tx_path = XAE_NO_CSUM_OFFLOAD;
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 5805e4a56385..9d66e24fa166 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -9,6 +9,7 @@
 #include <linux/nls.h>
 #include <linux/platform_device.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/interrupt.h>
 
 #include "fjes.h"
@@ -1351,7 +1352,7 @@ static void fjes_netdev_setup(struct net_device *netdev)
 	netdev->mtu = fjes_support_mtu[3];
 	netdev->min_mtu = fjes_support_mtu[0];
 	netdev->max_mtu = fjes_support_mtu[3];
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 }
 
 static void fjes_irq_watch_task(struct work_struct *work)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index a208e2b1a9af..a16c2d2b6e99 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -967,7 +967,7 @@ static void gtp_link_setup(struct net_device *dev)
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
 
 	dev->priv_flags	|= IFF_NO_QUEUE;
-	dev->features	|= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netif_keep_dst(dev);
 
 	dev->needed_headroom	= LL_MAX_HEADER + max_gtp_header_len;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 3b5d82b09675..70d1301d5b1b 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -460,7 +460,7 @@ static void bpq_setup(struct net_device *dev)
 
 	dev->flags      = 0;
 	netdev_active_features_zero(dev);
-	dev->features	|= NETIF_F_LLTX;	/* Allow recursion */
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);	/* Allow recursion */
 
 #if IS_ENABLED(CONFIG_AX25)
 	dev->header_ops      = &ax25_header_ops;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index b83a966b73db..72f0500ae697 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1164,7 +1164,7 @@ static void netvsc_init_settings(struct net_device *dev)
 	ndc->duplex = DUPLEX_FULL;
 
 	netdev_active_features_zero(dev);
-	dev->features |= NETIF_F_LRO;
+	netdev_active_feature_add(dev, NETIF_F_LRO_BIT);
 }
 
 static int netvsc_get_link_ksettings(struct net_device *dev,
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 456563b6b242..9729cd9c37b3 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1370,20 +1370,20 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	net_device_ctx->tx_checksum_mask = 0;
 
 	/* Compute tx offload settings based on hw capabilities */
-	net->hw_features |= NETIF_F_RXCSUM;
-	net->hw_features |= NETIF_F_SG;
-	net->hw_features |= NETIF_F_RXHASH;
+	netdev_hw_feature_add(net, NETIF_F_RXCSUM_BIT);
+	netdev_hw_feature_add(net, NETIF_F_SG_BIT);
+	netdev_hw_feature_add(net, NETIF_F_RXHASH_BIT);
 
 	if ((hwcaps.csum.ip4_txcsum & NDIS_TXCSUM_ALL_TCP4) == NDIS_TXCSUM_ALL_TCP4) {
 		/* Can checksum TCP */
-		net->hw_features |= NETIF_F_IP_CSUM;
+		netdev_hw_feature_add(net, NETIF_F_IP_CSUM_BIT);
 		net_device_ctx->tx_checksum_mask |= TRANSPORT_INFO_IPV4_TCP;
 
 		offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
 
 		if (hwcaps.lsov2.ip4_encap & NDIS_OFFLOAD_ENCAP_8023) {
 			offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
-			net->hw_features |= NETIF_F_TSO;
+			netdev_hw_feature_add(net, NETIF_F_TSO_BIT);
 
 			if (hwcaps.lsov2.ip4_maxsz < gso_max_size)
 				gso_max_size = hwcaps.lsov2.ip4_maxsz;
@@ -1396,7 +1396,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	}
 
 	if ((hwcaps.csum.ip6_txcsum & NDIS_TXCSUM_ALL_TCP6) == NDIS_TXCSUM_ALL_TCP6) {
-		net->hw_features |= NETIF_F_IPV6_CSUM;
+		netdev_hw_feature_add(net, NETIF_F_IPV6_CSUM_BIT);
 
 		offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
 		net_device_ctx->tx_checksum_mask |= TRANSPORT_INFO_IPV6_TCP;
@@ -1404,7 +1404,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 		if ((hwcaps.lsov2.ip6_encap & NDIS_OFFLOAD_ENCAP_8023) &&
 		    (hwcaps.lsov2.ip6_opts & NDIS_LSOV2_CAP_IP6) == NDIS_LSOV2_CAP_IP6) {
 			offloads.lso_v2_ipv6 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
-			net->hw_features |= NETIF_F_TSO6;
+			netdev_hw_feature_add(net, NETIF_F_TSO6_BIT);
 
 			if (hwcaps.lsov2.ip6_maxsz < gso_max_size)
 				gso_max_size = hwcaps.lsov2.ip6_maxsz;
@@ -1417,7 +1417,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	}
 
 	if (hwcaps.rsc.ip4 && hwcaps.rsc.ip6) {
-		net->hw_features |= NETIF_F_LRO;
+		netdev_hw_feature_add(net, NETIF_F_LRO_BIT);
 
 		if (net->features & NETIF_F_LRO) {
 			offloads.rsc_ip_v4 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED;
diff --git a/drivers/net/ipa/ipa_modem.c b/drivers/net/ipa/ipa_modem.c
index b7d16d16d523..a3a82aefcb69 100644
--- a/drivers/net/ipa/ipa_modem.c
+++ b/drivers/net/ipa/ipa_modem.c
@@ -225,7 +225,7 @@ static void ipa_modem_netdev_setup(struct net_device *netdev)
 	netdev->needed_tailroom = IPA_NETDEV_TAILROOM;
 	netdev->watchdog_timeo = IPA_NETDEV_TIMEOUT * HZ;
 	netdev_hw_features_zero(netdev);
-	netdev->hw_features |= NETIF_F_SG;
+	netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
 }
 
 /** ipa_modem_suspend() - suspend callback
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 41e17d737d33..35b9e9831ab8 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3456,7 +3456,7 @@ static int macsec_dev_init(struct net_device *dev)
 		dev->features = REAL_DEV_FEATURES(real_dev);
 	} else {
 		dev->features = real_dev->features & SW_MACSEC_FEATURES;
-		dev->features |= NETIF_F_LLTX;
+		netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 		dev->features |= NETIF_F_GSO_SOFTWARE;
 	}
 
@@ -3498,7 +3498,7 @@ static netdev_features_t macsec_fix_features(struct net_device *dev,
 	tmp |= NETIF_F_GSO_SOFTWARE;
 	tmp |= NETIF_F_SOFT_FEATURES;
 	features &= tmp;
-	features |= NETIF_F_LLTX;
+	netdev_feature_add(NETIF_F_LLTX_BIT, &features);
 
 	return features;
 }
@@ -4366,7 +4366,8 @@ static void __init macsec_features_init(void)
 	netdev_features_set_array(&sw_macsec_feature_set, &sw_macsec_features);
 
 	macsec_no_inherit_features = NETIF_F_VLAN_FEATURES;
-	macsec_no_inherit_features |= NETIF_F_HW_MACSEC;
+	netdev_feature_add(NETIF_F_HW_MACSEC_BIT,
+			   &macsec_no_inherit_features);
 }
 
 static int __init macsec_init(void)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index aac040522ee9..5df2989cf562 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -918,7 +918,7 @@ static int macvlan_init(struct net_device *dev)
 				  (lowerdev->state & MACVLAN_STATE_MASK);
 	dev->features 		= lowerdev->features & MACVLAN_FEATURES;
 	dev->features		|= ALWAYS_ON_FEATURES;
-	dev->hw_features	|= NETIF_F_LRO;
+	netdev_hw_feature_add(dev, NETIF_F_LRO_BIT);
 	dev->vlan_features	= lowerdev->vlan_features & MACVLAN_FEATURES;
 	dev->vlan_features	|= ALWAYS_ON_OFFLOADS;
 	dev->hw_enc_features    |= dev->features;
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index 50033364b2bd..c643e4914e8e 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -749,10 +749,10 @@ struct failover *net_failover_create(struct net_device *standby_dev)
 				       IFF_TX_SKB_SHARING);
 
 	/* don't acquire failover netdev's netif_tx_lock when transmitting */
-	failover_dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(failover_dev, NETIF_F_LLTX_BIT);
 
 	/* Don't allow failover devices to change network namespaces. */
-	failover_dev->features |= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(failover_dev, NETIF_F_NETNS_LOCAL_BIT);
 
 	failover_dev->hw_features = FAILOVER_VLAN_FEATURES |
 				    netdev_ctag_vlan_features;
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index d501c7c58f70..e0de6450d79f 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -297,7 +297,7 @@ static void nsim_setup(struct net_device *dev)
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE |
 			   IFF_NO_QUEUE;
 	netdev_active_features_set_array(dev, &nsim_feature_set);
-	dev->hw_features |= NETIF_F_HW_TC;
+	netdev_hw_feature_add(dev, NETIF_F_HW_TC_BIT);
 	dev->max_mtu = ETH_MAX_MTU;
 }
 
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index 2075e0b9f175..8abb86d9da92 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -422,7 +422,7 @@ static int ntb_netdev_probe(struct device *client_dev)
 	dev->ndev = ndev;
 	dev->pdev = pdev;
 	netdev_active_features_zero(ndev);
-	ndev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 
 	ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 9206c660a72e..3efa34e0342d 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -26,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/idr.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/poll.h>
 #include <linux/ppp_defs.h>
 #include <linux/filter.h>
@@ -1616,7 +1617,7 @@ static void ppp_setup(struct net_device *dev)
 	dev->netdev_ops = &ppp_netdev_ops;
 	SET_NETDEV_DEVTYPE(dev, &ppp_type);
 
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 
 	dev->hard_header_len = PPP_HDRLEN;
 	dev->mtu = PPP_MRU;
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 9f0175b73fd7..11b0204f070b 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -517,7 +517,7 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
 	ndev->min_mtu = ETH_MIN_MTU;
 	ndev->max_mtu = RIONET_MAX_MTU;
 	netdev_active_features_zero(ndev);
-	ndev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(ndev, NETIF_F_LLTX_BIT);
 	SET_NETDEV_DEV(ndev, &mport->dev);
 	ndev->ethtool_ops = &rionet_ethtool_ops;
 
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 496de424121e..323e4158cf4a 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -953,15 +953,18 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
 	features = tap->dev->features;
 
 	if (arg & TUN_F_CSUM) {
-		feature_mask |= NETIF_F_HW_CSUM;
+		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &feature_mask);
 
 		if (arg & (TUN_F_TSO4 | TUN_F_TSO6)) {
 			if (arg & TUN_F_TSO_ECN)
-				feature_mask |= NETIF_F_TSO_ECN;
+				netdev_feature_add(NETIF_F_TSO_ECN_BIT,
+						   &feature_mask);
 			if (arg & TUN_F_TSO4)
-				feature_mask |= NETIF_F_TSO;
+				netdev_feature_add(NETIF_F_TSO_BIT,
+						   &feature_mask);
 			if (arg & TUN_F_TSO6)
-				feature_mask |= NETIF_F_TSO6;
+				netdev_feature_add(NETIF_F_TSO6_BIT,
+						   &feature_mask);
 		}
 	}
 
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 4c999e18d4a1..e9b51c600b35 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2178,15 +2178,15 @@ static void team_setup(struct net_device *dev)
 	 */
 	dev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE;
 
-	dev->features |= NETIF_F_LLTX;
-	dev->features |= NETIF_F_GRO;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
+	netdev_active_feature_add(dev, NETIF_F_GRO_BIT);
 
 	/* Don't allow team devices to change network namespaces. */
-	dev->features |= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
 
 	dev->hw_features = TEAM_VLAN_FEATURES;
-	dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
-	dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_hw_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
+	netdev_hw_feature_add(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
 	dev->features |= dev->hw_features;
diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c
index 5fad8f09d69f..dc2b0c19b64b 100644
--- a/drivers/net/thunderbolt.c
+++ b/drivers/net/thunderbolt.c
@@ -1269,7 +1269,7 @@ static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id)
 	dev->hw_features = NETIF_F_ALL_TSO;
 	netdev_hw_features_set_array(dev, &tbnet_hw_feature_set);
 	dev->features = dev->hw_features;
-	dev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	dev->hard_header_len += sizeof(struct thunderbolt_ip_frame_header);
 
 	netif_napi_add(dev, &net->napi, tbnet_poll, NAPI_POLL_WEIGHT);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 661391e9399b..e7950125d628 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1004,7 +1004,7 @@ static int tun_net_init(struct net_device *dev)
 	dev->hw_features = TUN_USER_FEATURES;
 	netdev_hw_features_set_array(dev, &tun_hw_feature_set);
 	dev->features = dev->hw_features;
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	dev->vlan_features = dev->features & ~netdev_tx_vlan_features;
 
 	tun->flags = (tun->flags & ~TUN_FEATURES) |
@@ -2868,18 +2868,20 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
 	netdev_features_t features = netdev_empty_features;
 
 	if (arg & TUN_F_CSUM) {
-		features |= NETIF_F_HW_CSUM;
+		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &features);
 		arg &= ~TUN_F_CSUM;
 
 		if (arg & (TUN_F_TSO4|TUN_F_TSO6)) {
 			if (arg & TUN_F_TSO_ECN) {
-				features |= NETIF_F_TSO_ECN;
+				netdev_feature_add(NETIF_F_TSO_ECN_BIT,
+						   &features);
 				arg &= ~TUN_F_TSO_ECN;
 			}
 			if (arg & TUN_F_TSO4)
-				features |= NETIF_F_TSO;
+				netdev_feature_add(NETIF_F_TSO_BIT, &features);
 			if (arg & TUN_F_TSO6)
-				features |= NETIF_F_TSO6;
+				netdev_feature_add(NETIF_F_TSO6_BIT,
+						   &features);
 			arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
 		}
 
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 29451eb7263b..f063201df838 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -9,6 +9,7 @@
 
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 #include <linux/ip.h>
@@ -185,8 +186,8 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
 	dev->net->flags |= IFF_NOARP;
 
 	/* no need to put the VLAN tci in the packet headers */
-	dev->net->features |= NETIF_F_HW_VLAN_CTAG_TX;
-	dev->net->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_active_feature_add(dev->net, NETIF_F_HW_VLAN_CTAG_TX_BIT);
+	netdev_active_feature_add(dev->net, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	/* monitor VLAN additions and removals */
 	dev->net->netdev_ops = &cdc_mbim_netdev_ops;
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 1c67cfb9bdb8..d3dfd9f0fda9 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -3465,19 +3465,21 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
 	dev->net->features = netdev_empty_features;
 
 	if (DEFAULT_TX_CSUM_ENABLE)
-		dev->net->features |= NETIF_F_HW_CSUM;
+		netdev_active_feature_add(dev->net, NETIF_F_HW_CSUM_BIT);
 
 	if (DEFAULT_RX_CSUM_ENABLE)
-		dev->net->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(dev->net, NETIF_F_RXCSUM_BIT);
 
 	if (DEFAULT_TSO_CSUM_ENABLE)
 		netdev_active_features_set_array(dev->net, &lan78xx_tso_feature_set);
 
 	if (DEFAULT_VLAN_RX_OFFLOAD)
-		dev->net->features |= NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_active_feature_add(dev->net,
+					  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	if (DEFAULT_VLAN_FILTER_ENABLE)
-		dev->net->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_active_feature_add(dev->net,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	dev->net->hw_features = dev->net->features;
 
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 8aa7a0417476..0370e1fc3365 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1482,7 +1482,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
 		dev->net->features |= netdev_ip_csum_features;
 
 	if (DEFAULT_RX_CSUM_ENABLE)
-		dev->net->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(dev->net, NETIF_F_RXCSUM_BIT);
 
 	netdev_hw_features_zero(dev->net);
 	netdev_hw_features_set_array(dev->net, &smsc75xx_hw_feature_set);
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index d7c8b9d6ba29..1d6818c3d1fd 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1082,13 +1082,13 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 	 * for ipv4 packets.
 	 */
 	if (DEFAULT_TX_CSUM_ENABLE)
-		dev->net->features |= NETIF_F_IP_CSUM;
+		netdev_active_feature_add(dev->net, NETIF_F_IP_CSUM_BIT);
 	if (DEFAULT_RX_CSUM_ENABLE)
-		dev->net->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(dev->net, NETIF_F_RXCSUM_BIT);
 
 	netdev_hw_features_zero(dev->net);
-	dev->net->hw_features |= NETIF_F_IP_CSUM;
-	dev->net->hw_features |= NETIF_F_RXCSUM;
+	netdev_hw_feature_add(dev->net, NETIF_F_IP_CSUM_BIT);
+	netdev_hw_feature_add(dev->net, NETIF_F_RXCSUM_BIT);
 	set_bit(EVENT_NO_IP_ALIGN, &dev->flags);
 
 	smsc95xx_init_mac_address(dev);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 805056a246cc..7fcecff337a5 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1145,7 +1145,8 @@ static int veth_enable_xdp(struct net_device *dev)
 				/* user-space did not require GRO, but adding XDP
 				 * is supposed to get GRO working
 				 */
-				dev->features |= NETIF_F_GRO;
+				netdev_active_feature_add(dev,
+							  NETIF_F_GRO_BIT);
 				netdev_features_change(dev);
 			}
 		}
@@ -1466,7 +1467,7 @@ static netdev_features_t veth_fix_features(struct net_device *dev,
 			features &= ~NETIF_F_GSO_SOFTWARE;
 	}
 	if (priv->_xdp_prog)
-		features |= NETIF_F_GRO;
+		netdev_feature_add(NETIF_F_GRO_BIT, &features);
 
 	return features;
 }
@@ -1649,7 +1650,7 @@ static void veth_setup(struct net_device *dev)
 	dev->ethtool_ops = &veth_ethtool_ops;
 	veth_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
 	netdev_features_set_array(&veth_feature_set, &veth_features);
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	dev->features |= veth_features;
 	dev->vlan_features = dev->features & ~netdev_vlan_offload_features;
 	dev->needs_free_netdev = true;
@@ -1659,7 +1660,7 @@ static void veth_setup(struct net_device *dev)
 	dev->hw_features = veth_features;
 	dev->hw_enc_features = veth_features;
 	dev->mpls_features = NETIF_F_GSO_SOFTWARE;
-	dev->mpls_features |= NETIF_F_HW_CSUM;
+	netdev_mpls_feature_add(dev, NETIF_F_HW_CSUM_BIT);
 	netif_set_tso_max_size(dev, GSO_MAX_SIZE);
 }
 
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 4fb30d9534f4..d10c1a8782cc 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3286,7 +3286,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 	if (vi->has_cvq) {
 		vi->cvq = vqs[total_vqs - 1];
 		if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
-			vi->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+			netdev_active_feature_add(vi->dev,
+						  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	}
 
 	for (i = 0; i < vi->max_queue_pairs; i++) {
@@ -3504,7 +3505,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 			   IFF_TX_SKB_NO_LINEAR;
 	dev->netdev_ops = &virtnet_netdev;
 	netdev_active_features_zero(dev);
-	dev->features |= NETIF_F_HIGHDMA;
+	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	dev->ethtool_ops = &virtnet_ethtool_ops;
 	SET_NETDEV_DEV(dev, &vdev->dev);
@@ -3512,26 +3513,26 @@ static int virtnet_probe(struct virtio_device *vdev)
 	/* Do we support "hardware" checksums? */
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
 		/* This opens up the world of extra features. */
-		dev->hw_features |= NETIF_F_HW_CSUM;
-		dev->hw_features |= NETIF_F_SG;
+		netdev_hw_feature_add(dev, NETIF_F_HW_CSUM_BIT);
+		netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
 		if (csum) {
-			dev->features |= NETIF_F_HW_CSUM;
-			dev->features |= NETIF_F_SG;
+			netdev_active_feature_add(dev, NETIF_F_HW_CSUM_BIT);
+			netdev_active_feature_add(dev, NETIF_F_SG_BIT);
 		}
 
 		if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
 			dev->hw_features |= netdev_general_tso_features;
-			dev->hw_features |= NETIF_F_TSO_ECN;
+			netdev_hw_feature_add(dev, NETIF_F_TSO_ECN_BIT);
 		}
 		/* Individual feature bits: what can host handle? */
 		if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4))
-			dev->hw_features |= NETIF_F_TSO;
+			netdev_hw_feature_add(dev, NETIF_F_TSO_BIT);
 		if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO6))
-			dev->hw_features |= NETIF_F_TSO6;
+			netdev_hw_feature_add(dev, NETIF_F_TSO6_BIT);
 		if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
-			dev->hw_features |= NETIF_F_TSO_ECN;
+			netdev_hw_feature_add(dev, NETIF_F_TSO_ECN_BIT);
 
-		dev->features |= NETIF_F_GSO_ROBUST;
+		netdev_active_feature_add(dev, NETIF_F_GSO_ROBUST_BIT);
 
 		if (gso) {
 			netdev_features_t tmp = dev->hw_features & NETIF_F_ALL_TSO;
@@ -3541,12 +3542,12 @@ static int virtnet_probe(struct virtio_device *vdev)
 		/* (!csum && gso) case will be fixed by register_netdev() */
 	}
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
-		dev->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
 	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6))
-		dev->features |= NETIF_F_GRO_HW;
+		netdev_active_feature_add(dev, NETIF_F_GRO_HW_BIT);
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS))
-		dev->hw_features |= NETIF_F_GRO_HW;
+		netdev_hw_feature_add(dev, NETIF_F_GRO_HW_BIT);
 
 	dev->vlan_features = dev->features;
 
@@ -3605,7 +3606,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 				  VIRTIO_NET_RSS_HASH_TYPE_TCP_EX |
 				  VIRTIO_NET_RSS_HASH_TYPE_UDP_EX);
 
-		dev->hw_features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(dev, NETIF_F_RXHASH_BIT);
 	}
 
 	if (vi->has_rss_hash_report)
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 9f8a074eab03..f08209bf2274 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3332,8 +3332,8 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 	netdev_hw_features_set_array(netdev, &vmxnet3_hw_feature_set);
 
 	if (VMXNET3_VERSION_GE_4(adapter)) {
-		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
-		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT);
+		netdev_hw_feature_add(netdev, NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 		netdev_hw_enc_features_zero(netdev);
 		netdev_hw_enc_features_set_array(netdev,
 						 &vmxnet3_hw_enc_feature_set);
@@ -3390,7 +3390,7 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 	netdev->vlan_features = netdev->hw_features &
 				~netdev_ctag_vlan_offload_features;
 	netdev->features = netdev->hw_features;
-	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 }
 
 
@@ -3868,8 +3868,8 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 	if (adapter->num_rx_queues > 1 &&
 	    adapter->intr.type == VMXNET3_IT_MSIX) {
 		adapter->rss = true;
-		netdev->hw_features |= NETIF_F_RXHASH;
-		netdev->features |= NETIF_F_RXHASH;
+		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
+		netdev_active_feature_add(netdev, NETIF_F_RXHASH_BIT);
 		dev_dbg(&pdev->dev, "RSS is enabled.\n");
 	} else {
 		adapter->rss = false;
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 3ed93302084a..0444dedf75e7 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -328,9 +328,11 @@ static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_feat
 		netdev_hw_enc_features_set_array(netdev,
 						 &vmxnet3_hw_enc_feature_set);
 		if (features & NETIF_F_GSO_UDP_TUNNEL)
-			netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
+			netdev_hw_enc_feature_add(netdev,
+						  NETIF_F_GSO_UDP_TUNNEL_BIT);
 		if (features & NETIF_F_GSO_UDP_TUNNEL_CSUM)
-			netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+			netdev_hw_enc_feature_add(netdev,
+						  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	}
 	if (VMXNET3_VERSION_GE_7(adapter)) {
 		unsigned long flags;
@@ -414,8 +416,8 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 	u8 udp_tun_enabled;
 
 	netdev_features_zero(&tun_offload_mask);
-	tun_offload_mask |= NETIF_F_GSO_UDP_TUNNEL;
-	tun_offload_mask |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+	netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_BIT, &tun_offload_mask);
+	netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, &tun_offload_mask);
 	udp_tun_enabled = (netdev->features & tun_offload_mask) != 0;
 
 	if (changed & NETIF_F_RXCSUM ||
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 7ad145f832cc..98ae263639fc 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1687,13 +1687,13 @@ static void vrf_setup(struct net_device *dev)
 	eth_hw_addr_random(dev);
 
 	/* don't acquire vrf device's netif_tx_lock when transmitting */
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 
 	/* don't allow vrf devices to change network namespaces. */
-	dev->features |= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
 
 	/* does not make sense for a VLAN to be added to a vrf device */
-	dev->features   |= NETIF_F_VLAN_CHALLENGED;
+	netdev_active_feature_add(dev, NETIF_F_VLAN_CHALLENGED_BIT);
 
 	/* enable offload features */
 	dev->features   |= NETIF_F_GSO_SOFTWARE;
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index f78f910e113e..3c127313fb05 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -295,7 +295,7 @@ static void wg_setup(struct net_device *dev)
 	dev->type = ARPHRD_NONE;
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
 	dev->priv_flags |= IFF_NO_QUEUE;
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	wg_netdev_features = NETIF_F_GSO_SOFTWARE;
 	netdev_features_set_array(&wg_feature_set, &wg_netdev_features);
 	dev->features |= wg_netdev_features;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 4d9cd3df3095..30748857435c 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -10213,7 +10213,7 @@ int ath10k_mac_register(struct ath10k *ar)
 
 	if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
 		netdev_features_zero(&ar->hw->netdev_features);
-		ar->hw->netdev_features |= NETIF_F_HW_CSUM;
+		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &ar->hw->netdev_features);
 	}
 
 	if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 2b78b47e0a90..277aac5fb61b 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -8897,7 +8897,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
 
 	if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
 		netdev_features_zero(&ar->hw->netdev_features);
-		ar->hw->netdev_features |= NETIF_F_HW_CSUM;
+		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &ar->hw->netdev_features);
 		ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
 		ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
 	}
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 77e052336eb5..e37020cf794b 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -19,6 +19,7 @@
 #define CORE_H
 
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/rtnetlink.h>
 #include <linux/firmware.h>
 #include <linux/sched.h>
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 8c57cd413e79..4dbfdd1a8097 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1144,7 +1144,7 @@ static int ath6kl_set_features(struct net_device *dev,
 							 ar->rx_meta_ver, 0, 0);
 		if (err) {
 			dev->features = features;
-			dev->features |= NETIF_F_RXCSUM;
+			netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 			return err;
 		}
 	}
@@ -1306,8 +1306,8 @@ void init_netdev(struct net_device *dev)
 
 	if (!test_bit(ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
 		      ar->fw_capabilities)) {
-		dev->hw_features |= NETIF_F_IP_CSUM;
-		dev->hw_features |= NETIF_F_RXCSUM;
+		netdev_hw_feature_add(dev, NETIF_F_IP_CSUM_BIT);
+		netdev_hw_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	}
 
 	return;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index bd164a0821f9..ad0d49866f38 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -7,6 +7,7 @@
 #include <linux/etherdevice.h>
 #include <linux/module.h>
 #include <linux/inetdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/property.h>
 #include <net/cfg80211.h>
 #include <net/rtnetlink.h>
@@ -605,7 +606,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
 	/* Get current TOE mode from dongle */
 	if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
 	    && (toe_ol & TOE_TX_CSUM_OL) != 0)
-		ndev->features |= NETIF_F_IP_CSUM;
+		netdev_active_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
 	else
 		ndev->features &= ~NETIF_F_IP_CSUM;
 
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
index 53c41f48ecf8..8a75c57fc000 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
@@ -99,8 +99,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
 
 	if (priv->trans->max_skb_frags) {
 		netdev_features_zero(&hw->netdev_features);
-		hw->netdev_features |= NETIF_F_HIGHDMA;
-		hw->netdev_features |= NETIF_F_SG;
+		netdev_feature_add(NETIF_F_HIGHDMA_BIT, &hw->netdev_features);
+		netdev_feature_add(NETIF_F_SG_BIT, &hw->netdev_features);
 	}
 
 	hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 1c6bb3317a30..0c94d7bf80f6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -321,8 +321,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 
 	if (mvm->trans->max_skb_frags) {
 		netdev_features_zero(&hw->netdev_features);
-		hw->netdev_features |= NETIF_F_HIGHDMA;
-		hw->netdev_features |= NETIF_F_SG;
+		netdev_feature_add(NETIF_F_HIGHDMA_BIT, &hw->netdev_features);
+		netdev_feature_add(NETIF_F_SG_BIT, &hw->netdev_features);
 	}
 
 	hw->queues = IEEE80211_NUM_ACS;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 3283c346fbe7..e110ac000e88 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -6,6 +6,7 @@
  */
 #include <linux/ieee80211.h>
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/tcp.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -891,7 +892,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
 	u8 tid;
 
 	netdev_flags = NETIF_F_CSUM_MASK;
-	netdev_flags |= NETIF_F_SG;
+	netdev_feature_add(NETIF_F_SG_BIT, &netdev_flags);
 
 	snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) +
 		tcp_hdrlen(skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index bc2e309d45ed..8b899de8af2a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -368,7 +368,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
 	hw->max_report_rates = 7;
 	hw->max_rate_tries = 11;
 	netdev_features_zero(&hw->netdev_features);
-	hw->netdev_features |= NETIF_F_RXCSUM;
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, &hw->netdev_features);
 
 	hw->radiotap_timestamp.units_pos =
 		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index bc35271f41da..32b81deefbbe 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -331,7 +331,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
 	hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
 	hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
 	netdev_features_zero(&hw->netdev_features);
-	hw->netdev_features |= NETIF_F_RXCSUM;
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, &hw->netdev_features);
 
 	hw->radiotap_timestamp.units_pos =
 		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index 7824ee8e29cc..abc5d5667772 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -56,7 +56,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
 	hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
 	hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
 	netdev_features_zero(&hw->netdev_features);
-	hw->netdev_features |= NETIF_F_RXCSUM;
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, &hw->netdev_features);
 
 	hw->radiotap_timestamp.units_pos =
 		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
diff --git a/drivers/net/wwan/t7xx/t7xx_netdev.c b/drivers/net/wwan/t7xx/t7xx_netdev.c
index 52a77a224a64..4d9892adceac 100644
--- a/drivers/net/wwan/t7xx/t7xx_netdev.c
+++ b/drivers/net/wwan/t7xx/t7xx_netdev.c
@@ -174,16 +174,16 @@ static void t7xx_ccmni_wwan_setup(struct net_device *dev)
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
 
 	netdev_active_features_zero(dev);
-	dev->features |= NETIF_F_VLAN_CHALLENGED;
+	netdev_active_feature_add(dev, NETIF_F_VLAN_CHALLENGED_BIT);
 
-	dev->features |= NETIF_F_SG;
-	dev->hw_features |= NETIF_F_SG;
+	netdev_active_feature_add(dev, NETIF_F_SG_BIT);
+	netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
 
-	dev->features |= NETIF_F_HW_CSUM;
-	dev->hw_features |= NETIF_F_HW_CSUM;
+	netdev_active_feature_add(dev, NETIF_F_HW_CSUM_BIT);
+	netdev_hw_feature_add(dev, NETIF_F_HW_CSUM_BIT);
 
-	dev->features |= NETIF_F_RXCSUM;
-	dev->hw_features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
+	netdev_hw_feature_add(dev, NETIF_F_RXCSUM_BIT);
 
 	dev->needs_free_netdev = true;
 
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 8c37a65d8d06..b2e50d1a6cc2 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -534,7 +534,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_array(dev, &xenvif_hw_feature_set);
 	dev->features = dev->hw_features;
-	dev->features |= NETIF_F_RXCSUM;
+	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	dev->ethtool_ops = &xenvif_ethtool_ops;
 
 	dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 1a903161c46c..1975d01b6cad 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6362,10 +6362,10 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card)
 
 	dev->ethtool_ops = &qeth_ethtool_ops;
 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
-	dev->hw_features |= NETIF_F_SG;
-	dev->vlan_features |= NETIF_F_SG;
+	netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
+	netdev_vlan_feature_add(dev, NETIF_F_SG_BIT);
 	if (IS_IQD(card))
-		dev->features |= NETIF_F_SG;
+		netdev_active_feature_add(dev, NETIF_F_SG_BIT);
 
 	return dev;
 }
@@ -6826,7 +6826,8 @@ void qeth_enable_hw_features(struct net_device *dev)
 	/* toggle VLAN filter, so that VIDs are re-programmed: */
 	if (IS_LAYER2(card) && IS_VM_NIC(card)) {
 		dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
-		dev->wanted_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_wanted_feature_add(dev,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	}
 	netdev_update_features(dev);
 	if (features != dev->features)
@@ -6842,13 +6843,13 @@ static void qeth_check_restricted_features(struct qeth_card *card,
 	netdev_features_t ipv6_features = netdev_empty_features;
 	netdev_features_t ipv4_features = netdev_empty_features;
 
-	ipv6_features |= NETIF_F_TSO6;
-	ipv4_features |= NETIF_F_TSO;
+	netdev_feature_add(NETIF_F_TSO6_BIT, &ipv6_features);
+	netdev_feature_add(NETIF_F_TSO_BIT, &ipv4_features);
 
 	if (!card->info.has_lp2lp_cso_v6)
-		ipv6_features |= NETIF_F_IPV6_CSUM;
+		netdev_feature_add(NETIF_F_IPV6_CSUM_BIT, &ipv6_features);
 	if (!card->info.has_lp2lp_cso_v4)
-		ipv4_features |= NETIF_F_IP_CSUM;
+		netdev_feature_add(NETIF_F_IP_CSUM_BIT, &ipv4_features);
 
 	if ((changed & ipv6_features) && !(actual & ipv6_features))
 		qeth_flush_local_addrs6(card);
@@ -6949,14 +6950,16 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 		switch (vlan_get_protocol(skb)) {
 		case htons(ETH_P_IP):
 			if (!card->info.has_lp2lp_cso_v4)
-				restricted |= NETIF_F_IP_CSUM;
+				netdev_feature_add(NETIF_F_IP_CSUM_BIT,
+						   &restricted);
 
 			if (restricted && qeth_next_hop_is_local_v4(card, skb))
 				features &= ~restricted;
 			break;
 		case htons(ETH_P_IPV6):
 			if (!card->info.has_lp2lp_cso_v6)
-				restricted |= NETIF_F_IPV6_CSUM;
+				netdev_feature_add(NETIF_F_IPV6_CSUM_BIT,
+						   &restricted);
 
 			if (restricted && qeth_next_hop_is_local_v6(card, skb))
 				features &= ~restricted;
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 83950ce159f9..32926f3c90ed 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1093,37 +1093,41 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
 	card->dev->priv_flags |= IFF_UNICAST_FLT;
 
 	if (IS_OSM(card)) {
-		card->dev->features |= NETIF_F_VLAN_CHALLENGED;
+		netdev_active_feature_add(card->dev,
+					  NETIF_F_VLAN_CHALLENGED_BIT);
 	} else {
 		if (!IS_VM_NIC(card))
-			card->dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-		card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+			netdev_hw_feature_add(card->dev,
+					      NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+		netdev_active_feature_add(card->dev,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	}
 
 	if (IS_OSD(card) && !IS_VM_NIC(card)) {
-		card->dev->features |= NETIF_F_SG;
+		netdev_active_feature_add(card->dev, NETIF_F_SG_BIT);
 		/* OSA 3S and earlier has no RX/TX support */
 		if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) {
-			card->dev->hw_features |= NETIF_F_IP_CSUM;
-			card->dev->vlan_features |= NETIF_F_IP_CSUM;
+			netdev_hw_feature_add(card->dev, NETIF_F_IP_CSUM_BIT);
+			netdev_vlan_feature_add(card->dev,
+						NETIF_F_IP_CSUM_BIT);
 		}
 	}
 	if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
-		card->dev->hw_features |= NETIF_F_IPV6_CSUM;
-		card->dev->vlan_features |= NETIF_F_IPV6_CSUM;
+		netdev_hw_feature_add(card->dev, NETIF_F_IPV6_CSUM_BIT);
+		netdev_vlan_feature_add(card->dev, NETIF_F_IPV6_CSUM_BIT);
 	}
 	if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM) ||
 	    qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6)) {
-		card->dev->hw_features |= NETIF_F_RXCSUM;
-		card->dev->vlan_features |= NETIF_F_RXCSUM;
+		netdev_hw_feature_add(card->dev, NETIF_F_RXCSUM_BIT);
+		netdev_vlan_feature_add(card->dev, NETIF_F_RXCSUM_BIT);
 	}
 	if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
-		card->dev->hw_features |= NETIF_F_TSO;
-		card->dev->vlan_features |= NETIF_F_TSO;
+		netdev_hw_feature_add(card->dev, NETIF_F_TSO_BIT);
+		netdev_vlan_feature_add(card->dev, NETIF_F_TSO_BIT);
 	}
 	if (qeth_is_supported6(card, IPA_OUTBOUND_TSO)) {
-		card->dev->hw_features |= NETIF_F_TSO6;
-		card->dev->vlan_features |= NETIF_F_TSO6;
+		netdev_hw_feature_add(card->dev, NETIF_F_TSO6_BIT);
+		netdev_vlan_feature_add(card->dev, NETIF_F_TSO6_BIT);
 	}
 
 	if (card->dev->hw_features & netdev_general_tso_features) {
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index f7b30abac5e9..0f342a6d3070 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1872,7 +1872,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 		dev->dev_id = qeth_l3_get_unique_id(card, dev->dev_id);
 
 		if (!IS_VM_NIC(card)) {
-			card->dev->features |= NETIF_F_SG;
+			netdev_active_feature_add(card->dev, NETIF_F_SG_BIT);
 			netdev_hw_features_set_array(card->dev,
 						     &qeth_l3_feature_set);
 			netdev_vlan_features_set_array(card->dev,
@@ -1880,12 +1880,14 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 		}
 
 		if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
-			card->dev->hw_features |= NETIF_F_IPV6_CSUM;
-			card->dev->vlan_features |= NETIF_F_IPV6_CSUM;
+			netdev_hw_feature_add(card->dev,
+					      NETIF_F_IPV6_CSUM_BIT);
+			netdev_vlan_feature_add(card->dev,
+						NETIF_F_IPV6_CSUM_BIT);
 		}
 		if (qeth_is_supported6(card, IPA_OUTBOUND_TSO)) {
-			card->dev->hw_features |= NETIF_F_TSO6;
-			card->dev->vlan_features |= NETIF_F_TSO6;
+			netdev_hw_feature_add(card->dev, NETIF_F_TSO6_BIT);
+			netdev_vlan_feature_add(card->dev, NETIF_F_TSO6_BIT);
 		}
 
 		/* allow for de-acceleration of NETIF_F_HW_VLAN_CTAG_TX: */
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 0811ff9452f7..2d1109e7d03e 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/phy.h>
 #include <linux/slab.h>
@@ -422,12 +423,12 @@ int cvm_oct_common_init(struct net_device *dev)
 		priv->queue = -1;
 
 	if (priv->queue != -1) {
-		dev->features |= NETIF_F_SG;
-		dev->features |= NETIF_F_IP_CSUM;
+		netdev_active_feature_add(dev, NETIF_F_SG_BIT);
+		netdev_active_feature_add(dev, NETIF_F_IP_CSUM_BIT);
 	}
 
 	/* We do our own locking, Linux doesn't need to */
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	dev->ethtool_ops = &cvm_oct_ethtool_ops;
 
 	cvm_oct_set_mac_filter(dev);
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index 89ce268d9d81..2e67d69d6ac7 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -4586,7 +4586,7 @@ static int qlge_probe(struct pci_dev *pdev,
 	ndev->vlan_features &= ~netdev_ctag_vlan_features;
 
 	if (test_bit(QL_DMA64, &qdev->flags))
-		ndev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 
 	/*
 	 * Set up net_device structure.
diff --git a/include/net/udp.h b/include/net/udp.h
index 46d7527cae38..f901e40bd470 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -25,6 +25,7 @@
 #include <net/snmp.h>
 #include <net/ip.h>
 #include <linux/ipv6.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/seq_file.h>
 #include <linux/poll.h>
 #include <linux/indirect_call_wrapper.h>
@@ -460,7 +461,7 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk,
 	netdev_features_t features = netdev_empty_features;
 	struct sk_buff *segs;
 
-	features |= NETIF_F_SG;
+	netdev_feature_add(NETIF_F_SG_BIT, &features);
 
 	/* Avoid csum recalculation by skb_segment unless userspace explicitly
 	 * asks for the final checksum values
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 60b5e401e346..4c11028ce4f8 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -114,7 +114,7 @@ static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)
 
 	if ((ret & NETIF_F_GSO_ENCAP_ALL) && (ret & NETIF_F_CSUM_MASK)) {
 		ret &= ~NETIF_F_CSUM_MASK;
-		ret |= NETIF_F_HW_CSUM;
+		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &ret);
 		return ret;
 	}
 	netdev_features_zero(&ret);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index ab2847fa938d..6df3fd365714 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -579,7 +579,7 @@ static int vlan_dev_init(struct net_device *dev)
 	netdev_hw_features_set_array(dev, &vlan_hw_feature_set);
 
 	dev->features |= dev->hw_features;
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netif_inherit_tso_max(dev, real_dev);
 	if (dev->features & NETIF_F_VLAN_FEATURES)
 		netdev_warn(real_dev, "VLAN features are set incorrectly.  Q-in-Q configurations may not work correctly.\n");
@@ -656,19 +656,19 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
 	netdev_features_t tmp;
 
 	tmp = real_dev->vlan_features;
-	tmp |= NETIF_F_RXCSUM;
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, &tmp);
 	lower_features = netdev_intersect_features(tmp, real_dev->features);
 
 	/* Add HW_CSUM setting to preserve user ability to control
 	 * checksum offload on the vlan device.
 	 */
 	if (lower_features & netdev_ip_csum_features)
-		lower_features |= NETIF_F_HW_CSUM;
+		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &lower_features);
 	features = netdev_intersect_features(features, lower_features);
 	tmp = NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE;
 	tmp &= old_features;
 	features |= tmp;
-	features |= NETIF_F_LLTX;
+	netdev_feature_add(NETIF_F_LLTX_BIT, &features);
 
 	return features;
 }
diff --git a/net/core/dev.c b/net/core/dev.c
index 74b6315449a7..e374eb18c716 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3399,7 +3399,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;
 	}
@@ -10032,14 +10032,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
@@ -10047,26 +10047,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);
@@ -11155,7 +11155,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/core/sock.c b/net/core/sock.c
index 3127552e8989..c71c43882785 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -118,6 +118,7 @@
 #include <linux/uaccess.h>
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <net/protocol.h>
 #include <linux/skbuff.h>
 #include <net/net_namespace.h>
@@ -2317,7 +2318,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 	sk_dst_set(sk, dst);
 	sk->sk_route_caps = dst->dev->features;
 	if (sk_is_tcp(sk))
-		sk->sk_route_caps |= NETIF_F_GSO;
+		netdev_feature_add(NETIF_F_GSO_BIT, &sk->sk_route_caps);
 	if (sk->sk_route_caps & NETIF_F_GSO)
 		sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
 	if (unlikely(sk->sk_gso_disabled))
@@ -2326,8 +2327,8 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 		if (dst->header_len && !xfrm_dst_offload_ok(dst)) {
 			sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
 		} else {
-			sk->sk_route_caps |= NETIF_F_SG;
-			sk->sk_route_caps |= NETIF_F_HW_CSUM;
+			netdev_feature_add(NETIF_F_SG_BIT, &sk->sk_route_caps);
+			netdev_feature_add(NETIF_F_HW_CSUM_BIT, &sk->sk_route_caps);
 			/* pairs with the WRITE_ONCE() in netif_set_gso_max_size() */
 			sk->sk_gso_max_size = READ_ONCE(dst->dev->gso_max_size);
 			sk_trim_gso_size(sk);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index a7e831bc5632..7ed3699bdc4d 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -7,6 +7,7 @@
 #include <linux/list.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
 #include <linux/phylink.h>
@@ -1671,7 +1672,8 @@ int dsa_slave_manage_vlan_filtering(struct net_device *slave,
 	int err;
 
 	if (vlan_filtering) {
-		slave->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_active_feature_add(slave,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 		err = vlan_for_each(slave, dsa_slave_restore_vlan, slave);
 		if (err) {
@@ -2288,15 +2290,16 @@ void dsa_slave_setup_tagger(struct net_device *slave)
 	p->xmit = cpu_dp->tag_ops->xmit;
 
 	slave->features = master->vlan_features;
-	slave->features |= NETIF_F_HW_TC;
-	slave->hw_features |= NETIF_F_HW_TC;
-	slave->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(slave, NETIF_F_HW_TC_BIT);
+	netdev_hw_feature_add(slave, NETIF_F_HW_TC_BIT);
+	netdev_active_feature_add(slave, NETIF_F_LLTX_BIT);
 	if (slave->needed_tailroom) {
 		slave->features &= ~NETIF_F_SG;
 		slave->features &= ~NETIF_F_FRAGLIST;
 	}
 	if (ds->needs_standalone_vlan_filtering)
-		slave->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_active_feature_add(slave,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 }
 
 int dsa_slave_suspend(struct net_device *slave_dev)
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 7674629773a1..3e5116f6d56a 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -237,28 +237,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();
@@ -342,15 +342,15 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
 		return -EINVAL;
 
 	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(&eth_all_features);
 	netdev_features_set_array(&ethtool_all_feature_set, &eth_all_features);
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index ab1c4dfa25b7..421ce8c28932 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -462,15 +462,15 @@ void hsr_dev_setup(struct net_device *dev)
 	dev->features = dev->hw_features;
 
 	/* Prevent recursive tx locking */
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	/* VLAN on top of HSR needs testing and probably some work on
 	 * hsr_header_create() etc.
 	 */
-	dev->features |= NETIF_F_VLAN_CHALLENGED;
+	netdev_active_feature_add(dev, NETIF_F_VLAN_CHALLENGED_BIT);
 	/* Not sure about this. Taken from bridge code. netdev_features.h says
 	 * it means "Does not change network namespaces".
 	 */
-	dev->features |= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
 }
 
 /* Return true if dev is a HSR master; return false otherwise.
diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
index 2c087b7f17c5..5f7affe795f0 100644
--- a/net/ieee802154/6lowpan/core.c
+++ b/net/ieee802154/6lowpan/core.c
@@ -46,6 +46,7 @@
 
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/ieee802154.h>
 #include <linux/if_arp.h>
 
@@ -116,7 +117,7 @@ static void lowpan_setup(struct net_device *ldev)
 	ldev->netdev_ops	= &lowpan_netdev_ops;
 	ldev->header_ops	= &lowpan_header_ops;
 	ldev->needs_free_netdev	= true;
-	ldev->features		|= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(ldev, NETIF_F_NETNS_LOCAL_BIT);
 }
 
 static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[],
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index de259b5170ab..8eda70f58682 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -7,6 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/netdev_features_helper.h>
 
 #include <net/cfg802154.h>
 #include <net/rtnetlink.h>
@@ -208,7 +209,8 @@ int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
 		err = dev_change_net_namespace(wpan_dev->netdev, net, "wpan%d");
 		if (err)
 			break;
-		wpan_dev->netdev->features |= NETIF_F_NETNS_LOCAL;
+		netdev_active_feature_add(wpan_dev->netdev,
+					  NETIF_F_NETNS_LOCAL_BIT);
 	}
 
 	if (err) {
@@ -224,7 +226,8 @@ int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
 			err = dev_change_net_namespace(wpan_dev->netdev, net,
 						       "wpan%d");
 			WARN_ON(err);
-			wpan_dev->netdev->features |= NETIF_F_NETNS_LOCAL;
+			netdev_active_feature_add(wpan_dev->netdev,
+						  NETIF_F_NETNS_LOCAL_BIT);
 		}
 
 		return err;
@@ -269,7 +272,7 @@ static int cfg802154_netdev_notifier_call(struct notifier_block *nb,
 	switch (state) {
 		/* TODO NETDEV_DEVTYPE */
 	case NETDEV_REGISTER:
-		dev->features |= NETIF_F_NETNS_LOCAL;
+		netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
 		wpan_dev->identifier = ++rdev->wpan_dev_id;
 		list_add_rcu(&wpan_dev->list, &rdev->wpan_dev_list);
 		rdev->devlist_generation++;
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index e65e948cab9f..8c4fd17535dd 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -1074,7 +1074,8 @@ int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
 	 * Allowing to move it to another netns is clearly unsafe.
 	 */
 	if (!IS_ERR(itn->fb_tunnel_dev)) {
-		itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
+		netdev_active_feature_add(itn->fb_tunnel_dev,
+					  NETIF_F_NETNS_LOCAL_BIT);
 		itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev);
 		ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
 		itn->type = itn->fb_tunnel_dev->type;
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 8c2bd1d9ddce..022aee189e6f 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -21,6 +21,7 @@
 #include <linux/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/in.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
@@ -430,7 +431,7 @@ static int vti_tunnel_init(struct net_device *dev)
 
 	dev->flags		= IFF_NOARP;
 	dev->addr_len		= 4;
-	dev->features		|= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netif_keep_dst(dev);
 
 	return ip_tunnel_init(dev);
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 66b2deb4ddff..e1988286c523 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -371,7 +371,7 @@ static void ipip_tunnel_setup(struct net_device *dev)
 	dev->type		= ARPHRD_TUNNEL;
 	dev->flags		= IFF_NOARP;
 	dev->addr_len		= 4;
-	dev->features		|= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netif_keep_dst(dev);
 
 	ipip_features		= NETIF_F_GSO_SOFTWARE;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 73651d17e51f..330e3fa258e6 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -536,7 +536,7 @@ static void reg_vif_setup(struct net_device *dev)
 	dev->flags		= IFF_NOARP;
 	dev->netdev_ops		= &reg_vif_netdev_ops;
 	dev->needs_free_netdev	= true;
-	dev->features		|= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
 }
 
 static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt)
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 3f3c158a5ac5..3f1cbb081f39 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -82,7 +82,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
 	if (unlikely(skb->len <= mss))
 		goto out;
 
-	features |= NETIF_F_GSO_ROBUST;
+	netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, &features);
 	if (skb_gso_ok(skb, features)) {
 		/* Packet is from an untrusted source, reset gso_segs. */
 
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 0486dbe58390..b699b89e592b 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -79,7 +79,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 	if (remcsum) {
 		features &= ~NETIF_F_CSUM_MASK;
 		if (!need_csum || offload_csum)
-			features |= NETIF_F_HW_CSUM;
+			netdev_feature_add(NETIF_F_HW_CSUM_BIT, &features);
 	}
 
 	/* segment inner packet. */
@@ -415,7 +415,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 	 * software prior to segmenting the frame.
 	 */
 	if (!skb->encap_hdr_csum)
-		features |= NETIF_F_HW_CSUM;
+		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &features);
 
 	/* Fragment the skb. IP headers of the fragments are updated in
 	 * inet_gso_segment()
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index b91a001077af..1a322cd002cb 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1632,7 +1632,7 @@ static int __net_init ip6gre_init_net(struct net *net)
 	/* FB netdevice is special: we have one, and only one per netns.
 	 * Allowing to move it to another netns is clearly unsafe.
 	 */
-	ign->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(ign->fb_tunnel_dev, NETIF_F_NETNS_LOCAL_BIT);
 
 
 	ip6gre_fb_tunnel_init(ign->fb_tunnel_dev);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index da8eccfd1849..2922f0f66634 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1840,7 +1840,7 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
 	dev->type = ARPHRD_TUNNEL6;
 	dev->flags |= IFF_NOARP;
 	dev->addr_len = sizeof(struct in6_addr);
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netif_keep_dst(dev);
 
 	ipxipx_features = NETIF_F_GSO_SOFTWARE;
@@ -2288,7 +2288,7 @@ static int __net_init ip6_tnl_init_net(struct net *net)
 	/* FB netdevice is special: we have one, and only one per netns.
 	 * Allowing to move it to another netns is clearly unsafe.
 	 */
-	ip6n->fb_tnl_dev->features |= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(ip6n->fb_tnl_dev, NETIF_F_NETNS_LOCAL_BIT);
 
 	err = ip6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
 	if (err < 0)
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index a9ba41648e36..ac153f8783e1 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -22,6 +22,7 @@
 #include <linux/socket.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/inetdevice.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -640,7 +641,7 @@ static void reg_vif_setup(struct net_device *dev)
 	dev->flags		= IFF_NOARP;
 	dev->netdev_ops		= &reg_vif_netdev_ops;
 	dev->needs_free_netdev	= true;
-	dev->features		|= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
 }
 
 static struct net_device *ip6mr_reg_vif(struct net *net, struct mr_table *mrt)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 9e4c02fd379c..69d10ab34e1c 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1434,7 +1434,7 @@ static void ipip6_tunnel_setup(struct net_device *dev)
 	dev->addr_len		= 4;
 	sit_features = NETIF_F_GSO_SOFTWARE;
 	netdev_features_set_array(&sit_feature_set, &sit_features);
-	dev->features		|= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	dev->features		|= sit_features;
 	dev->hw_features	|= sit_features;
 }
@@ -1914,7 +1914,8 @@ static int __net_init sit_init_net(struct net *net)
 	/* FB netdevice is special: we have one, and only one per netns.
 	 * Allowing to move it to another netns is clearly unsafe.
 	 */
-	sitn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
+	netdev_active_feature_add(sitn->fb_tunnel_dev,
+				  NETIF_F_NETNS_LOCAL_BIT);
 
 	err = register_netdev(sitn->fb_tunnel_dev);
 	if (err)
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 7720d04ed396..301ba864096c 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -70,7 +70,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
 		 * software prior to segmenting the frame.
 		 */
 		if (!skb->encap_hdr_csum)
-			features |= NETIF_F_HW_CSUM;
+			netdev_feature_add(NETIF_F_HW_CSUM_BIT, &features);
 
 		/* Check if there is enough headroom to insert fragment header. */
 		tnl_hlen = skb_tnl_header_len(skb);
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 6cd97c75445c..0ee490b4b846 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -117,7 +117,7 @@ static void l2tp_eth_dev_setup(struct net_device *dev)
 	SET_NETDEV_DEVTYPE(dev, &l2tpeth_type);
 	ether_setup(dev);
 	dev->priv_flags		&= ~IFF_TX_SKB_SHARING;
-	dev->features		|= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	dev->netdev_ops		= &l2tp_eth_netdev_ops;
 	dev->needs_free_netdev	= true;
 }
diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
index ba98ac8e31c8..d9b55bf19fd0 100644
--- a/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -7,6 +7,7 @@
 
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <net/nsh.h>
 #include <net/tun_proto.h>
@@ -105,7 +106,7 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
 	skb->mac_len = proto == htons(ETH_P_TEB) ? ETH_HLEN : 0;
 	skb->protocol = proto;
 
-	tmp |= NETIF_F_SG;
+	netdev_feature_add(NETIF_F_SG_BIT, &tmp);
 	features &= tmp;
 	segs = skb_mac_gso_segment(skb, features);
 	if (IS_ERR_OR_NULL(segs)) {
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 73571e1393fc..9a4e86ae2cbf 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/time.h>
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/genetlink.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
@@ -325,7 +326,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
 	int err;
 
 	BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_GSO_CB_OFFSET);
-	features |= NETIF_F_SG;
+	netdev_feature_add(NETIF_F_SG_BIT, &features);
 	segs = __skb_gso_segment(skb, features, false);
 	if (IS_ERR(segs))
 		return PTR_ERR(segs);
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 522457207275..888ffcb2e1ca 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -160,7 +160,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
 
 	/* Restrict bridge port to current netns. */
 	if (vport->port_no == OVSP_LOCAL)
-		vport->dev->features |= NETIF_F_NETNS_LOCAL;
+		netdev_active_feature_add(vport->dev, NETIF_F_NETNS_LOCAL_BIT);
 
 	rtnl_lock();
 	err = register_netdevice(vport->dev);
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index 0b09b1ba0c05..a72d85722df7 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -214,7 +214,7 @@ static const struct net_device_ops gprs_netdev_ops = {
 static void gprs_setup(struct net_device *dev)
 {
 	netdev_active_features_zero(dev);
-	dev->features		|= NETIF_F_FRAGLIST;
+	netdev_active_feature_add(dev, NETIF_F_FRAGLIST_BIT);
 	dev->type		= ARPHRD_PHONET_PIPE;
 	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
 	dev->mtu		= GPRS_DEFAULT_MTU;
diff --git a/net/sctp/offload.c b/net/sctp/offload.c
index 1433fcc0977d..ad77e0362188 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -14,6 +14,7 @@
 #include <linux/proc_fs.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/kfifo.h>
 #include <linux/time.h>
 #include <net/net_namespace.h>
@@ -51,7 +52,7 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
 
 	__skb_pull(skb, sizeof(*sh));
 
-	tmp |= NETIF_F_GSO_ROBUST;
+	netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, &tmp);
 	if (skb_gso_ok(skb, tmp)) {
 		/* Packet is from an untrusted source, reset gso_segs. */
 		struct skb_shared_info *pinfo = skb_shinfo(skb);
@@ -71,7 +72,7 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
 	}
 
 	tmp = features;
-	tmp |= NETIF_F_HW_CSUM;
+	netdev_feature_add(NETIF_F_HW_CSUM_BIT, &tmp);
 	tmp &= ~NETIF_F_SG;
 	segs = skb_segment(skb, tmp);
 	if (IS_ERR(segs))
diff --git a/net/wireless/core.c b/net/wireless/core.c
index eefd6d8ff465..57504e859573 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -20,6 +20,7 @@
 #include <linux/notifier.h>
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/rtnetlink.h>
 #include <linux/sched.h>
 #include <net/genetlink.h>
@@ -168,7 +169,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 		err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
 		if (err)
 			break;
-		wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
+		netdev_active_feature_add(wdev->netdev,
+					  NETIF_F_NETNS_LOCAL_BIT);
 	}
 
 	if (err) {
@@ -184,7 +186,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 			err = dev_change_net_namespace(wdev->netdev, net,
 							"wlan%d");
 			WARN_ON(err);
-			wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
+			netdev_active_feature_add(wdev->netdev,
+						  NETIF_F_NETNS_LOCAL_BIT);
 		}
 
 		return err;
@@ -1412,7 +1415,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 		SET_NETDEV_DEVTYPE(dev, &wiphy_type);
 		wdev->netdev = dev;
 		/* can only change netns with wiphy */
-		dev->features |= NETIF_F_NETNS_LOCAL;
+		netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
 
 		cfg80211_init_wdev(wdev);
 		break;
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index d80bff81b346..41a05e6d2ef0 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -597,7 +597,7 @@ static int xfrmi_dev_init(struct net_device *dev)
 
 	xfrmi_features = NETIF_F_GSO_SOFTWARE;
 	netdev_features_set_array(&xfrmi_feature_set, &xfrmi_features);
-	dev->features |= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	dev->features |= xfrmi_features;
 	dev->hw_features |= xfrmi_features;
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 25/36] treewide: use netdev_features_or/set helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (23 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 24/36] treewide: use netdev_feature_add helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 26/36] treewide: use netdev_feature_change helpers Jian Shen
                   ` (10 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '|' expressions of features by netdev_features_or
helpers, and '|=' expressions by netdev_features_set helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/infiniband/ulp/ipoib/ipoib_main.c     |  2 +-
 drivers/net/amt.c                             |  4 +--
 drivers/net/bareudp.c                         |  4 +--
 drivers/net/bonding/bond_main.c               | 23 +++++++--------
 drivers/net/bonding/bond_options.c            |  5 ++--
 drivers/net/dummy.c                           |  8 +++---
 drivers/net/ethernet/alacritech/slicoss.c     |  2 +-
 drivers/net/ethernet/altera/altera_tse_main.c |  2 +-
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  4 +--
 drivers/net/ethernet/amd/amd8111e.c           |  3 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |  2 +-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c     |  2 +-
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |  2 +-
 drivers/net/ethernet/asix/ax88796c_main.c     |  4 +--
 drivers/net/ethernet/atheros/atlx/atl2.c      |  2 +-
 drivers/net/ethernet/broadcom/b44.c           |  3 +-
 drivers/net/ethernet/broadcom/bcmsysport.c    |  4 +--
 drivers/net/ethernet/broadcom/bnx2.c          |  6 ++--
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  9 +++---
 drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c |  3 +-
 .../net/ethernet/broadcom/genet/bcmgenet.c    |  4 +--
 drivers/net/ethernet/broadcom/tg3.c           |  8 +++---
 drivers/net/ethernet/brocade/bna/bnad.c       |  2 +-
 drivers/net/ethernet/calxeda/xgmac.c          |  2 +-
 .../net/ethernet/cavium/liquidio/lio_main.c   |  2 +-
 .../ethernet/cavium/liquidio/lio_vf_main.c    |  2 +-
 .../net/ethernet/cavium/thunder/nicvf_main.c  |  2 +-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  3 +-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  4 +--
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  2 +-
 drivers/net/ethernet/cisco/enic/enic_main.c   | 10 +++----
 drivers/net/ethernet/cortina/gemini.c         |  2 +-
 drivers/net/ethernet/davicom/dm9000.c         |  2 +-
 drivers/net/ethernet/dnet.c                   |  3 +-
 drivers/net/ethernet/emulex/benet/be_main.c   |  2 +-
 drivers/net/ethernet/ethoc.c                  |  3 +-
 drivers/net/ethernet/faraday/ftgmac100.c      |  2 +-
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  2 +-
 drivers/net/ethernet/freescale/gianfar.c      |  2 +-
 .../ethernet/fungible/funeth/funeth_main.c    |  8 +++---
 drivers/net/ethernet/hisilicon/hix5hd2_gmac.c |  4 +--
 drivers/net/ethernet/hisilicon/hns/hns_enet.c |  2 +-
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   |  8 +++---
 drivers/net/ethernet/ibm/emac/core.c          |  2 +-
 drivers/net/ethernet/ibm/ibmveth.c            |  6 ++--
 drivers/net/ethernet/ibm/ibmvnic.c            |  5 ++--
 drivers/net/ethernet/intel/e1000/e1000_main.c |  2 +-
 drivers/net/ethernet/intel/e1000e/netdev.c    |  3 +-
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  6 ++--
 drivers/net/ethernet/intel/i40e/i40e_main.c   | 15 +++++-----
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 21 +++++++-------
 drivers/net/ethernet/intel/ice/ice_main.c     | 28 ++++++++++---------
 drivers/net/ethernet/intel/igb/igb_main.c     | 12 ++++----
 drivers/net/ethernet/intel/igbvf/netdev.c     |  8 +++---
 drivers/net/ethernet/intel/igc/igc_main.c     |  8 +++---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 12 ++++----
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 10 +++----
 drivers/net/ethernet/marvell/mvneta.c         |  4 +--
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   | 13 +++++----
 .../ethernet/marvell/octeon_ep/octep_main.c   |  2 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  | 10 +++----
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  6 ++--
 drivers/net/ethernet/marvell/skge.c           |  2 +-
 drivers/net/ethernet/marvell/sky2.c           |  4 +--
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  2 +-
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  2 +-
 .../net/ethernet/mellanox/mlx5/core/en_rep.c  |  2 +-
 drivers/net/ethernet/micrel/ksz884x.c         |  2 +-
 .../ethernet/microchip/lan966x/lan966x_main.c |  3 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  2 +-
 drivers/net/ethernet/natsemi/ns83820.c        |  2 +-
 drivers/net/ethernet/neterion/s2io.c          |  2 +-
 .../ethernet/netronome/nfp/nfp_net_common.c   |  4 +--
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  6 ++--
 drivers/net/ethernet/nvidia/forcedeth.c       |  4 +--
 .../net/ethernet/pensando/ionic/ionic_lif.c   |  6 ++--
 .../ethernet/qlogic/netxen/netxen_nic_main.c  |  4 +--
 .../net/ethernet/qlogic/qlcnic/qlcnic_main.c  |  5 ++--
 drivers/net/ethernet/realtek/r8169_main.c     |  4 +--
 .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |  2 +-
 drivers/net/ethernet/sfc/ef10.c               |  6 ++--
 drivers/net/ethernet/sfc/ef100_netdev.c       |  8 +++---
 drivers/net/ethernet/sfc/ef100_nic.c          |  6 ++--
 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 +-
 drivers/net/ethernet/sfc/siena/efx.c          |  9 +++---
 drivers/net/ethernet/sfc/siena/efx_common.c   |  4 +--
 drivers/net/ethernet/sfc/siena/net_driver.h   |  3 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  8 +++---
 drivers/net/ethernet/sun/niu.c                |  2 +-
 drivers/net/ethernet/sun/sunhme.c             |  4 +--
 .../net/ethernet/synopsys/dwc-xlgmac-common.c |  6 ++--
 drivers/net/ethernet/via/via-rhine.c          |  2 +-
 drivers/net/geneve.c                          |  4 +--
 drivers/net/hyperv/rndis_filter.c             |  2 +-
 drivers/net/ifb.c                             | 11 ++++----
 drivers/net/ipvlan/ipvlan_main.c              | 17 +++++------
 drivers/net/macsec.c                          |  6 ++--
 drivers/net/macvlan.c                         | 17 +++++------
 drivers/net/net_failover.c                    | 11 ++++----
 drivers/net/tap.c                             |  2 +-
 drivers/net/team/team.c                       | 13 +++++----
 drivers/net/tun.c                             |  4 +--
 drivers/net/usb/ax88179_178a.c                |  2 +-
 drivers/net/usb/smsc75xx.c                    |  2 +-
 drivers/net/veth.c                            |  8 ++++--
 drivers/net/virtio_net.c                      |  5 ++--
 drivers/net/vrf.c                             |  2 +-
 drivers/net/vxlan/vxlan_core.c                |  4 +--
 drivers/net/wireguard/device.c                |  6 ++--
 drivers/net/wireless/ath/wil6210/netdev.c     |  2 +-
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |  4 +--
 drivers/net/xen-netfront.c                    |  2 +-
 drivers/s390/net/qeth_core_main.c             |  2 +-
 drivers/s390/net/qeth_l3_main.c               |  3 +-
 include/linux/netdev_features_helper.h        |  6 ++--
 include/net/udp.h                             |  2 +-
 net/8021q/vlan.h                              |  4 +--
 net/8021q/vlan_dev.c                          | 11 ++++----
 net/bridge/br_device.c                        |  3 +-
 net/core/dev.c                                | 18 ++++++------
 net/core/sock.c                               |  2 +-
 net/ethtool/ioctl.c                           |  6 ++--
 net/ipv4/ip_gre.c                             |  8 +++---
 net/ipv4/ipip.c                               |  4 +--
 net/ipv6/ip6_gre.c                            |  4 +--
 net/ipv6/ip6_tunnel.c                         |  4 +--
 net/ipv6/sit.c                                |  4 +--
 net/mac80211/iface.c                          |  4 +--
 net/mac80211/main.c                           |  3 +-
 net/openvswitch/vport-internal_dev.c          |  5 ++--
 net/xfrm/xfrm_device.c                        |  5 ++--
 net/xfrm/xfrm_interface.c                     |  4 +--
 137 files changed, 375 insertions(+), 341 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index fe18d7819d3c..e4d20673150c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1861,7 +1861,7 @@ static void ipoib_set_dev_features(struct ipoib_dev_priv *priv)
 		if (priv->kernel_caps & IBK_UD_TSO)
 			netdev_hw_feature_add(priv->dev, NETIF_F_TSO_BIT);
 
-		priv->dev->features |= priv->dev->hw_features;
+		netdev_active_features_set(priv->dev, priv->dev->hw_features);
 	}
 }
 
diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index f76013edd417..8a1ac2663260 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -3117,9 +3117,9 @@ static void amt_link_setup(struct net_device *dev)
 	dev->hard_header_len	= 0;
 	dev->addr_len		= 0;
 	dev->priv_flags		|= IFF_NO_QUEUE;
-	dev->features		|= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	netdev_active_features_set_array(dev, &amt_feature_set);
-	dev->hw_features	|= NETIF_F_GSO_SOFTWARE;
+	netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	netdev_hw_features_set_array(dev, &amt_hw_feature_set);
 	eth_hw_addr_random(dev);
 	eth_zero_addr(dev->broadcast);
diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
index 08b11ed436ad..4c602e2e178f 100644
--- a/drivers/net/bareudp.c
+++ b/drivers/net/bareudp.c
@@ -557,9 +557,9 @@ static void bareudp_setup(struct net_device *dev)
 	dev->needs_free_netdev = true;
 	SET_NETDEV_DEVTYPE(dev, &bareudp_type);
 	netdev_active_features_set_array(dev, &bareudp_feature_set);
-	dev->features    |= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	netdev_hw_features_set_array(dev, &bareudp_hw_feature_set);
-	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+	netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	dev->hard_header_len = 0;
 	dev->addr_len = 0;
 	dev->mtu = ETH_DATA_LEN;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f117f63e2879..06fa1a5fcb36 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1421,7 +1421,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 
 #if IS_ENABLED(CONFIG_TLS_DEVICE)
 	if (bond_sk_check(bond))
-		features |= BOND_TLS_FEATURES;
+		netdev_features_set(&features, BOND_TLS_FEATURES);
 	else
 		features &= ~BOND_TLS_FEATURES;
 #endif
@@ -1429,7 +1429,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 	mask = features;
 
 	features &= ~NETIF_F_ONE_FOR_ALL;
-	features |= NETIF_F_ALL_FOR_ALL;
+	netdev_features_set(&features, NETIF_F_ALL_FOR_ALL);
 
 	bond_for_each_slave(bond, slave, iter) {
 		features = netdev_increment_features(features,
@@ -1498,10 +1498,11 @@ static void bond_compute_features(struct bonding *bond)
 
 done:
 	bond_dev->vlan_features = vlan_features;
-	bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL;
-	bond_dev->hw_enc_features |= netdev_tx_vlan_features;
+	bond_dev->hw_enc_features = netdev_features_or(enc_features,
+						       NETIF_F_GSO_ENCAP_ALL);
+	netdev_hw_enc_features_set(bond_dev, netdev_tx_vlan_features);
 #ifdef CONFIG_XFRM_OFFLOAD
-	bond_dev->hw_enc_features |= xfrm_features;
+	netdev_hw_enc_features_set(bond_dev, xfrm_features);
 #endif /* CONFIG_XFRM_OFFLOAD */
 	bond_dev->mpls_features = mpls_features;
 	netif_set_tso_max_segs(bond_dev, tso_max_segs);
@@ -5769,18 +5770,18 @@ void bond_setup(struct net_device *bond_dev)
 	netdev_hw_feature_add(bond_dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	netdev_hw_feature_add(bond_dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
-	bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
-	bond_dev->features |= bond_dev->hw_features;
-	bond_dev->features |= netdev_tx_vlan_features;
+	netdev_hw_features_set(bond_dev, NETIF_F_GSO_ENCAP_ALL);
+	netdev_active_features_set(bond_dev, bond_dev->hw_features);
+	netdev_active_features_set(bond_dev, netdev_tx_vlan_features);
 #ifdef CONFIG_XFRM_OFFLOAD
-	bond_dev->hw_features |= BOND_XFRM_FEATURES;
+	netdev_hw_features_set(bond_dev, BOND_XFRM_FEATURES);
 	/* Only enable XFRM features if this is an active-backup config */
 	if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP)
-		bond_dev->features |= BOND_XFRM_FEATURES;
+		netdev_active_features_set(bond_dev, BOND_XFRM_FEATURES);
 #endif /* CONFIG_XFRM_OFFLOAD */
 #if IS_ENABLED(CONFIG_TLS_DEVICE)
 	if (bond_sk_check(bond))
-		bond_dev->features |= BOND_TLS_FEATURES;
+		netdev_active_features_set(bond_dev, BOND_TLS_FEATURES);
 #endif
 }
 
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 3498db1c1b3c..a90752e8aeef 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -8,6 +8,7 @@
 #include <linux/errno.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/spinlock.h>
 #include <linux/rcupdate.h>
 #include <linux/ctype.h>
@@ -835,7 +836,7 @@ static bool bond_set_xfrm_features(struct bonding *bond)
 		return false;
 
 	if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP)
-		bond->dev->wanted_features |= BOND_XFRM_FEATURES;
+		netdev_wanted_features_set(bond->dev, BOND_XFRM_FEATURES);
 	else
 		bond->dev->wanted_features &= ~BOND_XFRM_FEATURES;
 
@@ -848,7 +849,7 @@ static bool bond_set_tls_features(struct bonding *bond)
 		return false;
 
 	if (bond_sk_check(bond))
-		bond->dev->wanted_features |= BOND_TLS_FEATURES;
+		netdev_wanted_features_set(bond->dev, BOND_TLS_FEATURES);
 	else
 		bond->dev->wanted_features &= ~BOND_TLS_FEATURES;
 
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 6f176774efbd..ab196591a0bf 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -132,10 +132,10 @@ static void dummy_setup(struct net_device *dev)
 	dev->flags &= ~IFF_MULTICAST;
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
 	netdev_active_features_set_array(dev, &dummy_feature_set);
-	dev->features	|= NETIF_F_GSO_SOFTWARE;
-	dev->features	|= NETIF_F_GSO_ENCAP_ALL;
-	dev->hw_features |= dev->features;
-	dev->hw_enc_features |= dev->features;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
+	netdev_active_features_set(dev, NETIF_F_GSO_ENCAP_ALL);
+	netdev_hw_features_set(dev, dev->features);
+	netdev_hw_enc_features_set(dev, dev->features);
 	eth_hw_addr_random(dev);
 
 	dev->min_mtu = 0;
diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c
index a8989c1146bb..c88cdfef3f22 100644
--- a/drivers/net/ethernet/alacritech/slicoss.c
+++ b/drivers/net/ethernet/alacritech/slicoss.c
@@ -1781,7 +1781,7 @@ static int slic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->netdev_ops = &slic_netdev_ops;
 	netdev_hw_features_zero(dev);
 	netdev_hw_feature_add(dev, NETIF_F_RXCSUM_BIT);
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 
 	dev->ethtool_ops = &slic_ethtool_ops;
 
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 64f9ee8581ce..3539769a84bb 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -1558,7 +1558,7 @@ static int altera_tse_probe(struct platform_device *pdev)
 	 * so it is turned off
 	 */
 	ndev->hw_features &= ~NETIF_F_SG;
-	ndev->features |= ndev->hw_features;
+	netdev_active_features_set(ndev, ndev->hw_features);
 	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 
 	/* VLAN offloading of tagging, stripping and filtering is not
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index 202b10c77408..833f6e67e925 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -4050,8 +4050,8 @@ static void ena_set_dev_offloads(struct ena_com_dev_get_features_ctx *feat,
 	netdev->features = dev_features;
 	netdev_active_features_set_array(netdev, &ena_feature_set);
 
-	netdev->hw_features |= netdev->features;
-	netdev->vlan_features |= netdev->features;
+	netdev_hw_features_set(netdev, netdev->features);
+	netdev_vlan_features_set(netdev, netdev->features);
 }
 
 static void ena_set_conf_feat_params(struct ena_adapter *adapter,
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
index d94d982357b1..585f9f6bc8b8 100644
--- a/drivers/net/ethernet/amd/amd8111e.c
+++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -63,6 +63,7 @@ Revision History:
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -1791,7 +1792,7 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 #if AMD8111E_VLAN_TAG_USED
-	dev->features |= netdev_ctag_vlan_offload_features;
+	netdev_active_features_set(dev, netdev_ctag_vlan_offload_features);
 #endif
 
 	lp = netdev_priv(dev);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 4ee601db53cd..9d7ad79804e0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2203,7 +2203,7 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 	if ((features & vxlan_base) != vxlan_base) {
 		netdev_notice(netdev,
 			      "forcing both tx and rx udp tunnel support\n");
-		features |= vxlan_base;
+		netdev_features_set(&features, vxlan_base);
 	}
 
 	if (features & netdev_ip_csum_features) {
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index e6a050b6bdee..6f2071d6098c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -390,7 +390,7 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
 
 	netdev_vlan_features_set_array(netdev, &xgbe_vlan_feature_set);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	pdata->netdev_features = netdev->features;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 5d6eaefb8391..775fff8f67d0 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -383,7 +383,7 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 	const struct aq_hw_caps_s *aq_hw_caps = self->aq_nic_cfg.aq_hw_caps;
 	struct aq_nic_cfg_s *aq_nic_cfg = &self->aq_nic_cfg;
 
-	self->ndev->hw_features |= *aq_hw_caps->hw_features;
+	netdev_hw_features_set(self->ndev, *aq_hw_caps->hw_features);
 	self->ndev->features = *aq_hw_caps->hw_features;
 	netdev_vlan_features_set_array(self->ndev, &aq_nic_vlan_feature_set);
 	netdev_gso_partial_features_zero(self->ndev);
diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c
index 9309d371b8da..b6c193dbee99 100644
--- a/drivers/net/ethernet/asix/ax88796c_main.c
+++ b/drivers/net/ethernet/asix/ax88796c_main.c
@@ -1029,8 +1029,8 @@ static int ax88796c_probe(struct spi_device *spi)
 	ndev->irq = spi->irq;
 	ndev->netdev_ops = &ax88796c_netdev_ops;
 	ndev->ethtool_ops = &ax88796c_ethtool_ops;
-	ndev->hw_features |= ax88796c_features;
-	ndev->features |= ax88796c_features;
+	netdev_hw_features_set(ndev, ax88796c_features);
+	netdev_active_features_set(ndev, ax88796c_features);
 	ndev->needed_headroom = TX_OVERHEAD;
 	ndev->needed_tailroom = TX_EOP_SIZE;
 
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index e47f6325cfba..47b323c13448 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1392,7 +1392,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev_hw_features_zero(netdev);
 	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
-	netdev->features |= netdev_ctag_vlan_offload_features;
+	netdev_active_features_set(netdev, netdev_ctag_vlan_offload_features);
 
 	/* Init PHY as early as possible due to power saving issue  */
 	atl2_phy_init(&adapter->hw);
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 075bdded8e45..37eac9beda4e 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -18,6 +18,7 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/if_ether.h>
@@ -2359,7 +2360,7 @@ static int b44_init_one(struct ssb_device *sdev,
 	SET_NETDEV_DEV(dev, sdev->dev);
 
 	/* No interesting netdevice features in this card... */
-	dev->features |= netdev_empty_features;
+	netdev_active_features_set(dev, netdev_empty_features);
 
 	bp = netdev_priv(dev);
 	bp->sdev = sdev;
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 05a0c169e418..471be11b949c 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -2583,8 +2583,8 @@ static int bcm_sysport_probe(struct platform_device *pdev)
 	netif_napi_add(dev, &priv->napi, bcm_sysport_poll, 64);
 
 	netdev_active_features_set_array(dev, &bcm_feature_set);
-	dev->hw_features |= dev->features;
-	dev->vlan_features |= dev->features;
+	netdev_hw_features_set(dev, dev->features);
+	netdev_vlan_features_set(dev, dev->features);
 	dev->max_mtu = UMAC_MAX_MTU_SIZE;
 
 	/* Request the WOL interrupt and advertise suspend if available */
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index a47dd8ae6e8d..8455b0679670 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -7758,7 +7758,7 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
 		netdev_features_t tso;
 
 		tso = dev->hw_features & NETIF_F_ALL_TSO;
-		dev->vlan_features |= tso;
+		netdev_vlan_features_set(dev, tso);
 	} else {
 		dev->vlan_features &= ~NETIF_F_ALL_TSO;
 	}
@@ -8602,8 +8602,8 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 
 	dev->vlan_features = dev->hw_features;
-	dev->hw_features |= netdev_ctag_vlan_offload_features;
-	dev->features |= dev->hw_features;
+	netdev_hw_features_set(dev, netdev_ctag_vlan_offload_features);
+	netdev_active_features_set(dev, dev->hw_features);
 	dev->priv_flags |= IFF_UNICAST_FLT;
 	dev->min_mtu = MIN_ETHERNET_PACKET_SIZE;
 	dev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index fe618561b712..92a1e370eac6 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13278,7 +13278,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 	 * getting a response to CHANNEL_TLV_ACQUIRE from PF.
 	 */
 
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (dev->features & NETIF_F_LRO)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index a45a5c5684ca..258d9491a2f7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11203,7 +11203,8 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 		if (dev->features & BNXT_HW_FEATURE_VLAN_ALL_RX)
 			features &= ~BNXT_HW_FEATURE_VLAN_ALL_RX;
 		else if (vlan_features)
-			features |= BNXT_HW_FEATURE_VLAN_ALL_RX;
+			netdev_features_set(&features,
+					    BNXT_HW_FEATURE_VLAN_ALL_RX);
 	}
 #ifdef CONFIG_BNXT_SRIOV
 	if (BNXT_VF(bp) && bp->vf.vlan)
@@ -13648,12 +13649,12 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->vlan_features = dev->hw_features;
 	netdev_vlan_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (bp->fw_cap & BNXT_FW_CAP_VLAN_RX_STRIP)
-		dev->hw_features |= BNXT_HW_FEATURE_VLAN_ALL_RX;
+		netdev_hw_features_set(dev, BNXT_HW_FEATURE_VLAN_ALL_RX);
 	if (bp->fw_cap & BNXT_FW_CAP_VLAN_TX_INSERT)
-		dev->hw_features |= BNXT_HW_FEATURE_VLAN_ALL_TX;
+		netdev_hw_features_set(dev, BNXT_HW_FEATURE_VLAN_ALL_TX);
 	if (BNXT_SUPPORTS_TPA(bp))
 		netdev_hw_feature_add(dev, NETIF_F_GRO_HW_BIT);
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (dev->features & NETIF_F_GRO_HW)
 		dev->features &= ~NETIF_F_LRO;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index eb4803b11c0e..efd34f4ccd6a 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -8,6 +8,7 @@
  */
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/jhash.h>
@@ -472,7 +473,7 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
 	dev->gso_partial_features = pf_dev->gso_partial_features;
 	dev->vlan_features = pf_dev->vlan_features;
 	dev->hw_enc_features = pf_dev->hw_enc_features;
-	dev->features |= pf_dev->features;
+	netdev_active_features_set(dev, pf_dev->features);
 	bnxt_vf_rep_eth_addr_gen(bp->pf.mac_addr, vf_rep->vf_idx,
 				 dev->perm_addr);
 	eth_hw_addr_set(dev, dev->perm_addr);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 0d41ae12e262..4157ab4acfb0 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -4033,8 +4033,8 @@ static int bcmgenet_probe(struct platform_device *pdev)
 
 	/* Set default features */
 	netdev_active_features_set_array(dev, &bcmgenet_feature_set);
-	dev->hw_features |= dev->features;
-	dev->vlan_features |= dev->features;
+	netdev_hw_features_set(dev, dev->features);
+	netdev_vlan_features_set(dev, dev->features);
 
 	/* Request the WOL interrupt and advertise suspend if available */
 	priv->wol_irq_disabled = true;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index ad927bc15d12..841c6dc1546f 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17755,9 +17755,9 @@ static int tg3_init_one(struct pci_dev *pdev,
 			netdev_feature_add(NETIF_F_TSO_ECN_BIT, &features);
 	}
 
-	dev->features |= features;
-	dev->features |= netdev_ctag_vlan_offload_features;
-	dev->vlan_features |= features;
+	netdev_active_features_set(dev, features);
+	netdev_active_features_set(dev, netdev_ctag_vlan_offload_features);
+	netdev_vlan_features_set(dev, features);
 
 	/*
 	 * Add loopback capability only for a subset of devices that support
@@ -17769,7 +17769,7 @@ static int tg3_init_one(struct pci_dev *pdev,
 		/* Add the loopback capability */
 		netdev_feature_add(NETIF_F_LOOPBACK_BIT, &features);
 
-	dev->hw_features |= features;
+	netdev_hw_features_set(dev, features);
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
 	/* MTU range: 60 - 9000 or 1500, depending on hardware */
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 786df1e64947..e0732e92657b 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3450,7 +3450,7 @@ bnad_netdev_init(struct bnad *bnad)
 	netdev_vlan_features_zero(netdev);
 	netdev_vlan_features_set_array(netdev, &bnad_vlan_feature_set);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	netdev_active_features_set_array(netdev, &bnad_feature_set);
 
 	netdev->mem_start = bnad->mmio_start;
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 415f61527650..fc3d688c1228 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1787,7 +1787,7 @@ static int xgmac_probe(struct platform_device *pdev)
 	netdev_hw_features_set_array(ndev, &xgmac_hw_feature_set);
 	if (readl(priv->base + XGMAC_DMA_HW_FEATURE) & DMA_HW_FEAT_TXCOESEL)
 		netdev_hw_features_set_array(ndev, &xgmac_csum_feature_set);
-	ndev->features |= ndev->hw_features;
+	netdev_active_features_set(ndev, ndev->hw_features);
 	ndev->priv_flags |= IFF_UNICAST_FLT;
 
 	/* MTU range: 46 - 9000 */
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index fafd248977ed..aa2e0d3537a3 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3600,7 +3600,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 
 		netdev->vlan_features = lio->dev_capability;
 		/* Add any unchangeable hw features */
-		lio->dev_capability |= netdev_ctag_vlan_features;
+		netdev_features_set(&lio->dev_capability, netdev_ctag_vlan_features);
 
 		netdev->features = lio->dev_capability;
 		netdev->features &= ~NETIF_F_LRO;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 688a6c4931b9..6ee1032b3dad 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -2128,7 +2128,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 
 		netdev->vlan_features = lio->dev_capability;
 		/* Add any unchangeable hw features */
-		lio->dev_capability |= netdev_ctag_vlan_features;
+		netdev_features_set(&lio->dev_capability, netdev_ctag_vlan_features);
 
 		netdev->features = lio->dev_capability;
 		netdev->features &= ~NETIF_F_LRO;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index e806eb803dd5..67ad6c5e539f 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -2225,7 +2225,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	netdev_hw_feature_add(netdev, NETIF_F_LOOPBACK_BIT);
 
 	netdev_vlan_features_zero(netdev);
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 3174489477bc..80cc1f6fcfef 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -1048,7 +1048,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_active_features_set_array(netdev, &cxgb_feature_set);
 
 		if (vlan_tso_capable(adapter)) {
-			netdev->features |= netdev_ctag_vlan_offload_features;
+			netdev_active_features_set(netdev,
+						   netdev_ctag_vlan_offload_features);
 			netdev_hw_feature_add(netdev,
 					      NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 35daa61d3c4f..c6d08aceffa0 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3321,12 +3321,12 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev->mem_end = mmio_start + mmio_len - 1;
 		netdev_hw_features_zero(netdev);
 		netdev_hw_features_set_array(netdev, &cxgb_hw_feature_set);
-		netdev->features |= netdev->hw_features;
+		netdev_active_features_set(netdev, netdev->hw_features);
 		netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 		netdev_features_zero(&vlan_feat);
 		netdev_features_set_array(&cxgb_vlan_feature_set, &vlan_feat);
 		vlan_feat &= netdev->features;
-		netdev->vlan_features |= vlan_feat;
+		netdev_vlan_features_set(netdev, vlan_feat);
 
 		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index e5f29203a496..fd2e42662dd5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6861,7 +6861,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 				netdev->udp_tunnel_nic_info = &cxgb_udp_tunnels;
 		}
 
-		netdev->features |= netdev->hw_features;
+		netdev_active_features_set(netdev, netdev->hw_features);
 		vlan_features = tso_features;
 		netdev_features_set_array(&cxgb4_vlan_feature_set, &vlan_features);
 		netdev->vlan_features = netdev->features & vlan_features;
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 77379e284cb9..5e67f4cd4285 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2894,7 +2894,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->watchdog_timeo = 2 * HZ;
 	enic_set_ethtool_ops(netdev);
 
-	netdev->features |= netdev_ctag_vlan_offload_features;
+	netdev_active_features_set(netdev, netdev_ctag_vlan_offload_features);
 	if (ENIC_SETTING(enic, LOOP)) {
 		netdev->features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 		enic->loop_enable = 1;
@@ -2906,7 +2906,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_hw_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
 	}
 	if (ENIC_SETTING(enic, TSO)) {
-		netdev->hw_features |= netdev_general_tso_features;
+		netdev_hw_features_set(netdev, netdev_general_tso_features);
 		netdev_hw_feature_add(netdev, NETIF_F_TSO_ECN_BIT);
 	}
 	if (ENIC_SETTING(enic, RSS))
@@ -2919,7 +2919,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 		netdev_hw_enc_features_set_array(netdev,
 						 &enic_hw_enc_feature_set);
-		netdev->hw_features |= netdev->hw_enc_features;
+		netdev_hw_features_set(netdev, netdev->hw_enc_features);
 		/* get bit mask from hw about supported offload bit level
 		 * BIT(0) = fw supports patch_level 0
 		 *	    fcoe bit = encap
@@ -2952,8 +2952,8 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		}
 	}
 
-	netdev->features |= netdev->hw_features;
-	netdev->vlan_features |= netdev->features;
+	netdev_active_features_set(netdev, netdev->hw_features);
+	netdev_vlan_features_set(netdev, netdev->features);
 
 #ifdef CONFIG_RFS_ACCEL
 	netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 09e2dc3bd280..6acb087baa6b 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -2471,7 +2471,7 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
 	gmac_clear_hw_stats(netdev);
 
 	netdev->hw_features = GMAC_OFFLOAD_FEATURES;
-	netdev->features |= GMAC_OFFLOAD_FEATURES;
+	netdev_active_features_set(netdev, GMAC_OFFLOAD_FEATURES);
 	netdev_active_feature_add(netdev, NETIF_F_GRO_BIT);
 	/* We can handle jumbo frames up to 10236 bytes so, let's accept
 	 * payloads of 10236 bytes minus VLAN and ethernet header
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index c90d8be25be5..8d3e3b3413d3 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -1648,7 +1648,7 @@ dm9000_probe(struct platform_device *pdev)
 		netdev_hw_features_zero(ndev);
 		netdev_hw_feature_add(ndev, NETIF_F_RXCSUM_BIT);
 		netdev_hw_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
-		ndev->features |= ndev->hw_features;
+		netdev_active_features_set(ndev, ndev->hw_features);
 	}
 
 	/* from this point we assume that we have found a DM9000 */
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index 7f4dcea2cd87..81f07336d205 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
@@ -763,7 +764,7 @@ static int dnet_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	/* TODO: Actually, we have some interesting features... */
-	dev->features |= netdev_empty_features;
+	netdev_active_features_set(dev, netdev_empty_features);
 
 	bp = netdev_priv(dev);
 	bp->dev = dev;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 0a29313e167a..ed6339b57841 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5218,7 +5218,7 @@ static void be_netdev_init(struct net_device *netdev)
 	if ((be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
 		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	netdev_active_features_set_array(netdev, &be_feature_set);
 
 	netdev_vlan_features_set_array(netdev, &be_vlan_feature_set);
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 3ced63aaa6cb..1d62b8f04188 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mii.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
@@ -1220,7 +1221,7 @@ static int ethoc_probe(struct platform_device *pdev)
 	/* setup the net_device structure */
 	netdev->netdev_ops = &ethoc_netdev_ops;
 	netdev->watchdog_timeo = ETHOC_TIMEOUT;
-	netdev->features |= netdev_empty_features;
+	netdev_active_features_set(netdev, netdev_empty_features);
 	netdev->ethtool_ops = &ethoc_ethtool_ops;
 
 	/* setup NAPI */
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index c286e0039851..17525ce5f682 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1957,7 +1957,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
 		netdev->hw_features &= ~NETIF_F_HW_CSUM;
 		netdev->hw_features &= ~NETIF_F_RXCSUM;
 	}
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 
 	/* register network device */
 	err = register_netdev(netdev);
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index c0cd9b14ef72..6f9bde1c4153 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -244,7 +244,7 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 	/* we do not want shared skbs on TX */
 	net_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 
-	net_dev->features |= net_dev->hw_features;
+	netdev_active_features_set(net_dev, net_dev->hw_features);
 	net_dev->vlan_features = net_dev->features;
 
 	if (is_valid_ether_addr(mac_addr)) {
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 26861683f699..18efcb947d0f 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -3257,7 +3257,7 @@ static int gfar_probe(struct platform_device *ofdev)
 	}
 
 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
-		dev->hw_features |= netdev_ctag_vlan_offload_features;
+		netdev_hw_features_set(dev, netdev_ctag_vlan_offload_features);
 		netdev_active_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	}
 
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_main.c b/drivers/net/ethernet/fungible/funeth/funeth_main.c
index fd981e357f2f..0fee1effb7ce 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1784,18 +1784,18 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 
 	netdev_features_set_array(&fun_gso_encap_feature_set, &gso_encap_flags);
 	netdev_features_set_array(&fun_tso_feature_set, &tso_flags);
-	vlan_feat = gso_encap_flags | tso_flags;
+	vlan_feat = netdev_features_or(gso_encap_flags, tso_flags);
 	netdev_features_set_array(&fun_vlan_feature_set, &vlan_feat);
 
 	netdev_hw_features_set_array(netdev, &fun_hw_feature_set);
 	if (fp->port_caps & FUN_PORT_CAP_OFFLOADS) {
 		netdev_hw_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
-		netdev->hw_features |= tso_flags;
+		netdev_hw_features_set(netdev, tso_flags);
 	}
 	if (fp->port_caps & FUN_PORT_CAP_ENCAP_OFFLOADS)
-		netdev->hw_features |= gso_encap_flags;
+		netdev_hw_features_set(netdev, gso_encap_flags);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 	netdev->vlan_features = netdev->features & vlan_feat;
 	netdev->mpls_features = netdev->vlan_features;
diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
index bf79258b4904..a2d2ac6503ff 100644
--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
@@ -1237,9 +1237,9 @@ static int hix5hd2_dev_probe(struct platform_device *pdev)
 	if (HAS_CAP_TSO(priv->hw_cap))
 		netdev_hw_feature_add(ndev, NETIF_F_SG_BIT);
 
-	ndev->features |= ndev->hw_features;
+	netdev_active_features_set(ndev, ndev->hw_features);
 	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
-	ndev->vlan_features |= ndev->features;
+	netdev_vlan_features_set(ndev, ndev->features);
 
 	ret = hix5hd2_init_hw_desc_queue(priv);
 	if (ret)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 3a5a2adba3a2..837ff9f4e131 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -2364,7 +2364,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
 	case AE_VERSION_2:
 		netdev_active_features_set_array(ndev, &hns_v2_feature_set);
 		netdev_hw_features_set_array(ndev, &hns_hw_feature_set);
-		ndev->vlan_features |= netdev_general_tso_features;
+		netdev_vlan_features_set(ndev, netdev_general_tso_features);
 		ndev->max_mtu = MAC_MAX_MTU_V2 -
 				(ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
 		break;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index e67a30738a2d..30f231610e61 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -3305,7 +3305,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,
@@ -3314,7 +3314,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;
 
@@ -3322,9 +3322,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/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 5e8d43e04b53..87c277fc95c4 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -3177,7 +3177,7 @@ static int emac_probe(struct platform_device *ofdev)
 	if (dev->tah_dev) {
 		netdev_hw_features_zero(ndev);
 		netdev_hw_features_set_array(ndev, &emac_hw_feature_set);
-		ndev->features |= ndev->hw_features;
+		netdev_active_features_set(ndev, ndev->hw_features);
 		netdev_active_feature_add(ndev, NETIF_F_RXCSUM_BIT);
 	}
 	ndev->watchdog_timeo = 5 * HZ;
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 9d5b99ce60c2..4687a22434ed 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1689,15 +1689,15 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 	if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL)
 		netdev_hw_features_set_array(netdev, &ibmveth_hw_feature_set);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 
 	ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr);
 
 	/* If running older firmware, TSO should not be enabled by default */
 	if (ret == H_SUCCESS && (ret_attr & IBMVETH_ILLAN_LRG_SND_SUPPORT) &&
 	    !old_large_send) {
-		netdev->hw_features |= netdev_general_tso_features;
-		netdev->features |= netdev->hw_features;
+		netdev_hw_features_set(netdev, netdev_general_tso_features);
+		netdev_active_features_set(netdev, netdev->hw_features);
 	} else {
 		netdev_hw_feature_add(netdev, NETIF_F_TSO_BIT);
 	}
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 5b757634973d..b5fa773272dd 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4893,7 +4893,8 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 		netdev_hw_feature_add(adapter->netdev, NETIF_F_TSO6_BIT);
 
 	if (adapter->state == VNIC_PROBING) {
-		adapter->netdev->features |= adapter->netdev->hw_features;
+		netdev_active_features_set(adapter->netdev,
+					   adapter->netdev->hw_features);
 	} else if (old_hw_features != adapter->netdev->hw_features) {
 		netdev_features_t tmp = netdev_empty_features;
 
@@ -4903,7 +4904,7 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 		tmp = old_hw_features ^ adapter->netdev->hw_features;
 		tmp &= adapter->netdev->hw_features;
 		tmp &= adapter->netdev->wanted_features;
-		adapter->netdev->features |= tmp;
+		netdev_active_features_set(adapter->netdev, tmp);
 	}
 
 	memset(&crq, 0, sizeof(crq));
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index ea3a958a8945..acf68d405812 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -1063,7 +1063,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	netdev_hw_features_set_array(netdev, &e1000_hw_rx_feature_set);
 
 	if (pci_using_dac) {
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 439fb2110c55..a2b28da7a56e 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -5305,7 +5305,8 @@ static void e1000_watchdog_task(struct work_struct *work)
 					netdev->features &= ~netdev_general_tso_features;
 					break;
 				case SPEED_1000:
-					netdev->features |= netdev_general_tso_features;
+					netdev_active_features_set(netdev,
+								   netdev_general_tso_features);
 					break;
 				default:
 					/* oops */
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index e51f05bfaa1d..3b9df01b313e 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1595,17 +1595,17 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
 	netdev_feature_add(NETIF_F_HW_L2FW_DOFFLOAD_BIT, &hw_features);
 
 	/* configure VLAN features */
-	dev->vlan_features |= dev->features;
+	netdev_vlan_features_set(dev, dev->features);
 
 	/* we want to leave these both on as we cannot disable VLAN tag
 	 * insertion or stripping on the hardware since it is contained
 	 * in the FTAG and not in the frame itself.
 	 */
-	dev->features |= netdev_ctag_vlan_features;
+	netdev_active_features_set(dev, netdev_ctag_vlan_features);
 
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
-	dev->hw_features |= hw_features;
+	netdev_hw_features_set(dev, hw_features);
 
 	/* MTU range: 68 - 15342 */
 	dev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 0eb64901e3e1..25a2b77ffd6f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13687,10 +13687,10 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 
 	netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_GRE_CSUM_BIT);
 
-	netdev->hw_enc_features |= hw_enc_features;
+	netdev_hw_enc_features_set(netdev, hw_enc_features);
 
 	/* record features VLANs can make use of */
-	netdev->vlan_features |= hw_enc_features;
+	netdev_vlan_features_set(netdev, hw_enc_features);
 	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 
 	netdev_features_zero(&gso_partial_features);
@@ -13698,24 +13698,25 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 				  &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
 	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
-	netdev->features |= gso_partial_features;
+	netdev_active_features_set(netdev, gso_partial_features);
 
 	netdev_mpls_features_set_array(netdev, &i40e_mpls_feature_set);
-	netdev->mpls_features |= gso_partial_features;
+	netdev_mpls_features_set(netdev, gso_partial_features);
 
 	/* enable macvlan offloads */
 	netdev_hw_feature_add(netdev, NETIF_F_HW_L2FW_DOFFLOAD_BIT);
 
-	hw_features = hw_enc_features | netdev_ctag_vlan_offload_features;
+	hw_features = netdev_features_or(hw_enc_features,
+					 netdev_ctag_vlan_offload_features);
 
 	if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) {
 		netdev_feature_add(NETIF_F_NTUPLE_BIT, &hw_features);
 		netdev_feature_add(NETIF_F_HW_TC_BIT, &hw_features);
 	}
 
-	netdev->hw_features |= hw_features;
+	netdev_hw_features_set(netdev, hw_features);
 
-	netdev->features |= hw_features;
+	netdev_active_features_set(netdev, hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 19b79755ddda..ae8471342166 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4324,7 +4324,8 @@ iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter)
 
 	/* Enable VLAN features if supported */
 	if (VLAN_ALLOWED(adapter)) {
-		hw_features |= netdev_ctag_vlan_offload_features;
+		netdev_features_set(&hw_features,
+				    netdev_ctag_vlan_offload_features);
 	} else if (VLAN_V2_ALLOWED(adapter)) {
 		struct virtchnl_vlan_caps *vlan_v2_caps =
 			&adapter->vlan_v2_caps;
@@ -4390,7 +4391,7 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 		return features;
 
 	if (VLAN_ALLOWED(adapter)) {
-		features |= netdev_ctag_vlan_features;
+		netdev_features_set(&features, netdev_ctag_vlan_features);
 	} else if (VLAN_V2_ALLOWED(adapter)) {
 		struct virtchnl_vlan_caps *vlan_v2_caps =
 			&adapter->vlan_v2_caps;
@@ -4497,8 +4498,8 @@ iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
 {
 	netdev_features_t allowed_features;
 
-	allowed_features = iavf_get_netdev_vlan_hw_features(adapter) |
-		iavf_get_netdev_vlan_features(adapter);
+	allowed_features = netdev_features_or(iavf_get_netdev_vlan_hw_features(adapter),
+					      iavf_get_netdev_vlan_features(adapter));
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
@@ -4646,10 +4647,10 @@ int iavf_process_config(struct iavf_adapter *adapter)
 		netdev_gso_partial_feature_add(netdev,
 					       NETIF_F_GSO_GRE_CSUM_BIT);
 		netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
-		netdev->hw_enc_features |= hw_enc_features;
+		netdev_hw_enc_features_set(netdev, hw_enc_features);
 	}
 	/* record features VLANs can make use of */
-	netdev->vlan_features |= hw_enc_features;
+	netdev_vlan_features_set(netdev, hw_enc_features);
 	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 
 	/* Write features and hw_features separately to avoid polluting
@@ -4666,12 +4667,12 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_USO)
 		netdev_feature_add(NETIF_F_GSO_UDP_L4_BIT, &hw_features);
 
-	netdev->hw_features |= hw_features;
-	netdev->hw_features |= hw_vlan_features;
+	netdev_hw_features_set(netdev, hw_features);
+	netdev_hw_features_set(netdev, hw_vlan_features);
 	vlan_features = iavf_get_netdev_vlan_features(adapter);
 
-	netdev->features |= hw_features;
-	netdev->features |= vlan_features;
+	netdev_active_features_set(netdev, hw_features);
+	netdev_active_features_set(netdev, vlan_features);
 
 	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
 		netdev_active_feature_add(netdev,
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index d0ecd7f3302a..d71c226ae5af 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3365,27 +3365,27 @@ static void ice_set_netdev_features(struct net_device *netdev)
 				       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	netdev_gso_partial_feature_add(netdev, NETIF_F_GSO_GRE_CSUM_BIT);
 	/* set features that user can change */
-	netdev->hw_features = dflt_features | csumo_features;
-	netdev->hw_features |= vlano_features;
-	netdev->hw_features |= tso_features;
+	netdev->hw_features = netdev_features_or(dflt_features, csumo_features);
+	netdev_hw_features_set(netdev, vlano_features);
+	netdev_hw_features_set(netdev, tso_features);
 
 	/* add support for HW_CSUM on packets with MPLS header */
 	netdev_mpls_features_zero(netdev);
 	netdev_mpls_features_set_array(netdev, &ice_mpls_feature_set);
 
 	/* enable features */
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 
 	netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 	netdev_hw_feature_add(netdev, NETIF_F_LOOPBACK_BIT);
 
 	/* encap and VLAN devices inherit default, csumo and tso features */
-	netdev->hw_enc_features |= dflt_features;
-	netdev->hw_enc_features |= csumo_features;
-	netdev->hw_enc_features |= tso_features;
-	netdev->vlan_features |= dflt_features;
-	netdev->vlan_features |= csumo_features;
-	netdev->vlan_features |= tso_features;
+	netdev_hw_enc_features_set(netdev, dflt_features);
+	netdev_hw_enc_features_set(netdev, csumo_features);
+	netdev_hw_enc_features_set(netdev, tso_features);
+	netdev_vlan_features_set(netdev, dflt_features);
+	netdev_vlan_features_set(netdev, csumo_features);
+	netdev_vlan_features_set(netdev, tso_features);
 
 	/* advertise support but don't enable by default since only one type of
 	 * VLAN offload can be enabled at a time (i.e. CTAG or STAG). When one
@@ -3393,7 +3393,7 @@ static void ice_set_netdev_features(struct net_device *netdev)
 	 * ice_fix_features() ndo callback.
 	 */
 	if (is_dvm_ena)
-		netdev->hw_features |= netdev_stag_vlan_offload_features;
+		netdev_hw_features_set(netdev, netdev_stag_vlan_offload_features);
 }
 
 /**
@@ -5791,12 +5791,14 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 	if (req_vlan_fltr != cur_vlan_fltr) {
 		if (ice_is_dvm_ena(&np->vsi->back->hw)) {
 			if (req_ctag && req_stag) {
-				features |= NETIF_VLAN_FILTERING_FEATURES;
+				netdev_features_set(&features,
+						    NETIF_VLAN_FILTERING_FEATURES);
 			} else if (!req_ctag && !req_stag) {
 				features &= ~NETIF_VLAN_FILTERING_FEATURES;
 			} else if ((!cur_ctag && req_ctag && !cur_stag) ||
 				   (!cur_stag && req_stag && !cur_ctag)) {
-				features |= NETIF_VLAN_FILTERING_FEATURES;
+				netdev_features_set(&features,
+						    NETIF_VLAN_FILTERING_FEATURES);
 				netdev_warn(netdev,  "802.1Q and 802.1ad VLAN filtering must be either both on or both off. VLAN filtering has been enabled for both types.\n");
 			} else if ((cur_ctag && !req_ctag && cur_stag) ||
 				   (cur_stag && !req_stag && cur_ctag)) {
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 14e391e4bc23..c6b1d30ba2f6 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3310,11 +3310,11 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_features_set_array(&igb_feature_set, &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
 	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
-	netdev->features |= gso_partial_features;
+	netdev_active_features_set(netdev, gso_partial_features);
 
 	/* copy netdev features into list of user selectable features */
-	netdev->hw_features |= netdev->features;
-	netdev->hw_features |= netdev_ctag_vlan_offload_features;
+	netdev_hw_features_set(netdev, netdev->features);
+	netdev_hw_features_set(netdev, netdev_ctag_vlan_offload_features);
 	netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
 
 	if (hw->mac.type >= e1000_i350)
@@ -3322,13 +3322,13 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
-	netdev->vlan_features |= netdev->features;
+	netdev_vlan_features_set(netdev, netdev->features);
 	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 	netdev_mpls_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
-	netdev->hw_enc_features |= netdev->vlan_features;
+	netdev_hw_enc_features_set(netdev, netdev->vlan_features);
 
 	/* set this bit last since it cannot be part of vlan_features */
-	netdev->features |= netdev_ctag_vlan_features;
+	netdev_active_features_set(netdev, netdev_ctag_vlan_features);
 
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 55685206eac1..7d04d87157de 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2795,18 +2795,18 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev->gso_partial_features = gso_partial_features;
 	netdev_hw_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
-	netdev->hw_features |= gso_partial_features;
+	netdev_hw_features_set(netdev, gso_partial_features);
 
 	netdev->features = netdev->hw_features;
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
-	netdev->vlan_features |= netdev->features;
+	netdev_vlan_features_set(netdev, netdev->features);
 	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 	netdev_mpls_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
-	netdev->hw_enc_features |= netdev->vlan_features;
+	netdev_hw_enc_features_set(netdev, netdev->vlan_features);
 
 	/* set this bit last since it cannot be part of vlan_features */
-	netdev->features |= netdev_ctag_vlan_features;
+	netdev_active_features_set(netdev, netdev_ctag_vlan_features);
 
 	/* MTU range: 68 - 9216 */
 	netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index f53175a80606..c594dfeb5dfd 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6336,7 +6336,7 @@ static int igc_probe(struct pci_dev *pdev,
 				  &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
 	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
-	netdev->features |= gso_partial_features;
+	netdev_active_features_set(netdev, gso_partial_features);
 
 	/* setup the private structure */
 	err = igc_sw_init(adapter);
@@ -6347,14 +6347,14 @@ static int igc_probe(struct pci_dev *pdev,
 	netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
 	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
-	netdev->hw_features |= netdev->features;
+	netdev_hw_features_set(netdev, netdev->features);
 
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
-	netdev->vlan_features |= netdev->features;
+	netdev_vlan_features_set(netdev, netdev->features);
 	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 	netdev_mpls_feature_add(netdev, NETIF_F_HW_CSUM_BIT);
-	netdev->hw_enc_features |= netdev->vlan_features;
+	netdev_hw_enc_features_set(netdev, netdev->vlan_features);
 
 	/* MTU range: 68 - 9216 */
 	netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 40228bff5e82..727df1a82ec0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -11022,7 +11022,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev->gso_partial_features = gso_partial_features;
 	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
-	netdev->features |= gso_partial_features;
+	netdev_active_features_set(netdev, gso_partial_features);
 
 	if (hw->mac.type >= ixgbe_mac_82599EB) {
 		netdev_active_feature_add(netdev, NETIF_F_SCTP_CRC_BIT);
@@ -11034,7 +11034,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_active_features_set_array(netdev, &ixgbe_esp_feature_set);
 #endif
 	/* copy netdev features into list of user selectable features */
-	netdev->hw_features |= netdev->features;
+	netdev_hw_features_set(netdev, netdev->features);
 	netdev_hw_features_set_array(netdev, &ixgbe_hw_feature_set);
 
 	if (hw->mac.type >= ixgbe_mac_82599EB) {
@@ -11044,14 +11044,14 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
-	netdev->vlan_features |= netdev->features;
+	netdev_vlan_features_set(netdev, netdev->features);
 	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
-	netdev->hw_enc_features |= netdev->vlan_features;
+	netdev_hw_enc_features_set(netdev, netdev->vlan_features);
 	netdev_mpls_features_set_array(netdev, &ixgbe_mpls_feature_set);
-	netdev->mpls_features |= gso_partial_features;
+	netdev_mpls_features_set(netdev, gso_partial_features);
 
 	/* set this bit last since it cannot be part of vlan_features */
-	netdev->features |= netdev_ctag_vlan_features;
+	netdev_active_features_set(netdev, netdev_ctag_vlan_features);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 79d2400b03df..bca192bf7ed9 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4634,20 +4634,20 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				  &gso_partial_features);
 	netdev->gso_partial_features = gso_partial_features;
 	netdev_hw_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
-	netdev->hw_features |= gso_partial_features;
+	netdev_hw_features_set(netdev, gso_partial_features);
 
 	netdev->features = netdev->hw_features;
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
-	netdev->vlan_features |= netdev->features;
+	netdev_vlan_features_set(netdev, netdev->features);
 	netdev_vlan_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 
 	netdev_mpls_features_set_array(netdev, &ixgbevf_mpls_feature_set);
-	netdev->mpls_features |= gso_partial_features;
-	netdev->hw_enc_features |= netdev->vlan_features;
+	netdev_mpls_features_set(netdev, gso_partial_features);
+	netdev_hw_enc_features_set(netdev, netdev->vlan_features);
 
 	/* set this bit last since it cannot be part of vlan_features */
-	netdev->features |= netdev_ctag_vlan_features;
+	netdev_active_features_set(netdev, netdev_ctag_vlan_features);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 3b9c7257622d..c2a77f161286 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -5623,8 +5623,8 @@ static int mvneta_probe(struct platform_device *pdev)
 
 	netdev_active_features_zero(dev);
 	netdev_active_features_set_array(dev, &mvneta_feature_set);
-	dev->hw_features |= dev->features;
-	dev->vlan_features |= dev->features;
+	netdev_hw_features_set(dev, dev->features);
+	netdev_vlan_features_set(dev, dev->features);
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 	netif_set_tso_max_segs(dev, MVNETA_MAX_TSO_SEGS);
 
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index ce17ed4b8828..c6f608388dff 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1278,8 +1278,8 @@ static void mvpp2_set_hw_csum(struct mvpp2_port *port,
 		port->dev->features &= ~csums;
 		port->dev->hw_features &= ~csums;
 	} else {
-		port->dev->features |= csums;
-		port->dev->hw_features |= csums;
+		netdev_active_features_set(port->dev, csums);
+		netdev_hw_features_set(port->dev, csums);
 	}
 }
 
@@ -1344,8 +1344,9 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
 			dev->features &= ~netdev_ip_csum_features;
 			dev->hw_features &= ~netdev_ip_csum_features;
 		} else {
-			dev->features |= netdev_ip_csum_features;
-			dev->hw_features |= netdev_ip_csum_features;
+			netdev_active_features_set(dev,
+						   netdev_ip_csum_features);
+			netdev_hw_features_set(dev, netdev_ip_csum_features);
 		}
 	}
 
@@ -6860,7 +6861,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 	netdev_features_set_array(&mvpp2_feature_set, &features);
 	dev->features = features;
 	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
-	dev->hw_features |= features;
+	netdev_hw_features_set(dev, features);
 	netdev_hw_features_set_array(dev, &mvpp2_hw_feature_set);
 
 	if (mvpp22_rss_is_supported(port)) {
@@ -6871,7 +6872,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 	if (!port->priv->percpu_pools)
 		mvpp2_set_hw_csum(port, port->pool_long->id);
 
-	dev->vlan_features |= features;
+	netdev_vlan_features_set(dev, features);
 	netif_set_tso_max_segs(dev, MVPP2_MAX_TSO_SEGS);
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index bde76afe991d..3e7bb0126b12 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -1067,7 +1067,7 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev_hw_features_zero(netdev);
 	netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	netdev->min_mtu = OCTEP_MIN_MTU;
 	netdev->max_mtu = OCTEP_MAX_MTU;
 	netdev->mtu = OCTEP_DEFAULT_MTU;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index fc61e17b300f..ef2d175f586b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -2705,7 +2705,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_array(netdev, &otx2_hw_feature_set);
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 
 	err = otx2_mcam_flow_init(pf);
 	if (err)
@@ -2718,11 +2718,11 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 
 	/* Support TSO on tag interface */
-	netdev->vlan_features |= netdev->features;
-	netdev->hw_features  |= netdev_tx_vlan_features;
+	netdev_vlan_features_set(netdev, netdev->features);
+	netdev_hw_features_set(netdev, netdev_tx_vlan_features);
 	if (pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT)
-		netdev->hw_features |= netdev_rx_vlan_features;
-	netdev->features |= netdev->hw_features;
+		netdev_hw_features_set(netdev, netdev_rx_vlan_features);
+	netdev_active_features_set(netdev, netdev->hw_features);
 
 	/* HW supports tc offload but mutually exclusive with n-tuple filters */
 	if (pf->flags & OTX2_FLAG_TC_FLOWER_SUPPORT)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index d75a09f291b0..3303e9b631b2 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -652,9 +652,9 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	netdev_hw_features_set_array(netdev, &otx2vf_hw_feature_set);
 	netdev->features = netdev->hw_features;
 	/* Support TSO on tag interface */
-	netdev->vlan_features |= netdev->features;
-	netdev->hw_features  |= netdev_tx_vlan_features;
-	netdev->features |= netdev->hw_features;
+	netdev_vlan_features_set(netdev, netdev->features);
+	netdev_hw_features_set(netdev, netdev_tx_vlan_features);
+	netdev_active_features_set(netdev, netdev->hw_features);
 
 	netdev_hw_feature_add(netdev, NETIF_F_NTUPLE_BIT);
 	netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 9f16ade3e439..cd2636ef08d3 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3867,7 +3867,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 	else {
 		netdev_hw_features_zero(dev);
 		netdev_hw_features_set_array(dev, &skge_hw_feature_set);
-		dev->features |= dev->hw_features;
+		netdev_active_features_set(dev, dev->hw_features);
 	}
 
 	/* read the mac address */
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 01e9893f73bb..caaa3692e2b8 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4655,11 +4655,11 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 		netdev_hw_feature_add(dev, NETIF_F_RXHASH_BIT);
 
 	if (!(hw->flags & SKY2_HW_VLAN_BROKEN)) {
-		dev->hw_features |= netdev_ctag_vlan_offload_features;
+		netdev_hw_features_set(dev, netdev_ctag_vlan_offload_features);
 		netdev_vlan_features_set_array(dev, &sky2_vlan_feature_set);
 	}
 
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 
 	/* MTU range: 60 - 1500 or 9000 */
 	dev->min_mtu = ETH_ZLEN;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 0043f387449f..5557bae234b1 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3901,7 +3901,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 
 	eth->netdev[id]->vlan_features = *eth->soc->hw_features &
 		~netdev_ctag_vlan_offload_features;
-	eth->netdev[id]->features |= *eth->soc->hw_features;
+	netdev_active_features_set(eth->netdev[id], *eth->soc->hw_features);
 	eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
 
 	eth->netdev[id]->irq = eth->irq[0];
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 080b5450e3a8..113944e047ab 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3361,7 +3361,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_array(dev, &mlx4_hw_feature_set1);
 	if (mdev->LSO_support)
-		dev->hw_features |= netdev_general_tso_features;
+		netdev_hw_features_set(dev, netdev_general_tso_features);
 
 	if (mdev->dev->caps.tunnel_offload_mode ==
 	    MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 3ee785091aa7..bd2a7e875ce6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -687,7 +687,7 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev,
 	netdev_hw_feature_add(netdev, NETIF_F_TSO6_BIT);
 	netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_NETNS_LOCAL_BIT);
 }
 
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index f421f48cb135..39891b7e6c71 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -6720,7 +6720,7 @@ static int __init netdev_init(struct net_device *dev)
 	 */
 	netdev_hw_feature_add(dev, NETIF_F_IPV6_CSUM_BIT);
 
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 
 	sema_init(&priv->proc_sem, 1);
 
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index 738eaa88279a..c5c4d680e70c 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -5,6 +5,7 @@
 #include <linux/if_vlan.h>
 #include <linux/iopoll.h>
 #include <linux/ip.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/of_platform.h>
 #include <linux/of_net.h>
 #include <linux/packing.h>
@@ -753,7 +754,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
 
 	dev->netdev_ops = &lan966x_port_netdev_ops;
 	dev->ethtool_ops = &lan966x_ethtool_ops;
-	dev->features |= netdev_tx_vlan_features;
+	netdev_active_features_set(dev, netdev_tx_vlan_features);
 	dev->needed_headroom = IFH_LEN * sizeof(u32);
 
 	eth_hw_addr_gen(dev, lan966x->base_mac, p + 1);
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 83a3ad14c79f..c6dd11c872f9 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -3876,7 +3876,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->features = netdev->hw_features;
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
-	netdev->vlan_features |= mgp->features;
+	netdev_vlan_features_set(netdev, mgp->features);
 	if (mgp->fw_ver_tiny < 37)
 		netdev->vlan_features &= ~NETIF_F_TSO6;
 	if (mgp->fw_ver_tiny < 32)
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index a5db6ccdb2df..f7309c2498da 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -2150,7 +2150,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
 
 #ifdef NS83820_VLAN_ACCEL_SUPPORT
 	/* We also support hardware vlan acceleration */
-	ndev->features |= netdev_ctag_vlan_offload_features;
+	netdev_active_features_set(ndev, netdev_ctag_vlan_offload_features);
 #endif
 
 	if (using_dac) {
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 8b3def9866d0..9b74b1b87220 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -7869,7 +7869,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	dev->ethtool_ops = &netdev_ethtool_ops;
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_array(dev, &s2io_hw_feature_set);
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_features_set_array(dev, &s2io_feature_set);
 	dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
 	INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 0b2e6dfa0ac2..071e0c6aa219 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2359,7 +2359,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 		nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY;
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_TXCSUM) {
-		netdev->hw_features |= netdev_ip_csum_features;
+		netdev_hw_features_set(netdev, netdev_ip_csum_features);
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_TXCSUM;
 	}
 	if (nn->cap & NFP_NET_CFG_CTRL_GATHER) {
@@ -2368,7 +2368,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 	}
 	if ((nn->cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
 	    nn->cap & NFP_NET_CFG_CTRL_LSO2) {
-		netdev->hw_features |= netdev_general_tso_features;
+		netdev_hw_features_set(netdev, netdev_general_tso_features);
 		nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_LSO2 ?:
 					 NFP_NET_CFG_CTRL_LSO;
 	}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index a193d87c7e39..b8a8aa917fdd 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -252,7 +252,7 @@ nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
 	tmp = NETIF_F_SOFT_FEATURES;
 	netdev_feature_add(NETIF_F_HW_TC_BIT, &tmp);
 	tmp &= old_features;
-	features |= tmp;
+	netdev_features_set(&features, tmp);
 	netdev_feature_add(NETIF_F_LLTX_BIT, &features);
 
 	return features;
@@ -350,12 +350,12 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 	if (repr_cap & NFP_NET_CFG_CTRL_RXCSUM_ANY)
 		netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 	if (repr_cap & NFP_NET_CFG_CTRL_TXCSUM)
-		netdev->hw_features |= netdev_ip_csum_features;
+		netdev_hw_features_set(netdev, netdev_ip_csum_features);
 	if (repr_cap & NFP_NET_CFG_CTRL_GATHER)
 		netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
 	if ((repr_cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
 	    repr_cap & NFP_NET_CFG_CTRL_LSO2)
-		netdev->hw_features |= netdev_general_tso_features;
+		netdev_hw_features_set(netdev, netdev_general_tso_features);
 	if (repr_cap & NFP_NET_CFG_CTRL_RSS_ANY)
 		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 	if (repr_cap & NFP_NET_CFG_CTRL_VXLAN) {
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 5adc4f02f36f..44e502650328 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -5825,10 +5825,10 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 	np->vlanctl_bits = 0;
 	if (id->driver_data & DEV_HAS_VLAN) {
 		np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE;
-		dev->hw_features |= netdev_ctag_vlan_offload_features;
+		netdev_hw_features_set(dev, netdev_ctag_vlan_offload_features);
 	}
 
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 
 	/* Add loopback capability to the device. */
 	netdev_hw_feature_add(dev, NETIF_F_LOOPBACK_BIT);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 2d1c6d591baa..c330ea873300 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1546,10 +1546,10 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
 		netdev_hw_enc_feature_add(netdev,
 					  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
-	netdev->hw_features |= netdev->hw_enc_features;
-	netdev->features |= netdev->hw_features;
+	netdev_hw_features_set(netdev, netdev->hw_enc_features);
+	netdev_active_features_set(netdev, netdev->hw_features);
 	features = netdev->features & ~NETIF_F_VLAN_FEATURES;
-	netdev->vlan_features |= features;
+	netdev_vlan_features_set(netdev, features);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT |
 			      IFF_LIVE_ADDR_CHANGE;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index b4c56b023122..ce1bb941fd85 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1364,7 +1364,7 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
 		netdev_hw_feature_add(netdev, NETIF_F_TSO6_BIT);
 	}
 
-	netdev->vlan_features |= netdev->hw_features;
+	netdev_vlan_features_set(netdev, netdev->hw_features);
 
 	if (adapter->pci_using_dac) {
 		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
@@ -1377,7 +1377,7 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
 	if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)
 		netdev_hw_feature_add(netdev, NETIF_F_LRO_BIT);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 
 	netdev->irq = adapter->msix_entries[0].vector;
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index d768cee19d3a..fa06ba45e8dc 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2300,8 +2300,9 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 	netdev_vlan_features_set_array(netdev, &qlcnic_vlan_feature_set);
 
 	if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
-		netdev->features |= netdev_general_tso_features;
-		netdev->vlan_features |= netdev_general_tso_features;
+		netdev_active_features_set(netdev,
+					   netdev_general_tso_features);
+		netdev_vlan_features_set(netdev, netdev_general_tso_features);
 	}
 
 	if (qlcnic_vlan_tx_check(adapter))
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index ded5fef309be..d0887e74167f 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5445,7 +5445,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (rtl_chip_supports_csum_v2(tp))
 		netdev_hw_feature_add(dev, NETIF_F_IPV6_CSUM_BIT);
 
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 
 	/* There has been a number of reports that using SG/TSO results in
 	 * tx timeouts. However for a lot of people SG/TSO works fine.
@@ -5454,7 +5454,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 */
 	if (rtl_chip_supports_csum_v2(tp)) {
 		netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
-		dev->hw_features |= netdev_general_tso_features;
+		netdev_hw_features_set(dev, netdev_general_tso_features);
 		netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2);
 		netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V2);
 	} else {
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 0a664cc7739e..9c6b7136f7fa 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -2117,7 +2117,7 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
 
 	netdev_hw_features_zero(ndev);
 	netdev_hw_features_set_array(ndev, &sxgbe_hw_feature_set);
-	ndev->features |= ndev->hw_features;
+	netdev_active_features_set(ndev, ndev->hw_features);
 	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 	ndev->watchdog_timeo = msecs_to_jiffies(TX_TIMEO);
 
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 2e0a096b5967..351ee0954053 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 |= 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;
@@ -1366,9 +1366,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_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index cbe9fda5464f..3597c4e02d08 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -372,10 +372,10 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
 	efx->net_dev = net_dev;
 	SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
 
-	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);
 	netif_set_tso_max_segs(net_dev,
 			       ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT);
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index f40766137540..2fb83949b87c 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -201,9 +201,9 @@ 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.
 		 */
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 9feb3295ccaa..5134fbd0382a 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1014,7 +1014,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))
@@ -1023,11 +1023,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;
@@ -1037,7 +1037,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 c3a29d4169c9..def02fe850af 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)
 	/* Restore previously fixed features in hw_features and remove
 	 * features which are fixed now
 	 */
-	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 6fab0c10b78d..b803b8688c60 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -635,9 +635,9 @@ static void ef4_start_datapath(struct ef4_nic *efx)
 	/* Restore previously fixed features in hw_features and remove
 	 * features which are fixed now
 	 */
-	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);
 
@@ -2907,7 +2907,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 */
@@ -2919,7 +2919,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 f04b66b62840..f3812d26aeb0 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 4b0ae2353f3f..6b398fd3d6d4 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1754,7 +1754,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/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index 4a3d2be92a12..d5818151bb04 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -996,7 +996,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))
@@ -1005,10 +1005,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);
 
-	net_dev->hw_features |= net_dev->features & ~efx->fixed_features;
+	netdev_hw_features_set(net_dev,
+			       net_dev->features & ~efx->fixed_features);
 
 	/* Disable receiving frames with bad FCS, by default. */
 	net_dev->features &= ~NETIF_F_RXALL;
@@ -1018,7 +1019,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/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 4c0f915dba82..1c7a4ee1723f 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -411,9 +411,9 @@ static void efx_start_datapath(struct efx_nic *efx)
 	/* Restore previously fixed features in hw_features and remove
 	 * features which are fixed now
 	 */
-	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/siena/net_driver.h b/drivers/net/ethernet/sfc/siena/net_driver.h
index 331af932e56d..0748b4955f99 100644
--- a/drivers/net/ethernet/sfc/siena/net_driver.h
+++ b/drivers/net/ethernet/sfc/siena/net_driver.h
@@ -11,6 +11,7 @@
 #define EFX_NET_DRIVER_H
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
@@ -1681,7 +1682,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/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c85941528096..4d722a6ed2ca 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7148,7 +7148,7 @@ int stmmac_dvr_probe(struct device *device,
 	}
 
 	if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
-		ndev->hw_features |= netdev_general_tso_features;
+		netdev_hw_features_set(ndev, netdev_general_tso_features);
 		if (priv->plat->has_gmac4)
 			netdev_hw_feature_add(ndev, NETIF_F_GSO_UDP_L4_BIT);
 		priv->tso = true;
@@ -7194,14 +7194,14 @@ int stmmac_dvr_probe(struct device *device,
 		}
 	}
 
-	ndev->features |= ndev->hw_features;
+	netdev_active_features_set(ndev, ndev->hw_features);
 	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
 #ifdef STMMAC_VLAN_TAG_USED
 	/* Both mac100 and gmac support receive VLAN tag detection */
-	ndev->features |= netdev_rx_vlan_features;
+	netdev_active_features_set(ndev, netdev_rx_vlan_features);
 	if (priv->dma_cap.vlhash)
-		ndev->features |= netdev_vlan_filter_features;
+		netdev_active_features_set(ndev, netdev_vlan_filter_features);
 	if (priv->dma_cap.vlins) {
 		netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 		if (priv->dma_cap.dvlan)
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index 41398fa580c2..bc531188b957 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9743,7 +9743,7 @@ static void niu_set_basic_features(struct net_device *dev)
 {
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_array(dev, &niu_hw_feature_set);
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 }
 
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index 5eaf7c40a0ad..494bbfafd91b 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2788,7 +2788,7 @@ static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
 	netdev_hw_features_zero(dev);
 	netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
 	netdev_hw_feature_add(dev, NETIF_F_HW_CSUM_BIT);
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 
 	hp->irq = op->archdata.irqs[0];
@@ -3111,7 +3111,7 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
 	netdev_hw_features_zero(dev);
 	netdev_hw_feature_add(dev, NETIF_F_SG_BIT);
 	netdev_hw_feature_add(dev, NETIF_F_HW_CSUM_BIT);
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
index f15e8768526d..a20c6c055369 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
@@ -181,7 +181,7 @@ static int xlgmac_init(struct xlgmac_pdata *pdata)
 	if (pdata->hw_feat.tso) {
 		netdev->hw_features = netdev_general_tso_features;
 		netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
-		netdev->hw_features |= netdev_ip_csum_features;
+		netdev_hw_features_set(netdev, netdev_ip_csum_features);
 	} else if (pdata->hw_feat.tx_coe) {
 		netdev->hw_features = netdev_ip_csum_features;
 	}
@@ -194,7 +194,7 @@ static int xlgmac_init(struct xlgmac_pdata *pdata)
 	if (pdata->hw_feat.rss)
 		netdev_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 
-	netdev->vlan_features |= netdev->hw_features;
+	netdev_vlan_features_set(netdev, netdev->hw_features);
 
 	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	if (pdata->hw_feat.sa_vlan_ins)
@@ -202,7 +202,7 @@ static int xlgmac_init(struct xlgmac_pdata *pdata)
 	if (pdata->hw_feat.vlhash)
 		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	pdata->netdev_features = netdev->features;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index adc8a3de10ff..cee1a279832a 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -974,7 +974,7 @@ static int rhine_init_one_common(struct device *hwdev, u32 quirks,
 	}
 
 	if (rp->quirks & rqMgmt)
-		dev->features |= netdev_ctag_vlan_features;
+		netdev_active_features_set(dev, netdev_ctag_vlan_features);
 
 	/* dev->name not defined before register_netdev()! */
 	rc = register_netdev(dev);
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 33a1554c7f83..08bd27fd0ed0 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -1259,10 +1259,10 @@ static void geneve_setup(struct net_device *dev)
 	SET_NETDEV_DEVTYPE(dev, &geneve_type);
 
 	netdev_active_features_set_array(dev, &geneve_feature_set);
-	dev->features    |= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 
 	netdev_hw_features_set_array(dev, &geneve_hw_feature_set);
-	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+	netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
 
 	/* MTU range: 68 - (something less than 65535) */
 	dev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 9729cd9c37b3..0737794728a2 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1433,7 +1433,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	 */
 	netdev_features_fill(&features);
 	features &= ~NETVSC_SUPPORTED_HW_FEATURES;
-	features |= net->hw_features;
+	netdev_features_set(&features, net->hw_features);
 	net->features &= features;
 
 	netif_set_tso_max_size(net, gso_max_size);
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 370f3fa59587..912570321bfd 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -323,13 +323,14 @@ static void ifb_setup(struct net_device *dev)
 	ether_setup(dev);
 	dev->tx_queue_len = TX_Q_LIMIT;
 
-	ifb_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	ifb_features = netdev_features_or(NETIF_F_GSO_SOFTWARE,
+					  NETIF_F_GSO_ENCAP_ALL);
 	netdev_features_set_array(&ifb_feature_set, &ifb_features);
-	dev->features |= ifb_features;
-	dev->hw_features |= dev->features;
-	dev->hw_enc_features |= dev->features;
+	netdev_active_features_set(dev, ifb_features);
+	netdev_hw_features_set(dev, dev->features);
+	netdev_hw_enc_features_set(dev, dev->features);
 	ifb_features &= ~netdev_tx_vlan_features;
-	dev->vlan_features |= ifb_features;
+	netdev_vlan_features_set(dev, ifb_features);
 
 	dev->flags |= IFF_NOARP;
 	dev->flags &= ~IFF_MULTICAST;
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 0078ecfe8838..3d96a990eded 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -152,10 +152,10 @@ static int ipvlan_init(struct net_device *dev)
 	dev->state = (dev->state & ~IPVLAN_STATE_MASK) |
 		     (phy_dev->state & IPVLAN_STATE_MASK);
 	dev->features = phy_dev->features & IPVLAN_FEATURES;
-	dev->features |= IPVLAN_ALWAYS_ON;
+	netdev_active_features_set(dev, IPVLAN_ALWAYS_ON);
 	dev->vlan_features = phy_dev->vlan_features & IPVLAN_FEATURES;
-	dev->vlan_features |= IPVLAN_ALWAYS_ON_OFLOADS;
-	dev->hw_enc_features |= dev->features;
+	netdev_vlan_features_set(dev, IPVLAN_ALWAYS_ON_OFLOADS);
+	netdev_hw_enc_features_set(dev, dev->features);
 	netif_inherit_tso_max(dev, phy_dev);
 	dev->hard_header_len = phy_dev->hard_header_len;
 
@@ -256,15 +256,15 @@ static netdev_features_t ipvlan_fix_features(struct net_device *dev,
 	struct ipvl_dev *ipvlan = netdev_priv(dev);
 	netdev_features_t tmp;
 
-	features |= NETIF_F_ALL_FOR_ALL;
+	netdev_features_set(&features, NETIF_F_ALL_FOR_ALL);
 	netdev_features_fill(&tmp);
 	tmp &= ~IPVLAN_FEATURES;
-	tmp |= ipvlan->sfeatures;
+	netdev_features_set(&tmp, ipvlan->sfeatures);
 	features &= tmp;
 	features = netdev_increment_features(ipvlan->phy_dev->features,
 					     features, features);
-	features |= IPVLAN_ALWAYS_ON;
-	tmp = IPVLAN_FEATURES | IPVLAN_ALWAYS_ON;
+	netdev_features_set(&features, IPVLAN_ALWAYS_ON);
+	tmp = netdev_features_or(IPVLAN_FEATURES, IPVLAN_ALWAYS_ON);
 	features &= tmp;
 
 	return features;
@@ -1042,7 +1042,8 @@ static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
 
 static void __init ipvlan_features_init(void)
 {
-	ipvlan_offload_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	ipvlan_offload_features = netdev_features_or(NETIF_F_GSO_SOFTWARE,
+						     NETIF_F_GSO_ENCAP_ALL);
 	netdev_features_set_array(&ipvlan_on_offload_feature_set,
 				  &ipvlan_offload_features);
 
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 35b9e9831ab8..c8ee65e9c170 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3457,7 +3457,7 @@ static int macsec_dev_init(struct net_device *dev)
 	} else {
 		dev->features = real_dev->features & SW_MACSEC_FEATURES;
 		netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
-		dev->features |= NETIF_F_GSO_SOFTWARE;
+		netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	}
 
 	dev->needed_headroom = real_dev->needed_headroom +
@@ -3495,8 +3495,8 @@ static netdev_features_t macsec_fix_features(struct net_device *dev,
 		return REAL_DEV_FEATURES(real_dev);
 
 	tmp = real_dev->features & SW_MACSEC_FEATURES;
-	tmp |= NETIF_F_GSO_SOFTWARE;
-	tmp |= NETIF_F_SOFT_FEATURES;
+	netdev_features_set(&tmp, NETIF_F_GSO_SOFTWARE);
+	netdev_features_set(&tmp, NETIF_F_SOFT_FEATURES);
 	features &= tmp;
 	netdev_feature_add(NETIF_F_LLTX_BIT, &features);
 
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 5df2989cf562..1fc6941fe633 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -917,11 +917,11 @@ static int macvlan_init(struct net_device *dev)
 	dev->state		= (dev->state & ~MACVLAN_STATE_MASK) |
 				  (lowerdev->state & MACVLAN_STATE_MASK);
 	dev->features 		= lowerdev->features & MACVLAN_FEATURES;
-	dev->features		|= ALWAYS_ON_FEATURES;
+	netdev_active_features_set(dev, ALWAYS_ON_FEATURES);
 	netdev_hw_feature_add(dev, NETIF_F_LRO_BIT);
 	dev->vlan_features	= lowerdev->vlan_features & MACVLAN_FEATURES;
-	dev->vlan_features	|= ALWAYS_ON_OFFLOADS;
-	dev->hw_enc_features    |= dev->features;
+	netdev_vlan_features_set(dev, ALWAYS_ON_OFFLOADS);
+	netdev_hw_enc_features_set(dev, dev->features);
 	netif_inherit_tso_max(dev, lowerdev);
 	dev->hard_header_len	= lowerdev->hard_header_len;
 	macvlan_set_lockdep_class(dev);
@@ -1101,10 +1101,10 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
 	netdev_features_t mask;
 	netdev_features_t tmp;
 
-	features |= NETIF_F_ALL_FOR_ALL;
+	netdev_features_set(&features, NETIF_F_ALL_FOR_ALL);
 	netdev_features_fill(&tmp);
 	tmp &= ~MACVLAN_FEATURES;
-	tmp |= vlan->set_features;
+	netdev_features_set(&tmp, vlan->set_features);
 	features &= tmp;
 	mask = features;
 
@@ -1112,8 +1112,8 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
 	tmp &= ~NETIF_F_LRO;
 	lowerdev_features &= tmp;
 	features = netdev_increment_features(lowerdev_features, features, mask);
-	features |= ALWAYS_ON_FEATURES;
-	tmp = ALWAYS_ON_FEATURES | MACVLAN_FEATURES;
+	netdev_features_set(&features, ALWAYS_ON_FEATURES);
+	tmp = netdev_features_or(ALWAYS_ON_FEATURES, MACVLAN_FEATURES);
 	features &= tmp;
 
 	return features;
@@ -1840,7 +1840,8 @@ static struct notifier_block macvlan_notifier_block __read_mostly = {
 
 static void __init macvlan_features_init(void)
 {
-	macvlan_offload_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	macvlan_offload_features = netdev_features_or(NETIF_F_GSO_SOFTWARE,
+						      NETIF_F_GSO_ENCAP_ALL);
 	netdev_features_set_array(&macvlan_on_offload_feature_set,
 				  &macvlan_offload_features);
 
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index c643e4914e8e..b2721d802929 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -435,7 +435,8 @@ static void net_failover_compute_features(struct net_device *dev)
 	}
 
 	dev->vlan_features = vlan_features;
-	dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL;
+	dev->hw_enc_features = netdev_features_or(enc_features,
+						  NETIF_F_GSO_ENCAP_ALL);
 	dev->hard_header_len = max_hard_header_len;
 
 	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
@@ -754,11 +755,11 @@ struct failover *net_failover_create(struct net_device *standby_dev)
 	/* Don't allow failover devices to change network namespaces. */
 	netdev_active_feature_add(failover_dev, NETIF_F_NETNS_LOCAL_BIT);
 
-	failover_dev->hw_features = FAILOVER_VLAN_FEATURES |
-				    netdev_ctag_vlan_features;
+	failover_dev->hw_features = netdev_features_or(FAILOVER_VLAN_FEATURES,
+						       netdev_ctag_vlan_features);
 
-	failover_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
-	failover_dev->features |= failover_dev->hw_features;
+	netdev_hw_features_set(failover_dev, NETIF_F_GSO_ENCAP_ALL);
+	netdev_active_features_set(failover_dev, failover_dev->hw_features);
 
 	dev_addr_set(failover_dev, standby_dev->dev_addr);
 
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 323e4158cf4a..3700b3b6141a 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -347,7 +347,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
 	 * enabled.
 	 */
 	if (q->flags & IFF_VNET_HDR)
-		features |= tap->tap_features;
+		netdev_features_set(&features, tap->tap_features);
 	if (netif_needs_gso(skb, features)) {
 		struct sk_buff *segs = __skb_gso_segment(skb, features, false);
 		struct sk_buff *next;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index e9b51c600b35..2aaf3a8789f3 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1024,8 +1024,9 @@ static void __team_compute_features(struct team *team)
 	rcu_read_unlock();
 
 	team->dev->vlan_features = vlan_features;
-	team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL;
-	team->dev->hw_enc_features |= netdev_tx_vlan_features;
+	team->dev->hw_enc_features = netdev_features_or(enc_features,
+							NETIF_F_GSO_ENCAP_ALL);
+	netdev_hw_enc_features_set(team->dev, netdev_tx_vlan_features);
 	team->dev->hard_header_len = max_hard_header_len;
 
 	team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
@@ -2017,7 +2018,7 @@ static netdev_features_t team_fix_features(struct net_device *dev,
 
 	mask = features;
 	features &= ~NETIF_F_ONE_FOR_ALL;
-	features |= NETIF_F_ALL_FOR_ALL;
+	netdev_features_set(&features, NETIF_F_ALL_FOR_ALL);
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(port, &team->port_list, list) {
@@ -2188,9 +2189,9 @@ static void team_setup(struct net_device *dev)
 	netdev_hw_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	netdev_hw_feature_add(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
-	dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
-	dev->features |= dev->hw_features;
-	dev->features |= netdev_tx_vlan_features;
+	netdev_hw_features_set(dev, NETIF_F_GSO_ENCAP_ALL);
+	netdev_active_features_set(dev, dev->hw_features);
+	netdev_active_features_set(dev, netdev_tx_vlan_features);
 }
 
 static int team_newlink(struct net *src_net, struct net_device *dev,
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index e7950125d628..4f067242d634 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1179,7 +1179,7 @@ static netdev_features_t tun_net_fix_features(struct net_device *dev,
 
 	tmp1 = features & tun->set_features;
 	tmp2 = features & ~TUN_USER_FEATURES;
-	return tmp1 | tmp2;
+	return netdev_features_or(tmp1, tmp2);
 }
 
 static void tun_set_headroom(struct net_device *dev, int new_hr)
@@ -2895,7 +2895,7 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
 
 	tun->set_features = features;
 	tun->dev->wanted_features &= ~TUN_USER_FEATURES;
-	tun->dev->wanted_features |= features;
+	netdev_wanted_features_set(tun->dev, features);
 	netdev_update_features(tun->dev);
 
 	return 0;
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 67c4bce50df2..3d5f0241f2bc 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1301,7 +1301,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
 
 	netdev_active_features_set_array(dev->net, &ax88179_feature_set);
 
-	dev->net->hw_features |= dev->net->features;
+	netdev_hw_features_set(dev->net, dev->net->features);
 
 	netif_set_tso_max_size(dev->net, 16384);
 
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 0370e1fc3365..3a413073eb66 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1479,7 +1479,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
 	INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write);
 
 	if (DEFAULT_TX_CSUM_ENABLE)
-		dev->net->features |= netdev_ip_csum_features;
+		netdev_active_features_set(dev->net, netdev_ip_csum_features);
 
 	if (DEFAULT_RX_CSUM_ENABLE)
 		netdev_active_feature_add(dev->net, NETIF_F_RXCSUM_BIT);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 7fcecff337a5..fe9bc2f94672 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1575,7 +1575,8 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 				veth_disable_xdp(dev);
 
 			if (peer) {
-				peer->hw_features |= NETIF_F_GSO_SOFTWARE;
+				netdev_hw_features_set(peer,
+						       NETIF_F_GSO_SOFTWARE);
 				peer->max_mtu = ETH_MAX_MTU;
 			}
 		}
@@ -1648,10 +1649,11 @@ static void veth_setup(struct net_device *dev)
 
 	dev->netdev_ops = &veth_netdev_ops;
 	dev->ethtool_ops = &veth_ethtool_ops;
-	veth_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	veth_features = netdev_features_or(NETIF_F_GSO_SOFTWARE,
+					   NETIF_F_GSO_ENCAP_ALL);
 	netdev_features_set_array(&veth_feature_set, &veth_features);
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
-	dev->features |= veth_features;
+	netdev_active_features_set(dev, veth_features);
 	dev->vlan_features = dev->features & ~netdev_vlan_offload_features;
 	dev->needs_free_netdev = true;
 	dev->priv_destructor = veth_dev_free;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index d10c1a8782cc..d3eb1f5570d3 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3521,7 +3521,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 		}
 
 		if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
-			dev->hw_features |= netdev_general_tso_features;
+			netdev_hw_features_set(dev,
+					       netdev_general_tso_features);
 			netdev_hw_feature_add(dev, NETIF_F_TSO_ECN_BIT);
 		}
 		/* Individual feature bits: what can host handle? */
@@ -3537,7 +3538,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 		if (gso) {
 			netdev_features_t tmp = dev->hw_features & NETIF_F_ALL_TSO;
 
-			dev->features |= tmp;
+			netdev_active_features_set(dev, tmp);
 		}
 		/* (!csum && gso) case will be fixed by register_netdev() */
 	}
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 98ae263639fc..a257ba4202e6 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1696,7 +1696,7 @@ static void vrf_setup(struct net_device *dev)
 	netdev_active_feature_add(dev, NETIF_F_VLAN_CHALLENGED_BIT);
 
 	/* enable offload features */
-	dev->features   |= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	netdev_active_features_set_array(dev, &vrf_offload_feature_set);
 
 	dev->hw_features = dev->features;
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 0076b12b6bae..728684964be0 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3179,11 +3179,11 @@ static void vxlan_setup(struct net_device *dev)
 	SET_NETDEV_DEVTYPE(dev, &vxlan_type);
 
 	netdev_active_features_set_array(dev, &vxlan_feature_set);
-	dev->features   |= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 
 	dev->vlan_features = dev->features;
 	netdev_hw_features_set_array(dev, &vxlan_hw_feature_set);
-	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+	netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	netif_keep_dst(dev);
 	dev->priv_flags |= IFF_NO_QUEUE | IFF_CHANGE_PROTO_DOWN;
 
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index 3c127313fb05..ae084d85a065 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -298,9 +298,9 @@ static void wg_setup(struct net_device *dev)
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	wg_netdev_features = NETIF_F_GSO_SOFTWARE;
 	netdev_features_set_array(&wg_feature_set, &wg_netdev_features);
-	dev->features |= wg_netdev_features;
-	dev->hw_features |= wg_netdev_features;
-	dev->hw_enc_features |= wg_netdev_features;
+	netdev_active_features_set(dev, wg_netdev_features);
+	netdev_hw_features_set(dev, wg_netdev_features);
+	netdev_hw_enc_features_set(dev, wg_netdev_features);
 	dev->mtu = ETH_DATA_LEN - overhead;
 	dev->max_mtu = round_down(INT_MAX, MESSAGE_PADDING_MULTIPLE) - overhead;
 
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index c2012c4e0084..bc08d4eb5b30 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -347,7 +347,7 @@ wil_vif_alloc(struct wil6210_priv *wil, const char *name,
 	netdev_hw_features_zero(ndev);
 	netdev_hw_features_set_array(ndev, &wil_hw_feature_set);
 
-	ndev->features |= ndev->hw_features;
+	netdev_active_features_set(ndev, ndev->hw_features);
 	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
 	wdev->netdev = ndev;
 	return vif;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 0c94d7bf80f6..ee66440cbb22 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -615,7 +615,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 		hw->wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
 	}
 
-	hw->netdev_features |= *mvm->cfg->features;
+	netdev_features_set(&hw->netdev_features, *mvm->cfg->features);
 	if (!iwl_mvm_is_csum_supported(mvm))
 		hw->netdev_features &= ~IWL_CSUM_NETIF_FLAGS_MASK;
 
@@ -1416,7 +1416,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
 		goto out_unlock;
 	}
 
-	mvmvif->features |= hw->netdev_features;
+	netdev_features_set(&mvmvif->features, hw->netdev_features);
 
 	ret = iwl_mvm_mac_ctxt_add(mvm, vif);
 	if (ret)
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d4833794cec0..1b089e6ef929 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1750,7 +1750,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
          * xennet_connect() which is the earliest point where we can
          * negotiate with the backend regarding supported features.
          */
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 
 	netdev->ethtool_ops = &xennet_ethtool_ops;
 	netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 1975d01b6cad..0d3d0ffdb46b 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6945,7 +6945,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 		netdev_features_t restricted = netdev_empty_features;
 
 		if (skb_is_gso(skb) && !netif_needs_gso(skb, features))
-			restricted |= NETIF_F_ALL_TSO;
+			netdev_features_set(&restricted, NETIF_F_ALL_TSO);
 
 		switch (vlan_get_protocol(skb)) {
 		case htons(ETH_P_IP):
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 0f342a6d3070..daa1b6f2b47e 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1909,7 +1909,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 		return -ENODEV;
 
 	card->dev->needed_headroom = headroom;
-	card->dev->features |= netdev_ctag_vlan_offload_features;
+	netdev_active_features_set(card->dev,
+				   netdev_ctag_vlan_offload_features);
 
 	netif_keep_dst(card->dev);
 	if (card->dev->hw_features & netdev_general_tso_features)
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h
index 772401f25a81..e529e1cbde51 100644
--- a/include/linux/netdev_features_helper.h
+++ b/include/linux/netdev_features_helper.h
@@ -690,9 +690,9 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
 {
 	if ((f1 & NETIF_F_HW_CSUM) != (f2 & 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;
@@ -704,7 +704,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/include/net/udp.h b/include/net/udp.h
index f901e40bd470..7ef2157be238 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -467,7 +467,7 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk,
 	 * asks for the final checksum values
 	 */
 	if (!inet_get_convert_csum(sk))
-		features |= netdev_ip_csum_features;
+		netdev_features_set(&features, netdev_ip_csum_features);
 
 	/* UDP segmentation expects packets of type CHECKSUM_PARTIAL or
 	 * CHECKSUM_NONE in __udp_gso_segment. UDP GRO indeed builds partial
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 4c11028ce4f8..42eab811f8a1 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -108,8 +108,8 @@ static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)
 {
 	netdev_features_t ret;
 
-	ret = NETIF_F_CSUM_MASK | NETIF_F_GSO_SOFTWARE;
-	ret |= NETIF_F_GSO_ENCAP_ALL;
+	ret = netdev_features_or(NETIF_F_CSUM_MASK, NETIF_F_GSO_SOFTWARE);
+	netdev_features_set(&ret, NETIF_F_GSO_ENCAP_ALL);
 	ret &= real_dev->hw_enc_features;
 
 	if ((ret & NETIF_F_GSO_ENCAP_ALL) && (ret & NETIF_F_CSUM_MASK)) {
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 6df3fd365714..24c812234a79 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -574,11 +574,12 @@ static int vlan_dev_init(struct net_device *dev)
 	if (vlan->flags & VLAN_FLAG_BRIDGE_BINDING)
 		dev->state |= (1 << __LINK_STATE_NOCARRIER);
 
-	dev->hw_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
-	dev->hw_features |= NETIF_F_ALL_FCOE;
+	dev->hw_features = netdev_features_or(NETIF_F_GSO_SOFTWARE,
+					      NETIF_F_GSO_ENCAP_ALL);
+	netdev_hw_features_set(dev, NETIF_F_ALL_FCOE);
 	netdev_hw_features_set_array(dev, &vlan_hw_feature_set);
 
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netif_inherit_tso_max(dev, real_dev);
 	if (dev->features & NETIF_F_VLAN_FEATURES)
@@ -665,9 +666,9 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
 	if (lower_features & netdev_ip_csum_features)
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &lower_features);
 	features = netdev_intersect_features(features, lower_features);
-	tmp = NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE;
+	tmp = netdev_features_or(NETIF_F_SOFT_FEATURES, NETIF_F_GSO_SOFTWARE);
 	tmp &= old_features;
-	features |= tmp;
+	netdev_features_set(&features, tmp);
 	netdev_feature_add(NETIF_F_LLTX_BIT, &features);
 
 	return features;
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 1d5e13e2acb8..f9e510bb4bbc 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -507,7 +507,8 @@ void br_dev_setup(struct net_device *dev)
 	netdev_features_set_array(&br_common_feature_set, &common_features);
 	dev->features = common_features;
 	netdev_active_features_set_array(dev, &br_feature_set);
-	dev->hw_features = common_features | netdev_tx_vlan_features;
+	dev->hw_features = netdev_features_or(common_features,
+					      netdev_tx_vlan_features);
 	dev->vlan_features = common_features;
 
 	br->dev = dev;
diff --git a/net/core/dev.c b/net/core/dev.c
index e374eb18c716..6589b3c7c70c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3400,7 +3400,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;
 	}
 
@@ -3565,7 +3565,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);
 	}
 
@@ -10027,9 +10027,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);
@@ -11154,17 +11154,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/core/sock.c b/net/core/sock.c
index c71c43882785..456ce67fbb08 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2320,7 +2320,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 	if (sk_is_tcp(sk))
 		netdev_feature_add(NETIF_F_GSO_BIT, &sk->sk_route_caps);
 	if (sk->sk_route_caps & NETIF_F_GSO)
-		sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
+		netdev_features_set(&sk->sk_route_caps, NETIF_F_GSO_SOFTWARE);
 	if (unlikely(sk->sk_gso_disabled))
 		sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
 	if (sk_can_gso(sk)) {
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 3e5116f6d56a..f99fcbb224d4 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -294,7 +294,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;
 
@@ -356,7 +356,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
 	netdev_features_set_array(&ethtool_all_feature_set, &eth_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)
@@ -364,7 +364,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);
 
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index fbdf3713245f..04586ad67183 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -776,8 +776,8 @@ static void ipgre_link_update(struct net_device *dev, bool set_mtu)
 		dev->features &= ~NETIF_F_GSO_SOFTWARE;
 		dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
 	} else {
-		dev->features |= NETIF_F_GSO_SOFTWARE;
-		dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+		netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
+		netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	}
 }
 
@@ -975,8 +975,8 @@ static void __gre_tunnel_init(struct net_device *dev)
 	if (flags & TUNNEL_CSUM && tunnel->encap.type != TUNNEL_ENCAP_NONE)
 		return;
 
-	dev->features |= NETIF_F_GSO_SOFTWARE;
-	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
+	netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
 }
 
 static int ipgre_tunnel_init(struct net_device *dev)
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index e1988286c523..e2ad4be46c90 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -376,8 +376,8 @@ static void ipip_tunnel_setup(struct net_device *dev)
 
 	ipip_features		= NETIF_F_GSO_SOFTWARE;
 	netdev_features_set_array(&ipip_feature_set, &ipip_features);
-	dev->features		|= ipip_features;
-	dev->hw_features	|= ipip_features;
+	netdev_active_features_set(dev, ipip_features);
+	netdev_hw_features_set(dev, ipip_features);
 	ip_tunnel_setup(dev, ipip_net_id);
 }
 
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 1a322cd002cb..79393bd9c5b0 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1490,8 +1490,8 @@ static void ip6gre_tnl_init_features(struct net_device *dev)
 	if (flags & TUNNEL_CSUM && nt->encap.type != TUNNEL_ENCAP_NONE)
 		return;
 
-	dev->features |= NETIF_F_GSO_SOFTWARE;
-	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
+	netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
 }
 
 static int ip6gre_tunnel_init_common(struct net_device *dev)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 2922f0f66634..1239dcef22c5 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1845,8 +1845,8 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
 
 	ipxipx_features = NETIF_F_GSO_SOFTWARE;
 	netdev_features_set_array(&ipxipx_feature_set, &ipxipx_features);
-	dev->features		|= ipxipx_features;
-	dev->hw_features	|= ipxipx_features;
+	netdev_active_features_set(dev, ipxipx_features);
+	netdev_hw_features_set(dev, ipxipx_features);
 
 	/* This perm addr will be used as interface identifier by IPv6 */
 	dev->addr_assign_type = NET_ADDR_RANDOM;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 69d10ab34e1c..9f65f6cf0cd3 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1435,8 +1435,8 @@ static void ipip6_tunnel_setup(struct net_device *dev)
 	sit_features = NETIF_F_GSO_SOFTWARE;
 	netdev_features_set_array(&sit_feature_set, &sit_features);
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
-	dev->features		|= sit_features;
-	dev->hw_features	|= sit_features;
+	netdev_active_features_set(dev, sit_features);
+	netdev_hw_features_set(dev, sit_features);
 }
 
 static int ipip6_tunnel_init(struct net_device *dev)
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index bd0c2073828c..d3dc0628cac3 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -2397,9 +2397,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 		if (type == NL80211_IFTYPE_STATION)
 			sdata->u.mgd.use_4addr = params->use_4addr;
 
-		ndev->features |= local->hw.netdev_features;
+		netdev_active_features_set(ndev, local->hw.netdev_features);
 		tmp = ndev->features & MAC80211_SUPPORTED_FEATURES_TX;
-		ndev->hw_features |= tmp;
+		netdev_hw_features_set(ndev, tmp);
 
 		netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
 
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 00d8f3bce563..7a3d98473a0a 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1546,7 +1546,8 @@ static void __init ieee80211_features_init(void)
 				  &mac80211_tx_features);
 	netdev_features_set_array(&mac80211_rx_feature_set,
 				  &mac80211_rx_features);
-	mac80211_supported_features = mac80211_tx_features | mac80211_rx_features;
+	mac80211_supported_features = netdev_features_or(mac80211_tx_features,
+							 mac80211_rx_features);
 }
 
 static int __init ieee80211_init(void)
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 888ffcb2e1ca..4baf9c563c87 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -116,12 +116,13 @@ static void do_setup(struct net_device *netdev)
 	netdev->ethtool_ops = &internal_dev_ethtool_ops;
 	netdev->rtnl_link_ops = &internal_dev_link_ops;
 
-	netdev->features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev->features = netdev_features_or(NETIF_F_GSO_SOFTWARE,
+					      NETIF_F_GSO_ENCAP_ALL);
 	netdev_active_features_set_array(netdev, &ovs_feature_set);
 
 	netdev->vlan_features = netdev->features;
 	netdev->hw_enc_features = netdev->features;
-	netdev->features |= netdev_tx_vlan_features;
+	netdev_active_features_set(netdev, netdev_tx_vlan_features);
 	netdev->hw_features = netdev->features;
 	netdev->hw_features &= ~NETIF_F_LLTX;
 
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 06b94053097e..c492b2952d6a 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -156,7 +157,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 	}
 
 	if (!skb->next) {
-		esp_features |= skb->dev->gso_partial_features;
+		netdev_features_set(&esp_features, skb->dev->gso_partial_features);
 		xfrm_outer_mode_prep(x, skb);
 
 		xo->flags |= XFRM_DEV_RESUME;
@@ -177,7 +178,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 	}
 
 	skb_list_walk_safe(skb, skb2, nskb) {
-		esp_features |= skb->dev->gso_partial_features;
+		netdev_features_set(&esp_features, skb->dev->gso_partial_features);
 		skb_mark_not_on_list(skb2);
 
 		xo = xfrm_offload(skb2);
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 41a05e6d2ef0..3d3d62301078 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -598,8 +598,8 @@ static int xfrmi_dev_init(struct net_device *dev)
 	xfrmi_features = NETIF_F_GSO_SOFTWARE;
 	netdev_features_set_array(&xfrmi_feature_set, &xfrmi_features);
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
-	dev->features |= xfrmi_features;
-	dev->hw_features |= xfrmi_features;
+	netdev_active_features_set(dev, xfrmi_features);
+	netdev_hw_features_set(dev, xfrmi_features);
 
 	if (phydev) {
 		dev->needed_headroom = phydev->needed_headroom;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 26/36] treewide: use netdev_feature_change helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (24 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 25/36] treewide: use netdev_features_or/set helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 27/36] treewide: use netdev_feature_del helpers Jian Shen
                   ` (9 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '^=' expressions of single feature bit by
netdev_feature_change helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |  2 +-
 drivers/net/ethernet/google/gve/gve_main.c      |  2 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c  |  2 +-
 drivers/net/hyperv/netvsc_drv.c                 |  4 ++--
 drivers/s390/net/qeth_core_main.c               | 10 +++++-----
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index fd2e42662dd5..316fa87237b2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1285,7 +1285,7 @@ static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 			    !!(features & NETIF_F_HW_VLAN_CTAG_RX), true);
 	if (unlikely(err)) {
 		dev->features = features;
-		dev->features ^= NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_active_feature_change(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	}
 	return err;
 }
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index 357e2d9cd740..dd7bc0374d6f 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -1186,7 +1186,7 @@ static int gve_set_features(struct net_device *netdev,
 	int err;
 
 	if ((netdev->features & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
-		netdev->features ^= NETIF_F_LRO;
+		netdev_active_feature_change(netdev, NETIF_F_LRO_BIT);
 		if (netif_carrier_ok(netdev)) {
 			/* To make this process as simple as possible we
 			 * teardown the device, set the new configuration,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index fc51958cd77a..ab7e234132ed 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1100,7 +1100,7 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
 	if (!(changed & NETIF_F_LRO))
 		return 0;
 
-	netdev->features ^= NETIF_F_LRO;
+	netdev_active_feature_change(netdev, NETIF_F_LRO_BIT);
 
 	if (qlcnic_config_hw_lro(adapter, hw_lro))
 		return -EIO;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 72f0500ae697..e241f9a1fca7 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1910,7 +1910,7 @@ static netdev_features_t netvsc_fix_features(struct net_device *ndev,
 		return features;
 
 	if ((features & NETIF_F_LRO) && netvsc_xdp_get(nvdev)) {
-		features ^= NETIF_F_LRO;
+		netdev_feature_change(NETIF_F_LRO_BIT, &features);
 		netdev_info(ndev, "Skip LRO - unsupported with XDP\n");
 	}
 
@@ -1946,7 +1946,7 @@ static int netvsc_set_features(struct net_device *ndev,
 	ret = rndis_filter_set_offload_params(ndev, nvdev, &offloads);
 
 	if (ret) {
-		features ^= NETIF_F_LRO;
+		netdev_feature_change(NETIF_F_LRO_BIT, &features);
 		ndev->features = features;
 	}
 
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 0d3d0ffdb46b..39e0bd7ba519 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6871,31 +6871,31 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
 				       IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV4,
 				       &card->info.has_lp2lp_cso_v4);
 		if (rc)
-			changed ^= NETIF_F_IP_CSUM;
+			netdev_feature_change(NETIF_F_IP_CSUM_BIT, &changed);
 	}
 	if (changed & NETIF_F_IPV6_CSUM) {
 		rc = qeth_set_ipa_csum(card, features & NETIF_F_IPV6_CSUM,
 				       IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV6,
 				       &card->info.has_lp2lp_cso_v6);
 		if (rc)
-			changed ^= NETIF_F_IPV6_CSUM;
+			netdev_feature_change(NETIF_F_IPV6_CSUM_BIT, &changed);
 	}
 	if (changed & NETIF_F_RXCSUM) {
 		rc = qeth_set_ipa_rx_csum(card, features & NETIF_F_RXCSUM);
 		if (rc)
-			changed ^= NETIF_F_RXCSUM;
+			netdev_feature_change(NETIF_F_RXCSUM_BIT, &changed);
 	}
 	if (changed & NETIF_F_TSO) {
 		rc = qeth_set_ipa_tso(card, features & NETIF_F_TSO,
 				      QETH_PROT_IPV4);
 		if (rc)
-			changed ^= NETIF_F_TSO;
+			netdev_feature_change(NETIF_F_TSO_BIT, &changed);
 	}
 	if (changed & NETIF_F_TSO6) {
 		rc = qeth_set_ipa_tso(card, features & NETIF_F_TSO6,
 				      QETH_PROT_IPV6);
 		if (rc)
-			changed ^= NETIF_F_TSO6;
+			netdev_feature_change(NETIF_F_TSO6_BIT, &changed);
 	}
 
 	qeth_check_restricted_features(card, dev->features ^ features,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 27/36] treewide: use netdev_feature_del helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (25 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 26/36] treewide: use netdev_feature_change helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 28/36] treewide: use netdev_features_andnot and netdev_features_clear helpers Jian Shen
                   ` (8 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '&= ~' expreesions of single feature bit by
netdev_feature_del helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/infiniband/ulp/ipoib/ipoib_main.c     |  4 +-
 drivers/net/ethernet/altera/altera_tse_main.c |  2 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |  3 +-
 .../net/ethernet/aquantia/atlantic/aq_main.c  |  6 +--
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  2 +-
 .../net/ethernet/atheros/atl1e/atl1e_main.c   |  2 +-
 drivers/net/ethernet/atheros/atlx/atl2.c      |  2 +-
 drivers/net/ethernet/atheros/atlx/atlx.c      |  2 +-
 drivers/net/ethernet/broadcom/bnx2.c          |  2 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c   | 14 +++----
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  | 10 ++---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 34 ++++++++--------
 drivers/net/ethernet/cadence/macb_main.c      |  6 +--
 .../net/ethernet/cavium/liquidio/lio_main.c   | 20 +++++-----
 .../ethernet/cavium/liquidio/lio_vf_main.c    | 18 ++++-----
 .../net/ethernet/cavium/thunder/nicvf_main.c  |  2 +-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  2 +-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  5 ++-
 .../net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c   |  8 ++--
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  2 +-
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  2 +-
 drivers/net/ethernet/cisco/enic/enic_main.c   |  2 +-
 drivers/net/ethernet/emulex/benet/be_main.c   |  2 +-
 drivers/net/ethernet/faraday/ftgmac100.c      |  8 ++--
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   |  2 +-
 .../net/ethernet/huawei/hinic/hinic_main.c    |  2 +-
 drivers/net/ethernet/ibm/ibmveth.c            | 10 +++--
 drivers/net/ethernet/intel/e1000/e1000_main.c |  2 +-
 drivers/net/ethernet/intel/e1000e/netdev.c    |  4 +-
 drivers/net/ethernet/intel/fm10k/fm10k_main.c |  2 +-
 drivers/net/ethernet/intel/fm10k/fm10k_pci.c  |  3 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c   |  2 +-
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 28 +++++++------
 .../net/ethernet/intel/iavf/iavf_virtchnl.c   |  2 +-
 drivers/net/ethernet/intel/igb/igb_main.c     |  4 +-
 drivers/net/ethernet/intel/igbvf/netdev.c     |  2 +-
 drivers/net/ethernet/intel/igc/igc_main.c     |  4 +-
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 10 ++---
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |  2 +-
 drivers/net/ethernet/marvell/mvneta.c         |  4 +-
 .../marvell/octeontx2/nic/otx2_common.c       |  3 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  2 +-
 drivers/net/ethernet/marvell/sky2.c           |  6 +--
 .../net/ethernet/mellanox/mlx4/en_netdev.c    | 12 +++---
 .../net/ethernet/mellanox/mlx5/core/en_fs.c   |  2 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 34 ++++++++--------
 .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c |  2 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  6 +--
 .../ethernet/netronome/nfp/nfp_net_common.c   | 14 ++++---
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  2 +-
 .../ethernet/oki-semi/pch_gbe/pch_gbe_param.c |  2 +-
 .../ethernet/qlogic/netxen/netxen_nic_main.c  |  2 +-
 .../net/ethernet/qlogic/qede/qede_ethtool.c   |  3 +-
 .../net/ethernet/qlogic/qede/qede_filter.c    |  2 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c  |  4 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  7 ++--
 drivers/net/ethernet/realtek/8139cp.c         |  2 +-
 drivers/net/ethernet/realtek/r8169_main.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 +++--
 drivers/net/ethernet/sfc/siena/efx.c          |  4 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  2 +-
 drivers/net/ethernet/sun/sunvnet_common.c     |  2 +-
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  2 +-
 drivers/net/macvlan.c                         |  2 +-
 drivers/net/usb/r8152.c                       |  4 +-
 drivers/net/veth.c                            |  6 +--
 drivers/net/vmxnet3/vmxnet3_drv.c             | 12 ++++--
 drivers/net/vmxnet3/vmxnet3_ethtool.c         |  8 ++--
 drivers/net/wireless/ath/ath6kl/main.c        |  3 +-
 .../broadcom/brcm80211/brcmfmac/core.c        |  2 +-
 drivers/net/xen-netback/interface.c           | 10 ++---
 drivers/net/xen-netfront.c                    |  8 ++--
 drivers/s390/net/qeth_core_main.c             | 15 +++----
 drivers/s390/net/qeth_l3_main.c               |  2 +-
 net/core/dev.c                                | 39 ++++++++++---------
 net/core/skbuff.c                             |  3 +-
 net/dccp/ipv6.c                               |  5 ++-
 net/dsa/slave.c                               | 10 +++--
 net/ieee802154/core.c                         |  6 ++-
 net/ipv4/esp4_offload.c                       |  6 +--
 net/ipv4/gre_offload.c                        |  2 +-
 net/ipv4/udp_offload.c                        |  2 +-
 net/ipv6/esp6_offload.c                       |  6 +--
 net/openvswitch/vport-internal_dev.c          |  2 +-
 net/sctp/offload.c                            |  2 +-
 net/wireless/core.c                           |  6 ++-
 net/xfrm/xfrm_device.c                        |  6 +--
 92 files changed, 295 insertions(+), 254 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index e4d20673150c..8470f5ee6748 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -219,8 +219,8 @@ static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_featu
 	struct ipoib_dev_priv *priv = ipoib_priv(dev);
 
 	if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags)) {
-		features &= ~NETIF_F_IP_CSUM;
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_IP_CSUM_BIT, &features);
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 	}
 
 	return features;
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 3539769a84bb..97762bca0338 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -1557,7 +1557,7 @@ static int altera_tse_probe(struct platform_device *pdev)
 	/* Scatter/gather IO is not supported,
 	 * so it is turned off
 	 */
-	ndev->hw_features &= ~NETIF_F_SG;
+	netdev_hw_feature_del(ndev, NETIF_F_SG_BIT);
 	netdev_active_features_set(ndev, ndev->hw_features);
 	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
 
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 9d7ad79804e0..1ba0e24a0cb1 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2217,7 +2217,8 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 		if (features & NETIF_F_GSO_UDP_TUNNEL_CSUM) {
 			netdev_notice(netdev,
 				      "forcing tx udp tunnel checksumming off\n");
-			features &= ~NETIF_F_GSO_UDP_TUNNEL_CSUM;
+			netdev_feature_del(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+					   &features);
 		}
 	}
 
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
index 71acce12baec..53ca1fb4c989 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -270,13 +270,13 @@ static netdev_features_t aq_ndev_fix_features(struct net_device *ndev,
 	struct bpf_prog *prog;
 
 	if (!(features & NETIF_F_RXCSUM))
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	prog = READ_ONCE(aq_nic->xdp_prog);
 	if (prog && !prog->aux->xdp_has_frags &&
 	    aq_nic->xdp_prog && features & NETIF_F_LRO) {
 		netdev_err(ndev, "LRO is not supported with single buffer XDP, disabling\n");
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 	}
 
 	return features;
@@ -505,7 +505,7 @@ static int aq_xdp_setup(struct net_device *ndev, struct bpf_prog *prog,
 		if (prog && ndev->features & NETIF_F_LRO) {
 			netdev_err(ndev,
 				   "LRO is not supported with single buffer XDP, disabling\n");
-			ndev->features &= ~NETIF_F_LRO;
+			netdev_active_feature_del(ndev, NETIF_F_LRO_BIT);
 		}
 	}
 
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 01ab8bec3d4d..2113fa44026d 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -517,7 +517,7 @@ static netdev_features_t atl1c_fix_features(struct net_device *netdev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	if (hw->nic_type != athr_mt) {
 		if (netdev->mtu > MAX_TSO_FRAME_SIZE)
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 1e275e1006b3..43a64706bda6 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -392,7 +392,7 @@ static netdev_features_t atl1e_fix_features(struct net_device *netdev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 47b323c13448..81995490aa1d 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -382,7 +382,7 @@ static netdev_features_t atl2_fix_features(struct net_device *netdev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index 199b190ae23a..f9b0eddbe2ec 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -247,7 +247,7 @@ static netdev_features_t atlx_fix_features(struct net_device *netdev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 8455b0679670..d15ec211150c 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8609,7 +8609,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE;
 
 	if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
-		dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_hw_feature_del(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	if ((rc = register_netdev(dev))) {
 		dev_err(&pdev->dev, "Cannot register net device\n");
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index a1f3f6552101..7534fff7e676 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4891,7 +4891,7 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
 	dev->mtu = new_mtu;
 
 	if (!bnx2x_mtu_allows_gro(new_mtu))
-		dev->features &= ~NETIF_F_GRO_HW;
+		netdev_active_feature_del(dev, NETIF_F_GRO_HW_BIT);
 
 	if (IS_PF(bp) && SHMEM2_HAS(bp, curr_cfg))
 		SHMEM2_WR(bp, curr_cfg, CURR_CFG_MET_OS);
@@ -4911,14 +4911,14 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
 		 * would require internal reload of PF in bnx2x_set_features().
 		 */
 		if (!(features & NETIF_F_RXCSUM) && !bp->disable_tpa) {
-			features &= ~NETIF_F_RXCSUM;
+			netdev_feature_del(NETIF_F_RXCSUM_BIT, &features);
 			if (dev->features & NETIF_F_RXCSUM)
 				netdev_feature_add(NETIF_F_RXCSUM_BIT,
 						   &features);
 		}
 
 		if (changed & NETIF_F_LOOPBACK) {
-			features &= ~NETIF_F_LOOPBACK;
+			netdev_feature_del(NETIF_F_LOOPBACK_BIT, &features);
 			if (dev->features & NETIF_F_LOOPBACK)
 				netdev_feature_add(NETIF_F_LOOPBACK_BIT,
 						   &features);
@@ -4927,12 +4927,12 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
 
 	/* TPA requires Rx CSUM offloading */
 	if (!(features & NETIF_F_RXCSUM))
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	if (!(features & NETIF_F_GRO) || !bnx2x_mtu_allows_gro(dev->mtu))
-		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_feature_del(NETIF_F_LRO_BIT, &features);
 
 	return features;
 }
@@ -4960,7 +4960,7 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
 	}
 
 	/* Don't care about GRO changes */
-	changes &= ~NETIF_F_GRO;
+	netdev_feature_del(NETIF_F_GRO_BIT, &changes);
 
 	if (changes)
 		bnx2x_reload = true;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 92a1e370eac6..2c460493ccac 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12350,10 +12350,10 @@ static int bnx2x_init_bp(struct bnx2x *bp)
 
 	/* Set TPA flags */
 	if (bp->disable_tpa) {
-		bp->dev->hw_features &= ~NETIF_F_LRO;
-		bp->dev->hw_features &= ~NETIF_F_GRO_HW;
-		bp->dev->features &= ~NETIF_F_LRO;
-		bp->dev->features &= ~NETIF_F_GRO_HW;
+		netdev_hw_feature_del(bp->dev, NETIF_F_LRO_BIT);
+		netdev_hw_feature_del(bp->dev, NETIF_F_GRO_HW_BIT);
+		netdev_active_feature_del(bp->dev, NETIF_F_LRO_BIT);
+		netdev_active_feature_del(bp->dev, NETIF_F_GRO_HW_BIT);
 	}
 
 	if (CHIP_IS_E1(bp))
@@ -13282,7 +13282,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 	netdev_active_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (dev->features & NETIF_F_LRO)
-		dev->features &= ~NETIF_F_GRO_HW;
+		netdev_active_feature_del(dev, NETIF_F_GRO_HW_BIT);
 
 	/* Add Loopback capability to the device */
 	netdev_hw_feature_add(dev, NETIF_F_LOOPBACK_BIT);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 258d9491a2f7..e426aa407ed8 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -6511,8 +6511,8 @@ static int __bnxt_reserve_rings(struct bnxt *bp)
 
 			bp->flags &= ~BNXT_FLAG_AGG_RINGS;
 			bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
-			bp->dev->hw_features &= ~NETIF_F_LRO;
-			bp->dev->features &= ~NETIF_F_LRO;
+			netdev_hw_feature_del(bp->dev, NETIF_F_LRO_BIT);
+			netdev_active_feature_del(bp->dev, NETIF_F_LRO_BIT);
 			bnxt_set_ring_params(bp);
 		}
 	}
@@ -10444,7 +10444,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
 	if ((bp->flags & BNXT_FLAG_RFS) &&
 	    !(bp->flags & BNXT_FLAG_USING_MSIX)) {
 		/* disable RFS if falling back to INTA */
-		bp->dev->hw_features &= ~NETIF_F_NTUPLE;
+		netdev_hw_feature_del(bp->dev, NETIF_F_NTUPLE_BIT);
 		bp->flags &= ~BNXT_FLAG_RFS;
 	}
 
@@ -11177,23 +11177,23 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 	netdev_features_t vlan_features;
 
 	if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp))
-		features &= ~NETIF_F_NTUPLE;
+		netdev_feature_del(NETIF_F_NTUPLE_BIT, &features);
 
 	if (bp->flags & BNXT_FLAG_NO_AGG_RINGS) {
-		features &= ~NETIF_F_LRO;
-		features &= ~NETIF_F_GRO_HW;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
+		netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 	}
 
 	if (!(bp->flags & BNXT_FLAG_TPA)) {
-		features &= ~NETIF_F_LRO;
-		features &= ~NETIF_F_GRO_HW;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
+		netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 	}
 
 	if (!(features & NETIF_F_GRO))
-		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_feature_del(NETIF_F_LRO_BIT, &features);
 
 	/* Both CTAG and STAG VLAN accelaration on the RX side have to be
 	 * turned on or off together.
@@ -12263,8 +12263,8 @@ static void bnxt_set_dflt_rfs(struct bnxt *bp)
 {
 	struct net_device *dev = bp->dev;
 
-	dev->hw_features &= ~NETIF_F_NTUPLE;
-	dev->features &= ~NETIF_F_NTUPLE;
+	netdev_hw_feature_del(dev, NETIF_F_NTUPLE_BIT);
+	netdev_active_feature_del(dev, NETIF_F_NTUPLE_BIT);
 	bp->flags &= ~BNXT_FLAG_RFS;
 	if (bnxt_rfs_supported(bp)) {
 		netdev_hw_feature_add(dev, NETIF_F_NTUPLE_BIT);
@@ -13276,10 +13276,10 @@ static int bnxt_get_dflt_rings(struct bnxt *bp, int *max_rx, int *max_tx,
 			return rc;
 		}
 		bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
-		bp->dev->hw_features &= ~NETIF_F_LRO;
-		bp->dev->hw_features &= ~NETIF_F_GRO_HW;
-		bp->dev->features &= ~NETIF_F_LRO;
-		bp->dev->features &= ~NETIF_F_GRO_HW;
+		netdev_hw_feature_del(bp->dev, NETIF_F_LRO_BIT);
+		netdev_hw_feature_del(bp->dev, NETIF_F_GRO_HW_BIT);
+		netdev_active_feature_del(bp->dev, NETIF_F_LRO_BIT);
+		netdev_active_feature_del(bp->dev, NETIF_F_GRO_HW_BIT);
 		bnxt_set_ring_params(bp);
 	}
 
@@ -13657,7 +13657,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (dev->features & NETIF_F_GRO_HW)
-		dev->features &= ~NETIF_F_LRO;
+		netdev_active_feature_del(dev, NETIF_F_LRO_BIT);
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
 #ifdef CONFIG_BNXT_SRIOV
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 22553f3d69d6..fcac8394cb48 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -2149,7 +2149,7 @@ static netdev_features_t macb_features_check(struct sk_buff *skb,
 	 * apart from the last must be a multiple of 8 bytes in size.
 	 */
 	if (!IS_ALIGNED(skb_headlen(skb) - hdrlen, MACB_TX_LEN_ALIGN)) {
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 		return features;
 	}
 
@@ -2160,7 +2160,7 @@ static netdev_features_t macb_features_check(struct sk_buff *skb,
 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
 
 		if (!IS_ALIGNED(skb_frag_size(frag), MACB_TX_LEN_ALIGN)) {
-			features &= ~NETIF_F_TSO;
+			netdev_feature_del(NETIF_F_TSO_BIT, &features);
 			return features;
 		}
 	}
@@ -4065,7 +4065,7 @@ static int macb_init(struct platform_device *pdev)
 		netdev_hw_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	}
 	if (bp->caps & MACB_CAPS_SG_DISABLED)
-		dev->hw_features &= ~NETIF_F_SG;
+		netdev_hw_feature_del(dev, NETIF_F_SG_BIT);
 	dev->features = dev->hw_features;
 
 	/* Check RX Flow Filters support.
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index aa2e0d3537a3..fb12fcf85d0f 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2722,29 +2722,29 @@ static netdev_features_t liquidio_fix_features(struct net_device *netdev,
 
 	if ((request & NETIF_F_RXCSUM) &&
 	    !(lio->dev_capability & NETIF_F_RXCSUM))
-		request &= ~NETIF_F_RXCSUM;
+		netdev_feature_del(NETIF_F_RXCSUM_BIT, &request);
 
 	if ((request & NETIF_F_HW_CSUM) &&
 	    !(lio->dev_capability & NETIF_F_HW_CSUM))
-		request &= ~NETIF_F_HW_CSUM;
+		netdev_feature_del(NETIF_F_HW_CSUM_BIT, &request);
 
 	if ((request & NETIF_F_TSO) && !(lio->dev_capability & NETIF_F_TSO))
-		request &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &request);
 
 	if ((request & NETIF_F_TSO6) && !(lio->dev_capability & NETIF_F_TSO6))
-		request &= ~NETIF_F_TSO6;
+		netdev_feature_del(NETIF_F_TSO6_BIT, &request);
 
 	if ((request & NETIF_F_LRO) && !(lio->dev_capability & NETIF_F_LRO))
-		request &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &request);
 
 	/*Disable LRO if RXCSUM is off */
 	if (!(request & NETIF_F_RXCSUM) && (netdev->features & NETIF_F_LRO) &&
 	    (lio->dev_capability & NETIF_F_LRO))
-		request &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &request);
 
 	if ((request & NETIF_F_HW_VLAN_CTAG_FILTER) &&
 	    !(lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER))
-		request &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, &request);
 
 	return request;
 }
@@ -3591,7 +3591,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 					  &lio->enc_dev_capability);
 
 		netdev->hw_enc_features = lio->enc_dev_capability;
-		netdev->hw_enc_features &= ~NETIF_F_LRO;
+		netdev_hw_enc_feature_del(netdev, NETIF_F_LRO_BIT);
 
 		netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
 
@@ -3603,11 +3603,11 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 		netdev_features_set(&lio->dev_capability, netdev_ctag_vlan_features);
 
 		netdev->features = lio->dev_capability;
-		netdev->features &= ~NETIF_F_LRO;
+		netdev_active_feature_del(netdev, NETIF_F_LRO_BIT);
 
 		netdev->hw_features = lio->dev_capability;
 		/*HW_VLAN_RX and HW_VLAN_FILTER is always on*/
-		netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_hw_feature_del(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 		/* MTU range: 68 - 16000 */
 		netdev->min_mtu = LIO_MIN_MTU_SIZE;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 6ee1032b3dad..4d88cb7e1516 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -1820,25 +1820,25 @@ static netdev_features_t liquidio_fix_features(struct net_device *netdev,
 
 	if ((request & NETIF_F_RXCSUM) &&
 	    !(lio->dev_capability & NETIF_F_RXCSUM))
-		request &= ~NETIF_F_RXCSUM;
+		netdev_feature_del(NETIF_F_RXCSUM_BIT, &request);
 
 	if ((request & NETIF_F_HW_CSUM) &&
 	    !(lio->dev_capability & NETIF_F_HW_CSUM))
-		request &= ~NETIF_F_HW_CSUM;
+		netdev_feature_del(NETIF_F_HW_CSUM_BIT, &request);
 
 	if ((request & NETIF_F_TSO) && !(lio->dev_capability & NETIF_F_TSO))
-		request &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &request);
 
 	if ((request & NETIF_F_TSO6) && !(lio->dev_capability & NETIF_F_TSO6))
-		request &= ~NETIF_F_TSO6;
+		netdev_feature_del(NETIF_F_TSO6_BIT, &request);
 
 	if ((request & NETIF_F_LRO) && !(lio->dev_capability & NETIF_F_LRO))
-		request &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &request);
 
 	/* Disable LRO if RXCSUM is off */
 	if (!(request & NETIF_F_RXCSUM) && (netdev->features & NETIF_F_LRO) &&
 	    (lio->dev_capability & NETIF_F_LRO))
-		request &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &request);
 
 	return request;
 }
@@ -2123,7 +2123,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 					  &lio->enc_dev_capability);
 
 		netdev->hw_enc_features = lio->enc_dev_capability;
-		netdev->hw_enc_features &= ~NETIF_F_LRO;
+		netdev_hw_enc_feature_del(netdev, NETIF_F_LRO_BIT);
 		netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
 
 		netdev->vlan_features = lio->dev_capability;
@@ -2131,10 +2131,10 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 		netdev_features_set(&lio->dev_capability, netdev_ctag_vlan_features);
 
 		netdev->features = lio->dev_capability;
-		netdev->features &= ~NETIF_F_LRO;
+		netdev_active_feature_del(netdev, NETIF_F_LRO_BIT);
 
 		netdev->hw_features = lio->dev_capability;
-		netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_hw_feature_del(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 		/* MTU range: 68 - 16000 */
 		netdev->min_mtu = LIO_MIN_MTU_SIZE;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 67ad6c5e539f..373df6adcf6a 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1780,7 +1780,7 @@ static netdev_features_t nicvf_fix_features(struct net_device *netdev,
 
 	if ((features & NETIF_F_LOOPBACK) &&
 	    netif_running(netdev) && !nic->loopback_supported)
-		features &= ~NETIF_F_LOOPBACK;
+		netdev_feature_del(NETIF_F_LOOPBACK_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 80cc1f6fcfef..c00f4120e453 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -873,7 +873,7 @@ static netdev_features_t t1_fix_features(struct net_device *dev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index c6d08aceffa0..4c363379d995 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -2245,7 +2245,8 @@ static int cxgb_siocdevprivate(struct net_device *dev,
 				netdev_wanted_feature_add(dev,
 							  NETIF_F_GRO_BIT);
 			else
-				dev->wanted_features &= ~NETIF_F_GRO;
+				netdev_wanted_feature_del(dev,
+							  NETIF_F_GRO_BIT);
 			netdev_update_features(dev);
 		}
 
@@ -2597,7 +2598,7 @@ static netdev_features_t cxgb_fix_features(struct net_device *dev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
index a885f8d96e2f..13865ba2694a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c
@@ -110,10 +110,10 @@ int cxgb_fcoe_disable(struct net_device *netdev)
 
 	fcoe->flags &= ~CXGB_FCOE_ENABLED;
 
-	netdev->features &= ~NETIF_F_FCOE_CRC;
-	netdev->vlan_features &= ~NETIF_F_FCOE_CRC;
-	netdev->features &= ~NETIF_F_FCOE_MTU;
-	netdev->vlan_features &= ~NETIF_F_FCOE_MTU;
+	netdev_active_feature_del(netdev, NETIF_F_FCOE_CRC_BIT);
+	netdev_vlan_feature_del(netdev, NETIF_F_FCOE_CRC_BIT);
+	netdev_active_feature_del(netdev, NETIF_F_FCOE_MTU_BIT);
+	netdev_vlan_feature_del(netdev, NETIF_F_FCOE_MTU_BIT);
 
 	netdev_features_change(netdev);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 316fa87237b2..14a119232481 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3860,7 +3860,7 @@ static netdev_features_t cxgb_fix_features(struct net_device *dev,
 {
 	/* Disable GRO, if RX_CSUM is disabled */
 	if (!(features & NETIF_F_RXCSUM))
-		features &= ~NETIF_F_GRO;
+		netdev_feature_del(NETIF_F_GRO_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index a96a45e8e805..a6056a80058a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -1184,7 +1184,7 @@ static netdev_features_t cxgb4vf_fix_features(struct net_device *dev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 5e67f4cd4285..1b401125aaf0 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2896,7 +2896,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev_active_features_set(netdev, netdev_ctag_vlan_offload_features);
 	if (ENIC_SETTING(enic, LOOP)) {
-		netdev->features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_active_feature_del(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 		enic->loop_enable = 1;
 		enic->loop_tag = enic->config.loop_tag;
 		dev_info(dev, "loopback tag=0x%04x\n", enic->loop_tag);
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index ed6339b57841..ba54b89149a9 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5081,7 +5081,7 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
 		 * to Lancer and BE3 HW. Disable TSO6 feature.
 		 */
 		if (!skyhawk_chip(adapter) && is_ipv6_ext_hdr(skb))
-			features &= ~NETIF_F_TSO6;
+			netdev_feature_del(NETIF_F_TSO6_BIT, &features);
 
 		/* Lancer cannot handle the packet with MSS less than 256.
 		 * Also it can't handle a TSO packet with a single segment
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 17525ce5f682..ce160fa7fc46 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1947,15 +1947,15 @@ static int ftgmac100_probe(struct platform_device *pdev)
 
 	/* AST2400  doesn't have working HW checksum generation */
 	if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac")))
-		netdev->hw_features &= ~NETIF_F_HW_CSUM;
+		netdev_hw_feature_del(netdev, NETIF_F_HW_CSUM_BIT);
 
 	/* AST2600 tx checksum with NCSI is broken */
 	if (priv->use_ncsi && of_device_is_compatible(np, "aspeed,ast2600-mac"))
-		netdev->hw_features &= ~NETIF_F_HW_CSUM;
+		netdev_hw_feature_del(netdev, NETIF_F_HW_CSUM_BIT);
 
 	if (np && of_get_property(np, "no-hw-checksum", NULL)) {
-		netdev->hw_features &= ~NETIF_F_HW_CSUM;
-		netdev->hw_features &= ~NETIF_F_RXCSUM;
+		netdev_hw_feature_del(netdev, NETIF_F_HW_CSUM_BIT);
+		netdev_hw_feature_del(netdev, NETIF_F_RXCSUM_BIT);
 	}
 	netdev_active_features_set(netdev, netdev->hw_features);
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 30f231610e61..105ed4d4aab5 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -3316,7 +3316,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/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 4e49e2c4b409..544c4e499d38 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -872,7 +872,7 @@ static netdev_features_t hinic_fix_features(struct net_device *netdev,
 	/* If Rx checksum is disabled, then LRO should also be disabled */
 	if (!(features & NETIF_F_RXCSUM)) {
 		netif_info(nic_dev, drv, netdev, "disabling LRO as RXCSUM is off\n");
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 	}
 
 	return features;
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 4687a22434ed..8c1398f8b059 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -794,7 +794,8 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)
 					   set_attr, clr_attr, &ret_attr);
 
 			if (data == 1)
-				dev->features &= ~NETIF_F_IP_CSUM;
+				netdev_active_feature_del(dev,
+							  NETIF_F_IP_CSUM_BIT);
 
 		} else {
 			adapter->fw_ipv4_csum_support = data;
@@ -812,7 +813,8 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)
 					   set_attr6, clr_attr6, &ret_attr);
 
 			if (data == 1)
-				dev->features &= ~NETIF_F_IPV6_CSUM;
+				netdev_active_feature_del(dev,
+							  NETIF_F_IPV6_CSUM_BIT);
 
 		} else
 			adapter->fw_ipv6_csum_support = data;
@@ -884,7 +886,7 @@ static int ibmveth_set_tso(struct net_device *dev, u32 data)
 		 * support tcp6/ipv6
 		 */
 		if (data == 1) {
-			dev->features &= ~NETIF_F_TSO6;
+			netdev_active_feature_del(dev, NETIF_F_TSO6_BIT);
 			netdev_info(dev, "TSO feature requires all partitions to have updated driver");
 		}
 		adapter->large_send = data;
@@ -908,7 +910,7 @@ static int ibmveth_set_features(struct net_device *dev,
 		rc1 = ibmveth_set_csum_offload(dev, rx_csum);
 		if (rc1 && !adapter->rx_csum) {
 			dev->features = features & ~NETIF_F_CSUM_MASK;
-			dev->features &= ~NETIF_F_RXCSUM;
+			netdev_active_feature_del(dev, NETIF_F_RXCSUM_BIT);
 		}
 	}
 
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index acf68d405812..3958edb44a1d 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -796,7 +796,7 @@ static netdev_features_t e1000_fix_features(struct net_device *netdev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index a2b28da7a56e..1e51c751ff3b 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -7297,7 +7297,7 @@ static netdev_features_t e1000_fix_features(struct net_device *netdev,
 
 	/* Jumbo frame workaround on 82579 and newer requires CRC be stripped */
 	if ((hw->mac.type >= e1000_pch2lan) && (netdev->mtu > ETH_DATA_LEN))
-		features &= ~NETIF_F_RXFCS;
+		netdev_feature_del(NETIF_F_RXFCS_BIT, &features);
 
 	/* Since there is no support for separate Rx/Tx vlan accel
 	 * enable/disable make sure Tx flag is always in same state as Rx.
@@ -7305,7 +7305,7 @@ static netdev_features_t e1000_fix_features(struct net_device *netdev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index 3362f26d7f99..db6501c8ea39 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -772,7 +772,7 @@ static int fm10k_tso(struct fm10k_ring *tx_ring,
 	return 1;
 
 err_vxlan:
-	tx_ring->netdev->features &= ~NETIF_F_GSO_UDP_TUNNEL;
+	netdev_active_feature_del(tx_ring->netdev, NETIF_F_GSO_UDP_TUNNEL_BIT);
 	if (net_ratelimit())
 		netdev_err(tx_ring->netdev,
 			   "TSO requested for unsupported tunnel, disabling offload\n");
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index d5be43c80c14..dbb40065aeba 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -305,7 +305,8 @@ static int fm10k_handle_reset(struct fm10k_intfc *interface)
 		}
 
 		if (hw->mac.vlan_override)
-			netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+			netdev_active_feature_del(netdev,
+						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 		else
 			netdev_active_feature_add(netdev,
 						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 25a2b77ffd6f..2377a01904ac 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13720,7 +13720,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	netdev_hw_enc_feature_add(netdev, NETIF_F_TSO_MANGLEID_BIT);
 
-	netdev->features &= ~NETIF_F_HW_TC;
+	netdev_active_feature_del(netdev, NETIF_F_HW_TC_BIT);
 
 	if (vsi->type == I40E_VSI_MAIN) {
 		SET_NETDEV_DEV(netdev, &pf->pdev->dev);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index ae8471342166..38b4756e0992 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4504,31 +4504,37 @@ iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_CTAG_TX_BIT))
-		requested_features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				   &requested_features);
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_CTAG_RX_BIT))
-		requested_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				   &requested_features);
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_STAG_TX_BIT))
-		requested_features &= ~NETIF_F_HW_VLAN_STAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_STAG_TX_BIT,
+				   &requested_features);
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_STAG_RX_BIT))
-		requested_features &= ~NETIF_F_HW_VLAN_STAG_RX;
+		netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT,
+				   &requested_features);
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
-		requested_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				   &requested_features);
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_STAG_FILTER_BIT))
-		requested_features &= ~NETIF_F_HW_VLAN_STAG_FILTER;
+		netdev_feature_del(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
+				   &requested_features);
 
 	if ((requested_features & netdev_ctag_vlan_offload_features) &&
 	    (requested_features & netdev_stag_vlan_offload_features) &&
@@ -4686,16 +4692,16 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	if (netdev->wanted_features) {
 		if (!(netdev->wanted_features & NETIF_F_TSO) ||
 		    netdev->mtu < 576)
-			netdev->features &= ~NETIF_F_TSO;
+			netdev_active_feature_del(netdev, NETIF_F_TSO_BIT);
 		if (!(netdev->wanted_features & NETIF_F_TSO6) ||
 		    netdev->mtu < 576)
-			netdev->features &= ~NETIF_F_TSO6;
+			netdev_active_feature_del(netdev, NETIF_F_TSO6_BIT);
 		if (!(netdev->wanted_features & NETIF_F_TSO_ECN))
-			netdev->features &= ~NETIF_F_TSO_ECN;
+			netdev_active_feature_del(netdev, NETIF_F_TSO_ECN_BIT);
 		if (!(netdev->wanted_features & NETIF_F_GRO))
-			netdev->features &= ~NETIF_F_GRO;
+			netdev_active_feature_del(netdev, NETIF_F_GRO_BIT);
 		if (!(netdev->wanted_features & NETIF_F_GSO))
-			netdev->features &= ~NETIF_F_GSO;
+			netdev_active_feature_del(netdev, NETIF_F_GSO_BIT);
 	}
 
 	return 0;
diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
index 56bca0d7b0f5..1bb120db96cc 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -1880,7 +1880,7 @@ static void iavf_netdev_features_vlan_strip_set(struct net_device *netdev,
 	if (enable)
 		netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	else
-		netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_active_feature_del(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index c6b1d30ba2f6..cb109bc49c31 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2441,7 +2441,7 @@ static netdev_features_t igb_fix_features(struct net_device *netdev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
@@ -2543,7 +2543,7 @@ igb_features_check(struct sk_buff *skb, struct net_device *dev,
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
 	 */
 	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 7d04d87157de..09a7b7631950 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2656,7 +2656,7 @@ igbvf_features_check(struct sk_buff *skb, struct net_device *dev,
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
 	 */
 	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index c594dfeb5dfd..0d7f99a58a00 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4943,7 +4943,7 @@ static netdev_features_t igc_fix_features(struct net_device *netdev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
@@ -5011,7 +5011,7 @@ igc_features_check(struct sk_buff *skb, struct net_device *dev,
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
 	 */
 	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 7630db8cc290..82a7373268c8 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -302,7 +302,7 @@ ixgb_fix_features(struct net_device *netdev, netdev_features_t features)
 	 * disabled.
 	 */
 	if (!(features & NETIF_F_HW_VLAN_CTAG_RX))
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index 603a910aa611..dd180400b454 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -898,7 +898,7 @@ int ixgbe_fcoe_disable(struct net_device *netdev)
 
 	/* disable FCoE and notify stack */
 	adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
-	netdev->features &= ~NETIF_F_FCOE_MTU;
+	netdev_active_feature_del(netdev, NETIF_F_FCOE_MTU_BIT);
 
 	netdev_features_change(netdev);
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 727df1a82ec0..05ce8c4fdd99 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -4922,7 +4922,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
 		hw->addr_ctrl.user_set_promisc = true;
 		fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
 		vmolr |= IXGBE_VMOLR_MPE;
-		features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, &features);
 	} else {
 		if (netdev->flags & IFF_ALLMULTI) {
 			fctrl |= IXGBE_FCTRL_MPE;
@@ -9837,15 +9837,15 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev,
 
 	/* If Rx checksum is disabled, then RSC/LRO should also be disabled */
 	if (!(features & NETIF_F_RXCSUM))
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	/* Turn off LRO if not RSC capable */
 	if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	if (adapter->xdp_prog && (features & NETIF_F_LRO)) {
 		e_dev_err("LRO is not supported with XDP\n");
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 	}
 
 	return features;
@@ -10259,7 +10259,7 @@ ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
 #ifdef CONFIG_IXGBE_IPSEC
 		if (!secpath_exists(skb))
 #endif
-			features &= ~NETIF_F_TSO;
+			netdev_feature_del(NETIF_F_TSO_BIT, &features);
 	}
 
 	return features;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index bca192bf7ed9..2ccee2e984ec 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4437,7 +4437,7 @@ ixgbevf_features_check(struct sk_buff *skb, struct net_device *dev,
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
 	 */
 	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index c2a77f161286..dc67d93c6e44 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -3848,8 +3848,8 @@ static netdev_features_t mvneta_fix_features(struct net_device *dev,
 	struct mvneta_port *pp = netdev_priv(dev);
 
 	if (pp->tx_csum_limit && dev->mtu > pp->tx_csum_limit) {
-		features &= ~NETIF_F_IP_CSUM;
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_IP_CSUM_BIT, &features);
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 		netdev_info(dev,
 			    "Disable IP checksum for MTU greater than %dB\n",
 			    pp->tx_csum_limit);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index fb8db5888d2f..2d08af351de8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/pci.h>
 #include <net/tso.h>
 
@@ -496,7 +497,7 @@ void otx2_setup_segmentation(struct otx2_nic *pfvf)
 	mutex_unlock(&pfvf->mbox.lock);
 	netdev_info(pfvf->netdev,
 		    "Failed to get LSO index for UDP GSO offload, disabling\n");
-	pfvf->netdev->hw_features &= ~NETIF_F_GSO_UDP_L4;
+	netdev_hw_feature_del(pfvf->netdev, NETIF_F_GSO_UDP_L4_BIT);
 }
 
 void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index ef2d175f586b..9b68a79fc6e5 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1860,7 +1860,7 @@ static netdev_features_t otx2_fix_features(struct net_device *dev,
 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
 		netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_STAG_RX;
+		netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index caaa3692e2b8..74b91fddd036 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -2681,7 +2681,7 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
 		 * It will be reenabled on next ndo_set_features, but if it's
 		 * really broken, will get disabled again
 		 */
-		sky2->netdev->features &= ~NETIF_F_RXCSUM;
+		netdev_active_feature_del(sky2->netdev, NETIF_F_RXCSUM_BIT);
 		sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
 			     BMU_DIS_RX_CHKSUM);
 	}
@@ -4316,8 +4316,8 @@ static netdev_features_t sky2_fix_features(struct net_device *dev,
 	 */
 	if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) {
 		netdev_info(dev, "checksum offload not possible with jumbo frames\n");
-		features &= ~NETIF_F_TSO;
-		features &= ~NETIF_F_SG;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
+		netdev_feature_del(NETIF_F_SG_BIT, &features);
 		features &= ~NETIF_F_CSUM_MASK;
 	}
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 113944e047ab..ba8fdfc3b33a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2510,7 +2510,7 @@ static netdev_features_t mlx4_en_fix_features(struct net_device *netdev,
 	    !(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN))
 		netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT, &features);
 	else
-		features &= ~NETIF_F_HW_VLAN_STAG_RX;
+		netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT, &features);
 
 	return features;
 }
@@ -3565,7 +3565,8 @@ int mlx4_en_reset_config(struct net_device *dev,
 			netdev_active_feature_add(dev,
 						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 		else
-			dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+			netdev_active_feature_del(dev,
+						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	} else if (ts_config.rx_filter == HWTSTAMP_FILTER_NONE) {
 		/* RX time-stamping is OFF, update the RX vlan offload
 		 * to the latest wanted state
@@ -3574,14 +3575,15 @@ int mlx4_en_reset_config(struct net_device *dev,
 			netdev_active_feature_add(dev,
 						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 		else
-			dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+			netdev_active_feature_del(dev,
+						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	}
 
 	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_RXFCS_BIT)) {
 		if (features & NETIF_F_RXFCS)
 			netdev_active_feature_add(dev, NETIF_F_RXFCS_BIT);
 		else
-			dev->features &= ~NETIF_F_RXFCS;
+			netdev_active_feature_del(dev, NETIF_F_RXFCS_BIT);
 	}
 
 	/* RX vlan offload and RX time-stamping can't co-exist !
@@ -3591,7 +3593,7 @@ int mlx4_en_reset_config(struct net_device *dev,
 	if (ts_config.rx_filter != HWTSTAMP_FILTER_NONE) {
 		if (dev->features & NETIF_F_HW_VLAN_CTAG_RX)
 			en_warn(priv, "Turning off RX vlan offload since RX time-stamping is ON\n");
-		dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_active_feature_del(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	}
 
 	if (port_up) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
index e2a9b9be5c1f..c4b12191cfed 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -1279,7 +1279,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
 	if (err) {
 		mlx5_core_err(priv->fs->mdev, "Failed to create arfs tables, err=%d\n",
 			      err);
-		priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
+		netdev_hw_feature_del(priv->netdev, NETIF_F_NTUPLE_BIT);
 	}
 
 	err = mlx5e_create_inner_ttc_table(priv);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index ddedeac29935..bfbbc3bc152b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3890,19 +3890,19 @@ int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
 static netdev_features_t mlx5e_fix_uplink_rep_features(struct net_device *netdev,
 						       netdev_features_t features)
 {
-	features &= ~NETIF_F_HW_TLS_RX;
+	netdev_feature_del(NETIF_F_HW_TLS_RX_BIT, &features);
 	if (netdev->features & NETIF_F_HW_TLS_RX)
 		netdev_warn(netdev, "Disabling hw_tls_rx, not supported in switchdev mode\n");
 
-	features &= ~NETIF_F_HW_TLS_TX;
+	netdev_feature_del(NETIF_F_HW_TLS_TX_BIT, &features);
 	if (netdev->features & NETIF_F_HW_TLS_TX)
 		netdev_warn(netdev, "Disabling hw_tls_tx, not supported in switchdev mode\n");
 
-	features &= ~NETIF_F_NTUPLE;
+	netdev_feature_del(NETIF_F_NTUPLE_BIT, &features);
 	if (netdev->features & NETIF_F_NTUPLE)
 		netdev_warn(netdev, "Disabling ntuple, not supported in switchdev mode\n");
 
-	features &= ~NETIF_F_GRO_HW;
+	netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 	if (netdev->features & NETIF_F_GRO_HW)
 		netdev_warn(netdev, "Disabling HW_GRO, not supported in switchdev mode\n");
 
@@ -3922,7 +3922,7 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
 		/* HW strips the outer C-tag header, this is a problem
 		 * for S-tag traffic.
 		 */
-		features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_RX_BIT, &features);
 		if (!params->vlan_strip_disable)
 			netdev_warn(netdev, "Dropping C-tag vlan stripping offload due to S-tag vlan\n");
 	}
@@ -3930,22 +3930,22 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
 	if (!MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ)) {
 		if (features & NETIF_F_LRO) {
 			netdev_warn(netdev, "Disabling LRO, not supported in legacy RQ\n");
-			features &= ~NETIF_F_LRO;
+			netdev_feature_del(NETIF_F_LRO_BIT, &features);
 		}
 		if (features & NETIF_F_GRO_HW) {
 			netdev_warn(netdev, "Disabling HW-GRO, not supported in legacy RQ\n");
-			features &= ~NETIF_F_GRO_HW;
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 		}
 	}
 
 	if (params->xdp_prog) {
 		if (features & NETIF_F_LRO) {
 			netdev_warn(netdev, "LRO is incompatible with XDP\n");
-			features &= ~NETIF_F_LRO;
+			netdev_feature_del(NETIF_F_LRO_BIT, &features);
 		}
 		if (features & NETIF_F_GRO_HW) {
 			netdev_warn(netdev, "HW GRO is incompatible with XDP\n");
-			features &= ~NETIF_F_GRO_HW;
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 		}
 	}
 
@@ -3953,23 +3953,23 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
 		if (features & NETIF_F_LRO) {
 			netdev_warn(netdev, "LRO is incompatible with AF_XDP (%u XSKs are active)\n",
 				    priv->xsk.refcnt);
-			features &= ~NETIF_F_LRO;
+			netdev_feature_del(NETIF_F_LRO_BIT, &features);
 		}
 		if (features & NETIF_F_GRO_HW) {
 			netdev_warn(netdev, "HW GRO is incompatible with AF_XDP (%u XSKs are active)\n",
 				    priv->xsk.refcnt);
-			features &= ~NETIF_F_GRO_HW;
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 		}
 	}
 
 	if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
-		features &= ~NETIF_F_RXHASH;
+		netdev_feature_del(NETIF_F_RXHASH_BIT, &features);
 		if (netdev->features & NETIF_F_RXHASH)
 			netdev_warn(netdev, "Disabling rxhash, not supported when CQE compress is active\n");
 
 		if (features & NETIF_F_GRO_HW) {
 			netdev_warn(netdev, "Disabling HW-GRO, not supported when CQE compress is active\n");
-			features &= ~NETIF_F_GRO_HW;
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 		}
 	}
 
@@ -4975,10 +4975,10 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 
 	/* Defaults */
 	if (fcs_enabled)
-		netdev->features  &= ~NETIF_F_RXALL;
-	netdev->features  &= ~NETIF_F_LRO;
-	netdev->features  &= ~NETIF_F_GRO_HW;
-	netdev->features  &= ~NETIF_F_RXFCS;
+		netdev_active_feature_del(netdev, NETIF_F_RXALL_BIT);
+	netdev_active_feature_del(netdev, NETIF_F_LRO_BIT);
+	netdev_active_feature_del(netdev, NETIF_F_GRO_HW_BIT);
+	netdev_active_feature_del(netdev, NETIF_F_RXFCS_BIT);
 
 #define FT_CAP(f) MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive.f)
 	if (FT_CAP(flow_modify_en) &&
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
index d859b58c4c8b..71a0b7db41c7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -336,7 +336,7 @@ static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
 	if (err) {
 		netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n",
 			   err);
-		priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
+		netdev_hw_feature_del(priv->netdev, NETIF_F_NTUPLE_BIT);
 	}
 
 	err = mlx5e_create_ttc_table(priv);
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index c6dd11c872f9..285688a88a0e 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -2901,7 +2901,7 @@ static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
 	struct myri10ge_slice_state *ss;
 	netdev_tx_t status;
 
-	features &= ~NETIF_F_TSO6;
+	netdev_feature_del(NETIF_F_TSO6_BIT, &features);
 	segs = skb_gso_segment(skb, features);
 	if (IS_ERR(segs))
 		goto drop;
@@ -3878,9 +3878,9 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netdev_vlan_features_set(netdev, mgp->features);
 	if (mgp->fw_ver_tiny < 37)
-		netdev->vlan_features &= ~NETIF_F_TSO6;
+		netdev_vlan_feature_del(netdev, NETIF_F_TSO6_BIT);
 	if (mgp->fw_ver_tiny < 32)
-		netdev->vlan_features &= ~NETIF_F_TSO;
+		netdev_vlan_feature_del(netdev, NETIF_F_TSO_BIT);
 
 	/* make sure we can get an irq, and that MSI can be
 	 * setup (if available). */
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 071e0c6aa219..9bda15a858d6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1759,13 +1759,17 @@ nfp_net_fix_features(struct net_device *netdev,
 	if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
 	    (features & NETIF_F_HW_VLAN_STAG_RX)) {
 		if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
-			features &= ~NETIF_F_HW_VLAN_CTAG_RX;
-			netdev->wanted_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+			netdev_feature_del(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+					   &features);
+			netdev_wanted_feature_del(netdev,
+						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 			netdev_warn(netdev,
 				    "S-tag and C-tag stripping can't be enabled at the same time. Enabling S-tag stripping and disabling C-tag stripping\n");
 		} else if (netdev->features & NETIF_F_HW_VLAN_STAG_RX) {
-			features &= ~NETIF_F_HW_VLAN_STAG_RX;
-			netdev->wanted_features &= ~NETIF_F_HW_VLAN_STAG_RX;
+			netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT,
+					   &features);
+			netdev_wanted_feature_del(netdev,
+						  NETIF_F_HW_VLAN_STAG_RX_BIT);
 			netdev_warn(netdev,
 				    "S-tag and C-tag stripping can't be enabled at the same time. Enabling C-tag stripping and disabling S-tag stripping\n");
 		}
@@ -2431,7 +2435,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 	/* C-Tag strip and S-Tag strip can't be supported simultaneously,
 	 * so enable C-Tag strip and disable S-Tag strip by default.
 	 */
-	netdev->features &= ~NETIF_F_HW_VLAN_STAG_RX;
+	netdev_active_feature_del(netdev, NETIF_F_HW_VLAN_STAG_RX_BIT);
 	nn->dp.ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ;
 
 	/* Finalise the netdev setup */
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index b8a8aa917fdd..acee5eeb4d2e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -391,7 +391,7 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 	/* C-Tag strip and S-Tag strip can't be supported simultaneously,
 	 * so enable C-Tag strip and disable S-Tag strip by default.
 	 */
-	netdev->features &= ~NETIF_F_HW_VLAN_STAG_RX;
+	netdev_active_feature_del(netdev, NETIF_F_HW_VLAN_STAG_RX_BIT);
 	netif_set_tso_max_segs(netdev, NFP_NET_LSO_MAX_SEGS);
 
 	netdev->priv_flags |= IFF_NO_QUEUE | IFF_DISABLE_NETPOLL;
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
index 81fc5a6e3221..4652884248be 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
@@ -477,7 +477,7 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
 		val = XsumRX;
 		pch_gbe_validate_option(&val, &opt, adapter);
 		if (!val)
-			dev->features &= ~NETIF_F_RXCSUM;
+			netdev_active_feature_del(dev, NETIF_F_RXCSUM_BIT);
 	}
 	{ /* Checksum Offload Enable/Disable */
 		static const struct pch_gbe_option opt = {
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index ce1bb941fd85..20fa5204b15c 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -526,7 +526,7 @@ static netdev_features_t netxen_fix_features(struct net_device *dev,
 	if (!(features & NETIF_F_RXCSUM)) {
 		netdev_info(dev, "disabling LRO as RXCSUM is off\n");
 
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 	}
 
 	return features;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 97a7ab0826ed..dd8bd6ec734a 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -7,6 +7,7 @@
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/string.h>
@@ -1044,7 +1045,7 @@ int qede_change_mtu(struct net_device *ndev, int new_mtu)
 		   "Configuring MTU size of %d\n", new_mtu);
 
 	if (new_mtu > PAGE_SIZE)
-		ndev->features &= ~NETIF_F_GRO_HW;
+		netdev_active_feature_del(ndev, NETIF_F_GRO_HW_BIT);
 
 	/* Set the mtu field and re-start the interface if needed */
 	args.u.mtu = new_mtu;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index 3010833ddde3..9ec8daa60d6d 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -917,7 +917,7 @@ netdev_features_t qede_fix_features(struct net_device *dev,
 
 	if (edev->xdp_prog || edev->ndev->mtu > PAGE_SIZE ||
 	    !(features & NETIF_F_GRO))
-		features &= ~NETIF_F_GRO_HW;
+		netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 64ba47a8629b..832a4dc8d89c 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1583,7 +1583,7 @@ static int qede_alloc_mem_rxq(struct qede_dev *edev, struct qede_rx_queue *rxq)
 		rxq->rx_buf_seg_size = roundup_pow_of_two(size);
 	} else {
 		rxq->rx_buf_seg_size = PAGE_SIZE;
-		edev->ndev->features &= ~NETIF_F_GRO_HW;
+		netdev_active_feature_del(edev->ndev, NETIF_F_GRO_HW_BIT);
 	}
 
 	/* Allocate the parallel driver ring for Rx buffers */
@@ -2472,7 +2472,7 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,
 		goto err2;
 
 	if (qede_alloc_arfs(edev)) {
-		edev->ndev->features &= ~NETIF_F_NTUPLE;
+		netdev_active_feature_del(edev->ndev, NETIF_F_NTUPLE_BIT);
 		edev->dev_info.common.b_arfs_capable = false;
 	}
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index ab7e234132ed..503d18280559 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1042,12 +1042,13 @@ static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
 		adapter->rx_csum = 1;
 		if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
 			if (!(offload_flags & BIT_1))
-				features &= ~NETIF_F_TSO;
+				netdev_feature_del(NETIF_F_TSO_BIT, &features);
 			else
 				netdev_feature_add(NETIF_F_TSO_BIT, &features);
 
 			if (!(offload_flags & BIT_2))
-				features &= ~NETIF_F_TSO6;
+				netdev_feature_del(NETIF_F_TSO6_BIT,
+						   &features);
 			else
 				netdev_feature_add(NETIF_F_TSO6_BIT,
 						   &features);
@@ -1085,7 +1086,7 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 	}
 
 	if (!(features & NETIF_F_RXCSUM))
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 778c75b76950..63f4ef15ebba 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1862,7 +1862,7 @@ static netdev_features_t cp_features_check(struct sk_buff *skb,
 					   netdev_features_t features)
 {
 	if (skb_shinfo(skb)->gso_size > MSSMask)
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	return vlan_features_check(skb, features);
 }
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index d0887e74167f..d9f92be3e246 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5440,7 +5440,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 */
 	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
 		/* Disallow toggling */
-		dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_hw_feature_del(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	if (rtl_chip_supports_csum_v2(tp))
 		netdev_hw_feature_add(dev, NETIF_F_IPV6_CSUM_BIT);
diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c
index 4a3cbc1c50ec..ede1ec1c7d2f 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 5134fbd0382a..77aee7b35585 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1030,13 +1030,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 b803b8688c60..1ef24fb2315d 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2918,7 +2918,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 4ff6586116ee..dc6342710233 100644
--- a/drivers/net/ethernet/sfc/mcdi_filters.c
+++ b/drivers/net/ethernet/sfc/mcdi_filters.c
@@ -1330,9 +1330,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/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index d5818151bb04..a18f5fc16b20 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -1012,13 +1012,13 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 			       net_dev->features & ~efx->fixed_features);
 
 	/* 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/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 4d722a6ed2ca..8028c1e4d65b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5606,7 +5606,7 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
 	struct stmmac_priv *priv = netdev_priv(dev);
 
 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
-		features &= ~NETIF_F_RXCSUM;
+		netdev_feature_del(NETIF_F_RXCSUM_BIT, &features);
 
 	if (!priv->plat->tx_coe)
 		features &= ~NETIF_F_CSUM_MASK;
diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c
index f8aced92d2a9..7813677b63c9 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.c
+++ b/drivers/net/ethernet/sun/sunvnet_common.c
@@ -1275,7 +1275,7 @@ vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb,
 		skb_shinfo(skb)->gso_size = datalen;
 		skb_shinfo(skb)->gso_segs = gso_segs;
 	}
-	features &= ~NETIF_F_TSO;
+	netdev_feature_del(NETIF_F_TSO_BIT, &features);
 	segs = skb_gso_segment(skb, features);
 	if (IS_ERR(segs))
 		goto out_dropped;
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index fb32c1f045e6..4040481def57 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1999,7 +1999,7 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 
 	/* Disable TX checksum offload by default due to HW bug */
 	if (common->pdata.quirks & AM65_CPSW_QUIRK_I2027_NO_TX_CSUM)
-		port->ndev->features &= ~NETIF_F_HW_CSUM;
+		netdev_active_feature_del(port->ndev, NETIF_F_HW_CSUM_BIT);
 
 	ndev_priv->stats = netdev_alloc_pcpu_stats(struct am65_cpsw_ndev_stats);
 	if (!ndev_priv->stats)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 1fc6941fe633..16d2763fc227 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1109,7 +1109,7 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
 	mask = features;
 
 	tmp = features;
-	tmp &= ~NETIF_F_LRO;
+	netdev_feature_del(NETIF_F_LRO_BIT, &tmp);
 	lowerdev_features &= tmp;
 	features = netdev_increment_features(lowerdev_features, features, mask);
 	netdev_features_set(&features, ALWAYS_ON_FEATURES);
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 218e10ee5442..52489af158e6 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -9704,8 +9704,8 @@ static int rtl8152_probe(struct usb_interface *intf,
 	netdev_vlan_features_set_array(netdev, &r8152_vlan_feature_set);
 
 	if (tp->version == RTL_VER_01) {
-		netdev->features &= ~NETIF_F_RXCSUM;
-		netdev->hw_features &= ~NETIF_F_RXCSUM;
+		netdev_active_feature_del(netdev, NETIF_F_RXCSUM_BIT);
+		netdev_hw_feature_del(netdev, NETIF_F_RXCSUM_BIT);
 	}
 
 	tp->lenovo_macpassthru = rtl8152_supports_lenovo_macpassthru(udev);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index fe9bc2f94672..ef4bb4e63d70 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1175,7 +1175,7 @@ static void veth_disable_xdp(struct net_device *dev)
 		 * enabled it, clear it now
 		 */
 		if (!veth_gro_requested(dev) && netif_running(dev)) {
-			dev->features &= ~NETIF_F_GRO;
+			netdev_active_feature_del(dev, NETIF_F_GRO_BIT);
 			netdev_features_change(dev);
 		}
 	}
@@ -1690,8 +1690,8 @@ static struct rtnl_link_ops veth_link_ops;
 
 static void veth_disable_gro(struct net_device *dev)
 {
-	dev->features &= ~NETIF_F_GRO;
-	dev->wanted_features &= ~NETIF_F_GRO;
+	netdev_active_feature_del(dev, NETIF_F_GRO_BIT);
+	netdev_wanted_feature_del(dev, NETIF_F_GRO_BIT);
 	netdev_update_features(dev);
 }
 
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index f08209bf2274..b86820386f60 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3377,13 +3377,17 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 		    !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_VXLAN_CHECKSUM_OFFLOAD)) &&
 		    !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_GENEVE_TSO)) &&
 		    !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_VXLAN_TSO))) {
-			netdev->hw_enc_features &= ~NETIF_F_GSO_UDP_TUNNEL;
-			netdev->hw_features &= ~NETIF_F_GSO_UDP_TUNNEL;
+			netdev_hw_enc_feature_del(netdev,
+						  NETIF_F_GSO_UDP_TUNNEL_BIT);
+			netdev_hw_feature_del(netdev,
+					      NETIF_F_GSO_UDP_TUNNEL_BIT);
 		}
 		if (!(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD)) &&
 		    !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD))) {
-			netdev->hw_enc_features &= ~NETIF_F_GSO_UDP_TUNNEL_CSUM;
-			netdev->hw_features &= ~NETIF_F_GSO_UDP_TUNNEL_CSUM;
+			netdev_hw_enc_feature_del(netdev,
+						  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+			netdev_hw_feature_del(netdev,
+					      NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 		}
 	}
 
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 0444dedf75e7..dc54367e4e92 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -251,7 +251,7 @@ netdev_features_t vmxnet3_fix_features(struct net_device *netdev,
 {
 	/* If Rx checksum is disabled, then LRO should also be disabled */
 	if (!(features & NETIF_F_RXCSUM))
-		features &= ~NETIF_F_LRO;
+		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	return features;
 }
@@ -372,11 +372,13 @@ static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_feat
 		    !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_VXLAN_CHECKSUM_OFFLOAD)) &&
 		    !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_GENEVE_TSO)) &&
 		    !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_VXLAN_TSO))) {
-			netdev->hw_enc_features &= ~NETIF_F_GSO_UDP_TUNNEL;
+			netdev_hw_enc_feature_del(netdev,
+						  NETIF_F_GSO_UDP_TUNNEL_BIT);
 		}
 		if (!(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD)) &&
 		    !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD))) {
-			netdev->hw_enc_features &= ~NETIF_F_GSO_UDP_TUNNEL_CSUM;
+			netdev_hw_enc_feature_del(netdev,
+						  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 		}
 	}
 }
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 4dbfdd1a8097..4cf7801da3f5 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1133,7 +1133,8 @@ static int ath6kl_set_features(struct net_device *dev,
 							 vif->fw_vif_idx,
 							 ar->rx_meta_ver, 0, 0);
 		if (err) {
-			dev->features = features & ~NETIF_F_RXCSUM;
+			dev->features = features;
+			netdev_active_feature_del(dev, NETIF_F_RXCSUM_BIT);
 			return err;
 		}
 	} else if (!(features & NETIF_F_RXCSUM) &&
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index ad0d49866f38..b9726d8af8f3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -608,7 +608,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
 	    && (toe_ol & TOE_TX_CSUM_OL) != 0)
 		netdev_active_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
 	else
-		ndev->features &= ~NETIF_F_IP_CSUM;
+		netdev_active_feature_del(ndev, NETIF_F_IP_CSUM_BIT);
 
 	if (brcmf_cfg80211_up(ndev)) {
 		bphy_err(drvr, "failed to bring up cfg80211\n");
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index b2e50d1a6cc2..475de5418861 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -366,15 +366,15 @@ static netdev_features_t xenvif_fix_features(struct net_device *dev,
 	struct xenvif *vif = netdev_priv(dev);
 
 	if (!vif->can_sg)
-		features &= ~NETIF_F_SG;
+		netdev_feature_del(NETIF_F_SG_BIT, &features);
 	if (~(vif->gso_mask) & GSO_BIT(TCPV4))
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 	if (~(vif->gso_mask) & GSO_BIT(TCPV6))
-		features &= ~NETIF_F_TSO6;
+		netdev_feature_del(NETIF_F_TSO6_BIT, &features);
 	if (!vif->ip_csum)
-		features &= ~NETIF_F_IP_CSUM;
+		netdev_feature_del(NETIF_F_IP_CSUM_BIT, &features);
 	if (!vif->ipv6_csum)
-		features &= ~NETIF_F_IPV6_CSUM;
+		netdev_feature_del(NETIF_F_IPV6_CSUM_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 1b089e6ef929..aa88d5fd7d5f 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1476,20 +1476,20 @@ static netdev_features_t xennet_fix_features(struct net_device *dev,
 
 	if (features & NETIF_F_SG &&
 	    !xenbus_read_unsigned(np->xbdev->otherend, "feature-sg", 0))
-		features &= ~NETIF_F_SG;
+		netdev_feature_del(NETIF_F_SG_BIT, &features);
 
 	if (features & NETIF_F_IPV6_CSUM &&
 	    !xenbus_read_unsigned(np->xbdev->otherend,
 				  "feature-ipv6-csum-offload", 0))
-		features &= ~NETIF_F_IPV6_CSUM;
+		netdev_feature_del(NETIF_F_IPV6_CSUM_BIT, &features);
 
 	if (features & NETIF_F_TSO &&
 	    !xenbus_read_unsigned(np->xbdev->otherend, "feature-gso-tcpv4", 0))
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	if (features & NETIF_F_TSO6 &&
 	    !xenbus_read_unsigned(np->xbdev->otherend, "feature-gso-tcpv6", 0))
-		features &= ~NETIF_F_TSO6;
+		netdev_feature_del(NETIF_F_TSO6_BIT, &features);
 
 	return features;
 }
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 39e0bd7ba519..8118c2dae6c9 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6825,7 +6825,8 @@ void qeth_enable_hw_features(struct net_device *dev)
 	dev->features &= ~dev->hw_features;
 	/* toggle VLAN filter, so that VIDs are re-programmed: */
 	if (IS_LAYER2(card) && IS_VM_NIC(card)) {
-		dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_active_feature_del(dev,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 		netdev_wanted_feature_add(dev,
 					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	}
@@ -6917,16 +6918,16 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
 
 	QETH_CARD_TEXT(card, 2, "fixfeat");
 	if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
-		features &= ~NETIF_F_IP_CSUM;
+		netdev_feature_del(NETIF_F_IP_CSUM_BIT, &features);
 	if (!qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6))
-		features &= ~NETIF_F_IPV6_CSUM;
+		netdev_feature_del(NETIF_F_IPV6_CSUM_BIT, &features);
 	if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM) &&
 	    !qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6))
-		features &= ~NETIF_F_RXCSUM;
+		netdev_feature_del(NETIF_F_RXCSUM_BIT, &features);
 	if (!qeth_is_supported(card, IPA_OUTBOUND_TSO))
-		features &= ~NETIF_F_TSO;
+		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 	if (!qeth_is_supported6(card, IPA_OUTBOUND_TSO))
-		features &= ~NETIF_F_TSO6;
+		netdev_feature_del(NETIF_F_TSO6_BIT, &features);
 
 	QETH_CARD_HEX(card, 2, &features, sizeof(features));
 	return features;
@@ -6984,7 +6985,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 
 		/* linearize only if resulting skb allocations are order-0: */
 		if (SKB_DATA_ALIGN(hroom + doffset + hsize) <= SKB_MAX_HEAD(0))
-			features &= ~NETIF_F_SG;
+			netdev_feature_del(NETIF_F_SG_BIT, &features);
 	}
 
 	return vlan_features_check(skb, features);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index daa1b6f2b47e..f91066cb9e72 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1809,7 +1809,7 @@ static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb,
 						    netdev_features_t features)
 {
 	if (vlan_get_protocol(skb) != htons(ETH_P_IP))
-		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	return qeth_features_check(skb, dev, features);
 }
 
diff --git a/net/core/dev.c b/net/core/dev.c
index 6589b3c7c70c..7ba5ac96bbeb 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1586,7 +1586,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))
@@ -1607,7 +1607,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))
@@ -3401,7 +3401,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 +
@@ -3491,7 +3491,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;
 }
@@ -3542,7 +3542,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;
@@ -9622,30 +9623,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 */
@@ -9664,7 +9665,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);
 		}
 	}
 
@@ -9672,18 +9673,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) {
@@ -9693,13 +9694,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;
@@ -11170,7 +11171,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;
 	}
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 955d7640dde6..338ef07b8f42 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -61,6 +61,7 @@
 #include <linux/if_vlan.h>
 #include <linux/mpls.h>
 #include <linux/kcov.h>
+#include <linux/netdev_features_helper.h>
 
 #include <net/protocol.h>
 #include <net/dst.h>
@@ -4043,7 +4044,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
 		 * skbs; we do so by disabling SG.
 		 */
 		if (mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb))
-			features &= ~NETIF_F_SG;
+			netdev_feature_del(NETIF_F_SG_BIT, &features);
 	}
 
 	__skb_push(head_skb, doffset);
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 84fdb991bee5..1bd21a30f662 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/random.h>
 #include <linux/slab.h>
 #include <linux/xfrm.h>
@@ -490,8 +491,8 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
 
 	ip6_dst_store(newsk, dst, NULL, NULL);
 	newsk->sk_route_caps = dst->dev->features;
-	newsk->sk_route_caps &= ~NETIF_F_IP_CSUM;
-	newsk->sk_route_caps &= ~NETIF_F_TSO;
+	netdev_feature_del(NETIF_F_IP_CSUM_BIT, &newsk->sk_route_caps);
+	netdev_feature_del(NETIF_F_TSO_BIT, &newsk->sk_route_caps);
 	newdp6 = (struct dccp6_sock *)newsk;
 	newinet = inet_sk(newsk);
 	newinet->pinet6 = &newdp6->inet6;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 7ed3699bdc4d..d61daaa12f92 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1678,7 +1678,8 @@ int dsa_slave_manage_vlan_filtering(struct net_device *slave,
 		err = vlan_for_each(slave, dsa_slave_restore_vlan, slave);
 		if (err) {
 			vlan_for_each(slave, dsa_slave_clear_vlan, slave);
-			slave->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+			netdev_active_feature_del(slave,
+						  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 			return err;
 		}
 	} else {
@@ -1686,7 +1687,8 @@ int dsa_slave_manage_vlan_filtering(struct net_device *slave,
 		if (err)
 			return err;
 
-		slave->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+		netdev_active_feature_del(slave,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	}
 
 	return 0;
@@ -2294,8 +2296,8 @@ void dsa_slave_setup_tagger(struct net_device *slave)
 	netdev_hw_feature_add(slave, NETIF_F_HW_TC_BIT);
 	netdev_active_feature_add(slave, NETIF_F_LLTX_BIT);
 	if (slave->needed_tailroom) {
-		slave->features &= ~NETIF_F_SG;
-		slave->features &= ~NETIF_F_FRAGLIST;
+		netdev_active_feature_del(slave, NETIF_F_SG_BIT);
+		netdev_active_feature_del(slave, NETIF_F_FRAGLIST_BIT);
 	}
 	if (ds->needs_standalone_vlan_filtering)
 		netdev_active_feature_add(slave,
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index 8eda70f58682..fe454f71ec6e 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -205,7 +205,8 @@ int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
 	list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
 		if (!wpan_dev->netdev)
 			continue;
-		wpan_dev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
+		netdev_active_feature_del(wpan_dev->netdev,
+					  NETIF_F_NETNS_LOCAL_BIT);
 		err = dev_change_net_namespace(wpan_dev->netdev, net, "wpan%d");
 		if (err)
 			break;
@@ -222,7 +223,8 @@ int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
 						     list) {
 			if (!wpan_dev->netdev)
 				continue;
-			wpan_dev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
+			netdev_active_feature_del(wpan_dev->netdev,
+						  NETIF_F_NETNS_LOCAL_BIT);
 			err = dev_change_net_namespace(wpan_dev->netdev, net,
 						       "wpan%d");
 			WARN_ON(err);
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 2931b3385bc9..619240be4b5e 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -220,12 +220,12 @@ static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
 	if ((!(skb->dev->gso_partial_features & NETIF_F_HW_ESP) &&
 	     !(features & NETIF_F_HW_ESP)) || x->xso.dev != skb->dev) {
 		esp_features = features & ~NETIF_F_CSUM_MASK;
-		esp_features &= ~NETIF_F_SG;
-		esp_features &= ~NETIF_F_SCTP_CRC;
+		netdev_feature_del(NETIF_F_SG_BIT, &esp_features);
+		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	} else if (!(features & NETIF_F_HW_ESP_TX_CSUM) &&
 		 !(skb->dev->gso_partial_features & NETIF_F_HW_ESP_TX_CSUM)) {
 		esp_features = features & ~NETIF_F_CSUM_MASK;
-		esp_features  &= ~NETIF_F_SCTP_CRC;
+		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	}
 
 	xo->flags |= XFRM_GSO_SEGMENT;
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 07073fa35205..0b3f5a3ed86b 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -46,7 +46,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 
 	features &= skb->dev->hw_enc_features;
 	if (need_csum)
-		features &= ~NETIF_F_SCTP_CRC;
+		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &features);
 
 	need_ipsec = skb_dst(skb) && dst_xfrm(skb_dst(skb));
 	/* Try to offload checksum if possible */
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index b699b89e592b..2ac8360a2922 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -70,7 +70,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 
 	features &= skb->dev->hw_enc_features;
 	if (need_csum)
-		features &= ~NETIF_F_SCTP_CRC;
+		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &features);
 
 	/* The only checksum offload we care about from here on out is the
 	 * outer one so strip the existing checksum feature flags and
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 95b5c26abad5..8c09c2cec0f5 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -258,11 +258,11 @@ static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
 
 	if (!(features & NETIF_F_HW_ESP) || x->xso.dev != skb->dev) {
 		esp_features = features & ~NETIF_F_CSUM_MASK;
-		esp_features &= ~NETIF_F_SG;
-		esp_features &= ~NETIF_F_SCTP_CRC;
+		netdev_feature_del(NETIF_F_SG_BIT, &esp_features);
+		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	} else if (!(features & NETIF_F_HW_ESP_TX_CSUM)) {
 		esp_features = features & ~NETIF_F_CSUM_MASK;
-		esp_features  &= ~NETIF_F_SCTP_CRC;
+		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	}
 
 	xo->flags |= XFRM_GSO_SEGMENT;
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 4baf9c563c87..e33d496d26a0 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -124,7 +124,7 @@ static void do_setup(struct net_device *netdev)
 	netdev->hw_enc_features = netdev->features;
 	netdev_active_features_set(netdev, netdev_tx_vlan_features);
 	netdev->hw_features = netdev->features;
-	netdev->hw_features &= ~NETIF_F_LLTX;
+	netdev_hw_feature_del(netdev, NETIF_F_LLTX_BIT);
 
 	eth_hw_addr_random(netdev);
 }
diff --git a/net/sctp/offload.c b/net/sctp/offload.c
index ad77e0362188..a70619d0c207 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -73,7 +73,7 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
 
 	tmp = features;
 	netdev_feature_add(NETIF_F_HW_CSUM_BIT, &tmp);
-	tmp &= ~NETIF_F_SG;
+	netdev_feature_del(NETIF_F_SG_BIT, &tmp);
 	segs = skb_segment(skb, tmp);
 	if (IS_ERR(segs))
 		goto out;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 57504e859573..7d43401ecb2f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -165,7 +165,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
 		if (!wdev->netdev)
 			continue;
-		wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
+		netdev_active_feature_del(wdev->netdev,
+					  NETIF_F_NETNS_LOCAL_BIT);
 		err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
 		if (err)
 			break;
@@ -182,7 +183,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 						     list) {
 			if (!wdev->netdev)
 				continue;
-			wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
+			netdev_active_feature_del(wdev->netdev,
+						  NETIF_F_NETNS_LOCAL_BIT);
 			err = dev_change_net_namespace(wdev->netdev, net,
 							"wlan%d");
 			WARN_ON(err);
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index c492b2952d6a..63ad940853e0 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -115,7 +115,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 
 	if (!(features & NETIF_F_HW_ESP)) {
 		esp_features = features;
-		esp_features &= ~NETIF_F_SG;
+		netdev_feature_del(NETIF_F_SG_BIT, &esp_features);
 		esp_features &= ~NETIF_F_CSUM_MASK;
 	}
 
@@ -142,8 +142,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 		struct sk_buff *segs;
 
 		/* Packet got rerouted, fixup features and segment it. */
-		esp_features &= ~NETIF_F_HW_ESP;
-		esp_features &= ~NETIF_F_GSO_ESP;
+		netdev_feature_del(NETIF_F_HW_ESP_BIT, &esp_features);
+		netdev_feature_del(NETIF_F_GSO_ESP_BIT, &esp_features);
 
 		segs = skb_gso_segment(skb, esp_features);
 		if (IS_ERR(segs)) {
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 28/36] treewide: use netdev_features_andnot and netdev_features_clear helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (26 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 27/36] treewide: use netdev_feature_del helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 29/36] treewide: use netdev_features_xor helpers Jian Shen
                   ` (7 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '& ~' expressions of features by netdev_features_andnot
helpers, and replace the '&= ~' expressions by netdev_features_clear
helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 arch/um/drivers/vector_kern.c                 |  2 +-
 drivers/net/bonding/bond_main.c               |  5 +++--
 drivers/net/bonding/bond_options.c            |  4 ++--
 drivers/net/ethernet/3com/typhoon.c           |  2 +-
 drivers/net/ethernet/atheros/alx/main.c       |  2 +-
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  2 +-
 drivers/net/ethernet/broadcom/bnx2.c          |  2 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  7 ++++---
 drivers/net/ethernet/broadcom/tg3.c           |  6 +++---
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  2 +-
 drivers/net/ethernet/cisco/enic/enic_main.c   |  2 +-
 drivers/net/ethernet/cortina/gemini.c         |  2 +-
 drivers/net/ethernet/emulex/benet/be_main.c   |  5 +++--
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   |  4 ++--
 drivers/net/ethernet/ibm/ibmveth.c            | 10 ++++++----
 drivers/net/ethernet/ibm/ibmvnic.c            |  2 +-
 drivers/net/ethernet/intel/e1000e/netdev.c    |  6 ++++--
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  2 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c   |  4 ++--
 drivers/net/ethernet/intel/iavf/iavf_main.c   |  7 ++++---
 drivers/net/ethernet/intel/ice/ice_main.c     | 13 +++++++-----
 drivers/net/ethernet/jme.c                    |  4 ++--
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  9 +++++----
 drivers/net/ethernet/marvell/sky2.c           |  2 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  5 +++--
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  3 ++-
 .../mellanox/mlx5/core/en_accel/ipsec_rxtx.h  |  4 ++--
 .../net/ethernet/mellanox/mlx5/core/en_main.c |  2 +-
 .../ethernet/netronome/nfp/nfp_net_common.c   |  6 +++---
 .../ethernet/oki-semi/pch_gbe/pch_gbe_param.c |  2 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   |  3 ++-
 drivers/net/ethernet/qlogic/qede/qede_fp.c    |  5 +++--
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  3 ++-
 drivers/net/ethernet/realtek/r8169_main.c     | 20 +++++++++----------
 drivers/net/ethernet/sfc/efx.c                |  4 ++--
 drivers/net/ethernet/sfc/efx_common.c         | 10 ++++++----
 drivers/net/ethernet/sfc/falcon/efx.c         |  7 ++++---
 drivers/net/ethernet/sfc/siena/efx.c          |  4 ++--
 drivers/net/ethernet/sfc/siena/efx_common.c   |  8 +++++---
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  4 ++--
 drivers/net/hyperv/rndis_filter.c             |  4 ++--
 drivers/net/ifb.c                             |  2 +-
 drivers/net/ipvlan/ipvlan_main.c              |  2 +-
 drivers/net/macsec.c                          |  2 +-
 drivers/net/macvlan.c                         |  2 +-
 drivers/net/team/team.c                       |  2 +-
 drivers/net/tun.c                             |  7 ++++---
 drivers/net/usb/lan78xx.c                     |  2 +-
 drivers/net/usb/r8152.c                       |  4 ++--
 drivers/net/veth.c                            |  7 ++++---
 drivers/net/vmxnet3/vmxnet3_drv.c             |  4 ++--
 drivers/net/vmxnet3/vmxnet3_ethtool.c         |  8 +++++---
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |  3 ++-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c   |  2 +-
 drivers/s390/net/qeth_core_main.c             |  6 +++---
 drivers/staging/qlge/qlge_main.c              |  2 +-
 include/linux/netdev_features_helper.h        |  2 +-
 include/net/sock.h                            |  3 ++-
 include/net/vxlan.h                           |  2 +-
 net/8021q/vlan.h                              |  2 +-
 net/8021q/vlan_dev.c                          |  3 ++-
 net/bridge/br_if.c                            |  2 +-
 net/core/dev.c                                | 18 ++++++++---------
 net/core/sock.c                               |  4 ++--
 net/ethtool/ioctl.c                           |  6 +++---
 net/hsr/hsr_device.c                          |  2 +-
 net/ipv4/esp4_offload.c                       |  4 ++--
 net/ipv4/ip_gre.c                             |  4 ++--
 net/ipv4/ip_output.c                          |  2 +-
 net/ipv4/udp_offload.c                        |  2 +-
 net/ipv6/esp6_offload.c                       |  4 ++--
 net/ipv6/ip6_output.c                         |  2 +-
 net/sched/sch_cake.c                          |  2 +-
 net/sched/sch_netem.c                         |  2 +-
 net/sched/sch_taprio.c                        |  2 +-
 net/sched/sch_tbf.c                           |  3 ++-
 net/xfrm/xfrm_device.c                        |  2 +-
 78 files changed, 180 insertions(+), 150 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 9bd68d8dd410..1364f936512d 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1339,7 +1339,7 @@ static void vector_net_tx_timeout(struct net_device *dev, unsigned int txqueue)
 static netdev_features_t vector_fix_features(struct net_device *dev,
 	netdev_features_t features)
 {
-	features &= ~netdev_ip_csum_features;
+	netdev_features_clear(&features, netdev_ip_csum_features);
 	return features;
 }
 
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 06fa1a5fcb36..7041ff2f8896 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1423,12 +1423,13 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 	if (bond_sk_check(bond))
 		netdev_features_set(&features, BOND_TLS_FEATURES);
 	else
-		features &= ~BOND_TLS_FEATURES;
+		netdev_features_clear(&features, BOND_TLS_FEATURES);
 #endif
 
 	mask = features;
 
-	features &= ~NETIF_F_ONE_FOR_ALL;
+	netdev_features_clear(&features, NETIF_F_ONE_FOR_ALL);
+
 	netdev_features_set(&features, NETIF_F_ALL_FOR_ALL);
 
 	bond_for_each_slave(bond, slave, iter) {
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index a90752e8aeef..decb4751abb8 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -838,7 +838,7 @@ static bool bond_set_xfrm_features(struct bonding *bond)
 	if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP)
 		netdev_wanted_features_set(bond->dev, BOND_XFRM_FEATURES);
 	else
-		bond->dev->wanted_features &= ~BOND_XFRM_FEATURES;
+		netdev_wanted_features_clear(bond->dev, BOND_XFRM_FEATURES);
 
 	return true;
 }
@@ -851,7 +851,7 @@ static bool bond_set_tls_features(struct bonding *bond)
 	if (bond_sk_check(bond))
 		netdev_wanted_features_set(bond->dev, BOND_TLS_FEATURES);
 	else
-		bond->dev->wanted_features &= ~BOND_TLS_FEATURES;
+		netdev_wanted_features_clear(bond->dev, BOND_TLS_FEATURES);
 
 	return true;
 }
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index cb7a4bb5cf74..82d1958df83b 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -2266,7 +2266,7 @@ static netdev_features_t typhoon_features_check(struct sk_buff *skb,
 						netdev_features_t features)
 {
 	if (skb_shinfo(skb)->nr_frags > 32 && skb_is_gso(skb))
-		features &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(&features, NETIF_F_GSO_MASK);
 
 	features = vlan_features_check(skb, features);
 	return vxlan_features_check(skb, features);
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 2de5fb1ab3de..45861e329c4e 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -1102,7 +1102,7 @@ static netdev_features_t alx_fix_features(struct net_device *netdev,
 					  netdev_features_t features)
 {
 	if (netdev->mtu > ALX_MAX_TSO_PKT_SIZE)
-		features &= ~netdev_general_tso_features;
+		netdev_features_clear(&features, netdev_general_tso_features);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 2113fa44026d..06f6de7dbb85 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -521,7 +521,7 @@ static netdev_features_t atl1c_fix_features(struct net_device *netdev,
 
 	if (hw->nic_type != athr_mt) {
 		if (netdev->mtu > MAX_TSO_FRAME_SIZE)
-			features &= ~netdev_general_tso_features;
+			netdev_features_clear(&features, netdev_general_tso_features);
 	}
 
 	return features;
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index d15ec211150c..2d38958bc5d0 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -7760,7 +7760,7 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
 		tso = dev->hw_features & NETIF_F_ALL_TSO;
 		netdev_vlan_features_set(dev, tso);
 	} else {
-		dev->vlan_features &= ~NETIF_F_ALL_TSO;
+		netdev_vlan_features_clear(dev, NETIF_F_ALL_TSO);
 	}
 
 	if ((!!(features & NETIF_F_HW_VLAN_CTAG_RX) !=
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 2c460493ccac..64f56c9e2303 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12874,7 +12874,7 @@ static netdev_features_t bnx2x_features_check(struct sk_buff *skb,
 	if (unlikely(skb_is_gso(skb) &&
 		     (skb_shinfo(skb)->gso_size > 9000) &&
 		     !skb_gso_validate_mac_len(skb, 9700)))
-		features &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(&features, NETIF_F_GSO_MASK);
 
 	features = vlan_features_check(skb, features);
 	return vxlan_features_check(skb, features);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index e426aa407ed8..134b775f02f1 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11201,14 +11201,15 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 	vlan_features = features & BNXT_HW_FEATURE_VLAN_ALL_RX;
 	if (vlan_features != BNXT_HW_FEATURE_VLAN_ALL_RX) {
 		if (dev->features & BNXT_HW_FEATURE_VLAN_ALL_RX)
-			features &= ~BNXT_HW_FEATURE_VLAN_ALL_RX;
+			netdev_features_clear(&features,
+					      BNXT_HW_FEATURE_VLAN_ALL_RX);
 		else if (vlan_features)
 			netdev_features_set(&features,
 					    BNXT_HW_FEATURE_VLAN_ALL_RX);
 	}
 #ifdef CONFIG_BNXT_SRIOV
 	if (BNXT_VF(bp) && bp->vf.vlan)
-		features &= ~BNXT_HW_FEATURE_VLAN_ALL_RX;
+		netdev_features_clear(&features, BNXT_HW_FEATURE_VLAN_ALL_RX);
 #endif
 	return features;
 }
@@ -11398,7 +11399,7 @@ static netdev_features_t bnxt_features_check(struct sk_buff *skb,
 			return features;
 		break;
 	}
-	return features & ~netdev_csum_gso_features_mask;
+	return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 }
 
 int bnxt_dbg_hwrm_rd_reg(struct bnxt *bp, u32 reg_off, u16 num_words,
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 841c6dc1546f..25171a645e73 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -7877,8 +7877,8 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
 		netif_tx_wake_queue(txq);
 	}
 
-	segs = skb_gso_segment(skb, tp->dev->features &
-				    ~netdev_general_tso_features);
+	segs = skb_gso_segment(skb,
+			       netdev_active_features_andnot(tp->dev, netdev_general_tso_features));
 	if (IS_ERR(segs) || !segs)
 		goto tg3_tso_bug_end;
 
@@ -8308,7 +8308,7 @@ static netdev_features_t tg3_fix_features(struct net_device *dev,
 	struct tg3 *tp = netdev_priv(dev);
 
 	if (dev->mtu > ETH_DATA_LEN && tg3_flag(tp, 5780_CLASS))
-		features &= ~NETIF_F_ALL_TSO;
+		netdev_features_clear(&features, NETIF_F_ALL_TSO);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 14a119232481..bddc7f6f0d23 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3852,7 +3852,7 @@ static netdev_features_t cxgb_features_check(struct sk_buff *skb,
 		return features;
 
 	/* Offload is not supported for this encapsulated packet */
-	return features & ~netdev_csum_gso_features_mask;
+	return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 }
 
 static netdev_features_t cxgb_fix_features(struct net_device *dev,
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 1b401125aaf0..b2bf06b3054b 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -295,7 +295,7 @@ static netdev_features_t enic_features_check(struct sk_buff *skb,
 	return features;
 
 out:
-	return features & ~netdev_csum_gso_features_mask;
+	return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 }
 
 int enic_is_dynamic(struct enic *enic)
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 6acb087baa6b..e5459716a46d 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -1990,7 +1990,7 @@ static netdev_features_t gmac_fix_features(struct net_device *netdev,
 					   netdev_features_t features)
 {
 	if (netdev->mtu + ETH_HLEN + VLAN_HLEN > MTU_SIZE_BIT_MASK)
-		features &= ~GMAC_OFFLOAD_FEATURES;
+		netdev_features_clear(&features, GMAC_OFFLOAD_FEATURES);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index ba54b89149a9..cd8baf47ceed 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5090,7 +5090,7 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
 		if (lancer_chip(adapter) &&
 		    (skb_shinfo(skb)->gso_size < 256 ||
 		     skb_shinfo(skb)->gso_segs == 1))
-			features &= ~NETIF_F_GSO_MASK;
+			netdev_features_clear(&features, NETIF_F_GSO_MASK);
 	}
 
 	/* The code below restricts offload features for some tunneled and
@@ -5126,7 +5126,8 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
 		sizeof(struct udphdr) + sizeof(struct vxlanhdr) ||
 	    !adapter->vxlan_port ||
 	    udp_hdr(skb)->dest != adapter->vxlan_port)
-		return features & ~netdev_csum_gso_features_mask;
+		return netdev_features_andnot(features,
+					      netdev_csum_gso_features_mask);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 105ed4d4aab5..7b47f4328ac9 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 &= ~netdev_csum_gso_features_mask;
+		netdev_features_clear(&features, netdev_csum_gso_features_mask);
 
 	return features;
 }
@@ -3321,7 +3321,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/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 8c1398f8b059..2319507d6731 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -744,7 +744,7 @@ static netdev_features_t ibmveth_fix_features(struct net_device *dev,
 	 */
 
 	if (!(features & NETIF_F_RXCSUM))
-		features &= ~NETIF_F_CSUM_MASK;
+		netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 
 	return features;
 }
@@ -874,7 +874,8 @@ static int ibmveth_set_tso(struct net_device *dev, u32 data)
 					   set_attr, clr_attr, &ret_attr);
 
 			if (data == 1)
-				dev->features &= ~netdev_general_tso_features;
+				netdev_active_features_clear(dev,
+							     netdev_general_tso_features);
 			rc1 = -EIO;
 
 		} else {
@@ -909,7 +910,7 @@ static int ibmveth_set_features(struct net_device *dev,
 	if (rx_csum != adapter->rx_csum) {
 		rc1 = ibmveth_set_csum_offload(dev, rx_csum);
 		if (rc1 && !adapter->rx_csum) {
-			dev->features = features & ~NETIF_F_CSUM_MASK;
+			dev->features = netdev_features_andnot(features, NETIF_F_CSUM_MASK);
 			netdev_active_feature_del(dev, NETIF_F_RXCSUM_BIT);
 		}
 	}
@@ -917,7 +918,8 @@ static int ibmveth_set_features(struct net_device *dev,
 	if (large_send != adapter->large_send) {
 		rc2 = ibmveth_set_tso(dev, large_send);
 		if (rc2 && !adapter->large_send)
-			dev->features = features & ~netdev_general_tso_features;
+			dev->features = netdev_features_andnot(features,
+							       netdev_general_tso_features);
 	}
 
 	return rc1 ? rc1 : rc2;
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index b5fa773272dd..538bfc2fe829 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -3335,7 +3335,7 @@ static netdev_features_t ibmvnic_features_check(struct sk_buff *skb,
 	if (skb_is_gso(skb)) {
 		if (skb_shinfo(skb)->gso_size < 224 ||
 		    skb_shinfo(skb)->gso_segs == 1)
-			features &= ~NETIF_F_GSO_MASK;
+			netdev_features_clear(&features, NETIF_F_GSO_MASK);
 	}
 
 	return features;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 1e51c751ff3b..158222876102 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -5302,7 +5302,8 @@ static void e1000_watchdog_task(struct work_struct *work)
 				case SPEED_10:
 				case SPEED_100:
 					e_info("10/100 speed: disabling TSO\n");
-					netdev->features &= ~netdev_general_tso_features;
+					netdev_active_features_clear(netdev,
+								     netdev_general_tso_features);
 					break;
 				case SPEED_1000:
 					netdev_active_features_set(netdev,
@@ -5313,7 +5314,8 @@ static void e1000_watchdog_task(struct work_struct *work)
 					break;
 				}
 				if (hw->mac.type == e1000_pch_spt) {
-					netdev->features &= ~netdev_general_tso_features;
+					netdev_active_features_clear(netdev,
+								     netdev_general_tso_features);
 				}
 			}
 
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 3b9df01b313e..1be0f9dade38 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1512,7 +1512,7 @@ static netdev_features_t fm10k_features_check(struct sk_buff *skb,
 	if (!skb->encapsulation || fm10k_tx_encap_offload(skb))
 		return features;
 
-	return features & ~netdev_csum_gso_features_mask;
+	return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 }
 
 static const struct net_device_ops fm10k_netdev_ops = {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 2377a01904ac..e9008e997a3e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13205,7 +13205,7 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
 	 * 64 bytes.  If it is then we need to drop support for GSO.
 	 */
 	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
-		features &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(&features, NETIF_F_GSO_MASK);
 
 	/* MACLEN can support at most 63 words */
 	len = skb_network_header(skb) - skb->data;
@@ -13237,7 +13237,7 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
 
 	return features;
 out_err:
-	return features & ~netdev_csum_gso_features_mask;
+	return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 38b4756e0992..a21cde0c2bbb 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4272,7 +4272,7 @@ static netdev_features_t iavf_features_check(struct sk_buff *skb,
 	 * 64 bytes.  If it is then we need to drop support for GSO.
 	 */
 	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
-		features &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(&features, NETIF_F_GSO_MASK);
 
 	/* MACLEN can support at most 63 words */
 	len = skb_network_header(skb) - skb->data;
@@ -4304,7 +4304,7 @@ static netdev_features_t iavf_features_check(struct sk_buff *skb,
 
 	return features;
 out_err:
-	return features & ~netdev_csum_gso_features_mask;
+	return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 }
 
 /**
@@ -4541,7 +4541,8 @@ iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
 	    adapter->vlan_v2_caps.offloads.ethertype_match ==
 	    VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION) {
 		netdev_warn(adapter->netdev, "cannot support CTAG and STAG VLAN stripping and/or insertion simultaneously since CTAG and STAG offloads are mutually exclusive, clearing STAG offload settings\n");
-		requested_features &= ~netdev_stag_vlan_offload_features;
+		netdev_features_clear(&requested_features,
+				      netdev_stag_vlan_offload_features);
 	}
 
 	return requested_features;
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index d71c226ae5af..9078659838a9 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5794,7 +5794,8 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 				netdev_features_set(&features,
 						    NETIF_VLAN_FILTERING_FEATURES);
 			} else if (!req_ctag && !req_stag) {
-				features &= ~NETIF_VLAN_FILTERING_FEATURES;
+				netdev_features_clear(&features,
+						      NETIF_VLAN_FILTERING_FEATURES);
 			} else if ((!cur_ctag && req_ctag && !cur_stag) ||
 				   (!cur_stag && req_stag && !cur_ctag)) {
 				netdev_features_set(&features,
@@ -5802,7 +5803,8 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 				netdev_warn(netdev,  "802.1Q and 802.1ad VLAN filtering must be either both on or both off. VLAN filtering has been enabled for both types.\n");
 			} else if ((cur_ctag && !req_ctag && cur_stag) ||
 				   (cur_stag && !req_stag && cur_ctag)) {
-				features &= ~NETIF_VLAN_FILTERING_FEATURES;
+				netdev_features_clear(&features,
+						      NETIF_VLAN_FILTERING_FEATURES);
 				netdev_warn(netdev,  "802.1Q and 802.1ad VLAN filtering must be either both on or both off. VLAN filtering has been disabled for both types.\n");
 			}
 		} else {
@@ -5818,7 +5820,8 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 	if ((features & netdev_ctag_vlan_offload_features) &&
 	    (features & netdev_stag_vlan_offload_features)) {
 		netdev_warn(netdev, "cannot support CTAG and STAG VLAN stripping and/or insertion simultaneously since CTAG and STAG offloads are mutually exclusive, clearing STAG offload settings\n");
-		features &= ~netdev_stag_vlan_offload_features;
+		netdev_features_clear(&features,
+				      netdev_stag_vlan_offload_features);
 	}
 
 	return features;
@@ -8914,7 +8917,7 @@ ice_features_check(struct sk_buff *skb,
 	 * 64 bytes. If it is then we need to drop support for GSO.
 	 */
 	if (gso && (skb_shinfo(skb)->gso_size < ICE_TXD_CTX_MIN_MSS))
-		features &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(&features, NETIF_F_GSO_MASK);
 
 	len = skb_network_offset(skb);
 	if (len > ICE_TXD_MACLEN_MAX || len & 0x1)
@@ -8945,7 +8948,7 @@ ice_features_check(struct sk_buff *skb,
 
 	return features;
 out_rm_features:
-	return features & ~netdev_csum_gso_features_mask;
+	return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 }
 
 static const struct net_device_ops ice_netdev_safe_mode_ops = {
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index fbc3467a36ce..85a008905dcc 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2665,8 +2665,8 @@ static netdev_features_t
 jme_fix_features(struct net_device *netdev, netdev_features_t features)
 {
 	if (netdev->mtu > 1900) {
-		features &= ~NETIF_F_ALL_TSO;
-		features &= ~NETIF_F_CSUM_MASK;
+		netdev_features_clear(&features, NETIF_F_ALL_TSO);
+		netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 	}
 	return features;
 }
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index c6f608388dff..8e7abdc8fd9d 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1275,8 +1275,8 @@ static void mvpp2_set_hw_csum(struct mvpp2_port *port,
 	 * has 7 bits, so the maximum L3 offset is 128.
 	 */
 	if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
-		port->dev->features &= ~csums;
-		port->dev->hw_features &= ~csums;
+		netdev_active_features_clear(port->dev, csums);
+		netdev_hw_features_clear(port->dev, csums);
 	} else {
 		netdev_active_features_set(port->dev, csums);
 		netdev_hw_features_set(port->dev, csums);
@@ -1341,8 +1341,9 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
 
 		/* Update L4 checksum when jumbo enable/disable on port */
 		if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
-			dev->features &= ~netdev_ip_csum_features;
-			dev->hw_features &= ~netdev_ip_csum_features;
+			netdev_active_features_clear(dev,
+						     netdev_ip_csum_features);
+			netdev_hw_features_clear(dev, netdev_ip_csum_features);
 		} else {
 			netdev_active_features_set(dev,
 						   netdev_ip_csum_features);
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 74b91fddd036..76254d483e9f 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4318,7 +4318,7 @@ static netdev_features_t sky2_fix_features(struct net_device *dev,
 		netdev_info(dev, "checksum offload not possible with jumbo frames\n");
 		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 		netdev_feature_del(NETIF_F_SG_BIT, &features);
-		features &= ~NETIF_F_CSUM_MASK;
+		netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 	}
 
 	/* Some hardware requires receive checksum for RSS to work. */
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 5557bae234b1..55216e1eed59 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3899,8 +3899,9 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 	if (eth->hwlro)
 		netdev_hw_feature_add(eth->netdev[id], NETIF_F_LRO_BIT);
 
-	eth->netdev[id]->vlan_features = *eth->soc->hw_features &
-		~netdev_ctag_vlan_offload_features;
+	eth->netdev[id]->vlan_features =
+		netdev_features_andnot(*eth->soc->hw_features,
+				       netdev_ctag_vlan_offload_features);
 	netdev_active_features_set(eth->netdev[id], *eth->soc->hw_features);
 	eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index ba8fdfc3b33a..d9fa50d5ef69 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2695,7 +2695,8 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
 		if (!priv->vxlan_port ||
 		    (ip_hdr(skb)->version != 4) ||
 		    (udp_hdr(skb)->dest != priv->vxlan_port))
-			features &= ~netdev_csum_gso_features_mask;
+			netdev_features_clear(&features,
+					      netdev_csum_gso_features_mask);
 	}
 
 	return features;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
index f0f6251a5d87..c323b27c4883 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
@@ -121,7 +121,7 @@ mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features)
 
 	/* Disable CSUM and GSO for software IPsec */
 out_disable:
-	return features & ~netdev_csum_gso_features_mask;
+	return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 }
 
 static inline bool
@@ -161,7 +161,7 @@ static inline bool mlx5e_ipsec_eseg_meta(struct mlx5_wqe_eth_seg *eseg)
 static inline bool mlx5_ipsec_is_rx_flow(struct mlx5_cqe64 *cqe) { return false; }
 static inline netdev_features_t
 mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features)
-{ return features & ~netdev_csum_gso_features_mask; }
+{ return netdev_features_andnot(features, netdev_csum_gso_features_mask); }
 
 static inline bool
 mlx5e_ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index bfbbc3bc152b..50ceeab2540d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4468,7 +4468,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
 
 out:
 	/* Disable CSUM and GSO if the udp dport is not offloaded by HW */
-	return features & ~netdev_csum_gso_features_mask;
+	return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 }
 
 netdev_features_t mlx5e_features_check(struct sk_buff *skb,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 9bda15a858d6..0c605cb98ded 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1799,7 +1799,7 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
 		 * metadata prepend - 8B
 		 */
 		if (unlikely(hdrlen > NFP_NET_LSO_MAX_HDR_SZ - 8))
-			features &= ~NETIF_F_GSO_MASK;
+			netdev_features_clear(&features, NETIF_F_GSO_MASK);
 	}
 
 	/* VXLAN/GRE check */
@@ -1811,7 +1811,7 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
 		l4_hdr = ipv6_hdr(skb)->nexthdr;
 		break;
 	default:
-		return features & ~netdev_csum_gso_features_mask;
+		return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 	}
 
 	if (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
@@ -1820,7 +1820,7 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
 	    (l4_hdr == IPPROTO_UDP &&
 	     (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
 	      sizeof(struct udphdr) + sizeof(struct vxlanhdr))))
-		return features & ~netdev_csum_gso_features_mask;
+		return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 
 	return features;
 }
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
index 4652884248be..c55623f3709b 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
@@ -489,7 +489,7 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
 		val = XsumTX;
 		pch_gbe_validate_option(&val, &opt, adapter);
 		if (!val)
-			dev->features &= ~NETIF_F_CSUM_MASK;
+			netdev_active_features_clear(dev, NETIF_F_CSUM_MASK);
 	}
 	{ /* Flow Control */
 		static const struct pch_gbe_option opt = {
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index c330ea873300..12301e08c52f 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1548,7 +1548,8 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
 
 	netdev_hw_features_set(netdev, netdev->hw_enc_features);
 	netdev_active_features_set(netdev, netdev->hw_features);
-	features = netdev->features & ~NETIF_F_VLAN_FEATURES;
+	features = netdev_active_features_andnot(netdev,
+						 NETIF_F_VLAN_FEATURES);
 	netdev_vlan_features_set(netdev, features);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT |
diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c
index a6f28549f4b4..53c83e1901d7 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -1790,12 +1790,13 @@ netdev_features_t qede_features_check(struct sk_buff *skb,
 			     skb_transport_header(skb)) > hdrlen ||
 			     (ntohs(udp_hdr(skb)->dest) != vxln_port &&
 			      ntohs(udp_hdr(skb)->dest) != gnv_port))
-				return features & ~netdev_csum_gso_features_mask;
+				return netdev_features_andnot(features,
+							      netdev_csum_gso_features_mask);
 		} else if (l4_proto == IPPROTO_IPIP) {
 			/* IPIP tunnels are unknown to the device or at least unsupported natively,
 			 * offloads for them can't be done trivially, so disable them for such skb.
 			 */
-			return features & ~netdev_csum_gso_features_mask;
+			return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 		}
 	}
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 503d18280559..5da115f30b69 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1057,7 +1057,8 @@ static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
 		netdev_features_clear_array(&qlcnic_csum_feature_set, &features);
 
 		if (QLCNIC_IS_TSO_CAPABLE(adapter))
-			features &= ~netdev_general_tso_features;
+			netdev_features_clear(&features,
+					      netdev_general_tso_features);
 		adapter->rx_csum = 0;
 	}
 
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index d9f92be3e246..80caddaf0c3d 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1443,12 +1443,12 @@ static netdev_features_t rtl8169_fix_features(struct net_device *dev,
 	struct rtl8169_private *tp = netdev_priv(dev);
 
 	if (dev->mtu > TD_MSS_MAX)
-		features &= ~NETIF_F_ALL_TSO;
+		netdev_features_clear(&features, NETIF_F_ALL_TSO);
 
 	if (dev->mtu > ETH_DATA_LEN &&
 	    tp->mac_version > RTL_GIGA_MAC_VER_06) {
-		features &= ~NETIF_F_CSUM_MASK;
-		features &= ~NETIF_F_ALL_TSO;
+		netdev_features_clear(&features, NETIF_F_CSUM_MASK);
+		netdev_features_clear(&features, NETIF_F_ALL_TSO);
 	}
 
 	return features;
@@ -4387,15 +4387,15 @@ static netdev_features_t rtl8168evl_fix_tso(struct sk_buff *skb,
 	/* IPv4 header has options field */
 	if (vlan_get_protocol(skb) == htons(ETH_P_IP) &&
 	    ip_hdrlen(skb) > sizeof(struct iphdr))
-		features &= ~NETIF_F_ALL_TSO;
+		netdev_features_clear(&features, NETIF_F_ALL_TSO);
 
 	/* IPv4 TCP header has options field */
 	else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 &&
 		 tcp_hdrlen(skb) > sizeof(struct tcphdr))
-		features &= ~NETIF_F_ALL_TSO;
+		netdev_features_clear(&features, NETIF_F_ALL_TSO);
 
 	else if (rtl_last_frag_len(skb) <= 6)
-		features &= ~NETIF_F_ALL_TSO;
+		netdev_features_clear(&features, NETIF_F_ALL_TSO);
 
 	return features;
 }
@@ -4412,18 +4412,18 @@ static netdev_features_t rtl8169_features_check(struct sk_buff *skb,
 
 		if (skb_transport_offset(skb) > GTTCPHO_MAX &&
 		    rtl_chip_supports_csum_v2(tp))
-			features &= ~NETIF_F_ALL_TSO;
+			netdev_features_clear(&features, NETIF_F_ALL_TSO);
 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		/* work around hw bug on some chip versions */
 		if (skb->len < ETH_ZLEN)
-			features &= ~NETIF_F_CSUM_MASK;
+			netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 
 		if (rtl_quirk_packet_padto(tp, skb))
-			features &= ~NETIF_F_CSUM_MASK;
+			netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 
 		if (skb_transport_offset(skb) > TCPHO_MAX &&
 		    rtl_chip_supports_csum_v2(tp))
-			features &= ~NETIF_F_CSUM_MASK;
+			netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 	}
 
 	return vlan_features_check(skb, features);
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 77aee7b35585..e1d273770336 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1021,12 +1021,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 def02fe850af..57fcebde8198 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)
 	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)
 	 * features which are fixed now
 	 */
 	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);
@@ -1367,10 +1367,12 @@ 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 1ef24fb2315d..5914f1ca989d 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -636,7 +636,7 @@ static void ef4_start_datapath(struct ef4_nic *efx)
 	 * features which are fixed now
 	 */
 	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);
@@ -2186,7 +2186,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)
@@ -2912,7 +2912,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/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index a18f5fc16b20..d9e7e729e507 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -1003,13 +1003,13 @@ 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);
 
 	netdev_hw_features_set(net_dev,
-			       net_dev->features & ~efx->fixed_features);
+			       netdev_active_features_andnot(net_dev, efx->fixed_features));
 
 	/* Disable receiving frames with bad FCS, by default. */
 	netdev_active_feature_del(net_dev, NETIF_F_RXALL_BIT);
diff --git a/drivers/net/ethernet/sfc/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 1c7a4ee1723f..0284eb688121 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -412,7 +412,7 @@ static void efx_start_datapath(struct efx_nic *efx)
 	 * features which are fixed now
 	 */
 	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);
@@ -1378,10 +1378,12 @@ netdev_features_t efx_siena_features_check(struct sk_buff *skb,
 			 */
 			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/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 8028c1e4d65b..e6a13888d4c8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5609,7 +5609,7 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
 		netdev_feature_del(NETIF_F_RXCSUM_BIT, &features);
 
 	if (!priv->plat->tx_coe)
-		features &= ~NETIF_F_CSUM_MASK;
+		netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 
 	/* Some GMAC devices have a bugged Jumbo frame support that
 	 * needs to have the Tx COE disabled for oversized frames
@@ -5617,7 +5617,7 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
 	 * the TX csum insertion in the TDES and not use SF.
 	 */
 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
-		features &= ~NETIF_F_CSUM_MASK;
+		netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 
 	/* Disable tso if asked by ethtool */
 	if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 0737794728a2..cd6d771cf191 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1366,7 +1366,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED;
 
 	/* Reset previously set hw_features flags */
-	net->hw_features &= ~NETVSC_SUPPORTED_HW_FEATURES;
+	netdev_hw_features_clear(net, NETVSC_SUPPORTED_HW_FEATURES);
 	net_device_ctx->tx_checksum_mask = 0;
 
 	/* Compute tx offload settings based on hw capabilities */
@@ -1432,7 +1432,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	 * net->features list as they're no longer supported.
 	 */
 	netdev_features_fill(&features);
-	features &= ~NETVSC_SUPPORTED_HW_FEATURES;
+	netdev_features_clear(&features, NETVSC_SUPPORTED_HW_FEATURES);
 	netdev_features_set(&features, net->hw_features);
 	net->features &= features;
 
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 912570321bfd..e87272042e19 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -329,7 +329,7 @@ static void ifb_setup(struct net_device *dev)
 	netdev_active_features_set(dev, ifb_features);
 	netdev_hw_features_set(dev, dev->features);
 	netdev_hw_enc_features_set(dev, dev->features);
-	ifb_features &= ~netdev_tx_vlan_features;
+	netdev_features_clear(&ifb_features, netdev_tx_vlan_features);
 	netdev_vlan_features_set(dev, ifb_features);
 
 	dev->flags |= IFF_NOARP;
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 3d96a990eded..e719b457e4e8 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -258,7 +258,7 @@ static netdev_features_t ipvlan_fix_features(struct net_device *dev,
 
 	netdev_features_set(&features, NETIF_F_ALL_FOR_ALL);
 	netdev_features_fill(&tmp);
-	tmp &= ~IPVLAN_FEATURES;
+	netdev_features_clear(&tmp, IPVLAN_FEATURES);
 	netdev_features_set(&tmp, ipvlan->sfeatures);
 	features &= tmp;
 	features = netdev_increment_features(ipvlan->phy_dev->features,
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index c8ee65e9c170..84312e717720 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3434,7 +3434,7 @@ static DECLARE_NETDEV_FEATURE_SET(sw_macsec_feature_set,
  *   HW_MACSEC - no reason to report it
  */
 #define REAL_DEV_FEATURES(dev) \
-	((dev)->features & ~macsec_no_inherit_features)
+	(netdev_active_features_andnot((dev), macsec_no_inherit_features))
 
 static int macsec_dev_init(struct net_device *dev)
 {
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 16d2763fc227..956e93aaa25a 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1103,7 +1103,7 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
 
 	netdev_features_set(&features, NETIF_F_ALL_FOR_ALL);
 	netdev_features_fill(&tmp);
-	tmp &= ~MACVLAN_FEATURES;
+	netdev_features_clear(&tmp, MACVLAN_FEATURES);
 	netdev_features_set(&tmp, vlan->set_features);
 	features &= tmp;
 	mask = features;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 2aaf3a8789f3..5b501e5069cb 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2017,7 +2017,7 @@ static netdev_features_t team_fix_features(struct net_device *dev,
 	netdev_features_t mask;
 
 	mask = features;
-	features &= ~NETIF_F_ONE_FOR_ALL;
+	netdev_features_clear(&features, NETIF_F_ONE_FOR_ALL);
 	netdev_features_set(&features, NETIF_F_ALL_FOR_ALL);
 
 	rcu_read_lock();
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 4f067242d634..7d4ac857555c 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1005,7 +1005,8 @@ static int tun_net_init(struct net_device *dev)
 	netdev_hw_features_set_array(dev, &tun_hw_feature_set);
 	dev->features = dev->hw_features;
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
-	dev->vlan_features = dev->features & ~netdev_tx_vlan_features;
+	dev->vlan_features = netdev_active_features_andnot(dev,
+							   netdev_tx_vlan_features);
 
 	tun->flags = (tun->flags & ~TUN_FEATURES) |
 		      (ifr->ifr_flags & TUN_FEATURES);
@@ -1178,7 +1179,7 @@ static netdev_features_t tun_net_fix_features(struct net_device *dev,
 	netdev_features_t tmp1, tmp2;
 
 	tmp1 = features & tun->set_features;
-	tmp2 = features & ~TUN_USER_FEATURES;
+	tmp2 = netdev_features_andnot(features, TUN_USER_FEATURES);
 	return netdev_features_or(tmp1, tmp2);
 }
 
@@ -2894,7 +2895,7 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
 		return -EINVAL;
 
 	tun->set_features = features;
-	tun->dev->wanted_features &= ~TUN_USER_FEATURES;
+	netdev_wanted_features_clear(tun->dev, TUN_USER_FEATURES);
 	netdev_wanted_features_set(tun->dev, features);
 	netdev_update_features(tun->dev);
 
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index d3dfd9f0fda9..e8db2e8cb755 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -4294,7 +4294,7 @@ static netdev_features_t lan78xx_features_check(struct sk_buff *skb,
 	struct lan78xx_net *dev = netdev_priv(netdev);
 
 	if (skb->len > LAN78XX_TSO_SIZE(dev))
-		features &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(&features, NETIF_F_GSO_MASK);
 
 	features = vlan_features_check(skb, features);
 	features = vxlan_features_check(skb, features);
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 52489af158e6..c457b4252c68 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2768,9 +2768,9 @@ rtl8152_features_check(struct sk_buff *skb, struct net_device *dev,
 
 	if ((mss || skb->ip_summed == CHECKSUM_PARTIAL) &&
 	    skb_transport_offset(skb) > max_offset)
-		features &= ~netdev_csum_gso_features_mask;
+		netdev_features_clear(&features, netdev_csum_gso_features_mask);
 	else if ((skb->len + sizeof(struct tx_desc)) > agg_buf_sz)
-		features &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(&features, NETIF_F_GSO_MASK);
 
 	return features;
 }
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index ef4bb4e63d70..c4805165eb65 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1464,7 +1464,7 @@ static netdev_features_t veth_fix_features(struct net_device *dev,
 		struct veth_priv *peer_priv = netdev_priv(peer);
 
 		if (peer_priv->_xdp_prog)
-			features &= ~NETIF_F_GSO_SOFTWARE;
+			netdev_features_clear(&features, NETIF_F_GSO_SOFTWARE);
 	}
 	if (priv->_xdp_prog)
 		netdev_feature_add(NETIF_F_GRO_BIT, &features);
@@ -1564,7 +1564,7 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 		}
 
 		if (!old_prog) {
-			peer->hw_features &= ~NETIF_F_GSO_SOFTWARE;
+			netdev_hw_features_clear(peer, NETIF_F_GSO_SOFTWARE);
 			peer->max_mtu = max_mtu;
 		}
 	}
@@ -1654,7 +1654,8 @@ static void veth_setup(struct net_device *dev)
 	netdev_features_set_array(&veth_feature_set, &veth_features);
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netdev_active_features_set(dev, veth_features);
-	dev->vlan_features = dev->features & ~netdev_vlan_offload_features;
+	dev->vlan_features = netdev_active_features_andnot(dev,
+							   netdev_vlan_offload_features);
 	dev->needs_free_netdev = true;
 	dev->priv_destructor = veth_dev_free;
 	dev->max_mtu = ETH_MAX_MTU;
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index b86820386f60..ec24cef62a3a 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3391,8 +3391,8 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 		}
 	}
 
-	netdev->vlan_features = netdev->hw_features &
-				~netdev_ctag_vlan_offload_features;
+	netdev->vlan_features = netdev_hw_features_andnot(netdev,
+							  netdev_ctag_vlan_offload_features);
 	netdev->features = netdev->hw_features;
 	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 }
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index dc54367e4e92..faeb7bcc0cf2 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -277,7 +277,8 @@ netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
 			l4_proto = ipv6_hdr(skb)->nexthdr;
 			break;
 		default:
-			return features & ~netdev_csum_gso_features_mask;
+			return netdev_features_andnot(features,
+						      netdev_csum_gso_features_mask);
 		}
 
 		switch (l4_proto) {
@@ -288,11 +289,12 @@ netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
 			if (port != GENEVE_UDP_PORT &&
 			    port != IANA_VXLAN_UDP_PORT &&
 			    port != VXLAN_UDP_PORT) {
-				return features & ~netdev_csum_gso_features_mask;
+				return netdev_features_andnot(features,
+							      netdev_csum_gso_features_mask);
 			}
 			break;
 		default:
-			return features & ~netdev_csum_gso_features_mask;
+			return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 		}
 	}
 	return features;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index ee66440cbb22..ad8e312e9ae0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -617,7 +617,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 
 	netdev_features_set(&hw->netdev_features, *mvm->cfg->features);
 	if (!iwl_mvm_is_csum_supported(mvm))
-		hw->netdev_features &= ~IWL_CSUM_NETIF_FLAGS_MASK;
+		netdev_features_clear(&hw->netdev_features,
+				      IWL_CSUM_NETIF_FLAGS_MASK);
 
 	if (mvm->cfg->vht_mu_mimo_supported)
 		wiphy_ext_feature_set(hw->wiphy,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index e110ac000e88..6ac083a84597 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -909,7 +909,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
 	if (skb->protocol == htons(ETH_P_IPV6) &&
 	    ((struct ipv6hdr *)skb_network_header(skb))->nexthdr !=
 	    IPPROTO_TCP) {
-		netdev_flags &= ~NETIF_F_CSUM_MASK;
+		netdev_features_clear(&netdev_flags, NETIF_F_CSUM_MASK);
 		return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb);
 	}
 
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 8118c2dae6c9..7889ca14213e 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6822,7 +6822,7 @@ void qeth_enable_hw_features(struct net_device *dev)
 	/* force-off any feature that might need an IPA sequence.
 	 * netdev_update_features() will restart them.
 	 */
-	dev->features &= ~dev->hw_features;
+	netdev_active_features_clear(dev, dev->hw_features);
 	/* toggle VLAN filter, so that VIDs are re-programmed: */
 	if (IS_LAYER2(card) && IS_VM_NIC(card)) {
 		netdev_active_feature_del(dev,
@@ -6955,7 +6955,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 						   &restricted);
 
 			if (restricted && qeth_next_hop_is_local_v4(card, skb))
-				features &= ~restricted;
+				netdev_features_clear(&features, restricted);
 			break;
 		case htons(ETH_P_IPV6):
 			if (!card->info.has_lp2lp_cso_v6)
@@ -6963,7 +6963,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 						   &restricted);
 
 			if (restricted && qeth_next_hop_is_local_v6(card, skb))
-				features &= ~restricted;
+				netdev_features_clear(&features, restricted);
 			break;
 		default:
 			break;
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index 2e67d69d6ac7..43c17f542583 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -4583,7 +4583,7 @@ static int qlge_probe(struct pci_dev *pdev,
 	ndev->features = ndev->hw_features;
 	ndev->vlan_features = ndev->hw_features;
 	/* vlan gets same features (except vlan filter) */
-	ndev->vlan_features &= ~netdev_ctag_vlan_features;
+	netdev_vlan_features_clear(ndev, netdev_ctag_vlan_features);
 
 	if (test_bit(QL_DMA64, &qdev->flags))
 		netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h
index e529e1cbde51..3732d8a81b9f 100644
--- a/include/linux/netdev_features_helper.h
+++ b/include/linux/netdev_features_helper.h
@@ -703,7 +703,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/include/net/sock.h b/include/net/sock.h
index a7273b289188..d7196cd8cc1e 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -44,6 +44,7 @@
 #include <linux/bitops.h>
 #include <linux/lockdep.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>	/* struct sk_buff */
 #include <linux/mm.h>
 #include <linux/security.h>
@@ -2168,7 +2169,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst);
 static inline void sk_gso_disable(struct sock *sk)
 {
 	sk->sk_gso_disabled = 1;
-	sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
+	netdev_features_clear(&sk->sk_route_caps, NETIF_F_GSO_MASK);
 }
 
 static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb,
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 60a8675976c2..8c3dc6c3bad9 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -373,7 +373,7 @@ static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
 	      sizeof(struct udphdr) + sizeof(struct vxlanhdr)) ||
 	     (skb->ip_summed != CHECKSUM_NONE &&
 	      !can_checksum_protocol(features, inner_eth_hdr(skb)->h_proto))))
-		return features & ~netdev_csum_gso_features_mask;
+		return netdev_features_andnot(features, netdev_csum_gso_features_mask);
 
 	return features;
 }
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 42eab811f8a1..e08bbe2ae55b 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -113,7 +113,7 @@ static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)
 	ret &= real_dev->hw_enc_features;
 
 	if ((ret & NETIF_F_GSO_ENCAP_ALL) && (ret & NETIF_F_CSUM_MASK)) {
-		ret &= ~NETIF_F_CSUM_MASK;
+		netdev_features_clear(&ret, NETIF_F_CSUM_MASK);
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &ret);
 		return ret;
 	}
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 24c812234a79..56f9b0233d51 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -585,7 +585,8 @@ static int vlan_dev_init(struct net_device *dev)
 	if (dev->features & NETIF_F_VLAN_FEATURES)
 		netdev_warn(real_dev, "VLAN features are set incorrectly.  Q-in-Q configurations may not work correctly.\n");
 
-	dev->vlan_features = real_dev->vlan_features & ~NETIF_F_ALL_FCOE;
+	dev->vlan_features = netdev_vlan_features_andnot(real_dev,
+							 NETIF_F_ALL_FCOE);
 	dev->hw_enc_features = vlan_tnl_features(real_dev);
 	dev->mpls_features = real_dev->mpls_features;
 
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index a84a7cfb9d6d..4b5cec64df79 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -542,7 +542,7 @@ netdev_features_t br_features_recompute(struct net_bridge *br,
 		return features;
 
 	mask = features;
-	features &= ~NETIF_F_ONE_FOR_ALL;
+	netdev_features_clear(&features, NETIF_F_ONE_FOR_ALL);
 
 	list_for_each_entry(p, &br->port_list, list) {
 		features = netdev_increment_features(features,
diff --git a/net/core/dev.c b/net/core/dev.c
index 7ba5ac96bbeb..ca5dc39cd412 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3488,7 +3488,7 @@ 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);
@@ -3518,11 +3518,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
@@ -3532,7 +3532,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.
@@ -9611,13 +9611,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) &&
@@ -9654,7 +9654,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)) {
@@ -11164,7 +11164,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;
 
@@ -11172,7 +11172,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/core/sock.c b/net/core/sock.c
index 456ce67fbb08..7dc8b734e807 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2322,10 +2322,10 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 	if (sk->sk_route_caps & NETIF_F_GSO)
 		netdev_features_set(&sk->sk_route_caps, NETIF_F_GSO_SOFTWARE);
 	if (unlikely(sk->sk_gso_disabled))
-		sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(&sk->sk_route_caps, NETIF_F_GSO_MASK);
 	if (sk_can_gso(sk)) {
 		if (dst->header_len && !xfrm_dst_offload_ok(dst)) {
-			sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
+			netdev_features_clear(&sk->sk_route_caps, NETIF_F_GSO_MASK);
 		} else {
 			netdev_feature_add(NETIF_F_SG_BIT, &sk->sk_route_caps);
 			netdev_feature_add(NETIF_F_HW_CSUM_BIT, &sk->sk_route_caps);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index f99fcbb224d4..0ecaef5605f9 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -296,7 +296,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);
 
@@ -358,11 +358,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);
 
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index 421ce8c28932..14982fb7bfbb 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -193,7 +193,7 @@ static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr,
 	 * that were in features originally, and also is in NETIF_F_ONE_FOR_ALL,
 	 * may become enabled.
 	 */
-	features &= ~NETIF_F_ONE_FOR_ALL;
+	netdev_features_clear(&features, NETIF_F_ONE_FOR_ALL);
 	hsr_for_each_port(hsr, port)
 		features = netdev_increment_features(features,
 						     port->dev->features,
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 619240be4b5e..adfc4c7e36bf 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -219,12 +219,12 @@ static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
 
 	if ((!(skb->dev->gso_partial_features & NETIF_F_HW_ESP) &&
 	     !(features & NETIF_F_HW_ESP)) || x->xso.dev != skb->dev) {
-		esp_features = features & ~NETIF_F_CSUM_MASK;
+		esp_features = netdev_features_andnot(features, NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SG_BIT, &esp_features);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	} else if (!(features & NETIF_F_HW_ESP_TX_CSUM) &&
 		 !(skb->dev->gso_partial_features & NETIF_F_HW_ESP_TX_CSUM)) {
-		esp_features = features & ~NETIF_F_CSUM_MASK;
+		esp_features = netdev_features_andnot(features, NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	}
 
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 04586ad67183..228beaf40f42 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -773,8 +773,8 @@ static void ipgre_link_update(struct net_device *dev, bool set_mtu)
 
 	if (flags & TUNNEL_SEQ ||
 	    (flags & TUNNEL_CSUM && tunnel->encap.type != TUNNEL_ENCAP_NONE)) {
-		dev->features &= ~NETIF_F_GSO_SOFTWARE;
-		dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
+		netdev_active_features_clear(dev, NETIF_F_GSO_SOFTWARE);
+		netdev_hw_features_clear(dev, NETIF_F_GSO_SOFTWARE);
 	} else {
 		netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 		netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 9ca2620de9ea..2b9a127e6a20 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -264,7 +264,7 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk,
 	 */
 	features = netif_skb_features(skb);
 	BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_GSO_CB_OFFSET);
-	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+	segs = skb_gso_segment(skb, netdev_features_andnot(features, NETIF_F_GSO_MASK));
 	if (IS_ERR_OR_NULL(segs)) {
 		kfree_skb(skb);
 		return -ENOMEM;
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 2ac8360a2922..c4cf8fb52448 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -77,7 +77,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 	 * instead set the flag based on our outer checksum offload value.
 	 */
 	if (remcsum) {
-		features &= ~NETIF_F_CSUM_MASK;
+		netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 		if (!need_csum || offload_csum)
 			netdev_feature_add(NETIF_F_HW_CSUM_BIT, &features);
 	}
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 8c09c2cec0f5..ee83f7f2947c 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -257,11 +257,11 @@ static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
 	skb->encap_hdr_csum = 1;
 
 	if (!(features & NETIF_F_HW_ESP) || x->xso.dev != skb->dev) {
-		esp_features = features & ~NETIF_F_CSUM_MASK;
+		esp_features = netdev_features_andnot(features, NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SG_BIT, &esp_features);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	} else if (!(features & NETIF_F_HW_ESP_TX_CSUM)) {
-		esp_features = features & ~NETIF_F_CSUM_MASK;
+		esp_features = netdev_features_andnot(features, NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	}
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index f8fca2a3af3a..80f74d32e2ff 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -149,7 +149,7 @@ ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk,
 	 * egress MTU.
 	 */
 	features = netif_skb_features(skb);
-	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+	segs = skb_gso_segment(skb, netdev_features_andnot(features, NETIF_F_GSO_MASK));
 	if (IS_ERR_OR_NULL(segs)) {
 		kfree_skb(skb);
 		return -ENOMEM;
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index a43a58a73d09..135e943a4613 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -1743,7 +1743,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		netdev_features_t features = netif_skb_features(skb);
 		unsigned int slen = 0, numsegs = 0;
 
-		segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+		segs = skb_gso_segment(skb, netdev_features_andnot(features, NETIF_F_GSO_MASK));
 		if (IS_ERR_OR_NULL(segs))
 			return qdisc_drop(skb, sch, to_free);
 
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 5449ed114e40..b1e4948256ef 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -415,7 +415,7 @@ static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch,
 	struct sk_buff *segs;
 	netdev_features_t features = netif_skb_features(skb);
 
-	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+	segs = skb_gso_segment(skb, netdev_features_andnot(features, NETIF_F_GSO_MASK));
 
 	if (IS_ERR_OR_NULL(segs)) {
 		qdisc_drop(skb, sch, to_free);
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 0b941dd63d26..afde3f7126a1 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -463,7 +463,7 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		struct sk_buff *segs, *nskb;
 		int ret;
 
-		segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+		segs = skb_gso_segment(skb, netdev_features_andnot(features, NETIF_F_GSO_MASK));
 		if (IS_ERR_OR_NULL(segs))
 			return qdisc_drop(skb, sch, to_free);
 
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 72102277449e..6e4fe9e7dec1 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/skbuff.h>
 #include <net/netlink.h>
 #include <net/sch_generic.h>
@@ -210,7 +211,7 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
 	unsigned int len = 0, prev_len = qdisc_pkt_len(skb);
 	int ret, nb;
 
-	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+	segs = skb_gso_segment(skb, netdev_features_andnot(features, NETIF_F_GSO_MASK));
 
 	if (IS_ERR_OR_NULL(segs))
 		return qdisc_drop(skb, sch, to_free);
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 63ad940853e0..b14259162313 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -116,7 +116,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 	if (!(features & NETIF_F_HW_ESP)) {
 		esp_features = features;
 		netdev_feature_del(NETIF_F_SG_BIT, &esp_features);
-		esp_features &= ~NETIF_F_CSUM_MASK;
+		netdev_features_clear(&esp_features, NETIF_F_CSUM_MASK);
 	}
 
 	sp = skb_sec_path(skb);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 29/36] treewide: use netdev_features_xor helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (27 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 28/36] treewide: use netdev_features_andnot and netdev_features_clear helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 30/36] treewide: use netdev_feature_test helpers Jian Shen
                   ` (6 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '^' expressions of features by netdev_features_xor
helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/aquantia/atlantic/aq_main.c      |  2 +-
 drivers/net/ethernet/asix/ax88796c_main.c             |  2 +-
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c       |  3 ++-
 drivers/net/ethernet/atheros/atl1e/atl1e_main.c       |  3 ++-
 drivers/net/ethernet/atheros/atlx/atl2.c              |  3 ++-
 drivers/net/ethernet/atheros/atlx/atlx.c              |  3 ++-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c       |  5 +++--
 drivers/net/ethernet/broadcom/tg3.c                   |  2 +-
 drivers/net/ethernet/brocade/bna/bnad.c               |  2 +-
 drivers/net/ethernet/cadence/macb_main.c              |  2 +-
 drivers/net/ethernet/calxeda/xgmac.c                  |  2 +-
 drivers/net/ethernet/cavium/liquidio/lio_vf_main.c    |  3 ++-
 drivers/net/ethernet/cavium/thunder/nicvf_main.c      |  2 +-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c             |  2 +-
 drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c       |  2 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c       |  2 +-
 drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  2 +-
 drivers/net/ethernet/davicom/dm9000.c                 |  2 +-
 drivers/net/ethernet/faraday/ftgmac100.c              |  3 ++-
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c      |  2 +-
 drivers/net/ethernet/freescale/enetc/enetc.c          |  2 +-
 drivers/net/ethernet/freescale/enetc/enetc_pf.c       |  2 +-
 drivers/net/ethernet/freescale/fec_main.c             |  4 ++--
 drivers/net/ethernet/freescale/gianfar_ethtool.c      |  3 ++-
 drivers/net/ethernet/hisilicon/hns3/hns3_enet.c       |  3 ++-
 drivers/net/ethernet/huawei/hinic/hinic_main.c        | 10 ++++++++--
 drivers/net/ethernet/ibm/ibmvnic.c                    |  2 +-
 drivers/net/ethernet/intel/e100.c                     |  2 +-
 drivers/net/ethernet/intel/e1000/e1000_main.c         |  2 +-
 drivers/net/ethernet/intel/e1000e/netdev.c            |  2 +-
 drivers/net/ethernet/intel/ice/ice_main.c             |  6 +++---
 drivers/net/ethernet/intel/igb/igb_main.c             |  3 ++-
 drivers/net/ethernet/intel/igc/igc_main.c             |  3 ++-
 drivers/net/ethernet/intel/ixgb/ixgb_main.c           |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c         |  3 ++-
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c       |  2 +-
 .../net/ethernet/marvell/octeontx2/nic/otx2_common.c  |  2 +-
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c  |  2 +-
 drivers/net/ethernet/marvell/sky2.c                   |  2 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c           |  2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c     |  2 +-
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c        |  3 ++-
 drivers/net/ethernet/mscc/ocelot_net.c                |  2 +-
 drivers/net/ethernet/neterion/s2io.c                  |  2 +-
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c   |  3 ++-
 drivers/net/ethernet/nvidia/forcedeth.c               |  2 +-
 drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  2 +-
 drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c  |  2 +-
 drivers/net/ethernet/qlogic/qede/qede_filter.c        |  2 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c        |  6 +++---
 drivers/net/ethernet/qualcomm/emac/emac.c             |  2 +-
 drivers/net/ethernet/realtek/8139cp.c                 |  2 +-
 drivers/net/ethernet/realtek/8139too.c                |  2 +-
 drivers/net/ethernet/renesas/ravb_main.c              |  2 +-
 drivers/net/ethernet/renesas/sh_eth.c                 |  2 +-
 drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c       |  2 +-
 drivers/net/ethernet/sfc/efx_common.c                 |  2 +-
 drivers/net/ethernet/sfc/falcon/efx.c                 |  2 +-
 drivers/net/ethernet/sfc/siena/efx_common.c           |  2 +-
 drivers/net/hyperv/netvsc_drv.c                       |  2 +-
 drivers/net/usb/aqc111.c                              |  2 +-
 drivers/net/usb/ax88179_178a.c                        |  2 +-
 drivers/net/usb/r8152.c                               |  2 +-
 drivers/net/veth.c                                    |  2 +-
 drivers/net/virtio_net.c                              |  4 ++--
 drivers/net/vmxnet3/vmxnet3_ethtool.c                 |  2 +-
 drivers/s390/net/qeth_core_main.c                     | 11 ++++++-----
 drivers/staging/qlge/qlge_main.c                      |  2 +-
 net/core/dev.c                                        |  2 +-
 69 files changed, 102 insertions(+), 81 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
index 53ca1fb4c989..e05b285442f1 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -237,7 +237,7 @@ static int aq_ndev_set_features(struct net_device *ndev,
 		}
 	}
 
-	if ((aq_nic->ndev->features ^ features) & NETIF_F_RXCSUM) {
+	if (netdev_active_features_xor(aq_nic->ndev, features) & NETIF_F_RXCSUM) {
 		err = aq_nic->aq_hw_ops->hw_set_offload(aq_nic->aq_hw,
 							aq_cfg);
 
diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c
index b6c193dbee99..73c1d4a5856d 100644
--- a/drivers/net/ethernet/asix/ax88796c_main.c
+++ b/drivers/net/ethernet/asix/ax88796c_main.c
@@ -924,7 +924,7 @@ static int
 ax88796c_set_features(struct net_device *ndev, netdev_features_t features)
 {
 	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
-	netdev_features_t changed = features ^ ndev->features;
+	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 
 	if (!(changed & ax88796c_features))
 		return 0;
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 06f6de7dbb85..416185f1533a 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -530,7 +530,8 @@ static netdev_features_t atl1c_fix_features(struct net_device *netdev,
 static int atl1c_set_features(struct net_device *netdev,
 	netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		atl1c_vlan_mode(netdev, features);
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 43a64706bda6..15c299cc6514 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -400,7 +400,8 @@ static netdev_features_t atl1e_fix_features(struct net_device *netdev,
 static int atl1e_set_features(struct net_device *netdev,
 	netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		atl1e_vlan_mode(netdev, features);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 81995490aa1d..929cf069b567 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -390,7 +390,8 @@ static netdev_features_t atl2_fix_features(struct net_device *netdev,
 static int atl2_set_features(struct net_device *netdev,
 	netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		atl2_vlan_mode(netdev, features);
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index f9b0eddbe2ec..19495e1c91c4 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -255,7 +255,8 @@ static netdev_features_t atlx_fix_features(struct net_device *netdev,
 static int atlx_set_features(struct net_device *netdev,
 	netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		atlx_vlan_mode(netdev, features);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 7534fff7e676..d4de430b71cf 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4905,7 +4905,8 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
 	struct bnx2x *bp = netdev_priv(dev);
 
 	if (pci_num_vf(bp->pdev)) {
-		netdev_features_t changed = dev->features ^ features;
+		netdev_features_t changed = netdev_active_features_xor(dev,
+								       features);
 
 		/* Revert the requested changes in features if they
 		 * would require internal reload of PF in bnx2x_set_features().
@@ -4940,7 +4941,7 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
 int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-	netdev_features_t changes = features ^ dev->features;
+	netdev_features_t changes = netdev_active_features_xor(dev, features);
 	bool bnx2x_reload = false;
 	int rc;
 
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 25171a645e73..eee309801b1f 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -8315,7 +8315,7 @@ static netdev_features_t tg3_fix_features(struct net_device *dev,
 
 static int tg3_set_features(struct net_device *dev, netdev_features_t features)
 {
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
 	if ((changed & NETIF_F_LOOPBACK) && netif_running(dev))
 		tg3_set_loopback(dev, features);
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index e0732e92657b..649e1a6946e2 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3347,7 +3347,7 @@ bnad_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
 static int bnad_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct bnad *bnad = netdev_priv(dev);
-	netdev_features_t changed = features ^ dev->features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
 	if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && netif_running(dev)) {
 		unsigned long flags;
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index fcac8394cb48..b662f91c9b5d 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -3743,7 +3743,7 @@ static int macb_set_features(struct net_device *netdev,
 			     netdev_features_t features)
 {
 	struct macb *bp = netdev_priv(netdev);
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
 	/* TX checksum offload */
 	if (changed & NETIF_F_HW_CSUM)
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index fc3d688c1228..181c875ffda4 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1492,7 +1492,7 @@ static int xgmac_set_features(struct net_device *dev, netdev_features_t features
 	u32 ctrl;
 	struct xgmac_priv *priv = netdev_priv(dev);
 	void __iomem *ioaddr = priv->base;
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
 	if (!(changed & NETIF_F_RXCSUM))
 		return 0;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 4d88cb7e1516..45bc4d71d353 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -1850,7 +1850,8 @@ static netdev_features_t liquidio_fix_features(struct net_device *netdev,
 static int liquidio_set_features(struct net_device *netdev,
 				 netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 	struct lio *lio = netdev_priv(netdev);
 
 	if (!(changed & NETIF_F_LRO))
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 373df6adcf6a..52d810f4b39c 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1789,7 +1789,7 @@ static int nicvf_set_features(struct net_device *netdev,
 			      netdev_features_t features)
 {
 	struct nicvf *nic = netdev_priv(netdev);
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		nicvf_config_vlan_stripping(nic, features);
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index c00f4120e453..d9e2bf1eccf3 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -880,7 +880,7 @@ static netdev_features_t t1_fix_features(struct net_device *dev,
 
 static int t1_set_features(struct net_device *dev, netdev_features_t features)
 {
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	struct adapter *adapter = dev->ml_priv;
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 4c363379d995..1284e3d9c9c5 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -2605,7 +2605,7 @@ static netdev_features_t cxgb_fix_features(struct net_device *dev,
 
 static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 {
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		cxgb_vlan_mode(dev, features);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index bddc7f6f0d23..f77984b79a30 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1273,7 +1273,7 @@ int cxgb4_set_rspq_intr_params(struct sge_rspq *q,
 
 static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 {
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	const struct port_info *pi = netdev_priv(dev);
 	int err;
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index a6056a80058a..f99cc9715317 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -1193,7 +1193,7 @@ static int cxgb4vf_set_features(struct net_device *dev,
 	netdev_features_t features)
 {
 	struct port_info *pi = netdev_priv(dev);
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		t4vf_set_rxmode(pi->adapter, pi->viid, -1, -1, -1, -1,
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 8d3e3b3413d3..22bc1f9da086 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -587,7 +587,7 @@ static int dm9000_set_features(struct net_device *dev,
 	netdev_features_t features)
 {
 	struct board_info *dm = to_dm9000_board(dev);
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	unsigned long flags;
 
 	if (!(changed & NETIF_F_RXCSUM))
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index ce160fa7fc46..50f5fdcbedb4 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1597,7 +1597,8 @@ static int ftgmac100_set_features(struct net_device *netdev,
 				  netdev_features_t features)
 {
 	struct ftgmac100 *priv = netdev_priv(netdev);
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 
 	if (!netif_running(netdev))
 		return 0;
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 40c24fa45506..9781948df963 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -2422,7 +2422,7 @@ static int dpaa2_eth_set_features(struct net_device *net_dev,
 				  netdev_features_t features)
 {
 	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-	netdev_features_t changed = features ^ net_dev->features;
+	netdev_features_t changed = netdev_active_features_xor(net_dev, features);
 	bool enable;
 	int err;
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 4470a4a3e4c3..40e7ab38ed01 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2644,7 +2644,7 @@ static void enetc_enable_txvlan(struct net_device *ndev, bool en)
 int enetc_set_features(struct net_device *ndev,
 		       netdev_features_t features)
 {
-	netdev_features_t changed = ndev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 	int err = 0;
 
 	if (changed & NETIF_F_RXHASH)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 897932f08672..7f21068667b7 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -708,7 +708,7 @@ static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs)
 static int enetc_pf_set_features(struct net_device *ndev,
 				 netdev_features_t features)
 {
-	netdev_features_t changed = ndev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index c656c9744305..57cf1d83d125 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3378,7 +3378,7 @@ static inline void fec_enet_set_netdev_features(struct net_device *netdev,
 	netdev_features_t features)
 {
 	struct fec_enet_private *fep = netdev_priv(netdev);
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
 	netdev->features = features;
 
@@ -3395,7 +3395,7 @@ static int fec_set_features(struct net_device *netdev,
 	netdev_features_t features)
 {
 	struct fec_enet_private *fep = netdev_priv(netdev);
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
 	if (netif_running(netdev) && changed & NETIF_F_RXCSUM) {
 		napi_disable(&fep->napi);
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 8c541070ffe0..47e644b65ac7 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/net_tstamp.h>
 #include <linux/skbuff.h>
@@ -507,7 +508,7 @@ static int gfar_spauseparam(struct net_device *dev,
 
 int gfar_set_features(struct net_device *dev, netdev_features_t features)
 {
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	struct gfar_private *priv = netdev_priv(dev);
 	int err = 0;
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 7b47f4328ac9..a1363608a3fc 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2405,7 +2405,8 @@ 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;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 	struct hns3_nic_priv *priv = netdev_priv(netdev);
 	struct hnae3_handle *h = priv->ae_handle;
 	bool enable;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 544c4e499d38..c6c7087971ee 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -1072,12 +1072,17 @@ static int set_features(struct hinic_dev *nic_dev,
 			netdev_features_t pre_features,
 			netdev_features_t features, bool force_change)
 {
-	netdev_features_t changed = force_change ? ~0 : pre_features ^ features;
 	netdev_features_t failed_features = netdev_empty_features;
 	u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
+	netdev_features_t changed;
 	int ret = 0;
 	int err = 0;
 
+	if (force_change)
+		netdev_features_fill(&changed);
+	else
+		changed = netdev_features_xor(pre_features, features);
+
 	if (changed & NETIF_F_TSO) {
 		ret = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ?
 					 HINIC_TSO_ENABLE : HINIC_TSO_DISABLE);
@@ -1119,7 +1124,8 @@ static int set_features(struct hinic_dev *nic_dev,
 	}
 
 	if (err) {
-		nic_dev->netdev->features = features ^ failed_features;
+		nic_dev->netdev->features = netdev_features_xor(features,
+								failed_features);
 		return -EIO;
 	}
 
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 538bfc2fe829..09bd2505b39a 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4901,7 +4901,7 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 		/* disable features no longer supported */
 		adapter->netdev->features &= adapter->netdev->hw_features;
 		/* turn on features now supported if previously enabled */
-		tmp = old_hw_features ^ adapter->netdev->hw_features;
+		tmp = netdev_hw_features_xor(adapter->netdev, old_hw_features);
 		tmp &= adapter->netdev->hw_features;
 		tmp &= adapter->netdev->wanted_features;
 		netdev_active_features_set(adapter->netdev, tmp);
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 960411b8d77c..8e1b8fe9a04f 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2804,7 +2804,7 @@ static int e100_set_features(struct net_device *netdev,
 			     netdev_features_t features)
 {
 	struct nic *nic = netdev_priv(netdev);
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
 	if (!(changed & NETIF_F_RXFCS && changed & NETIF_F_RXALL))
 		return 0;
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 3958edb44a1d..af3fe857ec4e 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -805,7 +805,7 @@ static int e1000_set_features(struct net_device *netdev,
 	netdev_features_t features)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		e1000_vlan_mode(netdev, features);
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 158222876102..22cfd3fcbf1a 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -7324,7 +7324,7 @@ static int e1000_set_features(struct net_device *netdev,
 			      netdev_features_t features)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	netdev_features_t changeable;
 
 	if (changed & netdev_general_tso_features)
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 9078659838a9..9b9c73817692 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5915,7 +5915,7 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 
 	current_vlan_features = netdev->features & NETIF_VLAN_OFFLOAD_FEATURES;
 	requested_vlan_features = features & NETIF_VLAN_OFFLOAD_FEATURES;
-	diff = current_vlan_features ^ requested_vlan_features;
+	diff = netdev_features_xor(current_vlan_features, requested_vlan_features);
 	if (diff) {
 		err = ice_set_vlan_offload_features(vsi, features);
 		if (err)
@@ -5925,7 +5925,7 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 	current_vlan_features = netdev->features &
 		NETIF_VLAN_FILTERING_FEATURES;
 	requested_vlan_features = features & NETIF_VLAN_FILTERING_FEATURES;
-	diff = current_vlan_features ^ requested_vlan_features;
+	diff = netdev_features_xor(current_vlan_features, requested_vlan_features);
 	if (diff) {
 		err = ice_set_vlan_filtering_features(vsi, features);
 		if (err)
@@ -5969,7 +5969,7 @@ static int ice_set_loopback(struct ice_vsi *vsi, bool ena)
 static int
 ice_set_features(struct net_device *netdev, netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	struct ice_netdev_priv *np = netdev_priv(netdev);
 	struct ice_vsi *vsi = np->vsi;
 	struct ice_pf *pf = vsi->back;
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index cb109bc49c31..a87a0701bce1 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2449,7 +2449,8 @@ static netdev_features_t igb_fix_features(struct net_device *netdev,
 static int igb_set_features(struct net_device *netdev,
 	netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 	struct igb_adapter *adapter = netdev_priv(netdev);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 0d7f99a58a00..17973b86f3a6 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4951,7 +4951,8 @@ static netdev_features_t igc_fix_features(struct net_device *netdev,
 static int igc_set_features(struct net_device *netdev,
 			    netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 	struct igc_adapter *adapter = netdev_priv(netdev);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 82a7373268c8..8186c8e6305e 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -311,7 +311,7 @@ static int
 ixgb_set_features(struct net_device *netdev, netdev_features_t features)
 {
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
 	if (!(changed & NETIF_F_RXCSUM) && !(changed & NETIF_F_HW_VLAN_CTAG_RX))
 		return 0;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 05ce8c4fdd99..1a193cf10dab 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9871,7 +9871,8 @@ static int ixgbe_set_features(struct net_device *netdev,
 			      netdev_features_t features)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 	bool need_reset = false;
 
 	/* Make sure RSC matches LRO, reset if change */
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 8e7abdc8fd9d..09964559d77f 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -5279,7 +5279,7 @@ static int mvpp2_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
 static int mvpp2_set_features(struct net_device *dev,
 			      netdev_features_t features)
 {
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	struct mvpp2_port *port = netdev_priv(dev);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index 2d08af351de8..2f21d044318f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -1725,7 +1725,7 @@ EXPORT_SYMBOL(otx2_get_max_mtu);
 
 int otx2_handle_ntuple_tc_features(struct net_device *netdev, netdev_features_t features)
 {
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	struct otx2_nic *pfvf = netdev_priv(netdev);
 	bool ntuple = !!(features & NETIF_F_NTUPLE);
 	bool tc = !!(features & NETIF_F_HW_TC);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 9b68a79fc6e5..4811f51d297b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1882,7 +1882,7 @@ static void otx2_rx_mode_wrk_handler(struct work_struct *work)
 static int otx2_set_features(struct net_device *netdev,
 			     netdev_features_t features)
 {
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	struct otx2_nic *pf = netdev_priv(netdev);
 
 	if ((changed & NETIF_F_LOOPBACK) && netif_running(netdev))
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 76254d483e9f..851b1fd964c6 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4335,7 +4335,7 @@ static netdev_features_t sky2_fix_features(struct net_device *dev,
 static int sky2_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
 	if ((changed & NETIF_F_RXCSUM) &&
 	    !(sky2->hw->flags & SKY2_HW_NEW_LE)) {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 55216e1eed59..fb9d32d67884 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2727,7 +2727,7 @@ static int mtk_set_features(struct net_device *dev, netdev_features_t features)
 {
 	int err = 0;
 
-	if (!((dev->features ^ features) & NETIF_F_LRO))
+	if (!((netdev_active_features_xor(dev, features)) & NETIF_F_LRO))
 		return 0;
 
 	if (!(features & NETIF_F_LRO))
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 50ceeab2540d..dda033464220 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3838,7 +3838,7 @@ static int mlx5e_handle_feature(struct net_device *netdev,
 				unsigned short feature_bit,
 				mlx5e_feature_handler feature_handler)
 {
-	netdev_features_t changes = *features ^ netdev->features;
+	netdev_features_t changes = netdev_active_features_xor(netdev, *features);
 	bool enable = netdev_feature_test(feature_bit, *features);
 	int err;
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 19fbde6bd1a8..a11bd9859204 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1220,7 +1220,8 @@ static int mlxsw_sp_handle_feature(struct net_device *dev,
 				   int feature_bit,
 				   mlxsw_sp_feature_handler feature_handler)
 {
-	netdev_features_t changes = wanted_features ^ dev->features;
+	netdev_features_t changes = netdev_active_features_xor(dev,
+							       wanted_features);
 	bool enable = netdev_feature_test(feature_bit, wanted_features);
 	int err;
 
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 353a25f001e7..6d6f3a010ea4 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -838,7 +838,7 @@ static void ocelot_vlan_mode(struct ocelot *ocelot, int port,
 static int ocelot_set_features(struct net_device *dev,
 			       netdev_features_t features)
 {
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	struct ocelot_port_private *priv = netdev_priv(dev);
 	struct ocelot *ocelot = priv->port.ocelot;
 	int port = priv->port.index;
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 9b74b1b87220..24bf2275821e 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -6571,7 +6571,7 @@ static void s2io_ethtool_get_strings(struct net_device *dev,
 static int s2io_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct s2io_nic *sp = netdev_priv(dev);
-	netdev_features_t changed = features ^ dev->features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
 	if (changed & NETIF_F_LRO && netif_running(dev)) {
 		int rc;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 0c605cb98ded..84b36d529428 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1663,7 +1663,8 @@ static void nfp_net_stat64(struct net_device *netdev,
 static int nfp_net_set_features(struct net_device *netdev,
 				netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev,
+							       features);
 	struct nfp_net *nn = netdev_priv(netdev);
 	u32 new_ctrl;
 	int err;
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 44e502650328..84087466e6f4 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4962,7 +4962,7 @@ static int nv_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	int retval;
 
 	if ((changed & NETIF_F_LOOPBACK) && netif_running(dev)) {
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 8213d2300ff4..371efa0ed0a2 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -2206,7 +2206,7 @@ static int pch_gbe_set_features(struct net_device *netdev,
 	netdev_features_t features)
 {
 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
 	if (!(changed & NETIF_F_RXCSUM))
 		return 0;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 20fa5204b15c..09185d28552c 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -539,7 +539,7 @@ static int netxen_set_features(struct net_device *dev,
 	netdev_features_t changed;
 	int hw_lro;
 
-	changed = dev->features ^ features;
+	changed = netdev_active_features_xor(dev, features);
 	if (!(changed & NETIF_F_LRO))
 		return 0;
 
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index 9ec8daa60d6d..7a824b79cbcd 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -925,7 +925,7 @@ netdev_features_t qede_fix_features(struct net_device *dev,
 int qede_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct qede_dev *edev = netdev_priv(dev);
-	netdev_features_t changes = features ^ dev->features;
+	netdev_features_t changes = netdev_active_features_xor(dev, features);
 	bool need_reload = false;
 
 	if (changes & NETIF_F_GRO_HW)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 5da115f30b69..8dcb1cfdb5ba 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1077,12 +1077,12 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 		if (adapter->flags & QLCNIC_APP_CHANGED_FLAGS) {
 			features = qlcnic_process_flags(adapter, features);
 		} else {
-			changed = features ^ netdev->features;
+			changed = netdev_active_features_xor(netdev, features);
 			netdev_features_zero(&changeable);
 			netdev_features_set_array(&qlcnic_changable_feature_set,
 						  &changeable);
 			changed &= changeable;
-			features ^= changed;
+			netdev_features_toggle(&features, changed);
 		}
 	}
 
@@ -1096,7 +1096,7 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	int hw_lro = (features & NETIF_F_LRO) ? QLCNIC_LRO_ENABLED : 0;
 
 	if (!(changed & NETIF_F_LRO))
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 15ffa63415e1..3c85eb122448 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -176,7 +176,7 @@ static irqreturn_t emac_isr(int _irq, void *data)
 static int emac_set_features(struct net_device *netdev,
 			     netdev_features_t features)
 {
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	struct emac_adapter *adpt = netdev_priv(netdev);
 
 	/* We only need to reprogram the hardware if the VLAN tag features
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 63f4ef15ebba..d34d3f0ef041 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1461,7 +1461,7 @@ static void cp_set_msglevel(struct net_device *dev, u32 value)
 
 static int cp_set_features(struct net_device *dev, netdev_features_t features)
 {
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	struct cp_private *cp = netdev_priv(dev);
 	unsigned long flags;
 
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 7af89f43c4ca..4206c6b31802 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -902,7 +902,7 @@ static int rtl8139_set_features(struct net_device *dev, netdev_features_t featur
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
 	unsigned long flags;
-	netdev_features_t changed = features ^ dev->features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	void __iomem *ioaddr = tp->mmio_addr;
 
 	if (!(changed & NETIF_F_RXALL))
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 333a6aba78a2..a994062c7462 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -2336,7 +2336,7 @@ static int ravb_set_features_gbeth(struct net_device *ndev,
 static int ravb_set_features_rcar(struct net_device *ndev,
 				  netdev_features_t features)
 {
-	netdev_features_t changed = ndev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 
 	if (changed & NETIF_F_RXCSUM)
 		ravb_set_rx_csum(ndev, features & NETIF_F_RXCSUM);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 79cdd0b8d2e7..a393796f721a 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2932,7 +2932,7 @@ static void sh_eth_set_rx_csum(struct net_device *ndev, bool enable)
 static int sh_eth_set_features(struct net_device *ndev,
 			       netdev_features_t features)
 {
-	netdev_features_t changed = ndev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 
 	if (changed & NETIF_F_RXCSUM && mdp->cd->rx_csum)
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 9c6b7136f7fa..6f41b11e5570 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -1779,7 +1779,7 @@ static int sxgbe_set_features(struct net_device *dev,
 			      netdev_features_t features)
 {
 	struct sxgbe_priv_data *priv = netdev_priv(dev);
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
 	if (changed & NETIF_F_RXCSUM) {
 		if (features & NETIF_F_RXCSUM) {
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index 57fcebde8198..a5c47141e965 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -227,7 +227,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 5914f1ca989d..c8f52ad7fb83 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2194,7 +2194,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/drivers/net/ethernet/sfc/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 0284eb688121..0916336e4901 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -225,7 +225,7 @@ int efx_siena_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.
 	 */
-	features = net_dev->features ^ data;
+	features = netdev_active_features_xor(net_dev, data);
 	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) || (features & NETIF_F_RXFCS)) {
 		/* efx_siena_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/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index e241f9a1fca7..0af1d6dc1838 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1920,7 +1920,7 @@ static netdev_features_t netvsc_fix_features(struct net_device *ndev,
 static int netvsc_set_features(struct net_device *ndev,
 			       netdev_features_t features)
 {
-	netdev_features_t change = features ^ ndev->features;
+	netdev_features_t change = netdev_active_features_xor(ndev, features);
 	struct net_device_context *ndevctx = netdev_priv(ndev);
 	struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
 	struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index d55be54264f8..4fb65f445586 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -593,7 +593,7 @@ static int aqc111_set_features(struct net_device *net,
 {
 	struct usbnet *dev = netdev_priv(net);
 	struct aqc111_data *aqc111_data = dev->driver_priv;
-	netdev_features_t changed = net->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(net, features);
 	u16 reg16 = 0;
 	u8 reg8 = 0;
 
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 3d5f0241f2bc..d04e8a14a8ba 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -898,7 +898,7 @@ ax88179_set_features(struct net_device *net, netdev_features_t features)
 {
 	u8 tmp;
 	struct usbnet *dev = netdev_priv(net);
-	netdev_features_t changed = net->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(net, features);
 
 	if (changed & NETIF_F_IP_CSUM) {
 		ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index c457b4252c68..1de9c5bd9595 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -3251,7 +3251,7 @@ static void rtl_rx_vlan_en(struct r8152 *tp, bool enable)
 static int rtl8152_set_features(struct net_device *dev,
 				netdev_features_t features)
 {
-	netdev_features_t changed = features ^ dev->features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	struct r8152 *tp = netdev_priv(dev);
 	int ret;
 
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index c4805165eb65..2e4039b578ad 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1475,7 +1475,7 @@ static netdev_features_t veth_fix_features(struct net_device *dev,
 static int veth_set_features(struct net_device *dev,
 			     netdev_features_t features)
 {
-	netdev_features_t changed = features ^ dev->features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	struct veth_priv *priv = netdev_priv(dev);
 	int err;
 
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index d3eb1f5570d3..952af46cf956 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3017,7 +3017,7 @@ static int virtnet_set_features(struct net_device *dev,
 	u64 offloads;
 	int err;
 
-	if ((dev->features ^ features) & NETIF_F_GRO_HW) {
+	if ((netdev_active_features_xor(dev, features)) & NETIF_F_GRO_HW) {
 		if (vi->xdp_enabled)
 			return -EBUSY;
 
@@ -3033,7 +3033,7 @@ static int virtnet_set_features(struct net_device *dev,
 		vi->guest_offloads = offloads;
 	}
 
-	if ((dev->features ^ features) & NETIF_F_RXHASH) {
+	if ((netdev_active_features_xor(dev, features)) & NETIF_F_RXHASH) {
 		if (features & NETIF_F_RXHASH)
 			vi->ctrl->rss.hash_types = vi->rss_hash_types_saved;
 		else
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index faeb7bcc0cf2..850758b6252f 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -415,7 +415,7 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	unsigned long flags;
-	netdev_features_t changed = features ^ netdev->features;
+	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	netdev_features_t tun_offload_mask;
 	u8 udp_tun_enabled;
 
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 7889ca14213e..98e444f4c8f6 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6861,7 +6861,7 @@ static void qeth_check_restricted_features(struct qeth_card *card,
 int qeth_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct qeth_card *card = dev->ml_priv;
-	netdev_features_t changed = dev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	int rc = 0;
 
 	QETH_CARD_TEXT(card, 2, "setfeat");
@@ -6899,14 +6899,15 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
 			netdev_feature_change(NETIF_F_TSO6_BIT, &changed);
 	}
 
-	qeth_check_restricted_features(card, dev->features ^ features,
-				       dev->features ^ changed);
+	qeth_check_restricted_features(card,
+				       netdev_active_features_xor(dev, features),
+				       netdev_active_features_xor(dev, changed));
 
 	/* everything changed successfully? */
-	if ((dev->features ^ features) == changed)
+	if ((netdev_active_features_xor(dev, features)) == changed)
 		return 0;
 	/* something went wrong. save changed features and return error */
-	dev->features ^= changed;
+	netdev_active_features_toggle(dev, changed);
 	return -EIO;
 }
 EXPORT_SYMBOL_GPL(qeth_set_features);
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index 43c17f542583..7515e4d50999 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -2270,7 +2270,7 @@ static int qlge_update_hw_vlan_features(struct net_device *ndev,
 static int qlge_set_features(struct net_device *ndev,
 			     netdev_features_t features)
 {
-	netdev_features_t changed = ndev->features ^ features;
+	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 	int err;
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
diff --git a/net/core/dev.c b/net/core/dev.c
index ca5dc39cd412..4ddb0bf86dcc 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9756,7 +9756,7 @@ 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 = netdev_active_features_xor(dev, features);
 
 		if (diff & NETIF_F_RX_UDP_TUNNEL_PORT) {
 			/* udp_tunnel_{get,drop}_rx_info both need
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 30/36] treewide: use netdev_feature_test helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (28 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 29/36] treewide: use netdev_features_xor helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 31/36] treewide: use netdev_features_intersects helpers Jian Shen
                   ` (5 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '&' expressions of single feature bit by
netdev_feature_test helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 arch/um/drivers/vector_kern.c                 |  2 +-
 drivers/infiniband/ulp/ipoib/ipoib_cm.c       |  2 +-
 drivers/infiniband/ulp/ipoib/ipoib_ib.c       |  2 +-
 drivers/net/bonding/bond_main.c               | 10 +-
 drivers/net/ethernet/3com/3c59x.c             |  6 +-
 drivers/net/ethernet/aeroflex/greth.c         |  3 +-
 drivers/net/ethernet/altera/altera_tse_main.c |  2 +-
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  4 +-
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c      | 14 +--
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      | 37 ++++----
 .../net/ethernet/apm/xgene/xgene_enet_main.c  |  6 +-
 .../ethernet/aquantia/atlantic/aq_filters.c   |  8 +-
 .../net/ethernet/aquantia/atlantic/aq_main.c  | 27 +++---
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |  6 +-
 .../net/ethernet/aquantia/atlantic/aq_ring.c  |  3 +-
 .../aquantia/atlantic/hw_atl/hw_atl_b0.c      |  2 +-
 drivers/net/ethernet/asix/ax88796c_main.c     |  6 +-
 drivers/net/ethernet/atheros/alx/main.c       |  2 +-
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  6 +-
 .../net/ethernet/atheros/atl1e/atl1e_main.c   | 16 ++--
 drivers/net/ethernet/atheros/atlx/atl2.c      |  6 +-
 drivers/net/ethernet/atheros/atlx/atlx.c      |  6 +-
 drivers/net/ethernet/broadcom/bcmsysport.c    |  6 +-
 drivers/net/ethernet/broadcom/bnx2.c          | 12 +--
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c   | 24 ++---
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  6 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 22 ++---
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c |  2 +-
 .../net/ethernet/broadcom/genet/bcmgenet.c    |  2 +-
 drivers/net/ethernet/broadcom/tg3.c           | 14 +--
 drivers/net/ethernet/brocade/bna/bnad.c       | 10 +-
 drivers/net/ethernet/cadence/macb_main.c      | 31 ++++---
 drivers/net/ethernet/calxeda/xgmac.c          |  6 +-
 .../net/ethernet/cavium/liquidio/lio_core.c   |  4 +-
 .../net/ethernet/cavium/liquidio/lio_main.c   | 64 +++++++------
 .../ethernet/cavium/liquidio/lio_vf_main.c    | 45 +++++----
 .../net/ethernet/cavium/thunder/nicvf_main.c  | 14 +--
 .../ethernet/cavium/thunder/nicvf_queues.c    |  2 +-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  8 +-
 drivers/net/ethernet/chelsio/cxgb/sge.c       |  8 +-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   | 17 ++--
 drivers/net/ethernet/chelsio/cxgb3/sge.c      |  6 +-
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   | 13 ++-
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.h |  2 +-
 drivers/net/ethernet/chelsio/cxgb4/sge.c      |  8 +-
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  7 +-
 drivers/net/ethernet/chelsio/cxgb4vf/sge.c    |  4 +-
 .../chelsio/inline_crypto/chtls/chtls_main.c  |  2 +-
 drivers/net/ethernet/cisco/enic/enic_main.c   | 10 +-
 drivers/net/ethernet/cortina/gemini.c         |  2 +-
 drivers/net/ethernet/davicom/dm9000.c         | 11 ++-
 drivers/net/ethernet/davicom/dm9051.c         |  2 +-
 drivers/net/ethernet/emulex/benet/be_main.c   |  6 +-
 drivers/net/ethernet/faraday/ftgmac100.c      | 10 +-
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  5 +-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 13 +--
 drivers/net/ethernet/freescale/enetc/enetc.c  | 24 ++---
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  9 +-
 drivers/net/ethernet/freescale/fec_main.c     |  8 +-
 drivers/net/ethernet/freescale/gianfar.c      | 18 ++--
 .../net/ethernet/freescale/gianfar_ethtool.c  |  2 +-
 .../net/ethernet/fungible/funeth/funeth_rx.c  |  4 +-
 drivers/net/ethernet/google/gve/gve_adminq.c  |  2 +-
 drivers/net/ethernet/google/gve/gve_main.c    |  3 +-
 drivers/net/ethernet/google/gve/gve_rx.c      |  4 +-
 drivers/net/ethernet/google/gve/gve_rx_dqo.c  |  4 +-
 drivers/net/ethernet/hisilicon/hns/hns_enet.c |  2 +-
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   | 30 +++---
 .../ethernet/hisilicon/hns3/hns3_ethtool.c    |  4 +-
 .../net/ethernet/huawei/hinic/hinic_main.c    | 19 ++--
 drivers/net/ethernet/huawei/hinic/hinic_rx.c  |  4 +-
 drivers/net/ethernet/ibm/ibmveth.c            |  4 +-
 drivers/net/ethernet/intel/e100.c             | 11 ++-
 drivers/net/ethernet/intel/e1000/e1000_main.c | 24 ++---
 drivers/net/ethernet/intel/e1000e/netdev.c    | 30 +++---
 drivers/net/ethernet/intel/fm10k/fm10k_main.c |  4 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c   | 20 ++--
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   |  6 +-
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 12 +--
 drivers/net/ethernet/intel/iavf/iavf_txrx.c   |  8 +-
 drivers/net/ethernet/intel/ice/ice_main.c     | 44 +++++----
 drivers/net/ethernet/intel/ice/ice_tc_lib.c   |  2 +-
 drivers/net/ethernet/intel/ice/ice_txrx_lib.c |  8 +-
 drivers/net/ethernet/intel/igb/igb_ethtool.c  |  2 +-
 drivers/net/ethernet/intel/igb/igb_main.c     | 27 +++---
 drivers/net/ethernet/intel/igbvf/netdev.c     |  4 +-
 drivers/net/ethernet/intel/igc/igc_ethtool.c  |  2 +-
 drivers/net/ethernet/intel/igc/igc_main.c     | 23 ++---
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  9 +-
 .../net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c   |  2 +-
 .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c  |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c  |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 47 +++++-----
 .../net/ethernet/intel/ixgbe/ixgbe_sriov.c    |  4 +-
 drivers/net/ethernet/intel/ixgbevf/ipsec.c    |  2 +-
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |  8 +-
 drivers/net/ethernet/jme.c                    |  6 +-
 drivers/net/ethernet/marvell/mv643xx_eth.c    |  2 +-
 drivers/net/ethernet/marvell/mvneta.c         |  2 +-
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   | 10 +-
 .../marvell/octeontx2/nic/otx2_common.c       | 22 +++--
 .../marvell/octeontx2/nic/otx2_ethtool.c      |  4 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  | 14 +--
 .../marvell/octeontx2/nic/otx2_txrx.c         |  6 +-
 drivers/net/ethernet/marvell/skge.c           |  2 +-
 drivers/net/ethernet/marvell/sky2.c           | 24 ++---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 21 +++--
 .../net/ethernet/mellanox/mlx4/en_ethtool.c   |  4 +-
 drivers/net/ethernet/mellanox/mlx4/en_main.c  |  6 +-
 .../net/ethernet/mellanox/mlx4/en_netdev.c    | 24 ++---
 .../net/ethernet/mellanox/mlx4/en_resources.c |  4 +-
 drivers/net/ethernet/mellanox/mlx4/en_rx.c    | 14 +--
 .../mellanox/mlx5/core/en_accel/ktls.c        |  4 +-
 .../net/ethernet/mellanox/mlx5/core/en_arfs.c |  4 +-
 .../ethernet/mellanox/mlx5/core/en_ethtool.c  |  2 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 24 ++---
 .../net/ethernet/mellanox/mlx5/core/en_rx.c   |  8 +-
 .../net/ethernet/mellanox/mlx5/core/en_tc.c   |  2 +-
 drivers/net/ethernet/micrel/ksz884x.c         |  2 +-
 .../ethernet/microchip/lan966x/lan966x_fdma.c |  2 +-
 .../ethernet/microchip/lan966x/lan966x_main.c |  2 +-
 .../ethernet/microchip/sparx5/sparx5_fdma.c   |  2 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c |  4 +-
 drivers/net/ethernet/mscc/ocelot.c            |  2 +-
 drivers/net/ethernet/mscc/ocelot_net.c        |  7 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  4 +-
 drivers/net/ethernet/natsemi/ns83820.c        |  2 +-
 drivers/net/ethernet/neterion/s2io.c          |  8 +-
 drivers/net/ethernet/netronome/nfp/nfd3/dp.c  |  4 +-
 drivers/net/ethernet/netronome/nfp/nfdk/dp.c  |  4 +-
 .../ethernet/netronome/nfp/nfp_net_common.c   | 32 +++----
 drivers/net/ethernet/netronome/nfp/nfp_port.c |  3 +-
 drivers/net/ethernet/nvidia/forcedeth.c       | 24 ++---
 .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  2 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 36 ++++----
 .../net/ethernet/pensando/ionic/ionic_txrx.c  |  6 +-
 .../ethernet/qlogic/netxen/netxen_nic_init.c  |  4 +-
 .../ethernet/qlogic/netxen/netxen_nic_main.c  | 13 +--
 .../net/ethernet/qlogic/qede/qede_filter.c    |  4 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c  |  6 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  6 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_io.c    |  2 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_main.c  |  2 +-
 drivers/net/ethernet/qualcomm/emac/emac-mac.c |  4 +-
 .../ethernet/qualcomm/rmnet/rmnet_map_data.c  |  4 +-
 drivers/net/ethernet/realtek/8139cp.c         |  6 +-
 drivers/net/ethernet/realtek/8139too.c        | 12 +--
 drivers/net/ethernet/realtek/r8169_main.c     | 12 +--
 drivers/net/ethernet/renesas/ravb_main.c      |  9 +-
 drivers/net/ethernet/renesas/sh_eth.c         |  9 +-
 .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |  4 +-
 drivers/net/ethernet/sfc/ef10.c               |  2 +-
 drivers/net/ethernet/sfc/ef100_rep.c          |  4 +-
 drivers/net/ethernet/sfc/ef100_rx.c           |  4 +-
 drivers/net/ethernet/sfc/ef100_tx.c           |  8 +-
 drivers/net/ethernet/sfc/efx.c                |  4 +-
 drivers/net/ethernet/sfc/efx_common.c         |  6 +-
 drivers/net/ethernet/sfc/falcon/efx.c         |  6 +-
 drivers/net/ethernet/sfc/falcon/rx.c          |  4 +-
 drivers/net/ethernet/sfc/mcdi_filters.c       |  6 +-
 drivers/net/ethernet/sfc/mcdi_port_common.c   |  2 +-
 drivers/net/ethernet/sfc/rx.c                 |  2 +-
 drivers/net/ethernet/sfc/rx_common.c          |  5 +-
 drivers/net/ethernet/sfc/siena/efx.c          |  4 +-
 drivers/net/ethernet/sfc/siena/efx_common.c   |  6 +-
 drivers/net/ethernet/sfc/siena/farch.c        |  2 +-
 .../net/ethernet/sfc/siena/mcdi_port_common.c |  2 +-
 drivers/net/ethernet/sfc/siena/rx.c           |  2 +-
 drivers/net/ethernet/sfc/siena/rx_common.c    |  4 +-
 drivers/net/ethernet/sgi/ioc3-eth.c           |  2 +-
 drivers/net/ethernet/socionext/netsec.c       |  2 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_core.c |  2 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 10 +-
 .../stmicro/stmmac/stmmac_selftests.c         |  4 +-
 drivers/net/ethernet/sun/niu.c                |  2 +-
 drivers/net/ethernet/sun/sungem.c             |  2 +-
 drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c | 14 +--
 .../net/ethernet/synopsys/dwc-xlgmac-net.c    | 30 +++---
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  2 +-
 drivers/net/ethernet/toshiba/ps3_gelic_net.c  |  2 +-
 drivers/net/ethernet/toshiba/spider_net.c     |  2 +-
 drivers/net/hyperv/netvsc_bpf.c               |  2 +-
 drivers/net/hyperv/netvsc_drv.c               | 12 ++-
 drivers/net/hyperv/rndis_filter.c             |  2 +-
 drivers/net/macsec.c                          |  3 +-
 drivers/net/macvlan.c                         |  2 +-
 drivers/net/net_failover.c                    |  2 +-
 drivers/net/netdevsim/netdev.c                |  3 +-
 drivers/net/tap.c                             |  3 +-
 drivers/net/team/team.c                       |  4 +-
 drivers/net/usb/aqc111.c                      | 22 ++---
 drivers/net/usb/ax88179_178a.c                |  8 +-
 drivers/net/usb/lan78xx.c                     | 12 +--
 drivers/net/usb/r8152.c                       | 18 ++--
 drivers/net/usb/smsc75xx.c                    |  4 +-
 drivers/net/usb/smsc95xx.c                    |  8 +-
 drivers/net/veth.c                            | 11 ++-
 drivers/net/virtio_net.c                      | 14 +--
 drivers/net/vmxnet3/vmxnet3_drv.c             | 18 ++--
 drivers/net/vmxnet3/vmxnet3_ethtool.c         | 18 ++--
 drivers/net/wireless/ath/ath6kl/main.c        |  4 +-
 drivers/net/wireless/ath/ath6kl/txrx.c        |  4 +-
 drivers/net/wireless/intel/iwlwifi/mvm/rx.c   |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c |  2 +-
 drivers/net/xen-netfront.c                    | 12 +--
 drivers/s390/net/qeth_core_main.c             | 27 +++---
 drivers/s390/net/qeth_l3_main.c               |  4 +-
 drivers/scsi/fcoe/fcoe.c                      | 12 +--
 drivers/staging/qlge/qlge_main.c              | 18 ++--
 include/linux/if_vlan.h                       |  8 +-
 include/linux/netdev_features_helper.h        |  5 +-
 include/linux/netdevice.h                     | 18 ++--
 include/net/pkt_cls.h                         |  2 +-
 include/net/sock.h                            |  2 +-
 include/net/udp_tunnel.h                      |  8 +-
 net/8021q/vlan.c                              |  6 +-
 net/8021q/vlan_core.c                         |  4 +-
 net/core/dev.c                                | 92 ++++++++++---------
 net/core/pktgen.c                             |  8 +-
 net/core/skbuff.c                             |  7 +-
 net/core/skmsg.c                              |  2 +-
 net/core/sock.c                               |  2 +-
 net/ethtool/ioctl.c                           | 10 +-
 net/hsr/hsr_forward.c                         |  8 +-
 net/hsr/hsr_framereg.c                        |  2 +-
 net/hsr/hsr_slave.c                           |  2 +-
 net/ipv4/esp4_offload.c                       | 12 +--
 net/ipv4/gre_offload.c                        |  2 +-
 net/ipv4/ip_output.c                          | 18 ++--
 net/ipv4/tcp.c                                |  6 +-
 net/ipv4/udp_offload.c                        | 10 +-
 net/ipv6/esp6_offload.c                       |  6 +-
 net/ipv6/ip6_output.c                         | 14 +--
 net/netfilter/ipvs/ip_vs_proto_sctp.c         |  2 +-
 net/sctp/offload.c                            |  2 +-
 net/sctp/output.c                             |  2 +-
 net/sunrpc/sunrpc.h                           |  2 +-
 net/tls/tls_device.c                          |  6 +-
 net/xfrm/xfrm_device.c                        | 14 +--
 net/xfrm/xfrm_output.c                        |  3 +-
 241 files changed, 1126 insertions(+), 1029 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 1364f936512d..591ee69ecb1b 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1351,7 +1351,7 @@ static int vector_set_features(struct net_device *dev,
 	 * no way to negotiate it on raw sockets, so we can change
 	 * only our side.
 	 */
-	if (features & NETIF_F_GRO)
+	if (netdev_feature_test(NETIF_F_GRO_BIT, features))
 		/* All new frame buffers will be GRO-sized */
 		vp->req_size = 65536;
 	else
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index fd9d7f2c4d64..f020a2886ddd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -1070,7 +1070,7 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_
 	};
 	struct ib_qp *tx_qp;
 
-	if (dev->features & NETIF_F_SG)
+	if (netdev_active_feature_test(dev, NETIF_F_SG_BIT))
 		attr.cap.max_send_sge = min_t(u32, priv->ca->attrs.max_send_sge,
 					      MAX_SKB_FRAGS + 1);
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index f7995519bbc8..f56f8e5bf64a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -260,7 +260,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
 		dev->stats.multicast++;
 
 	skb->dev = dev;
-	if ((dev->features & NETIF_F_RXCSUM) &&
+	if ((netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)) &&
 			likely(wc->wc_flags & IB_WC_IP_CSUM_OK))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 7041ff2f8896..628526c3323a 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1829,7 +1829,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
 
 	/* vlan challenged mutual exclusion */
 	/* no need to lock since we're protected by rtnl_lock */
-	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
+	if (netdev_active_feature_test(slave_dev, NETIF_F_VLAN_CHALLENGED_BIT)) {
 		slave_dbg(bond_dev, slave_dev, "is NETIF_F_VLAN_CHALLENGED\n");
 		if (vlan_uses_dev(bond_dev)) {
 			SLAVE_NL_ERR(bond_dev, slave_dev, extack,
@@ -1842,7 +1842,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
 		slave_dbg(bond_dev, slave_dev, "is !NETIF_F_VLAN_CHALLENGED\n");
 	}
 
-	if (slave_dev->features & NETIF_F_HW_ESP)
+	if (netdev_active_feature_test(slave_dev, NETIF_F_HW_ESP_BIT))
 		slave_dbg(bond_dev, slave_dev, "is esp-hw-offload capable\n");
 
 	/* Old ifenslave binaries are no longer supported.  These can
@@ -2135,7 +2135,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
 	}
 #endif
 
-	if (!(bond_dev->features & NETIF_F_LRO))
+	if (!netdev_active_feature_test(bond_dev, NETIF_F_LRO_BIT))
 		dev_disable_lro(slave_dev);
 
 	res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
@@ -2437,8 +2437,8 @@ static int __bond_release_one(struct net_device *bond_dev,
 	}
 
 	bond_compute_features(bond);
-	if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
-	    (old_features & NETIF_F_VLAN_CHALLENGED))
+	if (!netdev_active_feature_test(bond_dev, NETIF_F_VLAN_CHALLENGED_BIT) &&
+	    netdev_feature_test(NETIF_F_VLAN_CHALLENGED_BIT, old_features))
 		slave_info(bond_dev, slave_dev, "last VLAN challenged slave left bond - VLAN blocking is removed\n");
 
 	vlan_vids_del_by_dev(slave_dev, bond_dev);
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index d816cb6f22ab..a3e07818f6b1 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -1457,9 +1457,9 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
 
 	if (print_info) {
 		pr_info("%s: scatter/gather %sabled. h/w checksums %sabled\n",
-				print_name,
-				(dev->features & NETIF_F_SG) ? "en":"dis",
-				(dev->features & NETIF_F_IP_CSUM) ? "en":"dis");
+			print_name,
+			netdev_active_feature_test(dev, NETIF_F_SG_BIT) ? "en" : "dis",
+			netdev_active_feature_test(dev, NETIF_F_IP_CSUM_BIT) ? "en" : "dis");
 	}
 
 	dev->ethtool_ops = &vortex_ethtool_ops;
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index ee4165257dfe..95ddbd990ecf 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -914,7 +914,8 @@ static int greth_rx_gbit(struct net_device *dev, int limit)
 
 				skb_put(skb, pkt_len);
 
-				if (dev->features & NETIF_F_RXCSUM && hw_checksummed(status))
+				if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT) &&
+				    hw_checksummed(status))
 					skb->ip_summed = CHECKSUM_UNNECESSARY;
 				else
 					skb_checksum_none_assert(skb);
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 97762bca0338..ca74d3b6963f 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -359,7 +359,7 @@ static inline void tse_rx_vlan(struct net_device *dev, struct sk_buff *skb)
 {
 	struct ethhdr *eth_hdr;
 	u16 vid;
-	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	    !__vlan_get_tag(skb, &vid)) {
 		eth_hdr = (struct ethhdr *)skb->data;
 		memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index 833f6e67e925..8386aac68c93 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -1533,7 +1533,7 @@ static void ena_rx_checksum(struct ena_ring *rx_ring,
 				   struct sk_buff *skb)
 {
 	/* Rx csum disabled */
-	if (unlikely(!(rx_ring->netdev->features & NETIF_F_RXCSUM))) {
+	if (unlikely(!netdev_active_feature_test(rx_ring->netdev, NETIF_F_RXCSUM_BIT))) {
 		skb->ip_summed = CHECKSUM_NONE;
 		return;
 	}
@@ -1591,7 +1591,7 @@ static void ena_set_rx_hash(struct ena_ring *rx_ring,
 {
 	enum pkt_hash_types hash_type;
 
-	if (likely(rx_ring->netdev->features & NETIF_F_RXHASH)) {
+	if (likely(netdev_active_feature_test(rx_ring->netdev, NETIF_F_RXHASH_BIT))) {
 		if (likely((ena_rx_ctx->l4_proto == ENA_ETH_IO_L4_PROTO_TCP) ||
 			   (ena_rx_ctx->l4_proto == ENA_ETH_IO_L4_PROTO_UDP)))
 
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 3936543a74d8..aa0e2bc68b82 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -449,7 +449,7 @@ static void xgbe_config_rss(struct xgbe_prv_data *pdata)
 	if (!pdata->hw_feat.rss)
 		return;
 
-	if (pdata->netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(pdata->netdev, NETIF_F_RXHASH_BIT))
 		ret = xgbe_enable_rss(pdata);
 	else
 		ret = xgbe_disable_rss(pdata);
@@ -948,7 +948,7 @@ static int xgbe_set_promiscuous_mode(struct xgbe_prv_data *pdata,
 	if (enable) {
 		xgbe_disable_rx_vlan_filtering(pdata);
 	} else {
-		if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+		if (netdev_active_feature_test(pdata->netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 			xgbe_enable_rx_vlan_filtering(pdata);
 	}
 
@@ -1990,7 +1990,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
 	rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
 
 	/* Set checksum done indicator as appropriate */
-	if (netdev->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) {
 		XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
 			       CSUM_DONE, 1);
 		XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
@@ -2021,7 +2021,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
 	if (!err || !etlt) {
 		/* No error if err is 0 or etlt is 0 */
 		if ((etlt == 0x09) &&
-		    (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
+		    (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))) {
 			XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
 				       VLAN_CTAG, 1);
 			packet->vlan_ctag = XGMAC_GET_BITS_LE(rdesc->desc0,
@@ -2823,7 +2823,7 @@ static void xgbe_config_mac_speed(struct xgbe_prv_data *pdata)
 
 static void xgbe_config_checksum_offload(struct xgbe_prv_data *pdata)
 {
-	if (pdata->netdev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(pdata->netdev, NETIF_F_RXCSUM_BIT))
 		xgbe_enable_rx_csum(pdata);
 	else
 		xgbe_disable_rx_csum(pdata);
@@ -2838,12 +2838,12 @@ static void xgbe_config_vlan_support(struct xgbe_prv_data *pdata)
 	/* Set the current VLAN Hash Table register value */
 	xgbe_update_vlan_hash_table(pdata);
 
-	if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+	if (netdev_active_feature_test(pdata->netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		xgbe_enable_rx_vlan_filtering(pdata);
 	else
 		xgbe_disable_rx_vlan_filtering(pdata);
 
-	if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(pdata->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		xgbe_enable_rx_vlan_stripping(pdata);
 	else
 		xgbe_disable_rx_vlan_stripping(pdata);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 1ba0e24a0cb1..90e22972fd81 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2192,8 +2192,8 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 		return features;
 
 	/* VXLAN CSUM requires VXLAN base */
-	if ((features & NETIF_F_GSO_UDP_TUNNEL_CSUM) &&
-	    !(features & NETIF_F_GSO_UDP_TUNNEL)) {
+	if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features) &&
+	    !netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_BIT, features)) {
 		netdev_notice(netdev,
 			      "forcing tx udp tunnel support\n");
 		netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_BIT, &features);
@@ -2207,14 +2207,14 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 	}
 
 	if (features & netdev_ip_csum_features) {
-		if (!(features & NETIF_F_GSO_UDP_TUNNEL_CSUM)) {
+		if (!netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features)) {
 			netdev_notice(netdev,
 				      "forcing tx udp tunnel checksumming on\n");
 			netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 					   &features);
 		}
 	} else {
-		if (features & NETIF_F_GSO_UDP_TUNNEL_CSUM) {
+		if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features)) {
 			netdev_notice(netdev,
 				      "forcing tx udp tunnel checksumming off\n");
 			netdev_feature_del(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
@@ -2230,34 +2230,35 @@ static int xgbe_set_features(struct net_device *netdev,
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
 	struct xgbe_hw_if *hw_if = &pdata->hw_if;
-	netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter;
+	bool rxhash, rxcsum, rxvlan, rxvlan_filter;
 	int ret = 0;
 
-	rxhash = pdata->netdev_features & NETIF_F_RXHASH;
-	rxcsum = pdata->netdev_features & NETIF_F_RXCSUM;
-	rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX;
-	rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER;
+	rxhash = netdev_feature_test(NETIF_F_RXHASH_BIT, pdata->netdev_features);
+	rxcsum = netdev_feature_test(NETIF_F_RXCSUM_BIT, pdata->netdev_features);
+	rxvlan = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, pdata->netdev_features);
+	rxvlan_filter = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+					    pdata->netdev_features);
 
-	if ((features & NETIF_F_RXHASH) && !rxhash)
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features) && !rxhash)
 		ret = hw_if->enable_rss(pdata);
-	else if (!(features & NETIF_F_RXHASH) && rxhash)
+	else if (!netdev_feature_test(NETIF_F_RXHASH_BIT, features) && rxhash)
 		ret = hw_if->disable_rss(pdata);
 	if (ret)
 		return ret;
 
-	if ((features & NETIF_F_RXCSUM) && !rxcsum)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && !rxcsum)
 		hw_if->enable_rx_csum(pdata);
-	else if (!(features & NETIF_F_RXCSUM) && rxcsum)
+	else if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && rxcsum)
 		hw_if->disable_rx_csum(pdata);
 
-	if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !rxvlan)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) && !rxvlan)
 		hw_if->enable_rx_vlan_stripping(pdata);
-	else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && rxvlan)
+	else if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) && rxvlan)
 		hw_if->disable_rx_vlan_stripping(pdata);
 
-	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) && !rxvlan_filter)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) && !rxvlan_filter)
 		hw_if->enable_rx_vlan_filtering(pdata);
-	else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter)
+	else if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) && rxvlan_filter)
 		hw_if->disable_rx_vlan_filtering(pdata);
 
 	pdata->netdev_features = features;
@@ -2599,7 +2600,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
 
 		/* Be sure we don't exceed the configured MTU */
 		max_len = netdev->mtu + ETH_HLEN;
-		if (!(netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+		if (!netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 		    (skb->protocol == htons(ETH_P_8021Q)))
 			max_len += VLAN_HLEN;
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 78c86e6be7a0..e3678e8a6d96 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -321,7 +321,7 @@ static int xgene_enet_work_msg(struct sk_buff *skb, u64 *hopinfo)
 	    unlikely(skb->protocol != htons(ETH_P_8021Q)))
 		goto out;
 
-	if (unlikely(!(skb->dev->features & NETIF_F_IP_CSUM)))
+	if (unlikely(!netdev_active_feature_test(skb->dev, NETIF_F_IP_CSUM_BIT)))
 		goto out;
 
 	iph = ip_hdr(skb);
@@ -332,7 +332,7 @@ static int xgene_enet_work_msg(struct sk_buff *skb, u64 *hopinfo)
 		l4hlen = tcp_hdrlen(skb) >> 2;
 		csum_enable = 1;
 		proto = TSO_IPPROTO_TCP;
-		if (ndev->features & NETIF_F_TSO) {
+		if (netdev_active_feature_test(ndev, NETIF_F_TSO_BIT)) {
 			hdr_len = ethhdr + ip_hdrlen(skb) + tcp_hdrlen(skb);
 			mss = skb_shinfo(skb)->gso_size;
 
@@ -591,7 +591,7 @@ static void xgene_enet_rx_csum(struct sk_buff *skb)
 	struct net_device *ndev = skb->dev;
 	struct iphdr *iph = ip_hdr(skb);
 
-	if (!(ndev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	if (skb->protocol != htons(ETH_P_IP))
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
index 30a573db02bb..96919291ec5d 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
@@ -164,7 +164,7 @@ aq_check_approve_fvlan(struct aq_nic_s *aq_nic,
 		return -EINVAL;
 	}
 
-	if ((aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
+	if (netdev_active_feature_test(aq_nic->ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT) &&
 	    (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci) & VLAN_VID_MASK,
 		       aq_nic->active_vlans))) {
 		netdev_err(aq_nic->ndev,
@@ -236,7 +236,7 @@ aq_rule_is_not_support(struct aq_nic_s *aq_nic,
 {
 	bool rule_is_not_support = false;
 
-	if (!(aq_nic->ndev->features & NETIF_F_NTUPLE)) {
+	if (!netdev_active_feature_test(aq_nic->ndev, NETIF_F_NTUPLE_BIT)) {
 		netdev_err(aq_nic->ndev,
 			   "ethtool: Please, to enable the RX flow control:\n"
 			   "ethtool -K %s ntuple on\n", aq_nic->ndev->name);
@@ -835,7 +835,7 @@ int aq_filters_vlans_update(struct aq_nic_s *aq_nic)
 	aq_fvlan_rebuild(aq_nic, aq_nic->active_vlans,
 			 aq_nic->aq_hw_rx_fltrs.fl2.aq_vlans);
 
-	if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
+	if (netdev_active_feature_test(aq_nic->ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT)) {
 		hweight = bitmap_weight(aq_nic->active_vlans, VLAN_N_VID);
 
 		err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw, false);
@@ -849,7 +849,7 @@ int aq_filters_vlans_update(struct aq_nic_s *aq_nic)
 	if (err)
 		return err;
 
-	if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
+	if (netdev_active_feature_test(aq_nic->ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT)) {
 		if (hweight <= AQ_VLAN_MAX_FILTERS && hweight > 0) {
 			err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw,
 				!(aq_nic->packet_filter & IFF_PROMISC));
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
index e05b285442f1..88c02af6a884 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -201,25 +201,27 @@ static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu)
 static int aq_ndev_set_features(struct net_device *ndev,
 				netdev_features_t features)
 {
-	bool is_vlan_tx_insert = !!(features & NETIF_F_HW_VLAN_CTAG_TX);
-	bool is_vlan_rx_strip = !!(features & NETIF_F_HW_VLAN_CTAG_RX);
+	bool is_vlan_tx_insert = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	bool is_vlan_rx_strip = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features);
 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 	bool need_ndev_restart = false;
 	struct aq_nic_cfg_s *aq_cfg;
+	netdev_features_t tmp;
 	bool is_lro = false;
 	int err = 0;
 
 	aq_cfg = aq_nic_get_cfg(aq_nic);
 
-	if (!(features & NETIF_F_NTUPLE)) {
-		if (aq_nic->ndev->features & NETIF_F_NTUPLE) {
+	if (!netdev_feature_test(NETIF_F_NTUPLE_BIT, features)) {
+		if (netdev_active_feature_test(aq_nic->ndev, NETIF_F_NTUPLE_BIT)) {
 			err = aq_clear_rxnfc_all_rules(aq_nic);
 			if (unlikely(err))
 				goto err_exit;
 		}
 	}
-	if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
-		if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
+	if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) {
+		if (netdev_active_feature_test(aq_nic->ndev,
+					       NETIF_F_HW_VLAN_CTAG_FILTER_BIT)) {
 			err = aq_filters_vlan_offload_off(aq_nic);
 			if (unlikely(err))
 				goto err_exit;
@@ -228,8 +230,8 @@ static int aq_ndev_set_features(struct net_device *ndev,
 
 	aq_cfg->features = features;
 
-	if (*aq_cfg->aq_hw_caps->hw_features & NETIF_F_LRO) {
-		is_lro = features & NETIF_F_LRO;
+	if (netdev_feature_test(NETIF_F_LRO_BIT, *aq_cfg->aq_hw_caps->hw_features)) {
+		is_lro = netdev_feature_test(NETIF_F_LRO_BIT, features);
 
 		if (aq_cfg->is_lro != is_lro) {
 			aq_cfg->is_lro = is_lro;
@@ -237,7 +239,8 @@ static int aq_ndev_set_features(struct net_device *ndev,
 		}
 	}
 
-	if (netdev_active_features_xor(aq_nic->ndev, features) & NETIF_F_RXCSUM) {
+	tmp = netdev_active_features_xor(aq_nic->ndev, features);
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, tmp)) {
 		err = aq_nic->aq_hw_ops->hw_set_offload(aq_nic->aq_hw,
 							aq_cfg);
 
@@ -269,12 +272,12 @@ static netdev_features_t aq_ndev_fix_features(struct net_device *ndev,
 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 	struct bpf_prog *prog;
 
-	if (!(features & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	prog = READ_ONCE(aq_nic->xdp_prog);
 	if (prog && !prog->aux->xdp_has_frags &&
-	    aq_nic->xdp_prog && features & NETIF_F_LRO) {
+	    aq_nic->xdp_prog && netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 		netdev_err(ndev, "LRO is not supported with single buffer XDP, disabling\n");
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 	}
@@ -502,7 +505,7 @@ static int aq_xdp_setup(struct net_device *ndev, struct bpf_prog *prog,
 			return -EOPNOTSUPP;
 		}
 
-		if (prog && ndev->features & NETIF_F_LRO) {
+		if (prog && netdev_active_feature_test(ndev, NETIF_F_LRO_BIT)) {
 			netdev_err(ndev,
 				   "LRO is not supported with single buffer XDP, disabling\n");
 			netdev_active_feature_del(ndev, NETIF_F_LRO_BIT);
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 775fff8f67d0..665c3053bec9 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -146,8 +146,10 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
 
 	cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk;
 	cfg->features = *cfg->aq_hw_caps->hw_features;
-	cfg->is_vlan_rx_strip = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_RX);
-	cfg->is_vlan_tx_insert = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_TX);
+	cfg->is_vlan_rx_strip = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+						    cfg->features);
+	cfg->is_vlan_tx_insert = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT,
+						     cfg->features);
 	cfg->is_vlan_force_promisc = true;
 
 	for (i = 0; i < sizeof(cfg->prio_tc_map); i++)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
index 25129e723b57..0b90377d65a9 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
@@ -369,7 +369,8 @@ static void aq_rx_checksum(struct aq_ring_s *self,
 			   struct aq_ring_buff_s *buff,
 			   struct sk_buff *skb)
 {
-	if (!(self->aq_nic->ndev->features & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT,
+				 self->aq_nic->ndev->features))
 		return;
 
 	if (unlikely(buff->is_cso_err)) {
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
index 0ba71726238a..bb0b93f3eb9f 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -260,7 +260,7 @@ static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self,
 int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
 			     struct aq_nic_cfg_s *aq_nic_cfg)
 {
-	u64 rxcsum = !!(aq_nic_cfg->features & NETIF_F_RXCSUM);
+	u64 rxcsum = netdev_feature_test(NETIF_F_RXCSUM_BIT, aq_nic_cfg->features);
 	unsigned int i;
 
 	/* TX checksums offloads*/
diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c
index 73c1d4a5856d..66e428e25b7d 100644
--- a/drivers/net/ethernet/asix/ax88796c_main.c
+++ b/drivers/net/ethernet/asix/ax88796c_main.c
@@ -414,7 +414,7 @@ ax88796c_skb_return(struct ax88796c_device *ax_local,
 	stats = this_cpu_ptr(ax_local->stats);
 
 	do {
-		if (!(ndev->features & NETIF_F_RXCSUM))
+		if (!netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT))
 			break;
 
 		/* checksum error bit is set */
@@ -780,7 +780,7 @@ static void ax88796c_set_csums(struct ax88796c_device *ax_local)
 
 	lockdep_assert_held(&ax_local->spi_lock);
 
-	if (ndev->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT)) {
 		AX_WRITE(&ax_local->ax_spi, COERCR0_DEFAULT, P4_COERCR0);
 		AX_WRITE(&ax_local->ax_spi, COERCR1_DEFAULT, P4_COERCR1);
 	} else {
@@ -788,7 +788,7 @@ static void ax88796c_set_csums(struct ax88796c_device *ax_local)
 		AX_WRITE(&ax_local->ax_spi, 0, P4_COERCR1);
 	}
 
-	if (ndev->features & NETIF_F_HW_CSUM) {
+	if (netdev_active_feature_test(ndev, NETIF_F_HW_CSUM_BIT)) {
 		AX_WRITE(&ax_local->ax_spi, COETCR0_DEFAULT, P4_COETCR0);
 		AX_WRITE(&ax_local->ax_spi, COETCR1_TXPPPE, P4_COETCR1);
 	} else {
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 45861e329c4e..3a87ff97c800 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -262,7 +262,7 @@ static int alx_clean_rx_irq(struct alx_rx_queue *rxq, int budget)
 		skb->protocol = eth_type_trans(skb, rxq->netdev);
 
 		skb_checksum_none_assert(skb);
-		if (alx->dev->features & NETIF_F_RXCSUM &&
+		if (netdev_active_feature_test(alx->dev, NETIF_F_RXCSUM_BIT) &&
 		    !(rrd->word3 & (cpu_to_le32(1 << RRD_ERR_L4_SHIFT) |
 				    cpu_to_le32(1 << RRD_ERR_IPV4_SHIFT)))) {
 			switch (ALX_GET_FIELD(le32_to_cpu(rrd->word2),
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 416185f1533a..40d53a105910 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -429,7 +429,7 @@ static void atl1c_set_multi(struct net_device *netdev)
 
 static void __atl1c_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data)
 {
-	if (features & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
 		/* enable VLAN tag insert/strip */
 		*mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
 	} else {
@@ -514,7 +514,7 @@ static netdev_features_t atl1c_fix_features(struct net_device *netdev,
 	 * Since there is no support for separate rx/tx vlan accel
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -533,7 +533,7 @@ static int atl1c_set_features(struct net_device *netdev,
 	netdev_features_t changed = netdev_active_features_xor(netdev,
 							       features);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		atl1c_vlan_mode(netdev, features);
 
 	return 0;
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 15c299cc6514..3617c6e5d1c4 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -299,7 +299,7 @@ static void atl1e_set_multi(struct net_device *netdev)
 static void __atl1e_rx_mode(netdev_features_t features, u32 *mac_ctrl_data)
 {
 
-	if (features & NETIF_F_RXALL) {
+	if (netdev_feature_test(NETIF_F_RXALL_BIT, features)) {
 		/* enable RX of ALL frames */
 		*mac_ctrl_data |= MAC_CTRL_DBG;
 	} else {
@@ -326,7 +326,7 @@ static void atl1e_rx_mode(struct net_device *netdev,
 
 static void __atl1e_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data)
 {
-	if (features & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
 		/* enable VLAN tag insert/strip */
 		*mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
 	} else {
@@ -389,7 +389,7 @@ static netdev_features_t atl1e_fix_features(struct net_device *netdev,
 	 * Since there is no support for separate rx/tx vlan accel
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -403,10 +403,10 @@ static int atl1e_set_features(struct net_device *netdev,
 	netdev_features_t changed = netdev_active_features_xor(netdev,
 							       features);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		atl1e_vlan_mode(netdev, features);
 
-	if (changed & NETIF_F_RXALL)
+	if (netdev_feature_test(NETIF_F_RXALL_BIT, changed))
 		atl1e_rx_mode(netdev, features);
 
 
@@ -1068,7 +1068,7 @@ static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
 		value |= MAC_CTRL_PROMIS_EN;
 	if (netdev->flags & IFF_ALLMULTI)
 		value |= MAC_CTRL_MC_ALL_EN;
-	if (netdev->features & NETIF_F_RXALL)
+	if (netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT))
 		value |= MAC_CTRL_DBG;
 	AT_WRITE_REG(hw, REG_MAC_CTRL, value);
 }
@@ -1430,7 +1430,7 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
 
 			/* error packet */
 			if ((prrs->pkt_flag & RRS_IS_ERR_FRAME) &&
-			    !(netdev->features & NETIF_F_RXALL)) {
+			    !netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)) {
 				if (prrs->err_flag & (RRS_ERR_BAD_CRC |
 					RRS_ERR_DRIBBLE | RRS_ERR_CODE |
 					RRS_ERR_TRUNC)) {
@@ -1444,7 +1444,7 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
 
 			packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
 					RRS_PKT_SIZE_MASK);
-			if (likely(!(netdev->features & NETIF_F_RXFCS)))
+			if (likely(!netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT)))
 				packet_size -= 4; /* CRC */
 
 			skb = netdev_alloc_skb_ip_align(netdev, packet_size);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 929cf069b567..4a1a44eb2b45 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -343,7 +343,7 @@ static inline void atl2_irq_disable(struct atl2_adapter *adapter)
 
 static void __atl2_vlan_mode(netdev_features_t features, u32 *ctrl)
 {
-	if (features & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
 		/* enable VLAN tag insert/strip */
 		*ctrl |= MAC_CTRL_RMV_VLAN;
 	} else {
@@ -379,7 +379,7 @@ static netdev_features_t atl2_fix_features(struct net_device *netdev,
 	 * Since there is no support for separate rx/tx vlan accel
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -393,7 +393,7 @@ static int atl2_set_features(struct net_device *netdev,
 	netdev_features_t changed = netdev_active_features_xor(netdev,
 							       features);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		atl2_vlan_mode(netdev, features);
 
 	return 0;
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index 19495e1c91c4..f73d10e701c3 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -207,7 +207,7 @@ static void atlx_link_chg_task(struct work_struct *work)
 
 static void __atlx_vlan_mode(netdev_features_t features, u32 *ctrl)
 {
-	if (features & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
 		/* enable VLAN tag insert/strip */
 		*ctrl |= MAC_CTRL_RMV_VLAN;
 	} else {
@@ -244,7 +244,7 @@ static netdev_features_t atlx_fix_features(struct net_device *netdev,
 	 * Since there is no support for separate rx/tx vlan accel
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -258,7 +258,7 @@ static int atlx_set_features(struct net_device *netdev,
 	netdev_features_t changed = netdev_active_features_xor(netdev,
 							       features);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		atlx_vlan_mode(netdev, features);
 
 	return 0;
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 471be11b949c..36234f731076 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -123,7 +123,7 @@ static void bcm_sysport_set_rx_csum(struct net_device *dev,
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	u32 reg;
 
-	priv->rx_chk_en = !!(wanted & NETIF_F_RXCSUM);
+	priv->rx_chk_en = netdev_feature_test(NETIF_F_RXCSUM_BIT, wanted);
 	reg = rxchk_readl(priv, RXCHK_CONTROL);
 	/* Clear L2 header checks, which would prevent BPDUs
 	 * from being received.
@@ -189,7 +189,7 @@ static void bcm_sysport_set_tx_csum(struct net_device *dev,
 	tdma_writel(priv, reg, TDMA_CONTROL);
 
 	/* Default TPID is ETH_P_8021AD, change to ETH_P_8021Q */
-	if (wanted & NETIF_F_HW_VLAN_CTAG_TX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, wanted))
 		tdma_writel(priv, ETH_P_8021Q, TDMA_TPID);
 }
 
@@ -1554,7 +1554,7 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
 	/* Adjust the packet size calculations if SYSTEMPORT is responsible
 	 * for HW insertion of VLAN tags
 	 */
-	if (priv->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)
+	if (netdev_active_feature_test(priv->netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT))
 		reg = VLAN_HLEN << RING_PKT_SIZE_ADJ_SHIFT;
 	tdma_writel(priv, reg, TDMA_DESC_RING_PCP_DEI_VID(index));
 
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 2d38958bc5d0..ac46a10b6252 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -3259,7 +3259,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
 		}
 
 		skb_checksum_none_assert(skb);
-		if ((bp->dev->features & NETIF_F_RXCSUM) &&
+		if (netdev_active_feature_test(bp->dev, NETIF_F_RXCSUM_BIT) &&
 			(status & (L2_FHDR_STATUS_TCP_SEGMENT |
 			L2_FHDR_STATUS_UDP_DATAGRAM))) {
 
@@ -3267,7 +3267,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
 					      L2_FHDR_ERRORS_UDP_XSUM)) == 0))
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
 		}
-		if ((bp->dev->features & NETIF_F_RXHASH) &&
+		if ((netdev_active_feature_test(bp->dev, NETIF_F_RXHASH_BIT)) &&
 		    ((status & L2_FHDR_STATUS_USE_RXHASH) ==
 		     L2_FHDR_STATUS_USE_RXHASH))
 			skb_set_hash(skb, rx_hdr->l2_fhdr_hash,
@@ -3587,7 +3587,7 @@ bnx2_set_rx_mode(struct net_device *dev)
 	rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
 				  BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
 	sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
-	if (!(dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (!netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	     (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
 		rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
 	if (dev->flags & IFF_PROMISC) {
@@ -7754,7 +7754,7 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
 	struct bnx2 *bp = netdev_priv(dev);
 
 	/* TSO with VLAN tag won't work with current firmware */
-	if (features & NETIF_F_HW_VLAN_CTAG_TX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features)) {
 		netdev_features_t tso;
 
 		tso = dev->hw_features & NETIF_F_ALL_TSO;
@@ -7763,8 +7763,8 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
 		netdev_vlan_features_clear(dev, NETIF_F_ALL_TSO);
 	}
 
-	if ((!!(features & NETIF_F_HW_VLAN_CTAG_RX) !=
-	    !!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) &&
+	if ((netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) !=
+	     !!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) &&
 	    netif_running(dev)) {
 		bnx2_netif_stop(bp, false);
 		dev->features = features;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index d4de430b71cf..d502ac4960fa 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -413,7 +413,7 @@ static u32 bnx2x_get_rxhash(const struct bnx2x *bp,
 			    enum pkt_hash_types *rxhash_type)
 {
 	/* Get Toeplitz hash from CQE */
-	if ((bp->dev->features & NETIF_F_RXHASH) &&
+	if (netdev_active_feature_test(bp->dev, NETIF_F_RXHASH_BIT) &&
 	    (cqe->status_flags & ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG)) {
 		enum eth_rss_hash_type htype;
 
@@ -1074,7 +1074,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 
 		skb_checksum_none_assert(skb);
 
-		if (bp->dev->features & NETIF_F_RXCSUM)
+		if (netdev_active_feature_test(bp->dev, NETIF_F_RXCSUM_BIT))
 			bnx2x_csum_validate(skb, cqe, fp,
 					    bnx2x_fp_qstats(bp, fp));
 
@@ -2496,9 +2496,9 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
 	/* set the tpa flag for each queue. The tpa flag determines the queue
 	 * minimal size so it must be set prior to queue memory allocation
 	 */
-	if (bp->dev->features & NETIF_F_LRO)
+	if (netdev_active_feature_test(bp->dev, NETIF_F_LRO_BIT))
 		fp->mode = TPA_MODE_LRO;
-	else if (bp->dev->features & NETIF_F_GRO_HW)
+	else if (netdev_active_feature_test(bp->dev, NETIF_F_GRO_HW_BIT))
 		fp->mode = TPA_MODE_GRO;
 	else
 		fp->mode = TPA_MODE_DISABLED;
@@ -4911,28 +4911,28 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
 		/* Revert the requested changes in features if they
 		 * would require internal reload of PF in bnx2x_set_features().
 		 */
-		if (!(features & NETIF_F_RXCSUM) && !bp->disable_tpa) {
+		if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && !bp->disable_tpa) {
 			netdev_feature_del(NETIF_F_RXCSUM_BIT, &features);
-			if (dev->features & NETIF_F_RXCSUM)
+			if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT))
 				netdev_feature_add(NETIF_F_RXCSUM_BIT,
 						   &features);
 		}
 
-		if (changed & NETIF_F_LOOPBACK) {
+		if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed)) {
 			netdev_feature_del(NETIF_F_LOOPBACK_BIT, &features);
-			if (dev->features & NETIF_F_LOOPBACK)
+			if (netdev_active_feature_test(dev, NETIF_F_LOOPBACK_BIT))
 				netdev_feature_add(NETIF_F_LOOPBACK_BIT,
 						   &features);
 		}
 	}
 
 	/* TPA requires Rx CSUM offloading */
-	if (!(features & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
-	if (!(features & NETIF_F_GRO) || !bnx2x_mtu_allows_gro(dev->mtu))
+	if (!netdev_feature_test(NETIF_F_GRO_BIT, features) || !bnx2x_mtu_allows_gro(dev->mtu))
 		netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
-	if (features & NETIF_F_GRO_HW)
+	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features))
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	return features;
@@ -4947,7 +4947,7 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
 
 	/* VFs or non SRIOV PFs should be able to change loopback feature */
 	if (!pci_num_vf(bp->pdev)) {
-		if (features & NETIF_F_LOOPBACK) {
+		if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features)) {
 			if (bp->link_params.loopback_mode != LOOPBACK_BMAC) {
 				bp->link_params.loopback_mode = LOOPBACK_BMAC;
 				bnx2x_reload = true;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 64f56c9e2303..640e37d2bc86 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -3405,9 +3405,9 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
 				ether_stat->mac_local + MAC_PAD, MAC_PAD,
 				ETH_ALEN);
 	ether_stat->mtu_size = bp->dev->mtu;
-	if (bp->dev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(bp->dev, NETIF_F_RXCSUM_BIT))
 		ether_stat->feature_flags |= FEATURE_ETH_CHKSUM_OFFLOAD_MASK;
-	if (bp->dev->features & NETIF_F_TSO)
+	if (netdev_active_feature_test(bp->dev, NETIF_F_TSO_BIT))
 		ether_stat->feature_flags |= FEATURE_ETH_LSO_MASK;
 	ether_stat->feature_flags |= bp->common.boot_mode;
 
@@ -13281,7 +13281,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
-	if (dev->features & NETIF_F_LRO)
+	if (netdev_active_feature_test(dev, NETIF_F_LRO_BIT))
 		netdev_active_feature_del(dev, NETIF_F_GRO_HW_BIT);
 
 	/* Add Loopback capability to the device */
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 134b775f02f1..dd744764cf4b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -2026,13 +2026,13 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
 
 	skb_checksum_none_assert(skb);
 	if (RX_CMP_L4_CS_OK(rxcmp1)) {
-		if (dev->features & NETIF_F_RXCSUM) {
+		if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)) {
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			skb->csum_level = RX_CMP_ENCAP(rxcmp1);
 		}
 	} else {
 		if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS) {
-			if (dev->features & NETIF_F_RXCSUM)
+			if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT))
 				bnapi->cp_ring.sw_stats.rx.rx_l4_csum_errors++;
 		}
 	}
@@ -3907,9 +3907,9 @@ void bnxt_set_tpa_flags(struct bnxt *bp)
 	bp->flags &= ~BNXT_FLAG_TPA;
 	if (bp->flags & BNXT_FLAG_NO_AGG_RINGS)
 		return;
-	if (bp->dev->features & NETIF_F_LRO)
+	if (netdev_active_feature_test(bp->dev, NETIF_F_LRO_BIT))
 		bp->flags |= BNXT_FLAG_LRO;
-	else if (bp->dev->features & NETIF_F_GRO_HW)
+	else if (netdev_active_feature_test(bp->dev, NETIF_F_GRO_HW_BIT))
 		bp->flags |= BNXT_FLAG_GRO;
 }
 
@@ -11176,7 +11176,7 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 	struct bnxt *bp = netdev_priv(dev);
 	netdev_features_t vlan_features;
 
-	if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp))
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, features) && !bnxt_rfs_capable(bp))
 		netdev_feature_del(NETIF_F_NTUPLE_BIT, &features);
 
 	if (bp->flags & BNXT_FLAG_NO_AGG_RINGS) {
@@ -11189,10 +11189,10 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 		netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 	}
 
-	if (!(features & NETIF_F_GRO))
+	if (!netdev_feature_test(NETIF_F_GRO_BIT, features))
 		netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 
-	if (features & NETIF_F_GRO_HW)
+	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features))
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	/* Both CTAG and STAG VLAN accelaration on the RX side have to be
@@ -11224,9 +11224,9 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
 	bool update_tpa = false;
 
 	flags &= ~BNXT_FLAG_ALL_CONFIG_FEATS;
-	if (features & NETIF_F_GRO_HW)
+	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features))
 		flags |= BNXT_FLAG_GRO;
-	else if (features & NETIF_F_LRO)
+	else if (netdev_feature_test(NETIF_F_LRO_BIT, features))
 		flags |= BNXT_FLAG_LRO;
 
 	if (bp->flags & BNXT_FLAG_NO_AGG_RINGS)
@@ -11235,7 +11235,7 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
 	if (features & BNXT_HW_FEATURE_VLAN_ALL_RX)
 		flags |= BNXT_FLAG_STRIP_VLAN;
 
-	if (features & NETIF_F_NTUPLE)
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, features))
 		flags |= BNXT_FLAG_RFS;
 
 	changes = flags ^ bp->flags;
@@ -13657,7 +13657,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_hw_feature_add(dev, NETIF_F_GRO_HW_BIT);
 	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
-	if (dev->features & NETIF_F_GRO_HW)
+	if (netdev_active_feature_test(dev, NETIF_F_GRO_HW_BIT))
 		netdev_active_feature_del(dev, NETIF_F_LRO_BIT);
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
index 9dd199dffb59..6328c38d7003 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -468,7 +468,7 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
 		return NULL;
 	skb_checksum_none_assert(skb);
 	if (RX_CMP_L4_CS_OK(rxcmp1)) {
-		if (bp->dev->features & NETIF_F_RXCSUM) {
+		if (netdev_active_feature_test(bp->dev, NETIF_F_RXCSUM_BIT)) {
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			skb->csum_level = RX_CMP_ENCAP(rxcmp1);
 		}
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 4157ab4acfb0..bb17909113e9 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -2293,7 +2293,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
 
 		status = (struct status_64 *)skb->data;
 		dma_length_status = status->length_status;
-		if (dev->features & NETIF_F_RXCSUM) {
+		if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)) {
 			rx_csum = (__force __be16)(status->rx_csum & 0xffff);
 			if (rx_csum) {
 				skb->csum = (__force __wsum)ntohs(rx_csum);
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index eee309801b1f..7fd03eba741d 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -6918,7 +6918,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 			tg3_hwclock_to_timestamp(tp, tstamp,
 						 skb_hwtstamps(skb));
 
-		if ((tp->dev->features & NETIF_F_RXCSUM) &&
+		if (netdev_active_feature_test(tp->dev, NETIF_F_RXCSUM_BIT) &&
 		    (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) &&
 		    (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK)
 		      >> RXD_TCPCSUM_SHIFT) == 0xffff))
@@ -8280,7 +8280,7 @@ static void tg3_set_loopback(struct net_device *dev, netdev_features_t features)
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	if (features & NETIF_F_LOOPBACK) {
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features)) {
 		if (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)
 			return;
 
@@ -8317,7 +8317,7 @@ static int tg3_set_features(struct net_device *dev, netdev_features_t features)
 {
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
-	if ((changed & NETIF_F_LOOPBACK) && netif_running(dev))
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed) && netif_running(dev))
 		tg3_set_loopback(dev, features);
 
 	return 0;
@@ -11645,7 +11645,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
 	 * Reset loopback feature if it was turned on while the device was down
 	 * make sure that it's installed properly now.
 	 */
-	if (dev->features & NETIF_F_LOOPBACK)
+	if (netdev_active_feature_test(dev, NETIF_F_LOOPBACK_BIT))
 		tg3_set_loopback(dev, dev->features);
 
 	return 0;
@@ -17741,10 +17741,10 @@ static int tg3_init_one(struct pci_dev *pdev,
 	if ((tg3_flag(tp, HW_TSO_1) ||
 	     tg3_flag(tp, HW_TSO_2) ||
 	     tg3_flag(tp, HW_TSO_3)) &&
-	    (features & NETIF_F_IP_CSUM))
+	    netdev_feature_test(NETIF_F_IP_CSUM_BIT, features))
 		netdev_feature_add(NETIF_F_TSO_BIT, &features);
 	if (tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3)) {
-		if (features & NETIF_F_IPV6_CSUM)
+		if (netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, features))
 			netdev_feature_add(NETIF_F_TSO6_BIT, &features);
 		if (tg3_flag(tp, HW_TSO_3) ||
 		    tg3_asic_rev(tp) == ASIC_REV_5761 ||
@@ -17905,7 +17905,7 @@ static int tg3_init_one(struct pci_dev *pdev,
 	}
 
 	netdev_info(dev, "RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n",
-		    (dev->features & NETIF_F_RXCSUM) != 0,
+		    (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)) != 0,
 		    tg3_flag(tp, USE_LINKCHG_REG) != 0,
 		    (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT) != 0,
 		    tg3_flag(tp, ENABLE_ASF) != 0,
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 649e1a6946e2..3d1deb7c114e 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -699,7 +699,7 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
 		masked_flags = flags & flags_cksum_prot_mask;
 
 		if (likely
-		    ((bnad->netdev->features & NETIF_F_RXCSUM) &&
+		    (netdev_active_feature_test(bnad->netdev, NETIF_F_RXCSUM_BIT) &&
 		     ((masked_flags == flags_tcp4) ||
 		      (masked_flags == flags_udp4) ||
 		      (masked_flags == flags_tcp6) ||
@@ -709,7 +709,7 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
 			skb_checksum_none_assert(skb);
 
 		if ((flags & BNA_CQ_EF_VLAN) &&
-		    (bnad->netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
+		    netdev_active_feature_test(bnad->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(cmpl->vlan_tag));
 
 		if (BNAD_RXBUF_IS_SK_BUFF(unmap_q->type))
@@ -2082,7 +2082,7 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
 	}
 
 	rx_config->vlan_strip_status =
-		(bnad->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) ?
+		(netdev_active_feature_test(bnad->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) ?
 		BNA_STATUS_T_ENABLED : BNA_STATUS_T_DISABLED;
 }
 
@@ -3349,12 +3349,12 @@ static int bnad_set_features(struct net_device *dev, netdev_features_t features)
 	struct bnad *bnad = netdev_priv(dev);
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
-	if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && netif_running(dev)) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed) && netif_running(dev)) {
 		unsigned long flags;
 
 		spin_lock_irqsave(&bnad->bna_lock, flags);
 
-		if (features & NETIF_F_HW_VLAN_CTAG_RX)
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 			bna_rx_vlan_strip_enable(bnad->rx_info[0].rx);
 		else
 			bna_rx_vlan_strip_disable(bnad->rx_info[0].rx);
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index b662f91c9b5d..d328fee017c9 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1375,7 +1375,7 @@ static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,
 
 		skb->protocol = eth_type_trans(skb, bp->dev);
 		skb_checksum_none_assert(skb);
-		if (bp->dev->features & NETIF_F_RXCSUM &&
+		if (netdev_active_feature_test(bp->dev, NETIF_F_RXCSUM_BIT) &&
 		    !(bp->dev->flags & IFF_PROMISC) &&
 		    GEM_BFEXT(RX_CSUM, ctrl) & GEM_RX_CSUM_CHECKED_MASK)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -2093,7 +2093,7 @@ static unsigned int macb_tx_map(struct macb *bp,
 		if (i == queue->tx_head) {
 			ctrl |= MACB_BF(TX_LSO, lso_ctrl);
 			ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);
-			if ((bp->dev->features & NETIF_F_HW_CSUM) &&
+			if (netdev_active_feature_test(bp->dev, NETIF_F_HW_CSUM_BIT) &&
 			    skb->ip_summed != CHECKSUM_PARTIAL && !lso_ctrl &&
 			    !ptp_one_step_sync(skb))
 				ctrl |= MACB_BIT(TX_NOCRC);
@@ -2195,7 +2195,7 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
 	struct sk_buff *nskb;
 	u32 fcs;
 
-	if (!(ndev->features & NETIF_F_HW_CSUM) ||
+	if (!netdev_active_feature_test(ndev, NETIF_F_HW_CSUM_BIT) ||
 	    !((*skb)->ip_summed != CHECKSUM_PARTIAL) ||
 	    skb_shinfo(*skb)->gso_size || ptp_one_step_sync(*skb))
 		return 0;
@@ -2674,7 +2674,7 @@ static void macb_configure_dma(struct macb *bp)
 		else
 			dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */
 
-		if (bp->dev->features & NETIF_F_HW_CSUM)
+		if (netdev_active_feature_test(bp->dev, NETIF_F_HW_CSUM_BIT))
 			dmacfg |= GEM_BIT(TXCOEN);
 		else
 			dmacfg &= ~GEM_BIT(TXCOEN);
@@ -2710,7 +2710,7 @@ static void macb_init_hw(struct macb *bp)
 		config |= MACB_BIT(BIG);	/* Receive oversized frames */
 	if (bp->dev->flags & IFF_PROMISC)
 		config |= MACB_BIT(CAF);	/* Copy All Frames */
-	else if (macb_is_gem(bp) && bp->dev->features & NETIF_F_RXCSUM)
+	else if (macb_is_gem(bp) && netdev_active_feature_test(bp->dev, NETIF_F_RXCSUM_BIT))
 		config |= GEM_BIT(RXCOEN);
 	if (!(bp->dev->flags & IFF_BROADCAST))
 		config |= MACB_BIT(NBC);	/* No BroadCast */
@@ -2821,7 +2821,7 @@ static void macb_set_rx_mode(struct net_device *dev)
 		cfg &= ~MACB_BIT(CAF);
 
 		/* Enable RX checksum offload only if requested */
-		if (macb_is_gem(bp) && dev->features & NETIF_F_RXCSUM)
+		if (macb_is_gem(bp) && netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT))
 			cfg |= GEM_BIT(RXCOEN);
 	}
 
@@ -3344,7 +3344,7 @@ static void gem_enable_flow_filters(struct macb *bp, bool enable)
 	u32 t2_scr;
 	int num_t2_scr;
 
-	if (!(netdev->features & NETIF_F_NTUPLE))
+	if (!(netdev_active_feature_test(netdev, NETIF_F_NTUPLE_BIT)))
 		return;
 
 	num_t2_scr = GEM_BFEXT(T2SCR, gem_readl(bp, DCFG8));
@@ -3704,7 +3704,7 @@ static inline void macb_set_txcsum_feature(struct macb *bp,
 		return;
 
 	val = gem_readl(bp, DMACFG);
-	if (features & NETIF_F_HW_CSUM)
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features))
 		val |= GEM_BIT(TXCOEN);
 	else
 		val &= ~GEM_BIT(TXCOEN);
@@ -3722,7 +3722,7 @@ static inline void macb_set_rxcsum_feature(struct macb *bp,
 		return;
 
 	val = gem_readl(bp, NCFGR);
-	if ((features & NETIF_F_RXCSUM) && !(netdev->flags & IFF_PROMISC))
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && !(netdev->flags & IFF_PROMISC))
 		val |= GEM_BIT(RXCOEN);
 	else
 		val &= ~GEM_BIT(RXCOEN);
@@ -3736,7 +3736,8 @@ static inline void macb_set_rxflow_feature(struct macb *bp,
 	if (!macb_is_gem(bp))
 		return;
 
-	gem_enable_flow_filters(bp, !!(features & NETIF_F_NTUPLE));
+	gem_enable_flow_filters(bp,
+				netdev_feature_test(NETIF_F_NTUPLE_BIT, features));
 }
 
 static int macb_set_features(struct net_device *netdev,
@@ -3746,15 +3747,15 @@ static int macb_set_features(struct net_device *netdev,
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
 	/* TX checksum offload */
-	if (changed & NETIF_F_HW_CSUM)
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, changed))
 		macb_set_txcsum_feature(bp, features);
 
 	/* RX checksum offload */
-	if (changed & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		macb_set_rxcsum_feature(bp, features);
 
 	/* RX Flow Filters */
-	if (changed & NETIF_F_NTUPLE)
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed))
 		macb_set_rxflow_feature(bp, features);
 
 	return 0;
@@ -5126,7 +5127,7 @@ static int __maybe_unused macb_suspend(struct device *dev)
 	if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
 		bp->pm_data.usrio = macb_or_gem_readl(bp, USRIO);
 
-	if (netdev->hw_features & NETIF_F_NTUPLE)
+	if (netdev_hw_feature_test(netdev, NETIF_F_NTUPLE_BIT))
 		bp->pm_data.scrt2 = gem_readl_n(bp, ETHT, SCRT2_ETHT);
 
 	if (bp->ptp_info)
@@ -5195,7 +5196,7 @@ static int __maybe_unused macb_resume(struct device *dev)
 		napi_enable(&queue->napi_tx);
 	}
 
-	if (netdev->hw_features & NETIF_F_NTUPLE)
+	if (netdev_hw_feature_test(netdev, NETIF_F_NTUPLE_BIT))
 		gem_writel_n(bp, ETHT, SCRT2_ETHT, bp->pm_data.scrt2);
 
 	if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 181c875ffda4..dbeabb229f25 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -975,7 +975,7 @@ static int xgmac_hw_init(struct net_device *dev)
 
 	ctrl |= XGMAC_CONTROL_DDIC | XGMAC_CONTROL_JE | XGMAC_CONTROL_ACS |
 		XGMAC_CONTROL_CAR;
-	if (dev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT))
 		ctrl |= XGMAC_CONTROL_IPC;
 	writel(ctrl, ioaddr + XGMAC_CONTROL);
 
@@ -1494,11 +1494,11 @@ static int xgmac_set_features(struct net_device *dev, netdev_features_t features
 	void __iomem *ioaddr = priv->base;
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
-	if (!(changed & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
 	ctrl = readl(ioaddr + XGMAC_CONTROL);
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		ctrl |= XGMAC_CONTROL_IPC;
 	else
 		ctrl &= ~XGMAC_CONTROL_IPC;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c
index 73cb03266549..6ab04e8ff569 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_core.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c
@@ -659,7 +659,7 @@ liquidio_push_packet(u32 __maybe_unused octeon_id,
 		skb_pull(skb, rh->r_dh.len * BYTES_PER_DHLEN_UNIT);
 		skb->protocol = eth_type_trans(skb, skb->dev);
 
-		if ((netdev->features & NETIF_F_RXCSUM) &&
+		if ((netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) &&
 		    (((rh->r_dh.encap_on) &&
 		      (rh->r_dh.csum_verified & CNNIC_TUN_CSUM_VERIFIED)) ||
 		     (!(rh->r_dh.encap_on) &&
@@ -680,7 +680,7 @@ liquidio_push_packet(u32 __maybe_unused octeon_id,
 		}
 
 		/* inbound VLAN tag */
-		if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+		if ((netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) &&
 		    rh->r_dh.vlan) {
 			u16 priority = rh->r_dh.priority;
 			u16 vid = rh->r_dh.vlan;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index fb12fcf85d0f..8b1b18d453c5 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2720,30 +2720,34 @@ static netdev_features_t liquidio_fix_features(struct net_device *netdev,
 {
 	struct lio *lio = netdev_priv(netdev);
 
-	if ((request & NETIF_F_RXCSUM) &&
-	    !(lio->dev_capability & NETIF_F_RXCSUM))
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_RXCSUM_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_RXCSUM_BIT, &request);
 
-	if ((request & NETIF_F_HW_CSUM) &&
-	    !(lio->dev_capability & NETIF_F_HW_CSUM))
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_HW_CSUM_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_HW_CSUM_BIT, &request);
 
-	if ((request & NETIF_F_TSO) && !(lio->dev_capability & NETIF_F_TSO))
+	if (netdev_feature_test(NETIF_F_TSO_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_TSO_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_TSO_BIT, &request);
 
-	if ((request & NETIF_F_TSO6) && !(lio->dev_capability & NETIF_F_TSO6))
+	if (netdev_feature_test(NETIF_F_TSO6_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_TSO6_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_TSO6_BIT, &request);
 
-	if ((request & NETIF_F_LRO) && !(lio->dev_capability & NETIF_F_LRO))
+	if (netdev_feature_test(NETIF_F_LRO_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_LRO_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_LRO_BIT, &request);
 
 	/*Disable LRO if RXCSUM is off */
-	if (!(request & NETIF_F_RXCSUM) && (netdev->features & NETIF_F_LRO) &&
-	    (lio->dev_capability & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, request) &&
+	    netdev_active_feature_test(netdev, NETIF_F_LRO_BIT) &&
+	    netdev_feature_test(NETIF_F_LRO_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_LRO_BIT, &request);
 
-	if ((request & NETIF_F_HW_VLAN_CTAG_FILTER) &&
-	    !(lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, &request);
 
 	return request;
@@ -2759,40 +2763,40 @@ static int liquidio_set_features(struct net_device *netdev,
 {
 	struct lio *lio = netdev_priv(netdev);
 
-	if ((features & NETIF_F_LRO) &&
-	    (lio->dev_capability & NETIF_F_LRO) &&
-	    !(netdev->features & NETIF_F_LRO))
+	if (netdev_feature_test(NETIF_F_LRO_BIT, features) &&
+	    netdev_feature_test(NETIF_F_LRO_BIT, lio->dev_capability) &&
+	    !netdev_active_feature_test(netdev, NETIF_F_LRO_BIT))
 		liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
 				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
-	else if (!(features & NETIF_F_LRO) &&
-		 (lio->dev_capability & NETIF_F_LRO) &&
-		 (netdev->features & NETIF_F_LRO))
+	else if (!netdev_feature_test(NETIF_F_LRO_BIT, features) &&
+		 netdev_feature_test(NETIF_F_LRO_BIT, lio->dev_capability) &&
+		 netdev_active_feature_test(netdev, NETIF_F_LRO_BIT))
 		liquidio_set_feature(netdev, OCTNET_CMD_LRO_DISABLE,
 				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
 
 	/* Sending command to firmware to enable/disable RX checksum
 	 * offload settings using ethtool
 	 */
-	if (!(netdev->features & NETIF_F_RXCSUM) &&
-	    (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
-	    (features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT) &&
+	    netdev_feature_test(NETIF_F_RXCSUM_BIT, lio->enc_dev_capability) &&
+	    netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		liquidio_set_rxcsum_command(netdev,
 					    OCTNET_CMD_TNL_RX_CSUM_CTL,
 					    OCTNET_CMD_RXCSUM_ENABLE);
-	else if ((netdev->features & NETIF_F_RXCSUM) &&
-		 (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
-		 !(features & NETIF_F_RXCSUM))
+	else if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT) &&
+		 netdev_feature_test(NETIF_F_RXCSUM_BIT, lio->enc_dev_capability) &&
+		 !netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
 					    OCTNET_CMD_RXCSUM_DISABLE);
 
-	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
-	    (lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER) &&
-	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) &&
+	    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, lio->dev_capability) &&
+	    !netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		liquidio_set_feature(netdev, OCTNET_CMD_VLAN_FILTER_CTL,
 				     OCTNET_CMD_VLAN_FILTER_ENABLE);
-	else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
-		 (lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER) &&
-		 (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+	else if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) &&
+		 netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, lio->dev_capability) &&
+		 netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		liquidio_set_feature(netdev, OCTNET_CMD_VLAN_FILTER_CTL,
 				     OCTNET_CMD_VLAN_FILTER_DISABLE);
 
@@ -3675,7 +3679,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 		else
 			octeon_dev->priv_flags = 0x0;
 
-		if (netdev->features & NETIF_F_LRO)
+		if (netdev_active_feature_test(netdev, NETIF_F_LRO_BIT))
 			liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
 					     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
 
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 45bc4d71d353..5cf13ee5840b 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -1818,26 +1818,30 @@ static netdev_features_t liquidio_fix_features(struct net_device *netdev,
 {
 	struct lio *lio = netdev_priv(netdev);
 
-	if ((request & NETIF_F_RXCSUM) &&
-	    !(lio->dev_capability & NETIF_F_RXCSUM))
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_RXCSUM_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_RXCSUM_BIT, &request);
 
-	if ((request & NETIF_F_HW_CSUM) &&
-	    !(lio->dev_capability & NETIF_F_HW_CSUM))
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_HW_CSUM_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_HW_CSUM_BIT, &request);
 
-	if ((request & NETIF_F_TSO) && !(lio->dev_capability & NETIF_F_TSO))
+	if (netdev_feature_test(NETIF_F_TSO_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_TSO_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_TSO_BIT, &request);
 
-	if ((request & NETIF_F_TSO6) && !(lio->dev_capability & NETIF_F_TSO6))
+	if (netdev_feature_test(NETIF_F_TSO6_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_TSO6_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_TSO6_BIT, &request);
 
-	if ((request & NETIF_F_LRO) && !(lio->dev_capability & NETIF_F_LRO))
+	if (netdev_feature_test(NETIF_F_LRO_BIT, request) &&
+	    !netdev_feature_test(NETIF_F_LRO_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_LRO_BIT, &request);
 
 	/* Disable LRO if RXCSUM is off */
-	if (!(request & NETIF_F_RXCSUM) && (netdev->features & NETIF_F_LRO) &&
-	    (lio->dev_capability & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, request) &&
+	    netdev_active_feature_test(netdev, NETIF_F_LRO_BIT) &&
+	    netdev_feature_test(NETIF_F_LRO_BIT, lio->dev_capability))
 		netdev_feature_del(NETIF_F_LRO_BIT, &request);
 
 	return request;
@@ -1854,24 +1858,25 @@ static int liquidio_set_features(struct net_device *netdev,
 							       features);
 	struct lio *lio = netdev_priv(netdev);
 
-	if (!(changed & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, changed))
 		return 0;
 
-	if ((features & NETIF_F_LRO) && (lio->dev_capability & NETIF_F_LRO))
+	if (netdev_feature_test(NETIF_F_LRO_BIT, features) &&
+	    netdev_feature_test(NETIF_F_LRO_BIT, lio->dev_capability))
 		liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
 				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
-	else if (!(features & NETIF_F_LRO) &&
-		 (lio->dev_capability & NETIF_F_LRO))
+	else if (!netdev_feature_test(NETIF_F_LRO_BIT, features) &&
+		 netdev_feature_test(NETIF_F_LRO_BIT, lio->dev_capability))
 		liquidio_set_feature(netdev, OCTNET_CMD_LRO_DISABLE,
 				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
-	if (!(netdev->features & NETIF_F_RXCSUM) &&
-	    (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
-	    (features & NETIF_F_RXCSUM))
+	if (!(netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) &&
+	    netdev_feature_test(NETIF_F_RXCSUM_BIT, lio->enc_dev_capability) &&
+	    netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
 					    OCTNET_CMD_RXCSUM_ENABLE);
-	else if ((netdev->features & NETIF_F_RXCSUM) &&
-		 (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
-		 !(features & NETIF_F_RXCSUM))
+	else if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT) &&
+		 netdev_feature_test(NETIF_F_RXCSUM_BIT, lio->enc_dev_capability) &&
+		 !netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
 					    OCTNET_CMD_RXCSUM_DISABLE);
 
@@ -2199,7 +2204,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 		else
 			octeon_dev->priv_flags = 0x0;
 
-		if (netdev->features & NETIF_F_LRO)
+		if (netdev_active_feature_test(netdev, NETIF_F_LRO_BIT))
 			liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
 					     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
 
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 52d810f4b39c..813f87feac2b 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -732,7 +732,7 @@ static inline void nicvf_set_rxhash(struct net_device *netdev,
 	u8 hash_type;
 	u32 hash;
 
-	if (!(netdev->features & NETIF_F_RXHASH))
+	if (!netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT))
 		return;
 
 	switch (cqe_rx->rss_alg) {
@@ -823,7 +823,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
 	nicvf_set_rxhash(netdev, cqe_rx, skb);
 
 	skb_record_rx_queue(skb, rq_idx);
-	if (netdev->hw_features & NETIF_F_RXCSUM) {
+	if (netdev_hw_feature_test(netdev, NETIF_F_RXCSUM_BIT)) {
 		/* HW by default verifies TCP/UDP/SCTP checksums */
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	} else {
@@ -837,7 +837,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
 				       ntohs((__force __be16)cqe_rx->vlan_tci));
 
-	if (napi && (netdev->features & NETIF_F_GRO))
+	if (napi && netdev_active_feature_test(netdev, NETIF_F_GRO_BIT))
 		napi_gro_receive(napi, skb);
 	else
 		netif_receive_skb(skb);
@@ -1768,7 +1768,7 @@ static int nicvf_config_loopback(struct nicvf *nic,
 
 	mbx.lbk.msg = NIC_MBOX_MSG_LOOPBACK;
 	mbx.lbk.vf_id = nic->vf_id;
-	mbx.lbk.enable = (features & NETIF_F_LOOPBACK) != 0;
+	mbx.lbk.enable = netdev_feature_test(NETIF_F_LOOPBACK_BIT, features);
 
 	return nicvf_send_msg_to_pf(nic, &mbx);
 }
@@ -1778,7 +1778,7 @@ static netdev_features_t nicvf_fix_features(struct net_device *netdev,
 {
 	struct nicvf *nic = netdev_priv(netdev);
 
-	if ((features & NETIF_F_LOOPBACK) &&
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features) &&
 	    netif_running(netdev) && !nic->loopback_supported)
 		netdev_feature_del(NETIF_F_LOOPBACK_BIT, &features);
 
@@ -1791,10 +1791,10 @@ static int nicvf_set_features(struct net_device *netdev,
 	struct nicvf *nic = netdev_priv(netdev);
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		nicvf_config_vlan_stripping(nic, features);
 
-	if ((changed & NETIF_F_LOOPBACK) && netif_running(netdev))
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed) && netif_running(netdev))
 		return nicvf_config_loopback(nic, features);
 
 	return 0;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index 06397cc8bb36..c9080dbccca1 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -715,7 +715,7 @@ void nicvf_config_vlan_stripping(struct nicvf *nic, netdev_features_t features)
 	rq_cfg = nicvf_queue_reg_read(nic, NIC_QSET_RQ_GEN_CFG, 0);
 
 	/* Enable first VLAN stripping */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		rq_cfg |= (1ULL << 25);
 	else
 		rq_cfg &= ~(1ULL << 25);
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index d9e2bf1eccf3..db6a422e8bb6 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -187,7 +187,7 @@ static void link_start(struct port_info *p)
 
 static void enable_hw_csum(struct adapter *adapter)
 {
-	if (adapter->port[0].dev->hw_features & NETIF_F_TSO)
+	if (netdev_hw_feature_test(adapter->port[0].dev, NETIF_F_TSO_BIT))
 		t1_tp_set_ip_checksum_offload(adapter->tp, 1);	/* for TSO only */
 	t1_tp_set_tcp_checksum_offload(adapter->tp, 1);
 }
@@ -870,7 +870,7 @@ static netdev_features_t t1_fix_features(struct net_device *dev,
 	 * Since there is no support for separate rx/tx vlan accel
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -883,7 +883,7 @@ static int t1_set_features(struct net_device *dev, netdev_features_t features)
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	struct adapter *adapter = dev->ml_priv;
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		t1_vlan_mode(adapter, features);
 
 	return 0;
@@ -1062,7 +1062,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		}
 
 		netdev->netdev_ops = &cxgb_netdev_ops;
-		netdev->hard_header_len += (netdev->hw_features & NETIF_F_TSO) ?
+		netdev->hard_header_len += netdev_hw_feature_test(netdev, NETIF_F_TSO_BIT) ?
 			sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt);
 
 		netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c
index 12e76fd0ae91..bcbcffd308f4 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -737,7 +737,7 @@ void t1_vlan_mode(struct adapter *adapter, netdev_features_t features)
 {
 	struct sge *sge = adapter->sge;
 
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		sge->sge_control |= F_VLAN_XTRACT;
 	else
 		sge->sge_control &= ~F_VLAN_XTRACT;
@@ -922,7 +922,7 @@ void t1_sge_intr_enable(struct sge *sge)
 	u32 en = SGE_INT_ENABLE;
 	u32 val = readl(sge->adapter->regs + A_PL_ENABLE);
 
-	if (sge->adapter->port[0].dev->hw_features & NETIF_F_TSO)
+	if (netdev_hw_feature_test(sge->adapter->port[0].dev, NETIF_F_TSO_BIT))
 		en &= ~F_PACKET_TOO_BIG;
 	writel(en, sge->adapter->regs + A_SG_INT_ENABLE);
 	writel(val | SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_ENABLE);
@@ -946,7 +946,7 @@ bool t1_sge_intr_error_handler(struct sge *sge)
 	u32 cause = readl(adapter->regs + A_SG_INT_CAUSE);
 	bool wake = false;
 
-	if (adapter->port[0].dev->hw_features & NETIF_F_TSO)
+	if (netdev_hw_feature_test(adapter->port[0].dev, NETIF_F_TSO_BIT))
 		cause &= ~F_PACKET_TOO_BIG;
 	if (cause & F_RESPQ_EXHAUSTED)
 		sge->stats.respQ_empty++;
@@ -1386,7 +1386,7 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
 	dev = adapter->port[p->iff].dev;
 
 	skb->protocol = eth_type_trans(skb, dev);
-	if ((dev->features & NETIF_F_RXCSUM) && p->csum == 0xffff &&
+	if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT) && p->csum == 0xffff &&
 	    skb->protocol == htons(ETH_P_IP) &&
 	    (skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
 		++st->rx_cso_good;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 1284e3d9c9c5..d7c1637f7d63 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -1184,15 +1184,16 @@ static void cxgb_vlan_mode(struct net_device *dev, netdev_features_t features)
 
 	if (adapter->params.rev > 0) {
 		t3_set_vlan_accel(adapter, 1 << pi->port_id,
-				  features & NETIF_F_HW_VLAN_CTAG_RX);
+				  netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features));
 	} else {
 		/* single control for all ports */
-		unsigned int i, have_vlans = features & NETIF_F_HW_VLAN_CTAG_RX;
+		unsigned int have_vlans = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+							      features);
+		unsigned int i;
 
 		for_each_port(adapter, i)
-			have_vlans |=
-				adapter->port[i]->features &
-				NETIF_F_HW_VLAN_CTAG_RX;
+			have_vlans |= netdev_active_feature_test(adapter->port[i],
+								 NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 		t3_set_vlan_accel(adapter, 1, have_vlans);
 	}
@@ -2286,7 +2287,7 @@ static int cxgb_siocdevprivate(struct net_device *dev,
 		t.fl_size[0] = q->fl_size;
 		t.fl_size[1] = q->jumbo_size;
 		t.polling = q->polling;
-		t.lro = !!(dev->features & NETIF_F_GRO);
+		t.lro = !!(netdev_active_feature_test(dev, NETIF_F_GRO_BIT));
 		t.intr_lat = q->coalesce_usecs;
 		t.cong_thres = q->cong_thres;
 		t.qnum = q1;
@@ -2595,7 +2596,7 @@ static netdev_features_t cxgb_fix_features(struct net_device *dev,
 	 * Since there is no support for separate rx/tx vlan accel
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -2607,7 +2608,7 @@ static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 {
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		cxgb_vlan_mode(dev, features);
 
 	return 0;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index 62dfbdd33365..265ff74629c9 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -2096,7 +2096,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
 	skb_pull(skb, sizeof(*p) + pad);
 	skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
 	pi = netdev_priv(skb->dev);
-	if ((skb->dev->features & NETIF_F_RXCSUM) && p->csum_valid &&
+	if (netdev_active_feature_test(skb->dev, NETIF_F_RXCSUM_BIT) && p->csum_valid &&
 	    p->csum == htons(0xffff) && !p->fragment) {
 		qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -2177,7 +2177,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
 		offset = 2 + sizeof(struct cpl_rx_pkt);
 		cpl = qs->lro_va = sd->pg_chunk.va + 2;
 
-		if ((qs->netdev->features & NETIF_F_RXCSUM) &&
+		if (netdev_active_feature_test(qs->netdev, NETIF_F_RXCSUM_BIT) &&
 		     cpl->csum_valid && cpl->csum == htons(0xffff)) {
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
@@ -2339,7 +2339,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
 
 	while (likely(budget_left && is_new_response(r, q))) {
 		int packet_complete, eth, ethpad = 2;
-		int lro = !!(qs->netdev->features & NETIF_F_GRO);
+		int lro = netdev_active_feature_test(qs->netdev, NETIF_F_GRO_BIT);
 		struct sk_buff *skb = NULL;
 		u32 len, flags;
 		__be32 rss_hi, rss_lo;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index f77984b79a30..e903fe97975d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -514,7 +514,8 @@ static int link_start(struct net_device *dev)
 	 */
 	ret = t4_set_rxmode(pi->adapter, mb, pi->viid, pi->viid_mirror,
 			    dev->mtu, -1, -1, -1,
-			    !!(dev->features & NETIF_F_HW_VLAN_CTAG_RX), true);
+			    netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT),
+			    true);
 	if (ret == 0)
 		ret = cxgb4_update_mac_filt(pi, pi->viid, &pi->xact_addr_filt,
 					    dev->dev_addr, true, &pi->smt_idx);
@@ -1277,12 +1278,13 @@ static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 	const struct port_info *pi = netdev_priv(dev);
 	int err;
 
-	if (!(changed & NETIF_F_HW_VLAN_CTAG_RX))
+	if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		return 0;
 
 	err = t4_set_rxmode(pi->adapter, pi->adapter->mbox, pi->viid,
 			    pi->viid_mirror, -1, -1, -1, -1,
-			    !!(features & NETIF_F_HW_VLAN_CTAG_RX), true);
+			    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features),
+			    true);
 	if (unlikely(err)) {
 		dev->features = features;
 		netdev_active_feature_change(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
@@ -1463,7 +1465,8 @@ static int cxgb4_port_mirror_start(struct net_device *dev)
 	ret = t4_set_rxmode(adap, adap->mbox, pi->viid, pi->viid_mirror,
 			    dev->mtu, (dev->flags & IFF_PROMISC) ? 1 : 0,
 			    (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1,
-			    !!(dev->features & NETIF_F_HW_VLAN_CTAG_RX), true);
+			    netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT),
+			    true);
 	if (ret) {
 		dev_err(adap->pdev_dev,
 			"Failed start up Rx mode for Mirror VI 0x%x, ret: %d\n",
@@ -3859,7 +3862,7 @@ static netdev_features_t cxgb_fix_features(struct net_device *dev,
 					   netdev_features_t features)
 {
 	/* Disable GRO, if RX_CSUM is disabled */
-	if (!(features & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		netdev_feature_del(NETIF_F_GRO_BIT, &features);
 
 	return features;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.h
index 70a07b7cca56..2be64141f3e4 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.h
@@ -41,7 +41,7 @@ static inline bool can_tc_u32_offload(struct net_device *dev)
 {
 	struct adapter *adap = netdev2adap(dev);
 
-	return (dev->features & NETIF_F_HW_TC) && adap->tc_u32 ? true : false;
+	return (netdev_active_feature_test(dev, NETIF_F_HW_TC_BIT)) && adap->tc_u32 ? true : false;
 }
 
 int cxgb4_config_knode(struct net_device *dev, struct tc_cls_u32_offload *cls);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index ee52e3b1d74f..12556a1c11d7 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -3468,7 +3468,7 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
 	if (pi->rxtstamp)
 		cxgb4_sgetim_to_hwtstamp(adapter, skb_hwtstamps(skb),
 					 gl->sgetstamp);
-	if (rxq->rspq.netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(rxq->rspq.netdev, NETIF_F_RXHASH_BIT))
 		skb_set_hash(skb, (__force u32)pkt->rsshdr.hash_val,
 			     PKT_HASH_TYPE_L3);
 
@@ -3710,7 +3710,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
 	}
 
 	csum_ok = pkt->csum_calc && !err_vec &&
-		  (q->netdev->features & NETIF_F_RXCSUM);
+		  netdev_active_feature_test(q->netdev, NETIF_F_RXCSUM_BIT);
 
 	if (err_vec)
 		rxq->stats.bad_rx_pkts++;
@@ -3723,7 +3723,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
 
 	if (((pkt->l2info & htonl(RXF_TCP_F)) ||
 	     tnl_hdr_len) &&
-	    (q->netdev->features & NETIF_F_GRO) && csum_ok && !pkt->ip_frag) {
+	    netdev_active_feature_test(q->netdev, NETIF_F_GRO_BIT) && csum_ok && !pkt->ip_frag) {
 		do_gro(rxq, si, pkt, tnl_hdr_len);
 		return 0;
 	}
@@ -3754,7 +3754,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
 
 	skb->protocol = eth_type_trans(skb, q->netdev);
 	skb_record_rx_queue(skb, q->idx);
-	if (skb->dev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(skb->dev, NETIF_F_RXHASH_BIT))
 		skb_set_hash(skb, (__force u32)pkt->rsshdr.hash_val,
 			     PKT_HASH_TYPE_L3);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index f99cc9715317..efc86d7e7c42 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -1181,7 +1181,7 @@ static netdev_features_t cxgb4vf_fix_features(struct net_device *dev,
 	 * Since there is no support for separate rx/tx vlan accel
 	 * enable/disable make sure tx flag is always in same state as rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -1195,9 +1195,10 @@ static int cxgb4vf_set_features(struct net_device *dev,
 	struct port_info *pi = netdev_priv(dev);
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		t4vf_set_rxmode(pi->adapter, pi->viid, -1, -1, -1, -1,
-				features & NETIF_F_HW_VLAN_CTAG_TX, 0);
+				netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features),
+				0);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index 43b2ceb6aa32..e40a46528021 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -1614,7 +1614,7 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
 	struct sk_buff *skb;
 	const struct cpl_rx_pkt *pkt = (void *)rsp;
 	bool csum_ok = pkt->csum_calc && !pkt->err_vec &&
-		       (rspq->netdev->features & NETIF_F_RXCSUM);
+		       netdev_active_feature_test(rspq->netdev, NETIF_F_RXCSUM_BIT);
 	struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
 	struct adapter *adapter = rspq->adapter;
 	struct sge *s = &adapter->sge;
@@ -1625,7 +1625,7 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
 	 * enabled, handle the packet in the GRO path.
 	 */
 	if ((pkt->l2info & cpu_to_be32(RXF_TCP_F)) &&
-	    (rspq->netdev->features & NETIF_F_GRO) && csum_ok &&
+	    netdev_active_feature_test(rspq->netdev, NETIF_F_GRO_BIT) && csum_ok &&
 	    !pkt->ip_frag) {
 		do_gro(rxq, gl, pkt);
 		return 0;
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
index 9098b3eed4da..eb642c01eb18 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
@@ -135,7 +135,7 @@ static int chtls_inline_feature(struct tls_toe_device *dev)
 
 	for (i = 0; i < cdev->lldi->nports; i++) {
 		netdev = cdev->ports[i];
-		if (netdev->features & NETIF_F_HW_TLS_RECORD)
+		if (netdev_active_feature_test(netdev, NETIF_F_HW_TLS_RECORD_BIT))
 			return 1;
 	}
 	return 0;
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index b2bf06b3054b..f48144b46153 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1359,8 +1359,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
 		skb_put(skb, bytes_written);
 		skb->protocol = eth_type_trans(skb, netdev);
 		skb_record_rx_queue(skb, q_number);
-		if ((netdev->features & NETIF_F_RXHASH) && rss_hash &&
-		    (type == 3)) {
+		if (netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT) &&
+		    rss_hash && (type == 3)) {
 			switch (rss_type) {
 			case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4:
 			case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6:
@@ -1402,8 +1402,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
 		 * inner csum_ok. outer_csum_ok is set by hw when outer udp
 		 * csum is correct or is zero.
 		 */
-		if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
-		    tcp_udp_csum_ok && outer_csum_ok &&
+		if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT) &&
+		    !csum_not_calc && tcp_udp_csum_ok && outer_csum_ok &&
 		    (ipv4_csum_ok || ipv6)) {
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			skb->csum_level = encap;
@@ -1413,7 +1413,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
 
 		skb_mark_napi_id(skb, &enic->napi[rq->index]);
-		if (!(netdev->features & NETIF_F_GRO))
+		if (!netdev_active_feature_test(netdev, NETIF_F_GRO_BIT))
 			netif_receive_skb(skb);
 		else
 			napi_gro_receive(&enic->napi[q_number], skb);
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index e5459716a46d..5ce606ebaadc 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -1999,7 +1999,7 @@ static int gmac_set_features(struct net_device *netdev,
 			     netdev_features_t features)
 {
 	struct gemini_ethernet_port *port = netdev_priv(netdev);
-	int enable = features & NETIF_F_RXCSUM;
+	int enable = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
 	unsigned long flags;
 	u32 reg;
 
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 22bc1f9da086..452b8496ddb4 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -590,11 +590,12 @@ static int dm9000_set_features(struct net_device *dev,
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	unsigned long flags;
 
-	if (!(changed & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
 	spin_lock_irqsave(&dm->lock, flags);
-	iow(dm, DM9000_RCSR, (features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0);
+	iow(dm, DM9000_RCSR,
+	    netdev_feature_test(NETIF_F_RXCSUM_BIT, features) ? RCSR_CSUM : 0);
 	spin_unlock_irqrestore(&dm->lock, flags);
 
 	return 0;
@@ -912,9 +913,9 @@ dm9000_init_dm9000(struct net_device *dev)
 	db->io_mode = ior(db, DM9000_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */
 
 	/* Checksum mode */
-	if (dev->hw_features & NETIF_F_RXCSUM)
+	if (netdev_hw_feature_test(dev, NETIF_F_RXCSUM_BIT))
 		iow(db, DM9000_RCSR,
-			(dev->features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0);
+			(netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)) ? RCSR_CSUM : 0);
 
 	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */
 	iow(db, DM9000_GPR, 0);
@@ -1170,7 +1171,7 @@ dm9000_rx(struct net_device *dev)
 
 			/* Pass to upper layer */
 			skb->protocol = eth_type_trans(skb, dev);
-			if (dev->features & NETIF_F_RXCSUM) {
+			if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)) {
 				if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
 					skb->ip_summed = CHECKSUM_UNNECESSARY;
 				else
diff --git a/drivers/net/ethernet/davicom/dm9051.c b/drivers/net/ethernet/davicom/dm9051.c
index a523ddda7609..ce2c0c6d940c 100644
--- a/drivers/net/ethernet/davicom/dm9051.c
+++ b/drivers/net/ethernet/davicom/dm9051.c
@@ -802,7 +802,7 @@ static int dm9051_loop_rx(struct board_info *db)
 			return ret;
 
 		skb->protocol = eth_type_trans(skb, db->ndev);
-		if (db->ndev->features & NETIF_F_RXCSUM)
+		if (netdev_active_feature_test(db->ndev, NETIF_F_RXCSUM_BIT))
 			skb_checksum_none_assert(skb);
 		netif_rx(skb);
 		db->ndev->stats.rx_bytes += rxlen;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index cd8baf47ceed..9e79243bd442 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2407,14 +2407,14 @@ static void be_rx_compl_process(struct be_rx_obj *rxo, struct napi_struct *napi,
 
 	skb_fill_rx_data(rxo, skb, rxcp);
 
-	if (likely((netdev->features & NETIF_F_RXCSUM) && csum_passed(rxcp)))
+	if (likely((netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) && csum_passed(rxcp)))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	else
 		skb_checksum_none_assert(skb);
 
 	skb->protocol = eth_type_trans(skb, netdev);
 	skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
-	if (netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT))
 		skb_set_hash(skb, rxcp->rss_hash, PKT_HASH_TYPE_L3);
 
 	skb->csum_level = rxcp->tunneled;
@@ -2472,7 +2472,7 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo,
 	skb->data_len = rxcp->pkt_size;
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 	skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
-	if (adapter->netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_RXHASH_BIT))
 		skb_set_hash(skb, rxcp->rss_hash, PKT_HASH_TYPE_L3);
 
 	skb->csum_level = rxcp->tunneled;
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 50f5fdcbedb4..4c553c3d4818 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -330,7 +330,7 @@ static void ftgmac100_start_hw(struct ftgmac100 *priv)
 		maccr |= FTGMAC100_MACCR_HT_MULTI_EN;
 
 	/* Vlan filtering enabled */
-	if (priv->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(priv->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		maccr |= FTGMAC100_MACCR_RM_VLAN;
 
 	/* Hit the HW */
@@ -514,7 +514,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
 	 * by HW as one of the supported checksummed protocols before
 	 * we accept the HW test results.
 	 */
-	if (netdev->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) {
 		u32 err_bits = FTGMAC100_RXDES1_TCP_CHKSUM_ERR |
 			FTGMAC100_RXDES1_UDP_CHKSUM_ERR |
 			FTGMAC100_RXDES1_IP_CHKSUM_ERR;
@@ -529,7 +529,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
 	skb_put(skb, size);
 
 	/* Extract vlan tag */
-	if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	    (csum_vlan & FTGMAC100_RXDES1_VLANTAG_AVAIL))
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
 				       csum_vlan & 0xffff);
@@ -1604,11 +1604,11 @@ static int ftgmac100_set_features(struct net_device *netdev,
 		return 0;
 
 	/* Update the vlan filtering bit */
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed)) {
 		u32 maccr;
 
 		maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR);
-		if (priv->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+		if (netdev_active_feature_test(priv->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 			maccr |= FTGMAC100_MACCR_RM_VLAN;
 		else
 			maccr &= ~FTGMAC100_MACCR_RM_VLAN;
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 6f9bde1c4153..626c9ba24bcd 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -1710,7 +1710,7 @@ static u8 rx_csum_offload(const struct dpaa_priv *priv, const struct qm_fd *fd)
 	 * We know there were no parser errors (and implicitly no
 	 * L4 csum error), otherwise we wouldn't be here.
 	 */
-	if ((priv->net_dev->features & NETIF_F_RXCSUM) &&
+	if (netdev_active_feature_test(priv->net_dev, NETIF_F_RXCSUM_BIT) &&
 	    (be32_to_cpu(fd->status) & FM_FD_STAT_L4CV))
 		return CHECKSUM_UNNECESSARY;
 
@@ -2709,7 +2709,8 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
 	}
 
 	/* Extract the hash stored in the headroom before running XDP */
-	if (net_dev->features & NETIF_F_RXHASH && priv->keygen_in_use &&
+	if (netdev_active_feature_test(net_dev, NETIF_F_RXHASH_BIT) &&
+	    priv->keygen_in_use &&
 	    !fman_port_get_hash_result_offset(priv->mac_dev->port[RX],
 					      &hash_offset)) {
 		hash = be32_to_cpu(*(u32 *)(vaddr + hash_offset));
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 9781948df963..165b6c9c0c41 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -122,7 +122,7 @@ static void dpaa2_eth_validate_rx_csum(struct dpaa2_eth_priv *priv,
 	skb_checksum_none_assert(skb);
 
 	/* HW checksum validation is disabled, nothing to do here */
-	if (!(priv->net_dev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(priv->net_dev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* Read checksum validation bits */
@@ -2426,15 +2426,15 @@ static int dpaa2_eth_set_features(struct net_device *net_dev,
 	bool enable;
 	int err;
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
-		enable = !!(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed)) {
+		enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features);
 		err = dpaa2_eth_set_rx_vlan_filtering(priv, enable);
 		if (err)
 			return err;
 	}
 
-	if (changed & NETIF_F_RXCSUM) {
-		enable = !!(features & NETIF_F_RXCSUM);
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
+		enable = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
 		err = dpaa2_eth_set_rx_csum(priv, enable);
 		if (err)
 			return err;
@@ -4696,7 +4696,8 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
 		goto err_netdev_init;
 
 	/* Configure checksum offload based on current interface flags */
-	err = dpaa2_eth_set_rx_csum(priv, !!(net_dev->features & NETIF_F_RXCSUM));
+	err = dpaa2_eth_set_rx_csum(priv,
+				    netdev_active_feature_test(net_dev, NETIF_F_RXCSUM_BIT));
 	if (err)
 		goto err_csum;
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 40e7ab38ed01..bc4a0288cfe7 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -989,7 +989,7 @@ static void enetc_get_offloads(struct enetc_bdr *rx_ring,
 	struct enetc_ndev_priv *priv = netdev_priv(rx_ring->ndev);
 
 	/* TODO: hashing */
-	if (rx_ring->ndev->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(rx_ring->ndev, NETIF_F_RXCSUM_BIT)) {
 		u16 inet_csum = le16_to_cpu(rxbd->r.inet_csum);
 
 		skb->csum = csum_unfold((__force __sum16)~htons(inet_csum));
@@ -2059,7 +2059,7 @@ static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
 	enetc_txbdr_wr(hw, idx, ENETC_TBICR0, ENETC_TBICR0_ICEN | 0x1);
 
 	tbmr = ENETC_TBMR_EN;
-	if (tx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_TX)
+	if (netdev_active_feature_test(tx_ring->ndev, NETIF_F_HW_VLAN_CTAG_TX_BIT))
 		tbmr |= ENETC_TBMR_VIH;
 
 	/* enable ring */
@@ -2100,7 +2100,7 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
 	if (rx_ring->ext_en)
 		rbmr |= ENETC_RBMR_BDS;
 
-	if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(rx_ring->ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		rbmr |= ENETC_RBMR_VTE;
 
 	rx_ring->rcir = hw->reg + ENETC_BDR(RX, idx, ENETC_RBCIR);
@@ -2647,19 +2647,21 @@ int enetc_set_features(struct net_device *ndev,
 	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 	int err = 0;
 
-	if (changed & NETIF_F_RXHASH)
-		enetc_set_rss(ndev, !!(features & NETIF_F_RXHASH));
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, changed))
+		enetc_set_rss(ndev,
+			      netdev_feature_test(NETIF_F_RXHASH_BIT, features));
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		enetc_enable_rxvlan(ndev,
-				    !!(features & NETIF_F_HW_VLAN_CTAG_RX));
+				    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features));
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_TX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, changed))
 		enetc_enable_txvlan(ndev,
-				    !!(features & NETIF_F_HW_VLAN_CTAG_TX));
+				    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features));
 
-	if (changed & NETIF_F_HW_TC)
-		err = enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
+	if (netdev_feature_test(NETIF_F_HW_TC_BIT, changed))
+		err = enetc_set_psfp(ndev,
+				     netdev_feature_test(NETIF_F_HW_TC_BIT, features));
 
 	return err;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 7f21068667b7..bf4229f82760 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -711,17 +711,18 @@ static int enetc_pf_set_features(struct net_device *ndev,
 	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed)) {
 		struct enetc_pf *pf = enetc_si_priv(priv->si);
 
-		if (!!(features & NETIF_F_HW_VLAN_CTAG_FILTER))
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
 			enetc_disable_si_vlan_promisc(pf, 0);
 		else
 			enetc_enable_si_vlan_promisc(pf, 0);
 	}
 
-	if (changed & NETIF_F_LOOPBACK)
-		enetc_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed))
+		enetc_set_loopback(ndev,
+				   netdev_feature_test(NETIF_F_LOOPBACK_BIT, features));
 
 	return enetc_set_features(ndev, features);
 }
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 57cf1d83d125..eff0f772892a 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1567,7 +1567,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 
 		/* If this is a VLAN packet remove the VLAN Tag */
 		vlan_packet_rcvd = false;
-		if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+		if (netdev_active_feature_test(ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 		    fep->bufdesc_ex &&
 		    (ebdp->cbd_esc & cpu_to_fec32(BD_ENET_RX_VLAN))) {
 			/* Push and remove the vlan tag */
@@ -3383,8 +3383,8 @@ static inline void fec_enet_set_netdev_features(struct net_device *netdev,
 	netdev->features = features;
 
 	/* Receive checksum has been changed */
-	if (changed & NETIF_F_RXCSUM) {
-		if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 			fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
 		else
 			fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;
@@ -3397,7 +3397,7 @@ static int fec_set_features(struct net_device *netdev,
 	struct fec_enet_private *fep = netdev_priv(netdev);
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
-	if (netif_running(netdev) && changed & NETIF_F_RXCSUM) {
+	if (netif_running(netdev) && netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		napi_disable(&fep->napi);
 		netif_tx_lock_bh(netdev);
 		fec_stop(netdev);
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 18efcb947d0f..4f7c3d086bc4 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -161,8 +161,8 @@ static void gfar_rx_offload_en(struct gfar_private *priv)
 	/* set this when rx hw offload (TOE) functions are being used */
 	priv->uses_rxfcb = 0;
 
-	if (priv->ndev->features & NETIF_F_RXCSUM ||
-	    priv->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(priv->ndev, NETIF_F_RXCSUM_BIT) ||
+	    netdev_active_feature_test(priv->ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		priv->uses_rxfcb = 1;
 
 	if (priv->hwts_rx_en || priv->rx_filer_enable)
@@ -184,7 +184,7 @@ static void gfar_mac_rx_config(struct gfar_private *priv)
 	if (priv->ndev->flags & IFF_PROMISC)
 		rctrl |= RCTRL_PROM;
 
-	if (priv->ndev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(priv->ndev, NETIF_F_RXCSUM_BIT))
 		rctrl |= RCTRL_CHECKSUMMING;
 
 	if (priv->extended_hash)
@@ -199,7 +199,7 @@ static void gfar_mac_rx_config(struct gfar_private *priv)
 	if (priv->hwts_rx_en)
 		rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
 
-	if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(priv->ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
 
 	/* Clear the LFC bit */
@@ -218,7 +218,7 @@ static void gfar_mac_tx_config(struct gfar_private *priv)
 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
 	u32 tctrl = 0;
 
-	if (priv->ndev->features & NETIF_F_IP_CSUM)
+	if (netdev_active_feature_test(priv->ndev, NETIF_F_IP_CSUM_BIT))
 		tctrl |= TCTRL_INIT_CSUM;
 
 	if (priv->prio_sched_en)
@@ -229,7 +229,7 @@ static void gfar_mac_tx_config(struct gfar_private *priv)
 		gfar_write(&regs->tr47wt, DEFAULT_WRRS_WEIGHT);
 	}
 
-	if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_TX)
+	if (netdev_active_feature_test(priv->ndev, NETIF_F_HW_VLAN_CTAG_TX_BIT))
 		tctrl |= TCTRL_VLINS;
 
 	gfar_write(&regs->tctrl, tctrl);
@@ -2483,14 +2483,14 @@ static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb)
 	/* Trim off the FCS */
 	pskb_trim(skb, skb->len - ETH_FCS_LEN);
 
-	if (ndev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT))
 		gfar_rx_checksum(skb, fcb);
 
 	/* There's need to check for NETIF_F_HW_VLAN_CTAG_RX here.
 	 * Even if vlan rx accel is disabled, on some chips
 	 * RXFCB_VLN is pseudo randomly set.
 	 */
-	if (ndev->features & NETIF_F_HW_VLAN_CTAG_RX &&
+	if (netdev_active_feature_test(ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	    be16_to_cpu(fcb->flags) & RXFCB_VLN)
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
 				       be16_to_cpu(fcb->vlctl));
@@ -3271,7 +3271,7 @@ static int gfar_probe(struct platform_device *ofdev)
 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
 		priv->padding = 8 + DEFAULT_PADDING;
 
-	if (dev->features & NETIF_F_IP_CSUM ||
+	if (netdev_active_feature_test(dev, NETIF_F_IP_CSUM_BIT) ||
 	    priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
 		dev->needed_headroom = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
 
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 47e644b65ac7..01e9e7aba739 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -513,7 +513,7 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features)
 	int err = 0;
 
 	if (!(changed & netdev_ctag_vlan_offload_features) &&
-	    !(changed & NETIF_F_RXCSUM))
+	    !netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
 	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_rx.c b/drivers/net/ethernet/fungible/funeth/funeth_rx.c
index 29a6c2ede43a..fcd72a474ee2 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_rx.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_rx.c
@@ -432,10 +432,10 @@ static void fun_handle_cqe_pkt(struct funeth_rxq *q, struct funeth_txq *xdp_q)
 
 	skb_record_rx_queue(skb, q->qidx);
 	cv = be16_to_cpu(rxreq->pkt_cv);
-	if (likely((q->netdev->features & NETIF_F_RXHASH) && rxreq->hash))
+	if (likely(netdev_active_feature_test(q->netdev, NETIF_F_RXHASH_BIT) && rxreq->hash))
 		skb_set_hash(skb, be32_to_cpu(rxreq->hash),
 			     cqe_to_pkt_hash_type(cv));
-	if (likely((q->netdev->features & NETIF_F_RXCSUM) && rxreq->csum)) {
+	if (likely(netdev_active_feature_test(q->netdev, NETIF_F_RXCSUM_BIT) && rxreq->csum)) {
 		FUN_QSTAT_INC(q, rx_cso);
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 		skb->csum_level = be16_to_cpu(rxreq->csum) - 1;
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index b8de076f079d..2beb96806dfc 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -564,7 +564,7 @@ static int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index)
 		cmd.create_rx_queue.rx_buff_ring_size =
 			cpu_to_be16(priv->options_dqo_rda.rx_buff_ring_entries);
 		cmd.create_rx_queue.enable_rsc =
-			!!(priv->dev->features & NETIF_F_LRO);
+			netdev_active_feature_test(priv->dev, NETIF_F_LRO_BIT);
 	}
 
 	return gve_adminq_issue_cmd(priv, &cmd);
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index dd7bc0374d6f..890003c6425e 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -1185,7 +1185,8 @@ static int gve_set_features(struct net_device *netdev,
 	struct gve_priv *priv = netdev_priv(netdev);
 	int err;
 
-	if ((netdev->features & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
+	if (netdev_active_feature_test(netdev, NETIF_F_LRO_BIT) !=
+	    netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 		netdev_active_feature_change(netdev, NETIF_F_LRO_BIT);
 		if (netif_carrier_ok(netdev)) {
 			/* To make this process as simple as possible we
diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c
index 021bbf308d68..5f479566011c 100644
--- a/drivers/net/ethernet/google/gve/gve_rx.c
+++ b/drivers/net/ethernet/google/gve/gve_rx.c
@@ -592,7 +592,7 @@ static bool gve_rx(struct gve_rx_ring *rx, netdev_features_t feat,
 		desc = &rx->desc.desc_ring[idx];
 	}
 
-	if (likely(feat & NETIF_F_RXCSUM)) {
+	if (likely(netdev_feature_test(NETIF_F_RXCSUM_BIT, feat))) {
 		/* NIC passes up the partial sum */
 		if (first_desc->csum)
 			skb->ip_summed = CHECKSUM_COMPLETE;
@@ -602,7 +602,7 @@ static bool gve_rx(struct gve_rx_ring *rx, netdev_features_t feat,
 	}
 
 	/* parse flags & pass relevant info up */
-	if (likely(feat & NETIF_F_RXHASH) &&
+	if (likely(netdev_feature_test(NETIF_F_RXHASH_BIT, feat)) &&
 	    gve_needs_rss(first_desc->flags_seq))
 		skb_set_hash(skb, be32_to_cpu(first_desc->rss_hash),
 			     gve_rss_type(first_desc->flags_seq));
diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
index 8c939628e2d8..edff4d162236 100644
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -637,10 +637,10 @@ static int gve_rx_complete_skb(struct gve_rx_ring *rx, struct napi_struct *napi,
 
 	skb_record_rx_queue(rx->ctx.skb_head, rx->q_num);
 
-	if (feat & NETIF_F_RXHASH)
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, feat))
 		gve_rx_skb_hash(rx->ctx.skb_head, desc, ptype);
 
-	if (feat & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, feat))
 		gve_rx_skb_csum(rx->ctx.skb_head, desc, ptype);
 
 	/* RSC packets must set gso_size otherwise the TCP stack will complain
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 837ff9f4e131..dbce348ca438 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -478,7 +478,7 @@ static void hns_nic_rx_checksum(struct hns_nic_ring_data *ring_data,
 	u32 l4id;
 
 	/* check if RX checksum offload is enabled */
-	if (unlikely(!(netdev->features & NETIF_F_RXCSUM)))
+	if (unlikely(!(netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT))))
 		return;
 
 	/* In hardware, we only support checksum for the following protocols:
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index a1363608a3fc..0a9e434e32c8 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.
@@ -2412,36 +2413,41 @@ static int hns3_nic_set_features(struct net_device *netdev,
 	bool enable;
 	int ret;
 
-	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;
@@ -3900,7 +3906,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))
@@ -4191,7 +4197,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 4c7988e308a2..cb519c2b3dc9 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/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index c6c7087971ee..807bcaec8d14 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -870,7 +870,7 @@ static netdev_features_t hinic_fix_features(struct net_device *netdev,
 	struct hinic_dev *nic_dev = netdev_priv(netdev);
 
 	/* If Rx checksum is disabled, then LRO should also be disabled */
-	if (!(features & NETIF_F_RXCSUM)) {
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
 		netif_info(nic_dev, drv, netdev, "disabling LRO as RXCSUM is off\n");
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 	}
@@ -1083,8 +1083,9 @@ static int set_features(struct hinic_dev *nic_dev,
 	else
 		changed = netdev_features_xor(pre_features, features);
 
-	if (changed & NETIF_F_TSO) {
-		ret = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ?
+	if (netdev_feature_test(NETIF_F_TSO_BIT, changed)) {
+		ret = hinic_port_set_tso(nic_dev,
+					 netdev_feature_test(NETIF_F_TSO_BIT, features) ?
 					 HINIC_TSO_ENABLE : HINIC_TSO_DISABLE);
 		if (ret) {
 			err = ret;
@@ -1092,7 +1093,7 @@ static int set_features(struct hinic_dev *nic_dev,
 		}
 	}
 
-	if (changed & NETIF_F_RXCSUM) {
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		ret = hinic_set_rx_csum_offload(nic_dev, csum_en);
 		if (ret) {
 			err = ret;
@@ -1101,9 +1102,9 @@ static int set_features(struct hinic_dev *nic_dev,
 		}
 	}
 
-	if (changed & NETIF_F_LRO) {
+	if (netdev_feature_test(NETIF_F_LRO_BIT, changed)) {
 		ret = hinic_set_rx_lro_state(nic_dev,
-					     !!(features & NETIF_F_LRO),
+					     netdev_feature_test(NETIF_F_LRO_BIT, features),
 					     HINIC_LRO_RX_TIMER_DEFAULT,
 					     HINIC_LRO_MAX_WQE_NUM_DEFAULT);
 		if (ret) {
@@ -1112,10 +1113,10 @@ static int set_features(struct hinic_dev *nic_dev,
 		}
 	}
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed)) {
 		ret = hinic_set_rx_vlan_offload(nic_dev,
-						!!(features &
-						   NETIF_F_HW_VLAN_CTAG_RX));
+						netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+								    features));
 		if (ret) {
 			err = ret;
 			netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
index a866bea65110..7bd76075a851 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
@@ -104,7 +104,7 @@ static void rx_csum(struct hinic_rxq *rxq, u32 status,
 
 	csum_err = HINIC_RQ_CQE_STATUS_GET(status, CSUM_ERR);
 
-	if (!(netdev->features & NETIF_F_RXCSUM))
+	if (!(netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)))
 		return;
 
 	if (!csum_err) {
@@ -409,7 +409,7 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget)
 
 		offload_type = be32_to_cpu(cqe->offload_type);
 		vlan_len = be32_to_cpu(cqe->len);
-		if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+		if ((netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) &&
 		    HINIC_GET_RX_VLAN_OFFLOAD_EN(offload_type)) {
 			vid = HINIC_GET_RX_VLAN_TAG(vlan_len);
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 2319507d6731..1f4e5a7d1f95 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -743,7 +743,7 @@ static netdev_features_t ibmveth_fix_features(struct net_device *dev,
 	 * checksummed.
 	 */
 
-	if (!(features & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		netdev_features_clear(&features, NETIF_F_CSUM_MASK);
 
 	return features;
@@ -903,7 +903,7 @@ static int ibmveth_set_features(struct net_device *dev,
 	netdev_features_t features)
 {
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
-	int rx_csum = !!(features & NETIF_F_RXCSUM);
+	int rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
 	int large_send = !!(features & netdev_general_tso_features);
 	int rc1 = 0, rc2 = 0;
 
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 8e1b8fe9a04f..e3e06bda2990 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -1115,7 +1115,7 @@ static int e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 		config->promiscuous_mode = 0x1;		/* 1=on, 0=off */
 	}
 
-	if (unlikely(netdev->features & NETIF_F_RXFCS))
+	if (unlikely(netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT)))
 		config->rx_crc_transfer = 0x1;	/* 1=save, 0=discard */
 
 	if (nic->flags & multicast_all)
@@ -1142,7 +1142,7 @@ static int e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 		}
 	}
 
-	if (netdev->features & NETIF_F_RXALL) {
+	if (netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)) {
 		config->rx_save_overruns = 0x1; /* 1=save, 0=discard */
 		config->rx_save_bad_frames = 0x1;       /* 1=save, 0=discard */
 		config->rx_discard_short_frames = 0x0;  /* 1=discard, 0=save */
@@ -1990,7 +1990,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
 	}
 
 	/* Get actual data size */
-	if (unlikely(dev->features & NETIF_F_RXFCS))
+	if (unlikely(netdev_active_feature_test(dev, NETIF_F_RXFCS_BIT)))
 		fcs_pad = 4;
 	actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
 	if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
@@ -2021,7 +2021,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
 	/* If we are receiving all frames, then don't bother
 	 * checking for errors.
 	 */
-	if (unlikely(dev->features & NETIF_F_RXALL)) {
+	if (unlikely(netdev_active_feature_test(dev, NETIF_F_RXALL_BIT))) {
 		if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN + fcs_pad)
 			/* Received oversized frame, but keep it. */
 			nic->rx_over_length_errors++;
@@ -2806,7 +2806,8 @@ static int e100_set_features(struct net_device *netdev,
 	struct nic *nic = netdev_priv(netdev);
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
-	if (!(changed & NETIF_F_RXFCS && changed & NETIF_F_RXALL))
+	if (!(netdev_feature_test(NETIF_F_RXFCS_BIT, changed) &&
+	      netdev_feature_test(NETIF_F_RXALL_BIT, changed)))
 		return 0;
 
 	netdev->features = features;
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index af3fe857ec4e..2e5800cc390b 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -793,7 +793,7 @@ static netdev_features_t e1000_fix_features(struct net_device *netdev,
 	/* Since there is no support for separate Rx/Tx vlan accel
 	 * enable/disable make sure Tx flag is always in same state as Rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -807,14 +807,15 @@ static int e1000_set_features(struct net_device *netdev,
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		e1000_vlan_mode(netdev, features);
 
-	if (!(changed & NETIF_F_RXCSUM && changed & NETIF_F_RXALL))
+	if (!(netdev_feature_test(NETIF_F_RXCSUM_BIT, changed) &&
+	      netdev_feature_test(NETIF_F_RXALL_BIT, changed)))
 		return 0;
 
 	netdev->features = features;
-	adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
+	adapter->rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
 
 	if (netif_running(netdev))
 		e1000_reinit_locked(adapter);
@@ -1835,7 +1836,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
 	}
 
 	/* This is useful for sniffing bad packets. */
-	if (adapter->netdev->features & NETIF_F_RXALL) {
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_RXALL_BIT)) {
 		/* UPE and MPE will be handled by normal PROMISC logic
 		 * in e1000e_set_rx_mode
 		 */
@@ -4191,7 +4192,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
 						    rx_desc->errors,
 						    length, mapped)) {
 				length--;
-			} else if (netdev->features & NETIF_F_RXALL) {
+			} else if (netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)) {
 				goto process_skb;
 			} else {
 				/* an error means any chain goes out the window
@@ -4242,7 +4243,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
 				if (length <= copybreak) {
 					u8 *vaddr;
 
-					if (likely(!(netdev->features & NETIF_F_RXFCS)))
+					if (likely(!netdev_active_feature_test(netdev,
+									       NETIF_F_RXFCS_BIT)))
 						length -= 4;
 					skb = e1000_alloc_rx_skb(adapter,
 								 length);
@@ -4288,7 +4290,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
 				  le16_to_cpu(rx_desc->csum), skb);
 
 		total_rx_bytes += (skb->len - 4); /* don't count FCS */
-		if (likely(!(netdev->features & NETIF_F_RXFCS)))
+		if (likely(!(netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT))))
 			pskb_trim(skb, skb->len - 4);
 		total_rx_packets++;
 
@@ -4443,7 +4445,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 						    rx_desc->errors,
 						    length, data)) {
 				length--;
-			} else if (netdev->features & NETIF_F_RXALL) {
+			} else if (netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)) {
 				goto process_skb;
 			} else {
 				dev_kfree_skb(skb);
@@ -4455,7 +4457,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 		total_rx_bytes += (length - 4); /* don't count FCS */
 		total_rx_packets++;
 
-		if (likely(!(netdev->features & NETIF_F_RXFCS)))
+		if (likely(!(netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT))))
 			/* adjust length to remove Ethernet CRC, this must be
 			 * done after the TBI_ACCEPT workaround above
 			 */
@@ -4903,7 +4905,7 @@ static void __e1000_vlan_mode(struct e1000_adapter *adapter,
 	u32 ctrl;
 
 	ctrl = er32(CTRL);
-	if (features & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
 		/* enable VLAN tag insert/strip */
 		ctrl |= E1000_CTRL_VME;
 	} else {
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 22cfd3fcbf1a..c164802ab58d 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -579,7 +579,7 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
 	skb_checksum_none_assert(skb);
 
 	/* Rx checksum disabled */
-	if (!(adapter->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(adapter->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* Ignore Checksum bit is set */
@@ -897,7 +897,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_ring *rx_ring,
 static inline void e1000_rx_hash(struct net_device *netdev, __le32 rss,
 				 struct sk_buff *skb)
 {
-	if (netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT))
 		skb_set_hash(skb, le32_to_cpu(rss), PKT_HASH_TYPE_L3);
 }
 
@@ -979,7 +979,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 		}
 
 		if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
-			     !(netdev->features & NETIF_F_RXALL))) {
+			     !netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT))) {
 			/* recycle */
 			buffer_info->skb = skb;
 			goto next_desc;
@@ -991,7 +991,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 			 * but keep the FCS bytes out of the total_rx_bytes
 			 * counter
 			 */
-			if (netdev->features & NETIF_F_RXFCS)
+			if (netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT))
 				total_rx_bytes -= 4;
 			else
 				length -= 4;
@@ -1365,7 +1365,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
 		}
 
 		if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
-			     !(netdev->features & NETIF_F_RXALL))) {
+			     !netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT))) {
 			dev_kfree_skb_irq(skb);
 			goto next_desc;
 		}
@@ -1416,7 +1416,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
 
 				/* remove the CRC */
 				if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
-					if (!(netdev->features & NETIF_F_RXFCS))
+					if (!netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT))
 						l1 -= 4;
 				}
 
@@ -1445,7 +1445,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
 		 * this whole operation can get a little cpu intensive
 		 */
 		if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
-			if (!(netdev->features & NETIF_F_RXFCS))
+			if (!netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT))
 				pskb_trim(skb, skb->len - 4);
 		}
 
@@ -1560,7 +1560,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 		/* errors is only valid for DD + EOP descriptors */
 		if (unlikely((staterr & E1000_RXD_STAT_EOP) &&
 			     ((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
-			      !(netdev->features & NETIF_F_RXALL)))) {
+			      !netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)))) {
 			/* recycle both page and skb */
 			buffer_info->skb = skb;
 			/* an error means any chain goes out the window too */
@@ -3167,7 +3167,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
 	}
 
 	/* This is useful for sniffing bad packets. */
-	if (adapter->netdev->features & NETIF_F_RXALL) {
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_RXALL_BIT)) {
 		/* UPE and MPE will be handled by normal PROMISC logic
 		 * in e1000e_set_rx_mode
 		 */
@@ -3272,7 +3272,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
 
 	/* Enable Receive Checksum Offload for TCP and UDP */
 	rxcsum = er32(RXCSUM);
-	if (adapter->netdev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_RXCSUM_BIT))
 		rxcsum |= E1000_RXCSUM_TUOFL;
 	else
 		rxcsum &= ~E1000_RXCSUM_TUOFL;
@@ -3453,7 +3453,7 @@ static void e1000e_set_rx_mode(struct net_device *netdev)
 
 	ew32(RCTL, rctl);
 
-	if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		e1000e_vlan_strip_enable(adapter);
 	else
 		e1000e_vlan_strip_disable(adapter);
@@ -3763,7 +3763,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
 
 	e1000_configure_tx(adapter);
 
-	if (adapter->netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_RXHASH_BIT))
 		e1000e_setup_rss_hash(adapter);
 	e1000_setup_rctl(adapter);
 	e1000_configure_rx(adapter);
@@ -7304,7 +7304,7 @@ static netdev_features_t e1000_fix_features(struct net_device *netdev,
 	/* Since there is no support for separate Rx/Tx vlan accel
 	 * enable/disable make sure Tx flag is always in same state as Rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -7335,8 +7335,8 @@ static int e1000_set_features(struct net_device *netdev,
 	if (!(changed & changeable))
 		return 0;
 
-	if (changed & NETIF_F_RXFCS) {
-		if (features & NETIF_F_RXFCS) {
+	if (netdev_feature_test(NETIF_F_RXFCS_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features)) {
 			adapter->flags2 &= ~FLAG2_CRC_STRIPPING;
 		} else {
 			/* We need to take it back to defaults, which might mean
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index db6501c8ea39..2f1e5af847f2 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -352,7 +352,7 @@ static inline void fm10k_rx_checksum(struct fm10k_ring *ring,
 	skb_checksum_none_assert(skb);
 
 	/* Rx checksum disabled via ethtool */
-	if (!(ring->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* TCP/UDP checksum error bit is set */
@@ -388,7 +388,7 @@ static inline void fm10k_rx_hash(struct fm10k_ring *ring,
 {
 	u16 rss_type;
 
-	if (!(ring->netdev->features & NETIF_F_RXHASH))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXHASH_BIT))
 		return;
 
 	rss_type = le16_to_cpu(rx_desc->w.pkt_info) & FM10K_RXD_RSSTYPE_MASK;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index e9008e997a3e..85c3faee4f72 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -3232,7 +3232,7 @@ static void i40e_restore_vlan(struct i40e_vsi *vsi)
 	if (!vsi->netdev)
 		return;
 
-	if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(vsi->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		i40e_vlan_stripping_enable(vsi);
 	else
 		i40e_vlan_stripping_disable(vsi);
@@ -12855,7 +12855,7 @@ bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features)
 	/* Check if Flow Director n-tuple support was enabled or disabled.  If
 	 * the state changed, we need to reset.
 	 */
-	if (features & NETIF_F_NTUPLE) {
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, features)) {
 		/* Enable filters and mark for reset */
 		if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
 			need_reset = true;
@@ -12924,25 +12924,27 @@ static int i40e_set_features(struct net_device *netdev,
 	struct i40e_pf *pf = vsi->back;
 	bool need_reset;
 
-	if (features & NETIF_F_RXHASH && !(netdev->features & NETIF_F_RXHASH))
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features) &&
+	    !netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT))
 		i40e_pf_config_rss(pf);
-	else if (!(features & NETIF_F_RXHASH) &&
-		 netdev->features & NETIF_F_RXHASH)
+	else if (!netdev_feature_test(NETIF_F_RXHASH_BIT, features) &&
+		 netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT))
 		i40e_clear_rss_lut(vsi);
 
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		i40e_vlan_stripping_enable(vsi);
 	else
 		i40e_vlan_stripping_disable(vsi);
 
-	if (!(features & NETIF_F_HW_TC) &&
-	    (netdev->features & NETIF_F_HW_TC) && pf->num_cloud_filters) {
+	if (!netdev_feature_test(NETIF_F_HW_TC_BIT, features) &&
+	    netdev_active_feature_test(netdev, NETIF_F_HW_TC_BIT) &&
+	    pf->num_cloud_filters) {
 		dev_err(&pf->pdev->dev,
 			"Offloaded tc filters active, can't turn hw_tc_offload off");
 		return -EINVAL;
 	}
 
-	if (!(features & NETIF_F_HW_L2FW_DOFFLOAD) && vsi->macvlan_cnt)
+	if (!netdev_feature_test(NETIF_F_HW_L2FW_DOFFLOAD_BIT, features) && vsi->macvlan_cnt)
 		i40e_del_all_macvlans(vsi);
 
 	need_reset = i40e_set_ntuple(pf, features);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index f6ba97a0166e..8c4ad5a32983 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1780,7 +1780,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
 	skb_checksum_none_assert(skb);
 
 	/* Rx csum enabled and ip headers found? */
-	if (!(vsi->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(vsi->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* did the hardware decode the packet and checksum? */
@@ -1882,7 +1882,7 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,
 		cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
 			    I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
 
-	if (!(ring->netdev->features & NETIF_F_RXHASH))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXHASH_BIT))
 		return;
 
 	if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
@@ -2944,7 +2944,7 @@ static inline int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
 	u32  tx_flags = 0;
 
 	if (protocol == htons(ETH_P_8021Q) &&
-	    !(tx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) {
+	    !netdev_active_feature_test(tx_ring->netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT)) {
 		/* When HW VLAN acceleration is turned off by the user the
 		 * stack sets the protocol to 8021q so that the driver
 		 * can take any steps required to support the SW only
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index a21cde0c2bbb..b59cc9891fce 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2572,7 +2572,7 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
 				 err);
 	}
 	dev_info(&pdev->dev, "MAC address: %pM\n", adapter->hw.mac.addr);
-	if (netdev->features & NETIF_F_GRO)
+	if (netdev_active_feature_test(netdev, NETIF_F_GRO_BIT))
 		dev_info(&pdev->dev, "GRO is enabled\n");
 
 	iavf_change_state(adapter, __IAVF_DOWN);
@@ -4691,17 +4691,17 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	 * TSO needs minimum 576 bytes to work correctly.
 	 */
 	if (netdev->wanted_features) {
-		if (!(netdev->wanted_features & NETIF_F_TSO) ||
+		if (!netdev_wanted_feature_test(netdev, NETIF_F_TSO_BIT) ||
 		    netdev->mtu < 576)
 			netdev_active_feature_del(netdev, NETIF_F_TSO_BIT);
-		if (!(netdev->wanted_features & NETIF_F_TSO6) ||
+		if (!netdev_wanted_feature_test(netdev, NETIF_F_TSO6_BIT) ||
 		    netdev->mtu < 576)
 			netdev_active_feature_del(netdev, NETIF_F_TSO6_BIT);
-		if (!(netdev->wanted_features & NETIF_F_TSO_ECN))
+		if (!netdev_wanted_feature_test(netdev, NETIF_F_TSO_ECN_BIT))
 			netdev_active_feature_del(netdev, NETIF_F_TSO_ECN_BIT);
-		if (!(netdev->wanted_features & NETIF_F_GRO))
+		if (!netdev_wanted_feature_test(netdev, NETIF_F_GRO_BIT))
 			netdev_active_feature_del(netdev, NETIF_F_GRO_BIT);
-		if (!(netdev->wanted_features & NETIF_F_GSO))
+		if (!netdev_wanted_feature_test(netdev, NETIF_F_GSO_BIT))
 			netdev_active_feature_del(netdev, NETIF_F_GSO_BIT);
 	}
 
diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
index 06d18797d25a..795faa0ca0b4 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
@@ -894,10 +894,10 @@ static void iavf_receive_skb(struct iavf_ring *rx_ring,
 {
 	struct iavf_q_vector *q_vector = rx_ring->q_vector;
 
-	if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (netdev_active_feature_test(rx_ring->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	    (vlan_tag & VLAN_VID_MASK))
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
-	else if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_STAG_RX) &&
+	else if (netdev_active_feature_test(rx_ring->netdev, NETIF_F_HW_VLAN_STAG_RX_BIT) &&
 		 vlan_tag & VLAN_VID_MASK)
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), vlan_tag);
 
@@ -998,7 +998,7 @@ static inline void iavf_rx_checksum(struct iavf_vsi *vsi,
 	skb_checksum_none_assert(skb);
 
 	/* Rx csum enabled and ip headers found? */
-	if (!(vsi->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(vsi->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* did the hardware decode the packet and checksum? */
@@ -1093,7 +1093,7 @@ static inline void iavf_rx_hash(struct iavf_ring *ring,
 		cpu_to_le64((u64)IAVF_RX_DESC_FLTSTAT_RSS_HASH <<
 			    IAVF_RX_DESC_STATUS_FLTSTAT_SHIFT);
 
-	if (ring->netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(ring->netdev, NETIF_F_RXHASH_BIT))
 		return;
 
 	if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 9b9c73817692..088719732394 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -433,8 +433,8 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
 						IFF_PROMISC;
 					goto out_promisc;
 				}
-				if (vsi->netdev->features &
-				    NETIF_F_HW_VLAN_CTAG_FILTER)
+				if (netdev_active_feature_test(vsi->netdev,
+							       NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 					vlan_ops->ena_rx_filtering(vsi);
 			}
 		}
@@ -5781,12 +5781,16 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 	bool cur_ctag, cur_stag, req_ctag, req_stag;
 
 	cur_vlan_fltr = netdev->features & NETIF_VLAN_FILTERING_FEATURES;
-	cur_ctag = cur_vlan_fltr & NETIF_F_HW_VLAN_CTAG_FILTER;
-	cur_stag = cur_vlan_fltr & NETIF_F_HW_VLAN_STAG_FILTER;
+	cur_ctag = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				       cur_vlan_fltr);
+	cur_stag = netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
+				       cur_vlan_fltr);
 
 	req_vlan_fltr = features & NETIF_VLAN_FILTERING_FEATURES;
-	req_ctag = req_vlan_fltr & NETIF_F_HW_VLAN_CTAG_FILTER;
-	req_stag = req_vlan_fltr & NETIF_F_HW_VLAN_STAG_FILTER;
+	req_ctag = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				       req_vlan_fltr);
+	req_stag = netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
+				       req_vlan_fltr);
 
 	if (req_vlan_fltr != cur_vlan_fltr) {
 		if (ice_is_dvm_ena(&np->vsi->back->hw)) {
@@ -5808,10 +5812,10 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 				netdev_warn(netdev,  "802.1Q and 802.1ad VLAN filtering must be either both on or both off. VLAN filtering has been disabled for both types.\n");
 			}
 		} else {
-			if (req_vlan_fltr & NETIF_F_HW_VLAN_STAG_FILTER)
+			if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT, req_vlan_fltr))
 				netdev_warn(netdev, "cannot support requested 802.1ad filtering setting in SVM mode\n");
 
-			if (req_vlan_fltr & NETIF_F_HW_VLAN_CTAG_FILTER)
+			if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, req_vlan_fltr))
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 						   &features);
 		}
@@ -5992,35 +5996,37 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
 	/* Multiple features can be changed in one call so keep features in
 	 * separate if/else statements to guarantee each feature is checked
 	 */
-	if (changed & NETIF_F_RXHASH)
-		ice_vsi_manage_rss_lut(vsi, !!(features & NETIF_F_RXHASH));
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, changed))
+		ice_vsi_manage_rss_lut(vsi,
+				       netdev_feature_test(NETIF_F_RXHASH_BIT, features));
 
 	ret = ice_set_vlan_features(netdev, features);
 	if (ret)
 		return ret;
 
-	if (changed & NETIF_F_NTUPLE) {
-		bool ena = !!(features & NETIF_F_NTUPLE);
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed)) {
+		bool ena = netdev_feature_test(NETIF_F_NTUPLE_BIT, features);
 
 		ice_vsi_manage_fdir(vsi, ena);
 		ena ? ice_init_arfs(vsi) : ice_clear_arfs(vsi);
 	}
 
 	/* don't turn off hw_tc_offload when ADQ is already enabled */
-	if (!(features & NETIF_F_HW_TC) && ice_is_adq_active(pf)) {
+	if (!netdev_feature_test(NETIF_F_HW_TC_BIT, features) && ice_is_adq_active(pf)) {
 		dev_err(ice_pf_to_dev(pf), "ADQ is active, can't turn hw_tc_offload off\n");
 		return -EACCES;
 	}
 
-	if (changed & NETIF_F_HW_TC) {
-		bool ena = !!(features & NETIF_F_HW_TC);
+	if (netdev_feature_test(NETIF_F_HW_TC_BIT, changed)) {
+		bool ena = netdev_feature_test(NETIF_F_HW_TC_BIT, features);
 
 		ena ? set_bit(ICE_FLAG_CLS_FLOWER, pf->flags) :
 		      clear_bit(ICE_FLAG_CLS_FLOWER, pf->flags);
 	}
 
-	if (changed & NETIF_F_LOOPBACK)
-		ret = ice_set_loopback(vsi, !!(features & NETIF_F_LOOPBACK));
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed))
+		ret = ice_set_loopback(vsi,
+				       netdev_feature_test(NETIF_F_LOOPBACK_BIT, features));
 
 	return ret;
 }
@@ -8229,7 +8235,7 @@ static void ice_remove_q_channels(struct ice_vsi *vsi, bool rem_fltr)
 		ice_rem_all_chnl_fltrs(pf);
 
 	/* remove ntuple filters since queue configuration is being changed */
-	if  (vsi->netdev->features & NETIF_F_NTUPLE) {
+	if  (netdev_active_feature_test(vsi->netdev, NETIF_F_NTUPLE_BIT)) {
 		struct ice_hw *hw = &pf->hw;
 
 		mutex_lock(&hw->fdir_fltr_lock);
@@ -8509,7 +8515,7 @@ static int ice_setup_tc_mqprio_qdisc(struct net_device *netdev, void *type_data)
 		 * and set the flag for TC flower filter if hw_tc_offload
 		 * already ON
 		 */
-		if (vsi->netdev->features & NETIF_F_HW_TC)
+		if (netdev_active_feature_test(vsi->netdev, NETIF_F_HW_TC_BIT))
 			set_bit(ICE_FLAG_CLS_FLOWER, pf->flags);
 		break;
 	default:
diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
index a298862857a8..bcb31c54a095 100644
--- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
@@ -1538,7 +1538,7 @@ ice_add_cls_flower(struct net_device *netdev, struct ice_vsi *vsi,
 	if (ice_is_port_repr_netdev(netdev))
 		vsi_netdev = netdev;
 
-	if (!(vsi_netdev->features & NETIF_F_HW_TC) &&
+	if (!(netdev_active_feature_test(vsi_netdev, NETIF_F_HW_TC_BIT)) &&
 	    !test_bit(ICE_FLAG_CLS_FLOWER, pf->flags)) {
 		/* Based on TC indirect notifications from kernel, all ice
 		 * devices get an instance of rule from higher level device.
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
index 7ee38d02d1e5..7bade466c0e5 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
@@ -76,7 +76,7 @@ ice_rx_hash(struct ice_rx_ring *rx_ring, union ice_32b_rx_flex_desc *rx_desc,
 	struct ice_32b_rx_flex_desc_nic *nic_mdid;
 	u32 hash;
 
-	if (!(rx_ring->netdev->features & NETIF_F_RXHASH))
+	if (!netdev_active_feature_test(rx_ring->netdev, NETIF_F_RXHASH_BIT))
 		return;
 
 	if (rx_desc->wb.rxdid != ICE_RXDID_FLEX_NIC)
@@ -114,7 +114,7 @@ ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb,
 	skb_checksum_none_assert(skb);
 
 	/* check if Rx checksum is enabled */
-	if (!(ring->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* check if HW has decoded the packet and checksum */
@@ -212,9 +212,9 @@ ice_receive_skb(struct ice_rx_ring *rx_ring, struct sk_buff *skb, u16 vlan_tag)
 	netdev_features_t features = rx_ring->netdev->features;
 	bool non_zero_vlan = !!(vlan_tag & VLAN_VID_MASK);
 
-	if ((features & NETIF_F_HW_VLAN_CTAG_RX) && non_zero_vlan)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) && non_zero_vlan)
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
-	else if ((features & NETIF_F_HW_VLAN_STAG_RX) && non_zero_vlan)
+	else if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_RX_BIT, features) && non_zero_vlan)
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), vlan_tag);
 
 	napi_gro_receive(&rx_ring->q_vector->napi, skb);
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index c14fc871dd41..2db7651fd292 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2901,7 +2901,7 @@ static int igb_add_ethtool_nfc_entry(struct igb_adapter *adapter,
 	struct igb_nfc_filter *input, *rule;
 	int err = 0;
 
-	if (!(netdev->hw_features & NETIF_F_NTUPLE))
+	if (!(netdev_hw_feature_test(netdev, NETIF_F_NTUPLE_BIT)))
 		return -EOPNOTSUPP;
 
 	/* Don't allow programming if the action is a queue greater than
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index a87a0701bce1..e543639a9c76 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2438,7 +2438,7 @@ static netdev_features_t igb_fix_features(struct net_device *netdev,
 	/* Since there is no support for separate Rx/Tx vlan accel
 	 * enable/disable make sure Tx flag is always in same state as Rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -2453,13 +2453,14 @@ static int igb_set_features(struct net_device *netdev,
 							       features);
 	struct igb_adapter *adapter = netdev_priv(netdev);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		igb_vlan_mode(netdev, features);
 
-	if (!(changed & NETIF_F_RXALL) && !(changed & NETIF_F_NTUPLE))
+	if (!netdev_feature_test(NETIF_F_RXALL_BIT, changed) &&
+	    !netdev_feature_test(NETIF_F_NTUPLE_BIT, changed))
 		return 0;
 
-	if (!(features & NETIF_F_NTUPLE)) {
+	if (!netdev_feature_test(NETIF_F_NTUPLE_BIT, features)) {
 		struct hlist_node *node2;
 		struct igb_nfc_filter *rule;
 
@@ -2543,7 +2544,7 @@ igb_features_check(struct sk_buff *skb, struct net_device *dev,
 	/* We can only support IPV4 TSO in tunnels if we can mangle the
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
 	 */
-	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features))
 		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	return features;
@@ -4567,7 +4568,7 @@ void igb_setup_rctl(struct igb_adapter *adapter)
 	}
 
 	/* This is useful for sniffing bad packets. */
-	if (adapter->netdev->features & NETIF_F_RXALL) {
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_RXALL_BIT)) {
 		/* UPE and MPE will be handled by normal PROMISC logic
 		 * in e1000e_set_rx_mode
 		 */
@@ -5076,7 +5077,7 @@ static int igb_vlan_promisc_enable(struct igb_adapter *adapter)
 	case e1000_i211:
 	case e1000_i350:
 		/* VLAN filtering needed for VLAN prio filter */
-		if (adapter->netdev->features & NETIF_F_NTUPLE)
+		if (netdev_active_feature_test(adapter->netdev, NETIF_F_NTUPLE_BIT))
 			break;
 		fallthrough;
 	case e1000_82576:
@@ -5248,7 +5249,7 @@ static void igb_set_rx_mode(struct net_device *netdev)
 
 	/* disable VLAN filtering for modes that require it */
 	if ((netdev->flags & IFF_PROMISC) ||
-	    (netdev->features & NETIF_F_RXALL)) {
+	    netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)) {
 		/* if we fail to set all rules then just clear VFE */
 		if (igb_vlan_promisc_enable(adapter))
 			rctl &= ~E1000_RCTL_VFE;
@@ -8611,7 +8612,7 @@ static inline void igb_rx_checksum(struct igb_ring *ring,
 		return;
 
 	/* Rx checksum disabled via ethtool */
-	if (!(ring->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* TCP/UDP checksum error bit is set */
@@ -8644,7 +8645,7 @@ static inline void igb_rx_hash(struct igb_ring *ring,
 			       union e1000_adv_rx_desc *rx_desc,
 			       struct sk_buff *skb)
 {
-	if (ring->netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(ring->netdev, NETIF_F_RXHASH_BIT))
 		skb_set_hash(skb,
 			     le32_to_cpu(rx_desc->wb.lower.hi_dword.rss),
 			     PKT_HASH_TYPE_L3);
@@ -8702,7 +8703,7 @@ static bool igb_cleanup_headers(struct igb_ring *rx_ring,
 	if (unlikely((igb_test_staterr(rx_desc,
 				       E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) {
 		struct net_device *netdev = rx_ring->netdev;
-		if (!(netdev->features & NETIF_F_RXALL)) {
+		if (!netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)) {
 			dev_kfree_skb_any(skb);
 			return true;
 		}
@@ -8739,7 +8740,7 @@ static void igb_process_skb_fields(struct igb_ring *rx_ring,
 	    !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))
 		igb_ptp_rx_rgtstamp(rx_ring->q_vector, skb);
 
-	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	    igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
 		u16 vid;
 
@@ -9163,7 +9164,7 @@ static void igb_vlan_mode(struct net_device *netdev, netdev_features_t features)
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl, rctl;
-	bool enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX);
+	bool enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features);
 
 	if (enable) {
 		/* enable VLAN tag insert/strip */
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 09a7b7631950..e52421c67d16 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2608,7 +2608,7 @@ static int igbvf_set_features(struct net_device *netdev,
 {
 	struct igbvf_adapter *adapter = netdev_priv(netdev);
 
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
 	else
 		adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
@@ -2655,7 +2655,7 @@ igbvf_features_check(struct sk_buff *skb, struct net_device *dev,
 	/* We can only support IPV4 TSO in tunnels if we can mangle the
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
 	 */
-	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features))
 		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	return features;
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 8cc077b712ad..abb319709be9 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1305,7 +1305,7 @@ static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter,
 	struct igc_nfc_rule *rule, *old_rule;
 	int err;
 
-	if (!(netdev->hw_features & NETIF_F_NTUPLE)) {
+	if (!(netdev_hw_feature_test(netdev, NETIF_F_NTUPLE_BIT))) {
 		netdev_dbg(netdev, "N-tuple filters disabled\n");
 		return -EOPNOTSUPP;
 	}
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 17973b86f3a6..ece12d553acc 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -826,7 +826,7 @@ static void igc_setup_rctl(struct igc_adapter *adapter)
 	wr32(IGC_RXDCTL(0), 0);
 
 	/* This is useful for sniffing bad packets. */
-	if (adapter->netdev->features & NETIF_F_RXALL) {
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_RXALL_BIT)) {
 		/* UPE and MPE will be handled by normal PROMISC logic
 		 * in set_rx_mode
 		 */
@@ -1531,7 +1531,7 @@ static void igc_rx_checksum(struct igc_ring *ring,
 		return;
 
 	/* Rx checksum disabled via ethtool */
-	if (!(ring->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* TCP/UDP checksum error bit is set */
@@ -1564,7 +1564,7 @@ static inline void igc_rx_hash(struct igc_ring *ring,
 			       union igc_adv_rx_desc *rx_desc,
 			       struct sk_buff *skb)
 {
-	if (ring->netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(ring->netdev, NETIF_F_RXHASH_BIT))
 		skb_set_hash(skb,
 			     le32_to_cpu(rx_desc->wb.lower.hi_dword.rss),
 			     PKT_HASH_TYPE_L3);
@@ -1577,7 +1577,7 @@ static void igc_rx_vlan(struct igc_ring *rx_ring,
 	struct net_device *dev = rx_ring->netdev;
 	u16 vid;
 
-	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	    igc_test_staterr(rx_desc, IGC_RXD_STAT_VP)) {
 		if (igc_test_staterr(rx_desc, IGC_RXDEXT_STATERR_LB) &&
 		    test_bit(IGC_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags))
@@ -1616,7 +1616,7 @@ static void igc_process_skb_fields(struct igc_ring *rx_ring,
 
 static void igc_vlan_mode(struct net_device *netdev, netdev_features_t features)
 {
-	bool enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX);
+	bool enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features);
 	struct igc_adapter *adapter = netdev_priv(netdev);
 	struct igc_hw *hw = &adapter->hw;
 	u32 ctrl;
@@ -1914,7 +1914,7 @@ static bool igc_cleanup_headers(struct igc_ring *rx_ring,
 	if (unlikely(igc_test_staterr(rx_desc, IGC_RXDEXT_STATERR_RXE))) {
 		struct net_device *netdev = rx_ring->netdev;
 
-		if (!(netdev->features & NETIF_F_RXALL)) {
+		if (!netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)) {
 			dev_kfree_skb_any(skb);
 			return true;
 		}
@@ -4940,7 +4940,7 @@ static netdev_features_t igc_fix_features(struct net_device *netdev,
 	/* Since there is no support for separate Rx/Tx vlan accel
 	 * enable/disable make sure Tx flag is always in same state as Rx.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
@@ -4955,14 +4955,15 @@ static int igc_set_features(struct net_device *netdev,
 							       features);
 	struct igc_adapter *adapter = netdev_priv(netdev);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		igc_vlan_mode(netdev, features);
 
 	/* Add VLAN support */
-	if (!(changed & NETIF_F_RXALL) && !(changed & NETIF_F_NTUPLE))
+	if (!netdev_feature_test(NETIF_F_RXALL_BIT, changed) &&
+	    !netdev_feature_test(NETIF_F_NTUPLE_BIT, changed))
 		return 0;
 
-	if (!(features & NETIF_F_NTUPLE))
+	if (!netdev_feature_test(NETIF_F_NTUPLE_BIT, features))
 		igc_flush_nfc_rules(adapter);
 
 	netdev->features = features;
@@ -5011,7 +5012,7 @@ igc_features_check(struct sk_buff *skb, struct net_device *dev,
 	/* We can only support IPv4 TSO in tunnels if we can mangle the
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
 	 */
-	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features))
 		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	return features;
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 8186c8e6305e..dbe03de3c12f 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -301,7 +301,7 @@ ixgb_fix_features(struct net_device *netdev, netdev_features_t features)
 	 * Tx VLAN insertion does not work per HW design when Rx stripping is
 	 * disabled.
 	 */
-	if (!(features & NETIF_F_HW_VLAN_CTAG_RX))
+	if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, &features);
 
 	return features;
@@ -313,10 +313,11 @@ ixgb_set_features(struct net_device *netdev, netdev_features_t features)
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
-	if (!(changed & NETIF_F_RXCSUM) && !(changed & NETIF_F_HW_VLAN_CTAG_RX))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, changed) &&
+	    !netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		return 0;
 
-	adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
+	adapter->rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
 
 	if (netif_running(netdev)) {
 		ixgb_down(adapter, true);
@@ -1098,7 +1099,7 @@ ixgb_set_multi(struct net_device *netdev)
 	}
 
 alloc_failed:
-	if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		ixgb_vlan_strip_enable(adapter);
 	else
 		ixgb_vlan_strip_disable(adapter);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index e85f7d2e8810..55ae3e59ee23 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
@@ -317,7 +317,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 		int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
 
 #ifdef IXGBE_FCOE
-		if (adapter->netdev->features & NETIF_F_FCOE_MTU)
+		if (netdev_active_feature_test(adapter->netdev, NETIF_F_FCOE_MTU_BIT))
 			max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
 #endif
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 04f453eabef6..2b5f348eddba 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -2396,7 +2396,7 @@ static bool ixgbe_update_rsc(struct ixgbe_adapter *adapter)
 
 	/* nothing to do if LRO or RSC are not enabled */
 	if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) ||
-	    !(netdev->features & NETIF_F_LRO))
+	    !(netdev_active_feature_test(netdev, NETIF_F_LRO_BIT)))
 		return false;
 
 	/* check the feature flag value and enable RSC if necessary */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index dd180400b454..82d2e9cdaf03 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -644,7 +644,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
 	u32 etqf;
 
 	/* Minimal functionality for FCoE requires at least CRC offloads */
-	if (!(adapter->netdev->features & NETIF_F_FCOE_CRC))
+	if (!netdev_active_feature_test(adapter->netdev, NETIF_F_FCOE_CRC_BIT))
 		return;
 
 	/* Enable L2 EtherType filter for FCoE, needed for FCoE CRC and DDP */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 86b11164655e..e83de178d43a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -982,7 +982,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
 			set_bit(__IXGBE_RX_CSUM_UDP_ZERO_ERR, &ring->state);
 
 #ifdef IXGBE_FCOE
-		if (adapter->netdev->features & NETIF_F_FCOE_MTU) {
+		if (netdev_active_feature_test(adapter->netdev, NETIF_F_FCOE_MTU_BIT)) {
 			struct ixgbe_ring_feature *f;
 			f = &adapter->ring_feature[RING_F_FCOE];
 			if ((rxr_idx >= f->offset) &&
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 1a193cf10dab..798870434fa7 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1427,7 +1427,7 @@ static inline void ixgbe_rx_hash(struct ixgbe_ring *ring,
 {
 	u16 rss_type;
 
-	if (!(ring->netdev->features & NETIF_F_RXHASH))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXHASH_BIT))
 		return;
 
 	rss_type = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) &
@@ -1477,7 +1477,7 @@ static inline void ixgbe_rx_checksum(struct ixgbe_ring *ring,
 	skb_checksum_none_assert(skb);
 
 	/* Rx csum disabled */
-	if (!(ring->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* check for VXLAN and Geneve packets */
@@ -1696,7 +1696,7 @@ void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
 	if (unlikely(flags & IXGBE_FLAG_RX_HWTSTAMP_ENABLED))
 		ixgbe_ptp_rx_hwtstamp(rx_ring, rx_desc, skb);
 
-	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	    ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) {
 		u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan);
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
@@ -1894,7 +1894,7 @@ bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
 	if (!netdev ||
 	    (unlikely(ixgbe_test_staterr(rx_desc,
 					 IXGBE_RXDADV_ERR_FRAME_ERR_MASK) &&
-	     !(netdev->features & NETIF_F_RXALL)))) {
+	     !netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)))) {
 		dev_kfree_skb_any(skb);
 		return true;
 	}
@@ -4961,7 +4961,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
 	}
 
 	/* This is useful for sniffing bad packets. */
-	if (features & NETIF_F_RXALL) {
+	if (netdev_feature_test(NETIF_F_RXALL_BIT, features)) {
 		/* UPE and MPE will be handled by normal PROMISC logic
 		 * in e1000e_set_rx_mode */
 		fctrl |= (IXGBE_FCTRL_SBP | /* Receive bad packets */
@@ -4974,12 +4974,12 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
 
 	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
 
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		ixgbe_vlan_strip_enable(adapter);
 	else
 		ixgbe_vlan_strip_disable(adapter);
 
-	if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
 		ixgbe_vlan_promisc_disable(adapter);
 	else
 		ixgbe_vlan_promisc_enable(adapter);
@@ -5061,7 +5061,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
 		netif_set_tso_max_size(adapter->netdev, 32768);
 
 #ifdef IXGBE_FCOE
-	if (adapter->netdev->features & NETIF_F_FCOE_MTU)
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_FCOE_MTU_BIT))
 		max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
 #endif
 
@@ -5118,7 +5118,7 @@ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb)
 
 #ifdef IXGBE_FCOE
 	/* FCoE traffic class uses FCOE jumbo frames */
-	if ((dev->features & NETIF_F_FCOE_MTU) &&
+	if (netdev_active_feature_test(dev, NETIF_F_FCOE_MTU_BIT) &&
 	    (tc < IXGBE_FCOE_JUMBO_FRAME_SIZE) &&
 	    (pb == ixgbe_fcoe_get_tc(adapter)))
 		tc = IXGBE_FCOE_JUMBO_FRAME_SIZE;
@@ -5179,7 +5179,7 @@ static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter, int pb)
 
 #ifdef IXGBE_FCOE
 	/* FCoE traffic class uses FCOE jumbo frames */
-	if ((dev->features & NETIF_F_FCOE_MTU) &&
+	if (netdev_active_feature_test(dev, NETIF_F_FCOE_MTU_BIT) &&
 	    (tc < IXGBE_FCOE_JUMBO_FRAME_SIZE) &&
 	    (pb == netdev_get_prio_tc_map(dev, adapter->fcoe.up)))
 		tc = IXGBE_FCOE_JUMBO_FRAME_SIZE;
@@ -8828,8 +8828,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 #ifdef IXGBE_FCOE
 	/* setup tx offload for FCoE */
 	if ((protocol == htons(ETH_P_FCOE)) &&
-	    (tx_ring->netdev->features & NETIF_F_FSO ||
-	     tx_ring->netdev->features & NETIF_F_FCOE_CRC)) {
+	    (netdev_active_feature_test(tx_ring->netdev, NETIF_F_FSO_BIT) ||
+	     netdev_active_feature_test(tx_ring->netdev, NETIF_F_FCOE_CRC_BIT))) {
 		tso = ixgbe_fso(tx_ring, first, &hdr_len);
 		if (tso < 0)
 			goto out_drop;
@@ -9836,14 +9836,14 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev,
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
 	/* If Rx checksum is disabled, then RSC/LRO should also be disabled */
-	if (!(features & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	/* Turn off LRO if not RSC capable */
 	if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
-	if (adapter->xdp_prog && (features & NETIF_F_LRO)) {
+	if (adapter->xdp_prog && netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 		e_dev_err("LRO is not supported with XDP\n");
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 	}
@@ -9876,7 +9876,7 @@ static int ixgbe_set_features(struct net_device *netdev,
 	bool need_reset = false;
 
 	/* Make sure RSC matches LRO, reset if change */
-	if (!(features & NETIF_F_LRO)) {
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
 			need_reset = true;
 		adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
@@ -9886,7 +9886,8 @@ static int ixgbe_set_features(struct net_device *netdev,
 		    adapter->rx_itr_setting > IXGBE_MIN_RSC_ITR) {
 			adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
 			need_reset = true;
-		} else if ((changed & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
+		} else if (netdev_feature_test(NETIF_F_LRO_BIT, changed) !=
+			   netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 			e_info(probe, "rx-usecs set too low, "
 			       "disabling RSC\n");
 		}
@@ -9896,7 +9897,8 @@ static int ixgbe_set_features(struct net_device *netdev,
 	 * Check if Flow Director n-tuple support or hw_tc support was
 	 * enabled or disabled.  If the state changed, we need to reset.
 	 */
-	if ((features & NETIF_F_NTUPLE) || (features & NETIF_F_HW_TC)) {
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, features) ||
+	    netdev_feature_test(NETIF_F_HW_TC_BIT, features)) {
 		/* turn off ATR, enable perfect filters and reset */
 		if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
 			need_reset = true;
@@ -9923,17 +9925,18 @@ static int ixgbe_set_features(struct net_device *netdev,
 			adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
 	}
 
-	if (changed & NETIF_F_RXALL)
+	if (netdev_feature_test(NETIF_F_RXALL_BIT, changed))
 		need_reset = true;
 
 	netdev->features = features;
 
-	if ((changed & NETIF_F_HW_L2FW_DOFFLOAD) && adapter->num_rx_pools > 1)
+	if (netdev_feature_test(NETIF_F_HW_L2FW_DOFFLOAD_BIT, changed) &&
+	    adapter->num_rx_pools > 1)
 		ixgbe_reset_l2fw_offload(adapter);
 	else if (need_reset)
 		ixgbe_do_reset(netdev);
-	else if (changed & NETIF_F_HW_VLAN_CTAG_RX ||
-		 changed & NETIF_F_HW_VLAN_CTAG_FILTER)
+	else if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed) ||
+		 netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed))
 		ixgbe_set_rx_mode(netdev);
 
 	return 1;
@@ -10256,7 +10259,7 @@ ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
 	 * IPsec offoad sets skb->encapsulation but still can handle
 	 * the TSO, so it's the exception.
 	 */
-	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID)) {
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features)) {
 #ifdef CONFIG_IXGBE_IPSEC
 		if (!secpath_exists(skb))
 #endif
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 29cc60988071..ae9e2259fe10 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -495,7 +495,7 @@ static int ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 max_frame, u32 vf
 		s32 err = 0;
 
 #ifdef CONFIG_FCOE
-		if (dev->features & NETIF_F_FCOE_MTU)
+		if (netdev_active_feature_test(dev, NETIF_F_FCOE_MTU_BIT))
 			pf_max_frame = max_t(int, pf_max_frame,
 					     IXGBE_FCOE_JUMBO_FRAME_SIZE);
 
@@ -859,7 +859,7 @@ static void ixgbe_set_vf_rx_tx(struct ixgbe_adapter *adapter, int vf)
 		int pf_max_frame = dev->mtu + ETH_HLEN;
 
 #if IS_ENABLED(CONFIG_FCOE)
-		if (dev->features & NETIF_F_FCOE_MTU)
+		if (netdev_active_feature_test(dev, NETIF_F_FCOE_MTU_BIT))
 			pf_max_frame = max_t(int, pf_max_frame,
 					     IXGBE_FCOE_JUMBO_FRAME_SIZE);
 #endif /* CONFIG_FCOE */
diff --git a/drivers/net/ethernet/intel/ixgbevf/ipsec.c b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
index 82341ac13e62..3c29c3f49371 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
@@ -104,7 +104,7 @@ void ixgbevf_ipsec_restore(struct ixgbevf_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 	int i;
 
-	if (!(adapter->netdev->features & NETIF_F_HW_ESP))
+	if (!netdev_active_feature_test(adapter->netdev, NETIF_F_HW_ESP_BIT))
 		return;
 
 	/* reload the Rx and Tx keys */
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 2ccee2e984ec..29f1b7b514f4 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -445,7 +445,7 @@ static inline void ixgbevf_rx_hash(struct ixgbevf_ring *ring,
 {
 	u16 rss_type;
 
-	if (!(ring->netdev->features & NETIF_F_RXHASH))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXHASH_BIT))
 		return;
 
 	rss_type = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) &
@@ -472,7 +472,7 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_ring *ring,
 	skb_checksum_none_assert(skb);
 
 	/* Rx csum disabled */
-	if (!(ring->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(ring->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	/* if IP and error */
@@ -743,7 +743,7 @@ static bool ixgbevf_cleanup_headers(struct ixgbevf_ring *rx_ring,
 					  IXGBE_RXDADV_ERR_FRAME_ERR_MASK))) {
 		struct net_device *netdev = rx_ring->netdev;
 
-		if (!(netdev->features & NETIF_F_RXALL)) {
+		if (!netdev_active_feature_test(netdev, NETIF_F_RXALL_BIT)) {
 			dev_kfree_skb_any(skb);
 			return true;
 		}
@@ -4436,7 +4436,7 @@ ixgbevf_features_check(struct sk_buff *skb, struct net_device *dev,
 	/* We can only support IPV4 TSO in tunnels if we can mangle the
 	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
 	 */
-	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features))
 		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
 	return features;
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 85a008905dcc..2a91f39dd6f6 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -717,7 +717,7 @@ jme_set_clean_rxdesc(struct jme_adapter *jme, int i)
 	rxdesc->desc1.bufaddrl	= cpu_to_le32(
 					(__u64)rxbi->mapping & 0xFFFFFFFFUL);
 	rxdesc->desc1.datalen	= cpu_to_le16(rxbi->len);
-	if (jme->dev->features & NETIF_F_HIGHDMA)
+	if (netdev_active_feature_test(jme->dev, NETIF_F_HIGHDMA_BIT))
 		rxdesc->desc1.flags = RXFLAG_64BIT;
 	wmb();
 	rxdesc->desc1.flags	|= RXFLAG_OWN | RXFLAG_INT;
@@ -2006,7 +2006,7 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx)
 	struct jme_ring *txring = &(jme->txring[0]);
 	struct txdesc *txdesc = txring->desc, *ctxdesc;
 	struct jme_buffer_info *txbi = txring->bufinf, *ctxbi;
-	bool hidma = jme->dev->features & NETIF_F_HIGHDMA;
+	bool hidma = netdev_active_feature_test(jme->dev, NETIF_F_HIGHDMA_BIT);
 	int i, nr_frags = skb_shinfo(skb)->nr_frags;
 	int mask = jme->tx_ring_mask;
 	u32 len;
@@ -2677,7 +2677,7 @@ jme_set_features(struct net_device *netdev, netdev_features_t features)
 	struct jme_adapter *jme = netdev_priv(netdev);
 
 	spin_lock_bh(&jme->rxmcs_lock);
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		jme->reg_rxmcs |= RXMCS_CHECKSUM;
 	else
 		jme->reg_rxmcs &= ~RXMCS_CHECKSUM;
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index b91318551538..7ed11331fd07 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -1686,7 +1686,7 @@ static int
 mv643xx_eth_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct mv643xx_eth_private *mp = netdev_priv(dev);
-	bool rx_csum = features & NETIF_F_RXCSUM;
+	bool rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
 
 	wrlp(mp, PORT_CONFIG, rx_csum ? 0x02000000 : 0x00000000);
 
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index dc67d93c6e44..8cfc07bf80a2 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1839,7 +1839,7 @@ static void mvneta_rx_error(struct mvneta_port *pp,
 /* Handle RX checksum offload based on the descriptor's status */
 static int mvneta_rx_csum(struct mvneta_port *pp, u32 status)
 {
-	if ((pp->dev->features & NETIF_F_RXCSUM) &&
+	if (netdev_active_feature_test(pp->dev, NETIF_F_RXCSUM_BIT) &&
 	    (status & MVNETA_RXD_L3_IP4) &&
 	    (status & MVNETA_RXD_L4_CSUM_OK))
 		return CHECKSUM_UNNECESSARY;
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 09964559d77f..7507dd20bfa2 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -4905,7 +4905,7 @@ static int mvpp2_prs_mac_da_accept_list(struct mvpp2_port *port,
 
 static void mvpp2_set_rx_promisc(struct mvpp2_port *port, bool enable)
 {
-	if (!enable && (port->dev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+	if (!enable && netdev_active_feature_test(port->dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		mvpp2_prs_vid_enable_filtering(port);
 	else
 		mvpp2_prs_vid_disable_filtering(port);
@@ -5282,8 +5282,8 @@ static int mvpp2_set_features(struct net_device *dev,
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	struct mvpp2_port *port = netdev_priv(dev);
 
-	if (changed & 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, changed)) {
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) {
 			mvpp2_prs_vid_enable_filtering(port);
 		} else {
 			/* Invalidate all registered VID filters for this
@@ -5295,8 +5295,8 @@ static int mvpp2_set_features(struct net_device *dev,
 		}
 	}
 
-	if (changed & NETIF_F_RXHASH) {
-		if (features & NETIF_F_RXHASH)
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_RXHASH_BIT, features))
 			mvpp22_port_rss_enable(port);
 		else
 			mvpp22_port_rss_disable(port);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index 2f21d044318f..94262084bda3 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -1727,13 +1727,13 @@ int otx2_handle_ntuple_tc_features(struct net_device *netdev, netdev_features_t
 {
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	struct otx2_nic *pfvf = netdev_priv(netdev);
-	bool ntuple = !!(features & NETIF_F_NTUPLE);
-	bool tc = !!(features & NETIF_F_HW_TC);
+	bool ntuple = netdev_feature_test(NETIF_F_NTUPLE_BIT, features);
+	bool tc = netdev_feature_test(NETIF_F_HW_TC_BIT, features);
 
-	if ((changed & NETIF_F_NTUPLE) && !ntuple)
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed) && !ntuple)
 		otx2_destroy_ntuple_flows(pfvf);
 
-	if ((changed & NETIF_F_NTUPLE) && ntuple) {
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed) && ntuple) {
 		if (!pfvf->flow_cfg->max_flows) {
 			netdev_err(netdev,
 				   "Can't enable NTUPLE, MCAM entries not allocated\n");
@@ -1741,7 +1741,7 @@ int otx2_handle_ntuple_tc_features(struct net_device *netdev, netdev_features_t
 		}
 	}
 
-	if ((changed & NETIF_F_HW_TC) && tc) {
+	if (netdev_feature_test(NETIF_F_HW_TC_BIT, changed) && tc) {
 		if (!pfvf->flow_cfg->max_flows) {
 			netdev_err(netdev,
 				   "Can't enable TC, MCAM entries not allocated\n");
@@ -1749,21 +1749,23 @@ int otx2_handle_ntuple_tc_features(struct net_device *netdev, netdev_features_t
 		}
 	}
 
-	if ((changed & NETIF_F_HW_TC) && !tc &&
+	if (netdev_feature_test(NETIF_F_HW_TC_BIT, changed) && !tc &&
 	    pfvf->flow_cfg && pfvf->flow_cfg->nr_flows) {
 		netdev_err(netdev, "Can't disable TC hardware offload while flows are active\n");
 		return -EBUSY;
 	}
 
-	if ((changed & NETIF_F_NTUPLE) && ntuple &&
-	    (netdev->features & NETIF_F_HW_TC) && !(changed & NETIF_F_HW_TC)) {
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed) && ntuple &&
+	    netdev_active_feature_test(netdev, NETIF_F_HW_TC_BIT) &&
+	    !netdev_feature_test(NETIF_F_HW_TC_BIT, changed)) {
 		netdev_err(netdev,
 			   "Can't enable NTUPLE when TC is active, disable TC and retry\n");
 		return -EINVAL;
 	}
 
-	if ((changed & NETIF_F_HW_TC) && tc &&
-	    (netdev->features & NETIF_F_NTUPLE) && !(changed & NETIF_F_NTUPLE)) {
+	if (netdev_feature_test(NETIF_F_HW_TC_BIT, changed) && tc &&
+	    netdev_active_feature_test(netdev, NETIF_F_NTUPLE_BIT) &&
+	    !netdev_feature_test(NETIF_F_NTUPLE_BIT, changed)) {
 		netdev_err(netdev,
 			   "Can't enable TC when NTUPLE is active, disable NTUPLE and retry\n");
 		return -EINVAL;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index 3f60a80e34c8..5e3bec4e45ce 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -716,7 +716,7 @@ static int otx2_set_rss_hash_opts(struct otx2_nic *pfvf,
 static int otx2_get_rxnfc(struct net_device *dev,
 			  struct ethtool_rxnfc *nfc, u32 *rules)
 {
-	bool ntuple = !!(dev->features & NETIF_F_NTUPLE);
+	bool ntuple = netdev_active_feature_test(dev, NETIF_F_NTUPLE_BIT);
 	struct otx2_nic *pfvf = netdev_priv(dev);
 	int ret = -EOPNOTSUPP;
 
@@ -749,7 +749,7 @@ static int otx2_get_rxnfc(struct net_device *dev,
 
 static int otx2_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc)
 {
-	bool ntuple = !!(dev->features & NETIF_F_NTUPLE);
+	bool ntuple = netdev_active_feature_test(dev, NETIF_F_NTUPLE_BIT);
 	struct otx2_nic *pfvf = netdev_priv(dev);
 	int ret = -EOPNOTSUPP;
 
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 4811f51d297b..d90e4f4a3be7 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1857,7 +1857,7 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
 static netdev_features_t otx2_fix_features(struct net_device *dev,
 					   netdev_features_t features)
 {
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT, &features);
 	else
 		netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT, &features);
@@ -1885,13 +1885,13 @@ static int otx2_set_features(struct net_device *netdev,
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	struct otx2_nic *pf = netdev_priv(netdev);
 
-	if ((changed & NETIF_F_LOOPBACK) && netif_running(netdev))
-		return otx2_cgx_config_loopback(pf,
-						features & NETIF_F_LOOPBACK);
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed) && netif_running(netdev))
+		return otx2_cgx_config_loopback(pf, netdev_feature_test(NETIF_F_LOOPBACK_BIT,
+									features));
 
-	if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && netif_running(netdev))
-		return otx2_enable_rxvlan(pf,
-					  features & NETIF_F_HW_VLAN_CTAG_RX);
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed) && netif_running(netdev))
+		return otx2_enable_rxvlan(pf, netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+								  features));
 
 	return otx2_handle_ntuple_tc_features(netdev, features);
 }
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index a18e8efd0f1e..2d3f367ff6b8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -231,7 +231,7 @@ static void otx2_set_rxhash(struct otx2_nic *pfvf,
 	struct otx2_rss_info *rss;
 	u32 hash = 0;
 
-	if (!(pfvf->netdev->features & NETIF_F_RXHASH))
+	if (!netdev_active_feature_test(pfvf->netdev, NETIF_F_RXHASH_BIT))
 		return;
 
 	rss = &pfvf->hw.rss_info;
@@ -321,7 +321,7 @@ static bool otx2_check_rcv_errors(struct otx2_nic *pfvf,
 	}
 
 	/* If RXALL is enabled pass on packets to stack. */
-	if (pfvf->netdev->features & NETIF_F_RXALL)
+	if (netdev_active_feature_test(pfvf->netdev, NETIF_F_RXALL_BIT))
 		return false;
 
 	/* Free buffer back to pool */
@@ -372,7 +372,7 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
 	otx2_set_rxhash(pfvf, cqe, skb);
 
 	skb_record_rx_queue(skb, cq->cq_idx);
-	if (pfvf->netdev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(pfvf->netdev, NETIF_F_RXCSUM_BIT))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 	napi_gro_frags(napi);
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index cd2636ef08d3..cad6263947eb 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3113,7 +3113,7 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
 
 	skb_put(skb, len);
 
-	if (dev->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)) {
 		skb->csum = le16_to_cpu(csum);
 		skb->ip_summed = CHECKSUM_COMPLETE;
 	}
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 851b1fd964c6..9da8a0ebb383 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -1274,7 +1274,7 @@ static void rx_set_checksum(struct sky2_port *sky2)
 
 	sky2_write32(sky2->hw,
 		     Q_ADDR(rxqaddr[sky2->port], Q_CSR),
-		     (sky2->netdev->features & NETIF_F_RXCSUM)
+		     netdev_active_feature_test(sky2->netdev, NETIF_F_RXCSUM_BIT)
 		     ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
 }
 
@@ -1292,7 +1292,7 @@ static void rx_set_rss(struct net_device *dev, netdev_features_t features)
 	}
 
 	/* Program RSS initial values */
-	if (features & NETIF_F_RXHASH) {
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features)) {
 		u32 rss_key[10];
 
 		netdev_rss_key_fill(rss_key, sizeof(rss_key));
@@ -1410,14 +1410,14 @@ static void sky2_vlan_mode(struct net_device *dev, netdev_features_t features)
 	struct sky2_hw *hw = sky2->hw;
 	u16 port = sky2->port;
 
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
 			     RX_VLAN_STRIP_ON);
 	else
 		sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
 			     RX_VLAN_STRIP_OFF);
 
-	if (features & NETIF_F_HW_VLAN_CTAG_TX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features)) {
 		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
 			     TX_VLAN_TAG_ON);
 
@@ -2747,7 +2747,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
 
 			/* This chip reports checksum status differently */
 			if (hw->flags & SKY2_HW_NEW_LE) {
-				if ((dev->features & NETIF_F_RXCSUM) &&
+				if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT) &&
 				    (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
 				    (le->css & CSS_TCPUDPCSOK))
 					skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -2771,7 +2771,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
 			sky2_rx_tag(sky2, length);
 			fallthrough;
 		case OP_RXCHKS:
-			if (likely(dev->features & NETIF_F_RXCSUM))
+			if (likely(netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)))
 				sky2_rx_checksum(sky2, status);
 			break;
 
@@ -4322,9 +4322,9 @@ static netdev_features_t sky2_fix_features(struct net_device *dev,
 	}
 
 	/* Some hardware requires receive checksum for RSS to work. */
-	if ( (features & NETIF_F_RXHASH) &&
-	     !(features & NETIF_F_RXCSUM) &&
-	     (sky2->hw->flags & SKY2_HW_RSS_CHKSUM)) {
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features) &&
+	    !netdev_feature_test(NETIF_F_RXCSUM_BIT, features) &&
+	    (sky2->hw->flags & SKY2_HW_RSS_CHKSUM)) {
 		netdev_info(dev, "receive hashing forces receive checksum\n");
 		netdev_feature_add(NETIF_F_RXCSUM_BIT, &features);
 	}
@@ -4337,15 +4337,15 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features)
 	struct sky2_port *sky2 = netdev_priv(dev);
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
-	if ((changed & NETIF_F_RXCSUM) &&
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed) &&
 	    !(sky2->hw->flags & SKY2_HW_NEW_LE)) {
 		sky2_write32(sky2->hw,
 			     Q_ADDR(rxqaddr[sky2->port], Q_CSR),
-			     (features & NETIF_F_RXCSUM)
+			     netdev_feature_test(NETIF_F_RXCSUM_BIT, features)
 			     ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
 	}
 
-	if (changed & NETIF_F_RXHASH)
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, changed))
 		rx_set_rss(dev, features);
 
 	if (changed & netdev_ctag_vlan_offload_features)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index fb9d32d67884..a8da58050ab6 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1930,7 +1930,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 			mtk_ppe_check_skb(eth->ppe, skb,
 					  trxd.rxd4 & MTK_RXD4_FOE_ENTRY);
 
-		if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
+		if (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
 			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
 				if (trxd.rxd3 & RX_DMA_VTAG_V2)
 					__vlan_hwaccel_put_tag(skb,
@@ -2709,7 +2709,7 @@ static int mtk_hwlro_get_fdir_all(struct net_device *dev,
 static netdev_features_t mtk_fix_features(struct net_device *dev,
 					  netdev_features_t features)
 {
-	if (!(features & NETIF_F_LRO)) {
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 		struct mtk_mac *mac = netdev_priv(dev);
 		int ip_cnt = mtk_hwlro_get_ip_cnt(mac);
 
@@ -2727,10 +2727,11 @@ static int mtk_set_features(struct net_device *dev, netdev_features_t features)
 {
 	int err = 0;
 
-	if (!((netdev_active_features_xor(dev, features)) & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT,
+				 netdev_active_features_xor(dev, features)))
 		return 0;
 
-	if (!(features & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, features))
 		mtk_hwlro_netdev_disable(dev);
 
 	return err;
@@ -3705,13 +3706,13 @@ static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
 
 	switch (cmd->cmd) {
 	case ETHTOOL_GRXRINGS:
-		if (dev->hw_features & NETIF_F_LRO) {
+		if (netdev_hw_feature_test(dev, NETIF_F_LRO_BIT)) {
 			cmd->data = MTK_MAX_RX_RING_NUM;
 			ret = 0;
 		}
 		break;
 	case ETHTOOL_GRXCLSRLCNT:
-		if (dev->hw_features & NETIF_F_LRO) {
+		if (netdev_hw_feature_test(dev, NETIF_F_LRO_BIT)) {
 			struct mtk_mac *mac = netdev_priv(dev);
 
 			cmd->rule_cnt = mac->hwlro_ip_cnt;
@@ -3719,11 +3720,11 @@ static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
 		}
 		break;
 	case ETHTOOL_GRXCLSRULE:
-		if (dev->hw_features & NETIF_F_LRO)
+		if (netdev_hw_feature_test(dev, NETIF_F_LRO_BIT))
 			ret = mtk_hwlro_get_fdir_entry(dev, cmd);
 		break;
 	case ETHTOOL_GRXCLSRLALL:
-		if (dev->hw_features & NETIF_F_LRO)
+		if (netdev_hw_feature_test(dev, NETIF_F_LRO_BIT))
 			ret = mtk_hwlro_get_fdir_all(dev, cmd,
 						     rule_locs);
 		break;
@@ -3740,11 +3741,11 @@ static int mtk_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 
 	switch (cmd->cmd) {
 	case ETHTOOL_SRXCLSRLINS:
-		if (dev->hw_features & NETIF_F_LRO)
+		if (netdev_hw_feature_test(dev, NETIF_F_LRO_BIT))
 			ret = mtk_hwlro_add_ipaddr(dev, cmd);
 		break;
 	case ETHTOOL_SRXCLSRLDEL:
-		if (dev->hw_features & NETIF_F_LRO)
+		if (netdev_hw_feature_test(dev, NETIF_F_LRO_BIT))
 			ret = mtk_hwlro_del_ipaddr(dev, cmd);
 		break;
 	default:
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 6400a827173c..62398896d7a3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -1244,13 +1244,13 @@ static int mlx4_en_check_rxfh_func(struct net_device *dev, u8 hfunc)
 	if (hfunc == ETH_RSS_HASH_TOP) {
 		if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP))
 			return -EINVAL;
-		if (!(dev->features & NETIF_F_RXHASH))
+		if (!(netdev_active_feature_test(dev, NETIF_F_RXHASH_BIT)))
 			en_warn(priv, "Toeplitz hash function should be used in conjunction with RX hashing for optimal performance\n");
 		return 0;
 	} else if (hfunc == ETH_RSS_HASH_XOR) {
 		if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR))
 			return -EINVAL;
-		if (dev->features & NETIF_F_RXHASH)
+		if (netdev_active_feature_test(dev, NETIF_F_RXHASH_BIT))
 			en_warn(priv, "Enabling both XOR Hash function and RX Hashing can limit RPS functionality\n");
 		return 0;
 	}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index edde15669886..1c09c8260dac 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -104,7 +104,7 @@ void mlx4_en_update_loopback_state(struct net_device *dev,
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 
-	if (features & NETIF_F_LOOPBACK)
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features))
 		priv->ctrl_flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK);
 	else
 		priv->ctrl_flags &= cpu_to_be32(~MLX4_WQE_CTRL_FORCE_LOOPBACK);
@@ -116,7 +116,7 @@ void mlx4_en_update_loopback_state(struct net_device *dev,
 	 * and not performing the selftest or flb disabled
 	 */
 	if (mlx4_is_mfunc(priv->mdev->dev) &&
-	    !(features & NETIF_F_LOOPBACK) && !priv->validate_loopback)
+	    !netdev_feature_test(NETIF_F_LOOPBACK_BIT, features) && !priv->validate_loopback)
 		priv->flags |= MLX4_EN_FLAG_RX_FILTER_NEEDED;
 
 	/* Set dmac in Tx WQE if we are in SRIOV mode or if loopback selftest
@@ -131,7 +131,7 @@ void mlx4_en_update_loopback_state(struct net_device *dev,
 	    priv->rss_map.indir_qp && priv->rss_map.indir_qp->qpn) {
 		int i;
 		int err = 0;
-		int loopback = !!(features & NETIF_F_LOOPBACK);
+		int loopback = netdev_feature_test(NETIF_F_LOOPBACK_BIT, features);
 
 		for (i = 0; i < priv->rx_ring_num; i++) {
 			int ret;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index d9fa50d5ef69..9cf8055b7f5f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2506,7 +2506,7 @@ static netdev_features_t mlx4_en_fix_features(struct net_device *netdev,
 	 * enable/disable make sure S-TAG flag is always in same state as
 	 * C-TAG.
 	 */
-	if (features & NETIF_F_HW_VLAN_CTAG_RX &&
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) &&
 	    !(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN))
 		netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT, &features);
 	else
@@ -2524,12 +2524,12 @@ static int mlx4_en_set_features(struct net_device *netdev,
 
 	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_RXFCS_BIT)) {
 		en_info(priv, "Turn %s RX-FCS\n",
-			(features & NETIF_F_RXFCS) ? "ON" : "OFF");
+			netdev_feature_test(NETIF_F_RXFCS_BIT, features) ? "ON" : "OFF");
 		reset = true;
 	}
 
 	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_RXALL_BIT)) {
-		u8 ignore_fcs_value = (features & NETIF_F_RXALL) ? 1 : 0;
+		u8 ignore_fcs_value = netdev_feature_test(NETIF_F_RXALL_BIT, features) ? 1 : 0;
 
 		en_info(priv, "Turn %s RX-ALL\n",
 			ignore_fcs_value ? "ON" : "OFF");
@@ -2541,21 +2541,21 @@ static int mlx4_en_set_features(struct net_device *netdev,
 
 	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
 		en_info(priv, "Turn %s RX vlan strip offload\n",
-			(features & NETIF_F_HW_VLAN_CTAG_RX) ? "ON" : "OFF");
+			netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) ? "ON" : "OFF");
 		reset = true;
 	}
 
 	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_CTAG_TX_BIT))
 		en_info(priv, "Turn %s TX vlan strip offload\n",
-			(features & NETIF_F_HW_VLAN_CTAG_TX) ? "ON" : "OFF");
+			netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features) ? "ON" : "OFF");
 
 	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_STAG_TX_BIT))
 		en_info(priv, "Turn %s TX S-VLAN strip offload\n",
-			(features & NETIF_F_HW_VLAN_STAG_TX) ? "ON" : "OFF");
+			netdev_feature_test(NETIF_F_HW_VLAN_STAG_TX_BIT, features) ? "ON" : "OFF");
 
 	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_LOOPBACK_BIT)) {
 		en_info(priv, "Turn %s loopback\n",
-			(features & NETIF_F_LOOPBACK) ? "ON" : "OFF");
+			netdev_feature_test(NETIF_F_LOOPBACK_BIT, features) ? "ON" : "OFF");
 		mlx4_en_update_loopback_state(netdev, features);
 	}
 
@@ -3535,7 +3535,7 @@ int mlx4_en_reset_config(struct net_device *dev,
 		return 0; /* Nothing to change */
 
 	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
-	    (features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) &&
 	    (priv->hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE)) {
 		en_warn(priv, "Can't turn ON rx vlan offload while time-stamping rx filter is ON\n");
 		return -EINVAL;
@@ -3562,7 +3562,7 @@ int mlx4_en_reset_config(struct net_device *dev,
 	mlx4_en_safe_replace_resources(priv, tmp);
 
 	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
-		if (features & NETIF_F_HW_VLAN_CTAG_RX)
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 			netdev_active_feature_add(dev,
 						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 		else
@@ -3572,7 +3572,7 @@ int mlx4_en_reset_config(struct net_device *dev,
 		/* RX time-stamping is OFF, update the RX vlan offload
 		 * to the latest wanted state
 		 */
-		if (dev->wanted_features & NETIF_F_HW_VLAN_CTAG_RX)
+		if (netdev_wanted_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 			netdev_active_feature_add(dev,
 						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 		else
@@ -3581,7 +3581,7 @@ int mlx4_en_reset_config(struct net_device *dev,
 	}
 
 	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_RXFCS_BIT)) {
-		if (features & NETIF_F_RXFCS)
+		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features))
 			netdev_active_feature_add(dev, NETIF_F_RXFCS_BIT);
 		else
 			netdev_active_feature_del(dev, NETIF_F_RXFCS_BIT);
@@ -3592,7 +3592,7 @@ int mlx4_en_reset_config(struct net_device *dev,
 	 * Turn Off RX vlan offload in case of time-stamping is ON
 	 */
 	if (ts_config.rx_filter != HWTSTAMP_FILTER_NONE) {
-		if (dev->features & NETIF_F_HW_VLAN_CTAG_RX)
+		if (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 			en_warn(priv, "Turning off RX vlan offload since RX time-stamping is ON\n");
 		netdev_active_feature_del(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
index 6883ac75d37f..ec422cb90404 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
@@ -76,12 +76,12 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
 	    context->pri_path.counter_index !=
 			    MLX4_SINK_COUNTER_INDEX(mdev->dev)) {
 		/* disable multicast loopback to qp with same counter */
-		if (!(dev->features & NETIF_F_LOOPBACK))
+		if (!(netdev_active_feature_test(dev, NETIF_F_LOOPBACK_BIT)))
 			context->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
 		context->pri_path.control |= MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER;
 	}
 	context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
-	if (!(dev->features & NETIF_F_HW_VLAN_CTAG_RX))
+	if (!(netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT)))
 		context->param3 |= cpu_to_be32(1 << 30);
 
 	if (!is_tx && !rss &&
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 8f762fc170b3..a4f61a4adb7e 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -643,7 +643,7 @@ static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va,
 	hw_checksum = csum_unfold((__force __sum16)cqe->checksum);
 
 	if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK) &&
-	    !(dev_features & NETIF_F_HW_VLAN_CTAG_RX)) {
+	    !netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, dev_features)) {
 		hw_checksum = get_fixed_vlan_csum(hw_checksum, hdr);
 		hdr += sizeof(struct vlan_hdr);
 	}
@@ -839,7 +839,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 		}
 		skb_record_rx_queue(skb, cq_ring);
 
-		if (likely(dev->features & NETIF_F_RXCSUM)) {
+		if (likely(netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT))) {
 			/* TODO: For IP non TCP/UDP packets when csum complete is
 			 * not an option (not supported or any other reason) we can
 			 * actually check cqe IPOK status bit and report
@@ -851,7 +851,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 			    cqe->checksum == cpu_to_be16(0xffff)) {
 				bool l2_tunnel;
 
-				l2_tunnel = (dev->hw_enc_features & NETIF_F_RXCSUM) &&
+				l2_tunnel = (netdev_hw_enc_feature_test(dev, NETIF_F_RXCSUM_BIT)) &&
 					(cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_L2_TUNNEL));
 				ip_summed = CHECKSUM_UNNECESSARY;
 				hash_type = PKT_HASH_TYPE_L4;
@@ -875,19 +875,19 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 			ring->csum_none++;
 		}
 		skb->ip_summed = ip_summed;
-		if (dev->features & NETIF_F_RXHASH)
+		if (netdev_active_feature_test(dev, NETIF_F_RXHASH_BIT))
 			skb_set_hash(skb,
 				     be32_to_cpu(cqe->immed_rss_invalid),
 				     hash_type);
 
 		if ((cqe->vlan_my_qpn &
 		     cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK)) &&
-		    (dev->features & NETIF_F_HW_VLAN_CTAG_RX))
+		    (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT)))
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
 					       be16_to_cpu(cqe->sl_vid));
 		else if ((cqe->vlan_my_qpn &
 			  cpu_to_be32(MLX4_CQE_SVLAN_PRESENT_MASK)) &&
-			 (dev->features & NETIF_F_HW_VLAN_STAG_RX))
+			 (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_STAG_RX_BIT)))
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD),
 					       be16_to_cpu(cqe->sl_vid));
 
@@ -1085,7 +1085,7 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
 	/* Cancel FCS removal if FW allows */
 	if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP) {
 		context->param3 |= cpu_to_be32(1 << 29);
-		if (priv->dev->features & NETIF_F_RXFCS)
+		if (netdev_active_feature_test(priv->dev, NETIF_F_RXFCS_BIT))
 			ring->fcs_del = 0;
 		else
 			ring->fcs_del = ETH_FCS_LEN;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
index 885c85dbfe73..593c2059a132 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
@@ -137,7 +137,7 @@ int mlx5e_ktls_init_rx(struct mlx5e_priv *priv)
 	if (!priv->tls->rx_wq)
 		return -ENOMEM;
 
-	if (priv->netdev->features & NETIF_F_HW_TLS_RX) {
+	if (netdev_active_feature_test(priv->netdev, NETIF_F_HW_TLS_RX_BIT)) {
 		err = mlx5e_accel_fs_tcp_create(priv);
 		if (err) {
 			destroy_workqueue(priv->tls->rx_wq);
@@ -153,7 +153,7 @@ void mlx5e_ktls_cleanup_rx(struct mlx5e_priv *priv)
 	if (!mlx5e_is_ktls_rx(priv->mdev))
 		return;
 
-	if (priv->netdev->features & NETIF_F_HW_TLS_RX)
+	if (netdev_active_feature_test(priv->netdev, NETIF_F_HW_TLS_RX_BIT))
 		mlx5e_accel_fs_tcp_destroy(priv);
 
 	destroy_workqueue(priv->tls->rx_wq);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
index cd7f245dcf14..3bb47f10239d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
@@ -181,7 +181,7 @@ static void _mlx5e_cleanup_tables(struct mlx5e_priv *priv)
 
 void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv)
 {
-	if (!(priv->netdev->hw_features & NETIF_F_NTUPLE))
+	if (!netdev_hw_feature_test(priv->netdev, NETIF_F_NTUPLE_BIT))
 		return;
 
 	_mlx5e_cleanup_tables(priv);
@@ -358,7 +358,7 @@ int mlx5e_arfs_create_tables(struct mlx5e_priv *priv)
 	int err = -ENOMEM;
 	int i;
 
-	if (!(priv->netdev->hw_features & NETIF_F_NTUPLE))
+	if (!netdev_hw_feature_test(priv->netdev, NETIF_F_NTUPLE_BIT))
 		return 0;
 
 	priv->fs->arfs = kvzalloc(sizeof(*priv->fs->arfs), GFP_KERNEL);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index b811207fe5ed..f8f6aac6ad77 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -492,7 +492,7 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
 
 	opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
 
-	arfs_enabled = opened && (priv->netdev->features & NETIF_F_NTUPLE);
+	arfs_enabled = opened && netdev_active_feature_test(priv->netdev, NETIF_F_NTUPLE_BIT);
 	if (arfs_enabled)
 		mlx5e_arfs_disable(priv);
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index dda033464220..1c1637445980 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3891,19 +3891,19 @@ static netdev_features_t mlx5e_fix_uplink_rep_features(struct net_device *netdev
 						       netdev_features_t features)
 {
 	netdev_feature_del(NETIF_F_HW_TLS_RX_BIT, &features);
-	if (netdev->features & NETIF_F_HW_TLS_RX)
+	if (netdev_active_feature_test(netdev, NETIF_F_HW_TLS_RX_BIT))
 		netdev_warn(netdev, "Disabling hw_tls_rx, not supported in switchdev mode\n");
 
 	netdev_feature_del(NETIF_F_HW_TLS_TX_BIT, &features);
-	if (netdev->features & NETIF_F_HW_TLS_TX)
+	if (netdev_active_feature_test(netdev, NETIF_F_HW_TLS_TX_BIT))
 		netdev_warn(netdev, "Disabling hw_tls_tx, not supported in switchdev mode\n");
 
 	netdev_feature_del(NETIF_F_NTUPLE_BIT, &features);
-	if (netdev->features & NETIF_F_NTUPLE)
+	if (netdev_active_feature_test(netdev, NETIF_F_NTUPLE_BIT))
 		netdev_warn(netdev, "Disabling ntuple, not supported in switchdev mode\n");
 
 	netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
-	if (netdev->features & NETIF_F_GRO_HW)
+	if (netdev_active_feature_test(netdev, NETIF_F_GRO_HW_BIT))
 		netdev_warn(netdev, "Disabling HW_GRO, not supported in switchdev mode\n");
 
 	return features;
@@ -3928,34 +3928,34 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
 	}
 
 	if (!MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ)) {
-		if (features & NETIF_F_LRO) {
+		if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 			netdev_warn(netdev, "Disabling LRO, not supported in legacy RQ\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_warn(netdev, "Disabling HW-GRO, not supported in legacy RQ\n");
 			netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 		}
 	}
 
 	if (params->xdp_prog) {
-		if (features & NETIF_F_LRO) {
+		if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 			netdev_warn(netdev, "LRO is incompatible with XDP\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_warn(netdev, "HW GRO is incompatible with XDP\n");
 			netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 		}
 	}
 
 	if (priv->xsk.refcnt) {
-		if (features & NETIF_F_LRO) {
+		if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 			netdev_warn(netdev, "LRO is incompatible with AF_XDP (%u XSKs are active)\n",
 				    priv->xsk.refcnt);
 			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_warn(netdev, "HW GRO is incompatible with AF_XDP (%u XSKs are active)\n",
 				    priv->xsk.refcnt);
 			netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
@@ -3964,10 +3964,10 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
 
 	if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
 		netdev_feature_del(NETIF_F_RXHASH_BIT, &features);
-		if (netdev->features & NETIF_F_RXHASH)
+		if (netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT))
 			netdev_warn(netdev, "Disabling rxhash, not supported when CQE compress is active\n");
 
-		if (features & NETIF_F_GRO_HW) {
+		if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) {
 			netdev_warn(netdev, "Disabling HW-GRO, not supported when CQE compress is active\n");
 			netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 		}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 24de37b79f5a..33db1e0de43a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -1343,7 +1343,7 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
 	int network_depth = 0;
 	__be16 proto;
 
-	if (unlikely(!(netdev->features & NETIF_F_RXCSUM)))
+	if (unlikely(!(netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT))))
 		goto csum_none;
 
 	if (lro) {
@@ -1437,7 +1437,7 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe,
 								  rq->clock, get_cqe_ts(cqe));
 	skb_record_rx_queue(skb, rq->ix);
 
-	if (likely(netdev->features & NETIF_F_RXHASH))
+	if (likely(netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT)))
 		mlx5e_skb_set_hash(cqe, skb);
 
 	if (cqe_has_vlan(cqe)) {
@@ -2312,7 +2312,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
 
 	skb->protocol = *((__be16 *)(skb->data));
 
-	if (netdev->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) {
 		skb->ip_summed = CHECKSUM_COMPLETE;
 		skb->csum = csum_unfold((__force __sum16)cqe->check_sum);
 		stats->csum_complete++;
@@ -2326,7 +2326,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
 								  rq->clock, get_cqe_ts(cqe));
 	skb_record_rx_queue(skb, rq->ix);
 
-	if (likely(netdev->features & NETIF_F_RXHASH))
+	if (likely(netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT)))
 		mlx5e_skb_set_hash(cqe, skb);
 
 	/* 20 bytes of ipoib header and 4 for encap existing */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index f154bda668ad..44e3c5937c0f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -4815,7 +4815,7 @@ static int mlx5e_tc_netdev_event(struct notifier_block *this,
 	priv = tc->priv;
 	peer_priv = netdev_priv(ndev);
 	if (priv == peer_priv ||
-	    !(priv->netdev->features & NETIF_F_HW_TC))
+	    !netdev_active_feature_test(priv->netdev, NETIF_F_HW_TC_BIT))
 		return NOTIFY_DONE;
 
 	mlx5e_tc_hairpin_update_dead_peer(priv, peer_priv);
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 39891b7e6c71..3095ba506145 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -6507,7 +6507,7 @@ static int netdev_set_features(struct net_device *dev,
 	mutex_lock(&hw_priv->lock);
 
 	/* see note in hw_setup() */
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		hw->rx_cfg |= DMA_RX_CSUM_TCP | DMA_RX_CSUM_IP;
 	else
 		hw->rx_cfg &= ~(DMA_RX_CSUM_TCP | DMA_RX_CSUM_IP);
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
index 6dea7f8c1481..814ae70e903f 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
@@ -430,7 +430,7 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
 	skb->dev = lan966x->ports[src_port]->dev;
 	skb_pull(skb, IFH_LEN * sizeof(u32));
 
-	if (likely(!(skb->dev->features & NETIF_F_RXFCS)))
+	if (likely(!netdev_active_feature_test(skb->dev, NETIF_F_RXFCS_BIT)))
 		skb_trim(skb, skb->len - ETH_FCS_LEN);
 
 	lan966x_ptp_rxtstamp(lan966x, skb, timestamp);
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index c5c4d680e70c..ea867f7a0907 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -642,7 +642,7 @@ static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args)
 		/* Update the statistics if part of the FCS was read before */
 		len -= ETH_FCS_LEN - sz;
 
-		if (unlikely(dev->features & NETIF_F_RXFCS)) {
+		if (unlikely(netdev_active_feature_test(dev, NETIF_F_RXFCS_BIT))) {
 			buf = (u32 *)skb_put(skb, ETH_FCS_LEN);
 			*buf = val;
 		}
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
index 66360c8c5a38..6f6c21c5142e 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
@@ -238,7 +238,7 @@ static bool sparx5_fdma_rx_get_frame(struct sparx5 *sparx5, struct sparx5_rx *rx
 	}
 	skb->dev = port->ndev;
 	skb_pull(skb, IFH_LEN * sizeof(u32));
-	if (likely(!(skb->dev->features & NETIF_F_RXFCS)))
+	if (likely(!netdev_active_feature_test(skb->dev, NETIF_F_RXFCS_BIT)))
 		skb_trim(skb, skb->len - ETH_FCS_LEN);
 
 	sparx5_ptp_rxtstamp(sparx5, skb, fi.timestamp);
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 29bb41fdcdcd..47d23f44c458 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1139,12 +1139,12 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe,
 	skb_checksum_none_assert(skb);
 	skb_record_rx_queue(skb, rxq_idx);
 
-	if ((ndev->features & NETIF_F_RXCSUM) && cqe->rx_iphdr_csum_succeed) {
+	if (netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT) && cqe->rx_iphdr_csum_succeed) {
 		if (cqe->rx_tcp_csum_succeed || cqe->rx_udp_csum_succeed)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 	}
 
-	if (cqe->rx_hashtype != 0 && (ndev->features & NETIF_F_RXHASH)) {
+	if (cqe->rx_hashtype != 0 && netdev_active_feature_test(ndev, NETIF_F_RXHASH_BIT)) {
 		hash_value = cqe->ppi[0].pkt_hash;
 
 		if (cqe->rx_hashtype & MANA_HASH_L4)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index d4649e4ee0e7..988fa4cd1aad 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1248,7 +1248,7 @@ int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **nskb)
 	/* Update the statistics if part of the FCS was read before */
 	len -= ETH_FCS_LEN - sz;
 
-	if (unlikely(dev->features & NETIF_F_RXFCS)) {
+	if (unlikely(netdev_active_feature_test(dev, NETIF_F_RXFCS_BIT))) {
 		buf = (u32 *)skb_put(skb, ETH_FCS_LEN);
 		*buf = val;
 	}
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 6d6f3a010ea4..7947fd23f646 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -828,7 +828,7 @@ static void ocelot_vlan_mode(struct ocelot *ocelot, int port,
 
 	/* Filtering */
 	val = ocelot_read(ocelot, ANA_VLANMASK);
-	if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
 		val |= BIT(port);
 	else
 		val &= ~BIT(port);
@@ -843,14 +843,15 @@ static int ocelot_set_features(struct net_device *dev,
 	struct ocelot *ocelot = priv->port.ocelot;
 	int port = priv->port.index;
 
-	if ((dev->features & NETIF_F_HW_TC) && !(features & NETIF_F_HW_TC) &&
+	if (netdev_active_feature_test(dev, NETIF_F_HW_TC_BIT) &&
+	    !netdev_feature_test(NETIF_F_HW_TC_BIT, features) &&
 	    priv->tc.offload_cnt) {
 		netdev_err(dev,
 			   "Cannot disable HW TC offload while offloads active\n");
 		return -EBUSY;
 	}
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed))
 		ocelot_vlan_mode(ocelot, port, features);
 
 	return 0;
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 285688a88a0e..18257214dff5 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -1289,7 +1289,7 @@ myri10ge_vlan_rx(struct net_device *dev, void *addr, struct sk_buff *skb)
 	va = addr;
 	va += MXGEFW_PAD;
 	veh = (struct vlan_ethhdr *)va;
-	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if ((netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) &&
 	    veh->h_vlan_proto == htons(ETH_P_8021Q)) {
 		/* fixup csum if needed */
 		if (skb->ip_summed == CHECKSUM_COMPLETE) {
@@ -1367,7 +1367,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum)
 	skb->len = len;
 	skb->data_len = len;
 	skb->truesize += len;
-	if (dev->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)) {
 		skb->ip_summed = CHECKSUM_COMPLETE;
 		skb->csum = csum;
 	}
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index f7309c2498da..ddb41fec3f9a 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -2164,7 +2164,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
 		(unsigned)readl(dev->base + SRR) >> 8,
 		(unsigned)readl(dev->base + SRR) & 0xff,
 		ndev->dev_addr, addr, pci_dev->irq,
-		(ndev->features & NETIF_F_HIGHDMA) ? "h,sg" : "sg"
+		(netdev_active_feature_test(ndev, NETIF_F_HIGHDMA_BIT)) ? "h,sg" : "sg"
 		);
 
 #ifdef PHY_CODE_IS_FINISHED
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 24bf2275821e..8dac24a73f98 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -6573,7 +6573,7 @@ static int s2io_set_features(struct net_device *dev, netdev_features_t features)
 	struct s2io_nic *sp = netdev_priv(dev);
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
-	if (changed & NETIF_F_LRO && netif_running(dev)) {
+	if (netdev_feature_test(NETIF_F_LRO_BIT, changed) && netif_running(dev)) {
 		int rc;
 
 		s2io_stop_all_tx_queue(sp);
@@ -7124,7 +7124,7 @@ static int s2io_card_up(struct s2io_nic *sp)
 		struct ring_info *ring = &mac_control->rings[i];
 
 		ring->mtu = dev->mtu;
-		ring->lro = !!(dev->features & NETIF_F_LRO);
+		ring->lro = netdev_active_feature_test(dev, NETIF_F_LRO_BIT);
 		ret = fill_rx_buffers(sp, ring, 1);
 		if (ret) {
 			DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n",
@@ -7158,7 +7158,7 @@ static int s2io_card_up(struct s2io_nic *sp)
 	/* Setting its receive mode */
 	s2io_set_multicast(dev, true);
 
-	if (dev->features & NETIF_F_LRO) {
+	if (netdev_active_feature_test(dev, NETIF_F_LRO_BIT)) {
 		/* Initialize max aggregatable pkts per session based on MTU */
 		sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu;
 		/* Check if we can use (if specified) user provided value */
@@ -7370,7 +7370,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
 	if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) &&
 	    ((!ring_data->lro) ||
 	     (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG))) &&
-	    (dev->features & NETIF_F_RXCSUM)) {
+	    (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT))) {
 		l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
 		l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1);
 		if ((l3_csum == L3_CKSUM_OK) && (l4_csum == L4_CKSUM_OK)) {
diff --git a/drivers/net/ethernet/netronome/nfp/nfd3/dp.c b/drivers/net/ethernet/netronome/nfp/nfd3/dp.c
index 448c1c1afaee..4246b1677db5 100644
--- a/drivers/net/ethernet/netronome/nfp/nfd3/dp.c
+++ b/drivers/net/ethernet/netronome/nfp/nfd3/dp.c
@@ -641,7 +641,7 @@ nfp_nfd3_rx_csum(const struct nfp_net_dp *dp, struct nfp_net_r_vector *r_vec,
 {
 	skb_checksum_none_assert(skb);
 
-	if (!(dp->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(dp->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	if (meta->csum_type) {
@@ -685,7 +685,7 @@ static void
 nfp_nfd3_set_hash(struct net_device *netdev, struct nfp_meta_parsed *meta,
 		  unsigned int type, __be32 *hash)
 {
-	if (!(netdev->features & NETIF_F_RXHASH))
+	if (!(netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT)))
 		return;
 
 	switch (type) {
diff --git a/drivers/net/ethernet/netronome/nfp/nfdk/dp.c b/drivers/net/ethernet/netronome/nfp/nfdk/dp.c
index 2b427d8ccb2f..e46fd9b392af 100644
--- a/drivers/net/ethernet/netronome/nfp/nfdk/dp.c
+++ b/drivers/net/ethernet/netronome/nfp/nfdk/dp.c
@@ -650,7 +650,7 @@ nfp_nfdk_rx_csum(struct nfp_net_dp *dp, struct nfp_net_r_vector *r_vec,
 {
 	skb_checksum_none_assert(skb);
 
-	if (!(dp->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(dp->netdev, NETIF_F_RXCSUM_BIT))
 		return;
 
 	if (meta->csum_type) {
@@ -694,7 +694,7 @@ static void
 nfp_nfdk_set_hash(struct net_device *netdev, struct nfp_meta_parsed *meta,
 		  unsigned int type, __be32 *hash)
 {
-	if (!(netdev->features & NETIF_F_RXHASH))
+	if (!(netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT)))
 		return;
 
 	switch (type) {
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 84b36d529428..8bcf75169a93 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1673,8 +1673,8 @@ static int nfp_net_set_features(struct net_device *netdev,
 
 	new_ctrl = nn->dp.ctrl;
 
-	if (changed & NETIF_F_RXCSUM) {
-		if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 			new_ctrl |= nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_RXCSUM_ANY;
@@ -1695,38 +1695,38 @@ static int nfp_net_set_features(struct net_device *netdev,
 			new_ctrl &= ~NFP_NET_CFG_CTRL_LSO_ANY;
 	}
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
-		if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 			new_ctrl |= nn->cap & NFP_NET_CFG_CTRL_RXVLAN_V2 ?:
 				    NFP_NET_CFG_CTRL_RXVLAN;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_RXVLAN_ANY;
 	}
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_TX) {
-		if (features & NETIF_F_HW_VLAN_CTAG_TX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features))
 			new_ctrl |= nn->cap & NFP_NET_CFG_CTRL_TXVLAN_V2 ?:
 				    NFP_NET_CFG_CTRL_TXVLAN;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_TXVLAN_ANY;
 	}
 
-	if (changed & 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, changed)) {
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
 			new_ctrl |= NFP_NET_CFG_CTRL_CTAG_FILTER;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_CTAG_FILTER;
 	}
 
-	if (changed & NETIF_F_HW_VLAN_STAG_RX) {
-		if (features & NETIF_F_HW_VLAN_STAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_RX_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_RX_BIT, features))
 			new_ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ;
 	}
 
-	if (changed & NETIF_F_SG) {
-		if (features & NETIF_F_SG)
+	if (netdev_feature_test(NETIF_F_SG_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_SG_BIT, features))
 			new_ctrl |= NFP_NET_CFG_CTRL_GATHER;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_GATHER;
@@ -1757,16 +1757,16 @@ static netdev_features_t
 nfp_net_fix_features(struct net_device *netdev,
 		     netdev_features_t features)
 {
-	if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
-	    (features & NETIF_F_HW_VLAN_STAG_RX)) {
-		if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) &&
+	    netdev_feature_test(NETIF_F_HW_VLAN_STAG_RX_BIT, features)) {
+		if (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
 			netdev_feature_del(NETIF_F_HW_VLAN_CTAG_RX_BIT,
 					   &features);
 			netdev_wanted_feature_del(netdev,
 						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 			netdev_warn(netdev,
 				    "S-tag and C-tag stripping can't be enabled at the same time. Enabling S-tag stripping and disabling C-tag stripping\n");
-		} else if (netdev->features & NETIF_F_HW_VLAN_STAG_RX) {
+		} else if (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_STAG_RX_BIT)) {
 			netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT,
 					   &features);
 			netdev_wanted_feature_del(netdev,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c
index c224707f763f..01a1fbf9aa0d 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c
@@ -66,7 +66,8 @@ int nfp_port_set_features(struct net_device *netdev, netdev_features_t features)
 	if (!port)
 		return 0;
 
-	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) &&
 	    port->tc_offload_cnt) {
 		netdev_err(netdev, "Cannot disable HW TC offload while offloads active\n");
 		return -EBUSY;
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 84087466e6f4..7fd4f3519414 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -3053,7 +3053,7 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
 			 * here. Even if vlan rx accel is disabled,
 			 * NV_RX3_VLAN_TAG_PRESENT is pseudo randomly set.
 			 */
-			if (dev->features & NETIF_F_HW_VLAN_CTAG_RX &&
+			if (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 			    vlanflags & NV_RX3_VLAN_TAG_PRESENT) {
 				u16 vid = vlanflags & NV_RX3_VLAN_TAG_MASK;
 
@@ -4881,7 +4881,7 @@ static int nv_set_loopback(struct net_device *dev, netdev_features_t features)
 
 	spin_lock_irqsave(&np->lock, flags);
 	miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
-	if (features & NETIF_F_LOOPBACK) {
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features)) {
 		if (miicontrol & BMCR_LOOPBACK) {
 			spin_unlock_irqrestore(&np->lock, flags);
 			netdev_info(dev, "Loopback already enabled\n");
@@ -4943,12 +4943,12 @@ static void nv_vlan_mode(struct net_device *dev, netdev_features_t features)
 
 	spin_lock_irq(&np->lock);
 
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP;
 	else
 		np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP;
 
-	if (features & NETIF_F_HW_VLAN_CTAG_TX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features))
 		np->txrxctl_bits |= NVREG_TXRXCTL_VLANINS;
 	else
 		np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS;
@@ -4965,16 +4965,16 @@ static int nv_set_features(struct net_device *dev, netdev_features_t features)
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	int retval;
 
-	if ((changed & NETIF_F_LOOPBACK) && netif_running(dev)) {
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed) && netif_running(dev)) {
 		retval = nv_set_loopback(dev, features);
 		if (retval != 0)
 			return retval;
 	}
 
-	if (changed & NETIF_F_RXCSUM) {
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		spin_lock_irq(&np->lock);
 
-		if (features & NETIF_F_RXCSUM)
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 			np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
 		else
 			np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK;
@@ -5616,7 +5616,7 @@ static int nv_open(struct net_device *dev)
 	/* If the loopback feature was set while the device was down, make sure
 	 * that it's set correctly now.
 	 */
-	if (dev->features & NETIF_F_LOOPBACK)
+	if (netdev_active_feature_test(dev, NETIF_F_LOOPBACK_BIT))
 		nv_set_loopback(dev, dev->features);
 
 	return 0;
@@ -6124,12 +6124,12 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 		 dev->name, np->phy_oui, np->phyaddr, dev->dev_addr);
 
 	dev_info(&pci_dev->dev, "%s%s%s%s%s%s%s%s%s%s%sdesc-v%u\n",
-		 dev->features & NETIF_F_HIGHDMA ? "highdma " : "",
-		 (dev->features & NETIF_F_IP_CSUM || dev->features & NETIF_F_SG) ?
-			"csum " : "",
+		 netdev_active_feature_test(dev, NETIF_F_HIGHDMA_BIT) ? "highdma " : "",
+		 (netdev_active_feature_test(dev, NETIF_F_IP_CSUM_BIT) ||
+		  netdev_active_feature_test(dev, NETIF_F_SG_BIT)) ? "csum " : "",
 		 dev->features & netdev_ctag_vlan_offload_features ?
 			"vlan " : "",
-		 dev->features & (NETIF_F_LOOPBACK) ?
+		 netdev_active_feature_test(dev, NETIF_F_LOOPBACK_BIT) ?
 			"loopback " : "",
 		 id->driver_data & DEV_HAS_POWER_CNTRL ? "pwrctl " : "",
 		 id->driver_data & DEV_HAS_MGMT_UNIT ? "mgmt " : "",
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 371efa0ed0a2..c7eec92dffcf 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -2208,7 +2208,7 @@ static int pch_gbe_set_features(struct net_device *netdev,
 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 
-	if (!(changed & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
 	if (netif_running(netdev))
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 12301e08c52f..75273f473caa 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1368,37 +1368,37 @@ static __le64 ionic_netdev_features_to_nic(netdev_features_t features)
 {
 	u64 wanted = 0;
 
-	if (features & NETIF_F_HW_VLAN_CTAG_TX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features))
 		wanted |= IONIC_ETH_HW_VLAN_TX_TAG;
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		wanted |= IONIC_ETH_HW_VLAN_RX_STRIP;
-	if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
 		wanted |= IONIC_ETH_HW_VLAN_RX_FILTER;
-	if (features & NETIF_F_RXHASH)
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features))
 		wanted |= IONIC_ETH_HW_RX_HASH;
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		wanted |= IONIC_ETH_HW_RX_CSUM;
-	if (features & NETIF_F_SG)
+	if (netdev_feature_test(NETIF_F_SG_BIT, features))
 		wanted |= IONIC_ETH_HW_TX_SG;
-	if (features & NETIF_F_HW_CSUM)
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features))
 		wanted |= IONIC_ETH_HW_TX_CSUM;
-	if (features & NETIF_F_TSO)
+	if (netdev_feature_test(NETIF_F_TSO_BIT, features))
 		wanted |= IONIC_ETH_HW_TSO;
-	if (features & NETIF_F_TSO6)
+	if (netdev_feature_test(NETIF_F_TSO6_BIT, features))
 		wanted |= IONIC_ETH_HW_TSO_IPV6;
-	if (features & NETIF_F_TSO_ECN)
+	if (netdev_feature_test(NETIF_F_TSO_ECN_BIT, features))
 		wanted |= IONIC_ETH_HW_TSO_ECN;
-	if (features & NETIF_F_GSO_GRE)
+	if (netdev_feature_test(NETIF_F_GSO_GRE_BIT, features))
 		wanted |= IONIC_ETH_HW_TSO_GRE;
-	if (features & NETIF_F_GSO_GRE_CSUM)
+	if (netdev_feature_test(NETIF_F_GSO_GRE_CSUM_BIT, features))
 		wanted |= IONIC_ETH_HW_TSO_GRE_CSUM;
-	if (features & NETIF_F_GSO_IPXIP4)
+	if (netdev_feature_test(NETIF_F_GSO_IPXIP4_BIT, features))
 		wanted |= IONIC_ETH_HW_TSO_IPXIP4;
-	if (features & NETIF_F_GSO_IPXIP6)
+	if (netdev_feature_test(NETIF_F_GSO_IPXIP6_BIT, features))
 		wanted |= IONIC_ETH_HW_TSO_IPXIP6;
-	if (features & NETIF_F_GSO_UDP_TUNNEL)
+	if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_BIT, features))
 		wanted |= IONIC_ETH_HW_TSO_UDP;
-	if (features & NETIF_F_GSO_UDP_TUNNEL_CSUM)
+	if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features))
 		wanted |= IONIC_ETH_HW_TSO_UDP_CSUM;
 
 	return cpu_to_le64(wanted);
@@ -1981,7 +1981,7 @@ static int ionic_txrx_init(struct ionic_lif *lif)
 		}
 	}
 
-	if (lif->netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(lif->netdev, NETIF_F_RXHASH_BIT))
 		ionic_lif_rss_init(lif);
 
 	ionic_lif_rx_mode(lif);
@@ -3062,7 +3062,7 @@ void ionic_lif_deinit(struct ionic_lif *lif)
 		cancel_work_sync(&lif->deferred.work);
 		cancel_work_sync(&lif->tx_timeout_work);
 		ionic_rx_filters_deinit(lif);
-		if (lif->netdev->features & NETIF_F_RXHASH)
+		if (netdev_active_feature_test(lif->netdev, NETIF_F_RXHASH_BIT))
 			ionic_lif_rss_deinit(lif);
 	}
 
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
index c03986bf2628..c9e89ce54c0d 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
@@ -247,7 +247,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
 
 	skb_record_rx_queue(skb, q->index);
 
-	if (likely(netdev->features & NETIF_F_RXHASH)) {
+	if (likely(netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT))) {
 		switch (comp->pkt_type_color & IONIC_RXQ_COMP_PKT_TYPE_MASK) {
 		case IONIC_PKT_TYPE_IPV4:
 		case IONIC_PKT_TYPE_IPV6:
@@ -264,7 +264,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
 		}
 	}
 
-	if (likely(netdev->features & NETIF_F_RXCSUM) &&
+	if (likely(netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) &&
 	    (comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_CALC)) {
 		skb->ip_summed = CHECKSUM_COMPLETE;
 		skb->csum = (__force __wsum)le16_to_cpu(comp->csum);
@@ -278,7 +278,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
 		     (comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_IP_BAD)))
 		stats->csum_error++;
 
-	if (likely(netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (likely(netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) &&
 	    (comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_VLAN)) {
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
 				       le16_to_cpu(comp->vlan_tci));
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
index 35ec9aab3dc7..15eb5cd4e3db 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
@@ -1497,8 +1497,8 @@ static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
 	if (!skb)
 		goto no_skb;
 
-	if (likely((adapter->netdev->features & NETIF_F_RXCSUM)
-	    && cksum == STATUS_CKSUM_OK)) {
+	if (likely(netdev_active_feature_test(adapter->netdev, NETIF_F_RXCSUM_BIT) &&
+		   cksum == STATUS_CKSUM_OK)) {
 		adapter->stats.csummed++;
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	} else
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 09185d28552c..30bc427dba46 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -523,7 +523,7 @@ static void netxen_set_multicast_list(struct net_device *dev)
 static netdev_features_t netxen_fix_features(struct net_device *dev,
 	netdev_features_t features)
 {
-	if (!(features & NETIF_F_RXCSUM)) {
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
 		netdev_info(dev, "disabling LRO as RXCSUM is off\n");
 
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
@@ -540,16 +540,17 @@ static int netxen_set_features(struct net_device *dev,
 	int hw_lro;
 
 	changed = netdev_active_features_xor(dev, features);
-	if (!(changed & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, changed))
 		return 0;
 
-	hw_lro = (features & NETIF_F_LRO) ? NETXEN_NIC_LRO_ENABLED
-	         : NETXEN_NIC_LRO_DISABLED;
+	hw_lro = netdev_feature_test(NETIF_F_LRO_BIT, features) ?
+		NETXEN_NIC_LRO_ENABLED : NETXEN_NIC_LRO_DISABLED;
 
 	if (netxen_config_hw_lro(adapter, hw_lro))
 		return -EIO;
 
-	if (!(features & NETIF_F_LRO) && netxen_send_lro_cleanup(adapter))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, features) &&
+	    netxen_send_lro_cleanup(adapter))
 		return -EIO;
 
 	return 0;
@@ -1123,7 +1124,7 @@ __netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 		netxen_config_intr_coalesce(adapter);
 
-	if (netdev->features & NETIF_F_LRO)
+	if (netdev_active_feature_test(netdev, NETIF_F_LRO_BIT))
 		netxen_config_hw_lro(adapter, NETXEN_NIC_LRO_ENABLED);
 
 	netxen_napi_enable(adapter);
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index 7a824b79cbcd..f416aed61ab0 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -916,7 +916,7 @@ netdev_features_t qede_fix_features(struct net_device *dev,
 	struct qede_dev *edev = netdev_priv(dev);
 
 	if (edev->xdp_prog || edev->ndev->mtu > PAGE_SIZE ||
-	    !(features & NETIF_F_GRO))
+	    !netdev_feature_test(NETIF_F_GRO_BIT, features))
 		netdev_feature_del(NETIF_F_GRO_HW_BIT, &features);
 
 	return features;
@@ -928,7 +928,7 @@ int qede_set_features(struct net_device *dev, netdev_features_t features)
 	netdev_features_t changes = netdev_active_features_xor(dev, features);
 	bool need_reload = false;
 
-	if (changes & NETIF_F_GRO_HW)
+	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, changes))
 		need_reload = true;
 
 	if (need_reload) {
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 832a4dc8d89c..2f5309023b0f 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1624,7 +1624,7 @@ static int qede_alloc_mem_rxq(struct qede_dev *edev, struct qede_rx_queue *rxq)
 		}
 	}
 
-	edev->gro_disable = !(edev->ndev->features & NETIF_F_GRO_HW);
+	edev->gro_disable = !netdev_active_feature_test(edev->ndev, NETIF_F_GRO_HW_BIT);
 	if (!edev->gro_disable)
 		qede_set_tpa_param(rxq);
 err:
@@ -2807,9 +2807,9 @@ static void qede_get_generic_tlv_data(void *dev, struct qed_generic_tlvs *data)
 	struct netdev_hw_addr *ha;
 	int i;
 
-	if (edev->ndev->features & NETIF_F_IP_CSUM)
+	if (netdev_active_feature_test(edev->ndev, NETIF_F_IP_CSUM_BIT))
 		data->feat_flags |= QED_TLV_IP_CSUM;
-	if (edev->ndev->features & NETIF_F_TSO)
+	if (netdev_active_feature_test(edev->ndev, NETIF_F_TSO_BIT))
 		data->feat_flags |= QED_TLV_LSO;
 
 	ether_addr_copy(data->mac[0], edev->ndev->dev_addr);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 8dcb1cfdb5ba..4fd623d65921 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1086,7 +1086,7 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 		}
 	}
 
-	if (!(features & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	return features;
@@ -1097,9 +1097,9 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
-	int hw_lro = (features & NETIF_F_LRO) ? QLCNIC_LRO_ENABLED : 0;
+	int hw_lro = netdev_feature_test(NETIF_F_LRO_BIT, features) ? QLCNIC_LRO_ENABLED : 0;
 
-	if (!(changed & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, changed))
 		return 0;
 
 	netdev_active_feature_change(netdev, NETIF_F_LRO_BIT);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 9da5e97f8a0a..7a2604557d71 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -1152,7 +1152,7 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
 			 DMA_FROM_DEVICE);
 
 	skb = buffer->skb;
-	if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
+	if (likely(netdev_active_feature_test(adapter->netdev, NETIF_F_RXCSUM_BIT) &&
 		   (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
 		adapter->stats.csummed++;
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index fa06ba45e8dc..aedd932400f2 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -1889,7 +1889,7 @@ int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
 
 	qlcnic_config_def_intr_coalesce(adapter);
 
-	if (netdev->features & NETIF_F_LRO)
+	if (netdev_active_feature_test(netdev, NETIF_F_LRO_BIT))
 		qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
 
 	set_bit(__QLCNIC_DEV_UP, &adapter->state);
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
index 0d80447d4d3b..ce22330ea963 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
@@ -286,7 +286,7 @@ void emac_mac_mode_config(struct emac_adapter *adpt)
 	mac = readl(adpt->base + EMAC_MAC_CTRL);
 	mac &= ~(VLAN_STRIP | PROM_MODE | MULTI_ALL | MAC_LP_EN);
 
-	if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		mac |= VLAN_STRIP;
 
 	if (netdev->flags & IFF_PROMISC)
@@ -1143,7 +1143,7 @@ void emac_mac_rx_process(struct emac_adapter *adpt, struct emac_rx_queue *rx_q,
 		skb_put(skb, RRD_PKT_SIZE(&rrd) - ETH_FCS_LEN);
 		skb->dev = netdev;
 		skb->protocol = eth_type_trans(skb, skb->dev);
-		if (netdev->features & NETIF_F_RXCSUM)
+		if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT))
 			skb->ip_summed = RRD_L4F(&rrd) ?
 					  CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
 		else
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
index 0b06f9875b56..2595fe837c78 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
@@ -404,7 +404,7 @@ int rmnet_map_checksum_downlink_packet(struct sk_buff *skb, u16 len)
 	struct rmnet_priv *priv = netdev_priv(skb->dev);
 	struct rmnet_map_dl_csum_trailer *csum_trailer;
 
-	if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM))) {
+	if (unlikely(!netdev_active_feature_test(skb->dev, NETIF_F_RXCSUM_BIT))) {
 		priv->stats.csum_sw++;
 		return -EOPNOTSUPP;
 	}
@@ -503,7 +503,7 @@ int rmnet_map_process_next_hdr_packet(struct sk_buff *skb,
 	if (nexthdr_type != RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD)
 		return -EINVAL;
 
-	if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM))) {
+	if (unlikely(!netdev_active_feature_test(skb->dev, NETIF_F_RXCSUM_BIT))) {
 		priv->stats.csum_sw++;
 	} else if (next_hdr->csum_info & MAPV5_CSUMINFO_VALID_FLAG) {
 		priv->stats.csum_ok++;
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index d34d3f0ef041..b80f98819d03 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1465,17 +1465,17 @@ static int cp_set_features(struct net_device *dev, netdev_features_t features)
 	struct cp_private *cp = netdev_priv(dev);
 	unsigned long flags;
 
-	if (!(changed & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
 	spin_lock_irqsave(&cp->lock, flags);
 
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		cp->cpcmd |= RxChkSum;
 	else
 		cp->cpcmd &= ~RxChkSum;
 
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		cp->cpcmd |= RxVlanOn;
 	else
 		cp->cpcmd &= ~RxVlanOn;
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 4206c6b31802..269d3c2136eb 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -905,14 +905,14 @@ static int rtl8139_set_features(struct net_device *dev, netdev_features_t featur
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 	void __iomem *ioaddr = tp->mmio_addr;
 
-	if (!(changed & NETIF_F_RXALL))
+	if (!netdev_feature_test(NETIF_F_RXALL_BIT, changed))
 		return 0;
 
 	spin_lock_irqsave(&tp->lock, flags);
 
-	if (changed & NETIF_F_RXALL) {
+	if (netdev_feature_test(NETIF_F_RXALL_BIT, changed)) {
 		int rx_mode = tp->rx_config;
-		if (features & NETIF_F_RXALL)
+		if (netdev_feature_test(NETIF_F_RXALL_BIT, features))
 			rx_mode |= (AcceptErr | AcceptRunt);
 		else
 			rx_mode &= ~(AcceptErr | AcceptRunt);
@@ -1975,7 +1975,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 		/* read size+status of next frame from DMA ring buffer */
 		rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset));
 		rx_size = rx_status >> 16;
-		if (likely(!(dev->features & NETIF_F_RXFCS)))
+		if (likely(!netdev_active_feature_test(dev, NETIF_F_RXFCS_BIT)))
 			pkt_size = rx_size - 4;
 		else
 			pkt_size = rx_size;
@@ -2016,7 +2016,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 		if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
 			     (rx_size < 8) ||
 			     (!(rx_status & RxStatusOK)))) {
-			if ((dev->features & NETIF_F_RXALL) &&
+			if (netdev_active_feature_test(dev, NETIF_F_RXALL_BIT) &&
 			    (rx_size <= (MAX_ETH_FRAME_SIZE + 4)) &&
 			    (rx_size >= 8) &&
 			    (!(rx_status & RxStatusOK))) {
@@ -2587,7 +2587,7 @@ static void __set_rx_mode (struct net_device *dev)
 		}
 	}
 
-	if (dev->features & NETIF_F_RXALL)
+	if (netdev_active_feature_test(dev, NETIF_F_RXALL_BIT))
 		rx_mode |= (AcceptErr | AcceptRunt);
 
 	/* We can safely update without stopping the chip. */
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 80caddaf0c3d..1ceb90fd4937 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1459,13 +1459,13 @@ static void rtl_set_rx_config_features(struct rtl8169_private *tp,
 {
 	u32 rx_config = RTL_R32(tp, RxConfig);
 
-	if (features & NETIF_F_RXALL)
+	if (netdev_feature_test(NETIF_F_RXALL_BIT, features))
 		rx_config |= RX_CONFIG_ACCEPT_ERR_MASK;
 	else
 		rx_config &= ~RX_CONFIG_ACCEPT_ERR_MASK;
 
 	if (rtl_is_8125(tp)) {
-		if (features & NETIF_F_HW_VLAN_CTAG_RX)
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 			rx_config |= RX_VLAN_8125;
 		else
 			rx_config &= ~RX_VLAN_8125;
@@ -1481,13 +1481,13 @@ static int rtl8169_set_features(struct net_device *dev,
 
 	rtl_set_rx_config_features(tp, features);
 
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		tp->cp_cmd |= RxChkSum;
 	else
 		tp->cp_cmd &= ~RxChkSum;
 
 	if (!rtl_is_8125(tp)) {
-		if (features & NETIF_F_HW_VLAN_CTAG_RX)
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 			tp->cp_cmd |= RxVlan;
 		else
 			tp->cp_cmd &= ~RxVlan;
@@ -4549,14 +4549,14 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, int budget
 			if (status & RxCRC)
 				dev->stats.rx_crc_errors++;
 
-			if (!(dev->features & NETIF_F_RXALL))
+			if (!(netdev_active_feature_test(dev, NETIF_F_RXALL_BIT)))
 				goto release_descriptor;
 			else if (status & RxRWT || !(status & (RxRUNT | RxCRC)))
 				goto release_descriptor;
 		}
 
 		pkt_size = status & GENMASK(13, 0);
-		if (likely(!(dev->features & NETIF_F_RXFCS)))
+		if (likely(!(netdev_active_feature_test(dev, NETIF_F_RXFCS_BIT))))
 			pkt_size -= ETH_FCS_LEN;
 
 		/* The driver does not support incoming fragmented frames.
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index a994062c7462..64d207806bdf 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -554,7 +554,7 @@ static void ravb_emac_init_rcar(struct net_device *ndev)
 
 	/* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */
 	ravb_write(ndev, ECMR_ZPF | ECMR_DM |
-		   (ndev->features & NETIF_F_RXCSUM ? ECMR_RCSC : 0) |
+		   (netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT) ? ECMR_RCSC : 0) |
 		   ECMR_TE | ECMR_RE, ECMR);
 
 	ravb_set_rate_rcar(ndev);
@@ -953,7 +953,7 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
 
 			skb_put(skb, pkt_len);
 			skb->protocol = eth_type_trans(skb, ndev);
-			if (ndev->features & NETIF_F_RXCSUM)
+			if (netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT))
 				ravb_rx_csum(skb);
 			napi_gro_receive(&priv->napi[q], skb);
 			stats->rx_packets++;
@@ -2338,8 +2338,9 @@ static int ravb_set_features_rcar(struct net_device *ndev,
 {
 	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 
-	if (changed & NETIF_F_RXCSUM)
-		ravb_set_rx_csum(ndev, features & NETIF_F_RXCSUM);
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
+		ravb_set_rx_csum(ndev,
+				 netdev_feature_test(NETIF_F_RXCSUM_BIT, features));
 
 	ndev->features = features;
 
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index a393796f721a..c737550bbbfb 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1507,7 +1507,7 @@ static int sh_eth_dev_init(struct net_device *ndev)
 
 	/* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */
 	sh_eth_write(ndev, ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) |
-		     (ndev->features & NETIF_F_RXCSUM ? ECMR_RCSC : 0) |
+		     (netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT) ? ECMR_RCSC : 0) |
 		     ECMR_TE | ECMR_RE, ECMR);
 
 	if (mdp->cd->set_rate)
@@ -1657,7 +1657,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
 					 DMA_FROM_DEVICE);
 			skb_put(skb, pkt_len);
 			skb->protocol = eth_type_trans(skb, ndev);
-			if (ndev->features & NETIF_F_RXCSUM)
+			if (netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT))
 				sh_eth_rx_csum(skb);
 			netif_receive_skb(skb);
 			ndev->stats.rx_packets++;
@@ -2935,8 +2935,9 @@ static int sh_eth_set_features(struct net_device *ndev,
 	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 
-	if (changed & NETIF_F_RXCSUM && mdp->cd->rx_csum)
-		sh_eth_set_rx_csum(ndev, features & NETIF_F_RXCSUM);
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed) && mdp->cd->rx_csum)
+		sh_eth_set_rx_csum(ndev,
+				   netdev_feature_test(NETIF_F_RXCSUM_BIT, features));
 
 	ndev->features = features;
 
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 6f41b11e5570..ea6103a4797d 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -1781,8 +1781,8 @@ static int sxgbe_set_features(struct net_device *dev,
 	struct sxgbe_priv_data *priv = netdev_priv(dev);
 	netdev_features_t changed = netdev_active_features_xor(dev, features);
 
-	if (changed & NETIF_F_RXCSUM) {
-		if (features & NETIF_F_RXCSUM) {
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
 			priv->hw->mac->enable_rx_csum(priv->ioaddr);
 			priv->rxcsum_insertion = true;
 		} else {
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 351ee0954053..7d48a5375a4f 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -2715,7 +2715,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_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
index 73ae4656a6e7..dcefd2f11b1a 100644
--- a/drivers/net/ethernet/sfc/ef100_rep.c
+++ b/drivers/net/ethernet/sfc/ef100_rep.c
@@ -216,8 +216,8 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,
 	net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops;
 	net_dev->min_mtu = EFX_MIN_MTU;
 	net_dev->max_mtu = EFX_MAX_MTU;
-	net_dev->features |= NETIF_F_LLTX;
-	net_dev->hw_features |= NETIF_F_LLTX;
+	netdev_active_feature_add(net_dev, NETIF_F_LLTX_BIT);
+	netdev_hw_feature_add(net_dev, NETIF_F_LLTX_BIT);
 	return efv;
 fail1:
 	free_netdev(net_dev);
diff --git a/drivers/net/ethernet/sfc/ef100_rx.c b/drivers/net/ethernet/sfc/ef100_rx.c
index 65bbe37753e6..dcdca4cddc67 100644
--- a/drivers/net/ethernet/sfc/ef100_rx.c
+++ b/drivers/net/ethernet/sfc/ef100_rx.c
@@ -68,7 +68,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));
@@ -111,7 +111,7 @@ void __ef100_rx_packet(struct efx_channel *channel)
 		goto free_rx_buffer;
 	}
 
-	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 102ddc7e206a..a6c8ae23faeb 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.c b/drivers/net/ethernet/sfc/efx.c
index e1d273770336..115740d4d95e 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1016,8 +1016,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 	/* Determine netdevice 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))
+	if (netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, *efx->type->offload_features) ||
+	    netdev_feature_test(NETIF_F_HW_CSUM_BIT, *efx->type->offload_features))
 		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))
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index a5c47141e965..a4366c23b50f 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -218,7 +218,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;
@@ -228,8 +228,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 c8f52ad7fb83..60f2152ec755 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -1689,7 +1689,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 (netdev_feature_test(NETIF_F_NTUPLE_BIT, *efx->type->offload_features)) {
 		struct ef4_channel *channel;
 		int i, success = 1;
 
@@ -2187,7 +2187,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;
@@ -2195,7 +2195,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 6bbdb5d2eebf..e3edf8ef2eb7 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/mcdi_filters.c b/drivers/net/ethernet/sfc/mcdi_filters.c
index dc6342710233..fcc71a9f4e14 100644
--- a/drivers/net/ethernet/sfc/mcdi_filters.c
+++ b/drivers/net/ethernet/sfc/mcdi_filters.c
@@ -1323,7 +1323,7 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining)
 		rc = efx_mcdi_filter_table_probe_matches(efx, table, true);
 	if (rc)
 		goto fail;
-	if ((efx_supported_features(efx) & NETIF_F_HW_VLAN_CTAG_FILTER) &&
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, efx_supported_features(efx)) &&
 	    !(efx_mcdi_filter_match_supported(table, false,
 		(EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC)) &&
 	      efx_mcdi_filter_match_supported(table, false,
@@ -1347,7 +1347,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);
 
@@ -1764,7 +1764,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 ab83fd836031..c0a5ace7af55 100644
--- a/drivers/net/ethernet/sfc/rx_common.c
+++ b/drivers/net/ethernet/sfc/rx_common.c
@@ -520,7 +520,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);
@@ -798,7 +798,8 @@ 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/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index d9e7e729e507..22812c48dda6 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -998,8 +998,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 	/* Determine netdevice 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))
+	if (netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, *efx->type->offload_features) ||
+	    netdev_feature_test(NETIF_F_HW_CSUM_BIT, *efx->type->offload_features))
 		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))
diff --git a/drivers/net/ethernet/sfc/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 0916336e4901..6f547c54e3f1 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -216,7 +216,8 @@ int efx_siena_set_features(struct net_device *net_dev, netdev_features_t data)
 	int rc;
 
 	/* If disabling RX n-tuple filtering, clear existing filters */
-	if ((net_dev->features & NETIF_F_NTUPLE) && !(data & NETIF_F_NTUPLE)) {
+	if (netdev_active_feature_test(net_dev, NETIF_F_NTUPLE_BIT) &&
+	    !netdev_feature_test(NETIF_F_NTUPLE_BIT, data)) {
 		rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
 		if (rc)
 			return rc;
@@ -226,7 +227,8 @@ int efx_siena_set_features(struct net_device *net_dev, netdev_features_t data)
 	 * If rx-fcs is changed, mac_reconfigure updates that too.
 	 */
 	features = netdev_active_features_xor(net_dev, data);
-	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) || (features & NETIF_F_RXFCS)) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) ||
+	    netdev_feature_test(NETIF_F_RXFCS_BIT, features)) {
 		/* efx_siena_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/siena/farch.c b/drivers/net/ethernet/sfc/siena/farch.c
index 89ccd65c978b..3047cf1c50cf 100644
--- a/drivers/net/ethernet/sfc/siena/farch.c
+++ b/drivers/net/ethernet/sfc/siena/farch.c
@@ -923,7 +923,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/siena/mcdi_port_common.c b/drivers/net/ethernet/sfc/siena/mcdi_port_common.c
index 067fe0f4393a..012cae6eb990 100644
--- a/drivers/net/ethernet/sfc/siena/mcdi_port_common.c
+++ b/drivers/net/ethernet/sfc/siena/mcdi_port_common.c
@@ -1119,7 +1119,7 @@ int efx_siena_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/siena/rx.c b/drivers/net/ethernet/sfc/siena/rx.c
index 98d3c0743c0f..36729823ffd9 100644
--- a/drivers/net/ethernet/sfc/siena/rx.c
+++ b/drivers/net/ethernet/sfc/siena/rx.c
@@ -387,7 +387,7 @@ void __efx_siena_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/siena/rx_common.c b/drivers/net/ethernet/sfc/siena/rx_common.c
index be17b8676fff..7d98d0af06d9 100644
--- a/drivers/net/ethernet/sfc/siena/rx_common.c
+++ b/drivers/net/ethernet/sfc/siena/rx_common.c
@@ -525,7 +525,7 @@ efx_siena_rx_packet_gro(struct efx_channel *channel,
 		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, efx_rx_buf_hash(efx, eh),
 			     PKT_HASH_TYPE_L3);
 	if (csum) {
@@ -805,7 +805,7 @@ int efx_siena_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/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index 84227eb0e3a4..7eb77aed3724 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -397,7 +397,7 @@ static inline void ioc3_rx(struct net_device *dev)
 				goto next;
 			}
 
-			if (likely(dev->features & NETIF_F_RXCSUM))
+			if (likely(netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT)))
 				ioc3_tcpudp_checksum(skb,
 						     w0 & ERXBUF_IPCKSUM_MASK,
 						     len);
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 67fba95978b4..4db2a8208d74 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -1752,7 +1752,7 @@ static int netsec_netdev_set_features(struct net_device *ndev,
 {
 	struct netsec_priv *priv = netdev_priv(ndev);
 
-	priv->rx_cksum_offload_flag = !!(features & NETIF_F_RXCSUM);
+	priv->rx_cksum_offload_flag = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index d8f1fbc25bdd..c51d236cb966 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -719,7 +719,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
 	}
 
 	/* VLAN filtering */
-	if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+	if (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		value |= GMAC_PACKET_FILTER_VTFE;
 
 	writel(value, ioaddr + GMAC_PACKET_FILTER);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e6a13888d4c8..f226c03c3405 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3157,7 +3157,7 @@ static void stmmac_mac_config_rss(struct stmmac_priv *priv)
 		return;
 	}
 
-	if (priv->dev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(priv->dev, NETIF_F_RXHASH_BIT))
 		priv->rss.enable = true;
 	else
 		priv->rss.enable = false;
@@ -4531,9 +4531,9 @@ static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
 	vlan_proto = veth->h_vlan_proto;
 
 	if ((vlan_proto == htons(ETH_P_8021Q) &&
-	     dev->features & NETIF_F_HW_VLAN_CTAG_RX) ||
+	     netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) ||
 	    (vlan_proto == htons(ETH_P_8021AD) &&
-	     dev->features & NETIF_F_HW_VLAN_STAG_RX)) {
+	     netdev_active_feature_test(dev, NETIF_F_HW_VLAN_STAG_RX_BIT))) {
 		/* pop the vlan tag */
 		vlanid = ntohs(veth->h_vlan_TCI);
 		memmove(skb->data + VLAN_HLEN, veth, ETH_ALEN * 2);
@@ -5621,7 +5621,7 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
 
 	/* Disable tso if asked by ethtool */
 	if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
-		if (features & NETIF_F_TSO)
+		if (netdev_feature_test(NETIF_F_TSO_BIT, features))
 			priv->tso = true;
 		else
 			priv->tso = false;
@@ -5636,7 +5636,7 @@ static int stmmac_set_features(struct net_device *netdev,
 	struct stmmac_priv *priv = netdev_priv(netdev);
 
 	/* Keep the COE Type in case of csum is supporting */
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		priv->hw->rx_csum = priv->plat->rx_coe;
 	else
 		priv->hw->rx_csum = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
index 49af7e78b7f5..c632b335b41c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
@@ -974,7 +974,7 @@ static int stmmac_test_vlanfilt_perfect(struct stmmac_priv *priv)
 {
 	int ret, prev_cap = priv->dma_cap.vlhash;
 
-	if (!(priv->dev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+	if (!netdev_active_feature_test(priv->dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		return -EOPNOTSUPP;
 
 	priv->dma_cap.vlhash = 0;
@@ -1068,7 +1068,7 @@ static int stmmac_test_dvlanfilt_perfect(struct stmmac_priv *priv)
 {
 	int ret, prev_cap = priv->dma_cap.vlhash;
 
-	if (!(priv->dev->features & NETIF_F_HW_VLAN_STAG_FILTER))
+	if (!netdev_active_feature_test(priv->dev, NETIF_F_HW_VLAN_STAG_FILTER_BIT))
 		return -EOPNOTSUPP;
 
 	priv->dma_cap.vlhash = 0;
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index bc531188b957..d104c9ded9dc 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -3492,7 +3492,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
 	__pskb_pull_tail(skb, len);
 
 	rh = (struct rx_pkt_hdr1 *) skb->data;
-	if (np->dev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(np->dev, NETIF_F_RXHASH_BIT))
 		skb_set_hash(skb,
 			     ((u32)rh->hashval2_0 << 24 |
 			      (u32)rh->hashval2_1 << 16 |
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index ef90119e1636..2a3e987068ff 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -843,7 +843,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
 			skb = copy_skb;
 		}
 
-		if (likely(dev->features & NETIF_F_RXCSUM)) {
+		if (likely(netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT))) {
 			__sum16 csum;
 
 			csum = (__force __sum16)htons((status & RXDCTRL_TCPCSUM) ^ 0xffff);
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c
index 76eb7db80f13..bbbe3409ce63 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c
@@ -263,7 +263,7 @@ static int xlgmac_set_promiscuous_mode(struct xlgmac_pdata *pdata,
 	if (enable) {
 		xlgmac_disable_rx_vlan_filtering(pdata);
 	} else {
-		if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+		if (netdev_active_feature_test(pdata->netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 			xlgmac_enable_rx_vlan_filtering(pdata);
 	}
 
@@ -404,7 +404,7 @@ static void xlgmac_config_jumbo_enable(struct xlgmac_pdata *pdata)
 
 static void xlgmac_config_checksum_offload(struct xlgmac_pdata *pdata)
 {
-	if (pdata->netdev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(pdata->netdev, NETIF_F_RXCSUM_BIT))
 		xlgmac_enable_rx_csum(pdata);
 	else
 		xlgmac_disable_rx_csum(pdata);
@@ -425,12 +425,12 @@ static void xlgmac_config_vlan_support(struct xlgmac_pdata *pdata)
 	/* Set the current VLAN Hash Table register value */
 	xlgmac_update_vlan_hash_table(pdata);
 
-	if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+	if (netdev_active_feature_test(pdata->netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		xlgmac_enable_rx_vlan_filtering(pdata);
 	else
 		xlgmac_disable_rx_vlan_filtering(pdata);
 
-	if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(pdata->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		xlgmac_enable_rx_vlan_stripping(pdata);
 	else
 		xlgmac_disable_rx_vlan_stripping(pdata);
@@ -2433,7 +2433,7 @@ static void xlgmac_config_rss(struct xlgmac_pdata *pdata)
 	if (!pdata->hw_feat.rss)
 		return;
 
-	if (pdata->netdev->features & NETIF_F_RXHASH)
+	if (netdev_active_feature_test(pdata->netdev, NETIF_F_RXHASH_BIT))
 		ret = xlgmac_enable_rss(pdata);
 	else
 		ret = xlgmac_disable_rss(pdata);
@@ -2760,7 +2760,7 @@ static int xlgmac_dev_read(struct xlgmac_channel *channel)
 			0);
 
 	/* Set checksum done indicator as appropriate */
-	if (netdev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT))
 		pkt_info->attributes = XLGMAC_SET_REG_BITS(
 				pkt_info->attributes,
 				RX_PACKET_ATTRIBUTES_CSUM_DONE_POS,
@@ -2779,7 +2779,7 @@ static int xlgmac_dev_read(struct xlgmac_channel *channel)
 	if (!err || !etlt) {
 		/* No error if err is 0 or etlt is 0 */
 		if ((etlt == 0x09) &&
-		    (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
+		    (netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))) {
 			pkt_info->attributes = XLGMAC_SET_REG_BITS(
 					pkt_info->attributes,
 					RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS,
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
index e54ce73396ee..f6e5ff0ce634 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
@@ -879,36 +879,38 @@ static void xlgmac_poll_controller(struct net_device *netdev)
 static int xlgmac_set_features(struct net_device *netdev,
 			       netdev_features_t features)
 {
-	netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter;
+	bool rxhash, rxcsum, rxvlan, rxvlan_filter;
 	struct xlgmac_pdata *pdata = netdev_priv(netdev);
 	struct xlgmac_hw_ops *hw_ops = &pdata->hw_ops;
 	int ret = 0;
 
-	rxhash = pdata->netdev_features & NETIF_F_RXHASH;
-	rxcsum = pdata->netdev_features & NETIF_F_RXCSUM;
-	rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX;
-	rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER;
+	rxhash = netdev_feature_test(NETIF_F_RXHASH_BIT, pdata->netdev_features);
+	rxcsum = netdev_feature_test(NETIF_F_RXCSUM_BIT, pdata->netdev_features);
+	rxvlan = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				     pdata->netdev_features);
+	rxvlan_filter = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+					    pdata->netdev_features);
 
-	if ((features & NETIF_F_RXHASH) && !rxhash)
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features) && !rxhash)
 		ret = hw_ops->enable_rss(pdata);
-	else if (!(features & NETIF_F_RXHASH) && rxhash)
+	else if (!netdev_feature_test(NETIF_F_RXHASH_BIT, features) && rxhash)
 		ret = hw_ops->disable_rss(pdata);
 	if (ret)
 		return ret;
 
-	if ((features & NETIF_F_RXCSUM) && !rxcsum)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && !rxcsum)
 		hw_ops->enable_rx_csum(pdata);
-	else if (!(features & NETIF_F_RXCSUM) && rxcsum)
+	else if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && rxcsum)
 		hw_ops->disable_rx_csum(pdata);
 
-	if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !rxvlan)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) && !rxvlan)
 		hw_ops->enable_rx_vlan_stripping(pdata);
-	else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && rxvlan)
+	else if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) && rxvlan)
 		hw_ops->disable_rx_vlan_stripping(pdata);
 
-	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) && !rxvlan_filter)
+	if ((netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) && !rxvlan_filter)
 		hw_ops->enable_rx_vlan_filtering(pdata);
-	else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter)
+	else if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) && rxvlan_filter)
 		hw_ops->disable_rx_vlan_filtering(pdata);
 
 	pdata->netdev_features = features;
@@ -1219,7 +1221,7 @@ static int xlgmac_rx_poll(struct xlgmac_channel *channel, int budget)
 
 		/* Be sure we don't exceed the configured MTU */
 		max_len = netdev->mtu + ETH_HLEN;
-		if (!(netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+		if (!(netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) &&
 		    (skb->protocol == htons(ETH_P_8021Q)))
 			max_len += VLAN_HLEN;
 
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 4040481def57..584f3e9f0933 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -666,7 +666,7 @@ static void am65_cpsw_nuss_rx_csum(struct sk_buff *skb, u32 csum_info)
 	 */
 	skb_checksum_none_assert(skb);
 
-	if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM)))
+	if (unlikely(!netdev_active_feature_test(skb->dev, NETIF_F_RXCSUM_BIT)))
 		return;
 
 	if ((csum_info & (AM65_CPSW_RX_PSD_IPV6_VALID |
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 78c817b3e88c..7006468b846f 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -936,7 +936,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr,
 	skb->protocol = eth_type_trans(skb, netdev);
 
 	/* checksum offload */
-	if (netdev->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) {
 		if ((data_status & GELIC_DESCR_DATA_STATUS_CHK_MASK) &&
 		    (!(data_error & GELIC_DESCR_DATA_ERROR_CHK_MASK)))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index 6267c414d356..9dfb9a8a1d1b 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -967,7 +967,7 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
 
 	/* checksum offload */
 	skb_checksum_none_assert(skb);
-	if (netdev->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT)) {
 		if ( ( (data_status & SPIDER_NET_DATA_STATUS_CKSUM_MASK) ==
 		       SPIDER_NET_DATA_STATUS_CKSUM_MASK) &&
 		     !(data_error & SPIDER_NET_DATA_ERR_CKSUM_MASK))
diff --git a/drivers/net/hyperv/netvsc_bpf.c b/drivers/net/hyperv/netvsc_bpf.c
index 4a9522689fa4..802c07df0e06 100644
--- a/drivers/net/hyperv/netvsc_bpf.c
+++ b/drivers/net/hyperv/netvsc_bpf.c
@@ -142,7 +142,7 @@ int netvsc_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 		return -EOPNOTSUPP;
 	}
 
-	if (prog && (dev->features & NETIF_F_LRO)) {
+	if (prog && (netdev_active_feature_test(dev, NETIF_F_LRO_BIT))) {
 		netdev_err(dev, "XDP: not support LRO\n");
 		NL_SET_ERR_MSG_MOD(extack, "XDP: not support LRO");
 
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 0af1d6dc1838..771bc0f304c1 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -844,13 +844,15 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
 	}
 
 	/* Do L4 checksum offload if enabled and present. */
-	if ((ppi_flags & NVSC_RSC_CSUM_INFO) && (net->features & NETIF_F_RXCSUM)) {
+	if ((ppi_flags & NVSC_RSC_CSUM_INFO) &&
+	    netdev_active_feature_test(net, NETIF_F_RXCSUM_BIT)) {
 		if (csum_info->receive.tcp_checksum_succeeded ||
 		    csum_info->receive.udp_checksum_succeeded)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 	}
 
-	if ((ppi_flags & NVSC_RSC_HASH_INFO) && (net->features & NETIF_F_RXHASH))
+	if ((ppi_flags & NVSC_RSC_HASH_INFO) &&
+	    netdev_active_feature_test(net, NETIF_F_RXHASH_BIT))
 		skb_set_hash(skb, *hash_info, PKT_HASH_TYPE_L4);
 
 	if (ppi_flags & NVSC_RSC_VLAN) {
@@ -1909,7 +1911,7 @@ static netdev_features_t netvsc_fix_features(struct net_device *ndev,
 	if (!nvdev || nvdev->destroy)
 		return features;
 
-	if ((features & NETIF_F_LRO) && netvsc_xdp_get(nvdev)) {
+	if (netdev_feature_test(NETIF_F_LRO_BIT, features) && netvsc_xdp_get(nvdev)) {
 		netdev_feature_change(NETIF_F_LRO_BIT, &features);
 		netdev_info(ndev, "Skip LRO - unsupported with XDP\n");
 	}
@@ -1930,12 +1932,12 @@ static int netvsc_set_features(struct net_device *ndev,
 	if (!nvdev || nvdev->destroy)
 		return -ENODEV;
 
-	if (!(change & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, change))
 		goto syncvf;
 
 	memset(&offloads, 0, sizeof(struct ndis_offload_params));
 
-	if (features & NETIF_F_LRO) {
+	if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
 		offloads.rsc_ip_v4 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED;
 		offloads.rsc_ip_v6 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED;
 	} else {
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index cd6d771cf191..02d2f94c8364 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1419,7 +1419,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	if (hwcaps.rsc.ip4 && hwcaps.rsc.ip6) {
 		netdev_hw_feature_add(net, NETIF_F_LRO_BIT);
 
-		if (net->features & NETIF_F_LRO) {
+		if (netdev_active_feature_test(net, NETIF_F_LRO_BIT)) {
 			offloads.rsc_ip_v4 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED;
 			offloads.rsc_ip_v6 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED;
 		} else {
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 84312e717720..b415e4aaae1d 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -351,7 +351,8 @@ static bool macsec_check_offload(enum macsec_offload offload,
 		return macsec->real_dev->phydev &&
 		       macsec->real_dev->phydev->macsec_ops;
 	else if (offload == MACSEC_OFFLOAD_MAC)
-		return macsec->real_dev->features & NETIF_F_HW_MACSEC &&
+		return netdev_active_feature_test(macsec->real_dev,
+						  NETIF_F_HW_MACSEC_BIT) &&
 		       macsec->real_dev->macsec_ops;
 
 	return false;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 956e93aaa25a..78dbe6003618 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -629,7 +629,7 @@ static int macvlan_open(struct net_device *dev)
 	/* Attempt to populate accel_priv which is used to offload the L2
 	 * forwarding requests for unicast packets.
 	 */
-	if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD)
+	if (netdev_active_feature_test(lowerdev, NETIF_F_HW_L2FW_DOFFLOAD_BIT))
 		vlan->accel_priv =
 		      lowerdev->netdev_ops->ndo_dfwd_add_station(lowerdev, dev);
 
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index b2721d802929..a58a1d325dcc 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -500,7 +500,7 @@ static int net_failover_slave_pre_register(struct net_device *slave_dev,
 				  !dev_is_pci(slave_dev->dev.parent)))
 		return -EINVAL;
 
-	if (failover_dev->features & NETIF_F_VLAN_CHALLENGED &&
+	if (netdev_active_feature_test(failover_dev, NETIF_F_VLAN_CHALLENGED_BIT) &&
 	    vlan_uses_dev(failover_dev)) {
 		netdev_err(failover_dev, "Device %s is VLAN challenged and failover device has VLAN set up\n",
 			   failover_dev->name);
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index e0de6450d79f..24f3ab8568cd 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -233,7 +233,8 @@ nsim_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct netdevsim *ns = netdev_priv(dev);
 
-	if ((dev->features & NETIF_F_HW_TC) && !(features & NETIF_F_HW_TC))
+	if (netdev_active_feature_test(dev, NETIF_F_HW_TC_BIT) &&
+	    !netdev_feature_test(NETIF_F_HW_TC_BIT, features))
 		return nsim_bpf_disable_tc(ns);
 
 	return 0;
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 3700b3b6141a..67bfe9cbc573 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -554,7 +554,8 @@ static int tap_open(struct inode *inode, struct file *file)
 	 * The macvlan supports zerocopy iff the lower device supports zero
 	 * copy so we don't have to look at the lower device directly.
 	 */
-	if ((tap->dev->features & NETIF_F_HIGHDMA) && (tap->dev->features & NETIF_F_SG))
+	if (netdev_active_feature_test(tap->dev, NETIF_F_HIGHDMA_BIT) &&
+	    netdev_active_feature_test(tap->dev, NETIF_F_SG_BIT))
 		sock_set_flag(&q->sk, SOCK_ZEROCOPY);
 
 	err = tap_set_queue(tap, file, q);
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 5b501e5069cb..406f0befe177 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1177,7 +1177,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
 		return -EBUSY;
 	}
 
-	if (port_dev->features & NETIF_F_VLAN_CHALLENGED &&
+	if (netdev_active_feature_test(port_dev, NETIF_F_VLAN_CHALLENGED_BIT) &&
 	    vlan_uses_dev(dev)) {
 		NL_SET_ERR_MSG(extack, "Device is VLAN challenged and team device has VLAN set up");
 		netdev_err(dev, "Device %s is VLAN challenged and team device has VLAN set up\n",
@@ -1242,7 +1242,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
 		goto err_enable_netpoll;
 	}
 
-	if (!(dev->features & NETIF_F_LRO))
+	if (!netdev_active_feature_test(dev, NETIF_F_LRO_BIT))
 		dev_disable_lro(port_dev);
 
 	err = netdev_rx_handler_register(port_dev, team_handle_frame,
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 4fb65f445586..f0b7f61379e4 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -597,23 +597,23 @@ static int aqc111_set_features(struct net_device *net,
 	u16 reg16 = 0;
 	u8 reg8 = 0;
 
-	if (changed & NETIF_F_IP_CSUM) {
+	if (netdev_feature_test(NETIF_F_IP_CSUM_BIT, changed)) {
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
 		reg8 ^= SFR_TXCOE_TCP | SFR_TXCOE_UDP;
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
 				 1, 1, &reg8);
 	}
 
-	if (changed & NETIF_F_IPV6_CSUM) {
+	if (netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, changed)) {
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
 		reg8 ^= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6;
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
 				 1, 1, &reg8);
 	}
 
-	if (changed & NETIF_F_RXCSUM) {
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, &reg8);
-		if (features & NETIF_F_RXCSUM) {
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
 			aqc111_data->rx_checksum = 1;
 			reg8 &= ~(SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP |
 				  SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6);
@@ -626,8 +626,8 @@ static int aqc111_set_features(struct net_device *net,
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL,
 				 1, 1, &reg8);
 	}
-	if (changed & 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, changed)) {
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) {
 			u16 i = 0;
 
 			for (i = 0; i < 256; i++) {
@@ -907,17 +907,17 @@ static void aqc111_configure_csum_offload(struct usbnet *dev)
 {
 	u8 reg8 = 0;
 
-	if (dev->net->features & NETIF_F_RXCSUM) {
+	if (netdev_active_feature_test(dev->net, NETIF_F_RXCSUM_BIT)) {
 		reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP |
 			SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6;
 	}
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, &reg8);
 
 	reg8 = 0;
-	if (dev->net->features & NETIF_F_IP_CSUM)
+	if (netdev_active_feature_test(dev->net, NETIF_F_IP_CSUM_BIT))
 		reg8 |= SFR_TXCOE_IP | SFR_TXCOE_TCP | SFR_TXCOE_UDP;
 
-	if (dev->net->features & NETIF_F_IPV6_CSUM)
+	if (netdev_active_feature_test(dev->net, NETIF_F_IPV6_CSUM_BIT))
 		reg8 |= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6;
 
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
@@ -934,7 +934,7 @@ static int aqc111_link_reset(struct usbnet *dev)
 
 		/* Vlan Tag Filter */
 		reg8 = SFR_VLAN_CONTROL_VSO;
-		if (dev->net->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+		if (netdev_active_feature_test(dev->net, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 			reg8 |= SFR_VLAN_CONTROL_VFE;
 
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
@@ -1240,7 +1240,7 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 			   AQ_TX_DESC_VLAN_SHIFT;
 	}
 
-	if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) &&
+	if (!dev->can_dma_sg && netdev_active_feature_test(dev->net, NETIF_F_SG_BIT) &&
 	    skb_linearize(skb))
 		return NULL;
 
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index d04e8a14a8ba..78529d9c1307 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -900,19 +900,19 @@ ax88179_set_features(struct net_device *net, netdev_features_t features)
 	struct usbnet *dev = netdev_priv(net);
 	netdev_features_t changed = netdev_active_features_xor(net, features);
 
-	if (changed & NETIF_F_IP_CSUM) {
+	if (netdev_feature_test(NETIF_F_IP_CSUM_BIT, changed)) {
 		ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
 		tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP;
 		ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
 	}
 
-	if (changed & NETIF_F_IPV6_CSUM) {
+	if (netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, changed)) {
 		ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
 		tmp ^= AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6;
 		ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
 	}
 
-	if (changed & NETIF_F_RXCSUM) {
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp);
 		tmp ^= AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
 		       AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6;
@@ -1483,7 +1483,7 @@ ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 
 	headroom = skb_headroom(skb) - 8;
 
-	if ((dev->net->features & NETIF_F_SG) && skb_linearize(skb))
+	if (netdev_active_feature_test(dev->net, NETIF_F_SG_BIT) && skb_linearize(skb))
 		return NULL;
 
 	if ((skb_header_cloned(skb) || headroom < 0) &&
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index e8db2e8cb755..de4056e2b544 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -2600,7 +2600,7 @@ static int lan78xx_set_features(struct net_device *netdev,
 
 	spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
 
-	if (features & NETIF_F_RXCSUM) {
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
 		pdata->rfe_ctl |= RFE_CTL_TCPUDP_COE_ | RFE_CTL_IP_COE_;
 		pdata->rfe_ctl |= RFE_CTL_ICMP_COE_ | RFE_CTL_IGMP_COE_;
 	} else {
@@ -2608,12 +2608,12 @@ static int lan78xx_set_features(struct net_device *netdev,
 		pdata->rfe_ctl &= ~(RFE_CTL_ICMP_COE_ | RFE_CTL_IGMP_COE_);
 	}
 
-	if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 		pdata->rfe_ctl |= RFE_CTL_VLAN_STRIP_;
 	else
 		pdata->rfe_ctl &= ~RFE_CTL_VLAN_STRIP_;
 
-	if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
 		pdata->rfe_ctl |= RFE_CTL_VLAN_FILTER_;
 	else
 		pdata->rfe_ctl &= ~RFE_CTL_VLAN_FILTER_;
@@ -3545,10 +3545,10 @@ static void lan78xx_rx_csum_offload(struct lan78xx_net *dev,
 	/* HW Checksum offload appears to be flawed if used when not stripping
 	 * VLAN headers. Drop back to S/W checksums under these conditions.
 	 */
-	if (!(dev->net->features & NETIF_F_RXCSUM) ||
+	if (!netdev_active_feature_test(dev->net, NETIF_F_RXCSUM_BIT) ||
 	    unlikely(rx_cmd_a & RX_CMD_A_ICSM_) ||
 	    ((rx_cmd_a & RX_CMD_A_FVTG_) &&
-	     !(dev->net->features & NETIF_F_HW_VLAN_CTAG_RX))) {
+	     !netdev_active_feature_test(dev->net, NETIF_F_HW_VLAN_CTAG_RX_BIT))) {
 		skb->ip_summed = CHECKSUM_NONE;
 	} else {
 		skb->csum = ntohs((u16)(rx_cmd_b >> RX_CMD_B_CSUM_SHIFT_));
@@ -3560,7 +3560,7 @@ static void lan78xx_rx_vlan_offload(struct lan78xx_net *dev,
 				    struct sk_buff *skb,
 				    u32 rx_cmd_a, u32 rx_cmd_b)
 {
-	if ((dev->net->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (netdev_active_feature_test(dev->net, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
 	    (rx_cmd_a & RX_CMD_A_FVTG_))
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
 				       (rx_cmd_b & 0xffff));
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 1de9c5bd9595..42d40ad4418e 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2350,7 +2350,7 @@ static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
 	u8 checksum = CHECKSUM_NONE;
 	u32 opts2, opts3;
 
-	if (!(tp->netdev->features & NETIF_F_RXCSUM))
+	if (!netdev_active_feature_test(tp->netdev, NETIF_F_RXCSUM_BIT))
 		goto return_result;
 
 	opts2 = le32_to_cpu(rx_desc->opts2);
@@ -3261,8 +3261,8 @@ static int rtl8152_set_features(struct net_device *dev,
 
 	mutex_lock(&tp->control);
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
-		if (features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed)) {
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 			rtl_rx_vlan_en(tp, true);
 		else
 			rtl_rx_vlan_en(tp, false);
@@ -5441,7 +5441,8 @@ static void r8152b_exit_oob(struct r8152 *tp)
 	ocp_write_dword(tp, MCU_TYPE_USB, USB_TX_DMA,
 			TEST_MODE_DISABLE | TX_SIZE_ADJUST1);
 
-	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
+	rtl_rx_vlan_en(tp,
+		       netdev_active_feature_test(tp->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT));
 
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
 
@@ -5886,7 +5887,8 @@ static void r8153_first_init(struct r8152 *tp)
 
 	wait_oob_link_list_ready(tp);
 
-	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
+	rtl_rx_vlan_en(tp,
+		       netdev_active_feature_test(tp->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT));
 
 	rtl8153_change_mtu(tp);
 
@@ -6392,7 +6394,8 @@ static void rtl8153c_up(struct r8152 *tp)
 
 	wait_oob_link_list_ready(tp);
 
-	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
+	rtl_rx_vlan_en(tp,
+		       netdev_active_feature_test(tp->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT));
 
 	rtl8153c_change_mtu(tp);
 
@@ -6497,7 +6500,8 @@ static void rtl8156_up(struct r8152 *tp)
 	ocp_data &= ~MCU_BORW_EN;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
 
-	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
+	rtl_rx_vlan_en(tp,
+		       netdev_active_feature_test(tp->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT));
 
 	rtl8156_change_mtu(tp);
 
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 3a413073eb66..769bf5a54952 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -944,7 +944,7 @@ static int smsc75xx_set_features(struct net_device *netdev,
 
 	spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
 
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		pdata->rfe_ctl |= RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM;
 	else
 		pdata->rfe_ctl &= ~(RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM);
@@ -2174,7 +2174,7 @@ static int smsc75xx_resume(struct usb_interface *intf)
 static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb,
 				     u32 rx_cmd_a, u32 rx_cmd_b)
 {
-	if (!(dev->net->features & NETIF_F_RXCSUM) ||
+	if (!netdev_active_feature_test(dev->net, NETIF_F_RXCSUM_BIT) ||
 	    unlikely(rx_cmd_a & RX_CMD_A_LCSM)) {
 		skb->ip_summed = CHECKSUM_NONE;
 	} else {
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 1d6818c3d1fd..0964a31d595d 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -601,12 +601,12 @@ static int smsc95xx_set_features(struct net_device *netdev,
 	if (ret < 0)
 		return ret;
 
-	if (features & NETIF_F_IP_CSUM)
+	if (netdev_feature_test(NETIF_F_IP_CSUM_BIT, features))
 		read_buf |= Tx_COE_EN_;
 	else
 		read_buf &= ~Tx_COE_EN_;
 
-	if (features & NETIF_F_RXCSUM)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		read_buf |= Rx_COE_EN_;
 	else
 		read_buf &= ~Rx_COE_EN_;
@@ -1824,7 +1824,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 
 			/* last frame in this batch */
 			if (skb->len == size) {
-				if (dev->net->features & NETIF_F_RXCSUM)
+				if (netdev_active_feature_test(dev->net, NETIF_F_RXCSUM_BIT))
 					smsc95xx_rx_csum_offload(skb);
 				skb_trim(skb, skb->len - 4); /* remove fcs */
 				skb->truesize = size + sizeof(struct sk_buff);
@@ -1842,7 +1842,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 			ax_skb->data = packet;
 			skb_set_tail_pointer(ax_skb, size);
 
-			if (dev->net->features & NETIF_F_RXCSUM)
+			if (netdev_active_feature_test(dev->net, NETIF_F_RXCSUM_BIT))
 				smsc95xx_rx_csum_offload(ax_skb);
 			skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
 			ax_skb->truesize = size + sizeof(struct sk_buff);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 2e4039b578ad..ec210e5586f4 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -307,8 +307,8 @@ static bool veth_skb_is_eligible_for_gro(const struct net_device *dev,
 {
 	return !(dev->features & NETIF_F_ALL_TSO) ||
 		(skb->destructor == sock_wfree &&
-		 (rcv->features & NETIF_F_GRO_FRAGLIST ||
-		  rcv->features & NETIF_F_GRO_UDP_FWD));
+		 (netdev_active_feature_test(rcv, NETIF_F_GRO_FRAGLIST_BIT) ||
+		  netdev_active_feature_test(rcv, NETIF_F_GRO_UDP_FWD_BIT)));
 }
 
 static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -1063,7 +1063,7 @@ static void veth_napi_del(struct net_device *dev)
 
 static bool veth_gro_requested(const struct net_device *dev)
 {
-	return !!(dev->wanted_features & NETIF_F_GRO);
+	return netdev_wanted_feature_test(dev, NETIF_F_GRO_BIT);
 }
 
 static int veth_enable_xdp_range(struct net_device *dev, int start, int end,
@@ -1479,10 +1479,11 @@ static int veth_set_features(struct net_device *dev,
 	struct veth_priv *priv = netdev_priv(dev);
 	int err;
 
-	if (!(changed & NETIF_F_GRO) || !(dev->flags & IFF_UP) || priv->_xdp_prog)
+	if (!netdev_feature_test(NETIF_F_GRO_BIT, changed) ||
+	    !(dev->flags & IFF_UP) || priv->_xdp_prog)
 		return 0;
 
-	if (features & NETIF_F_GRO) {
+	if (netdev_feature_test(NETIF_F_GRO_BIT, features)) {
 		err = veth_napi_enable(dev);
 		if (err)
 			return err;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 952af46cf956..81d5022c5c42 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1252,7 +1252,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
 		return;
 
 	hdr = skb_vnet_hdr(skb);
-	if (dev->features & NETIF_F_RXHASH && vi->has_rss_hash_report)
+	if (netdev_active_feature_test(dev, NETIF_F_RXHASH_BIT) && vi->has_rss_hash_report)
 		virtio_skb_set_hash((const struct virtio_net_hdr_v1_hash *)hdr, skb);
 
 	if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID)
@@ -2451,7 +2451,7 @@ static bool virtnet_set_hashflow(struct virtnet_info *vi, struct ethtool_rxnfc *
 	if (new_hashtypes != vi->rss_hash_types_saved) {
 		vi->rss_hash_types_saved = new_hashtypes;
 		vi->ctrl->rss.hash_types = vi->rss_hash_types_saved;
-		if (vi->dev->features & NETIF_F_RXHASH)
+		if (netdev_active_feature_test(vi->dev, NETIF_F_RXHASH_BIT))
 			return virtnet_commit_rss_command(vi);
 	}
 
@@ -3017,11 +3017,12 @@ static int virtnet_set_features(struct net_device *dev,
 	u64 offloads;
 	int err;
 
-	if ((netdev_active_features_xor(dev, features)) & NETIF_F_GRO_HW) {
+	if (netdev_feature_test(NETIF_F_GRO_HW_BIT,
+				netdev_active_features_xor(dev, features))) {
 		if (vi->xdp_enabled)
 			return -EBUSY;
 
-		if (features & NETIF_F_GRO_HW)
+		if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features))
 			offloads = vi->guest_offloads_capable;
 		else
 			offloads = vi->guest_offloads_capable &
@@ -3033,8 +3034,9 @@ static int virtnet_set_features(struct net_device *dev,
 		vi->guest_offloads = offloads;
 	}
 
-	if ((netdev_active_features_xor(dev, features)) & NETIF_F_RXHASH) {
-		if (features & NETIF_F_RXHASH)
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT,
+				netdev_active_features_xor(dev, features))) {
+		if (netdev_feature_test(NETIF_F_RXHASH_BIT, features))
 			vi->ctrl->rss.hash_types = vi->rss_hash_types_saved;
 		else
 			vi->ctrl->rss.hash_types = VIRTIO_NET_HASH_REPORT_NONE;
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index ec24cef62a3a..ddadb9e61bf6 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1271,7 +1271,7 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter,
 		struct sk_buff *skb,
 		union Vmxnet3_GenericDesc *gdesc)
 {
-	if (!gdesc->rcd.cnc && adapter->netdev->features & NETIF_F_RXCSUM) {
+	if (!gdesc->rcd.cnc && netdev_active_feature_test(adapter->netdev, NETIF_F_RXCSUM_BIT)) {
 		if (gdesc->rcd.v4 &&
 		    (le32_to_cpu(gdesc->dword[3]) &
 		     VMXNET3_RCD_CSUM_OK) == VMXNET3_RCD_CSUM_OK) {
@@ -1527,7 +1527,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 
 #ifdef VMXNET3_RSS
 			if (rcd->rssType != VMXNET3_RCD_RSS_TYPE_NONE &&
-			    (adapter->netdev->features & NETIF_F_RXHASH)) {
+			    netdev_active_feature_test(adapter->netdev, NETIF_F_RXHASH_BIT)) {
 				enum pkt_hash_types hash_type;
 
 				switch (rcd->rssType) {
@@ -1631,7 +1631,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 					(union Vmxnet3_GenericDesc *)rcd);
 			skb->protocol = eth_type_trans(skb, adapter->netdev);
 			if (!rcd->tcp ||
-			    !(adapter->netdev->features & NETIF_F_LRO))
+			    !netdev_active_feature_test(adapter->netdev, NETIF_F_LRO_BIT))
 				goto not_lro;
 
 			if (segCnt != 0 && mss != 0) {
@@ -1662,7 +1662,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 			if (unlikely(rcd->ts))
 				__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rcd->tci);
 
-			if (adapter->netdev->features & NETIF_F_LRO)
+			if (netdev_active_feature_test(adapter->netdev, NETIF_F_LRO_BIT))
 				netif_receive_skb(skb);
 			else
 				napi_gro_receive(&rq->napi, skb);
@@ -2582,18 +2582,18 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
 	devRead->misc.ddLen = cpu_to_le32(sizeof(struct vmxnet3_adapter));
 
 	/* set up feature flags */
-	if (adapter->netdev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_RXCSUM_BIT))
 		devRead->misc.uptFeatures |= UPT1_F_RXCSUM;
 
-	if (adapter->netdev->features & NETIF_F_LRO) {
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_LRO_BIT)) {
 		devRead->misc.uptFeatures |= UPT1_F_LRO;
 		devRead->misc.maxNumRxSG = cpu_to_le16(1 + MAX_SKB_FRAGS);
 	}
-	if (adapter->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		devRead->misc.uptFeatures |= UPT1_F_RXVLAN;
 
-	if (adapter->netdev->features & NETIF_F_GSO_UDP_TUNNEL ||
-	    adapter->netdev->features & NETIF_F_GSO_UDP_TUNNEL_CSUM)
+	if (netdev_active_feature_test(adapter->netdev, NETIF_F_GSO_UDP_TUNNEL_BIT) ||
+	    netdev_active_feature_test(adapter->netdev, NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT))
 		devRead->misc.uptFeatures |= UPT1_F_RXINNEROFLD;
 
 	devRead->misc.mtu = cpu_to_le32(adapter->netdev->mtu);
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 850758b6252f..8d1ba53fec93 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -250,7 +250,7 @@ netdev_features_t vmxnet3_fix_features(struct net_device *netdev,
 				       netdev_features_t features)
 {
 	/* If Rx checksum is disabled, then LRO should also be disabled */
-	if (!(features & NETIF_F_RXCSUM))
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 		netdev_feature_del(NETIF_F_LRO_BIT, &features);
 
 	return features;
@@ -329,10 +329,10 @@ static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_feat
 	if (VMXNET3_VERSION_GE_4(adapter)) {
 		netdev_hw_enc_features_set_array(netdev,
 						 &vmxnet3_hw_enc_feature_set);
-		if (features & NETIF_F_GSO_UDP_TUNNEL)
+		if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_BIT, features))
 			netdev_hw_enc_feature_add(netdev,
 						  NETIF_F_GSO_UDP_TUNNEL_BIT);
-		if (features & NETIF_F_GSO_UDP_TUNNEL_CSUM)
+		if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features))
 			netdev_hw_enc_feature_add(netdev,
 						  NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	}
@@ -424,11 +424,11 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 	netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, &tun_offload_mask);
 	udp_tun_enabled = (netdev->features & tun_offload_mask) != 0;
 
-	if (changed & NETIF_F_RXCSUM ||
-	    changed & NETIF_F_LRO ||
-	    changed & NETIF_F_HW_VLAN_CTAG_RX ||
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed) ||
+	    netdev_feature_test(NETIF_F_LRO_BIT, changed) ||
+	    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed) ||
 	    changed & tun_offload_mask) {
-		if (features & NETIF_F_RXCSUM)
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 			adapter->shared->devRead.misc.uptFeatures |=
 			UPT1_F_RXCSUM;
 		else
@@ -436,14 +436,14 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 			~UPT1_F_RXCSUM;
 
 		/* update hardware LRO capability accordingly */
-		if (features & NETIF_F_LRO)
+		if (netdev_feature_test(NETIF_F_LRO_BIT, features))
 			adapter->shared->devRead.misc.uptFeatures |=
 							UPT1_F_LRO;
 		else
 			adapter->shared->devRead.misc.uptFeatures &=
 							~UPT1_F_LRO;
 
-		if (features & NETIF_F_HW_VLAN_CTAG_RX)
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
 			adapter->shared->devRead.misc.uptFeatures |=
 			UPT1_F_RXVLAN;
 		else
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 4cf7801da3f5..f80df5fc28c3 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1126,7 +1126,7 @@ static int ath6kl_set_features(struct net_device *dev,
 	struct ath6kl *ar = vif->ar;
 	int err = 0;
 
-	if ((features & NETIF_F_RXCSUM) &&
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features) &&
 	    (ar->rx_meta_ver != WMI_META_VERSION_2)) {
 		ar->rx_meta_ver = WMI_META_VERSION_2;
 		err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi,
@@ -1137,7 +1137,7 @@ static int ath6kl_set_features(struct net_device *dev,
 			netdev_active_feature_del(dev, NETIF_F_RXCSUM_BIT);
 			return err;
 		}
-	} else if (!(features & NETIF_F_RXCSUM) &&
+	} else if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features) &&
 		   (ar->rx_meta_ver == WMI_META_VERSION_2)) {
 		ar->rx_meta_ver = 0;
 		err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi,
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index a56fab6232a9..88e84e4e8483 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -391,7 +391,7 @@ netdev_tx_t ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	if (test_bit(WMI_ENABLED, &ar->flag)) {
-		if ((dev->features & NETIF_F_IP_CSUM) &&
+		if ((netdev_active_feature_test(dev, NETIF_F_IP_CSUM_BIT)) &&
 		    (csum == CHECKSUM_PARTIAL)) {
 			csum_start = skb->csum_start -
 					(skb_network_header(skb) - skb->head) +
@@ -410,7 +410,7 @@ netdev_tx_t ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
 			goto fail_tx;
 		}
 
-		if ((dev->features & NETIF_F_IP_CSUM) &&
+		if ((netdev_active_feature_test(dev, NETIF_F_IP_CSUM_BIT)) &&
 		    (csum == CHECKSUM_PARTIAL)) {
 			meta_v2.csum_start = csum_start;
 			meta_v2.csum_dest = csum_dest;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 49ca1e168fc5..20c68f832923 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -271,7 +271,7 @@ static void iwl_mvm_rx_csum(struct ieee80211_sta *sta,
 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
 
-	if (mvmvif->features & NETIF_F_RXCSUM &&
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, mvmvif->features) &&
 	    status & RX_MPDU_RES_STATUS_CSUM_DONE &&
 	    status & RX_MPDU_RES_STATUS_CSUM_OK)
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 2c43a9989783..11c09b1ab7b8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -494,7 +494,7 @@ static void iwl_mvm_rx_csum(struct iwl_mvm *mvm,
 
 		mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
 
-		if (mvmvif->features & NETIF_F_RXCSUM &&
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, mvmvif->features) &&
 		    flags & IWL_RX_L3L4_TCP_UDP_CSUM_OK &&
 		    (flags & IWL_RX_L3L4_IP_HDR_CSUM_OK ||
 		     l3_prot == IWL_RX_L3_TYPE_IPV6 ||
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index aa88d5fd7d5f..2ef8a17224b8 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -240,7 +240,7 @@ static const struct attribute_group xennet_dev_group;
 
 static bool xennet_can_sg(struct net_device *dev)
 {
-	return dev->features & NETIF_F_SG;
+	return netdev_active_feature_test(dev, NETIF_F_SG_BIT);
 }
 
 
@@ -1474,20 +1474,20 @@ static netdev_features_t xennet_fix_features(struct net_device *dev,
 {
 	struct netfront_info *np = netdev_priv(dev);
 
-	if (features & NETIF_F_SG &&
+	if (netdev_feature_test(NETIF_F_SG_BIT, features) &&
 	    !xenbus_read_unsigned(np->xbdev->otherend, "feature-sg", 0))
 		netdev_feature_del(NETIF_F_SG_BIT, &features);
 
-	if (features & NETIF_F_IPV6_CSUM &&
+	if (netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, features) &&
 	    !xenbus_read_unsigned(np->xbdev->otherend,
 				  "feature-ipv6-csum-offload", 0))
 		netdev_feature_del(NETIF_F_IPV6_CSUM_BIT, &features);
 
-	if (features & NETIF_F_TSO &&
+	if (netdev_feature_test(NETIF_F_TSO_BIT, features) &&
 	    !xenbus_read_unsigned(np->xbdev->otherend, "feature-gso-tcpv4", 0))
 		netdev_feature_del(NETIF_F_TSO_BIT, &features);
 
-	if (features & NETIF_F_TSO6 &&
+	if (netdev_feature_test(NETIF_F_TSO6_BIT, features) &&
 	    !xenbus_read_unsigned(np->xbdev->otherend, "feature-gso-tcpv6", 0))
 		netdev_feature_del(NETIF_F_TSO6_BIT, &features);
 
@@ -1497,7 +1497,7 @@ static netdev_features_t xennet_fix_features(struct net_device *dev,
 static int xennet_set_features(struct net_device *dev,
 	netdev_features_t features)
 {
-	if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN) {
+	if (!netdev_feature_test(NETIF_F_SG_BIT, features) && dev->mtu > ETH_DATA_LEN) {
 		netdev_info(dev, "Reducing MTU because no SG offload");
 		dev->mtu = ETH_DATA_LEN;
 	}
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 98e444f4c8f6..1a181b2de48d 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -5575,7 +5575,7 @@ static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb,
 {
 	struct napi_struct *napi = &card->napi;
 
-	if (is_cso && (card->dev->features & NETIF_F_RXCSUM)) {
+	if (is_cso && netdev_active_feature_test(card->dev, NETIF_F_RXCSUM_BIT)) {
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 		QETH_CARD_STAT_INC(card, rx_skb_csum);
 	} else {
@@ -6867,33 +6867,38 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
 	QETH_CARD_TEXT(card, 2, "setfeat");
 	QETH_CARD_HEX(card, 2, &features, sizeof(features));
 
-	if ((changed & NETIF_F_IP_CSUM)) {
-		rc = qeth_set_ipa_csum(card, features & NETIF_F_IP_CSUM,
+	if (netdev_feature_test(NETIF_F_IP_CSUM_BIT, changed)) {
+		rc = qeth_set_ipa_csum(card,
+				       netdev_feature_test(NETIF_F_IP_CSUM_BIT, features),
 				       IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV4,
 				       &card->info.has_lp2lp_cso_v4);
 		if (rc)
 			netdev_feature_change(NETIF_F_IP_CSUM_BIT, &changed);
 	}
-	if (changed & NETIF_F_IPV6_CSUM) {
-		rc = qeth_set_ipa_csum(card, features & NETIF_F_IPV6_CSUM,
+	if (netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, changed)) {
+		rc = qeth_set_ipa_csum(card,
+				       netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, features),
 				       IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV6,
 				       &card->info.has_lp2lp_cso_v6);
 		if (rc)
 			netdev_feature_change(NETIF_F_IPV6_CSUM_BIT, &changed);
 	}
-	if (changed & NETIF_F_RXCSUM) {
-		rc = qeth_set_ipa_rx_csum(card, features & NETIF_F_RXCSUM);
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
+		rc = qeth_set_ipa_rx_csum(card,
+					  netdev_feature_test(NETIF_F_RXCSUM_BIT, features));
 		if (rc)
 			netdev_feature_change(NETIF_F_RXCSUM_BIT, &changed);
 	}
-	if (changed & NETIF_F_TSO) {
-		rc = qeth_set_ipa_tso(card, features & NETIF_F_TSO,
+	if (netdev_feature_test(NETIF_F_TSO_BIT, changed)) {
+		rc = qeth_set_ipa_tso(card,
+				      netdev_feature_test(NETIF_F_TSO_BIT, features),
 				      QETH_PROT_IPV4);
 		if (rc)
 			netdev_feature_change(NETIF_F_TSO_BIT, &changed);
 	}
-	if (changed & NETIF_F_TSO6) {
-		rc = qeth_set_ipa_tso(card, features & NETIF_F_TSO6,
+	if (netdev_feature_test(NETIF_F_TSO6_BIT, changed)) {
+		rc = qeth_set_ipa_tso(card,
+				      netdev_feature_test(NETIF_F_TSO6_BIT, features),
 				      QETH_PROT_IPV6);
 		if (rc)
 			netdev_feature_change(NETIF_F_TSO6_BIT, &changed);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index f91066cb9e72..4d0985f20050 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1891,9 +1891,9 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 		}
 
 		/* allow for de-acceleration of NETIF_F_HW_VLAN_CTAG_TX: */
-		if (card->dev->hw_features & NETIF_F_TSO6)
+		if (netdev_hw_feature_test(card->dev, NETIF_F_TSO6_BIT))
 			headroom = sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
-		else if (card->dev->hw_features & NETIF_F_TSO)
+		else if (netdev_hw_feature_test(card->dev, NETIF_F_TSO_BIT))
 			headroom = sizeof(struct qeth_hdr_tso);
 		else
 			headroom = sizeof(struct qeth_hdr) + VLAN_HLEN;
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index c2a59109857a..0d3ccb91ca38 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -653,19 +653,19 @@ static void fcoe_netdev_features_change(struct fc_lport *lport,
 {
 	mutex_lock(&lport->lp_mutex);
 
-	if (netdev->features & NETIF_F_SG)
+	if (netdev_active_feature_test(netdev, NETIF_F_SG_BIT))
 		lport->sg_supp = 1;
 	else
 		lport->sg_supp = 0;
 
-	if (netdev->features & NETIF_F_FCOE_CRC) {
+	if (netdev_active_feature_test(netdev, NETIF_F_FCOE_CRC_BIT)) {
 		lport->crc_offload = 1;
 		FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n");
 	} else {
 		lport->crc_offload = 0;
 	}
 
-	if (netdev->features & NETIF_F_FSO) {
+	if (netdev_active_feature_test(netdev, NETIF_F_FSO_BIT)) {
 		lport->seq_offload = 1;
 		lport->lso_max = min(netdev->gso_max_size, GSO_LEGACY_MAX_SIZE);
 		FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
@@ -722,7 +722,7 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
 	 * will return 0, so do this first.
 	 */
 	mfs = netdev->mtu;
-	if (netdev->features & NETIF_F_FCOE_MTU) {
+	if (netdev_active_feature_test(netdev, NETIF_F_FCOE_MTU_BIT)) {
 		mfs = FCOE_MTU;
 		FCOE_NETDEV_DBG(netdev, "Supports FCOE_MTU of %d bytes\n", mfs);
 	}
@@ -1549,7 +1549,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
 	skb->priority = fcoe->priority;
 
 	if (is_vlan_dev(fcoe->netdev) &&
-	    fcoe->realdev->features & NETIF_F_HW_VLAN_CTAG_TX) {
+	    netdev_active_feature_test(fcoe->realdev, NETIF_F_HW_VLAN_CTAG_TX_BIT)) {
 		/* must set skb->dev before calling vlan_put_tag */
 		skb->dev = fcoe->realdev;
 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
@@ -1864,7 +1864,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 	case NETDEV_CHANGE:
 		break;
 	case NETDEV_CHANGEMTU:
-		if (netdev->features & NETIF_F_FCOE_MTU)
+		if (netdev_active_feature_test(netdev, NETIF_F_FCOE_MTU_BIT))
 			break;
 		mfs = netdev->mtu - (sizeof(struct fcoe_hdr) +
 				     sizeof(struct fcoe_crc_eof));
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index 7515e4d50999..d033075f8bed 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -387,7 +387,7 @@ static int qlge_set_mac_addr_reg(struct qlge_adapter *qdev, const u8 *addr,
 		cam_output = (CAM_OUT_ROUTE_NIC |
 			      (qdev->func << CAM_OUT_FUNC_SHIFT) |
 			      (0 << CAM_OUT_CQ_ID_SHIFT));
-		if (qdev->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
+		if (netdev_active_feature_test(qdev->ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 			cam_output |= CAM_OUT_RV;
 		/* route to NIC core */
 		qlge_write32(qdev, MAC_ADDR_DATA, cam_output);
@@ -1396,7 +1396,7 @@ static void qlge_update_mac_hdr_len(struct qlge_adapter *qdev,
 {
 	u16 *tags;
 
-	if (qdev->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
+	if (netdev_active_feature_test(qdev->ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		return;
 	if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) {
 		tags = (u16 *)page;
@@ -1511,7 +1511,7 @@ static void qlge_process_mac_rx_page(struct qlge_adapter *qdev,
 	skb->protocol = eth_type_trans(skb, ndev);
 	skb_checksum_none_assert(skb);
 
-	if ((ndev->features & NETIF_F_RXCSUM) &&
+	if ((netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT)) &&
 	    !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) {
 		/* TCP frame. */
 		if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) {
@@ -1618,7 +1618,7 @@ static void qlge_process_mac_rx_skb(struct qlge_adapter *qdev,
 	/* If rx checksum is on, and there are no
 	 * csum or frame errors.
 	 */
-	if ((ndev->features & NETIF_F_RXCSUM) &&
+	if ((netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT)) &&
 	    !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) {
 		/* TCP frame. */
 		if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) {
@@ -1905,7 +1905,7 @@ static void qlge_process_mac_split_rx_intr(struct qlge_adapter *qdev,
 	/* If rx checksum is on, and there are no
 	 * csum or frame errors.
 	 */
-	if ((ndev->features & NETIF_F_RXCSUM) &&
+	if ((netdev_active_feature_test(ndev, NETIF_F_RXCSUM_BIT)) &&
 	    !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) {
 		/* TCP frame. */
 		if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) {
@@ -1944,7 +1944,7 @@ static unsigned long qlge_process_mac_rx_intr(struct qlge_adapter *qdev,
 {
 	u32 length = le32_to_cpu(ib_mac_rsp->data_len);
 	u16 vlan_id = ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) &&
-		       (qdev->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)) ?
+		       netdev_active_feature_test(qdev->ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) ?
 		((le16_to_cpu(ib_mac_rsp->vlan_id) &
 		  IB_MAC_IOCB_RSP_VLAN_MASK)) : 0xffff;
 
@@ -2224,7 +2224,7 @@ static void qlge_vlan_mode(struct net_device *ndev, netdev_features_t features)
 {
 	struct qlge_adapter *qdev = netdev_to_qdev(ndev);
 
-	if (features & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
 		qlge_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK |
 			     NIC_RCV_CFG_VLAN_MATCH_AND_NON);
 	} else {
@@ -2273,7 +2273,7 @@ static int qlge_set_features(struct net_device *ndev,
 	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 	int err;
 
-	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed)) {
 		/* Update the behavior of vlan accel in the adapter */
 		err = qlge_update_hw_vlan_features(ndev, features);
 		if (err)
@@ -3572,7 +3572,7 @@ static int qlge_adapter_initialize(struct qlge_adapter *qdev)
 	/* Set the default queue, and VLAN behavior. */
 	value = NIC_RCV_CFG_DFQ;
 	mask = NIC_RCV_CFG_DFQ_MASK;
-	if (qdev->ndev->features & NETIF_F_HW_VLAN_CTAG_RX) {
+	if (netdev_active_feature_test(qdev->ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
 		value |= NIC_RCV_CFG_RV;
 		mask |= (NIC_RCV_CFG_RV << 16);
 	}
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 890ea73b4ffb..173bf09b4cad 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -318,9 +318,11 @@ static inline bool eth_type_vlan(__be16 ethertype)
 static inline bool vlan_hw_offload_capable(netdev_features_t features,
 					   __be16 proto)
 {
-	if (proto == htons(ETH_P_8021Q) && features & NETIF_F_HW_VLAN_CTAG_TX)
+	if (proto == htons(ETH_P_8021Q) &&
+	    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features))
 		return true;
-	if (proto == htons(ETH_P_8021AD) && features & NETIF_F_HW_VLAN_STAG_TX)
+	if (proto == htons(ETH_P_8021AD) &&
+	    netdev_feature_test(NETIF_F_HW_VLAN_STAG_TX_BIT, features))
 		return true;
 	return false;
 }
@@ -568,7 +570,7 @@ static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb,
  */
 static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
 {
-	if (skb->dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
+	if (netdev_active_feature_test(skb->dev, NETIF_F_HW_VLAN_CTAG_TX_BIT)) {
 		return __vlan_hwaccel_get_tag(skb, vlan_tci);
 	} else {
 		return __vlan_get_tag(skb, vlan_tci);
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h
index 3732d8a81b9f..9adf376e1798 100644
--- a/include/linux/netdev_features_helper.h
+++ b/include/linux/netdev_features_helper.h
@@ -688,8 +688,9 @@ 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 & NETIF_F_HW_CSUM) != (f2 & NETIF_F_HW_CSUM)) {
-		if (f1 & NETIF_F_HW_CSUM)
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, f1) !=
+	    netdev_feature_test(NETIF_F_HW_CSUM_BIT, f2)) {
+		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 b01af2a3838d..4741f81fa968 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2364,7 +2364,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;
 }
@@ -4376,7 +4376,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) == 0) {	\
 		__netif_tx_lock(txq, cpu);		\
 	} else {					\
 		__netif_tx_acquire(txq);		\
@@ -4384,12 +4384,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) == 0) ?	\
 		__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) == 0) {	\
 		__netif_tx_unlock(txq);			\
 	} else {					\
 		__netif_tx_release(txq);		\
@@ -4781,20 +4781,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;
 	}
@@ -4917,7 +4917,7 @@ 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/include/net/pkt_cls.h b/include/net/pkt_cls.h
index d9d90e6925e1..a5cce3a41415 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -654,7 +654,7 @@ struct tc_cls_u32_offload {
 
 static inline bool tc_can_offload(const struct net_device *dev)
 {
-	return dev->features & NETIF_F_HW_TC;
+	return netdev_active_feature_test(dev, NETIF_F_HW_TC_BIT);
 }
 
 static inline bool tc_can_offload_extack(const struct net_device *dev,
diff --git a/include/net/sock.h b/include/net/sock.h
index d7196cd8cc1e..2cdda97fc8cf 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2181,7 +2181,7 @@ static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb,
 		if (!csum_and_copy_from_iter_full(to, copy, &csum, from))
 			return -EFAULT;
 		skb->csum = csum_block_add(skb->csum, csum, offset);
-	} else if (sk->sk_route_caps & NETIF_F_NOCACHE_COPY) {
+	} else if (netdev_feature_test(NETIF_F_NOCACHE_COPY_BIT, sk->sk_route_caps)) {
 		if (!copy_from_iter_full_nocache(to, copy, from))
 			return -EFAULT;
 	} else if (!copy_from_iter_full(to, copy, from))
diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h
index afc7ce713657..c4bf776439d7 100644
--- a/include/net/udp_tunnel.h
+++ b/include/net/udp_tunnel.h
@@ -129,7 +129,7 @@ void udp_tunnel_notify_del_rx_port(struct socket *sock, unsigned short type);
 static inline void udp_tunnel_get_rx_info(struct net_device *dev)
 {
 	ASSERT_RTNL();
-	if (!(dev->features & NETIF_F_RX_UDP_TUNNEL_PORT))
+	if (!netdev_active_feature_test(dev, NETIF_F_RX_UDP_TUNNEL_PORT_BIT))
 		return;
 	call_netdevice_notifiers(NETDEV_UDP_TUNNEL_PUSH_INFO, dev);
 }
@@ -137,7 +137,7 @@ static inline void udp_tunnel_get_rx_info(struct net_device *dev)
 static inline void udp_tunnel_drop_rx_info(struct net_device *dev)
 {
 	ASSERT_RTNL();
-	if (!(dev->features & NETIF_F_RX_UDP_TUNNEL_PORT))
+	if (!netdev_active_feature_test(dev, NETIF_F_RX_UDP_TUNNEL_PORT_BIT))
 		return;
 	call_netdevice_notifiers(NETDEV_UDP_TUNNEL_DROP_INFO, dev);
 }
@@ -326,7 +326,7 @@ udp_tunnel_nic_set_port_priv(struct net_device *dev, unsigned int table,
 static inline void
 udp_tunnel_nic_add_port(struct net_device *dev, struct udp_tunnel_info *ti)
 {
-	if (!(dev->features & NETIF_F_RX_UDP_TUNNEL_PORT))
+	if (!netdev_active_feature_test(dev, NETIF_F_RX_UDP_TUNNEL_PORT_BIT))
 		return;
 	if (udp_tunnel_nic_ops)
 		udp_tunnel_nic_ops->add_port(dev, ti);
@@ -335,7 +335,7 @@ udp_tunnel_nic_add_port(struct net_device *dev, struct udp_tunnel_info *ti)
 static inline void
 udp_tunnel_nic_del_port(struct net_device *dev, struct udp_tunnel_info *ti)
 {
-	if (!(dev->features & NETIF_F_RX_UDP_TUNNEL_PORT))
+	if (!netdev_active_feature_test(dev, NETIF_F_RX_UDP_TUNNEL_PORT_BIT))
 		return;
 	if (udp_tunnel_nic_ops)
 		udp_tunnel_nic_ops->del_port(dev, ti);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index e40aa3e3641c..9c3b4e54ed01 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -131,7 +131,7 @@ int vlan_check_real_dev(struct net_device *real_dev,
 {
 	const char *name = real_dev->name;
 
-	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
+	if (netdev_active_feature_test(real_dev, NETIF_F_VLAN_CHALLENGED_BIT)) {
 		pr_info("VLANs not supported on %s\n", name);
 		NL_SET_ERR_MSG_MOD(extack, "VLANs not supported on device");
 		return -EOPNOTSUPP;
@@ -379,13 +379,13 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 	}
 
 	if ((event == NETDEV_UP) &&
-	    (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
+	    (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))) {
 		pr_info("adding VLAN 0 to HW filter on device %s\n",
 			dev->name);
 		vlan_vid_add(dev, htons(ETH_P_8021Q), 0);
 	}
 	if (event == NETDEV_DOWN &&
-	    (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+	    (netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT)))
 		vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
 
 	vlan_info = rtnl_dereference(dev->vlan_info);
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 5aa8144101dc..9a16542ca35b 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -169,10 +169,10 @@ struct vlan_vid_info {
 static bool vlan_hw_filter_capable(const struct net_device *dev, __be16 proto)
 {
 	if (proto == htons(ETH_P_8021Q) &&
-	    dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+	    netdev_active_feature_test(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		return true;
 	if (proto == htons(ETH_P_8021AD) &&
-	    dev->features & NETIF_F_HW_VLAN_STAG_FILTER)
+	    netdev_active_feature_test(dev, NETIF_F_HW_VLAN_STAG_FILTER_BIT))
 		return true;
 	return false;
 }
diff --git a/net/core/dev.c b/net/core/dev.c
index 4ddb0bf86dcc..7188932a2158 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1589,7 +1589,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)
@@ -1610,7 +1610,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");
 }
 
@@ -3394,7 +3394,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;
 
@@ -3444,7 +3444,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];
 
@@ -3638,10 +3638,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) {
@@ -4405,7 +4405,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))
@@ -9608,89 +9608,96 @@ 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");
@@ -9698,7 +9705,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);
 	}
@@ -9758,7 +9766,7 @@ int __netdev_update_features(struct net_device *dev)
 	if (!err) {
 		netdev_features_t diff = netdev_active_features_xor(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.
@@ -9766,7 +9774,7 @@ 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 {
@@ -9774,8 +9782,8 @@ 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 {
@@ -9783,8 +9791,8 @@ 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 {
@@ -10010,8 +10018,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");
@@ -10047,13 +10055,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.
@@ -10956,7 +10964,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 */
@@ -11154,7 +11162,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);
 
@@ -11169,7 +11177,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);
@@ -11327,7 +11335,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/core/pktgen.c b/net/core/pktgen.c
index 198d94f2e8f0..aa3058dae0ae 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2963,8 +2963,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 
 	if (!(pkt_dev->flags & F_UDPCSUM)) {
 		skb->ip_summed = CHECKSUM_NONE;
-	} else if (odev->features & NETIF_F_HW_CSUM ||
-		   odev->features & NETIF_F_IP_CSUM) {
+	} else if (netdev_active_feature_test(odev, NETIF_F_HW_CSUM_BIT) ||
+		   netdev_active_feature_test(odev, NETIF_F_IP_CSUM_BIT)) {
 		skb->ip_summed = CHECKSUM_PARTIAL;
 		skb->csum = 0;
 		udp4_hwcsum(skb, iph->saddr, iph->daddr);
@@ -3099,8 +3099,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 
 	if (!(pkt_dev->flags & F_UDPCSUM)) {
 		skb->ip_summed = CHECKSUM_NONE;
-	} else if (odev->features & NETIF_F_HW_CSUM ||
-		   odev->features & NETIF_F_IPV6_CSUM) {
+	} else if (netdev_active_feature_test(odev, NETIF_F_HW_CSUM_BIT) ||
+		   netdev_active_feature_test(odev, NETIF_F_IPV6_CSUM_BIT)) {
 		skb->ip_summed = CHECKSUM_PARTIAL;
 		skb->csum_start = skb_transport_header(skb) - skb->head;
 		skb->csum_offset = offsetof(struct udphdr, check);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 338ef07b8f42..a00669f0b638 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4052,11 +4052,11 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
 	if (unlikely(!proto))
 		return ERR_PTR(-EINVAL);
 
-	sg = !!(features & NETIF_F_SG);
+	sg = netdev_feature_test(NETIF_F_SG_BIT, features);
 	csum = !!can_checksum_protocol(features, proto);
 
 	if (sg && csum && (mss != GSO_BY_FRAGS))  {
-		if (!(features & NETIF_F_GSO_PARTIAL)) {
+		if (!netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, features)) {
 			struct sk_buff *iter;
 			unsigned int frag_len;
 
@@ -4313,7 +4313,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
 		unsigned short gso_size = skb_shinfo(head_skb)->gso_size;
 
 		/* Update type to add partial and then remove dodgy if set */
-		type |= (features & NETIF_F_GSO_PARTIAL) ? 0 : SKB_GSO_PARTIAL;
+		type |= netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, features) ?
+				0 : SKB_GSO_PARTIAL;
 		type &= ~SKB_GSO_DODGY;
 
 		/* Update GSO info and prepare to start updating headers on
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
index 81627892bdd4..29e2838c3176 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -388,7 +388,7 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,
 		copy = (buf_size > bytes) ? bytes : buf_size;
 		to = sg_virt(sge) + msg->sg.copybreak;
 		msg->sg.copybreak += copy;
-		if (sk->sk_route_caps & NETIF_F_NOCACHE_COPY)
+		if (netdev_feature_test(NETIF_F_NOCACHE_COPY_BIT, sk->sk_route_caps))
 			ret = copy_from_iter_nocache(to, copy, from);
 		else
 			ret = copy_from_iter(to, copy, from);
diff --git a/net/core/sock.c b/net/core/sock.c
index 7dc8b734e807..88be1140358b 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2319,7 +2319,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 	sk->sk_route_caps = dst->dev->features;
 	if (sk_is_tcp(sk))
 		netdev_feature_add(NETIF_F_GSO_BIT, &sk->sk_route_caps);
-	if (sk->sk_route_caps & NETIF_F_GSO)
+	if (netdev_feature_test(NETIF_F_GSO_BIT, sk->sk_route_caps))
 		netdev_features_set(&sk->sk_route_caps, NETIF_F_GSO_SOFTWARE);
 	if (unlikely(sk->sk_gso_disabled))
 		netdev_features_clear(&sk->sk_route_caps, NETIF_F_GSO_MASK);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 0ecaef5605f9..c98b49d5eff1 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -317,15 +317,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;
diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
index 5bf357734b11..735ab1f6cb3e 100644
--- a/net/hsr/hsr_forward.c
+++ b/net/hsr/hsr_forward.c
@@ -291,7 +291,7 @@ struct sk_buff *hsr_create_tagged_frame(struct hsr_frame_info *frame,
 		/* set the lane id properly */
 		hsr_set_path_id(hsr_ethhdr, port);
 		return skb_clone(frame->skb_hsr, GFP_ATOMIC);
-	} else if (port->dev->features & NETIF_F_HW_HSR_TAG_INS) {
+	} else if (netdev_active_feature_test(port->dev, NETIF_F_HW_HSR_TAG_INS_BIT)) {
 		return skb_clone(frame->skb_std, GFP_ATOMIC);
 	}
 
@@ -335,7 +335,7 @@ struct sk_buff *prp_create_tagged_frame(struct hsr_frame_info *frame,
 			return NULL;
 		}
 		return skb_clone(frame->skb_prp, GFP_ATOMIC);
-	} else if (port->dev->features & NETIF_F_HW_HSR_TAG_INS) {
+	} else if (netdev_active_feature_test(port->dev, NETIF_F_HW_HSR_TAG_INS_BIT)) {
 		return skb_clone(frame->skb_std, GFP_ATOMIC);
 	}
 
@@ -391,7 +391,7 @@ bool prp_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port)
 
 bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port)
 {
-	if (port->dev->features & NETIF_F_HW_HSR_FWD)
+	if (netdev_active_feature_test(port->dev, NETIF_F_HW_HSR_FWD_BIT))
 		return prp_drop_frame(frame, port);
 
 	return false;
@@ -432,7 +432,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
 		/* If hardware duplicate generation is enabled, only send out
 		 * one port.
 		 */
-		if ((port->dev->features & NETIF_F_HW_HSR_DUP) && sent)
+		if (netdev_active_feature_test(port->dev, NETIF_F_HW_HSR_DUP_BIT) && sent)
 			continue;
 
 		/* Don't send frame over port where it has been sent before.
diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
index 584e21788799..0a1f7f9ebb9e 100644
--- a/net/hsr/hsr_framereg.c
+++ b/net/hsr/hsr_framereg.c
@@ -465,7 +465,7 @@ void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port,
 	 * ensures entries of restarted nodes gets pruned so that they can
 	 * re-register and resume communications.
 	 */
-	if (!(port->dev->features & NETIF_F_HW_HSR_TAG_RM) &&
+	if (!netdev_active_feature_test(port->dev, NETIF_F_HW_HSR_TAG_RM_BIT) &&
 	    seq_nr_before(sequence_nr, node->seq_out[port->type]))
 		return;
 
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
index b70e6bbf6021..e8b588a0b1aa 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -54,7 +54,7 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
 	 */
 	protocol = eth_hdr(skb)->h_proto;
 
-	if (!(port->dev->features & NETIF_F_HW_HSR_TAG_RM) &&
+	if (!netdev_active_feature_test(port->dev, NETIF_F_HW_HSR_TAG_RM_BIT) &&
 	    hsr->proto_ops->invalid_dan_ingress_frame &&
 	    hsr->proto_ops->invalid_dan_ingress_frame(protocol))
 		goto finish_pass;
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index adfc4c7e36bf..b6fb5fd1ff26 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -217,13 +217,13 @@ static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
 
 	skb->encap_hdr_csum = 1;
 
-	if ((!(skb->dev->gso_partial_features & NETIF_F_HW_ESP) &&
-	     !(features & NETIF_F_HW_ESP)) || x->xso.dev != skb->dev) {
+	if ((!netdev_gso_partial_feature_test(skb->dev, NETIF_F_HW_ESP_BIT) &&
+	     !netdev_feature_test(NETIF_F_HW_ESP_BIT, features)) || x->xso.dev != skb->dev) {
 		esp_features = netdev_features_andnot(features, NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SG_BIT, &esp_features);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
-	} else if (!(features & NETIF_F_HW_ESP_TX_CSUM) &&
-		 !(skb->dev->gso_partial_features & NETIF_F_HW_ESP_TX_CSUM)) {
+	} else if (!netdev_feature_test(NETIF_F_HW_ESP_TX_CSUM_BIT, features) &&
+		   !netdev_gso_partial_feature_test(skb->dev, NETIF_F_HW_ESP_TX_CSUM_BIT)) {
 		esp_features = netdev_features_andnot(features, NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	}
@@ -266,8 +266,8 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb,  netdev_features_
 	if (!xo)
 		return -EINVAL;
 
-	if ((!(features & NETIF_F_HW_ESP) &&
-	     !(skb->dev->gso_partial_features & NETIF_F_HW_ESP)) ||
+	if ((!netdev_feature_test(NETIF_F_HW_ESP_BIT, features) &&
+	     !netdev_gso_partial_feature_test(skb->dev, NETIF_F_HW_ESP_BIT)) ||
 	    x->xso.dev != skb->dev) {
 		xo->flags |= CRYPTO_FALLBACK;
 		hw_offload = false;
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 0b3f5a3ed86b..27b9e531ed62 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -51,7 +51,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 	need_ipsec = skb_dst(skb) && dst_xfrm(skb_dst(skb));
 	/* Try to offload checksum if possible */
 	offload_csum = !!(need_csum && !need_ipsec &&
-			  (skb->dev->features & NETIF_F_HW_CSUM));
+			  netdev_active_feature_test(skb->dev, NETIF_F_HW_CSUM_BIT));
 
 	/* segment inner packet. */
 	segs = skb_mac_gso_segment(skb, features);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 2b9a127e6a20..a51660b6185b 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1012,10 +1012,10 @@ static int __ip_append_data(struct sock *sk,
 	 */
 	if (transhdrlen &&
 	    length + fragheaderlen <= mtu &&
-	    (rt->dst.dev->features & NETIF_F_HW_CSUM ||
-	     rt->dst.dev->features & NETIF_F_IP_CSUM) &&
+	    (netdev_active_feature_test(rt->dst.dev, NETIF_F_HW_CSUM_BIT) ||
+	     netdev_active_feature_test(rt->dst.dev, NETIF_F_IP_CSUM_BIT)) &&
 	    (!(flags & MSG_MORE) || cork->gso_size) &&
-	    (!exthdrlen || (rt->dst.dev->features & NETIF_F_HW_ESP_TX_CSUM)))
+	    (!exthdrlen || netdev_active_feature_test(rt->dst.dev, NETIF_F_HW_ESP_TX_CSUM_BIT)))
 		csummode = CHECKSUM_PARTIAL;
 
 	if ((flags & MSG_ZEROCOPY) && length) {
@@ -1028,7 +1028,7 @@ static int __ip_append_data(struct sock *sk,
 			/* Leave uarg NULL if can't zerocopy, callers should
 			 * be able to handle it.
 			 */
-			if ((rt->dst.dev->features & NETIF_F_SG) &&
+			if (netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT) &&
 			    csummode == CHECKSUM_PARTIAL) {
 				paged = true;
 				zc = true;
@@ -1039,7 +1039,7 @@ static int __ip_append_data(struct sock *sk,
 			if (!uarg)
 				return -ENOBUFS;
 			extra_uref = !skb_zcopy(skb);	/* only ref on new uarg */
-			if (rt->dst.dev->features & NETIF_F_SG &&
+			if (netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT) &&
 			    csummode == CHECKSUM_PARTIAL) {
 				paged = true;
 				zc = true;
@@ -1104,11 +1104,11 @@ static int __ip_append_data(struct sock *sk,
 				alloc_extra += rt->dst.trailer_len;
 
 			if ((flags & MSG_MORE) &&
-			    !(rt->dst.dev->features&NETIF_F_SG))
+			    !netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT))
 				alloclen = mtu;
 			else if (!paged &&
 				 (fraglen + alloc_extra < SKB_MAX_ALLOC ||
-				  !(rt->dst.dev->features & NETIF_F_SG)))
+				  !netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT)))
 				alloclen = fraglen;
 			else if (!zc) {
 				alloclen = min_t(int, fraglen, MAX_HEADER);
@@ -1199,7 +1199,7 @@ static int __ip_append_data(struct sock *sk,
 		if (copy > length)
 			copy = length;
 
-		if (!(rt->dst.dev->features&NETIF_F_SG) &&
+		if (!netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT) &&
 		    skb_tailroom(skb) >= copy) {
 			unsigned int off;
 
@@ -1377,7 +1377,7 @@ ssize_t	ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
 	if (cork->flags & IPCORK_OPT)
 		opt = cork->opt;
 
-	if (!(rt->dst.dev->features & NETIF_F_SG))
+	if (!netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT))
 		return -EOPNOTSUPP;
 
 	hh_len = LL_RESERVED_SPACE(rt->dst.dev);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index df10a1e5027c..34874a7ded9d 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1132,7 +1132,7 @@ EXPORT_SYMBOL_GPL(do_tcp_sendpages);
 int tcp_sendpage_locked(struct sock *sk, struct page *page, int offset,
 			size_t size, int flags)
 {
-	if (!(sk->sk_route_caps & NETIF_F_SG))
+	if (!netdev_feature_test(NETIF_F_SG_BIT, sk->sk_route_caps))
 		return sock_no_sendpage_locked(sk, page, offset, size, flags);
 
 	tcp_rate_check_app_limited(sk);  /* is sending application-limited? */
@@ -1230,14 +1230,14 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
 		if (msg->msg_ubuf) {
 			uarg = msg->msg_ubuf;
 			net_zcopy_get(uarg);
-			zc = sk->sk_route_caps & NETIF_F_SG;
+			zc = netdev_feature_test(NETIF_F_SG_BIT, sk->sk_route_caps);
 		} else if (sock_flag(sk, SOCK_ZEROCOPY)) {
 			uarg = msg_zerocopy_realloc(sk, size, skb_zcopy(skb));
 			if (!uarg) {
 				err = -ENOBUFS;
 				goto out_err;
 			}
-			zc = sk->sk_route_caps & NETIF_F_SG;
+			zc = netdev_feature_test(NETIF_F_SG_BIT, sk->sk_route_caps);
 			if (!zc)
 				uarg->zerocopy = 0;
 		}
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index c4cf8fb52448..07c1237c69f3 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -64,9 +64,9 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 	/* Try to offload checksum if possible */
 	offload_csum = !!(need_csum &&
 			  !need_ipsec &&
-			  (skb->dev->features & NETIF_F_HW_CSUM ||
-			   (is_ipv6 ? (skb->dev->features & NETIF_F_IPV6_CSUM) :
-				      (skb->dev->features & NETIF_F_IP_CSUM))));
+			  (netdev_active_feature_test(skb->dev, NETIF_F_HW_CSUM_BIT) ||
+			   (is_ipv6 ? netdev_active_feature_test(skb->dev, NETIF_F_IPV6_CSUM_BIT) :
+				      netdev_active_feature_test(skb->dev, NETIF_F_IP_CSUM_BIT))));
 
 	features &= skb->dev->hw_enc_features;
 	if (need_csum)
@@ -548,10 +548,10 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb,
 	 */
 	NAPI_GRO_CB(skb)->is_flist = 0;
 	if (!sk || !udp_sk(sk)->gro_receive) {
-		if (skb->dev->features & NETIF_F_GRO_FRAGLIST)
+		if (netdev_active_feature_test(skb->dev, NETIF_F_GRO_FRAGLIST_BIT))
 			NAPI_GRO_CB(skb)->is_flist = sk ? !udp_sk(sk)->gro_enabled : 1;
 
-		if ((!sk && (skb->dev->features & NETIF_F_GRO_UDP_FWD)) ||
+		if ((!sk && netdev_active_feature_test(skb->dev, NETIF_F_GRO_UDP_FWD_BIT)) ||
 		    (sk && udp_sk(sk)->gro_enabled) || NAPI_GRO_CB(skb)->is_flist)
 			return call_gro_receive(udp_gro_receive_segment, head, skb);
 
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index ee83f7f2947c..5ddc261d33fe 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -256,11 +256,11 @@ static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
 
 	skb->encap_hdr_csum = 1;
 
-	if (!(features & NETIF_F_HW_ESP) || x->xso.dev != skb->dev) {
+	if (!netdev_feature_test(NETIF_F_HW_ESP_BIT, features) || x->xso.dev != skb->dev) {
 		esp_features = netdev_features_andnot(features, NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SG_BIT, &esp_features);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
-	} else if (!(features & NETIF_F_HW_ESP_TX_CSUM)) {
+	} else if (!netdev_feature_test(NETIF_F_HW_ESP_TX_CSUM_BIT, features)) {
 		esp_features = netdev_features_andnot(features, NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &esp_features);
 	}
@@ -303,7 +303,7 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb,  netdev_features
 	if (!xo)
 		return -EINVAL;
 
-	if (!(features & NETIF_F_HW_ESP) || x->xso.dev != skb->dev) {
+	if (!netdev_feature_test(NETIF_F_HW_ESP_BIT, features) || x->xso.dev != skb->dev) {
 		xo->flags |= CRYPTO_FALLBACK;
 		hw_offload = false;
 	}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 80f74d32e2ff..7113b3729626 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1539,8 +1539,8 @@ static int __ip6_append_data(struct sock *sk,
 	    headersize == sizeof(struct ipv6hdr) &&
 	    length <= mtu - headersize &&
 	    (!(flags & MSG_MORE) || cork->gso_size) &&
-	    (rt->dst.dev->features & NETIF_F_IPV6_CSUM ||
-	     rt->dst.dev->features & NETIF_F_HW_CSUM))
+	    (netdev_active_feature_test(rt->dst.dev, NETIF_F_IPV6_CSUM_BIT) ||
+	     netdev_active_feature_test(rt->dst.dev, NETIF_F_HW_CSUM_BIT)))
 		csummode = CHECKSUM_PARTIAL;
 
 	if ((flags & MSG_ZEROCOPY) && length) {
@@ -1553,7 +1553,7 @@ static int __ip6_append_data(struct sock *sk,
 			/* Leave uarg NULL if can't zerocopy, callers should
 			 * be able to handle it.
 			 */
-			if ((rt->dst.dev->features & NETIF_F_SG) &&
+			if (netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT) &&
 			    csummode == CHECKSUM_PARTIAL) {
 				paged = true;
 				zc = true;
@@ -1564,7 +1564,7 @@ static int __ip6_append_data(struct sock *sk,
 			if (!uarg)
 				return -ENOBUFS;
 			extra_uref = !skb_zcopy(skb);	/* only ref on new uarg */
-			if (rt->dst.dev->features & NETIF_F_SG &&
+			if (netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT) &&
 			    csummode == CHECKSUM_PARTIAL) {
 				paged = true;
 				zc = true;
@@ -1644,11 +1644,11 @@ static int __ip6_append_data(struct sock *sk,
 			alloc_extra += sizeof(struct frag_hdr);
 
 			if ((flags & MSG_MORE) &&
-			    !(rt->dst.dev->features&NETIF_F_SG))
+			    !netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT))
 				alloclen = mtu;
 			else if (!paged &&
 				 (fraglen + alloc_extra < SKB_MAX_ALLOC ||
-				  !(rt->dst.dev->features & NETIF_F_SG)))
+				  !netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT)))
 				alloclen = fraglen;
 			else if (!zc) {
 				alloclen = min_t(int, fraglen, MAX_HEADER);
@@ -1754,7 +1754,7 @@ static int __ip6_append_data(struct sock *sk,
 		if (copy > length)
 			copy = length;
 
-		if (!(rt->dst.dev->features&NETIF_F_SG) &&
+		if (!netdev_active_feature_test(rt->dst.dev, NETIF_F_SG_BIT) &&
 		    skb_tailroom(skb) >= copy) {
 			unsigned int off;
 
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index a0921adc31a9..7742f700f19b 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -172,7 +172,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
 	/* Only update csum if we really have to */
 	if (sctph->dest != cp->dport || payload_csum ||
 	    (skb->ip_summed == CHECKSUM_PARTIAL &&
-	     !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CRC))) {
+	     !netdev_active_feature_test(skb_dst(skb)->dev, NETIF_F_SCTP_CRC_BIT))) {
 		sctph->dest = cp->dport;
 		sctp_nat_csum(skb, sctph, sctphoff);
 	} else if (skb->ip_summed != CHECKSUM_PARTIAL) {
diff --git a/net/sctp/offload.c b/net/sctp/offload.c
index a70619d0c207..2806d23598d5 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -79,7 +79,7 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
 		goto out;
 
 	/* All that is left is update SCTP CRC if necessary */
-	if (!(features & NETIF_F_SCTP_CRC)) {
+	if (!netdev_feature_test(NETIF_F_SCTP_CRC_BIT, features)) {
 		for (skb = segs; skb; skb = skb->next) {
 			if (skb->ip_summed == CHECKSUM_PARTIAL) {
 				sh = sctp_hdr(skb);
diff --git a/net/sctp/output.c b/net/sctp/output.c
index a63df055ac57..9b3e83b8e544 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -544,7 +544,7 @@ static int sctp_packet_pack(struct sctp_packet *packet,
 	if (sctp_checksum_disable)
 		return 1;
 
-	if (!(tp->dst->dev->features & NETIF_F_SCTP_CRC) ||
+	if (!netdev_active_feature_test(tp->dst->dev, NETIF_F_SCTP_CRC_BIT) ||
 	    dst_xfrm(tp->dst) || packet->ipfragok || tp->encap_port) {
 		struct sctphdr *sh =
 			(struct sctphdr *)skb_transport_header(head);
diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h
index 2f59464e6524..d7108a6d17c6 100644
--- a/net/sunrpc/sunrpc.h
+++ b/net/sunrpc/sunrpc.h
@@ -44,7 +44,7 @@ static inline int sock_is_loopback(struct sock *sk)
 	rcu_read_lock();
 	dst = rcu_dereference(sk->sk_dst_cache);
 	if (dst && dst->dev &&
-	    (dst->dev->features & NETIF_F_LOOPBACK))
+	    netdev_active_feature_test(dst->dev, NETIF_F_LOOPBACK_BIT))
 		loopback = 1;
 	rcu_read_unlock();
 	return loopback;
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index 7e57a67ecce3..c88fbe2e1cf5 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -1065,7 +1065,7 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
 		return -EINVAL;
 	}
 
-	if (!(netdev->features & NETIF_F_HW_TLS_TX)) {
+	if (!netdev_active_feature_test(netdev, NETIF_F_HW_TLS_TX_BIT)) {
 		rc = -EOPNOTSUPP;
 		goto release_netdev;
 	}
@@ -1234,7 +1234,7 @@ int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx)
 		return -EINVAL;
 	}
 
-	if (!(netdev->features & NETIF_F_HW_TLS_RX)) {
+	if (!netdev_active_feature_test(netdev, NETIF_F_HW_TLS_RX_BIT)) {
 		rc = -EOPNOTSUPP;
 		goto release_netdev;
 	}
@@ -1411,7 +1411,7 @@ static int tls_dev_event(struct notifier_block *this, unsigned long event,
 	case NETDEV_FEAT_CHANGE:
 		if (netif_is_bond_master(dev))
 			return NOTIFY_DONE;
-		if ((dev->features & NETIF_F_HW_TLS_RX) &&
+		if (netdev_active_feature_test(dev, NETIF_F_HW_TLS_RX_BIT) &&
 		    !dev->tlsdev_ops->tls_dev_resync)
 			return NOTIFY_BAD;
 
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index b14259162313..0f89a6787bee 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -113,7 +113,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 	if (!xo || (xo->flags & XFRM_XMIT))
 		return skb;
 
-	if (!(features & NETIF_F_HW_ESP)) {
+	if (!netdev_feature_test(NETIF_F_HW_ESP_BIT, features)) {
 		esp_features = features;
 		netdev_feature_del(NETIF_F_SG_BIT, &esp_features);
 		netdev_features_clear(&esp_features, NETIF_F_CSUM_MASK);
@@ -373,18 +373,18 @@ void xfrm_dev_backlog(struct softnet_data *sd)
 static int xfrm_api_check(struct net_device *dev)
 {
 #ifdef CONFIG_XFRM_OFFLOAD
-	if ((dev->features & NETIF_F_HW_ESP_TX_CSUM) &&
-	    !(dev->features & NETIF_F_HW_ESP))
+	if (netdev_active_feature_test(dev, NETIF_F_HW_ESP_TX_CSUM_BIT) &&
+	    !netdev_active_feature_test(dev, NETIF_F_HW_ESP_BIT))
 		return NOTIFY_BAD;
 
-	if ((dev->features & NETIF_F_HW_ESP) &&
+	if ((netdev_active_feature_test(dev, NETIF_F_HW_ESP_BIT)) &&
 	    (!(dev->xfrmdev_ops &&
 	       dev->xfrmdev_ops->xdo_dev_state_add &&
 	       dev->xfrmdev_ops->xdo_dev_state_delete)))
 		return NOTIFY_BAD;
 #else
-	if (dev->features & NETIF_F_HW_ESP ||
-	    dev->features & NETIF_F_HW_ESP_TX_CSUM)
+	if (netdev_active_feature_test(dev, NETIF_F_HW_ESP_BIT) ||
+	    netdev_active_feature_test(dev, NETIF_F_HW_ESP_TX_CSUM_BIT))
 		return NOTIFY_BAD;
 #endif
 
@@ -393,7 +393,7 @@ static int xfrm_api_check(struct net_device *dev)
 
 static int xfrm_dev_down(struct net_device *dev)
 {
-	if (dev->features & NETIF_F_HW_ESP)
+	if (netdev_active_feature_test(dev, NETIF_F_HW_ESP_BIT))
 		xfrm_dev_state_flush(dev_net(dev), dev, true);
 
 	return NOTIFY_DONE;
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 85be950abae9..302d26d78ed5 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -746,7 +746,8 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
 			goto out;
 		}
 
-		if (x->xso.dev && x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM)
+		if (x->xso.dev &&
+		    netdev_active_feature_test(x->xso.dev, NETIF_F_HW_ESP_TX_CSUM_BIT))
 			goto out;
 	} else {
 		if (skb_is_gso(skb))
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 31/36] treewide: use netdev_features_intersects helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (29 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 30/36] treewide: use netdev_feature_test helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 32/36] net: use netdev_features_and and netdev_features_mask helpers Jian Shen
                   ` (4 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the inersect check expressions of features by
netdev_features_intersects helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |  2 +-
 drivers/net/ethernet/asix/ax88796c_main.c     |  4 ++--
 drivers/net/ethernet/broadcom/bcmsysport.c    |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 10 +++++-----
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |  8 +++++---
 .../net/ethernet/freescale/gianfar_ethtool.c  |  2 +-
 drivers/net/ethernet/hisilicon/hns/hns_enet.c |  6 +++---
 drivers/net/ethernet/ibm/ibmveth.c            |  3 ++-
 drivers/net/ethernet/ibm/ibmvnic.c            |  2 +-
 drivers/net/ethernet/intel/e1000e/netdev.c    |  4 ++--
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 20 +++++++++----------
 drivers/net/ethernet/intel/ice/ice_main.c     | 14 ++++++-------
 drivers/net/ethernet/marvell/sky2.c           |  2 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c |  3 ++-
 .../ethernet/netronome/nfp/nfp_net_common.c   |  8 ++++----
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  2 +-
 drivers/net/ethernet/nvidia/forcedeth.c       |  8 ++++----
 .../ethernet/qlogic/netxen/netxen_nic_main.c  |  2 +-
 drivers/net/ethernet/qualcomm/emac/emac.c     |  2 +-
 .../ethernet/qualcomm/rmnet/rmnet_map_data.c  |  2 +-
 drivers/net/ethernet/sfc/efx_common.c         |  4 ++--
 drivers/net/ethernet/sfc/siena/efx_common.c   |  4 ++--
 drivers/net/tap.c                             |  4 ++--
 drivers/net/veth.c                            |  2 +-
 drivers/net/vmxnet3/vmxnet3_ethtool.c         |  8 ++++----
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c   |  3 ++-
 drivers/s390/net/qeth_core_main.c             |  6 ++++--
 drivers/s390/net/qeth_l2_main.c               |  2 +-
 drivers/s390/net/qeth_l3_main.c               |  2 +-
 net/8021q/vlan.h                              |  3 ++-
 net/8021q/vlan_dev.c                          |  4 ++--
 net/core/dev.c                                | 11 +++++-----
 net/ethtool/ioctl.c                           |  5 +++--
 net/tls/tls_device.c                          |  2 +-
 34 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 90e22972fd81..f6015c49363e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2206,7 +2206,7 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 		netdev_features_set(&features, vxlan_base);
 	}
 
-	if (features & netdev_ip_csum_features) {
+	if (netdev_features_intersects(features, netdev_ip_csum_features)) {
 		if (!netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features)) {
 			netdev_notice(netdev,
 				      "forcing tx udp tunnel checksumming on\n");
diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c
index 66e428e25b7d..27f48743c72f 100644
--- a/drivers/net/ethernet/asix/ax88796c_main.c
+++ b/drivers/net/ethernet/asix/ax88796c_main.c
@@ -926,12 +926,12 @@ ax88796c_set_features(struct net_device *ndev, netdev_features_t features)
 	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
 	netdev_features_t changed = netdev_active_features_xor(ndev, features);
 
-	if (!(changed & ax88796c_features))
+	if (!netdev_features_intersects(changed, ax88796c_features))
 		return 0;
 
 	ndev->features = features;
 
-	if (changed & ax88796c_features)
+	if (netdev_features_intersects(changed, ax88796c_features))
 		ax88796c_set_csums(ax_local);
 
 	return 0;
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 36234f731076..4f8db6155c57 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -172,7 +172,7 @@ static void bcm_sysport_set_tx_csum(struct net_device *dev,
 	/* Hardware transmit checksum requires us to enable the Transmit status
 	 * block prepended to the packet contents
 	 */
-	priv->tsb_en = !!(wanted & tx_csum_features);
+	priv->tsb_en = netdev_features_intersects(tx_csum_features, wanted);
 	reg = tdma_readl(priv, TDMA_CONTROL);
 	if (priv->tsb_en)
 		reg |= tdma_control_bit(priv, TSB_EN);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index dd744764cf4b..35fb5b726df1 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1740,7 +1740,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
 		skb_set_hash(skb, tpa_info->rss_hash, tpa_info->hash_type);
 
 	if ((tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) &&
-	    (skb->dev->features & BNXT_HW_FEATURE_VLAN_ALL_RX)) {
+	    netdev_active_features_intersects(skb->dev, BNXT_HW_FEATURE_VLAN_ALL_RX)) {
 		__be16 vlan_proto = htons(tpa_info->metadata >>
 					  RX_CMP_FLAGS2_METADATA_TPID_SFT);
 		u16 vtag = tpa_info->metadata & RX_CMP_FLAGS2_METADATA_TCI_MASK;
@@ -2010,7 +2010,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
 
 	if ((rxcmp1->rx_cmp_flags2 &
 	     cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN)) &&
-	    (skb->dev->features & BNXT_HW_FEATURE_VLAN_ALL_RX)) {
+	    netdev_active_features_intersects(skb->dev, BNXT_HW_FEATURE_VLAN_ALL_RX)) {
 		u32 meta_data = le32_to_cpu(rxcmp1->rx_cmp_meta_data);
 		u16 vtag = meta_data & RX_CMP_FLAGS2_METADATA_TCI_MASK;
 		__be16 vlan_proto = htons(meta_data >>
@@ -11200,7 +11200,7 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 	 */
 	vlan_features = features & BNXT_HW_FEATURE_VLAN_ALL_RX;
 	if (vlan_features != BNXT_HW_FEATURE_VLAN_ALL_RX) {
-		if (dev->features & BNXT_HW_FEATURE_VLAN_ALL_RX)
+		if (netdev_active_features_intersects(dev, BNXT_HW_FEATURE_VLAN_ALL_RX))
 			netdev_features_clear(&features,
 					      BNXT_HW_FEATURE_VLAN_ALL_RX);
 		else if (vlan_features)
@@ -11232,7 +11232,7 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
 	if (bp->flags & BNXT_FLAG_NO_AGG_RINGS)
 		flags &= ~BNXT_FLAG_TPA;
 
-	if (features & BNXT_HW_FEATURE_VLAN_ALL_RX)
+	if (netdev_features_intersects(features, BNXT_HW_FEATURE_VLAN_ALL_RX))
 		flags |= BNXT_FLAG_STRIP_VLAN;
 
 	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, features))
@@ -13712,7 +13712,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	bnxt_init_dflt_coal(bp);
 
-	if (dev->hw_features & BNXT_HW_FEATURE_VLAN_ALL_RX)
+	if (netdev_hw_features_intersects(dev, BNXT_HW_FEATURE_VLAN_ALL_RX))
 		bp->flags |= BNXT_FLAG_STRIP_VLAN;
 
 	rc = bnxt_init_int_mode(bp);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 165b6c9c0c41..a552e5a5a353 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -2440,8 +2440,9 @@ static int dpaa2_eth_set_features(struct net_device *net_dev,
 			return err;
 	}
 
-	if (changed & netdev_ip_csum_features) {
-		enable = !!(features & netdev_ip_csum_features);
+	if (netdev_features_intersects(changed, netdev_ip_csum_features)) {
+		enable = netdev_features_intersects(features,
+						    netdev_ip_csum_features);
 		err = dpaa2_eth_set_tx_csum(priv, enable);
 		if (err)
 			return err;
@@ -4702,7 +4703,8 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
 		goto err_csum;
 
 	err = dpaa2_eth_set_tx_csum(priv,
-				    !!(net_dev->features & netdev_ip_csum_features));
+				    netdev_active_features_intersects(net_dev,
+								      netdev_ip_csum_features));
 	if (err)
 		goto err_csum;
 
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 01e9e7aba739..997a1551dce6 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -512,7 +512,7 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features)
 	struct gfar_private *priv = netdev_priv(dev);
 	int err = 0;
 
-	if (!(changed & netdev_ctag_vlan_offload_features) &&
+	if (!netdev_features_intersects(changed, netdev_ctag_vlan_offload_features) &&
 	    !netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index dbce348ca438..cba1c2cc4495 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1773,11 +1773,11 @@ static int hns_nic_set_features(struct net_device *netdev,
 
 	switch (priv->enet_ver) {
 	case AE_VERSION_1:
-		if (features & netdev_general_tso_features)
+		if (netdev_features_intersects(features, netdev_general_tso_features))
 			netdev_info(netdev, "enet v1 do not support tso!\n");
 		break;
 	default:
-		if (features & netdev_general_tso_features) {
+		if (netdev_features_intersects(features, netdev_general_tso_features)) {
 			priv->ops.fill_desc = fill_tso_desc;
 			priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tso;
 			/* The chip only support 7*4096 */
@@ -2166,7 +2166,7 @@ static void hns_nic_set_priv_ops(struct net_device *netdev)
 		priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tx;
 	} else {
 		priv->ops.get_rxd_bnum = get_v2rx_desc_bnum;
-		if (netdev->features & netdev_general_tso_features) {
+		if (netdev_active_features_intersects(netdev, netdev_general_tso_features)) {
 			priv->ops.fill_desc = fill_tso_desc;
 			priv->ops.maybe_stop_tx = hns_nic_maybe_stop_tso;
 			/* This chip only support 7*4096 */
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 1f4e5a7d1f95..bb581f978234 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -904,7 +904,8 @@ static int ibmveth_set_features(struct net_device *dev,
 {
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
 	int rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
-	int large_send = !!(features & netdev_general_tso_features);
+	int large_send = netdev_features_intersects(features,
+						    netdev_general_tso_features);
 	int rc1 = 0, rc2 = 0;
 
 	if (rx_csum != adapter->rx_csum) {
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 09bd2505b39a..79f9363ec939 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4884,7 +4884,7 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 	if (buf->tcp_ipv6_chksum || buf->udp_ipv6_chksum)
 		netdev_hw_feature_add(adapter->netdev, NETIF_F_IPV6_CSUM_BIT);
 
-	if ((adapter->netdev->features & netdev_ip_csum_features))
+	if (netdev_active_features_intersects(adapter->netdev, netdev_ip_csum_features))
 		netdev_hw_feature_add(adapter->netdev, NETIF_F_RXCSUM_BIT);
 
 	if (buf->large_tx_ipv4)
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index c164802ab58d..c6fbadfb8715 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -7327,12 +7327,12 @@ static int e1000_set_features(struct net_device *netdev,
 	netdev_features_t changed = netdev_active_features_xor(netdev, features);
 	netdev_features_t changeable;
 
-	if (changed & netdev_general_tso_features)
+	if (netdev_features_intersects(changed, netdev_general_tso_features))
 		adapter->flags |= FLAG_TSO_FORCE;
 
 	netdev_features_zero(&changeable);
 	netdev_features_set_array(&e1000_changable_feature_set, &changeable);
-	if (!(changed & changeable))
+	if (!netdev_features_intersects(changed, changeable))
 		return 0;
 
 	if (netdev_feature_test(NETIF_F_RXFCS_BIT, changed)) {
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index b59cc9891fce..09711e527bd3 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2125,20 +2125,20 @@ iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
 	 * ETH_P_8021Q so an ethertype is specified if disabling insertion and
 	 * stripping.
 	 */
-	if (features & netdev_stag_vlan_offload_features)
+	if (netdev_features_intersects(features, netdev_stag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021AD;
-	else if (features & netdev_ctag_vlan_offload_features)
+	else if (netdev_features_intersects(features, netdev_ctag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021Q;
-	else if (prev_features & netdev_stag_vlan_offload_features)
+	else if (netdev_features_intersects(prev_features, netdev_stag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021AD;
-	else if (prev_features & netdev_ctag_vlan_offload_features)
+	else if (netdev_features_intersects(prev_features, netdev_ctag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021Q;
 	else
 		vlan_ethertype = ETH_P_8021Q;
 
-	if (!(features & netdev_rx_vlan_features))
+	if (!netdev_features_intersects(features, netdev_rx_vlan_features))
 		enable_stripping = false;
-	if (!(features & netdev_tx_vlan_features))
+	if (!netdev_features_intersects(features, netdev_tx_vlan_features))
 		enable_insertion = false;
 
 	if (VLAN_ALLOWED(adapter)) {
@@ -4241,8 +4241,8 @@ static int iavf_set_features(struct net_device *netdev,
 	struct iavf_adapter *adapter = netdev_priv(netdev);
 
 	/* trigger update on any VLAN feature change */
-	if ((netdev->features & NETIF_VLAN_OFFLOAD_FEATURES) ^
-	    (features & NETIF_VLAN_OFFLOAD_FEATURES))
+	if (netdev_active_features_intersects(netdev, NETIF_VLAN_OFFLOAD_FEATURES) ^
+	    netdev_features_intersects(features, NETIF_VLAN_OFFLOAD_FEATURES))
 		iavf_set_vlan_offload_features(adapter, netdev->features,
 					       features);
 
@@ -4536,8 +4536,8 @@ iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
 		netdev_feature_del(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
 				   &requested_features);
 
-	if ((requested_features & netdev_ctag_vlan_offload_features) &&
-	    (requested_features & netdev_stag_vlan_offload_features) &&
+	if (netdev_features_intersects(requested_features, netdev_ctag_vlan_offload_features) &&
+	    netdev_features_intersects(requested_features, netdev_stag_vlan_offload_features) &&
 	    adapter->vlan_v2_caps.offloads.ethertype_match ==
 	    VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION) {
 		netdev_warn(adapter->netdev, "cannot support CTAG and STAG VLAN stripping and/or insertion simultaneously since CTAG and STAG offloads are mutually exclusive, clearing STAG offload settings\n");
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 088719732394..a58669228d64 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5821,8 +5821,8 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 		}
 	}
 
-	if ((features & netdev_ctag_vlan_offload_features) &&
-	    (features & netdev_stag_vlan_offload_features)) {
+	if (netdev_features_intersects(features, netdev_ctag_vlan_offload_features) &&
+	    netdev_features_intersects(features, netdev_stag_vlan_offload_features)) {
 		netdev_warn(netdev, "cannot support CTAG and STAG VLAN stripping and/or insertion simultaneously since CTAG and STAG offloads are mutually exclusive, clearing STAG offload settings\n");
 		netdev_features_clear(&features,
 				      netdev_stag_vlan_offload_features);
@@ -5850,14 +5850,14 @@ ice_set_vlan_offload_features(struct ice_vsi *vsi, netdev_features_t features)
 
 	vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
 
-	if (features & netdev_stag_vlan_offload_features)
+	if (netdev_features_intersects(features, netdev_stag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021AD;
-	else if (features & netdev_ctag_vlan_offload_features)
+	else if (netdev_features_intersects(features, netdev_ctag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021Q;
 
-	if (!(features & netdev_rx_vlan_features))
+	if (!netdev_features_intersects(features, netdev_rx_vlan_features))
 		enable_stripping = false;
-	if (!(features & netdev_tx_vlan_features))
+	if (!netdev_features_intersects(features, netdev_tx_vlan_features))
 		enable_insertion = false;
 
 	if (enable_stripping)
@@ -5893,7 +5893,7 @@ ice_set_vlan_filtering_features(struct ice_vsi *vsi, netdev_features_t features)
 	/* support Single VLAN Mode (SVM) and Double VLAN Mode (DVM) by checking
 	 * if either bit is set
 	 */
-	if (features & netdev_vlan_filter_features)
+	if (netdev_features_intersects(features, netdev_vlan_filter_features))
 		err = vlan_ops->ena_rx_filtering(vsi);
 	else
 		err = vlan_ops->dis_rx_filtering(vsi);
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 9da8a0ebb383..b5e3180a05f4 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4348,7 +4348,7 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features)
 	if (netdev_feature_test(NETIF_F_RXHASH_BIT, changed))
 		rx_set_rss(dev, features);
 
-	if (changed & netdev_ctag_vlan_offload_features)
+	if (netdev_features_intersects(changed, netdev_ctag_vlan_offload_features))
 		sky2_vlan_mode(dev, features);
 
 	return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 1c1637445980..9bad2a77bd54 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4482,7 +4482,8 @@ netdev_features_t mlx5e_features_check(struct sk_buff *skb,
 
 	/* Validate if the tunneled packet is being offloaded by HW */
 	if (skb->encapsulation &&
-	    (features & NETIF_F_CSUM_MASK || features & NETIF_F_GSO_MASK))
+	    (netdev_features_intersects(features, NETIF_F_CSUM_MASK) ||
+	     netdev_features_intersects(features, NETIF_F_GSO_MASK)))
 		return mlx5e_tunnel_features_check(priv, skb, features);
 
 	return features;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 8bcf75169a93..1ff44d5a2c7c 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1680,15 +1680,15 @@ static int nfp_net_set_features(struct net_device *netdev,
 			new_ctrl &= ~NFP_NET_CFG_CTRL_RXCSUM_ANY;
 	}
 
-	if (changed & netdev_ip_csum_features) {
-		if (features & netdev_ip_csum_features)
+	if (netdev_features_intersects(changed, netdev_ip_csum_features)) {
+		if (netdev_features_intersects(features, netdev_ip_csum_features))
 			new_ctrl |= NFP_NET_CFG_CTRL_TXCSUM;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_TXCSUM;
 	}
 
-	if (changed & netdev_general_tso_features) {
-		if (features & netdev_general_tso_features)
+	if (netdev_features_intersects(changed, netdev_general_tso_features)) {
+		if (netdev_features_intersects(features, netdev_general_tso_features))
 			new_ctrl |= nn->cap & NFP_NET_CFG_CTRL_LSO2 ?:
 					      NFP_NET_CFG_CTRL_LSO;
 		else
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index acee5eeb4d2e..346bc59ce40d 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -245,7 +245,7 @@ nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
 	lower_dev = repr->dst->u.port_info.lower_dev;
 
 	lower_features = lower_dev->features;
-	if (lower_features & netdev_ip_csum_features)
+	if (netdev_features_intersects(lower_features, netdev_ip_csum_features))
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &lower_features);
 
 	features = netdev_intersect_features(features, lower_features);
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 7fd4f3519414..b4a2fc027475 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4931,7 +4931,7 @@ static netdev_features_t nv_fix_features(struct net_device *dev,
 	netdev_features_t features)
 {
 	/* vlan is dependent on rx checksum offload */
-	if (features & netdev_ctag_vlan_offload_features)
+	if (netdev_features_intersects(features, netdev_ctag_vlan_offload_features))
 		netdev_feature_add(NETIF_F_RXCSUM_BIT, &features);
 
 	return features;
@@ -4985,7 +4985,7 @@ static int nv_set_features(struct net_device *dev, netdev_features_t features)
 		spin_unlock_irq(&np->lock);
 	}
 
-	if (changed & netdev_ctag_vlan_offload_features)
+	if (netdev_features_intersects(changed, netdev_ctag_vlan_offload_features))
 		nv_vlan_mode(dev, features);
 
 	return 0;
@@ -6127,8 +6127,8 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 		 netdev_active_feature_test(dev, NETIF_F_HIGHDMA_BIT) ? "highdma " : "",
 		 (netdev_active_feature_test(dev, NETIF_F_IP_CSUM_BIT) ||
 		  netdev_active_feature_test(dev, NETIF_F_SG_BIT)) ? "csum " : "",
-		 dev->features & netdev_ctag_vlan_offload_features ?
-			"vlan " : "",
+		 netdev_active_features_intersects(dev, netdev_ctag_vlan_offload_features) ?
+		 "vlan " : "",
 		 netdev_active_feature_test(dev, NETIF_F_LOOPBACK_BIT) ?
 			"loopback " : "",
 		 id->driver_data & DEV_HAS_POWER_CNTRL ? "pwrctl " : "",
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 30bc427dba46..707fb8a65be1 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1886,7 +1886,7 @@ netxen_tso_check(struct net_device *netdev,
 		vlan_oob = 1;
 	}
 
-	if ((netdev->features & netdev_general_tso_features) &&
+	if (netdev_active_features_intersects(netdev, netdev_general_tso_features) &&
 	    skb_shinfo(skb)->gso_size > 0) {
 
 		hdr_len = skb_tcp_all_headers(skb);
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 3c85eb122448..7b71c2e6f659 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -182,7 +182,7 @@ static int emac_set_features(struct net_device *netdev,
 	/* We only need to reprogram the hardware if the VLAN tag features
 	 * have changed, and if it's already running.
 	 */
-	if (!(changed & netdev_ctag_vlan_offload_features))
+	if (!netdev_features_intersects(changed, netdev_ctag_vlan_offload_features))
 		return 0;
 
 	if (!netif_running(netdev))
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
index 2595fe837c78..22777ec41f47 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
@@ -437,7 +437,7 @@ static void rmnet_map_v4_checksum_uplink_packet(struct sk_buff *skb,
 	ul_header = (struct rmnet_map_ul_csum_header *)
 		    skb_push(skb, sizeof(struct rmnet_map_ul_csum_header));
 
-	if (unlikely(!(orig_dev->features & netdev_ip_csum_features)))
+	if (unlikely(!netdev_active_features_intersects(orig_dev, netdev_ip_csum_features)))
 		goto sw_csum;
 
 	if (skb->ip_summed != CHECKSUM_PARTIAL)
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index a4366c23b50f..fdde83bef88e 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -1361,7 +1361,7 @@ netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev
 	struct efx_nic *efx = 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.
 			 */
@@ -1369,7 +1369,7 @@ netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev
 			    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/drivers/net/ethernet/sfc/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 6f547c54e3f1..7eaa2fe9dc13 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -1374,7 +1374,7 @@ netdev_features_t efx_siena_features_check(struct sk_buff *skb,
 	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.
 			 */
@@ -1382,7 +1382,7 @@ netdev_features_t efx_siena_features_check(struct sk_buff *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/drivers/net/tap.c b/drivers/net/tap.c
index 67bfe9cbc573..1ba49051308b 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -382,7 +382,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
 		 *	  check, we either support them all or none.
 		 */
 		if (skb->ip_summed == CHECKSUM_PARTIAL &&
-		    !(features & NETIF_F_CSUM_MASK) &&
+		    !netdev_features_intersects(features, NETIF_F_CSUM_MASK) &&
 		    skb_checksum_help(skb)) {
 			drop_reason = SKB_DROP_REASON_SKB_CSUM;
 			goto drop;
@@ -977,7 +977,7 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
 	 * When user space turns off TSO, we turn off GSO/LRO so that
 	 * user-space will not receive TSO frames.
 	 */
-	if (feature_mask & netdev_general_tso_features)
+	if (netdev_features_intersects(feature_mask, netdev_general_tso_features))
 		netdev_features_set_array(&tap_rx_offload_feature_set, &features);
 	else
 		netdev_features_clear_array(&tap_rx_offload_feature_set, &features);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index ec210e5586f4..c47a3cebc1bc 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -305,7 +305,7 @@ static bool veth_skb_is_eligible_for_gro(const struct net_device *dev,
 					 const struct net_device *rcv,
 					 const struct sk_buff *skb)
 {
-	return !(dev->features & NETIF_F_ALL_TSO) ||
+	return !netdev_active_features_intersects(dev, NETIF_F_ALL_TSO) ||
 		(skb->destructor == sock_wfree &&
 		 (netdev_active_feature_test(rcv, NETIF_F_GRO_FRAGLIST_BIT) ||
 		  netdev_active_feature_test(rcv, NETIF_F_GRO_UDP_FWD_BIT)));
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 8d1ba53fec93..797d0a75929e 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -422,12 +422,12 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 	netdev_features_zero(&tun_offload_mask);
 	netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_BIT, &tun_offload_mask);
 	netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, &tun_offload_mask);
-	udp_tun_enabled = (netdev->features & tun_offload_mask) != 0;
+	udp_tun_enabled = netdev_active_features_intersects(netdev, tun_offload_mask);
 
 	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed) ||
 	    netdev_feature_test(NETIF_F_LRO_BIT, changed) ||
 	    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed) ||
-	    changed & tun_offload_mask) {
+	    netdev_features_intersects(changed, tun_offload_mask)) {
 		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
 			adapter->shared->devRead.misc.uptFeatures |=
 			UPT1_F_RXCSUM;
@@ -450,11 +450,11 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 			adapter->shared->devRead.misc.uptFeatures &=
 			~UPT1_F_RXVLAN;
 
-		if ((features & tun_offload_mask) != 0) {
+		if (netdev_features_intersects(features, tun_offload_mask)) {
 			vmxnet3_enable_encap_offloads(netdev, features);
 			adapter->shared->devRead.misc.uptFeatures |=
 			UPT1_F_RXINNEROFLD;
-		} else if ((features & tun_offload_mask) == 0 &&
+		} else if (!netdev_features_intersects(features, tun_offload_mask) &&
 			   udp_tun_enabled) {
 			vmxnet3_disable_encap_offloads(netdev);
 			adapter->shared->devRead.misc.uptFeatures &=
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 6ac083a84597..4312bcf2d70a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -54,7 +54,8 @@ static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb,
 		goto out;
 
 	/* We do not expect to be requested to csum stuff we do not support */
-	if (WARN_ONCE(!(mvm->hw->netdev_features & IWL_TX_CSUM_NETIF_FLAGS) ||
+	if (WARN_ONCE(!netdev_features_intersects(mvm->hw->netdev_features,
+						  IWL_TX_CSUM_NETIF_FLAGS) ||
 		      (skb->protocol != htons(ETH_P_IP) &&
 		       skb->protocol != htons(ETH_P_IPV6)),
 		      "No support for requested checksum\n")) {
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 1a181b2de48d..99f7ad47dc19 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6852,9 +6852,11 @@ static void qeth_check_restricted_features(struct qeth_card *card,
 	if (!card->info.has_lp2lp_cso_v4)
 		netdev_feature_add(NETIF_F_IP_CSUM_BIT, &ipv4_features);
 
-	if ((changed & ipv6_features) && !(actual & ipv6_features))
+	if (netdev_features_intersects(changed, ipv6_features) &&
+	    !netdev_features_intersects(actual, ipv6_features))
 		qeth_flush_local_addrs6(card);
-	if ((changed & ipv4_features) && !(actual & ipv4_features))
+	if (netdev_features_intersects(changed, ipv4_features) &&
+	    !netdev_features_intersects(actual, ipv4_features))
 		qeth_flush_local_addrs4(card);
 }
 
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 32926f3c90ed..f7c2dec0b325 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1130,7 +1130,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
 		netdev_vlan_feature_add(card->dev, NETIF_F_TSO6_BIT);
 	}
 
-	if (card->dev->hw_features & netdev_general_tso_features) {
+	if (netdev_hw_features_intersects(card->dev, netdev_general_tso_features)) {
 		card->dev->needed_headroom = sizeof(struct qeth_hdr_tso);
 		netif_keep_dst(card->dev);
 		netif_set_tso_max_size(card->dev,
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 4d0985f20050..bf7901815998 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1913,7 +1913,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 				   netdev_ctag_vlan_offload_features);
 
 	netif_keep_dst(card->dev);
-	if (card->dev->hw_features & netdev_general_tso_features)
+	if (netdev_hw_features_intersects(card->dev, netdev_general_tso_features))
 		netif_set_tso_max_size(card->dev,
 				       PAGE_SIZE * (QETH_MAX_BUFFER_ELEMENTS(card) - 1));
 
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index e08bbe2ae55b..73c4a6595ace 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -112,7 +112,8 @@ static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)
 	netdev_features_set(&ret, NETIF_F_GSO_ENCAP_ALL);
 	ret &= real_dev->hw_enc_features;
 
-	if ((ret & NETIF_F_GSO_ENCAP_ALL) && (ret & NETIF_F_CSUM_MASK)) {
+	if (netdev_features_intersects(ret, NETIF_F_GSO_ENCAP_ALL) &&
+	    netdev_features_intersects(ret, NETIF_F_CSUM_MASK)) {
 		netdev_features_clear(&ret, NETIF_F_CSUM_MASK);
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &ret);
 		return ret;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 56f9b0233d51..d13236621a40 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -582,7 +582,7 @@ static int vlan_dev_init(struct net_device *dev)
 	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netif_inherit_tso_max(dev, real_dev);
-	if (dev->features & NETIF_F_VLAN_FEATURES)
+	if (netdev_active_features_intersects(dev, NETIF_F_VLAN_FEATURES))
 		netdev_warn(real_dev, "VLAN features are set incorrectly.  Q-in-Q configurations may not work correctly.\n");
 
 	dev->vlan_features = netdev_vlan_features_andnot(real_dev,
@@ -664,7 +664,7 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
 	/* Add HW_CSUM setting to preserve user ability to control
 	 * checksum offload on the vlan device.
 	 */
-	if (lower_features & netdev_ip_csum_features)
+	if (netdev_features_intersects(lower_features, netdev_ip_csum_features))
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &lower_features);
 	features = netdev_intersect_features(features, lower_features);
 	tmp = netdev_features_or(NETIF_F_SOFT_FEATURES, NETIF_F_GSO_SOFTWARE);
diff --git a/net/core/dev.c b/net/core/dev.c
index 7188932a2158..dc4cadf2e4df 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3644,7 +3644,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):
@@ -9609,13 +9609,13 @@ 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) &&
+	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);
@@ -9644,7 +9644,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. */
@@ -9655,7 +9656,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 c98b49d5eff1..f1ae7a4ade29 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -271,7 +271,7 @@ static int ethtool_get_one_feature(struct net_device *dev,
 	netdev_features_t mask = ethtool_get_feature_mask(ethcmd);
 	struct ethtool_value edata = {
 		.cmd = ethcmd,
-		.data = !!(dev->features & mask),
+		.data = netdev_active_features_intersects(dev, mask),
 	};
 
 	if (copy_to_user(useraddr, &edata, sizeof(edata)))
@@ -360,7 +360,8 @@ 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;
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index c88fbe2e1cf5..361c9fe1e689 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -1403,7 +1403,7 @@ static int tls_dev_event(struct notifier_block *this, unsigned long event,
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
 	if (!dev->tlsdev_ops &&
-	    !(dev->features & netdev_tls_features))
+	    !netdev_active_features_intersects(dev, netdev_tls_features))
 		return NOTIFY_DONE;
 
 	switch (event) {
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 32/36] net: use netdev_features_and and netdev_features_mask helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (30 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 31/36] treewide: use netdev_features_intersects helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 33/36] treewide: use netdev_features_subset helpers Jian Shen
                   ` (3 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '&' expressions of features by netdev_features_and
helpers, and replace the '& =' expressions by netdev_features_clear
helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/bonding/bond_main.c                 |  4 ++--
 drivers/net/ethernet/broadcom/bnx2.c            |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c       |  2 +-
 drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c |  2 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |  3 ++-
 .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c |  3 ++-
 .../net/ethernet/fungible/funeth/funeth_main.c  |  2 +-
 drivers/net/ethernet/ibm/ibmvnic.c              |  7 ++++---
 drivers/net/ethernet/intel/ice/ice_main.c       | 17 ++++++++++-------
 .../net/ethernet/netronome/nfp/nfp_net_common.c |  2 +-
 .../net/ethernet/netronome/nfp/nfp_net_repr.c   |  2 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c  |  2 +-
 drivers/net/hyperv/rndis_filter.c               |  2 +-
 drivers/net/ipvlan/ipvlan_main.c                |  9 +++++----
 drivers/net/macsec.c                            |  7 ++++---
 drivers/net/macvlan.c                           | 10 +++++-----
 drivers/net/net_failover.c                      |  4 ++--
 drivers/net/team/team.c                         |  4 ++--
 drivers/net/tun.c                               |  2 +-
 drivers/net/virtio_net.c                        |  3 ++-
 include/linux/if_vlan.h                         |  4 +++-
 include/linux/netdev_features_helper.h          |  2 +-
 net/8021q/vlan.h                                |  2 +-
 net/8021q/vlan_dev.c                            |  2 +-
 net/core/dev.c                                  | 17 +++++++++--------
 net/ethtool/ioctl.c                             |  6 +++---
 net/ipv4/af_inet.c                              |  2 +-
 net/ipv4/gre_offload.c                          |  2 +-
 net/ipv4/udp_offload.c                          |  2 +-
 net/ipv6/ip6_offload.c                          |  2 +-
 net/mac80211/iface.c                            |  3 ++-
 net/mpls/mpls_gso.c                             |  3 ++-
 net/nsh/nsh.c                                   |  2 +-
 33 files changed, 76 insertions(+), 62 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 628526c3323a..da6e6c73dc6a 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1467,8 +1467,8 @@ static void bond_compute_features(struct bonding *bond)
 
 	if (!bond_has_slaves(bond))
 		goto done;
-	vlan_features &= NETIF_F_ALL_FOR_ALL;
-	mpls_features &= NETIF_F_ALL_FOR_ALL;
+	netdev_features_mask(&vlan_features, NETIF_F_ALL_FOR_ALL);
+	netdev_features_mask(&mpls_features, NETIF_F_ALL_FOR_ALL);
 
 	bond_for_each_slave(bond, slave, iter) {
 		vlan_features = netdev_increment_features(vlan_features,
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index ac46a10b6252..d08141a77e1e 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -7757,7 +7757,7 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features)) {
 		netdev_features_t tso;
 
-		tso = dev->hw_features & NETIF_F_ALL_TSO;
+		tso = netdev_hw_features_and(dev, NETIF_F_ALL_TSO);
 		netdev_vlan_features_set(dev, tso);
 	} else {
 		netdev_vlan_features_clear(dev, NETIF_F_ALL_TSO);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 35fb5b726df1..6b2ee76666bf 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11198,7 +11198,7 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 	/* Both CTAG and STAG VLAN accelaration on the RX side have to be
 	 * turned on or off together.
 	 */
-	vlan_features = features & BNXT_HW_FEATURE_VLAN_ALL_RX;
+	vlan_features = netdev_features_and(features, BNXT_HW_FEATURE_VLAN_ALL_RX);
 	if (vlan_features != BNXT_HW_FEATURE_VLAN_ALL_RX) {
 		if (netdev_active_features_intersects(dev, BNXT_HW_FEATURE_VLAN_ALL_RX))
 			netdev_features_clear(&features,
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index d7c1637f7d63..d8d9b9a42aa4 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3327,7 +3327,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 		netdev_features_zero(&vlan_feat);
 		netdev_features_set_array(&cxgb_vlan_feature_set, &vlan_feat);
-		vlan_feat &= netdev->features;
+		netdev_features_mask(&vlan_feat, netdev->features);
 		netdev_vlan_features_set(netdev, vlan_feat);
 
 		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index e903fe97975d..da5e23346871 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6867,7 +6867,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_active_features_set(netdev, netdev->hw_features);
 		vlan_features = tso_features;
 		netdev_features_set_array(&cxgb4_vlan_feature_set, &vlan_features);
-		netdev->vlan_features = netdev->features & vlan_features;
+		netdev->vlan_features = netdev_active_features_and(netdev,
+								   vlan_features);
 #if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
 		if (pi->adapter->params.crypto & FW_CAPS_CONFIG_TLS_HW) {
 			netdev_hw_feature_add(netdev, NETIF_F_HW_TLS_TX_BIT);
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index efc86d7e7c42..729e0a272413 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -3098,7 +3098,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 		vlan_features = tso_features;
 		netdev_features_set_array(&cxgb4vf_vlan_feature_set,
 					  &vlan_features);
-		netdev->vlan_features = netdev->features & vlan_features;
+		netdev->vlan_features = netdev_active_features_and(netdev,
+								   vlan_features);
 
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 		netdev->min_mtu = 81;
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_main.c b/drivers/net/ethernet/fungible/funeth/funeth_main.c
index 0fee1effb7ce..c883572e48a1 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1797,7 +1797,7 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 
 	netdev_active_features_set(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
-	netdev->vlan_features = netdev->features & vlan_feat;
+	netdev->vlan_features = netdev_active_features_and(netdev, vlan_feat);
 	netdev->mpls_features = netdev->vlan_features;
 	netdev->hw_enc_features = netdev->hw_features;
 
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 79f9363ec939..95016982f03b 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4899,11 +4899,12 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 		netdev_features_t tmp = netdev_empty_features;
 
 		/* disable features no longer supported */
-		adapter->netdev->features &= adapter->netdev->hw_features;
+		netdev_active_features_mask(adapter->netdev,
+					    adapter->netdev->hw_features);
 		/* turn on features now supported if previously enabled */
 		tmp = netdev_hw_features_xor(adapter->netdev, old_hw_features);
-		tmp &= adapter->netdev->hw_features;
-		tmp &= adapter->netdev->wanted_features;
+		netdev_features_mask(&tmp, adapter->netdev->hw_features);
+		netdev_features_mask(&tmp, adapter->netdev->wanted_features);
 		netdev_active_features_set(adapter->netdev, tmp);
 	}
 
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index a58669228d64..19a0e82d45ae 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5780,13 +5780,13 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 	netdev_features_t req_vlan_fltr, cur_vlan_fltr;
 	bool cur_ctag, cur_stag, req_ctag, req_stag;
 
-	cur_vlan_fltr = netdev->features & NETIF_VLAN_FILTERING_FEATURES;
+	cur_vlan_fltr = netdev_active_features_and(netdev, NETIF_VLAN_FILTERING_FEATURES);
 	cur_ctag = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				       cur_vlan_fltr);
 	cur_stag = netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
 				       cur_vlan_fltr);
 
-	req_vlan_fltr = features & NETIF_VLAN_FILTERING_FEATURES;
+	req_vlan_fltr = netdev_features_and(features, NETIF_VLAN_FILTERING_FEATURES);
 	req_ctag = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				       req_vlan_fltr);
 	req_stag = netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
@@ -5917,8 +5917,10 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 	struct ice_vsi *vsi = np->vsi;
 	int err;
 
-	current_vlan_features = netdev->features & NETIF_VLAN_OFFLOAD_FEATURES;
-	requested_vlan_features = features & NETIF_VLAN_OFFLOAD_FEATURES;
+	current_vlan_features = netdev_active_features_and(netdev,
+							   NETIF_VLAN_OFFLOAD_FEATURES);
+	requested_vlan_features = netdev_features_and(features,
+						      NETIF_VLAN_OFFLOAD_FEATURES);
 	diff = netdev_features_xor(current_vlan_features, requested_vlan_features);
 	if (diff) {
 		err = ice_set_vlan_offload_features(vsi, features);
@@ -5926,9 +5928,10 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 			return err;
 	}
 
-	current_vlan_features = netdev->features &
-		NETIF_VLAN_FILTERING_FEATURES;
-	requested_vlan_features = features & NETIF_VLAN_FILTERING_FEATURES;
+	current_vlan_features = netdev_active_features_and(netdev,
+							   NETIF_VLAN_FILTERING_FEATURES);
+	requested_vlan_features = netdev_features_and(features,
+						      NETIF_VLAN_FILTERING_FEATURES);
 	diff = netdev_features_xor(current_vlan_features, requested_vlan_features);
 	if (diff) {
 		err = ice_set_vlan_filtering_features(vsi, features);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 1ff44d5a2c7c..bcd8513b3b43 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1785,7 +1785,7 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
 	u8 l4_hdr;
 
 	/* We can't do TSO over double tagged packets (802.1AD) */
-	features &= vlan_features_check(skb, features);
+	netdev_features_mask(&features, vlan_features_check(skb, features));
 
 	if (!skb->encapsulation)
 		return features;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 346bc59ce40d..f250067dad7e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -251,7 +251,7 @@ nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
 	features = netdev_intersect_features(features, lower_features);
 	tmp = NETIF_F_SOFT_FEATURES;
 	netdev_feature_add(NETIF_F_HW_TC_BIT, &tmp);
-	tmp &= old_features;
+	netdev_features_mask(&tmp, old_features);
 	netdev_features_set(&features, tmp);
 	netdev_feature_add(NETIF_F_LLTX_BIT, &features);
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 4fd623d65921..a7ce52edf2df 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1081,7 +1081,7 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 			netdev_features_zero(&changeable);
 			netdev_features_set_array(&qlcnic_changable_feature_set,
 						  &changeable);
-			changed &= changeable;
+			netdev_features_mask(&changed, changeable);
 			netdev_features_toggle(&features, changed);
 		}
 	}
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 02d2f94c8364..17bf22a0e9b0 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1434,7 +1434,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
 	netdev_features_fill(&features);
 	netdev_features_clear(&features, NETVSC_SUPPORTED_HW_FEATURES);
 	netdev_features_set(&features, net->hw_features);
-	net->features &= features;
+	netdev_active_features_mask(net, features);
 
 	netif_set_tso_max_size(net, gso_max_size);
 
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index e719b457e4e8..6db91e0de2f2 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -151,9 +151,10 @@ static int ipvlan_init(struct net_device *dev)
 
 	dev->state = (dev->state & ~IPVLAN_STATE_MASK) |
 		     (phy_dev->state & IPVLAN_STATE_MASK);
-	dev->features = phy_dev->features & IPVLAN_FEATURES;
+	dev->features = netdev_active_features_and(phy_dev, IPVLAN_FEATURES);
 	netdev_active_features_set(dev, IPVLAN_ALWAYS_ON);
-	dev->vlan_features = phy_dev->vlan_features & IPVLAN_FEATURES;
+	dev->vlan_features = netdev_vlan_features_and(phy_dev,
+						      IPVLAN_FEATURES);
 	netdev_vlan_features_set(dev, IPVLAN_ALWAYS_ON_OFLOADS);
 	netdev_hw_enc_features_set(dev, dev->features);
 	netif_inherit_tso_max(dev, phy_dev);
@@ -260,12 +261,12 @@ static netdev_features_t ipvlan_fix_features(struct net_device *dev,
 	netdev_features_fill(&tmp);
 	netdev_features_clear(&tmp, IPVLAN_FEATURES);
 	netdev_features_set(&tmp, ipvlan->sfeatures);
-	features &= tmp;
+	netdev_features_mask(&features, tmp);
 	features = netdev_increment_features(ipvlan->phy_dev->features,
 					     features, features);
 	netdev_features_set(&features, IPVLAN_ALWAYS_ON);
 	tmp = netdev_features_or(IPVLAN_FEATURES, IPVLAN_ALWAYS_ON);
-	features &= tmp;
+	netdev_features_mask(&features, tmp);
 
 	return features;
 }
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index b415e4aaae1d..999acee318d3 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3456,7 +3456,8 @@ static int macsec_dev_init(struct net_device *dev)
 	if (macsec_is_offloaded(macsec)) {
 		dev->features = REAL_DEV_FEATURES(real_dev);
 	} else {
-		dev->features = real_dev->features & SW_MACSEC_FEATURES;
+		dev->features = netdev_active_features_and(real_dev,
+							   SW_MACSEC_FEATURES);
 		netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 		netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	}
@@ -3495,10 +3496,10 @@ static netdev_features_t macsec_fix_features(struct net_device *dev,
 	if (macsec_is_offloaded(macsec))
 		return REAL_DEV_FEATURES(real_dev);
 
-	tmp = real_dev->features & SW_MACSEC_FEATURES;
+	tmp = netdev_active_features_and(real_dev, SW_MACSEC_FEATURES);
 	netdev_features_set(&tmp, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set(&tmp, NETIF_F_SOFT_FEATURES);
-	features &= tmp;
+	netdev_features_mask(&features, tmp);
 	netdev_feature_add(NETIF_F_LLTX_BIT, &features);
 
 	return features;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 78dbe6003618..83107ccc7e14 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -916,10 +916,10 @@ static int macvlan_init(struct net_device *dev)
 
 	dev->state		= (dev->state & ~MACVLAN_STATE_MASK) |
 				  (lowerdev->state & MACVLAN_STATE_MASK);
-	dev->features 		= lowerdev->features & MACVLAN_FEATURES;
+	dev->features = netdev_active_features_and(lowerdev, MACVLAN_FEATURES);
 	netdev_active_features_set(dev, ALWAYS_ON_FEATURES);
 	netdev_hw_feature_add(dev, NETIF_F_LRO_BIT);
-	dev->vlan_features	= lowerdev->vlan_features & MACVLAN_FEATURES;
+	dev->vlan_features = netdev_vlan_features_and(lowerdev, MACVLAN_FEATURES);
 	netdev_vlan_features_set(dev, ALWAYS_ON_OFFLOADS);
 	netdev_hw_enc_features_set(dev, dev->features);
 	netif_inherit_tso_max(dev, lowerdev);
@@ -1105,16 +1105,16 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
 	netdev_features_fill(&tmp);
 	netdev_features_clear(&tmp, MACVLAN_FEATURES);
 	netdev_features_set(&tmp, vlan->set_features);
-	features &= tmp;
+	netdev_features_mask(&features, tmp);
 	mask = features;
 
 	tmp = features;
 	netdev_feature_del(NETIF_F_LRO_BIT, &tmp);
-	lowerdev_features &= tmp;
+	netdev_features_mask(&lowerdev_features, tmp);
 	features = netdev_increment_features(lowerdev_features, features, mask);
 	netdev_features_set(&features, ALWAYS_ON_FEATURES);
 	tmp = netdev_features_or(ALWAYS_ON_FEATURES, MACVLAN_FEATURES);
-	features &= tmp;
+	netdev_features_mask(&features, tmp);
 
 	return features;
 }
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index a58a1d325dcc..bcf1a93826e1 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -393,8 +393,8 @@ static rx_handler_result_t net_failover_handle_frame(struct sk_buff **pskb)
 
 static void net_failover_compute_features(struct net_device *dev)
 {
-	netdev_features_t vlan_features = FAILOVER_VLAN_FEATURES &
-					  NETIF_F_ALL_FOR_ALL;
+	netdev_features_t vlan_features = netdev_features_and(FAILOVER_VLAN_FEATURES,
+							      NETIF_F_ALL_FOR_ALL);
 	netdev_features_t enc_features  = FAILOVER_ENC_FEATURES;
 	unsigned short max_hard_header_len = ETH_HLEN;
 	unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 406f0befe177..9a2103c753de 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -999,8 +999,8 @@ static netdev_features_t team_enc_features __ro_after_init;
 static void __team_compute_features(struct team *team)
 {
 	struct team_port *port;
-	netdev_features_t vlan_features = TEAM_VLAN_FEATURES &
-					  NETIF_F_ALL_FOR_ALL;
+	netdev_features_t vlan_features = netdev_features_and(TEAM_VLAN_FEATURES,
+							      NETIF_F_ALL_FOR_ALL);
 	netdev_features_t enc_features  = TEAM_ENC_FEATURES;
 	unsigned short max_hard_header_len = ETH_HLEN;
 	unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 7d4ac857555c..363a4ca29cce 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1178,7 +1178,7 @@ static netdev_features_t tun_net_fix_features(struct net_device *dev,
 	struct tun_struct *tun = netdev_priv(dev);
 	netdev_features_t tmp1, tmp2;
 
-	tmp1 = features & tun->set_features;
+	tmp1 = netdev_features_and(features, tun->set_features);
 	tmp2 = netdev_features_andnot(features, TUN_USER_FEATURES);
 	return netdev_features_or(tmp1, tmp2);
 }
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 81d5022c5c42..77038488eaf4 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3538,7 +3538,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 		netdev_active_feature_add(dev, NETIF_F_GSO_ROBUST_BIT);
 
 		if (gso) {
-			netdev_features_t tmp = dev->hw_features & NETIF_F_ALL_TSO;
+			netdev_features_t tmp = netdev_hw_features_and(dev,
+								       NETIF_F_ALL_TSO);
 
 			netdev_active_features_set(dev, tmp);
 		}
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 173bf09b4cad..9d2573f0461a 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -8,6 +8,7 @@
 #define _LINUX_IF_VLAN_H_
 
 #include <linux/netdevice.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/bug.h>
@@ -743,7 +744,8 @@ static inline netdev_features_t vlan_features_check(struct sk_buff *skb,
 		 * sure that only devices supporting NETIF_F_HW_CSUM will
 		 * have checksum offloading support.
 		 */
-		features &= netdev_multi_tags_features_mask;
+		netdev_features_mask(&features,
+				     netdev_multi_tags_features_mask);
 	}
 
 	return features;
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h
index 9adf376e1798..476d36352160 100644
--- a/include/linux/netdev_features_helper.h
+++ b/include/linux/netdev_features_helper.h
@@ -696,7 +696,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/8021q/vlan.h b/net/8021q/vlan.h
index 73c4a6595ace..f919ab183d69 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -110,7 +110,7 @@ static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)
 
 	ret = netdev_features_or(NETIF_F_CSUM_MASK, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set(&ret, NETIF_F_GSO_ENCAP_ALL);
-	ret &= real_dev->hw_enc_features;
+	netdev_features_mask(&ret, real_dev->hw_enc_features);
 
 	if (netdev_features_intersects(ret, NETIF_F_GSO_ENCAP_ALL) &&
 	    netdev_features_intersects(ret, NETIF_F_CSUM_MASK)) {
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index d13236621a40..be79c298f2ef 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -668,7 +668,7 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, &lower_features);
 	features = netdev_intersect_features(features, lower_features);
 	tmp = netdev_features_or(NETIF_F_SOFT_FEATURES, NETIF_F_GSO_SOFTWARE);
-	tmp &= old_features;
+	netdev_features_mask(&tmp, old_features);
 	netdev_features_set(&features, tmp);
 	netdev_feature_add(NETIF_F_LLTX_BIT, &features);
 
diff --git a/net/core/dev.c b/net/core/dev.c
index dc4cadf2e4df..b97b9316dbde 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3398,7 +3398,7 @@ 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);
@@ -3465,7 +3465,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;
 }
@@ -3563,7 +3563,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);
@@ -3574,7 +3574,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);
 }
@@ -10046,7 +10046,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);
@@ -11168,14 +11169,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/ioctl.c b/net/ethtool/ioctl.c
index f1ae7a4ade29..9bca8eb4f1c9 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -289,7 +289,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;
 
@@ -357,14 +357,14 @@ 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);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index ad3bea716358..4c22ea1c1f2d 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1359,7 +1359,7 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 
 	encap = SKB_GSO_CB(skb)->encap_level > 0;
 	if (encap)
-		features &= skb->dev->hw_enc_features;
+		netdev_features_mask(&features, skb->dev->hw_enc_features);
 	SKB_GSO_CB(skb)->encap_level += ihl;
 
 	skb_reset_transport_header(skb);
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 27b9e531ed62..de8d6849b49d 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -44,7 +44,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 	need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_GRE_CSUM);
 	skb->encap_hdr_csum = need_csum;
 
-	features &= skb->dev->hw_enc_features;
+	netdev_features_mask(&features, skb->dev->hw_enc_features);
 	if (need_csum)
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &features);
 
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 07c1237c69f3..9c9b58808137 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -68,7 +68,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 			   (is_ipv6 ? netdev_active_feature_test(skb->dev, NETIF_F_IPV6_CSUM_BIT) :
 				      netdev_active_feature_test(skb->dev, NETIF_F_IP_CSUM_BIT))));
 
-	features &= skb->dev->hw_enc_features;
+	netdev_features_mask(&features, skb->dev->hw_enc_features);
 	if (need_csum)
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, &features);
 
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index d12dba2dd535..1eb2098e0aea 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -115,7 +115,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 
 	encap = SKB_GSO_CB(skb)->encap_level > 0;
 	if (encap)
-		features &= skb->dev->hw_enc_features;
+		netdev_features_mask(&features, skb->dev->hw_enc_features);
 	SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h);
 
 	ipv6h = ipv6_hdr(skb);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index d3dc0628cac3..f78a5e1d2393 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -2398,7 +2398,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 			sdata->u.mgd.use_4addr = params->use_4addr;
 
 		netdev_active_features_set(ndev, local->hw.netdev_features);
-		tmp = ndev->features & MAC80211_SUPPORTED_FEATURES_TX;
+		tmp = netdev_active_features_and(ndev,
+						 MAC80211_SUPPORTED_FEATURES_TX);
 		netdev_hw_features_set(ndev, tmp);
 
 		netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c
index 1482259de9b5..9e93869ca7f6 100644
--- a/net/mpls/mpls_gso.c
+++ b/net/mpls/mpls_gso.c
@@ -12,6 +12,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/netdev_features.h>
+#include <linux/netdev_features_helper.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/mpls.h>
@@ -43,7 +44,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
 	skb_reset_mac_header(skb);
 
 	/* Segment inner packet. */
-	mpls_features = skb->dev->mpls_features & features;
+	mpls_features = netdev_mpls_features_and(skb->dev, features);
 	segs = skb_mac_gso_segment(skb, mpls_features);
 	if (IS_ERR_OR_NULL(segs)) {
 		skb_gso_error_unwind(skb, mpls_protocol, mpls_hlen, mac_offset,
diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
index d9b55bf19fd0..c1c465545d93 100644
--- a/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -107,7 +107,7 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
 	skb->protocol = proto;
 
 	netdev_feature_add(NETIF_F_SG_BIT, &tmp);
-	features &= tmp;
+	netdev_features_mask(&features, tmp);
 	segs = skb_mac_gso_segment(skb, features);
 	if (IS_ERR_OR_NULL(segs)) {
 		skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 33/36] treewide: use netdev_features_subset helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (31 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 32/36] net: use netdev_features_and and netdev_features_mask helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 34/36] treewide: use netdev_features_equal helpers Jian Shen
                   ` (2 subsequent siblings)
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '(f1 & f2) == f2' expressions of features by
netdev_features_subset helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +-
 net/core/dev.c                           | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index f6015c49363e..a4751aa92ddf 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2200,7 +2200,7 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 	}
 
 	/* Can't do one without doing the other */
-	if ((features & vxlan_base) != vxlan_base) {
+	if (!netdev_features_subset(vxlan_base, features)) {
 		netdev_notice(netdev,
 			      "forcing both tx and rx udp tunnel support\n");
 		netdev_features_set(&features, vxlan_base);
diff --git a/net/core/dev.c b/net/core/dev.c
index b97b9316dbde..01340e889e72 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9695,8 +9695,7 @@ 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(netdev_ip_csum_features, features);
 		bool hw_csum = netdev_feature_test(NETIF_F_HW_CSUM_BIT,
 						   features);
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 34/36] treewide: use netdev_features_equal helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (32 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 33/36] treewide: use netdev_features_subset helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 35/36] treewide: use netdev_features_empty helpers Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t Jian Shen
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the '==' and '!=' expressions of features by
netdev_features_equal helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c   | 2 +-
 drivers/net/ethernet/ibm/ibmvnic.c          | 2 +-
 drivers/net/ethernet/intel/ice/ice_main.c   | 2 +-
 drivers/net/ethernet/sfc/efx_common.c       | 2 +-
 drivers/net/ethernet/sfc/falcon/efx.c       | 2 +-
 drivers/net/ethernet/sfc/siena/efx_common.c | 2 +-
 drivers/s390/net/qeth_core_main.c           | 4 ++--
 net/core/dev.c                              | 2 +-
 net/ethtool/ioctl.c                         | 2 +-
 9 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 6b2ee76666bf..f329add7698e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11199,7 +11199,7 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 	 * turned on or off together.
 	 */
 	vlan_features = netdev_features_and(features, BNXT_HW_FEATURE_VLAN_ALL_RX);
-	if (vlan_features != BNXT_HW_FEATURE_VLAN_ALL_RX) {
+	if (!netdev_features_equal(vlan_features, BNXT_HW_FEATURE_VLAN_ALL_RX)) {
 		if (netdev_active_features_intersects(dev, BNXT_HW_FEATURE_VLAN_ALL_RX))
 			netdev_features_clear(&features,
 					      BNXT_HW_FEATURE_VLAN_ALL_RX);
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 95016982f03b..7f7d344addf5 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4895,7 +4895,7 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 	if (adapter->state == VNIC_PROBING) {
 		netdev_active_features_set(adapter->netdev,
 					   adapter->netdev->hw_features);
-	} else if (old_hw_features != adapter->netdev->hw_features) {
+	} else if (!netdev_hw_features_equal(adapter->netdev, old_hw_features)) {
 		netdev_features_t tmp = netdev_empty_features;
 
 		/* disable features no longer supported */
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 19a0e82d45ae..ae4ff4e3720f 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5792,7 +5792,7 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 	req_stag = netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
 				       req_vlan_fltr);
 
-	if (req_vlan_fltr != cur_vlan_fltr) {
+	if (netdev_features_equal(req_vlan_fltr, cur_vlan_fltr)) {
 		if (ice_is_dvm_ena(&np->vsi->back->hw)) {
 			if (req_ctag && req_stag) {
 				netdev_features_set(&features,
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index fdde83bef88e..737290635ff5 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 60f2152ec755..178c719e79ea 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -638,7 +638,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/drivers/net/ethernet/sfc/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 7eaa2fe9dc13..1fd27d37debf 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -416,7 +416,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/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 99f7ad47dc19..46d191c93137 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6665,7 +6665,7 @@ static int qeth_set_csum_on(struct qeth_card *card, enum qeth_ipa_funcs cstype,
 	if (rc)
 		return rc;
 
-	if ((required_features & features) != required_features) {
+	if (!netdev_features_subset(features, required_features)) {
 		qeth_set_csum_off(card, cstype, prot);
 		return -EOPNOTSUPP;
 	}
@@ -6831,7 +6831,7 @@ void qeth_enable_hw_features(struct net_device *dev)
 					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	}
 	netdev_update_features(dev);
-	if (features != dev->features)
+	if (!netdev_active_features_equal(dev, features))
 		dev_warn(&card->gdev->dev,
 			 "Device recovery failed to restore all offload features\n");
 }
diff --git a/net/core/dev.c b/net/core/dev.c
index 01340e889e72..2d6aed5a3a4f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9735,7 +9735,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",
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 9bca8eb4f1c9..78a276f34929 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -3033,7 +3033,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 (!netdev_active_features_equal(dev, old_features))
 		netdev_features_change(dev);
 out:
 	if (dev->dev.parent)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 35/36] treewide: use netdev_features_empty helpers
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (33 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 34/36] treewide: use netdev_features_equal helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t Jian Shen
  35 siblings, 0 replies; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the empty checking expressions of features by
netdev_features_subset helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c       | 2 +-
 drivers/net/ethernet/intel/iavf/iavf_main.c     | 2 +-
 drivers/net/ethernet/intel/ice/ice_main.c       | 4 ++--
 net/ethtool/ioctl.c                             | 4 ++--
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index d502ac4960fa..76ac235ca331 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4963,7 +4963,7 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
 	/* Don't care about GRO changes */
 	netdev_feature_del(NETIF_F_GRO_BIT, &changes);
 
-	if (changes)
+	if (!netdev_features_empty(changes))
 		bnx2x_reload = true;
 
 	if (bnx2x_reload) {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index f329add7698e..52c2c60cd1b7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11203,7 +11203,7 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 		if (netdev_active_features_intersects(dev, BNXT_HW_FEATURE_VLAN_ALL_RX))
 			netdev_features_clear(&features,
 					      BNXT_HW_FEATURE_VLAN_ALL_RX);
-		else if (vlan_features)
+		else if (!netdev_features_empty(vlan_features))
 			netdev_features_set(&features,
 					    BNXT_HW_FEATURE_VLAN_ALL_RX);
 	}
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 09711e527bd3..6af75df620e6 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4690,7 +4690,7 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	/* Do not turn on offloads when they are requested to be turned off.
 	 * TSO needs minimum 576 bytes to work correctly.
 	 */
-	if (netdev->wanted_features) {
+	if (!netdev_wanted_features_empty(netdev)) {
 		if (!netdev_wanted_feature_test(netdev, NETIF_F_TSO_BIT) ||
 		    netdev->mtu < 576)
 			netdev_active_feature_del(netdev, NETIF_F_TSO_BIT);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index ae4ff4e3720f..1c08aadf4c31 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5922,7 +5922,7 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 	requested_vlan_features = netdev_features_and(features,
 						      NETIF_VLAN_OFFLOAD_FEATURES);
 	diff = netdev_features_xor(current_vlan_features, requested_vlan_features);
-	if (diff) {
+	if (!netdev_features_empty(diff)) {
 		err = ice_set_vlan_offload_features(vsi, features);
 		if (err)
 			return err;
@@ -5933,7 +5933,7 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 	requested_vlan_features = netdev_features_and(features,
 						      NETIF_VLAN_FILTERING_FEATURES);
 	diff = netdev_features_xor(current_vlan_features, requested_vlan_features);
-	if (diff) {
+	if (!netdev_features_empty(diff)) {
 		err = ice_set_vlan_filtering_features(vsi, features);
 		if (err)
 			return err;
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 78a276f34929..e4718b24dd38 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -290,7 +290,7 @@ static int ethtool_set_one_feature(struct net_device *dev,
 
 	mask = ethtool_get_feature_mask(ethcmd);
 	netdev_features_mask(&mask, dev->hw_features);
-	if (!mask)
+	if (netdev_features_empty(mask))
 		return -EOPNOTSUPP;
 
 	if (edata.data)
@@ -359,7 +359,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;
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t
  2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (34 preceding siblings ...)
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 35/36] treewide: use netdev_features_empty helpers Jian Shen
@ 2022-08-10  3:06 ` Jian Shen
  2022-08-10 11:35   ` Alexander Lobakin
  35 siblings, 1 reply; 59+ messages in thread
From: Jian Shen @ 2022-08-10  3:06 UTC (permalink / raw)
  To: davem, kuba, andrew, ecree.xilinx, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

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. Serveal macroes remained
temporarily, by some precompile dependency.

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>
---
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  12 +-
 .../net/ethernet/intel/i40e/i40e_debugfs.c    |  12 +-
 .../ethernet/netronome/nfp/nfp_net_common.c   |   4 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   |   4 +-
 include/linux/netdev_features.h               | 101 ++----------
 include/linux/netdev_features_helper.h        | 149 +++++++++++-------
 include/linux/netdevice.h                     |   7 +-
 include/linux/skbuff.h                        |   4 +-
 include/net/ip_tunnels.h                      |   2 +-
 lib/vsprintf.c                                |  11 +-
 net/ethtool/features.c                        |  96 ++++-------
 net/ethtool/ioctl.c                           |  46 ++++--
 net/mac80211/main.c                           |   3 +-
 13 files changed, 201 insertions(+), 250 deletions(-)

diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index 8386aac68c93..97e74c8aafe2 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -3936,10 +3936,14 @@ static void ena_update_hints(struct ena_adapter *adapter,
 static void ena_update_host_info(struct ena_admin_host_info *host_info,
 				 struct net_device *netdev)
 {
-	host_info->supported_network_features[0] =
-		netdev->features & GENMASK_ULL(31, 0);
-	host_info->supported_network_features[1] =
-		(netdev->features & GENMASK_ULL(63, 32)) >> 32;
+#define DEV_FEATURE_WORDS	DIV_ROUND_UP(NETDEV_FEATURE_COUNT, 32)
+
+	u32 features[DEV_FEATURE_WORDS] = {0};
+
+	bitmap_to_arr32(features, netdev->features.bits, DEV_FEATURE_WORDS);
+
+	host_info->supported_network_features[0] = features[0];
+	host_info->supported_network_features[1] = features[1];
 }
 
 static void ena_timer_service(struct timer_list *t)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index c9dcd6d92c83..046882ab5593 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -131,12 +131,12 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
 
 		dev_info(&pf->pdev->dev, "    netdev: name = %s, state = %lu, flags = 0x%08x\n",
 			 nd->name, nd->state, nd->flags);
-		dev_info(&pf->pdev->dev, "        features      = 0x%08lx\n",
-			 (unsigned long int)nd->features);
-		dev_info(&pf->pdev->dev, "        hw_features   = 0x%08lx\n",
-			 (unsigned long int)nd->hw_features);
-		dev_info(&pf->pdev->dev, "        vlan_features = 0x%08lx\n",
-			 (unsigned long int)nd->vlan_features);
+		dev_info(&pf->pdev->dev, "        features      = %pNF\n",
+			 &nd->features);
+		dev_info(&pf->pdev->dev, "        hw_features   = %pNF\n",
+			 &nd->hw_features);
+		dev_info(&pf->pdev->dev, "        vlan_features = %pNF\n",
+			 &nd->vlan_features);
 	}
 	dev_info(&pf->pdev->dev,
 		 "    flags = 0x%08lx, netdev_registered = %i, current_netdev_flags = 0x%04x\n",
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index bcd8513b3b43..9bcd420b0f36 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1736,8 +1736,8 @@ static int nfp_net_set_features(struct net_device *netdev,
 	if (err)
 		return err;
 
-	nn_dbg(nn, "Feature change 0x%llx -> 0x%llx (changed=0x%llx)\n",
-	       netdev->features, features, changed);
+	nn_dbg(nn, "Feature change %pNF -> %pNF (changed=%pNF)\n",
+	       &netdev->features, &features, &changed);
 
 	if (new_ctrl == nn->dp.ctrl)
 		return 0;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 75273f473caa..653c64091121 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1564,8 +1564,8 @@ static int ionic_set_features(struct net_device *netdev,
 	struct ionic_lif *lif = netdev_priv(netdev);
 	int err;
 
-	netdev_dbg(netdev, "%s: lif->features=0x%08llx new_features=0x%08llx\n",
-		   __func__, (u64)lif->netdev->features, (u64)features);
+	netdev_dbg(netdev, "%s: lif->features=%pNF new_features=%pNF\n",
+		   __func__, &lif->netdev->features, &features);
 
 	err = ionic_set_nic_features(lif, features);
 
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index a005c781fabf..8836c957f365 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[];
@@ -113,6 +111,10 @@ enum {
 	/**/NETDEV_FEATURE_COUNT
 };
 
+typedef struct {
+	DECLARE_BITMAP(bits, NETDEV_FEATURE_COUNT);
+} netdev_features_t;
+
 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;
@@ -171,94 +173,16 @@ extern const struct netdev_feature_set netif_f_xfrm_feature_set;
 extern const struct netdev_feature_set netif_f_tls_feature_set;
 extern const struct netdev_feature_set netvsc_supported_hw_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-1 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;
-}
+#define NETIF_F_HW_VLAN_CTAG_TX
+#define NETIF_F_IPV6_CSUM
+#define NETIF_F_TSO
+#define NETIF_F_GSO
 
 /* 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)))
+	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 */
@@ -311,4 +235,11 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)
 
 #define NETIF_F_GSO_ENCAP_ALL	netdev_gso_encap_all_features
 
+#define GSO_ENCAP_FEATURES	(((u64)1 << NETIF_F_GSO_GRE_BIT) |		\
+				 ((u64)1 << NETIF_F_GSO_GRE_CSUM_BIT) |		\
+				 ((u64)1 << NETIF_F_GSO_IPXIP4_BIT) |		\
+				 ((u64)1 << NETIF_F_GSO_IPXIP6_BIT) |		\
+				 (((u64)1 << NETIF_F_GSO_UDP_TUNNEL_BIT) |	\
+				  ((u64)1 << NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT)))
+
 #endif	/* _LINUX_NETDEV_FEATURES_H */
diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h
index 476d36352160..479d120bd8bd 100644
--- a/include/linux/netdev_features_helper.h
+++ b/include/linux/netdev_features_helper.h
@@ -9,7 +9,7 @@
 
 static inline void netdev_features_zero(netdev_features_t *dst)
 {
-	*dst = 0;
+	bitmap_zero(dst->bits, NETDEV_FEATURE_COUNT);
 }
 
 /* active_feature prefer to netdev->features */
@@ -36,12 +36,12 @@ static inline void netdev_features_zero(netdev_features_t *dst)
 
 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);
 }
 
 #define netdev_active_features_empty(ndev) \
@@ -69,7 +69,7 @@ static inline bool netdev_features_empty(const netdev_features_t src)
 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);
 }
 
 #define netdev_active_features_equal(ndev, __features) \
@@ -97,7 +97,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) \
@@ -126,63 +129,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) \
@@ -210,64 +224,69 @@ 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);
 }
 
 static inline void netdev_feature_change(int nr, netdev_features_t *src)
 {
-	if (*src & __NETIF_F_BIT(nr))
-		*src &= ~(__NETIF_F_BIT(nr));
-	else
-		*src |= __NETIF_F_BIT(nr);
+	__change_bit(nr, src->bits);
 }
 
 #define netdev_active_feature_change(ndev, nr) \
@@ -295,7 +314,10 @@ static inline void netdev_feature_change(int nr, netdev_features_t *src)
 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) \
@@ -323,64 +345,74 @@ netdev_features_xor(const netdev_features_t a, const netdev_features_t b)
 static inline void
 netdev_features_toggle(netdev_features_t *dst, const netdev_features_t features)
 {
-	*dst = netdev_features_xor(*dst, features);
+	bitmap_xor(dst->bits, dst->bits, features.bits, NETDEV_FEATURE_COUNT);
 }
 
 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) \
@@ -428,63 +460,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) \
@@ -543,7 +583,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) \
@@ -602,7 +642,7 @@ netdev_features_clear_array(const struct netdev_feature_set *set,
 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) \
@@ -669,20 +709,11 @@ static inline void netdev_gso_partial_features_copy(struct net_device *ndev,
 	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;
+	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 4741f81fa968..11b31e512d68 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2338,7 +2338,7 @@ struct net_device {
 /* 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;
+	return test_bit(nr, src.bits);
 }
 
 #define netdev_active_feature_test(ndev, nr) \
@@ -4888,7 +4888,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 {
 #define GSO_INDEX(x)	((1ULL << (x)) >> NETIF_F_GSO_SHIFT)
 
-	netdev_features_t feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT;
+	netdev_features_t feature = netdev_empty_features;
 
 	/* check flags correspondence */
 	BUILD_BUG_ON(SKB_GSO_TCPV4   != GSO_INDEX(NETIF_F_TSO_BIT));
@@ -4911,7 +4911,8 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 	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 (features & feature) == feature;
+	bitmap_from_u64(feature.bits, (u64)gso_type << NETIF_F_GSO_SHIFT);
+	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/include/linux/skbuff.h b/include/linux/skbuff.h
index ca8afa382bf2..2f4e6cd05754 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3989,8 +3989,8 @@ static inline bool skb_needs_linearize(struct sk_buff *skb,
 				       netdev_features_t features)
 {
 	return skb_is_nonlinear(skb) &&
-	       ((skb_has_frag_list(skb) && !(features & NETIF_F_FRAGLIST)) ||
-		(skb_shinfo(skb)->nr_frags && !(features & NETIF_F_SG)));
+	       ((skb_has_frag_list(skb) && !test_bit(NETIF_F_FRAGLIST_BIT, features.bits)) ||
+		(skb_shinfo(skb)->nr_frags && !test_bit(NETIF_F_SG_BIT, features.bits)));
 }
 
 static inline void skb_copy_from_linear_data(const struct sk_buff *skb,
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 63fac94f9ace..4cf7e596eb53 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -447,7 +447,7 @@ static inline int iptunnel_pull_offloads(struct sk_buff *skb)
 		err = skb_unclone(skb, GFP_ATOMIC);
 		if (unlikely(err))
 			return err;
-		skb_shinfo(skb)->gso_type &= ~(NETIF_F_GSO_ENCAP_ALL >>
+		skb_shinfo(skb)->gso_type &= ~(GSO_ENCAP_FEATURES >>
 					       NETIF_F_GSO_SHIFT);
 	}
 
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 3c1853a9d1c0..d44e47681563 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1729,25 +1729,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;
+	netdev_features_t *features;
 
 	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);
+		features = (netdev_features_t *)addr;
+		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, features->bits, spec, fmt);
 }
 
 static noinline_for_stack
diff --git a/net/ethtool/features.c b/net/ethtool/features.c
index 38efdab960ba..7650a63cb234 100644
--- a/net/ethtool/features.c
+++ b/net/ethtool/features.c
@@ -27,10 +27,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, NETDEV_FEATURE_COUNT);
 }
 
 static int features_prepare_data(const struct ethnl_req_info *req_base,
@@ -45,7 +42,7 @@ static int features_prepare_data(const struct ethnl_req_info *req_base,
 	ethnl_features_to_bitmap32(data->wanted, dev->wanted_features);
 	ethnl_features_to_bitmap32(data->active, dev->features);
 	ethnl_features_to_bitmap32(data->nochange, NETIF_F_NEVER_CHANGE);
-	all_features = GENMASK_ULL(NETDEV_FEATURE_COUNT - 1, 0);
+	netdev_features_fill(&all_features);
 	ethnl_features_to_bitmap32(data->all, all_features);
 
 	return 0;
@@ -131,28 +128,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 = netdev_empty_features;
-	unsigned int i;
-
-	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);
-	return ret;
-}
-
 static int features_send_reply(struct net_device *dev, struct genl_info *info,
 			       const unsigned long *wanted,
 			       const unsigned long *wanted_mask,
@@ -209,16 +184,16 @@ 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;
@@ -235,50 +210,47 @@ 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);
-	ret = ethnl_parse_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT,
+	old_active = dev->features;
+	old_wanted = dev->wanted_features;
+	ret = ethnl_parse_bitset(req_wanted.bits, req_mask.bits,
+				 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(req_mask, NETIF_F_ETHTOOL_BITS)) {
 		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)) {
-		dev->wanted_features &= ~dev->hw_features;
-		tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features;
-		dev->wanted_features |= tmp;
+	netdev_features_mask(&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_wanted_features_clear(dev, dev->hw_features);
+		tmp = netdev_hw_features_and(dev, req_wanted);
+		netdev_wanted_features_set(dev, tmp);
 		__netdev_update_features(dev);
 	}
-	ethnl_features_to_bitmap(new_active, dev->features);
-	mod = !bitmap_equal(old_active, new_active, NETDEV_FEATURE_COUNT);
+	new_active = dev->features;
+	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);
-
-		ret = features_send_reply(dev, info, req_wanted,
-					  wanted_diff_mask, new_active,
-					  active_diff_mask, compact);
+		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.bits,
+					  wanted_diff_mask.bits, new_active.bits,
+					  active_diff_mask.bits, compact);
 	}
 	if (mod)
 		netdev_features_change(dev);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index e4718b24dd38..97df79c62420 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,16 @@ 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, dev->hw_features.bits, NETDEV_FEATURE_COUNT);
+	bitmap_to_arr32(wanted_arr, dev->wanted_features.bits, NETDEV_FEATURE_COUNT);
+	bitmap_to_arr32(active_arr, dev->features.bits, NETDEV_FEATURE_COUNT);
+	bitmap_to_arr32(never_changed_arr, netdev_never_change_features.bits,
+			NETDEV_FEATURE_COUNT);
 	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].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 +133,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_empty_features;
 	netdev_features_t valid = netdev_empty_features;
 	netdev_features_t tmp;
@@ -141,27 +151,29 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 		return -EFAULT;
 
 	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);
+		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 = valid & ~NETIF_F_ETHTOOL_BITS;
-	if (tmp)
+	tmp = netdev_features_andnot(valid, NETIF_F_ETHTOOL_BITS);
+	if (!netdev_features_empty(tmp))
 		return -EINVAL;
 
-	tmp = valid & ~dev->hw_features;
-	if (tmp) {
-		valid &= dev->hw_features;
+	tmp = netdev_hw_features_andnot_r(dev, valid);
+	if (!netdev_features_empty(tmp)) {
+		netdev_features_mask(&valid, dev->hw_features);
 		ret |= ETHTOOL_F_UNSUPPORTED;
 	}
 
-	dev->wanted_features &= ~valid;
-	tmp = wanted & valid;
-	dev->wanted_features |= tmp;
+	netdev_wanted_features_clear(dev, valid);
+	tmp = netdev_features_and(wanted, valid);
+	netdev_wanted_features_set(dev, tmp);
 	__netdev_update_features(dev);
 
-	tmp = dev->wanted_features ^ dev->features;
-	if (tmp & valid)
+	tmp = netdev_wanted_features_xor(dev, dev->features);
+	if (netdev_features_intersects(tmp, valid))
 		ret |= ETHTOOL_F_WISH;
 
 	return ret;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 7a3d98473a0a..614f2e7b3eb7 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1046,7 +1046,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	}
 
 	/* Only HW csum features are currently compatible with mac80211 */
-	if (WARN_ON(hw->netdev_features & ~MAC80211_SUPPORTED_FEATURES))
+	if (WARN_ON(!netdev_features_empty(netdev_features_andnot(hw->netdev_features,
+								  MAC80211_SUPPORTED_FEATURES))))
 		return -EINVAL;
 
 	if (hw->max_report_rates == 0)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features Jian Shen
@ 2022-08-10  9:43   ` Alexander Lobakin
  2022-08-10 11:32     ` shenjian (K)
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-10  9:43 UTC (permalink / raw)
  To: Jian Shen
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: Jian Shen <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 11:05:49 +0800

> Introduce a set of bitmap operation helpers for netdev features,
> then we can use them to replace the logical operation with them.
> 
> The implementation of these helpers are based on the old prototype
> of netdev_features_t is still u64. These helpers will be rewritten
> 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 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>
> ---
>  include/linux/netdev_features.h        |  11 +
>  include/linux/netdev_features_helper.h | 707 +++++++++++++++++++++++++

'netdev_feature_helpers.h' fits more I guess, doesn't it? It
contains several helpers, not only one.
And BTW, do you think it's worth to create a new file rather than
put everything just in netdev_features.h?

>  include/linux/netdevice.h              |  45 +-
>  net/8021q/vlan_dev.c                   |   1 +
>  net/core/dev.c                         |   1 +
>  5 files changed, 747 insertions(+), 18 deletions(-)
>  create mode 100644 include/linux/netdev_features_helper.h
> 
> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
> index 7c2d77d75a88..9d434b4e6e6e 100644
> --- a/include/linux/netdev_features.h
> +++ b/include/linux/netdev_features.h
> @@ -11,6 +11,17 @@
>  
>  typedef u64 netdev_features_t;
>  
> +struct netdev_feature_set {
> +	unsigned int cnt;
> +	unsigned short feature_bits[];
> +};
> +
> +#define DECLARE_NETDEV_FEATURE_SET(name, features...)			\
> +	const struct netdev_feature_set name = {			\
> +		.cnt = sizeof((unsigned short[]){ features }) / sizeof(unsigned short),	\
> +		.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..5423927d139b
> --- /dev/null
> +++ b/include/linux/netdev_features_helper.h
> @@ -0,0 +1,707 @@
> +/* 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;
> +}
> +
> +/* active_feature prefer to netdev->features */
> +#define netdev_active_features_zero(ndev) \
> +		netdev_features_zero(&ndev->features)

netdev_features_t sometimes is being placed and used on the stack.
I think it's better to pass just `netdev_features_t *` to those
helpers, this way you wouldn't also need to create a new helper
for each net_device::*_features.

> +
> +#define netdev_hw_features_zero(ndev) \
> +		netdev_features_zero(&ndev->hw_features)
> +
> +#define netdev_wanted_features_zero(ndev) \

[...]

> +#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);

A small proposal: if you look at bitmap_and() for example, it
returns 1 if the resulting bitmap is non-empty and 0 if it is. What
about doing the same here? It would probably help to do reduce
boilerplating in the drivers where we only want to know if there's
anything left after masking.
Same for xor, toggle etc.

> +}
> +
> +static inline void
> +netdev_active_features_mask(struct net_device *ndev,
> +			    const netdev_features_t features)
> +{
> +	ndev->features = netdev_active_features_and(ndev, 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++)

Nit: kernel is C11 now, you can do just `for (u32 i = 0; i ...`.
(and yeah, it's better to use unsigned types when you don't plan
to store negative values there).

> +		netdev_feature_add(set->feature_bits[i], dst);
> +}

[...]

> -- 
> 2.33.0

Thanks,
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 02/36] net: replace general features macroes with global netdev_features variables
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 02/36] net: replace general features macroes with global netdev_features variables Jian Shen
@ 2022-08-10  9:58   ` Alexander Lobakin
  2022-08-10 12:01     ` shenjian (K)
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-10  9:58 UTC (permalink / raw)
  To: Jian Shen
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: Jian Shen <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 11:05:50 +0800

> 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/hyperv/hyperv_net.h |   5 +-
>  include/linux/netdev_features.h | 111 +++++++++----
>  net/core/Makefile               |   2 +-
>  net/core/dev.c                  |  83 ++++++++++
>  net/core/netdev_features.c      | 281 ++++++++++++++++++++++++++++++++
>  5 files changed, 441 insertions(+), 41 deletions(-)
>  create mode 100644 net/core/netdev_features.c
> 
> diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
> index 25b38a374e3c..6336ed81fb8c 100644
> --- a/drivers/net/hyperv/hyperv_net.h
> +++ b/drivers/net/hyperv/hyperv_net.h
> @@ -873,10 +873,7 @@ struct nvsp_message {
>  #define NETVSC_RECEIVE_BUFFER_ID		0xcafe
>  #define NETVSC_SEND_BUFFER_ID			0
>  
> -#define NETVSC_SUPPORTED_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | \
> -				      NETIF_F_TSO | NETIF_F_IPV6_CSUM | \
> -				      NETIF_F_TSO6 | NETIF_F_LRO | \
> -				      NETIF_F_SG | NETIF_F_RXHASH)
> +#define NETVSC_SUPPORTED_HW_FEATURES	netvsc_supported_hw_features
>  
>  #define VRSS_SEND_TAB_SIZE 16  /* must be power of 2 */
>  #define VRSS_CHANNEL_MAX 64
> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
> index 9d434b4e6e6e..a005c781fabf 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;
> @@ -112,6 +113,64 @@ 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_offload_features __ro_after_init;
> +extern netdev_features_t netdev_stag_vlan_offload_features __ro_after_init;
> +extern netdev_features_t netdev_vlan_offload_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_multi_tags_features_mask __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 netdev_features_t netdev_empty_features __ro_after_init;
> +extern netdev_features_t netvsc_supported_hw_features __ro_after_init;

netvsc stuff belongs to hyperv_net driver, I'd place it there. Those
features aren't used outside of it I believe.

> +extern const struct netdev_feature_set netif_f_never_change_feature_set;
> +extern const struct netdev_feature_set netif_f_gso_feature_set_mask;
> +extern const struct netdev_feature_set netif_f_ip_csum_feature_set;
> +extern const struct netdev_feature_set netif_f_csum_feature_set_mask;
> +extern const struct netdev_feature_set netif_f_general_tso_feature_set;
> +extern const struct netdev_feature_set netif_f_all_tso_feature_set;
> +extern const struct netdev_feature_set netif_f_tso_ecn_feature_set;
> +extern const struct netdev_feature_set netif_f_all_fcoe_feature_set;
> +extern const struct netdev_feature_set netif_f_gso_soft_feature_set;
> +extern const struct netdev_feature_set netif_f_one_for_all_feature_set;
> +extern const struct netdev_feature_set netif_f_all_for_all_feature_set;
> +extern const struct netdev_feature_set netif_f_upper_disables_feature_set;
> +extern const struct netdev_feature_set netif_f_soft_feature_set;
> +extern const struct netdev_feature_set netif_f_soft_off_feature_set;
> +extern const struct netdev_feature_set netif_f_tx_vlan_feature_set;
> +extern const struct netdev_feature_set netif_f_rx_vlan_feature_set;
> +extern const struct netdev_feature_set netif_f_vlan_filter_feature_set;
> +extern const struct netdev_feature_set netif_f_ctag_vlan_feature_set;
> +extern const struct netdev_feature_set netif_f_stag_vlan_feature_set;
> +extern const struct netdev_feature_set netif_f_ctag_vlan_offload_feature_set;
> +extern const struct netdev_feature_set netif_f_stag_vlan_offload_feature_set;
> +extern const struct netdev_feature_set netif_f_multi_tags_feature_set_mask;
> +extern const struct netdev_feature_set netif_f_gso_encap_feature_set;
> +extern const struct netdev_feature_set netif_f_xfrm_feature_set;
> +extern const struct netdev_feature_set netif_f_tls_feature_set;
> +extern const struct netdev_feature_set netvsc_supported_hw_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)
> @@ -203,73 +262,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 e8ce3bd283a6..360a101584c8 100644
> --- a/net/core/Makefile
> +++ b/net/core/Makefile
> @@ -12,7 +12,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 45e80c84497f..9603bac63ffb 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>
> @@ -11362,6 +11363,86 @@ static struct pernet_operations __net_initdata default_device_ops = {
>  	.exit_batch = default_device_exit_batch,
>  };
>  
> +static void __init netdev_features_init(void)

Given that you're creating a new file dedicated to netdev features,
I'd place that initializer there. You can then declare its proto in
net/core/dev.h.

> +{
> +	netdev_features_t features;
> +
> +	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_gso_feature_set_mask,
> +				  &netdev_gso_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_gso_encap_feature_set,
> +				  &netdev_gso_encap_all_features);
> +
> +	netdev_csum_gso_features_mask =
> +		netdev_features_or(netdev_gso_features_mask,
> +				   netdev_csum_features_mask);

(I forgot to mention this in 01/36 ._.)

As you're converting to bitmaps, you should probably avoid direct
assignments. All the bitmap_*() modification functions take a pointer
to the destination as a first argument. So it should be

netdev_features_or(netdev_features_t *dst, const netdev_features_t *src1,
		   const netdev_features_t *src1);

> +
> +	netdev_features_set_array(&netif_f_one_for_all_feature_set,
> +				  &netdev_one_for_all_features);

Does it make sense to prefix features and the corresponding sets
differently? Why not just 'netdev_' for both of them?

> +	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_features_or(netdev_rx_vlan_features,
> +						      netdev_tx_vlan_features);
> +	netdev_features_set_array(&netif_f_ctag_vlan_offload_feature_set,
> +				  &netdev_ctag_vlan_offload_features);
> +	netdev_features_set_array(&netif_f_stag_vlan_offload_feature_set,
> +				  &netdev_stag_vlan_offload_features);
> +	netdev_vlan_offload_features =
> +			netdev_features_or(netdev_ctag_vlan_offload_features,
> +					   netdev_stag_vlan_offload_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_multi_tags_feature_set_mask,
> +				  &netdev_multi_tags_features_mask);
> +
> +	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_features_set_array(&netif_f_never_change_feature_set,
> +				  &netdev_never_change_features);
> +	netdev_features_fill(&features);
> +	netdev_ethtool_features =
> +		netdev_features_andnot(features, netdev_never_change_features);
> +
> +	netdev_features_zero(&netdev_empty_features);
> +
> +	netdev_features_set_array(&netvsc_supported_hw_feature_set,
> +				  &netvsc_supported_hw_features);
> +}
> +
>  /*
>   *	Initialize the DEV module. At boot time this walks the device list and
>   *	unhooks any devices that fail to initialise (normally hardware not
> @@ -11392,6 +11473,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..158c750ea7a2
> --- /dev/null
> +++ b/net/core/netdev_features.c
> @@ -0,0 +1,281 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Network device features.
> + */
> +
> +#include <linux/netdev_features.h>
> +
> +netdev_features_t netdev_ethtool_features __ro_after_init;
> +EXPORT_SYMBOL_GPL(netdev_ethtool_features);

I think GPL is too strict for such a core functionality.
I mean, I personally don't use non-GPL and don't work on such stuff,
but there must be plenty of non-GPL networking drivers, and with
this change they will simply stop working. Not that I don't like
it :D But there definitely will be argues and "angry" articles.

> +
> +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_offload_features __ro_after_init;
> +EXPORT_SYMBOL_GPL(netdev_ctag_vlan_offload_features);
> +
> +netdev_features_t netdev_stag_vlan_offload_features __ro_after_init;
> +EXPORT_SYMBOL_GPL(netdev_stag_vlan_offload_features);
> +
> +netdev_features_t netdev_vlan_offload_features __ro_after_init;
> +EXPORT_SYMBOL_GPL(netdev_vlan_offload_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_multi_tags_features_mask __ro_after_init;
> +EXPORT_SYMBOL_GPL(netdev_multi_tags_features_mask);
> +
> +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);
> +
> +netdev_features_t netdev_empty_features __ro_after_init;
> +EXPORT_SYMBOL_GPL(netdev_empty_features);
> +
> +netdev_features_t netvsc_supported_hw_features __ro_after_init;
> +EXPORT_SYMBOL_GPL(netvsc_supported_hw_features);
> +
> +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_BIT);
> +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_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_offload_feature_set,
> +			   NETIF_F_HW_VLAN_CTAG_TX_BIT,
> +			   NETIF_F_HW_VLAN_CTAG_RX_BIT);
> +EXPORT_SYMBOL_GPL(netif_f_ctag_vlan_offload_feature_set);
> +
> +DECLARE_NETDEV_FEATURE_SET(netif_f_stag_vlan_offload_feature_set,
> +			   NETIF_F_HW_VLAN_STAG_TX_BIT,
> +			   NETIF_F_HW_VLAN_STAG_RX_BIT);
> +EXPORT_SYMBOL_GPL(netif_f_stag_vlan_offload_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,
> +			   NETIF_F_HW_VLAN_CTAG_FILTER_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,
> +			   NETIF_F_HW_VLAN_STAG_FILTER_BIT);
> +EXPORT_SYMBOL_GPL(netif_f_stag_vlan_feature_set);
> +
> +DECLARE_NETDEV_FEATURE_SET(netif_f_multi_tags_feature_set_mask,
> +			   NETIF_F_SG_BIT,
> +			   NETIF_F_HIGHDMA_BIT,
> +			   NETIF_F_HW_CSUM_BIT,
> +			   NETIF_F_FRAGLIST_BIT,
> +			   NETIF_F_HW_VLAN_CTAG_TX_BIT,
> +			   NETIF_F_HW_VLAN_STAG_TX_BIT);
> +EXPORT_SYMBOL_GPL(netif_f_multi_tags_feature_set_mask);
> +
> +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);
> +
> +DECLARE_NETDEV_FEATURE_SET(netvsc_supported_hw_feature_set,
> +			   NETIF_F_RXCSUM_BIT,
> +			   NETIF_F_IP_CSUM_BIT,
> +			   NETIF_F_TSO_BIT,
> +			   NETIF_F_IPV6_CSUM_BIT,
> +			   NETIF_F_TSO6_BIT,
> +			   NETIF_F_LRO_BIT,
> +			   NETIF_F_SG_BIT,
> +			   NETIF_F_RXHASH_BIT);
> +EXPORT_SYMBOL_GPL(netvsc_supported_hw_feature_set);
> -- 
> 2.33.0

Thanks,
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 03/36] net: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET
  2022-08-10  3:05 ` [RFCv7 PATCH net-next 03/36] net: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET Jian Shen
@ 2022-08-10 10:37   ` Alexander Lobakin
  2022-08-10 12:15     ` shenjian (K)
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-10 10:37 UTC (permalink / raw)
  To: Jian Shen
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: Jian Shen <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 11:05:51 +0800

> There are many netdev_features bits group used in drivers, replace them
> with DECLARE_NETDEV_FEATURE_SET, prepare to remove all the NETIF_F_XXX
> macroes.
> 
> Signed-off-by: Jian Shen <shenjian15@huawei.com>
> ---
>  arch/um/drivers/vector_transports.c           |  49 +++++--
>  drivers/infiniband/ulp/ipoib/ipoib.h          |   1 +
>  drivers/infiniband/ulp/ipoib/ipoib_main.c     |   8 +-
>  drivers/net/amt.c                             |  16 ++-
>  drivers/net/bareudp.c                         |  21 ++-
>  drivers/net/bonding/bond_main.c               |  48 +++++--
>  drivers/net/dsa/xrs700x/xrs700x.c             |  15 +-
>  drivers/net/dummy.c                           |  11 +-
>  drivers/net/ethernet/3com/typhoon.c           |  18 ++-
>  drivers/net/ethernet/aeroflex/greth.c         |   9 +-
>  drivers/net/ethernet/alteon/acenic.c          |  10 +-
>  drivers/net/ethernet/amazon/ena/ena_netdev.c  |  13 +-
>  drivers/net/ethernet/amd/xgbe/xgbe-main.c     |  59 ++++----
>  .../net/ethernet/apm/xgene/xgene_enet_main.c  |  12 +-
>  .../net/ethernet/aquantia/atlantic/aq_nic.c   |  14 +-
>  drivers/net/ethernet/asix/ax88796c_main.c     |  21 ++-
>  drivers/net/ethernet/atheros/alx/main.c       |  15 +-
>  drivers/net/ethernet/atheros/atl1c/atl1c.h    |   1 +
>  .../net/ethernet/atheros/atl1c/atl1c_main.c   |  14 +-
>  drivers/net/ethernet/atheros/atl1e/atl1e.h    |   1 +
>  .../net/ethernet/atheros/atl1e/atl1e_main.c   |  10 +-
>  drivers/net/ethernet/atheros/atlx/atl1.c      |  22 ++-
>  drivers/net/ethernet/broadcom/bcmsysport.c    |  24 +++-
>  drivers/net/ethernet/broadcom/bgmac.c         |   9 +-
>  drivers/net/ethernet/broadcom/bnx2.c          |  14 +-
>  .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  83 ++++++++---
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  54 +++++--
>  .../net/ethernet/broadcom/genet/bcmgenet.c    |  10 +-
>  drivers/net/ethernet/brocade/bna/bnad.c       |  39 +++--
>  drivers/net/ethernet/calxeda/xgmac.c          |  15 +-
>  .../net/ethernet/cavium/liquidio/lio_main.c   |  42 ++++--
>  .../ethernet/cavium/liquidio/lio_vf_main.c    |  40 ++++--
>  .../ethernet/cavium/liquidio/octeon_network.h |   4 +-
>  .../net/ethernet/cavium/thunder/nicvf_main.c  |  27 +++-
>  drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  19 ++-
>  .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  29 +++-
>  .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  68 ++++++---
>  .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  39 ++++-
>  drivers/net/ethernet/cirrus/ep93xx_eth.c      |   7 +-
>  drivers/net/ethernet/cisco/enic/enic_main.c   |  19 ++-
>  drivers/net/ethernet/cortina/gemini.c         |  22 ++-
>  drivers/net/ethernet/emulex/benet/be_main.c   |  47 ++++--
>  drivers/net/ethernet/faraday/ftgmac100.c      |  13 +-
>  .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  14 +-
>  .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |  17 ++-
>  .../ethernet/freescale/dpaa2/dpaa2-switch.c   |  10 +-
>  .../ethernet/freescale/dpaa2/dpaa2-switch.h   |   1 +
>  .../net/ethernet/freescale/enetc/enetc_pf.c   |  42 ++++--
>  .../net/ethernet/freescale/enetc/enetc_vf.c   |  40 ++++--
>  drivers/net/ethernet/freescale/fec_main.c     |  11 +-
>  drivers/net/ethernet/freescale/gianfar.c      |  18 ++-
>  .../ethernet/fungible/funeth/funeth_main.c    |  48 +++++--
>  drivers/net/ethernet/google/gve/gve_main.c    |  21 +--
>  drivers/net/ethernet/hisilicon/hns/hns_enet.c |  51 +++++--
>  .../net/ethernet/hisilicon/hns3/hns3_enet.c   |  40 ++++--
>  .../net/ethernet/huawei/hinic/hinic_main.c    |  37 +++--
>  drivers/net/ethernet/ibm/ehea/ehea_main.c     |  34 +++--
>  drivers/net/ethernet/ibm/emac/core.c          |   7 +-
>  drivers/net/ethernet/ibm/ibmveth.c            |  11 +-
>  drivers/net/ethernet/ibm/ibmvnic.c            |   8 +-
>  drivers/net/ethernet/intel/e1000/e1000.h      |   1 +
>  drivers/net/ethernet/intel/e1000/e1000_main.c |  33 +++--
>  drivers/net/ethernet/intel/e1000e/netdev.c    |  46 ++++--
>  .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  37 +++--
>  drivers/net/ethernet/intel/i40e/i40e_main.c   |  75 +++++-----
>  drivers/net/ethernet/intel/iavf/iavf.h        |   1 +
>  drivers/net/ethernet/intel/iavf/iavf_main.c   |  43 +++---
>  drivers/net/ethernet/intel/ice/ice.h          |   1 +
>  drivers/net/ethernet/intel/ice/ice_main.c     |  64 ++++++---
>  drivers/net/ethernet/intel/igb/igb_main.c     |  74 ++++++----
>  drivers/net/ethernet/intel/igbvf/netdev.c     |  76 ++++++----
>  drivers/net/ethernet/intel/igc/igc_mac.c      |   1 +
>  drivers/net/ethernet/intel/igc/igc_main.c     |  77 ++++++----
>  drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  15 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 134 +++++++++++-------
>  drivers/net/ethernet/intel/ixgbevf/ipsec.c    |  15 +-
>  drivers/net/ethernet/intel/ixgbevf/ixgbevf.h  |   1 +
>  .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |  87 +++++++-----
>  drivers/net/ethernet/jme.c                    |  34 +++--
>  drivers/net/ethernet/marvell/mv643xx_eth.c    |   9 +-
>  drivers/net/ethernet/marvell/mvneta.c         |  12 +-
>  .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  19 ++-
>  .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  17 ++-
>  .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  17 ++-
>  drivers/net/ethernet/marvell/skge.c           |   9 +-
>  drivers/net/ethernet/marvell/sky2.c           |  19 ++-
>  drivers/net/ethernet/mellanox/mlx4/en_main.c  |   1 +
>  .../net/ethernet/mellanox/mlx4/en_netdev.c    |  75 ++++++----
>  .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c |  20 +--
>  .../net/ethernet/mellanox/mlxsw/spectrum.c    |  16 ++-
>  drivers/net/ethernet/micrel/ksz884x.c         |   9 +-
>  drivers/net/ethernet/microchip/lan743x_main.c |   9 +-
>  drivers/net/ethernet/microsoft/mana/mana_en.c |  15 +-
>  drivers/net/ethernet/mscc/ocelot_net.c        |  14 +-
>  .../net/ethernet/myricom/myri10ge/myri10ge.c  |  11 +-
>  drivers/net/ethernet/neterion/s2io.c          |  24 +++-
>  drivers/net/ethernet/nvidia/forcedeth.c       |  10 +-
>  .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  10 +-
>  drivers/net/ethernet/pasemi/pasemi_mac.c      |  11 +-
>  .../net/ethernet/pensando/ionic/ionic_lif.c   |  23 +--
>  .../ethernet/qlogic/netxen/netxen_nic_main.c  |  11 +-
>  drivers/net/ethernet/qlogic/qede/qede_main.c  |  50 +++++--
>  .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  29 ++--
>  .../net/ethernet/qlogic/qlcnic/qlcnic_main.c  |  34 +++--
>  drivers/net/ethernet/qualcomm/emac/emac.c     |  23 ++-
>  .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c   |  12 +-
>  drivers/net/ethernet/realtek/8139cp.c         |  23 ++-
>  drivers/net/ethernet/realtek/8139too.c        |   8 +-
>  drivers/net/ethernet/realtek/r8169_main.c     |  18 ++-
>  .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |  15 +-
>  drivers/net/ethernet/sfc/ef10.c               |  11 +-
>  drivers/net/ethernet/sfc/ef100_netdev.c       |   9 +-
>  drivers/net/ethernet/sfc/ef100_nic.c          |  15 +-
>  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 +
>  drivers/net/ethernet/sfc/siena/efx.c          |  22 ++-
>  drivers/net/ethernet/sgi/ioc3-eth.c           |  13 +-
>  drivers/net/ethernet/silan/sc92031.c          |  11 +-
>  drivers/net/ethernet/socionext/netsec.c       |  11 +-
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |  11 +-
>  drivers/net/ethernet/sun/ldmvsw.c             |   7 +-
>  drivers/net/ethernet/sun/niu.c                |   9 +-
>  drivers/net/ethernet/sun/sungem.c             |   9 +-
>  drivers/net/ethernet/sun/sunvnet.c            |  10 +-
>  drivers/net/ethernet/tehuti/tehuti.c          |  25 +++-
>  drivers/net/ethernet/tehuti/tehuti.h          |   1 +
>  drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  13 +-
>  drivers/net/ethernet/ti/cpsw_new.c            |  11 +-
>  drivers/net/ethernet/via/via-velocity.c       |  19 ++-
>  drivers/net/geneve.c                          |  20 ++-
>  drivers/net/hyperv/netvsc_drv.c               |  11 +-
>  drivers/net/ifb.c                             |  20 ++-
>  drivers/net/ipvlan/ipvlan_main.c              |  58 ++++++--
>  drivers/net/ipvlan/ipvtap.c                   |  12 +-
>  drivers/net/loopback.c                        |  25 ++--
>  drivers/net/macsec.c                          |  22 ++-
>  drivers/net/macvlan.c                         |  56 ++++++--
>  drivers/net/macvtap.c                         |  12 +-
>  drivers/net/net_failover.c                    |  23 +++
>  drivers/net/netdevsim/ipsec.c                 |  13 +-
>  drivers/net/netdevsim/netdev.c                |  14 +-
>  drivers/net/netdevsim/netdevsim.h             |   1 +
>  drivers/net/nlmon.c                           |  11 +-
>  drivers/net/tap.c                             |  18 ++-
>  drivers/net/team/team.c                       |  31 +++-
>  drivers/net/thunderbolt.c                     |  11 +-
>  drivers/net/tun.c                             |  28 +++-
>  drivers/net/usb/aqc111.c                      |  38 ++++-
>  drivers/net/usb/aqc111.h                      |  14 --
>  drivers/net/usb/ax88179_178a.c                |  11 +-
>  drivers/net/usb/lan78xx.c                     |   8 +-
>  drivers/net/usb/r8152.c                       |  53 +++++--
>  drivers/net/usb/smsc75xx.c                    |  10 +-
>  drivers/net/veth.c                            |  27 ++--
>  drivers/net/vmxnet3/vmxnet3_drv.c             |  36 +++--
>  drivers/net/vmxnet3/vmxnet3_ethtool.c         |  35 +++--
>  drivers/net/vmxnet3/vmxnet3_int.h             |   1 +
>  drivers/net/vrf.c                             |  12 +-
>  drivers/net/vsockmon.c                        |  11 +-
>  drivers/net/vxlan/vxlan_core.c                |  20 ++-
>  drivers/net/wireguard/device.c                |  20 ++-
>  drivers/net/wireless/ath/wil6210/netdev.c     |  14 +-
>  drivers/net/xen-netback/interface.c           |  14 +-
>  drivers/net/xen-netfront.c                    |  20 ++-
>  drivers/s390/net/qeth_l3_main.c               |  13 +-
>  drivers/staging/qlge/qlge_main.c              |  21 +--
>  include/net/bonding.h                         |   5 +-
>  include/net/net_failover.h                    |   8 +-
>  net/8021q/vlan_dev.c                          |  15 +-
>  net/batman-adv/soft-interface.c               |   9 +-
>  net/bridge/br_device.c                        |  25 +++-
>  net/ethtool/ioctl.c                           |  17 ++-
>  net/hsr/hsr_device.c                          |  13 +-
>  net/ipv4/ip_gre.c                             |  19 +--
>  net/ipv4/ipip.c                               |  19 ++-
>  net/ipv6/ip6_gre.c                            |  15 +-
>  net/ipv6/ip6_tunnel.c                         |  19 ++-
>  net/ipv6/sit.c                                |  18 ++-
>  net/mac80211/ieee80211_i.h                    |  13 +-
>  net/mac80211/main.c                           |  24 ++++
>  net/openvswitch/vport-internal_dev.c          |  13 +-
>  net/xfrm/xfrm_interface.c                     |  16 ++-
>  184 files changed, 2923 insertions(+), 1139 deletions(-)

[...]

> +static DECLARE_NETDEV_FEATURE_SET(bond_mpls_feature_set,
> +				  NETIF_F_HW_CSUM_BIT,
> +				  NETIF_F_SG_BIT);
> +
> +static netdev_features_t bond_vlan_features __ro_after_init;
> +static netdev_features_t bond_enc_features __ro_after_init;
> +static netdev_features_t bond_mpls_features __ro_after_init;
>  /*-------------------------- Forward declarations ---------------------------*/

Nit: any reason to not leave an empty space in between the
declarations and that comment line?

>  
>  static int bond_init(struct net_device *bond_dev);
> @@ -1421,16 +1441,11 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
>  	return features;
>  }

[...]

>  /**
>   * struct gmac_queue_page - page buffer per-page info
> @@ -2610,6 +2618,12 @@ static struct platform_driver gemini_ethernet_driver = {
>  	.remove = gemini_ethernet_remove,
>  };
>  
> +static void __init gmac_netdev_features_init(void)
> +{
> +	netdev_features_set_array(&gmac_offload_feature_set,
> +				  &gmac_offload_features);
> +}

I'd say it's not worth it to create a new function for a one-liner.

> +
>  static int __init gemini_ethernet_module_init(void)
>  {
>  	int ret;
> @@ -2624,6 +2638,8 @@ static int __init gemini_ethernet_module_init(void)
>  		return ret;
>  	}
>  
> +	gmac_netdev_features_init();
> +
>  	return 0;
>  }
>  module_init(gemini_ethernet_module_init);

[...]

> @@ -120,16 +144,12 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
>  	ndev->watchdog_timeo = 5 * HZ;
>  	ndev->max_mtu = ENETC_MAX_MTU;
>  
> -	ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
> -			    NETIF_F_HW_VLAN_CTAG_TX |
> -			    NETIF_F_HW_VLAN_CTAG_RX |
> -			    NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
> -	ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
> -			 NETIF_F_HW_VLAN_CTAG_TX |
> -			 NETIF_F_HW_VLAN_CTAG_RX |
> -			 NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
> -	ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
> -			      NETIF_F_TSO | NETIF_F_TSO6;
> +	netdev_hw_features_zero(ndev);
> +	netdev_hw_features_set_array(ndev, &enetc_vf_hw_feature_set);

Hmm, I see that pattern

netdev*_features_zero();
netdev*_features_set_array();

pretty often, maybe create a couple static inlines like
'netdev*_features_from_array'? And use it for initializing
shared/exported netdev_features as well? Otherwise, sooner or later,
but someone will forget to zero the features before setting them and
will get a garbage and some hard-to-track bugs %)

> +	netdev_active_features_zero(ndev);
> +	netdev_active_features_set_array(ndev, &enetc_vf_feature_set);
> +	netdev_vlan_features_zero(ndev);
> +	netdev_vlan_features_set_array(ndev, &enetc_vf_vlan_feature_set);
>  
>  	if (si->num_rss)
>  		ndev->hw_features |= NETIF_F_RXHASH;
> diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
> index e8e2aa1e7f01..49850ee91d4e 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c

[...]

> +static DECLARE_NETDEV_FEATURE_SET(fun_vlan_feature_set,
> +				  NETIF_F_SG_BIT,
> +				  NETIF_F_HW_CSUM_BIT,
> +				  NETIF_F_HIGHDMA_BIT);
> +
>  static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
>  {
> +	netdev_features_t gso_encap_flags = netdev_empty_features;
> +	netdev_features_t tso_flags = netdev_empty_features;

Same here as I mentioned previously, direct assignments wouldn't
work here later for bitmaps. So it's rather bitmap_copy(), i.e.
netdev_features_copy(), or am I missing something?

>  	struct fun_dev *fdev = &ed->fdev;
> +	netdev_features_t vlan_feat;
>  	struct net_device *netdev;
>  	struct funeth_priv *fp;
>  	unsigned int ntx, nrx;

[...]

> @@ -1265,6 +1266,13 @@ static void ax88179_get_mac_addr(struct usbnet *dev)
>  			  dev->net->dev_addr);
>  }
>  
> +DECLARE_NETDEV_FEATURE_SET(ax88179_feature_set,

static?
You can use sparse to detect such places (`make C=1`).

> +			   NETIF_F_SG_BIT,
> +			   NETIF_F_IP_CSUM_BIT,
> +			   NETIF_F_IPV6_CSUM_BIT,
> +			   NETIF_F_RXCSUM_BIT,
> +			   NETIF_F_TSO_BIT);

[...]

> -- 
> 2.33.0

Thanks,
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 16/36] treewide: use replace features '0' by netdev_empty_features
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 16/36] treewide: use replace features '0' by netdev_empty_features Jian Shen
@ 2022-08-10 10:48   ` Alexander Lobakin
  2022-08-10 12:25     ` shenjian (K)
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-10 10:48 UTC (permalink / raw)
  To: Jian Shen
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: Jian Shen <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 11:06:04 +0800

> For the prototype of netdev_features_t will be changed from
> u64 to bitmap, so it's unable to assignment with 0 directly.
> Replace it with netdev_empty_features.

Hmm, why not just netdev_features_zero() instead?
There's a couple places where empty netdev_features are needed, but
they're not probably worth a separate and rather pointless empty
variable, you could create one on the stack there.

> 
> Signed-off-by: Jian Shen <shenjian15@huawei.com>
> ---
>  drivers/hsi/clients/ssi_protocol.c             | 2 +-
>  drivers/net/caif/caif_serial.c                 | 2 +-
>  drivers/net/ethernet/amazon/ena/ena_netdev.c   | 2 +-
>  drivers/net/ethernet/broadcom/b44.c            | 2 +-
>  drivers/net/ethernet/broadcom/tg3.c            | 2 +-
>  drivers/net/ethernet/dnet.c                    | 2 +-
>  drivers/net/ethernet/ec_bhf.c                  | 2 +-
>  drivers/net/ethernet/emulex/benet/be_main.c    | 2 +-
>  drivers/net/ethernet/ethoc.c                   | 2 +-
>  drivers/net/ethernet/huawei/hinic/hinic_main.c | 5 +++--
>  drivers/net/ethernet/ibm/ibmvnic.c             | 6 +++---
>  drivers/net/ethernet/intel/iavf/iavf_main.c    | 9 +++++----
>  drivers/net/ethernet/microsoft/mana/mana_en.c  | 2 +-
>  drivers/net/ethernet/sfc/ef10.c                | 2 +-
>  drivers/net/tap.c                              | 2 +-
>  drivers/net/tun.c                              | 2 +-
>  drivers/net/usb/cdc-phonet.c                   | 3 ++-
>  drivers/net/usb/lan78xx.c                      | 2 +-
>  drivers/s390/net/qeth_core_main.c              | 2 +-
>  drivers/usb/gadget/function/f_phonet.c         | 3 ++-
>  net/dccp/ipv4.c                                | 2 +-
>  net/dccp/ipv6.c                                | 2 +-
>  net/ethtool/features.c                         | 2 +-
>  net/ethtool/ioctl.c                            | 6 ++++--
>  net/ipv4/af_inet.c                             | 2 +-
>  net/ipv4/tcp.c                                 | 2 +-
>  net/ipv4/tcp_ipv4.c                            | 2 +-
>  net/ipv6/af_inet6.c                            | 2 +-
>  net/ipv6/inet6_connection_sock.c               | 2 +-
>  net/ipv6/tcp_ipv6.c                            | 2 +-
>  net/openvswitch/datapath.c                     | 2 +-
>  31 files changed, 44 insertions(+), 38 deletions(-)

[...]

> -- 
> 2.33.0

Thanks,
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [RFCv7 PATCH net-next 17/36] treewide: adjust features initialization
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 17/36] treewide: adjust features initialization Jian Shen
@ 2022-08-10 10:58   ` Alexander Lobakin
  2022-08-10 14:06     ` shenjian (K)
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-10 10:58 UTC (permalink / raw)
  To: Jian Shen
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: Jian Shen <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 11:06:05 +0800

> There are many direclty single bit assignment to netdev features.
> Adjust these expressions, so can use netdev features helpers later.
> 
> Signed-off-by: Jian Shen <shenjian15@huawei.com>
> ---
>  arch/um/drivers/vector_kern.c                       | 5 ++++-
>  drivers/firewire/net.c                              | 4 +++-
>  drivers/infiniband/hw/hfi1/vnic_main.c              | 4 +++-
>  drivers/misc/sgi-xp/xpnet.c                         | 3 ++-
>  drivers/net/can/dev/dev.c                           | 4 +++-
>  drivers/net/ethernet/alacritech/slicoss.c           | 4 +++-
>  drivers/net/ethernet/amd/xgbe/xgbe-drv.c            | 4 +++-
>  drivers/net/ethernet/aquantia/atlantic/aq_nic.c     | 3 ++-
>  drivers/net/ethernet/atheros/atlx/atl2.c            | 4 +++-
>  drivers/net/ethernet/cadence/macb_main.c            | 4 +++-
>  drivers/net/ethernet/davicom/dm9000.c               | 4 +++-
>  drivers/net/ethernet/engleder/tsnep_main.c          | 4 +++-
>  drivers/net/ethernet/ibm/ibmveth.c                  | 3 ++-
>  drivers/net/ethernet/marvell/octeon_ep/octep_main.c | 4 +++-
>  drivers/net/ethernet/mellanox/mlx4/en_netdev.c      | 3 ++-
>  drivers/net/ethernet/mellanox/mlx5/core/en_main.c   | 4 +++-
>  drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 7 +++++--
>  drivers/net/ethernet/netronome/nfp/nfp_net_repr.c   | 3 ++-
>  drivers/net/ethernet/ni/nixge.c                     | 4 +++-
>  drivers/net/ethernet/renesas/sh_eth.c               | 6 ++++--
>  drivers/net/ethernet/sun/sunhme.c                   | 7 +++++--
>  drivers/net/ethernet/toshiba/ps3_gelic_net.c        | 6 ++++--
>  drivers/net/ethernet/toshiba/spider_net.c           | 3 ++-
>  drivers/net/ethernet/tundra/tsi108_eth.c            | 3 ++-
>  drivers/net/ethernet/xilinx/ll_temac_main.c         | 4 +++-
>  drivers/net/ethernet/xilinx/xilinx_axienet_main.c   | 4 +++-
>  drivers/net/hamradio/bpqether.c                     | 4 +++-
>  drivers/net/hyperv/netvsc_drv.c                     | 3 ++-
>  drivers/net/ipa/ipa_modem.c                         | 4 +++-
>  drivers/net/ntb_netdev.c                            | 4 +++-
>  drivers/net/rionet.c                                | 4 +++-
>  drivers/net/tap.c                                   | 2 +-
>  drivers/net/thunderbolt.c                           | 3 ++-
>  drivers/net/usb/smsc95xx.c                          | 4 +++-
>  drivers/net/virtio_net.c                            | 4 +++-
>  drivers/net/wireless/ath/ath10k/mac.c               | 7 +++++--
>  drivers/net/wireless/ath/ath11k/mac.c               | 4 +++-
>  drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c   | 4 +++-
>  drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c   | 4 +++-
>  drivers/net/wireless/mediatek/mt76/mt7615/init.c    | 4 +++-
>  drivers/net/wireless/mediatek/mt76/mt7915/init.c    | 4 +++-
>  drivers/net/wireless/mediatek/mt76/mt7921/init.c    | 4 +++-
>  drivers/net/wwan/t7xx/t7xx_netdev.c                 | 4 +++-
>  drivers/s390/net/qeth_core_main.c                   | 7 +++++--
>  include/net/udp.h                                   | 4 +++-
>  net/phonet/pep-gprs.c                               | 4 +++-
>  46 files changed, 138 insertions(+), 52 deletions(-)
> 
> diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
> index 1d59522a50d8..d797758850e1 100644
> --- a/arch/um/drivers/vector_kern.c
> +++ b/arch/um/drivers/vector_kern.c
> @@ -1628,7 +1628,10 @@ static void vector_eth_configure(
>  		.bpf			= NULL
>  	});
>  
> -	dev->features = dev->hw_features = (NETIF_F_SG | NETIF_F_FRAGLIST);
> +	netdev_active_features_zero(dev);
> +	dev->features |= NETIF_F_SG;
> +	dev->features |= NETIF_F_FRAGLIST;
> +	dev->features = dev->hw_features;

I think a new helper can be useful there and in a couple other
places, which would set or clear an array of bits taking them as
varargs:

#define __netdev_features_set_set(feat, uniq, ...) ({	\
	DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
	netdev_features_set_array(feat, &(uniq));	\
})
#define netdev_features_set_set(feat, ...)		\
	__smth(feat, __UNIQUE_ID(feat_set), __VA_ARGS__)

(name is a placeholder)

so that you can do

	netdev_active_features_zero(dev);
	netdev_features_set_set(dev->features, NETIF_F_SG, NETIF_F_FRAGLIST);

in one take. I think it looks elegant, doesn't it?

>  	INIT_WORK(&vp->reset_tx, vector_reset_tx);
>  
>  	timer_setup(&vp->tl, vector_timer_expire, 0);

[...]

> -- 
> 2.33.0

Thanks,
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 23/36] net: adjust the build check for net_gso_ok()
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 23/36] net: adjust the build check for net_gso_ok() Jian Shen
@ 2022-08-10 11:09   ` Alexander Lobakin
  2022-08-10 14:41     ` shenjian (K)
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-10 11:09 UTC (permalink / raw)
  To: Jian Shen
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: Jian Shen <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 11:06:11 +0800

> Introduce macro GSO_INDEX(x) to replace the NETIF_F_XXX
> feature shift check, for all the macroes NETIF_F_XXX will
> be remove later.
> 
> Signed-off-by: Jian Shen <shenjian15@huawei.com>
> ---
>  include/linux/netdevice.h | 40 ++++++++++++++++++++-------------------
>  1 file changed, 21 insertions(+), 19 deletions(-)
> 
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 1bd5dcbc884d..b01af2a3838d 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -4886,28 +4886,30 @@ netdev_features_t netif_skb_features(struct sk_buff *skb);
>  
>  static inline bool net_gso_ok(netdev_features_t features, int gso_type)
>  {
> +#define GSO_INDEX(x)	((1ULL << (x)) >> NETIF_F_GSO_SHIFT)

What if we get a new GSO offload which's corresponding bit will be
higher than 64?
You could instead do

#define __SKB_GSO_FLAG(x)	(1ULL << (x))

enum {
	SKB_GSO_TCPV4_BIT	= 0,
	SKB_GSO_DODGY_BIT	= 1,
	...,
};
enum {
	SKB_GSO_TCPV4		= __SKB_GSO_FLAG(TCPV4),
	SKB_GSO_DODGY		= __SKB_GSO_FLAG(DODGY),
	...,
};

and then just

#define ASSERT_GSO_TYPE(fl, feat)	\
	static_assert((fl) == (feat) - NETIF_F_GSO_SHIFT)

	...
	ASSERT_GSO_TYPE(SKB_GSO_TCPV4_BIT, NETIF_F_TSO_BIT);
	ASSERT_GSO_TYPE(SKB_GSO_DODGY, NETIF_F_GSO_ROBUST_BIT);
	...

> +
>  	netdev_features_t feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT;
>  
>  	/* 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));
> +	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 (features & feature) == feature;
>  }
> -- 
> 2.33.0

Thanks,
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features
  2022-08-10  9:43   ` Alexander Lobakin
@ 2022-08-10 11:32     ` shenjian (K)
  2022-08-11 10:49       ` Alexander Lobakin
  0 siblings, 1 reply; 59+ messages in thread
From: shenjian (K) @ 2022-08-10 11:32 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, andrew, ecree.xilinx, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/8/10 17:43, Alexander Lobakin 写道:
> From: Jian Shen <shenjian15@huawei.com>
> Date: Wed, 10 Aug 2022 11:05:49 +0800
>
>> Introduce a set of bitmap operation helpers for netdev features,
>> then we can use them to replace the logical operation with them.
>>
>> The implementation of these helpers are based on the old prototype
>> of netdev_features_t is still u64. These helpers will be rewritten
>> 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 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>
>> ---
>>   include/linux/netdev_features.h        |  11 +
>>   include/linux/netdev_features_helper.h | 707 +++++++++++++++++++++++++
> 'netdev_feature_helpers.h' fits more I guess, doesn't it? It
> contains several helpers, not only one.
ok, will rename it.

> And BTW, do you think it's worth to create a new file rather than
> put everything just in netdev_features.h?
Jakub suggested me to move them to a new file, then it can be includued
at users appropriately. 
[https://www.spinics.net/lists/netdev/msg809370.html]

And it's unable to put everything in netdev_features.h, because these 
helpers
need to see the definition of struct net_device which is defined in 
netdevice.h.
It leading interdependence for netdeice.h include netdev_features.h.


>>   include/linux/netdevice.h              |  45 +-
>>   net/8021q/vlan_dev.c                   |   1 +
>>   net/core/dev.c                         |   1 +
>>   5 files changed, 747 insertions(+), 18 deletions(-)
>>   create mode 100644 include/linux/netdev_features_helper.h
>>
>> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
>> index 7c2d77d75a88..9d434b4e6e6e 100644
>> --- a/include/linux/netdev_features.h
>> +++ b/include/linux/netdev_features.h
>> @@ -11,6 +11,17 @@
>>   
>>   typedef u64 netdev_features_t;
>>   
>> +struct netdev_feature_set {
>> +	unsigned int cnt;
>> +	unsigned short feature_bits[];
>> +};
>> +
>> +#define DECLARE_NETDEV_FEATURE_SET(name, features...)			\
>> +	const struct netdev_feature_set name = {			\
>> +		.cnt = sizeof((unsigned short[]){ features }) / sizeof(unsigned short),	\
>> +		.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..5423927d139b
>> --- /dev/null
>> +++ b/include/linux/netdev_features_helper.h
>> @@ -0,0 +1,707 @@
>> +/* 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;
>> +}
>> +
>> +/* active_feature prefer to netdev->features */
>> +#define netdev_active_features_zero(ndev) \
>> +		netdev_features_zero(&ndev->features)
> netdev_features_t sometimes is being placed and used on the stack.
> I think it's better to pass just `netdev_features_t *` to those
> helpers, this way you wouldn't also need to create a new helper
> for each net_device::*_features.
My purpose of defining  helpers for each net_device::*_features is to
avoiding driver to change  net_device::*_features directly.

>> +
>> +#define netdev_hw_features_zero(ndev) \
>> +		netdev_features_zero(&ndev->hw_features)
>> +
>> +#define netdev_wanted_features_zero(ndev) \
> [...]
>
>> +#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);
> A small proposal: if you look at bitmap_and() for example, it
> returns 1 if the resulting bitmap is non-empty and 0 if it is. What
> about doing the same here? It would probably help to do reduce
> boilerplating in the drivers where we only want to know if there's
> anything left after masking.
> Same for xor, toggle etc.
Thanks for point this.  Return whether empty, then I can remove 
netdev_features_intersects
helpers. But there are also many places to use 'f1 & f2' as return value 
or input param, then
I need to define more temporay features to store the result, and then 
return the temporay
features or pass into it.

>> +}
>> +
>> +static inline void
>> +netdev_active_features_mask(struct net_device *ndev,
>> +			    const netdev_features_t features)
>> +{
>> +	ndev->features = netdev_active_features_and(ndev, 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++)
> Nit: kernel is C11 now, you can do just `for (u32 i = 0; i ...`.
> (and yeah, it's better to use unsigned types when you don't plan
> to store negative values there).
ok, will fix it.

>> +		netdev_feature_add(set->feature_bits[i], dst);
>> +}
> [...]
>
>> -- 
>> 2.33.0
> Thanks,
> Olek
>
> .
>


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t
  2022-08-10  3:06 ` [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t Jian Shen
@ 2022-08-10 11:35   ` Alexander Lobakin
       [not found]     ` <3df89822-7dec-c01e-0df9-15b8e6f7d4e5@huawei.com>
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-10 11:35 UTC (permalink / raw)
  To: Jian Shen
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: Jian Shen <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 11:06:24 +0800

> 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. Serveal macroes remained
> temporarily, by some precompile dependency.
> 
> 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>
> ---
>  drivers/net/ethernet/amazon/ena/ena_netdev.c  |  12 +-
>  .../net/ethernet/intel/i40e/i40e_debugfs.c    |  12 +-
>  .../ethernet/netronome/nfp/nfp_net_common.c   |   4 +-
>  .../net/ethernet/pensando/ionic/ionic_lif.c   |   4 +-
>  include/linux/netdev_features.h               | 101 ++----------
>  include/linux/netdev_features_helper.h        | 149 +++++++++++-------
>  include/linux/netdevice.h                     |   7 +-
>  include/linux/skbuff.h                        |   4 +-
>  include/net/ip_tunnels.h                      |   2 +-
>  lib/vsprintf.c                                |  11 +-
>  net/ethtool/features.c                        |  96 ++++-------
>  net/ethtool/ioctl.c                           |  46 ++++--
>  net/mac80211/main.c                           |   3 +-
>  13 files changed, 201 insertions(+), 250 deletions(-)

[...]

> -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;
> -}
> +#define NETIF_F_HW_VLAN_CTAG_TX
> +#define NETIF_F_IPV6_CSUM
> +#define NETIF_F_TSO
> +#define NETIF_F_GSO

Uhm, what are those empty definitions for? They look confusing.

>  
>  /* 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)))
> +	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 */
> @@ -311,4 +235,11 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)
>  
>  #define NETIF_F_GSO_ENCAP_ALL	netdev_gso_encap_all_features
>  
> +#define GSO_ENCAP_FEATURES	(((u64)1 << NETIF_F_GSO_GRE_BIT) |		\
> +				 ((u64)1 << NETIF_F_GSO_GRE_CSUM_BIT) |		\
> +				 ((u64)1 << NETIF_F_GSO_IPXIP4_BIT) |		\
> +				 ((u64)1 << NETIF_F_GSO_IPXIP6_BIT) |		\
> +				 (((u64)1 << NETIF_F_GSO_UDP_TUNNEL_BIT) |	\
> +				  ((u64)1 << NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT)))

1) 1ULL;
2) what if we get a new GSO encap type which's bit will be higher
   than 64?

> +
>  #endif	/* _LINUX_NETDEV_FEATURES_H */
> diff --git a/include/linux/netdev_features_helper.h b/include/linux/netdev_features_helper.h
> index 476d36352160..479d120bd8bd 100644
> --- a/include/linux/netdev_features_helper.h
> +++ b/include/linux/netdev_features_helper.h
> @@ -9,7 +9,7 @@
>  
>  static inline void netdev_features_zero(netdev_features_t *dst)
>  {
> -	*dst = 0;
> +	bitmap_zero(dst->bits, NETDEV_FEATURE_COUNT);
>  }
>  
>  /* active_feature prefer to netdev->features */
> @@ -36,12 +36,12 @@ static inline void netdev_features_zero(netdev_features_t *dst)
>  
>  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);
>  }
>  
>  #define netdev_active_features_empty(ndev) \
> @@ -69,7 +69,7 @@ static inline bool netdev_features_empty(const netdev_features_t src)
>  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);
>  }
>  
>  #define netdev_active_features_equal(ndev, __features) \
> @@ -97,7 +97,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;

Yeah, so as I wrote previously, not a good idea to return a whole
bitmap/structure.

netdev_features_and(*dst, const *a, const *b)
{
	return bitmap_and(); // bitmap_and() actually returns useful value
}

I mean, 16 bytes (currently 8, but some new features will come
pretty shortly, I'm sure) are probably okayish, but... let's see
what other folks think, but even Linus wrote about this recently
BTW.

>  }
>  
>  #define netdev_active_features_and(ndev, __features) \
> @@ -126,63 +129,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;

Same here.

>  }
>  
>  #define netdev_active_features_or(ndev, __features) \
> @@ -210,64 +224,69 @@ 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);
>  }
>  
>  static inline void netdev_feature_change(int nr, netdev_features_t *src)
>  {
> -	if (*src & __NETIF_F_BIT(nr))
> -		*src &= ~(__NETIF_F_BIT(nr));
> -	else
> -		*src |= __NETIF_F_BIT(nr);
> +	__change_bit(nr, src->bits);
>  }
>  
>  #define netdev_active_feature_change(ndev, nr) \
> @@ -295,7 +314,10 @@ static inline void netdev_feature_change(int nr, netdev_features_t *src)
>  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;
>  }

Here as well.

>  
>  #define netdev_active_features_xor(ndev, __features) \
> @@ -323,64 +345,74 @@ netdev_features_xor(const netdev_features_t a, const netdev_features_t b)
>  static inline void
>  netdev_features_toggle(netdev_features_t *dst, const netdev_features_t features)
>  {
> -	*dst = netdev_features_xor(*dst, features);
> +	bitmap_xor(dst->bits, dst->bits, features.bits, NETDEV_FEATURE_COUNT);
>  }
>  
>  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;
>  }

And in all other such places.

>  
>  #define netdev_active_features_andnot(ndev, __features) \
> @@ -428,63 +460,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) \
> @@ -543,7 +583,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) \
> @@ -602,7 +642,7 @@ netdev_features_clear_array(const struct netdev_feature_set *set,
>  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) \
> @@ -669,20 +709,11 @@ static inline void netdev_gso_partial_features_copy(struct net_device *ndev,
>  	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;
> +	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 4741f81fa968..11b31e512d68 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -2338,7 +2338,7 @@ struct net_device {
>  /* 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;
> +	return test_bit(nr, src.bits);
>  }
>  
>  #define netdev_active_feature_test(ndev, nr) \
> @@ -4888,7 +4888,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
>  {
>  #define GSO_INDEX(x)	((1ULL << (x)) >> NETIF_F_GSO_SHIFT)
>  
> -	netdev_features_t feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT;
> +	netdev_features_t feature = netdev_empty_features;
>  
>  	/* check flags correspondence */
>  	BUILD_BUG_ON(SKB_GSO_TCPV4   != GSO_INDEX(NETIF_F_TSO_BIT));
> @@ -4911,7 +4911,8 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
>  	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 (features & feature) == feature;
> +	bitmap_from_u64(feature.bits, (u64)gso_type << NETIF_F_GSO_SHIFT);
> +	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/include/linux/skbuff.h b/include/linux/skbuff.h
> index ca8afa382bf2..2f4e6cd05754 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -3989,8 +3989,8 @@ static inline bool skb_needs_linearize(struct sk_buff *skb,
>  				       netdev_features_t features)
>  {
>  	return skb_is_nonlinear(skb) &&
> -	       ((skb_has_frag_list(skb) && !(features & NETIF_F_FRAGLIST)) ||
> -		(skb_shinfo(skb)->nr_frags && !(features & NETIF_F_SG)));
> +	       ((skb_has_frag_list(skb) && !test_bit(NETIF_F_FRAGLIST_BIT, features.bits)) ||
> +		(skb_shinfo(skb)->nr_frags && !test_bit(NETIF_F_SG_BIT, features.bits)));
>  }
>  
>  static inline void skb_copy_from_linear_data(const struct sk_buff *skb,
> diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
> index 63fac94f9ace..4cf7e596eb53 100644
> --- a/include/net/ip_tunnels.h
> +++ b/include/net/ip_tunnels.h
> @@ -447,7 +447,7 @@ static inline int iptunnel_pull_offloads(struct sk_buff *skb)
>  		err = skb_unclone(skb, GFP_ATOMIC);
>  		if (unlikely(err))
>  			return err;
> -		skb_shinfo(skb)->gso_type &= ~(NETIF_F_GSO_ENCAP_ALL >>
> +		skb_shinfo(skb)->gso_type &= ~(GSO_ENCAP_FEATURES >>
>  					       NETIF_F_GSO_SHIFT);
>  	}
>  
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 3c1853a9d1c0..d44e47681563 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1729,25 +1729,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;
> +	netdev_features_t *features;

const? We're printing.

>  
>  	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);
> +		features = (netdev_features_t *)addr;

Casts are not needed when assigning from `void *`.

> +		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, features->bits, spec, fmt);
>  }
>  
>  static noinline_for_stack
> diff --git a/net/ethtool/features.c b/net/ethtool/features.c
> index 38efdab960ba..7650a63cb234 100644
> --- a/net/ethtool/features.c
> +++ b/net/ethtool/features.c
> @@ -27,10 +27,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, NETDEV_FEATURE_COUNT);
>  }
>  
>  static int features_prepare_data(const struct ethnl_req_info *req_base,
> @@ -45,7 +42,7 @@ static int features_prepare_data(const struct ethnl_req_info *req_base,
>  	ethnl_features_to_bitmap32(data->wanted, dev->wanted_features);
>  	ethnl_features_to_bitmap32(data->active, dev->features);
>  	ethnl_features_to_bitmap32(data->nochange, NETIF_F_NEVER_CHANGE);
> -	all_features = GENMASK_ULL(NETDEV_FEATURE_COUNT - 1, 0);
> +	netdev_features_fill(&all_features);
>  	ethnl_features_to_bitmap32(data->all, all_features);
>  
>  	return 0;
> @@ -131,28 +128,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 = netdev_empty_features;
> -	unsigned int i;
> -
> -	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);
> -	return ret;
> -}
> -
>  static int features_send_reply(struct net_device *dev, struct genl_info *info,
>  			       const unsigned long *wanted,
>  			       const unsigned long *wanted_mask,
> @@ -209,16 +184,16 @@ 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;

8 bitmaps, that can provoke frame warning to appear sooner or later.
Maybe worth to kzalloc() a chunk of heap for them here.

>  	struct net_device *dev;
>  	netdev_features_t tmp;
>  	bool mod;
> @@ -235,50 +210,47 @@ 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);
> -	ret = ethnl_parse_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT,
> +	old_active = dev->features;
> +	old_wanted = dev->wanted_features;
> +	ret = ethnl_parse_bitset(req_wanted.bits, req_mask.bits,
> +				 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(req_mask, NETIF_F_ETHTOOL_BITS)) {
>  		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)) {
> -		dev->wanted_features &= ~dev->hw_features;
> -		tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features;
> -		dev->wanted_features |= tmp;
> +	netdev_features_mask(&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_wanted_features_clear(dev, dev->hw_features);
> +		tmp = netdev_hw_features_and(dev, req_wanted);
> +		netdev_wanted_features_set(dev, tmp);
>  		__netdev_update_features(dev);
>  	}
> -	ethnl_features_to_bitmap(new_active, dev->features);
> -	mod = !bitmap_equal(old_active, new_active, NETDEV_FEATURE_COUNT);
> +	new_active = dev->features;
> +	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);
> -
> -		ret = features_send_reply(dev, info, req_wanted,
> -					  wanted_diff_mask, new_active,
> -					  active_diff_mask, compact);
> +		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.bits,
> +					  wanted_diff_mask.bits, new_active.bits,
> +					  active_diff_mask.bits, compact);
>  	}
>  	if (mod)
>  		netdev_features_change(dev);
> diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
> index e4718b24dd38..97df79c62420 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,16 @@ 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, dev->hw_features.bits, NETDEV_FEATURE_COUNT);
> +	bitmap_to_arr32(wanted_arr, dev->wanted_features.bits, NETDEV_FEATURE_COUNT);
> +	bitmap_to_arr32(active_arr, dev->features.bits, NETDEV_FEATURE_COUNT);
> +	bitmap_to_arr32(never_changed_arr, netdev_never_change_features.bits,
> +			NETDEV_FEATURE_COUNT);
>  	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].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 +133,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_empty_features;
>  	netdev_features_t valid = netdev_empty_features;
>  	netdev_features_t tmp;
> @@ -141,27 +151,29 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
>  		return -EFAULT;
>  
>  	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);
> +		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 = valid & ~NETIF_F_ETHTOOL_BITS;
> -	if (tmp)
> +	tmp = netdev_features_andnot(valid, NETIF_F_ETHTOOL_BITS);
> +	if (!netdev_features_empty(tmp))
>  		return -EINVAL;
>  
> -	tmp = valid & ~dev->hw_features;
> -	if (tmp) {
> -		valid &= dev->hw_features;
> +	tmp = netdev_hw_features_andnot_r(dev, valid);
> +	if (!netdev_features_empty(tmp)) {
> +		netdev_features_mask(&valid, dev->hw_features);
>  		ret |= ETHTOOL_F_UNSUPPORTED;
>  	}
>  
> -	dev->wanted_features &= ~valid;
> -	tmp = wanted & valid;
> -	dev->wanted_features |= tmp;
> +	netdev_wanted_features_clear(dev, valid);
> +	tmp = netdev_features_and(wanted, valid);
> +	netdev_wanted_features_set(dev, tmp);
>  	__netdev_update_features(dev);
>  
> -	tmp = dev->wanted_features ^ dev->features;
> -	if (tmp & valid)
> +	tmp = netdev_wanted_features_xor(dev, dev->features);
> +	if (netdev_features_intersects(tmp, valid))
>  		ret |= ETHTOOL_F_WISH;
>  
>  	return ret;
> diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> index 7a3d98473a0a..614f2e7b3eb7 100644
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -1046,7 +1046,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
>  	}
>  
>  	/* Only HW csum features are currently compatible with mac80211 */
> -	if (WARN_ON(hw->netdev_features & ~MAC80211_SUPPORTED_FEATURES))
> +	if (WARN_ON(!netdev_features_empty(netdev_features_andnot(hw->netdev_features,
> +								  MAC80211_SUPPORTED_FEATURES))))
>  		return -EINVAL;
>  
>  	if (hw->max_report_rates == 0)
> -- 
> 2.33.0

That's my last review email for now. Insane amount of work, I'm glad
someone did it finally. Thanks a lot!

Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 02/36] net: replace general features macroes with global netdev_features variables
  2022-08-10  9:58   ` Alexander Lobakin
@ 2022-08-10 12:01     ` shenjian (K)
  2022-08-11 11:05       ` Alexander Lobakin
  0 siblings, 1 reply; 59+ messages in thread
From: shenjian (K) @ 2022-08-10 12:01 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, andrew, ecree.xilinx, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/8/10 17:58, Alexander Lobakin 写道:
> From: Jian Shen <shenjian15@huawei.com>
> Date: Wed, 10 Aug 2022 11:05:50 +0800
>
>> 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/hyperv/hyperv_net.h |   5 +-
>>   include/linux/netdev_features.h | 111 +++++++++----
>>   net/core/Makefile               |   2 +-
>>   net/core/dev.c                  |  83 ++++++++++
>>   net/core/netdev_features.c      | 281 ++++++++++++++++++++++++++++++++
>>   5 files changed, 441 insertions(+), 41 deletions(-)
>>   create mode 100644 net/core/netdev_features.c
>>
>> diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
>> index 25b38a374e3c..6336ed81fb8c 100644
>> --- a/drivers/net/hyperv/hyperv_net.h
>> +++ b/drivers/net/hyperv/hyperv_net.h
>> @@ -873,10 +873,7 @@ struct nvsp_message {
>>   #define NETVSC_RECEIVE_BUFFER_ID		0xcafe
>>   #define NETVSC_SEND_BUFFER_ID			0
>>   
>> -#define NETVSC_SUPPORTED_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | \
>> -				      NETIF_F_TSO | NETIF_F_IPV6_CSUM | \
>> -				      NETIF_F_TSO6 | NETIF_F_LRO | \
>> -				      NETIF_F_SG | NETIF_F_RXHASH)
>> +#define NETVSC_SUPPORTED_HW_FEATURES	netvsc_supported_hw_features
>>   
>>   #define VRSS_SEND_TAB_SIZE 16  /* must be power of 2 */
>>   #define VRSS_CHANNEL_MAX 64
>> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
>> index 9d434b4e6e6e..a005c781fabf 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;
>> @@ -112,6 +113,64 @@ 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_offload_features __ro_after_init;
>> +extern netdev_features_t netdev_stag_vlan_offload_features __ro_after_init;
>> +extern netdev_features_t netdev_vlan_offload_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_multi_tags_features_mask __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 netdev_features_t netdev_empty_features __ro_after_init;
>> +extern netdev_features_t netvsc_supported_hw_features __ro_after_init;
> netvsc stuff belongs to hyperv_net driver, I'd place it there. Those
> features aren't used outside of it I believe.
Yes, it shoule be defined in hyperv_net driver.
Will fix it, thanks!

>> +extern const struct netdev_feature_set netif_f_never_change_feature_set;
>> +extern const struct netdev_feature_set netif_f_gso_feature_set_mask;
>> +extern const struct netdev_feature_set netif_f_ip_csum_feature_set;
>> +extern const struct netdev_feature_set netif_f_csum_feature_set_mask;
>> +extern const struct netdev_feature_set netif_f_general_tso_feature_set;
>> +extern const struct netdev_feature_set netif_f_all_tso_feature_set;
>> +extern const struct netdev_feature_set netif_f_tso_ecn_feature_set;
>> +extern const struct netdev_feature_set netif_f_all_fcoe_feature_set;
>> +extern const struct netdev_feature_set netif_f_gso_soft_feature_set;
>> +extern const struct netdev_feature_set netif_f_one_for_all_feature_set;
>> +extern const struct netdev_feature_set netif_f_all_for_all_feature_set;
>> +extern const struct netdev_feature_set netif_f_upper_disables_feature_set;
>> +extern const struct netdev_feature_set netif_f_soft_feature_set;
>> +extern const struct netdev_feature_set netif_f_soft_off_feature_set;
>> +extern const struct netdev_feature_set netif_f_tx_vlan_feature_set;
>> +extern const struct netdev_feature_set netif_f_rx_vlan_feature_set;
>> +extern const struct netdev_feature_set netif_f_vlan_filter_feature_set;
>> +extern const struct netdev_feature_set netif_f_ctag_vlan_feature_set;
>> +extern const struct netdev_feature_set netif_f_stag_vlan_feature_set;
>> +extern const struct netdev_feature_set netif_f_ctag_vlan_offload_feature_set;
>> +extern const struct netdev_feature_set netif_f_stag_vlan_offload_feature_set;
>> +extern const struct netdev_feature_set netif_f_multi_tags_feature_set_mask;
>> +extern const struct netdev_feature_set netif_f_gso_encap_feature_set;
>> +extern const struct netdev_feature_set netif_f_xfrm_feature_set;
>> +extern const struct netdev_feature_set netif_f_tls_feature_set;
>> +extern const struct netdev_feature_set netvsc_supported_hw_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)
>> @@ -203,73 +262,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 e8ce3bd283a6..360a101584c8 100644
>> --- a/net/core/Makefile
>> +++ b/net/core/Makefile
>> @@ -12,7 +12,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 45e80c84497f..9603bac63ffb 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>
>> @@ -11362,6 +11363,86 @@ static struct pernet_operations __net_initdata default_device_ops = {
>>   	.exit_batch = default_device_exit_batch,
>>   };
>>   
>> +static void __init netdev_features_init(void)
> Given that you're creating a new file dedicated to netdev features,
> I'd place that initializer there. You can then declare its proto in
> net/core/dev.h.
I want to make sure it cann't be called outside net/core/dev.c, for some
drivers include net/core/dev.h, then they can see it.

>> +{
>> +	netdev_features_t features;
>> +
>> +	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_gso_feature_set_mask,
>> +				  &netdev_gso_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_gso_encap_feature_set,
>> +				  &netdev_gso_encap_all_features);
>> +
>> +	netdev_csum_gso_features_mask =
>> +		netdev_features_or(netdev_gso_features_mask,
>> +				   netdev_csum_features_mask);
> (I forgot to mention this in 01/36 ._.)
>
> As you're converting to bitmaps, you should probably avoid direct
> assignments. All the bitmap_*() modification functions take a pointer
> to the destination as a first argument. So it should be
>
> netdev_features_or(netdev_features_t *dst, const netdev_features_t *src1,
> 		   const netdev_features_t *src1);
The netdev_features_t will be convert to a structure which only contained
a feature bitmap. So assginement is ok.


>> +
>> +	netdev_features_set_array(&netif_f_one_for_all_feature_set,
>> +				  &netdev_one_for_all_features);
> Does it make sense to prefix features and the corresponding sets
> differently? Why not just 'netdev_' for both of them?
For all the feature bits are named "NETFI_F_XXX_BIT",


>> +	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_features_or(netdev_rx_vlan_features,
>> +						      netdev_tx_vlan_features);
>> +	netdev_features_set_array(&netif_f_ctag_vlan_offload_feature_set,
>> +				  &netdev_ctag_vlan_offload_features);
>> +	netdev_features_set_array(&netif_f_stag_vlan_offload_feature_set,
>> +				  &netdev_stag_vlan_offload_features);
>> +	netdev_vlan_offload_features =
>> +			netdev_features_or(netdev_ctag_vlan_offload_features,
>> +					   netdev_stag_vlan_offload_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_multi_tags_feature_set_mask,
>> +				  &netdev_multi_tags_features_mask);
>> +
>> +	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_features_set_array(&netif_f_never_change_feature_set,
>> +				  &netdev_never_change_features);
>> +	netdev_features_fill(&features);
>> +	netdev_ethtool_features =
>> +		netdev_features_andnot(features, netdev_never_change_features);
>> +
>> +	netdev_features_zero(&netdev_empty_features);
>> +
>> +	netdev_features_set_array(&netvsc_supported_hw_feature_set,
>> +				  &netvsc_supported_hw_features);
>> +}
>> +
>>   /*
>>    *	Initialize the DEV module. At boot time this walks the device list and
>>    *	unhooks any devices that fail to initialise (normally hardware not
>> @@ -11392,6 +11473,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..158c750ea7a2
>> --- /dev/null
>> +++ b/net/core/netdev_features.c
>> @@ -0,0 +1,281 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Network device features.
>> + */
>> +
>> +#include <linux/netdev_features.h>
>> +
>> +netdev_features_t netdev_ethtool_features __ro_after_init;
>> +EXPORT_SYMBOL_GPL(netdev_ethtool_features);
> I think GPL is too strict for such a core functionality.
> I mean, I personally don't use non-GPL and don't work on such stuff,
> but there must be plenty of non-GPL networking drivers, and with
> this change they will simply stop working. Not that I don't like
> it :D But there definitely will be argues and "angry" articles.
you are right, will use EXPORT_SYMBOL instead.

>> +
>> +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_offload_features __ro_after_init;
>> +EXPORT_SYMBOL_GPL(netdev_ctag_vlan_offload_features);
>> +
>> +netdev_features_t netdev_stag_vlan_offload_features __ro_after_init;
>> +EXPORT_SYMBOL_GPL(netdev_stag_vlan_offload_features);
>> +
>> +netdev_features_t netdev_vlan_offload_features __ro_after_init;
>> +EXPORT_SYMBOL_GPL(netdev_vlan_offload_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_multi_tags_features_mask __ro_after_init;
>> +EXPORT_SYMBOL_GPL(netdev_multi_tags_features_mask);
>> +
>> +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);
>> +
>> +netdev_features_t netdev_empty_features __ro_after_init;
>> +EXPORT_SYMBOL_GPL(netdev_empty_features);
>> +
>> +netdev_features_t netvsc_supported_hw_features __ro_after_init;
>> +EXPORT_SYMBOL_GPL(netvsc_supported_hw_features);
>> +
>> +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_BIT);
>> +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_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_offload_feature_set,
>> +			   NETIF_F_HW_VLAN_CTAG_TX_BIT,
>> +			   NETIF_F_HW_VLAN_CTAG_RX_BIT);
>> +EXPORT_SYMBOL_GPL(netif_f_ctag_vlan_offload_feature_set);
>> +
>> +DECLARE_NETDEV_FEATURE_SET(netif_f_stag_vlan_offload_feature_set,
>> +			   NETIF_F_HW_VLAN_STAG_TX_BIT,
>> +			   NETIF_F_HW_VLAN_STAG_RX_BIT);
>> +EXPORT_SYMBOL_GPL(netif_f_stag_vlan_offload_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,
>> +			   NETIF_F_HW_VLAN_CTAG_FILTER_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,
>> +			   NETIF_F_HW_VLAN_STAG_FILTER_BIT);
>> +EXPORT_SYMBOL_GPL(netif_f_stag_vlan_feature_set);
>> +
>> +DECLARE_NETDEV_FEATURE_SET(netif_f_multi_tags_feature_set_mask,
>> +			   NETIF_F_SG_BIT,
>> +			   NETIF_F_HIGHDMA_BIT,
>> +			   NETIF_F_HW_CSUM_BIT,
>> +			   NETIF_F_FRAGLIST_BIT,
>> +			   NETIF_F_HW_VLAN_CTAG_TX_BIT,
>> +			   NETIF_F_HW_VLAN_STAG_TX_BIT);
>> +EXPORT_SYMBOL_GPL(netif_f_multi_tags_feature_set_mask);
>> +
>> +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);
>> +
>> +DECLARE_NETDEV_FEATURE_SET(netvsc_supported_hw_feature_set,
>> +			   NETIF_F_RXCSUM_BIT,
>> +			   NETIF_F_IP_CSUM_BIT,
>> +			   NETIF_F_TSO_BIT,
>> +			   NETIF_F_IPV6_CSUM_BIT,
>> +			   NETIF_F_TSO6_BIT,
>> +			   NETIF_F_LRO_BIT,
>> +			   NETIF_F_SG_BIT,
>> +			   NETIF_F_RXHASH_BIT);
>> +EXPORT_SYMBOL_GPL(netvsc_supported_hw_feature_set);
>> -- 
>> 2.33.0
> Thanks,
> Olek
>
> .

Thank,
Jian


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 03/36] net: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET
  2022-08-10 10:37   ` Alexander Lobakin
@ 2022-08-10 12:15     ` shenjian (K)
  0 siblings, 0 replies; 59+ messages in thread
From: shenjian (K) @ 2022-08-10 12:15 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, andrew, ecree.xilinx, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/8/10 18:37, Alexander Lobakin 写道:
> From: Jian Shen <shenjian15@huawei.com>
> Date: Wed, 10 Aug 2022 11:05:51 +0800
>
>> There are many netdev_features bits group used in drivers, replace them
>> with DECLARE_NETDEV_FEATURE_SET, prepare to remove all the NETIF_F_XXX
>> macroes.
>>
>> Signed-off-by: Jian Shen <shenjian15@huawei.com>
>> ---
>>   arch/um/drivers/vector_transports.c           |  49 +++++--
>>   drivers/infiniband/ulp/ipoib/ipoib.h          |   1 +
>>   drivers/infiniband/ulp/ipoib/ipoib_main.c     |   8 +-
>>   drivers/net/amt.c                             |  16 ++-
>>   drivers/net/bareudp.c                         |  21 ++-
>>   drivers/net/bonding/bond_main.c               |  48 +++++--
>>   drivers/net/dsa/xrs700x/xrs700x.c             |  15 +-
>>   drivers/net/dummy.c                           |  11 +-
>>   drivers/net/ethernet/3com/typhoon.c           |  18 ++-
>>   drivers/net/ethernet/aeroflex/greth.c         |   9 +-
>>   drivers/net/ethernet/alteon/acenic.c          |  10 +-
>>   drivers/net/ethernet/amazon/ena/ena_netdev.c  |  13 +-
>>   drivers/net/ethernet/amd/xgbe/xgbe-main.c     |  59 ++++----
>>   .../net/ethernet/apm/xgene/xgene_enet_main.c  |  12 +-
>>   .../net/ethernet/aquantia/atlantic/aq_nic.c   |  14 +-
>>   drivers/net/ethernet/asix/ax88796c_main.c     |  21 ++-
>>   drivers/net/ethernet/atheros/alx/main.c       |  15 +-
>>   drivers/net/ethernet/atheros/atl1c/atl1c.h    |   1 +
>>   .../net/ethernet/atheros/atl1c/atl1c_main.c   |  14 +-
>>   drivers/net/ethernet/atheros/atl1e/atl1e.h    |   1 +
>>   .../net/ethernet/atheros/atl1e/atl1e_main.c   |  10 +-
>>   drivers/net/ethernet/atheros/atlx/atl1.c      |  22 ++-
>>   drivers/net/ethernet/broadcom/bcmsysport.c    |  24 +++-
>>   drivers/net/ethernet/broadcom/bgmac.c         |   9 +-
>>   drivers/net/ethernet/broadcom/bnx2.c          |  14 +-
>>   .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  83 ++++++++---
>>   drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  54 +++++--
>>   .../net/ethernet/broadcom/genet/bcmgenet.c    |  10 +-
>>   drivers/net/ethernet/brocade/bna/bnad.c       |  39 +++--
>>   drivers/net/ethernet/calxeda/xgmac.c          |  15 +-
>>   .../net/ethernet/cavium/liquidio/lio_main.c   |  42 ++++--
>>   .../ethernet/cavium/liquidio/lio_vf_main.c    |  40 ++++--
>>   .../ethernet/cavium/liquidio/octeon_network.h |   4 +-
>>   .../net/ethernet/cavium/thunder/nicvf_main.c  |  27 +++-
>>   drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  19 ++-
>>   .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  29 +++-
>>   .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  68 ++++++---
>>   .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  39 ++++-
>>   drivers/net/ethernet/cirrus/ep93xx_eth.c      |   7 +-
>>   drivers/net/ethernet/cisco/enic/enic_main.c   |  19 ++-
>>   drivers/net/ethernet/cortina/gemini.c         |  22 ++-
>>   drivers/net/ethernet/emulex/benet/be_main.c   |  47 ++++--
>>   drivers/net/ethernet/faraday/ftgmac100.c      |  13 +-
>>   .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  14 +-
>>   .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |  17 ++-
>>   .../ethernet/freescale/dpaa2/dpaa2-switch.c   |  10 +-
>>   .../ethernet/freescale/dpaa2/dpaa2-switch.h   |   1 +
>>   .../net/ethernet/freescale/enetc/enetc_pf.c   |  42 ++++--
>>   .../net/ethernet/freescale/enetc/enetc_vf.c   |  40 ++++--
>>   drivers/net/ethernet/freescale/fec_main.c     |  11 +-
>>   drivers/net/ethernet/freescale/gianfar.c      |  18 ++-
>>   .../ethernet/fungible/funeth/funeth_main.c    |  48 +++++--
>>   drivers/net/ethernet/google/gve/gve_main.c    |  21 +--
>>   drivers/net/ethernet/hisilicon/hns/hns_enet.c |  51 +++++--
>>   .../net/ethernet/hisilicon/hns3/hns3_enet.c   |  40 ++++--
>>   .../net/ethernet/huawei/hinic/hinic_main.c    |  37 +++--
>>   drivers/net/ethernet/ibm/ehea/ehea_main.c     |  34 +++--
>>   drivers/net/ethernet/ibm/emac/core.c          |   7 +-
>>   drivers/net/ethernet/ibm/ibmveth.c            |  11 +-
>>   drivers/net/ethernet/ibm/ibmvnic.c            |   8 +-
>>   drivers/net/ethernet/intel/e1000/e1000.h      |   1 +
>>   drivers/net/ethernet/intel/e1000/e1000_main.c |  33 +++--
>>   drivers/net/ethernet/intel/e1000e/netdev.c    |  46 ++++--
>>   .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  37 +++--
>>   drivers/net/ethernet/intel/i40e/i40e_main.c   |  75 +++++-----
>>   drivers/net/ethernet/intel/iavf/iavf.h        |   1 +
>>   drivers/net/ethernet/intel/iavf/iavf_main.c   |  43 +++---
>>   drivers/net/ethernet/intel/ice/ice.h          |   1 +
>>   drivers/net/ethernet/intel/ice/ice_main.c     |  64 ++++++---
>>   drivers/net/ethernet/intel/igb/igb_main.c     |  74 ++++++----
>>   drivers/net/ethernet/intel/igbvf/netdev.c     |  76 ++++++----
>>   drivers/net/ethernet/intel/igc/igc_mac.c      |   1 +
>>   drivers/net/ethernet/intel/igc/igc_main.c     |  77 ++++++----
>>   drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  15 +-
>>   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 134 +++++++++++-------
>>   drivers/net/ethernet/intel/ixgbevf/ipsec.c    |  15 +-
>>   drivers/net/ethernet/intel/ixgbevf/ixgbevf.h  |   1 +
>>   .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |  87 +++++++-----
>>   drivers/net/ethernet/jme.c                    |  34 +++--
>>   drivers/net/ethernet/marvell/mv643xx_eth.c    |   9 +-
>>   drivers/net/ethernet/marvell/mvneta.c         |  12 +-
>>   .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  19 ++-
>>   .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  17 ++-
>>   .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  17 ++-
>>   drivers/net/ethernet/marvell/skge.c           |   9 +-
>>   drivers/net/ethernet/marvell/sky2.c           |  19 ++-
>>   drivers/net/ethernet/mellanox/mlx4/en_main.c  |   1 +
>>   .../net/ethernet/mellanox/mlx4/en_netdev.c    |  75 ++++++----
>>   .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c |  20 +--
>>   .../net/ethernet/mellanox/mlxsw/spectrum.c    |  16 ++-
>>   drivers/net/ethernet/micrel/ksz884x.c         |   9 +-
>>   drivers/net/ethernet/microchip/lan743x_main.c |   9 +-
>>   drivers/net/ethernet/microsoft/mana/mana_en.c |  15 +-
>>   drivers/net/ethernet/mscc/ocelot_net.c        |  14 +-
>>   .../net/ethernet/myricom/myri10ge/myri10ge.c  |  11 +-
>>   drivers/net/ethernet/neterion/s2io.c          |  24 +++-
>>   drivers/net/ethernet/nvidia/forcedeth.c       |  10 +-
>>   .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  10 +-
>>   drivers/net/ethernet/pasemi/pasemi_mac.c      |  11 +-
>>   .../net/ethernet/pensando/ionic/ionic_lif.c   |  23 +--
>>   .../ethernet/qlogic/netxen/netxen_nic_main.c  |  11 +-
>>   drivers/net/ethernet/qlogic/qede/qede_main.c  |  50 +++++--
>>   .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  29 ++--
>>   .../net/ethernet/qlogic/qlcnic/qlcnic_main.c  |  34 +++--
>>   drivers/net/ethernet/qualcomm/emac/emac.c     |  23 ++-
>>   .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c   |  12 +-
>>   drivers/net/ethernet/realtek/8139cp.c         |  23 ++-
>>   drivers/net/ethernet/realtek/8139too.c        |   8 +-
>>   drivers/net/ethernet/realtek/r8169_main.c     |  18 ++-
>>   .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |  15 +-
>>   drivers/net/ethernet/sfc/ef10.c               |  11 +-
>>   drivers/net/ethernet/sfc/ef100_netdev.c       |   9 +-
>>   drivers/net/ethernet/sfc/ef100_nic.c          |  15 +-
>>   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 +
>>   drivers/net/ethernet/sfc/siena/efx.c          |  22 ++-
>>   drivers/net/ethernet/sgi/ioc3-eth.c           |  13 +-
>>   drivers/net/ethernet/silan/sc92031.c          |  11 +-
>>   drivers/net/ethernet/socionext/netsec.c       |  11 +-
>>   .../net/ethernet/stmicro/stmmac/stmmac_main.c |  11 +-
>>   drivers/net/ethernet/sun/ldmvsw.c             |   7 +-
>>   drivers/net/ethernet/sun/niu.c                |   9 +-
>>   drivers/net/ethernet/sun/sungem.c             |   9 +-
>>   drivers/net/ethernet/sun/sunvnet.c            |  10 +-
>>   drivers/net/ethernet/tehuti/tehuti.c          |  25 +++-
>>   drivers/net/ethernet/tehuti/tehuti.h          |   1 +
>>   drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  13 +-
>>   drivers/net/ethernet/ti/cpsw_new.c            |  11 +-
>>   drivers/net/ethernet/via/via-velocity.c       |  19 ++-
>>   drivers/net/geneve.c                          |  20 ++-
>>   drivers/net/hyperv/netvsc_drv.c               |  11 +-
>>   drivers/net/ifb.c                             |  20 ++-
>>   drivers/net/ipvlan/ipvlan_main.c              |  58 ++++++--
>>   drivers/net/ipvlan/ipvtap.c                   |  12 +-
>>   drivers/net/loopback.c                        |  25 ++--
>>   drivers/net/macsec.c                          |  22 ++-
>>   drivers/net/macvlan.c                         |  56 ++++++--
>>   drivers/net/macvtap.c                         |  12 +-
>>   drivers/net/net_failover.c                    |  23 +++
>>   drivers/net/netdevsim/ipsec.c                 |  13 +-
>>   drivers/net/netdevsim/netdev.c                |  14 +-
>>   drivers/net/netdevsim/netdevsim.h             |   1 +
>>   drivers/net/nlmon.c                           |  11 +-
>>   drivers/net/tap.c                             |  18 ++-
>>   drivers/net/team/team.c                       |  31 +++-
>>   drivers/net/thunderbolt.c                     |  11 +-
>>   drivers/net/tun.c                             |  28 +++-
>>   drivers/net/usb/aqc111.c                      |  38 ++++-
>>   drivers/net/usb/aqc111.h                      |  14 --
>>   drivers/net/usb/ax88179_178a.c                |  11 +-
>>   drivers/net/usb/lan78xx.c                     |   8 +-
>>   drivers/net/usb/r8152.c                       |  53 +++++--
>>   drivers/net/usb/smsc75xx.c                    |  10 +-
>>   drivers/net/veth.c                            |  27 ++--
>>   drivers/net/vmxnet3/vmxnet3_drv.c             |  36 +++--
>>   drivers/net/vmxnet3/vmxnet3_ethtool.c         |  35 +++--
>>   drivers/net/vmxnet3/vmxnet3_int.h             |   1 +
>>   drivers/net/vrf.c                             |  12 +-
>>   drivers/net/vsockmon.c                        |  11 +-
>>   drivers/net/vxlan/vxlan_core.c                |  20 ++-
>>   drivers/net/wireguard/device.c                |  20 ++-
>>   drivers/net/wireless/ath/wil6210/netdev.c     |  14 +-
>>   drivers/net/xen-netback/interface.c           |  14 +-
>>   drivers/net/xen-netfront.c                    |  20 ++-
>>   drivers/s390/net/qeth_l3_main.c               |  13 +-
>>   drivers/staging/qlge/qlge_main.c              |  21 +--
>>   include/net/bonding.h                         |   5 +-
>>   include/net/net_failover.h                    |   8 +-
>>   net/8021q/vlan_dev.c                          |  15 +-
>>   net/batman-adv/soft-interface.c               |   9 +-
>>   net/bridge/br_device.c                        |  25 +++-
>>   net/ethtool/ioctl.c                           |  17 ++-
>>   net/hsr/hsr_device.c                          |  13 +-
>>   net/ipv4/ip_gre.c                             |  19 +--
>>   net/ipv4/ipip.c                               |  19 ++-
>>   net/ipv6/ip6_gre.c                            |  15 +-
>>   net/ipv6/ip6_tunnel.c                         |  19 ++-
>>   net/ipv6/sit.c                                |  18 ++-
>>   net/mac80211/ieee80211_i.h                    |  13 +-
>>   net/mac80211/main.c                           |  24 ++++
>>   net/openvswitch/vport-internal_dev.c          |  13 +-
>>   net/xfrm/xfrm_interface.c                     |  16 ++-
>>   184 files changed, 2923 insertions(+), 1139 deletions(-)
> [...]
>
>> +static DECLARE_NETDEV_FEATURE_SET(bond_mpls_feature_set,
>> +				  NETIF_F_HW_CSUM_BIT,
>> +				  NETIF_F_SG_BIT);
>> +
>> +static netdev_features_t bond_vlan_features __ro_after_init;
>> +static netdev_features_t bond_enc_features __ro_after_init;
>> +static netdev_features_t bond_mpls_features __ro_after_init;
>>   /*-------------------------- Forward declarations ---------------------------*/
> Nit: any reason to not leave an empty space in between the
> declarations and that comment line?
ok, will fix it.

>>   
>>   static int bond_init(struct net_device *bond_dev);
>> @@ -1421,16 +1441,11 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
>>   	return features;
>>   }
> [...]
>
>>   /**
>>    * struct gmac_queue_page - page buffer per-page info
>> @@ -2610,6 +2618,12 @@ static struct platform_driver gemini_ethernet_driver = {
>>   	.remove = gemini_ethernet_remove,
>>   };
>>   
>> +static void __init gmac_netdev_features_init(void)
>> +{
>> +	netdev_features_set_array(&gmac_offload_feature_set,
>> +				  &gmac_offload_features);
>> +}
> I'd say it's not worth it to create a new function for a one-liner.
ok,  will  move it into gemini_ethernet_module_init().

>> +
>>   static int __init gemini_ethernet_module_init(void)
>>   {
>>   	int ret;
>> @@ -2624,6 +2638,8 @@ static int __init gemini_ethernet_module_init(void)
>>   		return ret;
>>   	}
>>   
>> +	gmac_netdev_features_init();
>> +
>>   	return 0;
>>   }
>>   module_init(gemini_ethernet_module_init);
> [...]
>
>> @@ -120,16 +144,12 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
>>   	ndev->watchdog_timeo = 5 * HZ;
>>   	ndev->max_mtu = ENETC_MAX_MTU;
>>   
>> -	ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
>> -			    NETIF_F_HW_VLAN_CTAG_TX |
>> -			    NETIF_F_HW_VLAN_CTAG_RX |
>> -			    NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
>> -	ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
>> -			 NETIF_F_HW_VLAN_CTAG_TX |
>> -			 NETIF_F_HW_VLAN_CTAG_RX |
>> -			 NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
>> -	ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
>> -			      NETIF_F_TSO | NETIF_F_TSO6;
>> +	netdev_hw_features_zero(ndev);
>> +	netdev_hw_features_set_array(ndev, &enetc_vf_hw_feature_set);
> Hmm, I see that pattern
>
> netdev*_features_zero();
> netdev*_features_set_array();
>
> pretty often, maybe create a couple static inlines like
> 'netdev*_features_from_array'? And use it for initializing
> shared/exported netdev_features as well? Otherwise, sooner or later,
> but someone will forget to zero the features before setting them and
> will get a garbage and some hard-to-track bugs %)
Make sense, this also trouble me too. I will add it.
BTW, I want to add a netdev*_features_from_bit too, for there
are many places use "xxx_features = NET_IF_F_XXX".


>> +	netdev_active_features_zero(ndev);
>> +	netdev_active_features_set_array(ndev, &enetc_vf_feature_set);
>> +	netdev_vlan_features_zero(ndev);
>> +	netdev_vlan_features_set_array(ndev, &enetc_vf_vlan_feature_set);
>>   
>>   	if (si->num_rss)
>>   		ndev->hw_features |= NETIF_F_RXHASH;
>> diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
>> index e8e2aa1e7f01..49850ee91d4e 100644
>> --- a/drivers/net/ethernet/freescale/fec_main.c
>> +++ b/drivers/net/ethernet/freescale/fec_main.c
> [...]
>
>> +static DECLARE_NETDEV_FEATURE_SET(fun_vlan_feature_set,
>> +				  NETIF_F_SG_BIT,
>> +				  NETIF_F_HW_CSUM_BIT,
>> +				  NETIF_F_HIGHDMA_BIT);
>> +
>>   static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
>>   {
>> +	netdev_features_t gso_encap_flags = netdev_empty_features;
>> +	netdev_features_t tso_flags = netdev_empty_features;
> Same here as I mentioned previously, direct assignments wouldn't
> work here later for bitmaps. So it's rather bitmap_copy(), i.e.
> netdev_features_copy(), or am I missing something?
netdev_features_t will be converted from u64 to structure below:

	typedef struct {

		DECLARE_BITMAP(bits, NETDEV_FEATURE_COUNT);

	} netdev_features_t;

So directly assignement is ok

>>   	struct fun_dev *fdev = &ed->fdev;
>> +	netdev_features_t vlan_feat;
>>   	struct net_device *netdev;
>>   	struct funeth_priv *fp;
>>   	unsigned int ntx, nrx;
> [...]
>
>> @@ -1265,6 +1266,13 @@ static void ax88179_get_mac_addr(struct usbnet *dev)
>>   			  dev->net->dev_addr);
>>   }
>>   
>> +DECLARE_NETDEV_FEATURE_SET(ax88179_feature_set,
> static?
> You can use sparse to detect such places (`make C=1`).
Right, I will check it.

>> +			   NETIF_F_SG_BIT,
>> +			   NETIF_F_IP_CSUM_BIT,
>> +			   NETIF_F_IPV6_CSUM_BIT,
>> +			   NETIF_F_RXCSUM_BIT,
>> +			   NETIF_F_TSO_BIT);
> [...]
>
>> -- 
>> 2.33.0
> Thanks,
> Olek
>
> .

Thanks,
Jian

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 16/36] treewide: use replace features '0' by netdev_empty_features
  2022-08-10 10:48   ` Alexander Lobakin
@ 2022-08-10 12:25     ` shenjian (K)
  2022-08-11 12:35       ` Alexander Lobakin
  0 siblings, 1 reply; 59+ messages in thread
From: shenjian (K) @ 2022-08-10 12:25 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, andrew, ecree.xilinx, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/8/10 18:48, Alexander Lobakin 写道:
> From: Jian Shen <shenjian15@huawei.com>
> Date: Wed, 10 Aug 2022 11:06:04 +0800
>
>> For the prototype of netdev_features_t will be changed from
>> u64 to bitmap, so it's unable to assignment with 0 directly.
>> Replace it with netdev_empty_features.
> Hmm, why not just netdev_features_zero() instead?
> There's a couple places where empty netdev_features are needed, but
> they're not probably worth a separate and rather pointless empty
> variable, you could create one on the stack there.
As replied before, the new netdev_features_t supports being
assigned directly, so use netdev_emtpy_features looks
more simple.

>> Signed-off-by: Jian Shen <shenjian15@huawei.com>
>> ---
>>   drivers/hsi/clients/ssi_protocol.c             | 2 +-
>>   drivers/net/caif/caif_serial.c                 | 2 +-
>>   drivers/net/ethernet/amazon/ena/ena_netdev.c   | 2 +-
>>   drivers/net/ethernet/broadcom/b44.c            | 2 +-
>>   drivers/net/ethernet/broadcom/tg3.c            | 2 +-
>>   drivers/net/ethernet/dnet.c                    | 2 +-
>>   drivers/net/ethernet/ec_bhf.c                  | 2 +-
>>   drivers/net/ethernet/emulex/benet/be_main.c    | 2 +-
>>   drivers/net/ethernet/ethoc.c                   | 2 +-
>>   drivers/net/ethernet/huawei/hinic/hinic_main.c | 5 +++--
>>   drivers/net/ethernet/ibm/ibmvnic.c             | 6 +++---
>>   drivers/net/ethernet/intel/iavf/iavf_main.c    | 9 +++++----
>>   drivers/net/ethernet/microsoft/mana/mana_en.c  | 2 +-
>>   drivers/net/ethernet/sfc/ef10.c                | 2 +-
>>   drivers/net/tap.c                              | 2 +-
>>   drivers/net/tun.c                              | 2 +-
>>   drivers/net/usb/cdc-phonet.c                   | 3 ++-
>>   drivers/net/usb/lan78xx.c                      | 2 +-
>>   drivers/s390/net/qeth_core_main.c              | 2 +-
>>   drivers/usb/gadget/function/f_phonet.c         | 3 ++-
>>   net/dccp/ipv4.c                                | 2 +-
>>   net/dccp/ipv6.c                                | 2 +-
>>   net/ethtool/features.c                         | 2 +-
>>   net/ethtool/ioctl.c                            | 6 ++++--
>>   net/ipv4/af_inet.c                             | 2 +-
>>   net/ipv4/tcp.c                                 | 2 +-
>>   net/ipv4/tcp_ipv4.c                            | 2 +-
>>   net/ipv6/af_inet6.c                            | 2 +-
>>   net/ipv6/inet6_connection_sock.c               | 2 +-
>>   net/ipv6/tcp_ipv6.c                            | 2 +-
>>   net/openvswitch/datapath.c                     | 2 +-
>>   31 files changed, 44 insertions(+), 38 deletions(-)
> [...]
>
>> -- 
>> 2.33.0
> Thanks,
> Olek
> .
>
Thanks,
Jian

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 17/36] treewide: adjust features initialization
  2022-08-10 10:58   ` Alexander Lobakin
@ 2022-08-10 14:06     ` shenjian (K)
  0 siblings, 0 replies; 59+ messages in thread
From: shenjian (K) @ 2022-08-10 14:06 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, andrew, ecree.xilinx, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/8/10 18:58, Alexander Lobakin 写道:
> From: Jian Shen <shenjian15@huawei.com>
> Date: Wed, 10 Aug 2022 11:06:05 +0800
>
>> There are many direclty single bit assignment to netdev features.
>> Adjust these expressions, so can use netdev features helpers later.
>>
>> Signed-off-by: Jian Shen <shenjian15@huawei.com>
>> ---
>>   arch/um/drivers/vector_kern.c                       | 5 ++++-
>>   drivers/firewire/net.c                              | 4 +++-
>>   drivers/infiniband/hw/hfi1/vnic_main.c              | 4 +++-
>>   drivers/misc/sgi-xp/xpnet.c                         | 3 ++-
>>   drivers/net/can/dev/dev.c                           | 4 +++-
>>   drivers/net/ethernet/alacritech/slicoss.c           | 4 +++-
>>   drivers/net/ethernet/amd/xgbe/xgbe-drv.c            | 4 +++-
>>   drivers/net/ethernet/aquantia/atlantic/aq_nic.c     | 3 ++-
>>   drivers/net/ethernet/atheros/atlx/atl2.c            | 4 +++-
>>   drivers/net/ethernet/cadence/macb_main.c            | 4 +++-
>>   drivers/net/ethernet/davicom/dm9000.c               | 4 +++-
>>   drivers/net/ethernet/engleder/tsnep_main.c          | 4 +++-
>>   drivers/net/ethernet/ibm/ibmveth.c                  | 3 ++-
>>   drivers/net/ethernet/marvell/octeon_ep/octep_main.c | 4 +++-
>>   drivers/net/ethernet/mellanox/mlx4/en_netdev.c      | 3 ++-
>>   drivers/net/ethernet/mellanox/mlx5/core/en_main.c   | 4 +++-
>>   drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 7 +++++--
>>   drivers/net/ethernet/netronome/nfp/nfp_net_repr.c   | 3 ++-
>>   drivers/net/ethernet/ni/nixge.c                     | 4 +++-
>>   drivers/net/ethernet/renesas/sh_eth.c               | 6 ++++--
>>   drivers/net/ethernet/sun/sunhme.c                   | 7 +++++--
>>   drivers/net/ethernet/toshiba/ps3_gelic_net.c        | 6 ++++--
>>   drivers/net/ethernet/toshiba/spider_net.c           | 3 ++-
>>   drivers/net/ethernet/tundra/tsi108_eth.c            | 3 ++-
>>   drivers/net/ethernet/xilinx/ll_temac_main.c         | 4 +++-
>>   drivers/net/ethernet/xilinx/xilinx_axienet_main.c   | 4 +++-
>>   drivers/net/hamradio/bpqether.c                     | 4 +++-
>>   drivers/net/hyperv/netvsc_drv.c                     | 3 ++-
>>   drivers/net/ipa/ipa_modem.c                         | 4 +++-
>>   drivers/net/ntb_netdev.c                            | 4 +++-
>>   drivers/net/rionet.c                                | 4 +++-
>>   drivers/net/tap.c                                   | 2 +-
>>   drivers/net/thunderbolt.c                           | 3 ++-
>>   drivers/net/usb/smsc95xx.c                          | 4 +++-
>>   drivers/net/virtio_net.c                            | 4 +++-
>>   drivers/net/wireless/ath/ath10k/mac.c               | 7 +++++--
>>   drivers/net/wireless/ath/ath11k/mac.c               | 4 +++-
>>   drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c   | 4 +++-
>>   drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c   | 4 +++-
>>   drivers/net/wireless/mediatek/mt76/mt7615/init.c    | 4 +++-
>>   drivers/net/wireless/mediatek/mt76/mt7915/init.c    | 4 +++-
>>   drivers/net/wireless/mediatek/mt76/mt7921/init.c    | 4 +++-
>>   drivers/net/wwan/t7xx/t7xx_netdev.c                 | 4 +++-
>>   drivers/s390/net/qeth_core_main.c                   | 7 +++++--
>>   include/net/udp.h                                   | 4 +++-
>>   net/phonet/pep-gprs.c                               | 4 +++-
>>   46 files changed, 138 insertions(+), 52 deletions(-)
>>
>> diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
>> index 1d59522a50d8..d797758850e1 100644
>> --- a/arch/um/drivers/vector_kern.c
>> +++ b/arch/um/drivers/vector_kern.c
>> @@ -1628,7 +1628,10 @@ static void vector_eth_configure(
>>   		.bpf			= NULL
>>   	});
>>   
>> -	dev->features = dev->hw_features = (NETIF_F_SG | NETIF_F_FRAGLIST);
>> +	netdev_active_features_zero(dev);
>> +	dev->features |= NETIF_F_SG;
>> +	dev->features |= NETIF_F_FRAGLIST;
>> +	dev->features = dev->hw_features;
> I think a new helper can be useful there and in a couple other
> places, which would set or clear an array of bits taking them as
> varargs:
>
> #define __netdev_features_set_set(feat, uniq, ...) ({	\
> 	DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
> 	netdev_features_set_array(feat, &(uniq));	\
> })
> #define netdev_features_set_set(feat, ...)		\
> 	__smth(feat, __UNIQUE_ID(feat_set), __VA_ARGS__)
>
> (name is a placeholder)
>
> so that you can do
>
> 	netdev_active_features_zero(dev);
> 	netdev_features_set_set(dev->features, NETIF_F_SG, NETIF_F_FRAGLIST);
>
> in one take. I think it looks elegant, doesn't it?
good idea. I will try it, thanks!


>>   	INIT_WORK(&vp->reset_tx, vector_reset_tx);
>>   
>>   	timer_setup(&vp->tl, vector_timer_expire, 0);
> [...]
>
>> -- 
>> 2.33.0
> Thanks,
> Olek
>
> .
>


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 23/36] net: adjust the build check for net_gso_ok()
  2022-08-10 11:09   ` Alexander Lobakin
@ 2022-08-10 14:41     ` shenjian (K)
  0 siblings, 0 replies; 59+ messages in thread
From: shenjian (K) @ 2022-08-10 14:41 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, andrew, ecree.xilinx, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/8/10 19:09, Alexander Lobakin 写道:
> From: Jian Shen <shenjian15@huawei.com>
> Date: Wed, 10 Aug 2022 11:06:11 +0800
>
>> Introduce macro GSO_INDEX(x) to replace the NETIF_F_XXX
>> feature shift check, for all the macroes NETIF_F_XXX will
>> be remove later.
>>
>> Signed-off-by: Jian Shen <shenjian15@huawei.com>
>> ---
>>   include/linux/netdevice.h | 40 ++++++++++++++++++++-------------------
>>   1 file changed, 21 insertions(+), 19 deletions(-)
>>
>> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>> index 1bd5dcbc884d..b01af2a3838d 100644
>> --- a/include/linux/netdevice.h
>> +++ b/include/linux/netdevice.h
>> @@ -4886,28 +4886,30 @@ netdev_features_t netif_skb_features(struct sk_buff *skb);
>>   
>>   static inline bool net_gso_ok(netdev_features_t features, int gso_type)
>>   {
>> +#define GSO_INDEX(x)	((1ULL << (x)) >> NETIF_F_GSO_SHIFT)
> What if we get a new GSO offload which's corresponding bit will be
> higher than 64?
> You could instead do
>
> #define __SKB_GSO_FLAG(x)	(1ULL << (x))
>
> enum {
> 	SKB_GSO_TCPV4_BIT	= 0,
> 	SKB_GSO_DODGY_BIT	= 1,
> 	...,
> };
> enum {
> 	SKB_GSO_TCPV4		= __SKB_GSO_FLAG(TCPV4),
> 	SKB_GSO_DODGY		= __SKB_GSO_FLAG(DODGY),
> 	...,
> };
>
> and then just
>
> #define ASSERT_GSO_TYPE(fl, feat)	\
> 	static_assert((fl) == (feat) - NETIF_F_GSO_SHIFT)
>
> 	...
> 	ASSERT_GSO_TYPE(SKB_GSO_TCPV4_BIT, NETIF_F_TSO_BIT);
> 	ASSERT_GSO_TYPE(SKB_GSO_DODGY, NETIF_F_GSO_ROBUST_BIT);
> 	...
Yes, it may be misused for new GSO offload bit higher than 64, the macro
__SKB_GSO_FLAG(x) is better.

>> +
>>   	netdev_features_t feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT;
>>   
>>   	/* 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));
>> +	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 (features & feature) == feature;
>>   }
>> -- 
>> 2.33.0
> Thanks,
> Olek
> .
>


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features
  2022-08-10 11:32     ` shenjian (K)
@ 2022-08-11 10:49       ` Alexander Lobakin
  2022-08-12  2:39         ` shenjian (K)
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-11 10:49 UTC (permalink / raw)
  To: shenjian (K)
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: "shenjian (K)" <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 19:32:28 +0800

> 在 2022/8/10 17:43, Alexander Lobakin 写道:
> > From: Jian Shen <shenjian15@huawei.com>
> > Date: Wed, 10 Aug 2022 11:05:49 +0800
> >
> >> Introduce a set of bitmap operation helpers for netdev features,
> >> then we can use them to replace the logical operation with them.
> >>
> >> The implementation of these helpers are based on the old prototype
> >> of netdev_features_t is still u64. These helpers will be rewritten
> >> 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 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>
> >> ---
> >>   include/linux/netdev_features.h        |  11 +
> >>   include/linux/netdev_features_helper.h | 707 +++++++++++++++++++++++++
> > 'netdev_feature_helpers.h' fits more I guess, doesn't it? It
> > contains several helpers, not only one.
> ok, will rename it.
> 
> > And BTW, do you think it's worth to create a new file rather than
> > put everything just in netdev_features.h?
> Jakub suggested me to move them to a new file, then it can be includued
> at users appropriately. 
> [https://www.spinics.net/lists/netdev/msg809370.html]
> 
> And it's unable to put everything in netdev_features.h, because these 
> helpers
> need to see the definition of struct net_device which is defined in 
> netdevice.h.
> It leading interdependence for netdeice.h include netdev_features.h.

Ah, correct then, sure! I missed that fact.

> 
> 
> >>   include/linux/netdevice.h              |  45 +-
> >>   net/8021q/vlan_dev.c                   |   1 +
> >>   net/core/dev.c                         |   1 +
> >>   5 files changed, 747 insertions(+), 18 deletions(-)
> >>   create mode 100644 include/linux/netdev_features_helper.h
> >>
> >> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
> >> index 7c2d77d75a88..9d434b4e6e6e 100644
> >> --- a/include/linux/netdev_features.h
> >> +++ b/include/linux/netdev_features.h
> >> @@ -11,6 +11,17 @@
> >>   
> >>   typedef u64 netdev_features_t;
> >>   
> >> +struct netdev_feature_set {
> >> +	unsigned int cnt;
> >> +	unsigned short feature_bits[];
> >> +};
> >> +
> >> +#define DECLARE_NETDEV_FEATURE_SET(name, features...)			\
> >> +	const struct netdev_feature_set name = {			\
> >> +		.cnt = sizeof((unsigned short[]){ features }) / sizeof(unsigned short),	\
> >> +		.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..5423927d139b
> >> --- /dev/null
> >> +++ b/include/linux/netdev_features_helper.h
> >> @@ -0,0 +1,707 @@
> >> +/* 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;
> >> +}
> >> +
> >> +/* active_feature prefer to netdev->features */
> >> +#define netdev_active_features_zero(ndev) \
> >> +		netdev_features_zero(&ndev->features)
> > netdev_features_t sometimes is being placed and used on the stack.
> > I think it's better to pass just `netdev_features_t *` to those
> > helpers, this way you wouldn't also need to create a new helper
> > for each net_device::*_features.
> My purpose of defining  helpers for each net_device::*_features is to
> avoiding driver to change  net_device::*_features directly.

But why? My point is that you have to create a whole bunch of
copy'n'paste functions differing only by the &net_device field
name.

> 
> >> +
> >> +#define netdev_hw_features_zero(ndev) \
> >> +		netdev_features_zero(&ndev->hw_features)

Oh BTW: wrap `ndev` in the netdev_features_zero() call into braces,
`netdev_feature_zero(&(ndev)->hw_features)`, otherwise it may cause
unwanted sneaky logical changes or build failures.

> >> +
> >> +#define netdev_wanted_features_zero(ndev) \
> > [...]
> >
> >> +#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);
> > A small proposal: if you look at bitmap_and() for example, it
> > returns 1 if the resulting bitmap is non-empty and 0 if it is. What
> > about doing the same here? It would probably help to do reduce
> > boilerplating in the drivers where we only want to know if there's
> > anything left after masking.
> > Same for xor, toggle etc.
> Thanks for point this.  Return whether empty, then I can remove 
> netdev_features_intersects
> helpers. But there are also many places to use 'f1 & f2' as return value 
> or input param, then
> I need to define more temporay features to store the result, and then 
> return the temporay
> features or pass into it.

No, netdev_features_intersects() is okay, leave it as it is. Just
look on bitmap_*() prototypes and return its values when applicable.

> 
> >> +}
> >> +
> >> +static inline void
> >> +netdev_active_features_mask(struct net_device *ndev,
> >> +			    const netdev_features_t features)
> >> +{
> >> +	ndev->features = netdev_active_features_and(ndev, 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++)
> > Nit: kernel is C11 now, you can do just `for (u32 i = 0; i ...`.
> > (and yeah, it's better to use unsigned types when you don't plan
> > to store negative values there).
> ok, will fix it.
> 
> >> +		netdev_feature_add(set->feature_bits[i], dst);
> >> +}
> > [...]
> >
> >> -- 
> >> 2.33.0
> > Thanks,
> > Olek
> >
> > .

Thanks,
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 02/36] net: replace general features macroes with global netdev_features variables
  2022-08-10 12:01     ` shenjian (K)
@ 2022-08-11 11:05       ` Alexander Lobakin
  2022-08-12 10:58         ` shenjian (K)
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-11 11:05 UTC (permalink / raw)
  To: shenjian (K)
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: "shenjian (K)" <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 20:01:15 +0800

> 在 2022/8/10 17:58, Alexander Lobakin 写道:
> > From: Jian Shen <shenjian15@huawei.com>
> > Date: Wed, 10 Aug 2022 11:05:50 +0800
> >
> >> 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>
> >> ---

[...]

> >> @@ -11362,6 +11363,86 @@ static struct pernet_operations __net_initdata default_device_ops = {
> >>   	.exit_batch = default_device_exit_batch,
> >>   };
> >>   
> >> +static void __init netdev_features_init(void)
> > Given that you're creating a new file dedicated to netdev features,
> > I'd place that initializer there. You can then declare its proto in
> > net/core/dev.h.
> I want to make sure it cann't be called outside net/core/dev.c, for some
> drivers include net/core/dev.h, then they can see it.

net/core/dev.h is internal, nobody outside net/core/ uses it and
this was its purpose.

> 
> >> +{
> >> +	netdev_features_t features;
> >> +
> >> +	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_gso_feature_set_mask,
> >> +				  &netdev_gso_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_gso_encap_feature_set,
> >> +				  &netdev_gso_encap_all_features);
> >> +
> >> +	netdev_csum_gso_features_mask =
> >> +		netdev_features_or(netdev_gso_features_mask,
> >> +				   netdev_csum_features_mask);
> > (I forgot to mention this in 01/36 ._.)
> >
> > As you're converting to bitmaps, you should probably avoid direct
> > assignments. All the bitmap_*() modification functions take a pointer
> > to the destination as a first argument. So it should be
> >
> > netdev_features_or(netdev_features_t *dst, const netdev_features_t *src1,
> > 		   const netdev_features_t *src1);
> The netdev_features_t will be convert to a structure which only contained
> a feature bitmap. So assginement is ok.

Yeah I realized it later, probably a good idea.

> 
> 
> >> +
> >> +	netdev_features_set_array(&netif_f_one_for_all_feature_set,
> >> +				  &netdev_one_for_all_features);
> > Does it make sense to prefix features and the corresponding sets
> > differently? Why not just 'netdev_' for both of them?
> For all the feature bits are named "NETFI_F_XXX_BIT",

Right, but then why are netdev_*_features prefixed with 'netdev',
not 'netif_f'? :D Those sets are tied tightly with the feature
structures, so I think they should have the same prefix. I'd go
with 'netdev' for both.

> 
> 
> >> +	netdev_features_set_array(&netif_f_all_for_all_feature_set,
> >> +				  &netdev_all_for_all_features);

[...]

> >> -- 
> >> 2.33.0
> > Thanks,
> > Olek
> >
> > .
> 
> Thank,
> Jian

Thanks,
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 16/36] treewide: use replace features '0' by netdev_empty_features
  2022-08-10 12:25     ` shenjian (K)
@ 2022-08-11 12:35       ` Alexander Lobakin
  0 siblings, 0 replies; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-11 12:35 UTC (permalink / raw)
  To: shenjian (K)
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: "shenjian (K)" <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 20:25:38 +0800

> 在 2022/8/10 18:48, Alexander Lobakin 写道:
> > From: Jian Shen <shenjian15@huawei.com>
> > Date: Wed, 10 Aug 2022 11:06:04 +0800
> >
> >> For the prototype of netdev_features_t will be changed from
> >> u64 to bitmap, so it's unable to assignment with 0 directly.
> >> Replace it with netdev_empty_features.
> > Hmm, why not just netdev_features_zero() instead?
> > There's a couple places where empty netdev_features are needed, but
> > they're not probably worth a separate and rather pointless empty
> > variable, you could create one on the stack there.
> As replied before, the new netdev_features_t supports being
> assigned directly, so use netdev_emtpy_features looks
> more simple.

Dunno, looks reduntant. For declaring onstack variables, one can
simply:

	netdev_features_t feat = { };

For zeroing in the code it's a bit more complex:

	feat = (typeof(feat)){ };

But I can't remember empty complex variables in the kernel code
declared just to ease type initialization.

Hmm, how about

#define netdev_empty_features	((netdev_features_t){ })

?

It would work just as your variable, but without creating any
globals.
Before converting netdev_features to a structure, you can define
it just as `0`.

> 
> >> Signed-off-by: Jian Shen <shenjian15@huawei.com>
> >> ---
> >>   drivers/hsi/clients/ssi_protocol.c             | 2 +-
> >>   drivers/net/caif/caif_serial.c                 | 2 +-
> >>   drivers/net/ethernet/amazon/ena/ena_netdev.c   | 2 +-
> >>   drivers/net/ethernet/broadcom/b44.c            | 2 +-
> >>   drivers/net/ethernet/broadcom/tg3.c            | 2 +-
> >>   drivers/net/ethernet/dnet.c                    | 2 +-
> >>   drivers/net/ethernet/ec_bhf.c                  | 2 +-
> >>   drivers/net/ethernet/emulex/benet/be_main.c    | 2 +-
> >>   drivers/net/ethernet/ethoc.c                   | 2 +-
> >>   drivers/net/ethernet/huawei/hinic/hinic_main.c | 5 +++--
> >>   drivers/net/ethernet/ibm/ibmvnic.c             | 6 +++---
> >>   drivers/net/ethernet/intel/iavf/iavf_main.c    | 9 +++++----
> >>   drivers/net/ethernet/microsoft/mana/mana_en.c  | 2 +-
> >>   drivers/net/ethernet/sfc/ef10.c                | 2 +-
> >>   drivers/net/tap.c                              | 2 +-
> >>   drivers/net/tun.c                              | 2 +-
> >>   drivers/net/usb/cdc-phonet.c                   | 3 ++-
> >>   drivers/net/usb/lan78xx.c                      | 2 +-
> >>   drivers/s390/net/qeth_core_main.c              | 2 +-
> >>   drivers/usb/gadget/function/f_phonet.c         | 3 ++-
> >>   net/dccp/ipv4.c                                | 2 +-
> >>   net/dccp/ipv6.c                                | 2 +-
> >>   net/ethtool/features.c                         | 2 +-
> >>   net/ethtool/ioctl.c                            | 6 ++++--
> >>   net/ipv4/af_inet.c                             | 2 +-
> >>   net/ipv4/tcp.c                                 | 2 +-
> >>   net/ipv4/tcp_ipv4.c                            | 2 +-
> >>   net/ipv6/af_inet6.c                            | 2 +-
> >>   net/ipv6/inet6_connection_sock.c               | 2 +-
> >>   net/ipv6/tcp_ipv6.c                            | 2 +-
> >>   net/openvswitch/datapath.c                     | 2 +-
> >>   31 files changed, 44 insertions(+), 38 deletions(-)
> > [...]
> >
> >> -- 
> >> 2.33.0
> > Thanks,
> > Olek
> > .
> >
> Thanks,
> Jian

Thanks,
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t
       [not found]     ` <3df89822-7dec-c01e-0df9-15b8e6f7d4e5@huawei.com>
@ 2022-08-11 13:07       ` Alexander Lobakin
  2022-08-11 15:13         ` Jakub Kicinski
  2022-08-12 11:30         ` shenjian (K)
  0 siblings, 2 replies; 59+ messages in thread
From: Alexander Lobakin @ 2022-08-11 13:07 UTC (permalink / raw)
  To: shenjian (K)
  Cc: Alexander Lobakin, davem, kuba, andrew, ecree.xilinx, hkallweit1,
	saeed, leon, netdev, linuxarm

From: "shenjian (K)" <shenjian15@huawei.com>
Date: Wed, 10 Aug 2022 21:34:43 +0800

BTW, you replied in HTML instead of plain text and korg mail servers
rejected it. So non-Ccs can't see it. Just be aware that LKML
accepts plain text only :)

> 在 2022/8/10 19:35, Alexander Lobakin 写道:
> > From: Jian Shen <shenjian15@huawei.com>
> > Date: Wed, 10 Aug 2022 11:06:24 +0800
> >
> >> 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. Serveal macroes remained
> >> temporarily, by some precompile dependency.
> >>
> >> 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>
> >> ---
> >>   drivers/net/ethernet/amazon/ena/ena_netdev.c  |  12 +-
> >>   .../net/ethernet/intel/i40e/i40e_debugfs.c    |  12 +-
> >>   .../ethernet/netronome/nfp/nfp_net_common.c   |   4 +-
> >>   .../net/ethernet/pensando/ionic/ionic_lif.c   |   4 +-
> >>   include/linux/netdev_features.h               | 101 ++----------
> >>   include/linux/netdev_features_helper.h        | 149 +++++++++++-------
> >>   include/linux/netdevice.h                     |   7 +-
> >>   include/linux/skbuff.h                        |   4 +-
> >>   include/net/ip_tunnels.h                      |   2 +-
> >>   lib/vsprintf.c                                |  11 +-
> >>   net/ethtool/features.c                        |  96 ++++-------
> >>   net/ethtool/ioctl.c                           |  46 ++++--
> >>   net/mac80211/main.c                           |   3 +-
> >>   13 files changed, 201 insertions(+), 250 deletions(-)
> > [...]
> >
> >> -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;
> >> -}
> >> +#define NETIF_F_HW_VLAN_CTAG_TX
> >> +#define NETIF_F_IPV6_CSUM
> >> +#define NETIF_F_TSO
> >> +#define NETIF_F_GSO
> > Uhm, what are those empty definitions for? They look confusing.
> I kept them temporary for some drivers use them like below:
> for example in drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
> #ifdef NETIF_F_HW_VLAN_CTAG_TX
> #include <linux/if_vlan.h>
> #endif
> 
> So far I haven't got a good way to replace it.

I believe such constructs sneaked in from some development/draft
versions of the code, as those definitions are always here, so
this is just redundant/pointless.
Just remove those ifdefs and always include the file.
The empty definitions you left in netdev_features.h are confusing,
I'd not keep them.

> 
> >>   
> >>   /* This goes for the MSB to the LSB through the set feature bits,
> >>    * mask_addr should be a u64 and bit an int
> >>    */

[...]

> >> +#define GSO_ENCAP_FEATURES	(((u64)1 << NETIF_F_GSO_GRE_BIT) |		\
> >> +				 ((u64)1 << NETIF_F_GSO_GRE_CSUM_BIT) |		\
> >> +				 ((u64)1 << NETIF_F_GSO_IPXIP4_BIT) |		\
> >> +				 ((u64)1 << NETIF_F_GSO_IPXIP6_BIT) |		\
> >> +				 (((u64)1 << NETIF_F_GSO_UDP_TUNNEL_BIT) |	\
> >> +				  ((u64)1 << NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT)))
> > 1) 1ULL;
> ok,will fix it
> 
> > 2) what if we get a new GSO encap type which's bit will be higher
> >     than 64?
> So far I prefer to use this.  It's used to assgned to 
> skb_shinfo(skb)->gso_type, which prototype
> is 'unsigned int'.  Once new gso encap type introduced, we should extend 
> the gso_type first.

But ::gso_type accepts flags like %SKB_GSO_DODGY and so on, not
netdev_features, doesn't it?

> 
> 
> >> +
> >>   #endif	/* _LINUX_NETDEV_FEATURES_H */

[...]

> >>   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;
> > Yeah, so as I wrote previously, not a good idea to return a whole
> > bitmap/structure.
> >
> > netdev_features_and(*dst, const *a, const *b)
> > {
> > 	return bitmap_and(); // bitmap_and() actually returns useful value
> > }
> >
> > I mean, 16 bytes (currently 8, but some new features will come
> > pretty shortly, I'm sure) are probably okayish, but... let's see
> > what other folks think, but even Linus wrote about this recently
> > BTW.
> Yes, Jakub also mentioned this.
> 
> But there are many existed features interfaces(e.g. ndo_fix_features,
> ndo_features_check), use netdev_features_t as return value. Then we
> have to change their prototype.

We have to do 12k lines of changes already :D
You know, 16 bytes is probably fine to return directly and it will
be enough for up to 128 features (+64 more comparing to the
mainline). OTOH, using pointers removes that "what if/when", so
it's more flexible in that term. So that's why I asked for other
folks' opinions -- 2 PoVs doesn't seem enough here.

> 
> second problem is for the helpers' definition. For example:
> When we introduce helper like netdev_features_zero(netdev_features_t 
> *features)
> without change prototype of netdev_features_t.
> once covert netdev_features_t from u64 to unsigned long *, then it becomes
> netdev_features_zero(unsigned long **features), result in much redundant 
> work
> to adjust it to netdev_features_zero(unsigned long *features).

> 
> 
> >>   }

[...]

> >>   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;
> >> +	netdev_features_t *features;
> > const? We're printing.
> It will cause compile warning for bitmap_string use features->bits
> as input param without "const" definition in its prototype.

Oof, that's weird. I checked the function you mentioned and don't
see any reason why it would require non-RO access to the bitmap it
prints.
Could you maybe please change its proto to take const bitmap, so
that it won't complain on your code? As a separate patch going right
before this one in your series.

> >>   
> >>   	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);
> >> +		features = (netdev_features_t *)addr;
> > Casts are not needed when assigning from `void *`.
> ok, will fix it
> >> +		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, features->bits, spec, fmt);
> >>   }

[...]

> >> -- 
> >> 2.33.0
> > That's my last review email for now. Insane amount of work, I'm glad
> > someone did it finally. Thanks a lot!
> >
> > Olek
> > .
> Hi   Olek,
> Grateful for your review.  You made a lot of valuable suggestions. I will
> check and continue refine the patchset.
> 
> Thanks again!
> 
> Jian

Thanks!
Olek

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t
  2022-08-11 13:07       ` Alexander Lobakin
@ 2022-08-11 15:13         ` Jakub Kicinski
  2022-08-12 11:43           ` shenjian (K)
  2022-08-12 11:30         ` shenjian (K)
  1 sibling, 1 reply; 59+ messages in thread
From: Jakub Kicinski @ 2022-08-11 15:13 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: shenjian (K),
	davem, andrew, ecree.xilinx, hkallweit1, saeed, leon, netdev,
	linuxarm

On Thu, 11 Aug 2022 15:07:57 +0200 Alexander Lobakin wrote:

> > Yes, Jakub also mentioned this.
> > 
> > But there are many existed features interfaces(e.g. ndo_fix_features,
> > ndo_features_check), use netdev_features_t as return value. Then we
> > have to change their prototype.  
> 
> We have to do 12k lines of changes already :D
> You know, 16 bytes is probably fine to return directly and it will
> be enough for up to 128 features (+64 more comparing to the
> mainline). OTOH, using pointers removes that "what if/when", so
> it's more flexible in that term. So that's why I asked for other
> folks' opinions -- 2 PoVs doesn't seem enough here.

From a quick grep it seems like the and() is mostly used in some form
of:

	features = and(features, mask);

and we already have netdev_features_clear() which modifies its first
argument. I'd also have and() update its first arg rather than return
the result as a value. It will require changing the prototype of
ndo_features_check() :( But yeah, I reckon we shouldn't be putting of
refactoring, best if we make all the changes at once than have to
revisit this once the flags grow again and return by value starts to
be a problem.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features
  2022-08-11 10:49       ` Alexander Lobakin
@ 2022-08-12  2:39         ` shenjian (K)
  0 siblings, 0 replies; 59+ messages in thread
From: shenjian (K) @ 2022-08-12  2:39 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, andrew, ecree.xilinx, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/8/11 18:49, Alexander Lobakin 写道:
> From: "shenjian (K)" <shenjian15@huawei.com>
> Date: Wed, 10 Aug 2022 19:32:28 +0800
>
>> 在 2022/8/10 17:43, Alexander Lobakin 写道:
>> > From: Jian Shen <shenjian15@huawei.com>
>> > Date: Wed, 10 Aug 2022 11:05:49 +0800
>> >
>> >> Introduce a set of bitmap operation helpers for netdev features,
>> >> then we can use them to replace the logical operation with them.
>> >>
>> >> The implementation of these helpers are based on the old prototype
>> >> of netdev_features_t is still u64. These helpers will be rewritten
>> >> 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 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>
>> >> ---
>> >>   include/linux/netdev_features.h        |  11 +
>> >>   include/linux/netdev_features_helper.h | 707 
>> +++++++++++++++++++++++++
>> > 'netdev_feature_helpers.h' fits more I guess, doesn't it? It
>> > contains several helpers, not only one.
>> ok, will rename it.
>>
>> > And BTW, do you think it's worth to create a new file rather than
>> > put everything just in netdev_features.h?
>> Jakub suggested me to move them to a new file, then it can be includued
>> at users appropriately. 
>> [https://www.spinics.net/lists/netdev/msg809370.html]
>>
>> And it's unable to put everything in netdev_features.h, because these 
>> helpers
>> need to see the definition of struct net_device which is defined in 
>> netdevice.h.
>> It leading interdependence for netdeice.h include netdev_features.h.
>
> Ah, correct then, sure! I missed that fact.
>
>>
>>
>> >>   include/linux/netdevice.h              |  45 +-
>> >>   net/8021q/vlan_dev.c                   |   1 +
>> >>   net/core/dev.c                         |   1 +
>> >>   5 files changed, 747 insertions(+), 18 deletions(-)
>> >>   create mode 100644 include/linux/netdev_features_helper.h
>> >>
>> >> diff --git a/include/linux/netdev_features.h 
>> b/include/linux/netdev_features.h
>> >> index 7c2d77d75a88..9d434b4e6e6e 100644
>> >> --- a/include/linux/netdev_features.h
>> >> +++ b/include/linux/netdev_features.h
>> >> @@ -11,6 +11,17 @@
>> >>   >>   typedef u64 netdev_features_t;
>> >>   >> +struct netdev_feature_set {
>> >> +    unsigned int cnt;
>> >> +    unsigned short feature_bits[];
>> >> +};
>> >> +
>> >> +#define DECLARE_NETDEV_FEATURE_SET(name, features...)            \
>> >> +    const struct netdev_feature_set name = {            \
>> >> +        .cnt = sizeof((unsigned short[]){ features }) / 
>> sizeof(unsigned short),    \
>> >> +        .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..5423927d139b
>> >> --- /dev/null
>> >> +++ b/include/linux/netdev_features_helper.h
>> >> @@ -0,0 +1,707 @@
>> >> +/* 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;
>> >> +}
>> >> +
>> >> +/* active_feature prefer to netdev->features */
>> >> +#define netdev_active_features_zero(ndev) \
>> >> +        netdev_features_zero(&ndev->features)
>> > netdev_features_t sometimes is being placed and used on the stack.
>> > I think it's better to pass just `netdev_features_t *` to those
>> > helpers, this way you wouldn't also need to create a new helper
>> > for each net_device::*_features.
>> My purpose of defining  helpers for each net_device::*_features is to
>> avoiding driver to change  net_device::*_features directly.
>
> But why? My point is that you have to create a whole bunch of
> copy'n'paste functions differing only by the &net_device field
> name.
>
I noticed that Jakub have done a lot work for avoiding driver to write 
netdev->dev_addr
directly. Also in earlier discuss, Saeed had suggested to hide hide the 
implementation
details and abstract it away from drivers using getters and manipulation 
APIs.
[https://lore.kernel.org/all/b335852ecaba3c86d1745b5021bb500798fc843b.camel@kernel.org/]


>>
>> >> +
>> >> +#define netdev_hw_features_zero(ndev) \
>> >> + netdev_features_zero(&ndev->hw_features)
>
> Oh BTW: wrap `ndev` in the netdev_features_zero() call into braces,
> `netdev_feature_zero(&(ndev)->hw_features)`, otherwise it may cause
> unwanted sneaky logical changes or build failures.
>
OK, will fix it.

>> >> +
>> >> +#define netdev_wanted_features_zero(ndev) \
>> > [...]
>> >
>> >> +#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);
>> > A small proposal: if you look at bitmap_and() for example, it
>> > returns 1 if the resulting bitmap is non-empty and 0 if it is. What
>> > about doing the same here? It would probably help to do reduce
>> > boilerplating in the drivers where we only want to know if there's
>> > anything left after masking.
>> > Same for xor, toggle etc.
>> Thanks for point this.  Return whether empty, then I can remove 
>> netdev_features_intersects
>> helpers. But there are also many places to use 'f1 & f2' as return 
>> value or input param, then
>> I need to define more temporay features to store the result, and then 
>> return the temporay
>> features or pass into it.
>
> No, netdev_features_intersects() is okay, leave it as it is. Just
> look on bitmap_*() prototypes and return its values when applicable.
>
OK, will follow the prototypes of bitmap_and and others.


>>
>> >> +}
>> >> +
>> >> +static inline void
>> >> +netdev_active_features_mask(struct net_device *ndev,
>> >> +                const netdev_features_t features)
>> >> +{
>> >> +    ndev->features = netdev_active_features_and(ndev, 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++)
>> > Nit: kernel is C11 now, you can do just `for (u32 i = 0; i ...`.
>> > (and yeah, it's better to use unsigned types when you don't plan
>> > to store negative values there).
>> ok, will fix it.
>>
>> >> +        netdev_feature_add(set->feature_bits[i], dst);
>> >> +}
>> > [...]
>> >
>> >> -- >> 2.33.0
>> > Thanks,
>> > Olek
>> >
>> > .
>
> Thanks,
> Olek
>
> .
>
Thanks,
Jian


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 02/36] net: replace general features macroes with global netdev_features variables
  2022-08-11 11:05       ` Alexander Lobakin
@ 2022-08-12 10:58         ` shenjian (K)
  0 siblings, 0 replies; 59+ messages in thread
From: shenjian (K) @ 2022-08-12 10:58 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, andrew, ecree.xilinx, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/8/11 19:05, Alexander Lobakin 写道:
> From: "shenjian (K)" <shenjian15@huawei.com>
> Date: Wed, 10 Aug 2022 20:01:15 +0800
>
>> 在 2022/8/10 17:58, Alexander Lobakin 写道:
>> > From: Jian Shen <shenjian15@huawei.com>
>> > Date: Wed, 10 Aug 2022 11:05:50 +0800
>> >
>> >> 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>
>> >> ---
>
> [...]
>
>> >> @@ -11362,6 +11363,86 @@ static struct pernet_operations 
>> __net_initdata default_device_ops = {
>> >>       .exit_batch = default_device_exit_batch,
>> >>   };
>> >>   >> +static void __init netdev_features_init(void)
>> > Given that you're creating a new file dedicated to netdev features,
>> > I'd place that initializer there. You can then declare its proto in
>> > net/core/dev.h.
>> I want to make sure it cann't be called outside net/core/dev.c, for some
>> drivers include net/core/dev.h, then they can see it.
>
> net/core/dev.h is internal, nobody outside net/core/ uses it and
> this was its purpose.
>
All right, will move it netdev_features.c
>>
>> >> +{
>> >> +    netdev_features_t features;
>> >> +
>> >> + 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_gso_feature_set_mask,
>> >> +                  &netdev_gso_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_gso_encap_feature_set,
>> >> +                  &netdev_gso_encap_all_features);
>> >> +
>> >> +    netdev_csum_gso_features_mask =
>> >> +        netdev_features_or(netdev_gso_features_mask,
>> >> +                   netdev_csum_features_mask);
>> > (I forgot to mention this in 01/36 ._.)
>> >
>> > As you're converting to bitmaps, you should probably avoid direct
>> > assignments. All the bitmap_*() modification functions take a pointer
>> > to the destination as a first argument. So it should be
>> >
>> > netdev_features_or(netdev_features_t *dst, const netdev_features_t 
>> *src1,
>> >            const netdev_features_t *src1);
>> The netdev_features_t will be convert to a structure which only 
>> contained
>> a feature bitmap. So assginement is ok.
>
> Yeah I realized it later, probably a good idea.
>
>>
>>
>> >> +
>> >> + netdev_features_set_array(&netif_f_one_for_all_feature_set,
>> >> +                  &netdev_one_for_all_features);
>> > Does it make sense to prefix features and the corresponding sets
>> > differently? Why not just 'netdev_' for both of them?
>> For all the feature bits are named "NETFI_F_XXX_BIT",
>
> Right, but then why are netdev_*_features prefixed with 'netdev',
> not 'netif_f'? :D Those sets are tied tightly with the feature
> structures, so I think they should have the same prefix. I'd go
> with 'netdev' for both.
>
ok, will prefix with 'netdev'

>>
>>
>> >> + netdev_features_set_array(&netif_f_all_for_all_feature_set,
>> >> +                  &netdev_all_for_all_features);
>
> [...]
>
>> >> -- >> 2.33.0
>> > Thanks,
>> > Olek
>> >
>> > .
>>
>> Thank,
>> Jian
>
> Thanks,
> Olek
>
> .
>
Thanks,
Jian

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t
  2022-08-11 13:07       ` Alexander Lobakin
  2022-08-11 15:13         ` Jakub Kicinski
@ 2022-08-12 11:30         ` shenjian (K)
  1 sibling, 0 replies; 59+ messages in thread
From: shenjian (K) @ 2022-08-12 11:30 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, andrew, ecree.xilinx, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/8/11 21:07, Alexander Lobakin 写道:
> From: "shenjian (K)" <shenjian15@huawei.com>
> Date: Wed, 10 Aug 2022 21:34:43 +0800
>
> BTW, you replied in HTML instead of plain text and korg mail servers
> rejected it. So non-Ccs can't see it. Just be aware that LKML
> accepts plain text only :)
>
>> 在 2022/8/10 19:35, Alexander Lobakin 写道:
>> > From: Jian Shen <shenjian15@huawei.com>
>> > Date: Wed, 10 Aug 2022 11:06:24 +0800
>> >
>> >> 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. Serveal macroes remained
>> >> temporarily, by some precompile dependency.
>> >>
>> >> 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>
>> >> ---
>> >>   drivers/net/ethernet/amazon/ena/ena_netdev.c  |  12 +-
>> >>   .../net/ethernet/intel/i40e/i40e_debugfs.c    |  12 +-
>> >>   .../ethernet/netronome/nfp/nfp_net_common.c   |   4 +-
>> >>   .../net/ethernet/pensando/ionic/ionic_lif.c   |   4 +-
>> >>   include/linux/netdev_features.h               | 101 ++----------
>> >>   include/linux/netdev_features_helper.h        | 149 
>> +++++++++++-------
>> >>   include/linux/netdevice.h                     |   7 +-
>> >>   include/linux/skbuff.h                        |   4 +-
>> >>   include/net/ip_tunnels.h                      |   2 +-
>> >>   lib/vsprintf.c                                |  11 +-
>> >>   net/ethtool/features.c                        |  96 ++++-------
>> >>   net/ethtool/ioctl.c                           |  46 ++++--
>> >>   net/mac80211/main.c                           |   3 +-
>> >>   13 files changed, 201 insertions(+), 250 deletions(-)
>> > [...]
>> >
>> >> -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;
>> >> -}
>> >> +#define NETIF_F_HW_VLAN_CTAG_TX
>> >> +#define NETIF_F_IPV6_CSUM
>> >> +#define NETIF_F_TSO
>> >> +#define NETIF_F_GSO
>> > Uhm, what are those empty definitions for? They look confusing.
>> I kept them temporary for some drivers use them like below:
>> for example in drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
>> #ifdef NETIF_F_HW_VLAN_CTAG_TX
>> #include <linux/if_vlan.h>
>> #endif
>>
>> So far I haven't got a good way to replace it.
>
> I believe such constructs sneaked in from some development/draft
> versions of the code, as those definitions are always here, so
> this is just redundant/pointless.
> Just remove those ifdefs and always include the file.
> The empty definitions you left in netdev_features.h are confusing,
> I'd not keep them.
>
OK, I will add a new patch to remove them.

>>
>> >>   >>   /* This goes for the MSB to the LSB through the set feature 
>> bits,
>> >>    * mask_addr should be a u64 and bit an int
>> >>    */
>
> [...]
>
>> >> +#define GSO_ENCAP_FEATURES (((u64)1 << NETIF_F_GSO_GRE_BIT) 
>> |        \
>> >> +                 ((u64)1 << NETIF_F_GSO_GRE_CSUM_BIT) |        \
>> >> +                 ((u64)1 << NETIF_F_GSO_IPXIP4_BIT) |        \
>> >> +                 ((u64)1 << NETIF_F_GSO_IPXIP6_BIT) |        \
>> >> +                 (((u64)1 << NETIF_F_GSO_UDP_TUNNEL_BIT) |    \
>> >> +                  ((u64)1 << NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT)))
>> > 1) 1ULL;
>> ok,will fix it
>>
>> > 2) what if we get a new GSO encap type which's bit will be higher
>> >     than 64?
>> So far I prefer to use this.  It's used to assgned to 
>> skb_shinfo(skb)->gso_type, which prototype
>> is 'unsigned int'.  Once new gso encap type introduced, we should 
>> extend the gso_type first.
>
> But ::gso_type accepts flags like %SKB_GSO_DODGY and so on, not
> netdev_features, doesn't it?
>
>>
>>
>> >> +
>> >>   #endif    /* _LINUX_NETDEV_FEATURES_H */
>
> [...]
>
>> >>   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;
>> > Yeah, so as I wrote previously, not a good idea to return a whole
>> > bitmap/structure.
>> >
>> > netdev_features_and(*dst, const *a, const *b)
>> > {
>> >     return bitmap_and(); // bitmap_and() actually returns useful value
>> > }
>> >
>> > I mean, 16 bytes (currently 8, but some new features will come
>> > pretty shortly, I'm sure) are probably okayish, but... let's see
>> > what other folks think, but even Linus wrote about this recently
>> > BTW.
>> Yes, Jakub also mentioned this.
>>
>> But there are many existed features interfaces(e.g. ndo_fix_features,
>> ndo_features_check), use netdev_features_t as return value. Then we
>> have to change their prototype.
>
> We have to do 12k lines of changes already :D
> You know, 16 bytes is probably fine to return directly and it will
> be enough for up to 128 features (+64 more comparing to the
> mainline). OTOH, using pointers removes that "what if/when", so
> it's more flexible in that term. So that's why I asked for other
> folks' opinions -- 2 PoVs doesn't seem enough here.
>

>>
>> second problem is for the helpers' definition. For example:
>> When we introduce helper like netdev_features_zero(netdev_features_t 
>> *features)
>> without change prototype of netdev_features_t.
>> once covert netdev_features_t from u64 to unsigned long *, then it 
>> becomes
>> netdev_features_zero(unsigned long **features), result in much 
>> redundant work
>> to adjust it to netdev_features_zero(unsigned long *features).
>
>>
>>
>> >>   }
>
> [...]
>
>> >>   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;
>> >> +    netdev_features_t *features;
>> > const? We're printing.
>> It will cause compile warning for bitmap_string use features->bits
>> as input param without "const" definition in its prototype.
>
> Oof, that's weird. I checked the function you mentioned and don't
> see any reason why it would require non-RO access to the bitmap it
> prints.
> Could you maybe please change its proto to take const bitmap, so
> that it won't complain on your code? As a separate patch going right
> before this one in your series.
>
OK,  will do it.

>> >>   >>       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);
>> >> +        features = (netdev_features_t *)addr;
>> > Casts are not needed when assigning from `void *`.
>> ok, will fix it
>> >> +        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, features->bits, spec, fmt);
>> >>   }
>
> [...]
>
>> >> -- >> 2.33.0
>> > That's my last review email for now. Insane amount of work, I'm glad
>> > someone did it finally. Thanks a lot!
>> >
>> > Olek
>> > .
>> Hi   Olek,
>> Grateful for your review.  You made a lot of valuable suggestions. I 
>> will
>> check and continue refine the patchset.
>>
>> Thanks again!
>>
>> Jian
>
> Thanks!
> Olek
> .
>
Thanks,
Jian


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t
  2022-08-11 15:13         ` Jakub Kicinski
@ 2022-08-12 11:43           ` shenjian (K)
  0 siblings, 0 replies; 59+ messages in thread
From: shenjian (K) @ 2022-08-12 11:43 UTC (permalink / raw)
  To: Jakub Kicinski, Alexander Lobakin
  Cc: davem, andrew, ecree.xilinx, hkallweit1, saeed, leon, netdev, linuxarm



在 2022/8/11 23:13, Jakub Kicinski 写道:
> On Thu, 11 Aug 2022 15:07:57 +0200 Alexander Lobakin wrote:
>
>>> Yes, Jakub also mentioned this.
>>>
>>> But there are many existed features interfaces(e.g. ndo_fix_features,
>>> ndo_features_check), use netdev_features_t as return value. Then we
>>> have to change their prototype.
>> We have to do 12k lines of changes already :D
>> You know, 16 bytes is probably fine to return directly and it will
>> be enough for up to 128 features (+64 more comparing to the
>> mainline). OTOH, using pointers removes that "what if/when", so
>> it's more flexible in that term. So that's why I asked for other
>> folks' opinions -- 2 PoVs doesn't seem enough here.
> >From a quick grep it seems like the and() is mostly used in some form
> of:
>
> 	features = and(features, mask);
>
> and we already have netdev_features_clear() which modifies its first
> argument. I'd also have and() update its first arg rather than return
> the result as a value.
ok, I will follow the behaviour of bitmap_and().

> It will require changing the prototype of
> ndo_features_check() :( But yeah, I reckon we shouldn't be putting of
> refactoring, best if we make all the changes at once than have to
> revisit this once the flags grow again and return by value starts to
> be a problem.
> .
>



Thanks,
Jian

^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2022-08-12 11:43 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-10  3:05 [RFCv7 PATCH net-next 00/36] net: extend the type of netdev_features_t to bitmap Jian Shen
2022-08-10  3:05 ` [RFCv7 PATCH net-next 01/36] net: introduce operation helpers for netdev features Jian Shen
2022-08-10  9:43   ` Alexander Lobakin
2022-08-10 11:32     ` shenjian (K)
2022-08-11 10:49       ` Alexander Lobakin
2022-08-12  2:39         ` shenjian (K)
2022-08-10  3:05 ` [RFCv7 PATCH net-next 02/36] net: replace general features macroes with global netdev_features variables Jian Shen
2022-08-10  9:58   ` Alexander Lobakin
2022-08-10 12:01     ` shenjian (K)
2022-08-11 11:05       ` Alexander Lobakin
2022-08-12 10:58         ` shenjian (K)
2022-08-10  3:05 ` [RFCv7 PATCH net-next 03/36] net: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET Jian Shen
2022-08-10 10:37   ` Alexander Lobakin
2022-08-10 12:15     ` shenjian (K)
2022-08-10  3:05 ` [RFCv7 PATCH net-next 04/36] net: sfc: replace const features initialization " Jian Shen
2022-08-10  3:05 ` [RFCv7 PATCH net-next 05/36] net: atlantic: replace const features initialization with NETDEV_FEATURE_SET Jian Shen
2022-08-10  3:05 ` [RFCv7 PATCH net-next 06/36] iwlwifi: " Jian Shen
2022-08-10  3:05 ` [RFCv7 PATCH net-next 07/36] net: ethernet: mtk_eth_soc: " Jian Shen
2022-08-10  3:05 ` [RFCv7 PATCH net-next 08/36] ravb: " Jian Shen
2022-08-10  3:05 ` [RFCv7 PATCH net-next 09/36] test_bpf: " Jian Shen
2022-08-10  3:05 ` [RFCv7 PATCH net-next 10/36] treewide: replace NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK by netdev_csum_gso_features_mask Jian Shen
2022-08-10  3:05 ` [RFCv7 PATCH net-next 11/36] treewide: replace NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM by netdev_ip_csum_features Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 12/36] treewide: replace NETIF_F_TSO | NETIF_F_TSO6 by netdev_general_tso_features Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 13/36] treewide: replace VLAN tag feature array by const vlan features Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 14/36] net: simplify the netdev features expressions for xxx_gso_segment Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 15/36] treewide: simplify the netdev features expression Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 16/36] treewide: use replace features '0' by netdev_empty_features Jian Shen
2022-08-10 10:48   ` Alexander Lobakin
2022-08-10 12:25     ` shenjian (K)
2022-08-11 12:35       ` Alexander Lobakin
2022-08-10  3:06 ` [RFCv7 PATCH net-next 17/36] treewide: adjust features initialization Jian Shen
2022-08-10 10:58   ` Alexander Lobakin
2022-08-10 14:06     ` shenjian (K)
2022-08-10  3:06 ` [RFCv7 PATCH net-next 18/36] net: mlx4: adjust the net device feature relative macroes Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 19/36] net: mlx5e: adjust " Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 20/36] net: mlxsw: adjust input parameter for function mlxsw_sp_handle_feature Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 21/36] net: iavf: adjust net device features relative macroes Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 22/36] net: core: adjust netdev_sync_xxx_features Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 23/36] net: adjust the build check for net_gso_ok() Jian Shen
2022-08-10 11:09   ` Alexander Lobakin
2022-08-10 14:41     ` shenjian (K)
2022-08-10  3:06 ` [RFCv7 PATCH net-next 24/36] treewide: use netdev_feature_add helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 25/36] treewide: use netdev_features_or/set helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 26/36] treewide: use netdev_feature_change helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 27/36] treewide: use netdev_feature_del helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 28/36] treewide: use netdev_features_andnot and netdev_features_clear helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 29/36] treewide: use netdev_features_xor helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 30/36] treewide: use netdev_feature_test helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 31/36] treewide: use netdev_features_intersects helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 32/36] net: use netdev_features_and and netdev_features_mask helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 33/36] treewide: use netdev_features_subset helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 34/36] treewide: use netdev_features_equal helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 35/36] treewide: use netdev_features_empty helpers Jian Shen
2022-08-10  3:06 ` [RFCv7 PATCH net-next 36/36] net: redefine the prototype of netdev_features_t Jian Shen
2022-08-10 11:35   ` Alexander Lobakin
     [not found]     ` <3df89822-7dec-c01e-0df9-15b8e6f7d4e5@huawei.com>
2022-08-11 13:07       ` Alexander Lobakin
2022-08-11 15:13         ` Jakub Kicinski
2022-08-12 11:43           ` shenjian (K)
2022-08-12 11:30         ` shenjian (K)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).