All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap
@ 2022-09-18  9:42 Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 01/55] net: introduce operation helpers for netdev features Jian Shen
                   ` (56 more replies)
  0 siblings, 57 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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 55]

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, 54]

For the prototype of netdev_features_t is larger than 8 bytes, so it's
not recommend to be passed direclty. There are many function in kernel
use netdev_features_t as parameter or return value, change the prototype
of these functions by using netdev_features_t *. [patch 36~53]

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

The former discussion please see [1][2][3][4][5][6].
[1]:https://www.spinics.net/lists/netdev/msg769952.html
[2]:https://www.spinics.net/lists/netdev/msg777764.html
[3]:https://www.spinics.net/lists/netdev/msg778921.html
[4]:https://www.spinics.net/lists/netdev/msg809293.html
[5]:https://www.spinics.net/lists/netdev/msg814349.html
[6]: https://www.spinics.net/lists/netdev/msg838709.html

ChangeLog:
V7->V8:
fix comments from Alexander Lobakin:
change the prototype of netdev_features_and and other similar helpers
reduce the using of netdev_emtpy_features
fix some typo issue
use netdev_features_set/clear_set to replace the definition of feature set
refine the build check for net_gso_ok()
change the prototype of functions using netdev_features_t
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 (55):
  net: introduce operation helpers for netdev features
  net: replace general features macroes with global netdev_features
    variables
  treewide: 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: adjust the handle for netdev features '0'
  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/clear helpers
  treewide: use netdev_features_xor helpers
  treewide: use netdev_feature_test helpers
  treewide: use netdev_features_intersects helpers
  treewide: use netdev_features_and/mask helpers
  treewide: use netdev_features_subset helpers
  treewide: use netdev_features_equal helpers
  treewide: use netdev_features_empty helpers
  net: adjust the prototype of netdev_increment_features()
  net: adjust the prototype of netdev_add_tso_features()
  net: core: adjust prototype of several functions used in
    net/core/dev.c
  net: adjust the prototype of netdev_intersect_features()
  net: adjust the prototype of netif_skb_features()
  net: adjust the prototype of xxx_features_check()
  net: adjust the prototype of ndo_fix_features
  net: adjust the prototype of xxx_set_features()
  net: adjust the prototype fo xxx_gso_segment() family
  net: vlan: adjust the prototype of vlan functions
  net: adjust the prototype of netif_needs_gso() and relative functions
  net: adjust the prototype of skb_needs_linearize()
  net: adjust the prototype of validate_xmit_xfrm() and relative
    functions
  net: adjust the prototype of can_checksum_protocol()
  net: tap: adjust the prototype of update_features()
  net: mlx4: adjust the prototype of check_csum() and
    mlx4_en_update_loopback_state()
  net: gve: adjust the prototype of gve_rx(), gve_clean_rx_done() and
    gve_rx_complete_skb()
  net: sfc: adjust the prototype of xxx_supported_features()
  treewide: use netdev_features_copy helpers
  net: redefine the prototype of netdev_features_t

 arch/um/drivers/vector_kern.c                 |  16 +-
 arch/um/drivers/vector_transports.c           |  32 +-
 drivers/firewire/net.c                        |   4 +-
 drivers/hsi/clients/ssi_protocol.c            |   2 +-
 drivers/infiniband/hw/hfi1/netdev.h           |   1 +
 drivers/infiniband/hw/hfi1/vnic_main.c        |   8 +-
 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     |  19 +-
 drivers/infiniband/ulp/ipoib/ipoib_verbs.c    |   2 +-
 drivers/misc/sgi-xp/xpnet.c                   |   3 +-
 drivers/net/amt.c                             |  13 +-
 drivers/net/bareudp.c                         |  15 +-
 drivers/net/bonding/bond_main.c               | 143 ++--
 drivers/net/bonding/bond_options.c            |   8 +-
 drivers/net/caif/caif_serial.c                |   3 +-
 drivers/net/can/dev/dev.c                     |   4 +-
 drivers/net/dsa/xrs700x/xrs700x.c             |  17 +-
 drivers/net/dummy.c                           |  14 +-
 drivers/net/ethernet/3com/3c59x.c             |  10 +-
 drivers/net/ethernet/3com/typhoon.c           |  31 +-
 drivers/net/ethernet/adaptec/starfire.c       |   9 +-
 drivers/net/ethernet/aeroflex/greth.c         |  12 +-
 drivers/net/ethernet/alacritech/slicoss.c     |   6 +-
 drivers/net/ethernet/alteon/acenic.c          |   9 +-
 drivers/net/ethernet/altera/altera_tse_main.c |  10 +-
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  47 +-
 drivers/net/ethernet/amd/amd8111e.c           |   3 +-
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c      |  14 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |  81 +-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c     |  57 +-
 drivers/net/ethernet/amd/xgbe/xgbe.h          |   1 +
 drivers/net/ethernet/apm/xgene-v2/main.c      |   5 +-
 drivers/net/ethernet/apm/xgene-v2/main.h      |   1 +
 .../net/ethernet/apm/xgene/xgene_enet_main.c  |  19 +-
 .../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  |  92 ++-
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |  23 +-
 .../net/ethernet/aquantia/atlantic/aq_nic.h   |   6 +-
 .../net/ethernet/aquantia/atlantic/aq_ring.c  |   2 +-
 .../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       |  20 +-
 drivers/net/ethernet/atheros/atl1c/atl1c.h    |   1 +
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  44 +-
 drivers/net/ethernet/atheros/atl1e/atl1e.h    |   1 +
 .../net/ethernet/atheros/atl1e/atl1e_main.c   |  59 +-
 drivers/net/ethernet/atheros/atlx/atl1.c      |  21 +-
 drivers/net/ethernet/atheros/atlx/atl2.c      |  39 +-
 drivers/net/ethernet/atheros/atlx/atlx.c      |  27 +-
 drivers/net/ethernet/broadcom/b44.c           |   3 +-
 drivers/net/ethernet/broadcom/bcmsysport.c    |  36 +-
 drivers/net/ethernet/broadcom/bgmac.c         |  10 +-
 drivers/net/ethernet/broadcom/bnx2.c          |  52 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c   |  60 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h   |   5 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  | 101 ++-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 157 ++--
 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 |  10 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c |   4 +-
 .../net/ethernet/broadcom/genet/bcmgenet.c    |  17 +-
 drivers/net/ethernet/broadcom/tg3.c           |  68 +-
 drivers/net/ethernet/brocade/bna/bnad.c       |  45 +-
 drivers/net/ethernet/cadence/macb_main.c      |  90 ++-
 drivers/net/ethernet/calxeda/xgmac.c          |  23 +-
 .../net/ethernet/cavium/liquidio/lio_core.c   |   4 +-
 .../net/ethernet/cavium/liquidio/lio_main.c   | 147 ++--
 .../ethernet/cavium/liquidio/lio_vf_main.c    | 117 +--
 .../ethernet/cavium/liquidio/octeon_network.h |   4 +-
 .../net/ethernet/cavium/thunder/nicvf_main.c  |  52 +-
 .../ethernet/cavium/thunder/nicvf_queues.c    |   7 +-
 .../ethernet/cavium/thunder/nicvf_queues.h    |   2 +-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  51 +-
 drivers/net/ethernet/chelsio/cxgb/sge.c       |  10 +-
 drivers/net/ethernet/chelsio/cxgb/sge.h       |   2 +-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  73 +-
 drivers/net/ethernet/chelsio/cxgb3/sge.c      |   8 +-
 .../net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c   |  16 +-
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   | 110 +--
 .../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      |   3 +-
 drivers/net/ethernet/cisco/enic/enic_main.c   |  60 +-
 drivers/net/ethernet/cortina/gemini.c         |  28 +-
 drivers/net/ethernet/davicom/dm9000.c         |  23 +-
 drivers/net/ethernet/davicom/dm9051.c         |   2 +-
 drivers/net/ethernet/dnet.c                   |   3 +-
 drivers/net/ethernet/ec_bhf.c                 |   3 +-
 drivers/net/ethernet/emulex/benet/be_main.c   |  62 +-
 drivers/net/ethernet/engleder/tsnep_main.c    |  16 +-
 drivers/net/ethernet/ethoc.c                  |   3 +-
 drivers/net/ethernet/faraday/ftgmac100.c      |  34 +-
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  21 +-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |  42 +-
 .../ethernet/freescale/dpaa2/dpaa2-switch.c   |   8 +-
 .../ethernet/freescale/dpaa2/dpaa2-switch.h   |   1 +
 drivers/net/ethernet/freescale/enetc/enetc.c  |  29 +-
 drivers/net/ethernet/freescale/enetc/enetc.h  |   2 +-
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  48 +-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  31 +-
 drivers/net/ethernet/freescale/fec_main.c     |  31 +-
 .../ethernet/freescale/fs_enet/fs_enet-main.c |   2 +-
 drivers/net/ethernet/freescale/gianfar.c      |  34 +-
 drivers/net/ethernet/freescale/gianfar.h      |   2 +-
 .../net/ethernet/freescale/gianfar_ethtool.c  |  12 +-
 .../ethernet/fungible/funeth/funeth_ktls.c    |   4 +-
 .../ethernet/fungible/funeth/funeth_main.c    |  47 +-
 .../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    |  28 +-
 drivers/net/ethernet/google/gve/gve_rx.c      |  10 +-
 drivers/net/ethernet/google/gve/gve_rx_dqo.c  |  11 +-
 drivers/net/ethernet/hisilicon/hix5hd2_gmac.c |   8 +-
 drivers/net/ethernet/hisilicon/hns/hns_enet.c |  52 +-
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   | 107 +--
 .../ethernet/hisilicon/hns3/hns3_ethtool.c    |   4 +-
 .../net/ethernet/huawei/hinic/hinic_main.c    | 104 ++-
 drivers/net/ethernet/huawei/hinic/hinic_rx.c  |   4 +-
 drivers/net/ethernet/ibm/ehea/ehea_main.c     |  22 +-
 drivers/net/ethernet/ibm/emac/core.c          |   7 +-
 drivers/net/ethernet/ibm/ibmveth.c            |  66 +-
 drivers/net/ethernet/ibm/ibmvnic.c            |  57 +-
 drivers/net/ethernet/intel/e100.c             |  25 +-
 drivers/net/ethernet/intel/e1000/e1000.h      |   1 +
 drivers/net/ethernet/intel/e1000/e1000_main.c |  85 +-
 drivers/net/ethernet/intel/e1000e/netdev.c    | 108 +--
 drivers/net/ethernet/intel/fm10k/fm10k_main.c |   6 +-
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  59 +-
 drivers/net/ethernet/intel/fm10k/fm10k_pci.c  |  11 +-
 drivers/net/ethernet/intel/i40e/i40e.h        |   2 +-
 .../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        |   5 +-
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 307 ++++----
 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_lib.c      |   5 +-
 drivers/net/ethernet/intel/ice/ice_main.c     | 285 ++++---
 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 |  11 +-
 drivers/net/ethernet/intel/igb/igb_ethtool.c  |   2 +-
 drivers/net/ethernet/intel/igb/igb_main.c     | 158 ++--
 drivers/net/ethernet/intel/igbvf/netdev.c     | 100 +--
 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     | 139 ++--
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  46 +-
 .../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 |   7 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c  |   2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 224 +++---
 .../net/ethernet/intel/ixgbe/ixgbe_sriov.c    |   6 +-
 drivers/net/ethernet/intel/ixgbevf/ipsec.c    |  16 +-
 drivers/net/ethernet/intel/ixgbevf/ixgbevf.h  |   1 +
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 111 +--
 drivers/net/ethernet/jme.c                    |  55 +-
 drivers/net/ethernet/marvell/mv643xx_eth.c    |  18 +-
 drivers/net/ethernet/marvell/mvneta.c         |  22 +-
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  58 +-
 .../ethernet/marvell/octeon_ep/octep_main.c   |   6 +-
 .../marvell/octeontx2/nic/otx2_common.c       |  31 +-
 .../marvell/octeontx2/nic/otx2_common.h       |   2 +-
 .../marvell/octeontx2/nic/otx2_ethtool.c      |   4 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  59 +-
 .../marvell/octeontx2/nic/otx2_txrx.c         |   6 +-
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  30 +-
 .../ethernet/marvell/prestera/prestera_main.c |   4 +-
 drivers/net/ethernet/marvell/skge.c           |  12 +-
 drivers/net/ethernet/marvell/sky2.c           |  81 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  80 +-
 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  |  11 +-
 .../net/ethernet/mellanox/mlx4/en_netdev.c    | 181 ++---
 .../net/ethernet/mellanox/mlx4/en_resources.c |   4 +-
 drivers/net/ethernet/mellanox/mlx4/en_rx.c    |  18 +-
 .../net/ethernet/mellanox/mlx4/en_selftest.c  |   4 +-
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h  |   9 +-
 drivers/net/ethernet/mellanox/mlx5/core/en.h  |   8 +-
 .../mellanox/mlx5/core/en_accel/ipsec.c       |  16 +-
 .../mellanox/mlx5/core/en_accel/ipsec_rxtx.h  |  16 +-
 .../mellanox/mlx5/core/en_accel/ktls.c        |  10 +-
 .../mellanox/mlx5/core/en_accel/macsec.c      |   6 +-
 .../ethernet/mellanox/mlx5/core/en_ethtool.c  |   2 +-
 .../net/ethernet/mellanox/mlx5/core/en_fs.c   |   7 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 277 +++----
 .../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 |  24 +-
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  40 +-
 drivers/net/ethernet/micrel/ksz884x.c         |  13 +-
 drivers/net/ethernet/microchip/lan743x_main.c |  14 +-
 .../ethernet/microchip/lan966x/lan966x_fdma.c |   2 +-
 .../ethernet/microchip/lan966x/lan966x_main.c |   5 +-
 .../ethernet/microchip/sparx5/sparx5_fdma.c   |   2 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c |  17 +-
 drivers/net/ethernet/mscc/ocelot.c            |   2 +-
 drivers/net/ethernet/mscc/ocelot_net.c        |  22 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  33 +-
 drivers/net/ethernet/natsemi/ns83820.c        |  11 +-
 drivers/net/ethernet/neterion/s2io.c          |  32 +-
 .../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 +-
 .../ethernet/netronome/nfp/nfp_net_common.c   | 135 ++--
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  69 +-
 drivers/net/ethernet/netronome/nfp/nfp_port.c |   6 +-
 drivers/net/ethernet/netronome/nfp/nfp_port.h |   3 +-
 drivers/net/ethernet/ni/nixge.c               |   4 +-
 drivers/net/ethernet/nvidia/forcedeth.c       |  74 +-
 .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  15 +-
 .../ethernet/oki-semi/pch_gbe/pch_gbe_param.c |   4 +-
 drivers/net/ethernet/pasemi/pasemi_mac.c      |   6 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 114 +--
 .../net/ethernet/pensando/ionic/ionic_txrx.c  |   6 +-
 .../ethernet/qlogic/netxen/netxen_nic_init.c  |   4 +-
 .../ethernet/qlogic/netxen/netxen_nic_main.c  |  47 +-
 drivers/net/ethernet/qlogic/qede/qede.h       |  10 +-
 .../net/ethernet/qlogic/qede/qede_ethtool.c   |   3 +-
 .../net/ethernet/qlogic/qede/qede_filter.c    |  20 +-
 drivers/net/ethernet/qlogic/qede/qede_fp.c    |  21 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c  |  67 +-
 drivers/net/ethernet/qlogic/qla3xxx.c         |   6 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h   |   7 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  72 +-
 .../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     |  28 +-
 .../ethernet/qualcomm/rmnet/rmnet_map_data.c  |   7 +-
 .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c   |  10 +-
 drivers/net/ethernet/realtek/8139cp.c         |  45 +-
 drivers/net/ethernet/realtek/8139too.c        |  28 +-
 drivers/net/ethernet/realtek/r8169_main.c     |  91 +--
 drivers/net/ethernet/renesas/ravb.h           |   7 +-
 drivers/net/ethernet/renesas/ravb_main.c      |  43 +-
 drivers/net/ethernet/renesas/sh_eth.c         |  25 +-
 drivers/net/ethernet/rocker/rocker_main.c     |   4 +-
 .../net/ethernet/samsung/sxgbe/sxgbe_common.h |   7 +-
 .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |  21 +-
 drivers/net/ethernet/sfc/ef10.c               |  35 +-
 drivers/net/ethernet/sfc/ef100_netdev.c       |  11 +-
 drivers/net/ethernet/sfc/ef100_nic.c          |  31 +-
 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                |  58 +-
 drivers/net/ethernet/sfc/efx_common.c         |  38 +-
 drivers/net/ethernet/sfc/efx_common.h         |   6 +-
 drivers/net/ethernet/sfc/falcon/efx.c         |  59 +-
 drivers/net/ethernet/sfc/falcon/efx.h         |   3 +
 drivers/net/ethernet/sfc/falcon/falcon.c      |   4 +-
 drivers/net/ethernet/sfc/falcon/net_driver.h  |   8 +-
 drivers/net/ethernet/sfc/falcon/rx.c          |   4 +-
 drivers/net/ethernet/sfc/mcdi_filters.c       |  17 +-
 drivers/net/ethernet/sfc/mcdi_port_common.c   |   2 +-
 drivers/net/ethernet/sfc/net_driver.h         |   8 +-
 drivers/net/ethernet/sfc/rx.c                 |   2 +-
 drivers/net/ethernet/sfc/rx_common.c          |   4 +-
 drivers/net/ethernet/sfc/rx_common.h          |   4 +
 drivers/net/ethernet/sfc/siena/efx.c          |  46 +-
 drivers/net/ethernet/sfc/siena/efx.h          |   2 +
 drivers/net/ethernet/sfc/siena/efx_common.c   |  40 +-
 drivers/net/ethernet/sfc/siena/efx_common.h   |   7 +-
 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   |   8 +-
 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    |   4 +-
 drivers/net/ethernet/sfc/tx_common.c          |   4 +-
 drivers/net/ethernet/sgi/ioc3-eth.c           |  10 +-
 drivers/net/ethernet/silan/sc92031.c          |   7 +-
 drivers/net/ethernet/socionext/netsec.c       |  14 +-
 drivers/net/ethernet/socionext/sni_ave.c      |   7 +-
 .../net/ethernet/stmicro/stmmac/dwmac4_core.c |   2 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  56 +-
 .../stmicro/stmmac/stmmac_selftests.c         |   4 +-
 drivers/net/ethernet/sun/cassini.c            |   6 +-
 drivers/net/ethernet/sun/ldmvsw.c             |   5 +-
 drivers/net/ethernet/sun/niu.c                |  12 +-
 drivers/net/ethernet/sun/sungem.c             |  11 +-
 drivers/net/ethernet/sun/sunhme.c             |  13 +-
 drivers/net/ethernet/sun/sunvnet.c            |   7 +-
 drivers/net/ethernet/sun/sunvnet_common.c     |   5 +-
 .../net/ethernet/synopsys/dwc-xlgmac-common.c |  29 +-
 drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c |  14 +-
 .../net/ethernet/synopsys/dwc-xlgmac-net.c    |  34 +-
 drivers/net/ethernet/synopsys/dwc-xlgmac.h    |   1 +
 drivers/net/ethernet/tehuti/tehuti.c          |  22 +-
 drivers/net/ethernet/tehuti/tehuti.h          |   1 +
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  19 +-
 drivers/net/ethernet/ti/cpsw.c                |   7 +-
 drivers/net/ethernet/ti/cpsw_new.c            |   9 +-
 drivers/net/ethernet/ti/netcp_core.c          |   8 +-
 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          |   8 +-
 drivers/net/ethernet/via/via-velocity.c       |  13 +-
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c |   3 +-
 .../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   |  39 +-
 .../net/ethernet/xilinx/xilinx_axienet_main.c |   8 +-
 drivers/net/fjes/fjes_main.c                  |   3 +-
 drivers/net/geneve.c                          |  16 +-
 drivers/net/gtp.c                             |   2 +-
 drivers/net/hamradio/bpqether.c               |   4 +-
 drivers/net/hyperv/hyperv_net.h               |   6 +-
 drivers/net/hyperv/netvsc_bpf.c               |   2 +-
 drivers/net/hyperv/netvsc_drv.c               |  62 +-
 drivers/net/hyperv/rndis_filter.c             |  27 +-
 drivers/net/ifb.c                             |  25 +-
 drivers/net/ipa/ipa_modem.c                   |   4 +-
 drivers/net/ipvlan/ipvlan_main.c              |  87 ++-
 drivers/net/ipvlan/ipvtap.c                   |  13 +-
 drivers/net/loopback.c                        |  22 +-
 drivers/net/macsec.c                          |  56 +-
 drivers/net/macvlan.c                         |  99 ++-
 drivers/net/macvtap.c                         |  13 +-
 drivers/net/net_failover.c                    |  76 +-
 drivers/net/netdevsim/ipsec.c                 |  12 +-
 drivers/net/netdevsim/netdev.c                |  16 +-
 drivers/net/netdevsim/netdevsim.h             |   1 +
 drivers/net/nlmon.c                           |   8 +-
 drivers/net/ntb_netdev.c                      |   6 +-
 drivers/net/ppp/ppp_generic.c                 |   2 +-
 drivers/net/rionet.c                          |   4 +-
 drivers/net/tap.c                             |  48 +-
 drivers/net/team/team.c                       |  97 ++-
 drivers/net/thunderbolt.c                     |  11 +-
 drivers/net/tun.c                             |  55 +-
 drivers/net/usb/aqc111.c                      |  65 +-
 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                     |  49 +-
 drivers/net/usb/r8152.c                       |  78 +-
 drivers/net/usb/smsc75xx.c                    |  18 +-
 drivers/net/usb/smsc95xx.c                    |  21 +-
 drivers/net/veth.c                            |  78 +-
 drivers/net/virtio_net.c                      |  62 +-
 drivers/net/vmxnet3/vmxnet3_drv.c             |  76 +-
 drivers/net/vmxnet3/vmxnet3_ethtool.c         | 108 ++-
 drivers/net/vmxnet3/vmxnet3_int.h             |  12 +-
 drivers/net/vrf.c                             |  22 +-
 drivers/net/vsockmon.c                        |   7 +-
 drivers/net/vxlan/vxlan_core.c                |  18 +-
 drivers/net/wireguard/device.c                |  22 +-
 drivers/net/wireless/ath/ath10k/mac.c         |   8 +-
 drivers/net/wireless/ath/ath11k/mac.c         |   5 +-
 drivers/net/wireless/ath/ath6kl/core.h        |   1 +
 drivers/net/wireless/ath/ath6kl/main.c        |  15 +-
 drivers/net/wireless/ath/ath6kl/txrx.c        |   4 +-
 drivers/net/wireless/ath/wil6210/netdev.c     |  11 +-
 .../broadcom/brcm80211/brcmfmac/core.c        |   4 +-
 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  |  30 +
 .../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  |  23 +
 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   |  20 +-
 .../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                    |  48 +-
 drivers/s390/block/dasd_devmap.c              |   2 +-
 drivers/s390/net/qeth_core.h                  |   9 +-
 drivers/s390/net/qeth_core_main.c             | 132 ++--
 drivers/s390/net/qeth_l2_main.c               |  34 +-
 drivers/s390/net/qeth_l3_main.c               |  44 +-
 drivers/scsi/fcoe/fcoe.c                      |  12 +-
 drivers/staging/octeon/ethernet.c             |   6 +-
 drivers/staging/qlge/qlge_main.c              |  58 +-
 drivers/usb/gadget/function/f_phonet.c        |   3 +-
 include/linux/if_tap.h                        |   3 +-
 include/linux/if_vlan.h                       |  27 +-
 include/linux/netdev_feature_helpers.h        | 724 ++++++++++++++++++
 include/linux/netdev_features.h               | 178 ++---
 include/linux/netdevice.h                     | 175 +++--
 include/linux/skbuff.h                        |  79 +-
 include/linux/tcp.h                           |   1 +
 include/net/bonding.h                         |   5 +-
 include/net/inet_common.h                     |   2 +-
 include/net/ip_tunnels.h                      |   3 +-
 include/net/net_failover.h                    |   8 +-
 include/net/pkt_cls.h                         |   2 +-
 include/net/sock.h                            |   7 +-
 include/net/tcp.h                             |   2 +-
 include/net/udp.h                             |  13 +-
 include/net/udp_tunnel.h                      |   8 +-
 include/net/vxlan.h                           |  16 +-
 include/net/xfrm.h                            |  11 +-
 lib/test_bpf.c                                |  37 +-
 lib/vsprintf.c                                |   9 +-
 net/8021q/vlan.c                              |  10 +-
 net/8021q/vlan.h                              |  24 +-
 net/8021q/vlan_core.c                         |   4 +-
 net/8021q/vlan_dev.c                          |  55 +-
 net/batman-adv/soft-interface.c               |   6 +-
 net/bridge/br_device.c                        |  26 +-
 net/bridge/br_if.c                            |  17 +-
 net/bridge/br_private.h                       |   3 +-
 net/core/Makefile                             |   2 +-
 net/core/dev.c                                | 411 +++++-----
 net/core/dev.h                                |   2 +
 net/core/gro.c                                |   5 +-
 net/core/netdev_features.c                    | 226 ++++++
 net/core/netpoll.c                            |   4 +-
 net/core/pktgen.c                             |   6 +-
 net/core/skbuff.c                             |  22 +-
 net/core/skmsg.c                              |   2 +-
 net/core/sock.c                               |  16 +-
 net/dccp/ipv4.c                               |   2 +-
 net/dccp/ipv6.c                               |   8 +-
 net/dsa/slave.c                               |  25 +-
 net/ethtool/common.h                          |   1 +
 net/ethtool/features.c                        | 126 ++-
 net/ethtool/ioctl.c                           | 136 ++--
 net/hsr/hsr_device.c                          |  37 +-
 net/hsr/hsr_forward.c                         |   8 +-
 net/hsr/hsr_framereg.c                        |   2 +-
 net/hsr/hsr_slave.c                           |   2 +-
 net/ieee802154/6lowpan/core.c                 |   2 +-
 net/ieee802154/core.c                         |  15 +-
 net/ipv4/af_inet.c                            |  13 +-
 net/ipv4/esp4_offload.c                       |  42 +-
 net/ipv4/gre_offload.c                        |  12 +-
 net/ipv4/ip_gre.c                             |  31 +-
 net/ipv4/ip_output.c                          |  24 +-
 net/ipv4/ip_tunnel.c                          |   3 +-
 net/ipv4/ip_vti.c                             |   2 +-
 net/ipv4/ipip.c                               |  20 +-
 net/ipv4/ipmr.c                               |   2 +-
 net/ipv4/tcp.c                                |  10 +-
 net/ipv4/tcp_ipv4.c                           |   2 +-
 net/ipv4/tcp_offload.c                        |  11 +-
 net/ipv4/udp_offload.c                        |  47 +-
 net/ipv6/af_inet6.c                           |   2 +-
 net/ipv6/esp6_offload.c                       |  36 +-
 net/ipv6/inet6_connection_sock.c              |   2 +-
 net/ipv6/ip6_gre.c                            |  23 +-
 net/ipv6/ip6_offload.c                        |  14 +-
 net/ipv6/ip6_output.c                         |  20 +-
 net/ipv6/ip6_tunnel.c                         |  22 +-
 net/ipv6/ip6mr.c                              |   2 +-
 net/ipv6/sit.c                                |  22 +-
 net/ipv6/tcp_ipv6.c                           |   2 +-
 net/ipv6/tcpv6_offload.c                      |   2 +-
 net/ipv6/udp_offload.c                        |  13 +-
 net/l2tp/l2tp_eth.c                           |   2 +-
 net/mac80211/ieee80211_i.h                    |  13 +-
 net/mac80211/iface.c                          |   9 +-
 net/mac80211/main.c                           |  24 +-
 net/mac80211/tx.c                             |   4 +-
 net/mpls/mpls_gso.c                           |   7 +-
 net/netfilter/ipvs/ip_vs_proto_sctp.c         |   3 +-
 net/netfilter/nfnetlink_queue.c               |   5 +-
 net/nsh/nsh.c                                 |  10 +-
 net/openvswitch/datapath.c                    |  10 +-
 net/openvswitch/vport-internal_dev.c          |  22 +-
 net/phonet/pep-gprs.c                         |   4 +-
 net/sched/sch_cake.c                          |   6 +-
 net/sched/sch_netem.c                         |   6 +-
 net/sched/sch_taprio.c                        |   6 +-
 net/sched/sch_tbf.c                           |   7 +-
 net/sctp/offload.c                            |  13 +-
 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                        |  40 +-
 net/xfrm/xfrm_interface.c                     |  16 +-
 net/xfrm/xfrm_output.c                        |   9 +-
 508 files changed, 8214 insertions(+), 5558 deletions(-)
 create mode 100644 include/linux/netdev_feature_helpers.h
 create mode 100644 net/core/netdev_features.c

-- 
2.33.0


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

* [RFCv8 PATCH net-next 01/55] net: introduce operation helpers for netdev features
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-20 20:10   ` Jakub Kicinski
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables Jian Shen
                   ` (55 subsequent siblings)
  56 siblings, 1 reply; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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, follow the prototype changes. For the new type
netdev_features_t maybe large than 8 bytes, use netdev_features_t
pointer as parameter.

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>
---
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |   1 +
 include/linux/netdev_feature_helpers.h        | 607 ++++++++++++++++++
 include/linux/netdev_features.h               |  11 +
 include/linux/netdevice.h                     |  48 +-
 net/8021q/vlan_dev.c                          |   1 +
 net/core/dev.c                                |   1 +
 6 files changed, 651 insertions(+), 18 deletions(-)
 create mode 100644 include/linux/netdev_feature_helpers.h

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 8b77582bdfa0..8023a3f0d43b 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_feature_helpers.h>
 #include <net/dst_metadata.h>
 
 #include "nfpcore/nfp_cpp.h"
diff --git a/include/linux/netdev_feature_helpers.h b/include/linux/netdev_feature_helpers.h
new file mode 100644
index 000000000000..4bb5de61e4e9
--- /dev/null
+++ b/include/linux/netdev_feature_helpers.h
@@ -0,0 +1,607 @@
+/* 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;
+}
+
+#define netdev_features_zero(features) __netdev_features_zero(&(features))
+
+/* 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;
+}
+
+#define netdev_features_fill(features) __netdev_features_fill(&(features))
+
+static inline bool __netdev_features_empty(const netdev_features_t *src)
+{
+	return *src == 0;
+}
+
+#define netdev_features_empty(features) __netdev_features_empty(&(features))
+
+#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 *feats1,
+					   const netdev_features_t *feats2)
+{
+	return *feats1 == *feats2;
+}
+
+#define netdev_features_equal(feat1, feat2)	\
+			__netdev_features_equal(&(feat1), &(feat2))
+
+#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 bool
+__netdev_features_and(netdev_features_t *dst, const netdev_features_t *a,
+		      const netdev_features_t *b)
+{
+	*dst = *a & *b;
+	return *dst != 0;
+}
+
+#define netdev_features_and(dst, a, b) __netdev_features_and(&(dst), &(a), &(b))
+
+#define netdev_active_features_and(ndev, a, b) \
+		netdev_features_and((ndev)->features, a, b)
+
+#define netdev_hw_features_and(ndev, a, b) \
+		netdev_features_and((ndev)->hw_features, a, b)
+
+#define netdev_wanted_features_and(ndev, a, b) \
+		netdev_features_and((ndev)->wanted_features, a, b)
+
+#define netdev_vlan_features_and(ndev, a, b) \
+		netdev_features_and((ndev)->vlan_features, a, b)
+
+#define netdev_hw_enc_features_and(ndev, a, b) \
+		netdev_features_and((ndev)->hw_enc_features, a, b)
+
+#define netdev_mpls_features_and(ndev, a, b) \
+		netdev_features_and((ndev)->mpls_features, a, b)
+
+#define netdev_gso_partial_features_and(ndev, a, b) \
+		netdev_features_and((ndev)->gso_partial_features, a, b)
+
+/* helpers for netdev features '&=' operation */
+static inline bool
+__netdev_features_mask(netdev_features_t *dst,
+		       const netdev_features_t *features)
+{
+	return __netdev_features_and(dst, dst, features);
+}
+
+#define netdev_features_mask(dst, __features)	\
+	__netdev_features_mask(&(dst), &(__features))
+
+#define netdev_active_features_mask(ndev, __features) \
+		netdev_features_mask((ndev)->features, __features)
+
+#define netdev_hw_features_mask(ndev, __features) \
+		netdev_features_mask((ndev)->hw_features, __features)
+
+#define netdev_wanted_features_mask(ndev, __features) \
+		netdev_features_mask((ndev)->wanted_features, __features)
+
+#define netdev_vlan_features_mask(ndev, __features) \
+		netdev_features_mask((ndev)->vlan_features, __features)
+
+#define netdev_hw_enc_features_mask(ndev, __features) \
+		netdev_features_mask((ndev)->hw_enc_features, __features)
+
+#define netdev_mpls_features_mask(ndev, __features) \
+		netdev_features_mask((ndev)->mpls_features, __features)
+
+#define netdev_gso_partial_features_mask(ndev, __features) \
+		netdev_features_mask((ndev)->gso_partial_features, __features)
+
+/* helpers for netdev features '|' operation */
+static inline void
+__netdev_features_or(netdev_features_t *dst, const netdev_features_t *a,
+		     const netdev_features_t *b)
+{
+	*dst = *a | *b;
+}
+
+#define netdev_features_or(dst, a, b) __netdev_features_or(&(dst), &(a), &(b))
+
+#define netdev_active_features_or(ndev, a, b) \
+		netdev_features_or((ndev)->features, a, b)
+
+#define netdev_hw_features_or(ndev, a, b) \
+		netdev_features_or((ndev)->hw_features, a, b)
+
+#define netdev_wanted_features_or(ndev, a, b) \
+		netdev_features_or((ndev)->wanted_features, a, b)
+
+#define netdev_vlan_features_or(ndev, a, b) \
+		netdev_features_or((ndev)->vlan_features, a, b)
+
+#define netdev_hw_enc_features_or(ndev, a, b) \
+		netdev_features_or((ndev)->hw_enc_features, a, b)
+
+#define netdev_mpls_features_or(ndev, a, b) \
+		netdev_features_or((ndev)->mpls_features, a, b)
+
+#define netdev_gso_partial_features_or(ndev, a, b) \
+		netdev_features_or((ndev)->gso_partial_features, a, b)
+
+/* helpers for netdev features '|=' operation */
+static inline void
+__netdev_features_set(netdev_features_t *dst, const netdev_features_t *features)
+{
+	__netdev_features_or(dst, dst, features);
+}
+
+#define netdev_features_set(dst, __features)	\
+		__netdev_features_set(&(dst), &(__features))
+
+#define netdev_active_features_set(ndev, __features) \
+		netdev_features_set((ndev)->features, __features)
+
+#define netdev_hw_features_set(ndev, __features) \
+		netdev_features_set((ndev)->hw_features, __features)
+
+#define netdev_wanted_features_set(ndev, __features) \
+		netdev_features_set((ndev)->wanted_features, __features)
+
+#define netdev_vlan_features_set(ndev, __features) \
+		netdev_features_set((ndev)->vlan_features, __features)
+
+#define netdev_hw_enc_features_set(ndev, __features) \
+		netdev_features_set((ndev)->hw_enc_features, __features)
+
+#define netdev_mpls_features_set(ndev, __features) \
+		netdev_features_set((ndev)->mpls_features, __features)
+
+#define netdev_gso_partial_features_set(ndev, __features) \
+		netdev_features_set((ndev)->gso_partial_features, __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_feature_change(nr, src)	\
+		__netdev_feature_change(nr, &(src))
+
+#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 void
+__netdev_features_xor(netdev_features_t *dst, const netdev_features_t *a,
+		      const netdev_features_t *b)
+{
+	*dst = *a ^ *b;
+}
+
+#define netdev_features_xor(dst, a, b) __netdev_features_xor(&(dst), &(a), &(b))
+
+#define netdev_active_features_xor(ndev, a, b) \
+		netdev_features_xor((ndev)->features, a, b)
+
+#define netdev_hw_features_xor(ndev, a, b) \
+		netdev_features_xor((ndev)->hw_features, a, b)
+
+#define netdev_wanted_features_xor(ndev, a, b) \
+		netdev_features_xor((ndev)->wanted_features, a, b)
+
+#define netdev_vlan_features_xor(ndev, a, b) \
+		netdev_features_xor((ndev)->vlan_features, a, b)
+
+#define netdev_hw_enc_features_xor(ndev, a, b) \
+		netdev_features_xor((ndev)->hw_enc_features, a, b)
+
+#define netdev_mpls_features_xor(ndev, a, b) \
+		netdev_features_xor((ndev)->mpls_features, a, b)
+
+#define netdev_gso_partial_features_xor(ndev, a, b) \
+		netdev_features_xor((ndev)->gso_partial_features, a, b)
+
+/* helpers for netdev features '^=' operation */
+static inline void
+__netdev_features_toggle(netdev_features_t *dst,
+			 const netdev_features_t *features)
+{
+	__netdev_features_xor(dst, dst, features);
+}
+
+#define netdev_features_toggle(dst, __features)	\
+		__netdev_features_toggle(&(dst), &(__features))
+
+#define netdev_active_features_toggle(ndev, __features) \
+		netdev_features_toggle((ndev)->features, __features)
+
+#define netdev_hw_features_toggle(ndev, __features) \
+		netdev_features_toggle((ndev)->hw_features, __features)
+
+#define netdev_wanted_features_toggle(ndev, __features) \
+		netdev_features_toggle((ndev)->wanted_features, __features)
+
+#define netdev_vlan_features_toggle(ndev, __features) \
+		netdev_features_toggle((ndev)->vlan_features, __features)
+
+#define netdev_hw_enc_features_toggle(ndev, __features) \
+		netdev_features_toggle((ndev)->hw_enc_features, __features)
+
+#define netdev_mpls_features_toggle(ndev, __features) \
+		netdev_features_toggle((ndev)->mpls_features, __features)
+
+#define netdev_gso_partial_features_toggle(ndev, __features) \
+		netdev_features_toggle((ndev)->gso_partial_features, __features)
+
+/* helpers for netdev features '& ~' operation */
+static inline bool
+__netdev_features_andnot(netdev_features_t *dst, const netdev_features_t *a,
+			 const netdev_features_t *b)
+{
+	*dst = *a & ~(*b);
+	return *dst == 0;
+}
+
+#define netdev_features_andnot(dst, a, b)	\
+		__netdev_features_andnot(&(dst), &(a), &(b))
+
+#define netdev_active_features_andnot(ndev, a, b) \
+		netdev_features_andnot((ndev)->features, a, b)
+
+#define netdev_hw_features_andnot(ndev, a, b) \
+		netdev_features_andnot((ndev)->hw_features, a, b)
+
+#define netdev_wanted_features_andnot(ndev, a, b) \
+		netdev_features_andnot((ndev)->wanted_features, a, b)
+
+#define netdev_vlan_features_andnot(ndev, a, b) \
+		netdev_features_andnot((ndev)->vlan_features, a, b)
+
+#define netdev_hw_enc_features_andnot(ndev, a, b) \
+		netdev_features_andnot((ndev)->hw_enc_features, a, b)
+
+#define netdev_mpls_features_andnot(ndev, a, b) \
+		netdev_features_andnot((ndev)->mpls_features, a, b)
+
+#define netdev_gso_partial_features_andnot(ndev, a, b) \
+		netdev_features_andnot((ndev)->gso_partial_features, a, b)
+
+static inline void
+__netdev_features_clear(netdev_features_t *dst,
+			const netdev_features_t *features)
+{
+	__netdev_features_andnot(dst, dst, features);
+}
+
+#define netdev_features_clear(dst, __features)	\
+		__netdev_features_clear(&(dst), &(__features))
+
+#define netdev_active_features_clear(ndev, __features) \
+		netdev_features_clear((ndev)->features, __features)
+
+#define netdev_hw_features_clear(ndev, __features) \
+		netdev_features_clear((ndev)->hw_features, __features)
+
+#define netdev_wanted_features_clear(ndev, __features) \
+		netdev_features_clear((ndev)->wanted_features, __features)
+
+#define netdev_vlan_features_clear(ndev, __features) \
+		netdev_features_clear((ndev)->vlan_features, __features)
+
+#define netdev_hw_enc_features_clear(ndev, __features) \
+		netdev_features_clear((ndev)->hw_enc_features, __features)
+
+#define netdev_mpls_features_clear(ndev, __features) \
+		netdev_features_clear((ndev)->mpls_features, __features)
+
+#define netdev_gso_partial_features_clear(ndev, __features) \
+		netdev_features_clear((ndev)->gso_partial_features, __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_feature_add(nr, src) __netdev_feature_add(nr, &(src))
+
+#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)
+{
+	unsigned int i;
+
+	for (i = 0; i < set->cnt; i++)
+		__netdev_feature_add(set->feature_bits[i], dst);
+}
+
+#define netdev_features_set_array(set, dst) \
+		__netdev_features_set_array(set, &(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_feature_del(nr, src) __netdev_feature_del(nr, &(src))
+
+#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)
+{
+	unsigned int i;
+
+	for (i = 0; i < set->cnt; i++)
+		__netdev_feature_del(set->feature_bits[i], dst);
+}
+
+#define netdev_features_clear_array(set, dst) \
+		__netdev_features_clear_array(set, &(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 *feats1,
+						const netdev_features_t *feats2)
+{
+	return (*feats1 & *feats2) > 0;
+}
+
+#define netdev_features_intersects(feats1, feats2)	\
+		__netdev_features_intersects(&(feats1), &(feats2))
+
+#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_features_copy(netdev_features_t *dst,
+					  const netdev_features_t *src)
+{
+	*dst = *src;
+}
+
+#define netdev_features_copy(dst, src)	__netdev_features_copy(&(dst), &(src))
+
+#define netdev_active_features_copy(ndev, __features)	\
+		netdev_features_copy((ndev)->features, __features)
+
+#define netdev_hw_features_copy(ndev, __features)	\
+		netdev_features_copy((ndev)->hw_features, __features)
+
+#define netdev_wanted_features_copy(ndev, __features)	\
+		netdev_features_copy((ndev)->wanted_features, __features)
+
+#define netdev_vlan_features_copy(ndev, __features)	\
+		netdev_features_copy((ndev)->vlan_features, __features)
+
+#define netdev_hw_enc_features_copy(ndev, __features)	\
+		netdev_features_copy((ndev)->hw_enc_features, __features)
+
+#define netdev_mpls_features_copy(ndev, __features)	\
+		netdev_features_copy((ndev)->mpls_features, __features)
+
+#define netdev_gso_partial_features_copy(ndev, __features)	\
+		netdev_features_copy((ndev)->gso_partial_features, __features)
+
+/* helpers for netdev features 'subset' */
+static inline bool __netdev_features_subset(const netdev_features_t *feats1,
+					    const netdev_features_t *feats2)
+{
+	return (*feats1 & *feats2) == *feats2;
+}
+
+#define netdev_features_subset(feats1, feats2)	\
+		__netdev_features_subset(&(feats1), &(feats2))
+
+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/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/netdevice.h b/include/linux/netdevice.h
index f0068c1ff1df..9bbab3856347 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2345,6 +2345,36 @@ 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_feature_test(nr, __features)	\
+		__netdev_feature_test(nr, &(__features))
+
+#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)
@@ -4860,24 +4890,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 e1bb41a443c4..7940074bdb27 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/net_tstamp.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
diff --git a/net/core/dev.c b/net/core/dev.c
index d66c73c1c734..fdae614ecffa 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/skbuff.h>
-- 
2.33.0


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

* [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 01/55] net: introduce operation helpers for netdev features Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18 12:05   ` kernel test robot
  2022-09-20 20:12   ` Jakub Kicinski
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 03/55] treewide: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET Jian Shen
                   ` (54 subsequent siblings)
  56 siblings, 2 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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 net device
module init.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/wireguard/device.c         |  12 +-
 include/linux/netdev_feature_helpers.h | 112 +++++++++++++
 include/linux/netdev_features.h        |  84 ++++++----
 net/core/Makefile                      |   2 +-
 net/core/dev.c                         |   2 +
 net/core/dev.h                         |   2 +
 net/core/netdev_features.c             | 223 +++++++++++++++++++++++++
 7 files changed, 394 insertions(+), 43 deletions(-)
 create mode 100644 net/core/netdev_features.c

diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index d58e9f818d3b..32831d40d757 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -275,9 +275,9 @@ static const struct device_type device_type = { .name = KBUILD_MODNAME };
 static void wg_setup(struct net_device *dev)
 {
 	struct wg_device *wg = netdev_priv(dev);
-	enum { WG_NETDEV_FEATURES = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
-				    NETIF_F_SG | NETIF_F_GSO |
-				    NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA };
+	netdev_features_t wg_netdev_features =
+		NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
+		NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA;
 	const int overhead = MESSAGE_MINIMUM_LENGTH + sizeof(struct udphdr) +
 			     max(sizeof(struct ipv6hdr), sizeof(struct iphdr));
 
@@ -291,9 +291,9 @@ static void wg_setup(struct net_device *dev)
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
 	dev->priv_flags |= IFF_NO_QUEUE;
 	dev->features |= NETIF_F_LLTX;
-	dev->features |= WG_NETDEV_FEATURES;
-	dev->hw_features |= WG_NETDEV_FEATURES;
-	dev->hw_enc_features |= WG_NETDEV_FEATURES;
+	dev->features |= wg_netdev_features;
+	dev->hw_features |= wg_netdev_features;
+	dev->hw_enc_features |= wg_netdev_features;
 	dev->mtu = ETH_DATA_LEN - overhead;
 	dev->max_mtu = round_down(INT_MAX, MESSAGE_PADDING_MULTIPLE) - overhead;
 
diff --git a/include/linux/netdev_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index 4bb5de61e4e9..132bf0de1523 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -585,6 +585,118 @@ static inline bool __netdev_features_subset(const netdev_features_t *feats1,
 #define netdev_features_subset(feats1, feats2)	\
 		__netdev_features_subset(&(feats1), &(feats2))
 
+#define __netdev_features_set_set(feat, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	__netdev_features_set_array(&(uniq), &(feat));	\
+})
+#define netdev_features_set_set(feat, ...)		\
+	__netdev_features_set_set(feat, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_active_features_set_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_active_features_set_array(ndev, uniq);	\
+})
+#define netdev_active_features_set_set(ndev, ...)		\
+	__netdev_active_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_hw_features_set_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_hw_features_set_array(ndev, uniq);	\
+})
+#define netdev_hw_features_set_set(ndev, ...)		\
+	__netdev_hw_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_wanted_features_set_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_wanted_features_set_array(ndev, uniq);	\
+})
+#define netdev_wanted_features_set_set(ndev, ...)		\
+	__netdev_wanted_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_vlan_features_set_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_vlan_features_set_array(ndev, uniq);	\
+})
+#define netdev_vlan_features_set_set(ndev, ...)		\
+	__netdev_vlan_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_hw_enc_features_set_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_hw_enc_features_set_array(ndev, uniq);	\
+})
+#define netdev_hw_enc_features_set_set(ndev, ...)		\
+	__netdev_hw_enc_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_mpls_features_set_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_mpls_features_set_array(ndev, uniq);	\
+})
+#define netdev_mpls_features_set_set(ndev, ...)		\
+	__netdev_mpls_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_gso_partial_features_set_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_gso_partial_features_set_array(ndev, uniq);	\
+})
+#define netdev_gso_partial_features_set_set(ndev, ...)		\
+	__netdev_gso_partial_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_features_clear_set(feat, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	__netdev_features_clear_array(&(uniq), &(feat));	\
+})
+#define netdev_features_clear_set(feat, ...)		\
+	__netdev_features_clear_set(feat, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_active_features_clear_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_active_features_clear_array(ndev, uniq);	\
+})
+#define netdev_active_features_clear_set(ndev, ...)		\
+	__netdev_active_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_hw_features_clear_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_hw_features_clear_array(ndev, uniq);	\
+})
+#define netdev_hw_features_clear_set(ndev, ...)		\
+	__netdev_hw_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_wanted_features_clear_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_wanted_features_clear_array(ndev, uniq);	\
+})
+#define netdev_wanted_features_clear_set(ndev, ...)		\
+		__netdev_wanted_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_vlan_features_clear_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_vlan_features_clear_array(ndev, uniq);	\
+})
+#define netdev_vlan_features_clear_set(ndev, ...)		\
+	__netdev_vlan_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_hw_enc_features_clear_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_hw_enc_features_clear_array(ndev, uniq);	\
+})
+#define netdev_hw_enc_features_clear_set(ndev, ...)		\
+	__netdev_hw_enc_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_mpls_features_clear_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_mpls_features_clear_array(ndev, uniq);	\
+})
+#define netdev_mpls_features_clear_set(ndev, ...)		\
+	__netdev_mpls_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
+#define __netdev_gso_partial_features_clear_set(ndev, uniq, ...) ({	\
+	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
+	netdev_gso_partial_features_clear_array(ndev, uniq);	\
+})
+#define netdev_gso_partial_features_clear_set(ndev, ...)		\
+	__netdev_gso_partial_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
+
 static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
 							  netdev_features_t f2)
 {
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 9d434b4e6e6e..664055209b2e 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,37 @@ 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;
+
 /* 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 +235,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 5857cec87b83..77618bfaa890 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 fdae614ecffa..491130bdbbad 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11390,6 +11390,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/dev.h b/net/core/dev.h
index cbb8a925175a..b4aae4f2bd9b 100644
--- a/net/core/dev.h
+++ b/net/core/dev.h
@@ -88,6 +88,8 @@ int dev_change_carrier(struct net_device *dev, bool new_carrier);
 
 void __dev_set_rx_mode(struct net_device *dev);
 
+void __init netdev_features_init(void);
+
 static inline void netif_set_gso_max_size(struct net_device *dev,
 					  unsigned int size)
 {
diff --git a/net/core/netdev_features.c b/net/core/netdev_features.c
new file mode 100644
index 000000000000..a017c8fc6e65
--- /dev/null
+++ b/net/core/netdev_features.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Network device features.
+ */
+
+#include <linux/netdev_features.h>
+#include <linux/netdev_feature_helpers.h>
+
+netdev_features_t netdev_ethtool_features __ro_after_init;
+EXPORT_SYMBOL(netdev_ethtool_features);
+
+netdev_features_t netdev_never_change_features __ro_after_init;
+EXPORT_SYMBOL(netdev_never_change_features);
+
+netdev_features_t netdev_gso_features_mask __ro_after_init;
+EXPORT_SYMBOL(netdev_gso_features_mask);
+
+netdev_features_t netdev_ip_csum_features __ro_after_init;
+EXPORT_SYMBOL(netdev_ip_csum_features);
+
+netdev_features_t netdev_csum_features_mask __ro_after_init;
+EXPORT_SYMBOL(netdev_csum_features_mask);
+
+netdev_features_t netdev_general_tso_features __ro_after_init;
+EXPORT_SYMBOL(netdev_general_tso_features);
+
+netdev_features_t netdev_all_tso_features __ro_after_init;
+EXPORT_SYMBOL(netdev_all_tso_features);
+
+netdev_features_t netdev_tso_ecn_features __ro_after_init;
+EXPORT_SYMBOL(netdev_tso_ecn_features);
+
+netdev_features_t netdev_all_fcoe_features __ro_after_init;
+EXPORT_SYMBOL(netdev_all_fcoe_features);
+
+netdev_features_t netdev_gso_software_features __ro_after_init;
+EXPORT_SYMBOL(netdev_gso_software_features);
+
+netdev_features_t netdev_one_for_all_features __ro_after_init;
+EXPORT_SYMBOL(netdev_one_for_all_features);
+
+netdev_features_t netdev_all_for_all_features __ro_after_init;
+EXPORT_SYMBOL(netdev_all_for_all_features);
+
+netdev_features_t netdev_upper_disable_features __ro_after_init;
+EXPORT_SYMBOL(netdev_upper_disable_features);
+
+netdev_features_t netdev_soft_features __ro_after_init;
+EXPORT_SYMBOL(netdev_soft_features);
+
+netdev_features_t netdev_soft_off_features __ro_after_init;
+EXPORT_SYMBOL(netdev_soft_off_features);
+
+netdev_features_t netdev_all_vlan_features __ro_after_init;
+EXPORT_SYMBOL(netdev_all_vlan_features);
+
+netdev_features_t netdev_vlan_filter_features __ro_after_init;
+EXPORT_SYMBOL(netdev_vlan_filter_features);
+
+netdev_features_t netdev_rx_vlan_features __ro_after_init;
+EXPORT_SYMBOL(netdev_rx_vlan_features);
+
+netdev_features_t netdev_tx_vlan_features __ro_after_init;
+EXPORT_SYMBOL(netdev_tx_vlan_features);
+
+netdev_features_t netdev_ctag_vlan_offload_features __ro_after_init;
+EXPORT_SYMBOL(netdev_ctag_vlan_offload_features);
+
+netdev_features_t netdev_stag_vlan_offload_features __ro_after_init;
+EXPORT_SYMBOL(netdev_stag_vlan_offload_features);
+
+netdev_features_t netdev_vlan_offload_features __ro_after_init;
+EXPORT_SYMBOL(netdev_vlan_offload_features);
+
+netdev_features_t netdev_ctag_vlan_features __ro_after_init;
+EXPORT_SYMBOL(netdev_ctag_vlan_features);
+
+netdev_features_t netdev_stag_vlan_features __ro_after_init;
+EXPORT_SYMBOL(netdev_stag_vlan_features);
+
+netdev_features_t netdev_multi_tags_features_mask __ro_after_init;
+EXPORT_SYMBOL(netdev_multi_tags_features_mask);
+
+netdev_features_t netdev_gso_encap_all_features __ro_after_init;
+EXPORT_SYMBOL(netdev_gso_encap_all_features);
+
+netdev_features_t netdev_xfrm_features __ro_after_init;
+EXPORT_SYMBOL(netdev_xfrm_features);
+
+netdev_features_t netdev_tls_features __ro_after_init;
+EXPORT_SYMBOL(netdev_tls_features);
+
+netdev_features_t netdev_csum_gso_features_mask __ro_after_init;
+EXPORT_SYMBOL(netdev_csum_gso_features_mask);
+
+netdev_features_t netdev_empty_features __ro_after_init;
+EXPORT_SYMBOL_GPL(netdev_empty_features);
+
+void __init netdev_features_init(void)
+{
+	netdev_features_t features;
+
+	netdev_features_set_set(netdev_ip_csum_features,
+				NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT);
+	netdev_features_set_set(netdev_csum_features_mask,
+				NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT,
+				NETIF_F_HW_CSUM_BIT);
+
+	netdev_features_set_set(netdev_gso_features_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);
+	netdev_features_set_set(netdev_general_tso_features,
+				NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
+	netdev_features_set_set(netdev_all_tso_features,
+				NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
+				NETIF_F_TSO_ECN_BIT, NETIF_F_TSO_MANGLEID_BIT);
+	netdev_features_set_set(netdev_tso_ecn_features,
+				NETIF_F_TSO_ECN_BIT);
+	netdev_features_set_set(netdev_all_fcoe_features,
+				NETIF_F_FCOE_CRC_BIT, NETIF_F_FCOE_MTU_BIT,
+				NETIF_F_FSO_BIT);
+	netdev_features_set_set(netdev_gso_software_features,
+				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);
+	netdev_features_set_set(netdev_gso_encap_all_features,
+				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);
+
+	netdev_features_or(netdev_csum_gso_features_mask,
+			   netdev_gso_features_mask, netdev_csum_features_mask);
+
+	netdev_features_set_set(netdev_one_for_all_features,
+				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);
+	netdev_features_set_set(netdev_all_for_all_features,
+				NETIF_F_NOCACHE_COPY_BIT, NETIF_F_FSO_BIT);
+
+	netdev_features_set_set(netdev_upper_disable_features, NETIF_F_LRO_BIT);
+
+	netdev_features_set_set(netdev_soft_features,
+				NETIF_F_GSO_BIT, NETIF_F_GRO_BIT);
+	netdev_features_set_set(netdev_soft_off_features,
+				NETIF_F_GRO_FRAGLIST_BIT,
+				NETIF_F_GRO_UDP_FWD_BIT);
+
+	netdev_features_set_set(netdev_rx_vlan_features,
+				NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				NETIF_F_HW_VLAN_STAG_RX_BIT);
+	netdev_features_set_set(netdev_tx_vlan_features,
+				NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				NETIF_F_HW_VLAN_STAG_TX_BIT);
+	netdev_features_set_set(netdev_vlan_filter_features,
+				NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				NETIF_F_HW_VLAN_STAG_FILTER_BIT);
+	netdev_features_set_set(netdev_ctag_vlan_offload_features,
+				NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				NETIF_F_HW_VLAN_CTAG_RX_BIT);
+	netdev_features_set_set(netdev_stag_vlan_offload_features,
+				NETIF_F_HW_VLAN_STAG_TX_BIT,
+				NETIF_F_HW_VLAN_STAG_RX_BIT);
+	netdev_features_or(netdev_vlan_offload_features,
+			   netdev_ctag_vlan_offload_features,
+			   netdev_stag_vlan_offload_features);
+	netdev_features_set_set(netdev_ctag_vlan_features,
+				NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+	netdev_features_set_set(netdev_stag_vlan_features,
+				NETIF_F_HW_VLAN_STAG_TX_BIT,
+				NETIF_F_HW_VLAN_STAG_RX_BIT,
+				NETIF_F_HW_VLAN_STAG_FILTER_BIT);
+	netdev_features_or(netdev_all_vlan_features, netdev_ctag_vlan_features,
+			   netdev_stag_vlan_features);
+	netdev_features_set_set(netdev_multi_tags_features_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);
+
+	netdev_features_set_set(netdev_xfrm_features,
+				NETIF_F_HW_ESP_BIT,
+				NETIF_F_HW_ESP_TX_CSUM_BIT,
+				NETIF_F_GSO_ESP_BIT);
+	netdev_features_set_set(netdev_tls_features,
+				NETIF_F_HW_TLS_TX_BIT,
+				NETIF_F_HW_TLS_RX_BIT);
+
+	netdev_features_set_set(netdev_never_change_features,
+				NETIF_F_VLAN_CHALLENGED_BIT,
+				NETIF_F_LLTX_BIT,
+				NETIF_F_NETNS_LOCAL_BIT);
+	netdev_features_fill(features);
+	netdev_features_andnot(netdev_ethtool_features, features,
+			       netdev_never_change_features);
+
+	netdev_features_zero(netdev_empty_features);
+}
-- 
2.33.0


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

* [RFCv8 PATCH net-next 03/55] treewide: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 01/55] net: introduce operation helpers for netdev features Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-20 20:13   ` Jakub Kicinski
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 04/55] net: sfc: replace const features initialization " Jian Shen
                   ` (53 subsequent siblings)
  56 siblings, 1 reply; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

There are many netdev_features bits group used in drivers, replace them
with netdev_features_set_set and netdev_features_clear_set, preparing to
remove all the NETIF_F_XXX macroes later.

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

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 548265312743..e1e91f6db8f9 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);
+	netdev_active_features_set_set(dev, NETIF_F_SG_BIT,
+				       NETIF_F_FRAGLIST_BIT);
+	dev->features = dev->hw_features;
 	INIT_WORK(&vp->reset_tx, vector_reset_tx);
 
 	timer_setup(&vp->tl, vector_timer_expire, 0);
diff --git a/arch/um/drivers/vector_transports.c b/arch/um/drivers/vector_transports.c
index 0794d23f07cb..91c93993306e 100644
--- a/arch/um/drivers/vector_transports.c
+++ b/arch/um/drivers/vector_transports.c
@@ -406,10 +406,12 @@ 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_set(vp->dev, NETIF_F_TSO_BIT,
+					   NETIF_F_GRO_BIT);
+		netdev_active_features_set_set(vp->dev, NETIF_F_RXCSUM_BIT,
+					       NETIF_F_HW_CSUM_BIT,
+					       NETIF_F_TSO_BIT,
+					       NETIF_F_GRO_BIT);
 		netdev_info(
 			vp->dev,
 			"raw: using vnet headers for tso and tx/rx checksum"
@@ -425,11 +427,12 @@ 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_set(vp->dev, NETIF_F_TSO_BIT,
+					   NETIF_F_GSO_BIT, NETIF_F_GRO_BIT);
+		netdev_active_features_set_set(vp->dev, NETIF_F_RXCSUM_BIT,
+					       NETIF_F_HW_CSUM_BIT,
+					       NETIF_F_TSO_BIT, NETIF_F_GSO_BIT,
+					       NETIF_F_GRO_BIT);
 		netdev_info(
 			vp->dev,
 			"tap/raw hybrid: using vnet headers for tso and tx/rx checksum"
@@ -450,11 +453,12 @@ 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_set(vp->dev, NETIF_F_TSO_BIT,
+					   NETIF_F_GSO_BIT, NETIF_F_GRO_BIT);
+		netdev_active_features_set_set(vp->dev, NETIF_F_RXCSUM_BIT,
+					       NETIF_F_HW_CSUM_BIT,
+					       NETIF_F_TSO_BIT, NETIF_F_GSO_BIT,
+					       NETIF_F_GRO_BIT);
 		netdev_info(
 			vp->dev,
 			"tap: using vnet headers for tso and tx/rx checksum"
diff --git a/drivers/infiniband/hw/hfi1/netdev.h b/drivers/infiniband/hw/hfi1/netdev.h
index 8aa074670a9c..685de6e3055d 100644
--- a/drivers/infiniband/hw/hfi1/netdev.h
+++ b/drivers/infiniband/hw/hfi1/netdev.h
@@ -10,6 +10,7 @@
 #include "hfi.h"
 
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/xarray.h>
 
 /**
diff --git a/drivers/infiniband/hw/hfi1/vnic_main.c b/drivers/infiniband/hw/hfi1/vnic_main.c
index 3650fababf25..949a414d4d7d 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_active_features_set_set(netdev, NETIF_F_HIGHDMA_BIT,
+				       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.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 35e9c8a330e2..2080dfe5986b 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_feature_helpers.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 a4904371e2db..7ec6c1fedfa1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -219,7 +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 | NETIF_F_TSO);
+		netdev_features_clear_set(features, NETIF_F_IP_CSUM_BIT,
+					  NETIF_F_TSO_BIT);
 
 	return features;
 }
@@ -1855,7 +1856,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;
+		netdev_hw_features_set_set(priv->dev, NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_RXCSUM_BIT);
 
 		if (priv->kernel_caps & IBK_UD_TSO)
 			priv->dev->hw_features |= NETIF_F_TSO;
@@ -2121,8 +2123,9 @@ 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_set(dev, NETIF_F_VLAN_CHALLENGED_BIT,
+				       NETIF_F_HIGHDMA_BIT);
 	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 2d20be6ffb7e..f3cd014f93d0 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_feature_helpers.h>
 #include <linux/igmp.h>
 #include <linux/workqueue.h>
 #include <net/sch_generic.h>
@@ -3105,12 +3106,12 @@ 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_set(dev, NETIF_F_LLTX_BIT,
+				       NETIF_F_NETNS_LOCAL_BIT);
 	dev->hw_features	|= NETIF_F_GSO_SOFTWARE;
+	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_FRAGLIST_BIT, NETIF_F_RXCSUM_BIT);
 	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..c71190b54118 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_feature_helpers.h>
 #include <net/dst_metadata.h>
 #include <net/gro_cells.h>
 #include <net/rtnetlink.h>
@@ -542,12 +543,12 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				       NETIF_F_RXCSUM_BIT, NETIF_F_FRAGLIST_BIT,
+				       NETIF_F_LLTX_BIT);
 	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_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_FRAGLIST_BIT, NETIF_F_RXCSUM_BIT);
 	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 ddd07395827a..7cdaf25cb920 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_feature_helpers.h>
 #include <linux/inetdevice.h>
 #include <linux/igmp.h>
 #include <linux/etherdevice.h>
@@ -254,6 +255,10 @@ static const struct flow_dissector_key flow_keys_bonding_keys[] = {
 
 static struct flow_dissector flow_keys_bonding __read_mostly;
 
+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 +1426,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_ENC_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
-				 NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE)
+#define BOND_VLAN_FEATURES	bond_vlan_features
 
-#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)
 {
@@ -6216,6 +6216,22 @@ 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_set(bond_vlan_features, NETIF_F_HW_CSUM_BIT,
+				NETIF_F_SG_BIT, NETIF_F_FRAGLIST_BIT,
+				NETIF_F_HIGHDMA_BIT, NETIF_F_LRO_BIT);
+
+	bond_enc_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_set(bond_enc_features, NETIF_F_HW_CSUM_BIT,
+				NETIF_F_SG_BIT, NETIF_F_RXCSUM_BIT);
+
+	bond_mpls_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_set(bond_mpls_features,  NETIF_F_HW_CSUM_BIT,
+				NETIF_F_SG_BIT);
+}
+
 /* Called from registration process */
 static int bond_init(struct net_device *bond_dev)
 {
@@ -6376,6 +6392,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 fa622639d640..d9e23850d184 100644
--- a/drivers/net/dsa/xrs700x/xrs700x.c
+++ b/drivers/net/dsa/xrs700x/xrs700x.c
@@ -9,16 +9,13 @@
 #include <linux/if_bridge.h>
 #include <linux/of_device.h>
 #include <linux/netdev_features.h>
+#include <linux/netdev_feature_helpers.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)
-
 #define XRS7003E_ID	0x100
 #define XRS7003F_ID	0x101
 #define XRS7004E_ID	0x200
@@ -633,7 +630,11 @@ 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_set(slave,
+					       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);
 	}
 
 	return 0;
@@ -687,7 +688,11 @@ 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_set(slave,
+						 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);
 	}
 
 	return 0;
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index aa0fc00faecb..8bee9d473b78 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/init.h>
@@ -123,9 +124,10 @@ 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_set(dev, NETIF_F_SG_BIT,
+				       NETIF_F_FRAGLIST_BIT, NETIF_F_HW_CSUM_BIT,
+				       NETIF_F_HIGHDMA_BIT, NETIF_F_LLTX_BIT);
 	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/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 082388bb6169..66eb2d9fe576 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -1448,7 +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 | NETIF_F_SG;
+			netdev_active_features_set_set(dev, NETIF_F_IP_CSUM_BIT,
+						       NETIF_F_SG_BIT);
 		}
 	} else
 		dev->netdev_ops =  &vortex_netdev_ops;
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index aaaff3ba43ef..d72f1ef73484 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/mm.h>
@@ -2476,10 +2477,13 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
+				   NETIF_F_TSO_BIT,
+				   NETIF_F_HW_VLAN_CTAG_TX_BIT);
+	dev->features = dev->hw_features;
+	netdev_active_features_set_set(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				       NETIF_F_RXCSUM_BIT);
 
 	err = register_netdev(dev);
 	if (err < 0) {
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index 857361c74f5d..408be86d6c88 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -685,11 +686,13 @@ 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;
+		netdev_active_features_set_set(dev, NETIF_F_IP_CSUM_BIT,
+					       NETIF_F_SG_BIT);
 #endif /* ZEROCOPY */
 
 #ifdef VLAN_SUPPORT
-	dev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_active_features_set_set(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				       NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 #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 9c4fe25aca6c..6065eabcd87a 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1483,8 +1483,10 @@ 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_set(dev, NETIF_F_SG_BIT,
+					   NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_RXCSUM_BIT);
 		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 d7762da8b2c0..a3c6dcc6d57b 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
@@ -469,8 +470,10 @@ 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_set(dev, NETIF_F_SG_BIT,
+				       NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				       NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	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 371269e0b2b9..571dc950c863 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_feature_helpers.h>
 #include <linux/numa.h>
 #include <linux/pci.h>
 #include <linux/utsname.h>
@@ -4041,11 +4042,9 @@ 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_set(netdev, NETIF_F_SG_BIT,
+				       NETIF_F_RXHASH_BIT, NETIF_F_HIGHDMA_BIT);
 
 	netdev->hw_features |= netdev->features;
 	netdev->vlan_features |= netdev->features;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index f342bb853189..4101c9ee7c99 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2183,7 +2183,9 @@ 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;
+	netdev_features_zero(vxlan_base);
+	netdev_features_set_set(vxlan_base, NETIF_F_GSO_UDP_TUNNEL_BIT,
+				NETIF_F_RX_UDP_TUNNEL_PORT_BIT);
 
 	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 0e8698928e4d..912335f684e5 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/io.h>
 #include <linux/notifier.h>
@@ -342,42 +343,38 @@ 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_set(netdev, 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);
 
 	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_features |= NETIF_F_GSO_UDP_TUNNEL |
-				       NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev_hw_enc_features_zero(netdev);
+		netdev_hw_enc_features_set_set(netdev, 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);
+
+		netdev_hw_features_set_set(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT,
+					   NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 		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_set(netdev, NETIF_F_SG_BIT,
+				     NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT,
+				     NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 
 	netdev->features |= netdev->hw_features;
 	pdata->netdev_features = netdev->features;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index b875c430222e..c57a5e98c0d6 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -119,6 +119,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/workqueue.h>
 #include <linux/phy.h>
 #include <linux/if_vlan.h>
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c
index d022b6db9e06..c33d9f810953 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -648,8 +648,7 @@ 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;
+	netdev_active_features_set_set(ndev, NETIF_F_GSO_BIT, 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..ac7bfdd8e2b1 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_feature_helpers.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 53dc8d5fede8..a6709e94f31d 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_feature_helpers.h>
 #include "xgene_enet_main.h"
 #include "xgene_enet_hw.h"
 #include "xgene_enet_sgmac.h"
@@ -2034,10 +2035,9 @@ 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_set(ndev, NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_GSO_BIT, NETIF_F_GRO_BIT,
+				       NETIF_F_SG_BIT);
 
 	of_id = of_match_device(xgene_enet_of_match, &pdev->dev);
 	if (of_id) {
@@ -2065,7 +2065,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;
+		netdev_active_features_set_set(ndev, NETIF_F_TSO_BIT,
+					       NETIF_F_RXCSUM_BIT);
 		spin_lock_init(&pdata->mss_lock);
 	}
 	ndev->hw_features = ndev->features;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 06508eebb585..11b3425562fe 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/timer.h>
 #include <linux/cpu.h>
@@ -373,9 +374,10 @@ 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_set(self->ndev, 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);
 	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..9996030a2e5d 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_feature_helpers.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;
 
@@ -1150,6 +1156,8 @@ static __init int ax88796c_spi_init(void)
 		pr_err("Invalid bitmap description, masking all registers\n");
 	}
 
+	netdev_features_set_array(&ax88796c_feature_set, ax88796c_features);
+
 	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..e07247d87407 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <net/ip6_checksum.h>
 #include <linux/crc32.h>
@@ -1821,11 +1822,10 @@ 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_set(netdev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_RXCSUM_BIT, NETIF_F_TSO_BIT,
+				   NETIF_F_TSO6_BIT);
 
 	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..e2e1c28141e7 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_feature_helpers.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..cb2c12cdd0dc 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2629,11 +2629,10 @@ 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_set(netdev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_HW_VLAN_CTAG_RX_BIT, NETIF_F_TSO_BIT,
+				   NETIF_F_TSO6_BIT);
 	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..96eb671c3e1b 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_feature_helpers.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..13b5b706d1ce 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -2269,11 +2269,14 @@ 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_set(netdev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_TSO_BIT,
+				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_TX;
 	/* not enabled by default */
-	netdev->hw_features |= NETIF_F_RXALL | NETIF_F_RXFCS;
+	netdev_hw_features_set_set(netdev, NETIF_F_RXALL_BIT,
+				   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 7fcfba370fc3..a7e3ae45b5af 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_feature_helpers.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/pm.h>
@@ -2987,12 +2988,16 @@ 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_set(netdev, NETIF_F_HW_CSUM_BIT,
+				       NETIF_F_SG_BIT,
+				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				       NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
-	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_set(netdev, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
+				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	/* 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 52144ea2bbf3..e7b2840a3db9 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_feature_helpers.h>
 #include <linux/dsa/brcm.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
@@ -157,13 +158,17 @@ 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_set(tx_csum_features, NETIF_F_IP_CSUM_BIT,
+				NETIF_F_IPV6_CSUM_BIT,
+				NETIF_F_HW_VLAN_CTAG_TX_BIT);
 	/* 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);
@@ -2566,9 +2571,10 @@ 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_set(dev, 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);
 	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 29a9ab20ff98..2c902c0b4ffe 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_feature_helpers.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
 #include <net/dsa.h>
@@ -1535,7 +1536,10 @@ 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_set(net_dev, NETIF_F_SG_BIT,
+				       NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_IPV6_CSUM_BIT);
 	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 b612781be893..687e2aa9c721 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
@@ -8580,12 +8581,14 @@ 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_set(dev, 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);
 
 	if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
-		dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+		netdev_hw_features_set_set(dev, NETIF_F_IPV6_CSUM_BIT,
+					   NETIF_F_TSO6_BIT);
 
 	dev->vlan_features = dev->hw_features;
 	dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | 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 51b1690fd045..ad2c38c261bc 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
@@ -12349,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);
+		netdev_hw_features_clear_set(bp->dev, NETIF_F_LRO_BIT,
+					     NETIF_F_GRO_HW_BIT);
+		netdev_active_features_clear_set(bp->dev, NETIF_F_LRO_BIT,
+						 NETIF_F_GRO_HW_BIT);
 	}
 
 	if (CHIP_IS_E1(bp))
@@ -13197,34 +13200,49 @@ 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_set(dev, 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);
 	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_set(dev, 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);
+
+		netdev_hw_enc_features_zero(dev);
+		netdev_hw_enc_features_set_set(dev, 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);
+
+		netdev_gso_partial_features_zero(dev);
+		netdev_gso_partial_features_set_set(dev,
+						    NETIF_F_GSO_GRE_CSUM_BIT,
+						    NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 		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_set(dev, 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);
 
 	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 f46eefb5a029..a737cc9d2752 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
@@ -11179,7 +11180,8 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 		features &= ~NETIF_F_NTUPLE;
 
 	if ((bp->flags & BNXT_FLAG_NO_AGG_RINGS) || bp->xdp_prog)
-		features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
+		netdev_features_clear_set(features, NETIF_F_LRO_BIT,
+					  NETIF_F_GRO_HW_BIT);
 
 	if (!(features & NETIF_F_GRO))
 		features &= ~NETIF_F_GRO_HW;
@@ -13267,8 +13269,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);
+		netdev_hw_features_clear_set(bp->dev, NETIF_F_LRO_BIT,
+					     NETIF_F_GRO_HW_BIT);
+		netdev_active_features_clear_set(bp->dev, NETIF_F_LRO_BIT,
+						 NETIF_F_GRO_HW_BIT);
 		bnxt_set_ring_params(bp);
 	}
 
@@ -13591,27 +13595,36 @@ 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_set(dev, 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);
 
 	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_set(dev, 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_IPXIP4_BIT,
+				       NETIF_F_GSO_PARTIAL_BIT);
 	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_set(dev, NETIF_F_GSO_GRE_CSUM_BIT,
+					    NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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 667e66079c73..4912fe1a027d 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_feature_helpers.h>
 #include <linux/inetdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -4025,8 +4026,8 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
+				       NETIF_F_HW_CSUM_BIT, NETIF_F_RXCSUM_BIT);
 	dev->hw_features |= dev->features;
 	dev->vlan_features |= dev->features;
 
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 59d2d907e989..e27272328a65 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -17725,7 +17726,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;
+		netdev_features_set_set(features, NETIF_F_SG_BIT,
+					NETIF_F_IP_CSUM_BIT,
+					NETIF_F_RXCSUM_BIT);
 
 		if (tg3_flag(tp, 5755_PLUS))
 			features |= NETIF_F_IPV6_CSUM;
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 29dd0f93d6c0..ae3f2656c268 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_feature_helpers.h>
 #include <linux/skbuff.h>
 #include <linux/etherdevice.h>
 #include <linux/in.h>
@@ -3422,17 +3423,21 @@ 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->features |= netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER |
-			    NETIF_F_HIGHDMA;
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_set(netdev, 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);
+	netdev_vlan_features_zero(netdev);
+	netdev_vlan_features_set_set(netdev, 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);
+
+	netdev->features |= netdev->hw_features;
+	netdev_active_features_set_set(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				       NETIF_F_HIGHDMA_BIT);
 
 	netdev->mem_start = bnad->mmio_start;
 	netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1;
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 66c7d08d376a..fbdce0d335c2 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
@@ -4056,7 +4057,8 @@ static int macb_init(struct platform_device *pdev)
 
 	/* 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;
+		netdev_hw_features_set_set(dev, NETIF_F_HW_CSUM_BIT,
+					   NETIF_F_RXCSUM_BIT);
 	if (bp->caps & MACB_CAPS_SG_DISABLED)
 		dev->hw_features &= ~NETIF_F_SG;
 	dev->features = dev->hw_features;
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 1281d1565ef8..8d379803e2fb 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_feature_helpers.h>
 #include <linux/slab.h>
 
 /* XGMAC Register definitions */
@@ -1774,10 +1775,12 @@ 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_set(ndev, NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT);
 	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_set(ndev, NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_IPV6_CSUM_BIT,
+					   NETIF_F_RXCSUM_BIT);
 	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..51334509ba12 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_feature_helpers.h>
 #include <net/vxlan.h>
 #include <linux/kthread.h>
 #include "liquidio_common.h"
@@ -3555,26 +3556,31 @@ 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_set(lio->dev_capability,
+						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);
 		}
 		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_set(lio->enc_dev_capability,
+					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);
 
 		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..861ecd176404 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_feature_helpers.h>
 #include <net/vxlan.h>
 #include "liquidio_common.h"
 #include "octeon_droq.h"
@@ -2088,24 +2089,27 @@ 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_set(lio->dev_capability,
+					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);
 		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_set(lio->enc_dev_capability,
+					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);
 
 		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..30250252dac5 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_feature_helpers.h>
 #include <linux/if_vlan.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -2203,18 +2204,22 @@ 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_set(netdev, 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);
 
 	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_vlan_features_set_set(netdev, NETIF_F_SG_BIT,
+				     NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT,
+				     NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 
 	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 17043c4fce52..c787b9122df8 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
 #include <linux/mii.h>
@@ -1031,10 +1032,14 @@ 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_set(netdev, NETIF_F_SG_BIT,
+					   NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_RXCSUM_BIT);
+		netdev_active_features_set_set(netdev, NETIF_F_SG_BIT,
+					       NETIF_F_IP_CSUM_BIT,
+					       NETIF_F_RXCSUM_BIT,
+					       NETIF_F_LLTX_BIT,
+					       NETIF_F_HIGHDMA_BIT);
 
 		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 a46afc0bf5cc..1e933a9220e9 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
 #include <linux/mdio.h>
@@ -3199,15 +3200,13 @@ 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 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 +3302,21 @@ 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_set(netdev, 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);
 		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_set(vlan_feat, NETIF_F_SG_BIT,
+					NETIF_F_IP_CSUM_BIT, NETIF_F_TSO_BIT,
+					NETIF_F_RXCSUM_BIT,
+					NETIF_F_HW_VLAN_CTAG_RX_BIT);
+		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 9cbce1faab26..964a98ae9556 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_feature_helpers.h>
 #include <linux/pci.h>
 #include <linux/aer.h>
 #include <linux/rtnetlink.h>
@@ -6205,10 +6206,6 @@ 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)
 #define SEGMENT_SIZE 128
 
 static int t4_get_chip_type(struct adapter *adap, int ver)
@@ -6598,6 +6595,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 +6808,48 @@ 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_set(tso_features, NETIF_F_TSO_BIT,
+					NETIF_F_TSO6_BIT, NETIF_F_TSO_ECN_BIT,
+					NETIF_F_GSO_UDP_L4_BIT);
+		netdev->hw_features = tso_features;
+		netdev_hw_features_set_set(netdev, 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);
 
 		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_features |= NETIF_F_GSO_UDP_TUNNEL |
-					       NETIF_F_GSO_UDP_TUNNEL_CSUM |
-					       NETIF_F_HW_TLS_RECORD;
+			netdev_hw_enc_features_set_set(netdev,
+						       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);
+
+			netdev_hw_features_set_set(netdev,
+						   NETIF_F_GSO_UDP_TUNNEL_BIT,
+						   NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+						   NETIF_F_HW_TLS_RECORD_BIT);
 
 			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_set(vlan_features, NETIF_F_SG_BIT,
+					NETIF_F_IP_CSUM_BIT, NETIF_F_GRO_BIT,
+					NETIF_F_IPV6_CSUM_BIT,
+					NETIF_F_HIGHDMA_BIT);
+		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 54db79f4dcfe..e26142ea68de 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/debugfs.h>
 #include <linux/ethtool.h>
@@ -1918,13 +1919,6 @@ static void cxgb4vf_get_wol(struct net_device *dev,
 	memset(&wol->sopass, 0, sizeof(wol->sopass));
 }
 
-/*
- * 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 const struct ethtool_ops cxgb4vf_ethtool_ops = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
 				     ETHTOOL_COALESCE_RX_MAX_FRAMES,
@@ -2895,6 +2889,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 +3063,23 @@ 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_set(tso_features, NETIF_F_TSO_BIT,
+					NETIF_F_TSO6_BIT, NETIF_F_TSO_ECN_BIT);
+		netdev->hw_features = tso_features;
+		netdev_hw_features_set_set(netdev, 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);
 		netdev->features = netdev->hw_features | NETIF_F_HIGHDMA;
-		netdev->vlan_features = netdev->features & VLAN_FEAT;
+		vlan_features = tso_features;
+		netdev_features_set_set(vlan_features, NETIF_F_SG_BIT,
+					NETIF_F_IP_CSUM_BIT, NETIF_F_GRO_BIT,
+					NETIF_F_IPV6_CSUM_BIT,
+					NETIF_F_HIGHDMA_BIT);
+		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 888506185326..0f7727cc47ce 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_feature_helpers.h>
 #include <linux/mii.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -751,7 +752,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_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT);
 
 	return dev;
 }
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 372fb7b3a282..24f9c5497b8a 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
@@ -2892,10 +2893,12 @@ 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 | NETIF_F_HW_CSUM;
+		netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT,
+					   NETIF_F_HW_CSUM_BIT);
 	if (ENIC_SETTING(enic, TSO))
-		netdev->hw_features |= NETIF_F_TSO |
-			NETIF_F_TSO6 | NETIF_F_TSO_ECN;
+		netdev_hw_features_set_set(netdev, NETIF_F_TSO_BIT,
+					   NETIF_F_TSO6_BIT,
+					   NETIF_F_TSO_ECN_BIT);
 	if (ENIC_SETTING(enic, RSS))
 		netdev->hw_features |= NETIF_F_RXHASH;
 	if (ENIC_SETTING(enic, RXCSUM))
@@ -2904,13 +2907,13 @@ 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_set(netdev, 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);
 		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 6dae768671e3..ee85285c4b11 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_feature_helpers.h>
 
 #include <linux/in.h>
 #include <linux/ip.h>
@@ -78,9 +79,8 @@ 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 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
@@ -2624,6 +2624,11 @@ static int __init gemini_ethernet_module_init(void)
 		return ret;
 	}
 
+	netdev_features_set_set(gmac_offload_features, 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);
+
 	return 0;
 }
 module_init(gemini_ethernet_module_init);
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 77229e53b04e..6e274878b962 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
 #include <linux/skbuff.h>
@@ -1644,7 +1645,9 @@ 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;
+		netdev_hw_features_zero(ndev);
+		netdev_hw_features_set_set(ndev, NETIF_F_RXCSUM_BIT,
+					   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 414362febbb9..55c0a66acad2 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_feature_helpers.h>
 #include <net/busy_poll.h>
 #include <net/vxlan.h>
 
@@ -3999,9 +4000,10 @@ 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_set(netdev, NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT,
+				       NETIF_F_TSO6_BIT,
+				       NETIF_F_GSO_UDP_TUNNEL_BIT);
 
 	dev_info(dev, "Enabled VxLAN offloads for UDP port %d\n",
 		 be16_to_cpu(ti->port));
@@ -5186,19 +5188,22 @@ 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_set(netdev, 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);
 	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_set(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				       NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				       NETIF_F_HIGHDMA_BIT);
 
-	netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev_vlan_features_set_set(netdev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
+				     NETIF_F_TSO6_BIT, NETIF_F_IP_CSUM_BIT,
+				     NETIF_F_IPV6_CSUM_BIT);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 9277d5fb5052..f3cdbd10af8a 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1931,9 +1931,11 @@ 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_set(netdev, 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);
 
 	if (priv->use_ncsi)
 		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
@@ -1947,7 +1949,8 @@ static int ftgmac100_probe(struct platform_device *pdev)
 		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);
+		netdev_hw_features_clear_set(netdev, NETIF_F_HW_CSUM_BIT,
+					     NETIF_F_RXCSUM_BIT);
 	netdev->features |= netdev->hw_features;
 
 	/* register network device */
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 0a180d17121c..ea97e40b4194 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_feature_helpers.h>
 #include <linux/skbuff.h>
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
@@ -227,10 +228,10 @@ 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_set(net_dev, 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);
 	/* 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 75d51572693d..2b79cf7b6b69 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_feature_helpers.h>
 #include <linux/kthread.h>
 #include <linux/iommu.h>
 #include <linux/fsl/mc.h>
@@ -4388,10 +4389,12 @@ 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_set(net_dev, 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);
 	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..9f18e88754a4 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -3280,9 +3280,11 @@ 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_set(port_netdev,
+				       NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				       NETIF_F_HW_VLAN_STAG_FILTER_BIT,
+				       NETIF_F_HW_TC_BIT);
 
 	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..7c310a672ddc 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_feature_helpers.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..19c00607ff7c 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_feature_helpers.h>
 #include <linux/fsl/enetc_mdio.h>
 #include <linux/of_platform.h>
 #include <linux/of_mdio.h>
@@ -761,16 +762,23 @@ 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_set(ndev, 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);
+	netdev_active_features_zero(ndev);
+	netdev_active_features_set_set(ndev, 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);
+	netdev_vlan_features_zero(ndev);
+	netdev_vlan_features_set_set(ndev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				     NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 
 	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..d9899932de67 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_feature_helpers.h>
 #include "enetc.h"
 
 #define ENETC_DRV_NAME_STR "ENETC VF driver"
@@ -120,16 +121,22 @@ 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_set(ndev, 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);
+	netdev_active_features_zero(ndev);
+	netdev_active_features_set_set(ndev, 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);
+	netdev_vlan_features_zero(ndev);
+	netdev_vlan_features_set_set(ndev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				     NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 
 	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 ad01db156972..a594e7e90378 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
@@ -3641,8 +3642,10 @@ 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_set(ndev, NETIF_F_IP_CSUM_BIT,
+					       NETIF_F_IPV6_CSUM_BIT,
+					       NETIF_F_RXCSUM_BIT,
+					       NETIF_F_SG_BIT, NETIF_F_TSO_BIT);
 		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..f2d015371e6c 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/if_vlan.h>
@@ -3239,10 +3240,13 @@ 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_set(dev, NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_SG_BIT, NETIF_F_RXCSUM_BIT);
+		netdev_active_features_set_set(dev, NETIF_F_IP_CSUM_BIT,
+					       NETIF_F_SG_BIT,
+					       NETIF_F_RXCSUM_BIT,
+					       NETIF_F_HIGHDMA_BIT);
 	}
 
 	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 b6de2ad82a32..dd2affc863cc 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_feature_helpers.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;
@@ -1711,6 +1704,9 @@ int fun_change_num_queues(struct net_device *dev, unsigned int ntx,
 static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 {
 	struct fun_dev *fdev = &ed->fdev;
+	netdev_features_t gso_encap_flags;
+	netdev_features_t tso_flags;
+	netdev_features_t vlan_feat;
 	struct net_device *netdev;
 	struct funeth_priv *fp;
 	unsigned int ntx, nrx;
@@ -1763,14 +1759,30 @@ 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_zero(gso_encap_flags);
+	netdev_features_zero(tso_flags);
+	netdev_features_set_set(gso_encap_flags, 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);
+	netdev_features_set_set(tso_flags, NETIF_F_TSO_BIT,
+				NETIF_F_TSO6_BIT, NETIF_F_TSO_ECN_BIT,
+				NETIF_F_GSO_UDP_L4_BIT);
+	vlan_feat = gso_encap_flags | tso_flags;
+	netdev_features_set_set(vlan_feat, NETIF_F_SG_BIT,
+				NETIF_F_HW_CSUM_BIT,
+				NETIF_F_HIGHDMA_BIT);
+
+	netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT, NETIF_F_RXHASH_BIT,
+				   NETIF_F_RXCSUM_BIT);
 	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 044db3ebb071..df3a8b786c7a 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_feature_helpers.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
@@ -1588,14 +1589,11 @@ 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_set(dev, 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);
 	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..11f208e479ae 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_feature_helpers.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
 #include <linux/skbuff.h>
@@ -1798,8 +1799,9 @@ 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_set(features, NETIF_F_TSO_BIT,
+					  NETIF_F_TSO6_BIT,
+					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 		break;
 	default:
 		break;
@@ -2323,21 +2325,27 @@ 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_set(ndev, 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);
+	netdev_vlan_features_set_set(ndev, 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);
 
 	/* 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_set(ndev, NETIF_F_TSO_BIT,
+					       NETIF_F_TSO6_BIT,
+					       NETIF_F_NTUPLE_BIT);
+		netdev_hw_features_set_set(ndev, 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);
 		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 82f83e3f8162..e91e1d39800d 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_feature_helpers.h>
 #include <linux/pci.h>
 #include <linux/aer.h>
 #include <linux/skbuff.h>
@@ -3305,17 +3306,23 @@ 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_set(netdev, 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);
 
 	if (hnae3_ae_dev_gro_supported(ae_dev))
 		netdev->features |= NETIF_F_GRO_HW;
@@ -3341,10 +3348,15 @@ 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_set(vlan_off_features,
+				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);
+	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..7ae848678461 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_feature_helpers.h>
 #include <linux/slab.h>
 #include <linux/if_vlan.h>
 #include <linux/semaphore.h>
@@ -918,19 +919,28 @@ static const struct net_device_ops hinicvf_netdev_ops = {
 
 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_set(netdev, 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);
 
 	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_set(netdev, 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 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..1ea3ead47eb1 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -2993,14 +2993,20 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
+				   NETIF_F_IP_CSUM_BIT,
+				   NETIF_F_HW_VLAN_CTAG_TX_BIT);
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_set(dev, 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);
+	netdev_vlan_features_zero(dev);
+	netdev_vlan_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
+				     NETIF_F_HIGHDMA_BIT, NETIF_F_IP_CSUM_BIT);
 	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 0a4d04a8825d..ce8e7d9be073 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -3171,7 +3171,9 @@ 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_set(ndev, NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_SG_BIT);
 		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 ee4548e08446..424ba4a1870c 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1681,10 +1681,10 @@ 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_set(netdev, NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_IPV6_CSUM_BIT,
+					   NETIF_F_RXCSUM_BIT);
 
 	netdev->features |= netdev->hw_features;
 
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 5ab7c0f81e9a..1987bedb5c12 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4870,7 +4870,9 @@ 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_set(adapter->netdev, NETIF_F_SG_BIT,
+				   NETIF_F_GSO_BIT, NETIF_F_GRO_BIT);
 
 	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..16ee3bfa316b 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_feature_helpers.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..9b96bace6707 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -1035,11 +1035,15 @@ 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_set(netdev,
+					   NETIF_F_SG_BIT,
+					   NETIF_F_HW_CSUM_BIT,
+					   NETIF_F_HW_VLAN_CTAG_RX_BIT);
+		netdev_active_features_zero(netdev);
+		netdev_active_features_set_set(netdev,
+					       NETIF_F_HW_VLAN_CTAG_TX_BIT,
+					       NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	}
 
 	if ((hw->mac_type >= e1000_82544) &&
@@ -1049,18 +1053,20 @@ 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_set(netdev,
+				   NETIF_F_RXCSUM_BIT,
+				   NETIF_F_RXALL_BIT,
+				   NETIF_F_RXFCS_BIT);
 
 	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_set(netdev,
+				     NETIF_F_TSO_BIT,
+				     NETIF_F_HW_CSUM_BIT,
+				     NETIF_F_SG_BIT);
 
 	/* 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 56984803c957..f716cefb46b4 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_feature_helpers.h>
 #include <linux/interrupt.h>
 #include <linux/tcp.h>
 #include <linux/ipv6.h>
@@ -7316,13 +7317,17 @@ static int e1000_set_features(struct net_device *netdev,
 {
 	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_set(changeable, 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);
+	if (!(changed & changeable))
 		return 0;
 
 	if (changed & NETIF_F_RXFCS) {
@@ -7523,14 +7528,13 @@ 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_set(netdev, 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);
 
 	/* Set user-changeable features (subset of all device features) */
 	netdev->hw_features = netdev->features;
@@ -7541,10 +7545,8 @@ 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_set(netdev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
+				     NETIF_F_TSO6_BIT, NETIF_F_HW_CSUM_BIT);
 
 	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..d0790e2b8a92 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_feature_helpers.h>
 
 /**
  * fm10k_setup_tx_resources - allocate Tx resources (Descriptors)
@@ -1557,24 +1558,27 @@ 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_set(dev,
+				       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);
 
 	/* 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_set(dev,
+					       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);
 
 		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 5e60ff79450d..fd2cac55cb31 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_feature_helpers.h>
 
 /* Local includes */
 #include "i40e.h"
@@ -13629,6 +13630,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;
 
@@ -13641,25 +13643,18 @@ 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_set(hw_enc_features, 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);
 
 	if (!(pf->hw_features & I40E_HW_OUTER_UDP_CSUM_CAPABLE))
 		netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
@@ -13673,22 +13668,21 @@ 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_set(gso_partial_features, 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);
+	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_set(netdev, NETIF_F_SG_BIT,
+				     NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_BIT,
+				     NETIF_F_TSO6_BIT);
+	netdev->mpls_features |= gso_partial_features;
 
 	/* enable macvlan offloads */
 	netdev->hw_features |= NETIF_F_HW_L2FW_DOFFLOAD;
@@ -13698,7 +13692,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 		      NETIF_F_HW_VLAN_CTAG_RX;
 
 	if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
-		hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;
+		netdev_features_set_set(hw_features, NETIF_F_NTUPLE_BIT,
+					NETIF_F_HW_TC_BIT);
 
 	netdev->hw_features |= hw_features;
 
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
index 3f6187c16424..5f19135f50d2 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_feature_helpers.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 1671e52b6ba2..34d55e5b461c 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4725,31 +4725,31 @@ 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_set(hw_enc_features,
+				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);
 
 	/* 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_set(hw_enc_features,
+					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);
 
 		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 001500afc4a6..f8182f31302d 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_feature_helpers.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 7f59050e4122..dab06a6c12d2 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3327,20 +3327,26 @@ 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_set(netdev, NETIF_F_SG_BIT,
+					       NETIF_F_HIGHDMA_BIT);
 		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_set(dflt_features,
+				NETIF_F_SG_BIT,
+				NETIF_F_HIGHDMA_BIT,
+				NETIF_F_NTUPLE_BIT,
+				NETIF_F_RXHASH_BIT);
 
-	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_set(csumo_features,
+				NETIF_F_RXCSUM_BIT,
+				NETIF_F_IP_CSUM_BIT,
+				NETIF_F_SCTP_CRC_BIT,
+				NETIF_F_IPV6_CSUM_BIT);
 
 	vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER |
 			 NETIF_F_HW_VLAN_CTAG_TX     |
@@ -3350,28 +3356,33 @@ 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->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM |
-					NETIF_F_GSO_GRE_CSUM;
+	netdev_features_zero(tso_features);
+	netdev_features_set_set(tso_features,
+				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);
+
+	netdev_gso_partial_features_set_set(netdev,
+					    NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+					    NETIF_F_GSO_GRE_CSUM_BIT);
 	/* set features that user can change */
 	netdev->hw_features = dflt_features | csumo_features |
 			      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_set(netdev,
+				     NETIF_F_HW_CSUM_BIT,
+				     NETIF_F_TSO_BIT,
+				     NETIF_F_TSO6_BIT);
 
 	/* 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 ff0c7f0bf07a..af656420ec4d 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_feature_helpers.h>
 #include <linux/ipv6.h>
 #include <linux/slab.h>
 #include <net/checksum.h>
@@ -2511,21 +2512,27 @@ 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_set(features,
+					  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);
+		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_set(features,
+					  NETIF_F_HW_CSUM_BIT,
+					  NETIF_F_SCTP_CRC_BIT,
+					  NETIF_F_GSO_UDP_L4_BIT,
+					  NETIF_F_TSO_BIT,
+					  NETIF_F_TSO6_BIT);
+		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.
@@ -3164,6 +3171,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,34 +3276,39 @@ 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_set(netdev,
+				       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);
 
 	if (hw->mac.type >= e1000_82576)
-		netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_GSO_UDP_L4;
+		netdev_active_features_set_set(netdev,
+					       NETIF_F_SCTP_CRC_BIT,
+					       NETIF_F_GSO_UDP_L4_BIT);
 
 	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_set(gso_partial_features,
+				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);
+	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 |
-			       NETIF_F_HW_VLAN_CTAG_RX |
-			       NETIF_F_HW_VLAN_CTAG_TX |
-			       NETIF_F_RXALL;
+	netdev->hw_features |= netdev->features;
+	netdev_hw_features_set_set(netdev,
+				   NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				   NETIF_F_RXALL_BIT);
 
 	if (hw->mac.type >= e1000_i350)
 		netdev->hw_features |= NETIF_F_NTUPLE;
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index f4e91db89fe5..2964afacac72 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_feature_helpers.h>
 #include <linux/tcp.h>
 #include <linux/ipv6.h>
 #include <linux/slab.h>
@@ -2626,19 +2627,25 @@ 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_set(features,
+					  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);
+		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_set(features,
+					  NETIF_F_HW_CSUM_BIT,
+					  NETIF_F_SCTP_CRC_BIT,
+					  NETIF_F_TSO_BIT,
+					  NETIF_F_TSO6_BIT);
+		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.
@@ -2684,6 +2691,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 +2766,26 @@ 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_set(netdev,
+				   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);
+
+	netdev_features_zero(gso_partial_features);
+	netdev_features_set_set(gso_partial_features,
+				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);
+
+	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..dc0e3aee643b 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_feature_helpers.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 bf6c461e1a2a..63f30912cada 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_feature_helpers.h>
 #include <net/pkt_sched.h>
 #include <linux/bpf_trace.h>
 #include <net/xdp_sock_drv.h>
@@ -5019,19 +5020,25 @@ 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_set(features,
+					  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);
+		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_set(features,
+					  NETIF_F_HW_CSUM_BIT,
+					  NETIF_F_SCTP_CRC_BIT,
+					  NETIF_F_TSO_BIT,
+					  NETIF_F_TSO6_BIT);
+		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.
@@ -6257,6 +6264,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);
@@ -6337,24 +6345,26 @@ 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_set(netdev,
+				       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);
+
+	netdev_features_zero(gso_partial_features);
+	netdev_features_set_set(gso_partial_features,
+				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);
+	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..51e89e9aefcb 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_feature_helpers.h>
 #include <linux/prefetch.h>
 #include "ixgb.h"
 
@@ -428,11 +429,13 @@ 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_set(netdev,
+				   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);
 	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 298cfbfcb7b6..38f553e0411e 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_feature_helpers.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
 #include <linux/in.h>
@@ -10221,21 +10222,27 @@ 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_set(features,
+					  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);
+		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_set(features,
+					  NETIF_F_HW_CSUM_BIT,
+					  NETIF_F_SCTP_CRC_BIT,
+					  NETIF_F_GSO_UDP_L4_BIT,
+					  NETIF_F_TSO_BIT,
+					  NETIF_F_TSO6_BIT);
+		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.
@@ -10772,6 +10779,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,56 +10966,64 @@ 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_set(netdev,
+				       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);
+
+	netdev_features_zero(gso_partial_features);
+	netdev_features_set_set(gso_partial_features,
+				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);
+
+	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;
+		netdev_hw_features_set_set(netdev,
+					   NETIF_F_SCTP_CRC_BIT,
+					   NETIF_F_GSO_UDP_L4_BIT);
 
 #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_set(netdev,
+					       NETIF_F_HW_ESP_BIT,
+					       NETIF_F_HW_ESP_TX_CSUM_BIT,
+					       NETIF_F_GSO_ESP_BIT);
 #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_set(netdev,
+				   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);
 
 	if (hw->mac.type >= ixgbe_mac_82599EB)
-		netdev->hw_features |= NETIF_F_NTUPLE |
-				       NETIF_F_HW_TC;
+		netdev_active_features_set_set(netdev,
+					       NETIF_F_NTUPLE_BIT,
+					       NETIF_F_HW_TC_BIT);
 
 	netdev->features |= NETIF_F_HIGHDMA;
 
 	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_set(netdev,
+				     NETIF_F_SG_BIT,
+				     NETIF_F_TSO_BIT,
+				     NETIF_F_TSO6_BIT,
+				     NETIF_F_HW_CSUM_BIT);
+	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 +11056,13 @@ 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_set(netdev,
+					       NETIF_F_FSO_BIT,
+					       NETIF_F_FCOE_CRC_BIT);
+		netdev_vlan_features_set_set(netdev,
+					     NETIF_F_FSO_BIT,
+					     NETIF_F_FCOE_CRC_BIT,
+					     NETIF_F_FCOE_MTU_BIT);
 	}
 #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..ae7ec049e020 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
@@ -651,12 +651,14 @@ 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_set(adapter->netdev,
+				       NETIF_F_HW_ESP_BIT,
+				       NETIF_F_HW_ESP_TX_CSUM_BIT,
+				       NETIF_F_GSO_ESP_BIT);
+	netdev_hw_enc_features_set_set(adapter->netdev,
+				       NETIF_F_HW_ESP_BIT,
+				       NETIF_F_HW_ESP_TX_CSUM_BIT,
+				       NETIF_F_GSO_ESP_BIT);
 
 	return;
 
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 149c733fcc2b..2fa9286e0975 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_feature_helpers.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..248fb4b58166 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_feature_helpers.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
 #include <linux/in.h>
@@ -4407,19 +4408,25 @@ 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_set(features,
+					  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);
+		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_set(features,
+					  NETIF_F_HW_CSUM_BIT,
+					  NETIF_F_SCTP_CRC_BIT,
+					  NETIF_F_TSO_BIT,
+					  NETIF_F_TSO6_BIT);
+		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.
@@ -4521,6 +4528,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 +4601,37 @@ 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_set(netdev,
+				   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);
+
+	netdev_features_zero(gso_partial_features);
+	netdev_features_set_set(gso_partial_features,
+				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);
+	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_set(netdev,
+				     NETIF_F_SG_BIT,
+				     NETIF_F_TSO_BIT,
+				     NETIF_F_TSO6_BIT,
+				     NETIF_F_HW_CSUM_BIT);
+	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 b56594407965..6eb610dce765 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -2955,19 +2956,23 @@ 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_set(netdev,
+				   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);
+	netdev_active_features_zero(netdev);
+	netdev_active_features_set_set(netdev,
+				       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);
 	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 8b9abe622489..0891bbe7d95e 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_feature_helpers.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
@@ -3200,7 +3201,9 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_TSO_BIT);
 	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 b500fe1dfa81..cb54394aad51 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_feature_helpers.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -3847,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);
+		netdev_features_clear_set(features, NETIF_F_IP_CSUM_BIT,
+					  NETIF_F_TSO_BIT);
 		netdev_info(dev,
 			    "Disable IP checksum for MTU greater than %dB\n",
 			    pp->tx_csum_limit);
@@ -5612,8 +5614,10 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT,
+				       NETIF_F_RXCSUM_BIT);
 	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 38e5b4be6a4d..be0b95342b1d 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/skbuff.h>
@@ -6846,11 +6847,13 @@ 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_set(features, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
+				NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT);
 	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_set(dev, NETIF_F_RXCSUM_BIT, NETIF_F_GRO_BIT,
+				   NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	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 49a4ff01cecb..1c94b41927a7 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_feature_helpers.h>
 
 #include "otx2_reg.h"
 #include "otx2_common.h"
@@ -2744,10 +2745,12 @@ 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_set(netdev, 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);
 	netdev->features |= netdev->hw_features;
 
 	err = otx2_mcam_flow_init(pf);
@@ -2773,7 +2776,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_set_set(netdev, NETIF_F_LOOPBACK_BIT,
+				   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 86653bb8e403..7fdcf33a35e7 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_feature_helpers.h>
 #include <linux/pci.h>
 #include <linux/net_tstamp.h>
 
@@ -637,10 +638,12 @@ 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_set(netdev, 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);
 	netdev->features = netdev->hw_features;
 	/* Support TSO on tag interface */
 	netdev->vlan_features |= netdev->features;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c
index 3956d6d5df3c..470b059443b8 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_feature_helpers.h>
 #include <linux/of.h>
 #include <linux/of_net.h>
 #include <linux/if_vlan.h>
@@ -627,7 +628,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;
+	netdev_active_features_set_set(dev, NETIF_F_NETNS_LOCAL_BIT,
+				       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 bcc4aa59d10a..424bd88a0946 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/pci.h>
@@ -3860,8 +3861,9 @@ 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_set(dev, NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_SG_BIT, NETIF_F_RXCSUM_BIT);
 		dev->features |= dev->hw_features;
 	}
 
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index e19acfcd84d4..90c5297c791f 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_feature_helpers.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);
 	}
 }
 
@@ -4634,7 +4638,8 @@ 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_set(dev, NETIF_F_IP_CSUM_BIT, NETIF_F_SG_BIT,
+				   NETIF_F_TSO_BIT);
 
 	if (highmem)
 		dev->features |= NETIF_F_HIGHDMA;
@@ -4646,7 +4651,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..ff4395638546 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_feature_helpers.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..2561daf63151 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_feature_helpers.h>
 #include <net/ip.h>
 #include <net/vxlan.h>
 #include <net/devlink.h>
@@ -3322,41 +3323,49 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
+				   NETIF_F_IPV6_CSUM_BIT);
 	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_set(dev, NETIF_F_GSO_UDP_TUNNEL_BIT,
+					   NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+					   NETIF_F_GSO_PARTIAL_BIT);
+		netdev_active_features_set_set(dev, NETIF_F_GSO_UDP_TUNNEL_BIT,
+					       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+					       NETIF_F_GSO_PARTIAL_BIT);
 		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_set(dev, 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);
 
 		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_set(dev, NETIF_F_RXCSUM_BIT, NETIF_F_RXHASH_BIT);
+	dev->features = dev->hw_features;
+	netdev_active_features_set_set(dev, 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);
+	netdev_hw_features_set_set(dev, NETIF_F_LOOPBACK_BIT,
+				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	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;
+		netdev_active_features_set_set(dev, NETIF_F_HW_VLAN_STAG_RX_BIT,
+					       NETIF_F_HW_VLAN_STAG_FILTER_BIT);
 		dev->hw_features |= NETIF_F_HW_VLAN_STAG_RX;
 	}
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 13aac5131ff7..841e4fb520d7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -34,6 +34,7 @@
 
 #include <linux/if_vlan.h>
 #include <linux/etherdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/timecounter.h>
 #include <linux/net_tstamp.h>
 #include <linux/crash_dump.h>
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 905025a10a8a..8b1be6bfb475 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4920,31 +4920,33 @@ 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_set_set(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT,
+					   NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+		netdev_hw_enc_features_set_set(netdev,
+					       NETIF_F_GSO_UDP_TUNNEL_BIT,
+					       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 		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_set_set(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT,
+					     NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	}
 
 	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_set_set(netdev, NETIF_F_GSO_GRE_BIT,
+					   NETIF_F_GSO_GRE_CSUM_BIT);
+		netdev_hw_enc_features_set_set(netdev, NETIF_F_GSO_GRE_BIT,
+					       NETIF_F_GSO_GRE_CSUM_BIT);
+		netdev_gso_partial_features_set_set(netdev, NETIF_F_GSO_GRE_BIT,
+						    NETIF_F_GSO_GRE_CSUM_BIT);
 	}
 
 	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_set_set(netdev, NETIF_F_GSO_IPXIP4_BIT,
+					   NETIF_F_GSO_IPXIP6_BIT);
+		netdev_hw_enc_features_set_set(netdev, NETIF_F_GSO_IPXIP4_BIT,
+					       NETIF_F_GSO_IPXIP6_BIT);
+		netdev_gso_partial_features_set_set(netdev,
+						    NETIF_F_GSO_IPXIP4_BIT,
+						    NETIF_F_GSO_IPXIP6_BIT);
 	}
 
 	netdev->gso_partial_features             |= NETIF_F_GSO_UDP_L4;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 5bcf5bceff71..72aa22236ffa 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/slab.h>
@@ -1682,9 +1683,12 @@ 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_set(dev, 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);
+	netdev_hw_features_set_set(dev, NETIF_F_HW_TC_BIT,
+				   NETIF_F_LOOPBACK_BIT);
 
 	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 468520079c65..02c666cc48e6 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_feature_helpers.h>
 
 
 /* DMA Registers */
@@ -6705,7 +6706,9 @@ 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_set(dev, NETIF_F_IP_CSUM_BIT, NETIF_F_SG_BIT,
+				   NETIF_F_RXCSUM_BIT);
 
 	/*
 	 * 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 2599dfffd1da..934d9e2c4008 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/crc32.h>
 #include <linux/microchipphy.h>
@@ -3394,8 +3395,10 @@ 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 | NETIF_F_RXCSUM;
+	netdev_active_features_zero(adapter->netdev);
+	netdev_active_features_set_set(adapter->netdev, NETIF_F_SG_BIT,
+				       NETIF_F_TSO_BIT, NETIF_F_HW_CSUM_BIT,
+				       NETIF_F_RXCSUM_BIT);
 	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..68962a6c0bbd 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2081,10 +2081,11 @@ 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_set(ndev, 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);
 	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 2979fb1ba0f7..a2db1db99c4b 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_feature_helpers.h>
 #include <linux/of_net.h>
 #include <linux/phy/phy.h>
 #include <net/pkt_cls.h>
@@ -1854,9 +1855,10 @@ 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_set(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				   NETIF_F_RXFCS_BIT, NETIF_F_HW_TC_BIT);
+	netdev_active_features_set_set(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				       NETIF_F_HW_TC_BIT);
 
 	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 9063e2e22cd5..8873cdcadb0f 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_feature_helpers.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;
@@ -687,7 +688,9 @@ static int myri10ge_get_firmware_capabilities(struct myri10ge_priv *mgp)
 	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_set(mgp->features, NETIF_F_SG_BIT,
+				NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_BIT);
 	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 d8a77b0db50d..4d69c006dcaa 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/mdio.h>
 #include <linux/skbuff.h>
@@ -7853,12 +7854,15 @@ 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_set(dev, 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);
+	dev->features |= dev->hw_features;
+	netdev_active_features_set_set(dev, NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				       NETIF_F_HW_VLAN_CTAG_RX_BIT,
+				       NETIF_F_HIGHDMA_BIT);
 	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/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 469c3939c306..e6d11d509145 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
 #include <linux/ip.h>
@@ -2377,9 +2378,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_set_set(netdev,
+						   NETIF_F_GSO_UDP_TUNNEL_BIT,
+						   NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+						   NETIF_F_GSO_PARTIAL_BIT);
 			netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
 		}
 		netdev->udp_tunnel_nic_info = &nfp_udp_tunnels;
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 7c0675ca337b..7afbd49551bc 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
@@ -5811,8 +5812,9 @@ 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_set(dev, NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
+					   NETIF_F_RXCSUM_BIT);
 	}
 
 	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..ab519deead53 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_feature_helpers.h>
 #include <linux/net_tstamp.h>
 #include <linux/ptp_classify.h>
 #include <linux/ptp_pch.h>
@@ -2518,8 +2519,9 @@ 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_set(netdev, NETIF_F_RXCSUM_BIT,
+				   NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT);
 	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..42a0f3fbd649 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -1699,8 +1699,10 @@ 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_set(dev, NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_LLTX_BIT, NETIF_F_SG_BIT,
+				       NETIF_F_HIGHDMA_BIT, NETIF_F_GSO_BIT);
 
 	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 0be79c516781..6930603e1698 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
 #include <linux/rtnetlink.h>
@@ -1486,15 +1487,17 @@ 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_set(features,
+				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);
 
 	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..5f950dfed66c 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_feature_helpers.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
@@ -1347,11 +1348,13 @@ 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_set(netdev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
+				   NETIF_F_TSO_BIT, NETIF_F_RXCSUM_BIT);
 
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		netdev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+		netdev_hw_features_set_set(netdev, NETIF_F_IPV6_CSUM_BIT,
+					   NETIF_F_TSO6_BIT);
 
 	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 3c1bfff29157..7fc2fed4472f 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_feature_helpers.h>
 #include <linux/udp.h>
 #include <linux/tcp.h>
 #include <net/udp_tunnel.h>
@@ -850,9 +851,12 @@ 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_set(hw_features, 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);
 
 	if (edev->dev_info.common.b_arfs_capable)
 		hw_features |= NETIF_F_NTUPLE;
@@ -863,32 +867,41 @@ 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_set(ndev, 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);
 	}
 
 	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);
+		netdev_features_set_set(hw_features, NETIF_F_GSO_UDP_TUNNEL_BIT,
+					NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+		netdev_hw_enc_features_set_set(ndev, NETIF_F_GSO_UDP_TUNNEL_BIT,
+					       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 | NETIF_F_GSO_GRE_CSUM);
-		ndev->hw_enc_features |= (NETIF_F_GSO_GRE |
-					  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;
+		netdev_features_set_set(hw_features, NETIF_F_GSO_GRE_BIT,
+					NETIF_F_GSO_GRE_CSUM_BIT);
+		netdev_hw_enc_features_set_set(ndev, NETIF_F_GSO_GRE_BIT,
+					       NETIF_F_GSO_GRE_CSUM_BIT);
+	}
+
+	ndev->vlan_features = hw_features;
+	netdev_vlan_features_set_set(ndev, NETIF_F_RXHASH_BIT,
+				     NETIF_F_RXCSUM_BIT, NETIF_F_HIGHDMA_BIT);
+	ndev->features = hw_features;
+	netdev_active_features_set_set(ndev, 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);
 
 	ndev->hw_features = hw_features;
 
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 31e3ab149727..5777ca67a327 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/skbuff.h>
@@ -3796,7 +3797,8 @@ static int ql3xxx_probe(struct pci_dev *pdev,
 
 	ndev->features |= NETIF_F_HIGHDMA;
 	if (qdev->device_id == QL3032_DEVICE_ID)
-		ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+		netdev_active_features_set_set(ndev, NETIF_F_IP_CSUM_BIT,
+					       NETIF_F_SG_BIT);
 
 	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 4b8bc46f55c2..a68d14f6068f 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_feature_helpers.h>
 
 #include "qlcnic.h"
 #include "qlcnic_hdr.h"
@@ -1026,8 +1027,9 @@ static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
 	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_set(features, NETIF_F_RXCSUM_BIT,
+					NETIF_F_IP_CSUM_BIT,
+					NETIF_F_IPV6_CSUM_BIT);
 		adapter->rx_csum = 1;
 		if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
 			if (!(offload_flags & BIT_1))
@@ -1041,9 +1043,9 @@ 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_set(features, NETIF_F_RXCSUM_BIT,
+					  NETIF_F_IP_CSUM_BIT,
+					  NETIF_F_IPV6_CSUM_BIT);
 
 		if (QLCNIC_IS_TSO_CAPABLE(adapter))
 			features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
@@ -1057,6 +1059,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 +1068,14 @@ 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_set(changeable,
+						NETIF_F_RXCSUM_BIT,
+						NETIF_F_IP_CSUM_BIT,
+						NETIF_F_IPV6_CSUM_BIT,
+						NETIF_F_TSO_BIT,
+						NETIF_F_TSO6_BIT);
+			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..c118ab110fd5 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_feature_helpers.h>
 #include <linux/pci.h>
 #include <net/vxlan.h>
 
@@ -2276,11 +2277,14 @@ 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_set(netdev, 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);
+	netdev_vlan_features_set_set(netdev, NETIF_F_SG_BIT,
+				     NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT,
+				     NETIF_F_HIGHDMA_BIT);
 
 	if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
 		netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
@@ -2300,10 +2304,11 @@ 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_hw_enc_features_zero(netdev);
+		netdev_hw_enc_features_set_set(netdev, NETIF_F_IP_CSUM_BIT,
+					       NETIF_F_GSO_UDP_TUNNEL_BIT,
+					       NETIF_F_TSO_BIT,
+					       NETIF_F_TSO6_BIT);
 	}
 
 	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..986a12eb1d67 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_feature_helpers.h>
 #include <linux/of.h>
 #include <linux/of_net.h>
 #include <linux/of_device.h>
@@ -665,13 +666,17 @@ 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_set(netdev, 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);
 	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_set(netdev, NETIF_F_SG_BIT,
+				     NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_BIT,
+				     NETIF_F_TSO6_BIT);
 
 	/* 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..3532f47190bc 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_feature_helpers.h>
 #include <net/pkt_sched.h>
 #include "rmnet_config.h"
 #include "rmnet_handlers.h"
@@ -261,9 +262,10 @@ 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_set(rmnet_dev, NETIF_F_RXCSUM_BIT,
+				   NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT,
+				   NETIF_F_SG_BIT);
 
 	priv->real_dev = real_dev;
 
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index f5786d78ed23..8543fc682d12 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -1990,16 +1991,20 @@ 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_set(dev, 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);
 
 	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_set(dev, 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);
+	netdev_vlan_features_zero(dev);
+	netdev_vlan_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
+				     NETIF_F_TSO_BIT, NETIF_F_HIGHDMA_BIT);
 
 	/* 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 ab424b5b4920..8c7b6b80dbd9 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/delay.h>
@@ -1008,7 +1009,8 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				       NETIF_F_HIGHDMA_BIT);
 	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 f6f63ba6593a..e44a553398f2 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -5239,9 +5240,13 @@ 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_set(dev, NETIF_F_IP_CSUM_BIT, NETIF_F_RXCSUM_BIT,
+				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
+	netdev_vlan_features_zero(dev);
+	netdev_vlan_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
+				     NETIF_F_TSO_BIT);
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
 	/*
@@ -5267,7 +5272,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;
+		netdev_hw_features_set_set(dev, NETIF_F_SG_BIT,
+					   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);
 	}
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 9e7b62750bb0..dd21b60ec33c 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_feature_helpers.h>
 #include <linux/skbuff.h>
 #include <linux/socket.h>
 #include <linux/etherdevice.h>
@@ -2578,7 +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 | NETIF_F_SG;
+	netdev_active_features_set_set(dev, NETIF_F_NETNS_LOCAL_BIT,
+				       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 a1c10b61269b..37428e2d4f3d 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_feature_helpers.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
 #include <linux/prefetch.h>
@@ -2105,9 +2106,11 @@ 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_set(ndev, 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);
 	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..74f3af39f132 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1356,8 +1356,12 @@ 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_set(encap_tso_features,
+					NETIF_F_GSO_UDP_TUNNEL_BIT,
+					NETIF_F_GSO_GRE_BIT,
+					NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
+					NETIF_F_GSO_GRE_CSUM_BIT);
 
 		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..7568230083e8 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -370,8 +370,9 @@ 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_set(net_dev, NETIF_F_HW_CSUM_BIT,
+				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT);
 	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..2c8ecb2fdf98 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -188,10 +188,15 @@ 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_set(tso, 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);
 		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 054d5ce6029e..b16c6aeb9c38 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1001,17 +1001,19 @@ 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_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
+				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
 	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_set(net_dev, NETIF_F_HW_CSUM_BIT,
+				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
+				     NETIF_F_RXCSUM_BIT);
 
 	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 f18418e07eb8..0a07a52fe180 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2901,9 +2901,9 @@ 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_set(net_dev, NETIF_F_HW_CSUM_BIT,
+				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
+				     NETIF_F_RXCSUM_BIT);
 	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..e876ac952cbc 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_feature_helpers.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..0f49fe683008 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_feature_helpers.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 60e5b7c8ccf9..ef3c5d16c4f5 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/notifier.h>
@@ -983,17 +984,19 @@ 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_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
+				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
 	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_set(net_dev, NETIF_F_HW_CSUM_BIT,
+				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
+				     NETIF_F_RXCSUM_BIT);
 
 	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 8fc3f5272fa7..de799075704a 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -926,8 +926,12 @@ 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_set(dev, NETIF_F_IP_CSUM_BIT,
+				   NETIF_F_RXCSUM_BIT);
+	netdev_active_features_zero(dev);
+	netdev_active_features_set_set(dev, NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_HIGHDMA_BIT);
 
 	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..b26446e85965 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -1437,8 +1438,10 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
+				       NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_IPV6_CSUM_BIT);
 
 	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 85e62f5489b6..af4fc0b60a7e 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_feature_helpers.h>
 #include <linux/netlink.h>
 #include <linux/bpf.h>
 #include <linux/bpf_trace.h>
@@ -2098,8 +2099,10 @@ 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_set(ndev, NETIF_F_HIGHDMA_BIT,
+				       NETIF_F_RXCSUM_BIT, NETIF_F_GSO_BIT,
+				       NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_IPV6_CSUM_BIT);
 	ndev->hw_features = ndev->features;
 
 	priv->rx_cksum_offload_flag = true;
diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c
index ee341a383e69..e17193624604 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_feature_helpers.h>
 #include <linux/of_net.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
@@ -1594,8 +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 | NETIF_F_RXCSUM);
-	ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_RXCSUM);
+	netdev_active_features_set_set(ndev, NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_RXCSUM_BIT);
+	netdev_hw_features_set_set(ndev, NETIF_F_IP_CSUM_BIT,
+				   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 8418e795cc21..f4e7007e1f0c 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_feature_helpers.h>
 #include <linux/net_tstamp.h>
 #include <linux/phylink.h>
 #include <linux/udp.h>
@@ -7117,8 +7118,9 @@ 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_set(ndev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
+				   NETIF_F_IPV6_CSUM_BIT, NETIF_F_RXCSUM_BIT);
 
 	ret = stmmac_tc_init(priv, priv);
 	if (!ret) {
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index 19a3eb6efc3a..0f5a60bb69fa 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -5057,7 +5058,8 @@ 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 | NETIF_F_SG;
+		netdev_active_features_set_set(dev, NETIF_F_HW_CSUM_BIT,
+					       NETIF_F_SG_BIT);
 
 	dev->features |= NETIF_F_HIGHDMA;
 
diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c
index bc51a75a0e19..eaf2b6d8c187 100644
--- a/drivers/net/ethernet/sun/ldmvsw.c
+++ b/drivers/net/ethernet/sun/ldmvsw.c
@@ -246,7 +246,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_set(dev, NETIF_F_HW_CSUM_BIT, NETIF_F_SG_BIT);
 	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 204a29e72292..1b4d6b2f57ec 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_feature_helpers.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
@@ -9735,7 +9736,9 @@ static void niu_device_announce(struct niu *np)
 
 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_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_RXHASH_BIT);
 	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 6fb89c55f957..443537075d55 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/mii.h>
@@ -2989,7 +2990,9 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_RXCSUM_BIT);
 	dev->features = dev->hw_features;
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index 1921054b7f7d..fd99c2e677b1 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_feature_helpers.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 | NETIF_F_HW_CSUM;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT);
 	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
 
 	hp->irq = op->archdata.irqs[0];
@@ -3104,7 +3106,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 | NETIF_F_HW_CSUM;
+	netdev_hw_features_zero(dev);
+	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT);
 	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index 042b50227850..469a1f9cc2fc 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -314,8 +314,9 @@ 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_set(dev, NETIF_F_TSO_BIT, NETIF_F_GSO_BIT,
+				   NETIF_F_HW_CSUM_BIT, NETIF_F_SG_BIT);
 	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 08ba658db987..b0dee4f3f23f 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -1976,13 +1976,19 @@ 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;
-
-		ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
-			NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_active_features_zero(ndev);
+		netdev_active_features_set_set(ndev, 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);
+
+		netdev_hw_features_zero(ndev);
+		netdev_hw_features_set_set(ndev, NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
+					   NETIF_F_HW_VLAN_CTAG_TX_BIT);
 
 	/************** 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..c1f70f9b0786 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_feature_helpers.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 7ef5d8208a4e..728aaba3fef2 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_feature_helpers.h>
 #include <linux/net_tstamp.h>
 #include <linux/of.h>
 #include <linux/of_mdio.h>
@@ -1977,10 +1978,10 @@ 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_set(port->ndev, NETIF_F_SG_BIT,
+				   NETIF_F_RXCSUM_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_HW_TC_BIT);
 	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.c b/drivers/net/ethernet/ti/cpsw.c
index 312250c642bb..de8b0529b2bd 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_feature_helpers.h>
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/phy/phy.h>
@@ -1456,7 +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 | NETIF_F_HW_VLAN_CTAG_RX;
+	netdev_active_features_set_set(ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				       NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_ops;
@@ -1633,7 +1635,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;
+	netdev_active_features_set_set(ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				       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/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index 007de15179f0..70f9dcf2d572 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_feature_helpers.h>
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/phy/phy.h>
@@ -1403,9 +1404,11 @@ 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_set(ndev,
+					       NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+					       NETIF_F_HW_VLAN_CTAG_RX_BIT,
+					       NETIF_F_NETNS_LOCAL_BIT,
+					       NETIF_F_HW_TC_BIT);
 		ndev->netdev_ops = &cpsw_netdev_ops;
 		ndev->ethtool_ops = &cpsw_ethtool_ops;
 		SET_NETDEV_DEV(ndev, dev);
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 6e838e8f79d0..9e9eb2f4efda 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -1461,7 +1461,9 @@ 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_zero(netdev);
+	netdev_hw_features_set_set(netdev, NETIF_F_IP_CSUM_BIT,
+				   NETIF_F_RXCSUM_BIT);
 
 	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..0d02fc2cdfff 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -2275,10 +2275,13 @@ 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_zero(netdev);
+	netdev_hw_features_set_set(netdev, NETIF_F_RXCSUM_BIT,
+				   NETIF_F_IP_CSUM_BIT);
 	if (SPIDER_NET_RX_CSUM_DEFAULT)
 		netdev->features |= NETIF_F_RXCSUM;
-	netdev->features |= NETIF_F_IP_CSUM | NETIF_F_LLTX;
+	netdev_active_features_set_set(netdev, NETIF_F_IP_CSUM_BIT,
+				       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/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 29cde0bec4b1..5c94afc768b2 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
@@ -968,7 +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|NETIF_F_HW_CSUM;
+		netdev_active_features_set_set(dev, NETIF_F_SG_BIT,
+					       NETIF_F_HW_CSUM_BIT);
 
 	if (rp->quirks & rqMgmt)
 		dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index 5d710ebb9680..558a520376bc 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
@@ -2848,11 +2849,13 @@ 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_set(netdev, NETIF_F_IP_CSUM_BIT, NETIF_F_SG_BIT,
+				   NETIF_F_HW_VLAN_CTAG_TX_BIT);
+	netdev_active_features_set_set(netdev, 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);
 
 	/* MTU range: 64 - 9000 */
 	netdev->min_mtu = VELOCITY_MIN_MTU;
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index f393e454f45c..bdf8624995f5 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_feature_helpers.h>
 #include <net/ipv6_stubs.h>
 #include <net/dst_metadata.h>
 #include <net/gro_cells.h>
@@ -1245,13 +1246,14 @@ 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_set(dev, NETIF_F_LLTX_BIT,
+				       NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				       NETIF_F_FRAGLIST_BIT,
+				       NETIF_F_RXCSUM_BIT);
 	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_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_FRAGLIST_BIT, NETIF_F_RXCSUM_BIT);
 	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
 
 	/* MTU range: 68 - (something less than 65535) */
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 25b38a374e3c..a5f3c033605f 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -873,10 +873,8 @@ 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)
+extern netdev_features_t netvsc_supported_hw_features __ro_after_init;
+#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/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 5f08482065ca..f438a98cd2f4 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_feature_helpers.h>
 #include <linux/inetdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/pci.h>
@@ -52,6 +53,8 @@ static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
 				NETIF_MSG_IFDOWN | NETIF_MSG_RX_ERR |
 				NETIF_MSG_TX_ERR;
 
+netdev_features_t netvsc_supported_hw_features __ro_after_init;
+
 static int debug = -1;
 module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
@@ -2533,9 +2536,10 @@ 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_set(net, NETIF_F_HIGHDMA_BIT,
+				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				       NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	net->vlan_features = net->features;
 
 	netdev_lockdep_set_classes(net);
@@ -2769,6 +2773,16 @@ static int __init netvsc_drv_init(void)
 	if (ret)
 		return ret;
 
+	netdev_features_set_set(netvsc_supported_hw_features,
+				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);
+
 	register_netdevice_notifier(&netvsc_netdev_notifier);
 	return 0;
 }
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 1c64d5347b8e..56dcf6677cdf 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_feature_helpers.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -288,11 +289,6 @@ 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 void ifb_dev_free(struct net_device *dev)
 {
 	struct ifb_dev_private *dp = netdev_priv(dev);
@@ -309,6 +305,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 +315,16 @@ 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_set(ifb_features, 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);
+	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 54c94a69c2bb..a4f461ec1374 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_feature_helpers.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,20 +112,9 @@ 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)
-
-	/* NETIF_F_GSO_ENCAP_ALL NETIF_F_GSO_SOFTWARE Newly added */
+#define IPVLAN_FEATURES			ipvlan_features
+#define IPVLAN_ALWAYS_ON_OFLOADS	ipvlan_offload_features
+#define IPVLAN_ALWAYS_ON		ipvlan_always_on_features
 
 #define IPVLAN_STATE_MASK \
 	((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
@@ -1018,6 +1012,31 @@ static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
 };
 #endif
 
+static void __init ipvlan_features_init(void)
+{
+	/* NETIF_F_GSO_ENCAP_ALL NETIF_F_GSO_SOFTWARE Newly added */
+	ipvlan_offload_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev_features_set_set(ipvlan_offload_features,
+				NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				NETIF_F_GSO_ROBUST_BIT);
+
+	ipvlan_always_on_features = ipvlan_offload_features;
+	netdev_features_set_set(ipvlan_always_on_features, NETIF_F_LLTX_BIT,
+				NETIF_F_VLAN_CHALLENGED_BIT);
+
+	ipvlan_features = NETIF_F_ALL_TSO;
+	netdev_features_set_set(ipvlan_features, 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);
+}
+
 static int __init ipvlan_init_module(void)
 {
 	int err;
@@ -1042,6 +1061,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 cbabca167a07..ba2730ba5c1f 100644
--- a/drivers/net/ipvlan/ipvtap.c
+++ b/drivers/net/ipvlan/ipvtap.c
@@ -18,15 +18,13 @@
 #include <linux/idr.h>
 #include <linux/fs.h>
 #include <linux/uio.h>
+#include <linux/netdev_feature_helpers.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 dev_t ipvtap_major;
 static struct cdev ipvtap_cdev;
 
@@ -86,7 +84,10 @@ 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_set(vlantap->tap.tap_features,
+				NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_ECN_BIT,
+				NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 	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..f5f5cbb29766 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -176,16 +177,15 @@ 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_set(dev, 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);
 	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 830fed3914b6..299879133317 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_feature_helpers.h>
 #include <linux/rtnetlink.h>
 #include <linux/refcount.h>
 #include <net/genetlink.h>
@@ -3446,15 +3447,16 @@ 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;
+#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)
 {
@@ -4391,6 +4393,15 @@ static struct notifier_block macsec_notifier = {
 	.notifier_call = macsec_notify,
 };
 
+static void __init macsec_features_init(void)
+{
+	netdev_features_set_set(sw_macsec_features, NETIF_F_SG_BIT,
+				NETIF_F_HIGHDMA_BIT, NETIF_F_FRAGLIST_BIT);
+
+	macsec_no_inherit_features = NETIF_F_VLAN_FEATURES;
+	macsec_no_inherit_features |= NETIF_F_HW_MACSEC;
+}
+
 static int __init macsec_init(void)
 {
 	int err;
@@ -4408,6 +4419,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 713e3354cb2e..fa20b4b2ff0a 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_feature_helpers.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,9 @@ 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)
+#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 +1810,33 @@ 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_set(macvlan_offload_features,
+				NETIF_F_SG_BIT,
+				NETIF_F_HW_CSUM_BIT,
+				NETIF_F_GSO_ROBUST_BIT);
+
+	macvlan_always_on_features = macvlan_offload_features;
+	netdev_features_set_set(macvlan_always_on_features, NETIF_F_LLTX_BIT);
+
+	netdev_features_set_set(macvlan_features,
+				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);
+}
+
 static int __init macvlan_init_module(void)
 {
 	int err;
@@ -1822,6 +1846,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..14f75986f4c4 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_feature_helpers.h>
 
 #include <net/net_namespace.h>
 #include <net/rtnetlink.h>
@@ -49,9 +50,6 @@ 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 void macvtap_count_tx_dropped(struct tap_dev *tap)
 {
 	struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap);
@@ -90,7 +88,10 @@ 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_set(vlantap->tap.tap_features,
+				NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_ECN_BIT,
+				NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 
 	/* 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 7a28e082436e..9adc0cbce2a8 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -15,6 +15,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/module.h>
@@ -27,6 +28,9 @@
 #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 bool net_failover_xmit_ready(struct net_device *dev)
 {
 	return netif_running(dev) && netif_carrier_ok(dev);
@@ -823,9 +827,24 @@ void net_failover_destroy(struct failover *failover)
 }
 EXPORT_SYMBOL_GPL(net_failover_destroy);
 
+static __init void net_failover_features_init(void)
+{
+	netdev_features_set_set(failover_vlan_features,
+				NETIF_F_HIGHDMA_BIT,
+				NETIF_F_SG_BIT,
+				NETIF_F_FRAGLIST_BIT,
+				NETIF_F_HIGHDMA_BIT,
+				NETIF_F_LRO_BIT);
+	netdev_features_set_set(failover_enc_features,
+				NETIF_F_HW_CSUM_BIT,
+				NETIF_F_SG_BIT,
+				NETIF_F_RXCSUM_BIT);
+}
+
 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..10677f52f131 100644
--- a/drivers/net/netdevsim/ipsec.c
+++ b/drivers/net/netdevsim/ipsec.c
@@ -276,12 +276,12 @@ 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_set(ns->netdev, NETIF_F_HW_ESP_BIT,
+				       NETIF_F_HW_ESP_TX_CSUM_BIT,
+				       NETIF_F_GSO_ESP_BIT);
+	netdev_hw_enc_features_set_set(ns->netdev, NETIF_F_HW_ESP_BIT,
+				       NETIF_F_HW_ESP_TX_CSUM_BIT,
+				       NETIF_F_GSO_ESP_BIT);
 
 	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 9a1a5b203624..2fdfb4e6ba23 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_feature_helpers.h>
 #include <linux/slab.h>
 #include <net/netlink.h>
 #include <net/pkt_cls.h>
@@ -288,11 +289,9 @@ 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_set(dev, NETIF_F_HIGHDMA_BIT,
+				       NETIF_F_SG_BIT, NETIF_F_FRAGLIST_BIT,
+				       NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_BIT);
 	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..9a33a10e1dd9 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_feature_helpers.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..189651736277 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_feature_helpers.h>
 #include <linux/netlink.h>
 #include <net/net_namespace.h>
 #include <linux/if_arp.h>
@@ -89,8 +90,11 @@ 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_set(dev, NETIF_F_SG_BIT,
+				       NETIF_F_FRAGLIST_BIT,
+				       NETIF_F_HIGHDMA_BIT,
+				       NETIF_F_LLTX_BIT);
 	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 9e75ed3f08ce..c82465160e4d 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_feature_helpers.h>
 
 #include <net/net_namespace.h>
 #include <net/rtnetlink.h>
@@ -116,9 +117,6 @@ 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 struct tap_dev *tap_dev_get_rcu(const struct net_device *dev)
 {
 	return rcu_dereference(dev->rx_handler_data);
@@ -321,7 +319,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 +332,9 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
 
 	skb_push(skb, ETH_HLEN);
 
+	netdev_features_zero(features);
+	netdev_features_set_set(features, NETIF_F_GSO_BIT, NETIF_F_SG_BIT,
+				NETIF_F_FRAGLIST_BIT);
 	/* Apply the forward feature mask so that we perform segmentation
 	 * according to users wishes.  This only works if VNET_HDR is
 	 * enabled.
@@ -968,9 +969,11 @@ 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_set(features, NETIF_F_GRO_BIT,
+					NETIF_F_LRO_BIT);
 	else
-		features &= ~RX_OFFLOADS;
+		netdev_features_clear_set(features, NETIF_F_GRO_BIT,
+					  NETIF_F_LRO_BIT);
 
 	/* 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 ab92416d861f..fa0fb4d074e7 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_feature_helpers.h>
 #include <linux/netpoll.h>
 #include <linux/if_vlan.h>
 #include <linux/if_arp.h>
@@ -980,12 +981,10 @@ 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 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)
 {
@@ -2876,6 +2875,19 @@ 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_set(team_vlan_features,
+				NETIF_F_HW_CSUM_BIT,
+				NETIF_F_SG_BIT,
+				NETIF_F_FRAGLIST_BIT,
+				NETIF_F_HIGHDMA_BIT,
+				NETIF_F_LRO_BIT);
+	team_enc_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_set(team_enc_features, NETIF_F_HW_CSUM_BIT,
+				NETIF_F_SG_BIT, NETIF_F_RXCSUM_BIT);
+}
 
 /******************
  * Change checkers
@@ -3051,6 +3063,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 c058eabd7b36..b3842ff71c75 100644
--- a/drivers/net/thunderbolt.c
+++ b/drivers/net/thunderbolt.c
@@ -15,6 +15,7 @@
 #include <linux/jhash.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/rtnetlink.h>
 #include <linux/sizes.h>
 #include <linux/thunderbolt.h>
@@ -1277,8 +1278,11 @@ 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_set(dev, NETIF_F_SG_BIT,
+				   NETIF_F_GRO_BIT,
+				   NETIF_F_IP_CSUM_BIT,
+				   NETIF_F_IPV6_CSUM_BIT);
 	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 3732e51b5ad8..be2d41f0c10d 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/miscdevice.h>
 #include <linux/ethtool.h>
@@ -171,6 +172,9 @@ struct tun_prog {
 	struct bpf_prog *prog;
 };
 
+static netdev_features_t tun_user_features __ro_after_init;
+#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 +188,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 +991,11 @@ 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_set(dev, NETIF_F_SG_BIT,
+				   NETIF_F_FRAGLIST_BIT,
+				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				   NETIF_F_HW_VLAN_STAG_TX_BIT);
 	dev->features = dev->hw_features | NETIF_F_LLTX;
 	dev->vlan_features = dev->features &
 			     ~(NETIF_F_HW_VLAN_CTAG_TX |
@@ -3692,6 +3696,10 @@ static int __init tun_init(void)
 		goto err_notifier;
 	}
 
+	netdev_features_set_set(tun_user_features, NETIF_F_HW_CSUM_BIT,
+				NETIF_F_TSO_ECN_BIT, NETIF_F_TSO_BIT,
+				NETIF_F_TSO6_BIT);
+
 	return  0;
 
 err_notifier:
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index a017e9de2119..bf6d429b31f2 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_feature_helpers.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 aff39bf3161d..ac430e2d19b4 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_feature_helpers.h>
 
 #define AX88179_PHY_ID				0x03
 #define AX_EEPROM_LEN				0x100
@@ -1291,8 +1292,11 @@ 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_set(dev->net, NETIF_F_SG_BIT,
+				       NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_IPV6_CSUM_BIT,
+				       NETIF_F_RXCSUM_BIT,
+				       NETIF_F_TSO_BIT);
 
 	dev->net->hw_features |= dev->net->features;
 
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index c89639381eca..22d425731938 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_feature_helpers.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 #include <linux/ip.h>
@@ -185,7 +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 | NETIF_F_HW_VLAN_CTAG_FILTER;
+	netdev_active_features_set_set(dev->net, NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				       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 3226ab33afae..381799e045e1 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_feature_helpers.h>
 #include <linux/phy_fixed.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
@@ -3465,7 +3466,9 @@ 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_set(dev->net, NETIF_F_TSO_BIT,
+					       NETIF_F_TSO6_BIT,
+					       NETIF_F_SG_BIT);
 
 	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 a51d8ded60f3..b64ac07157df 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
@@ -2109,7 +2110,9 @@ 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_set(features, NETIF_F_SG_BIT,
+					  NETIF_F_IPV6_CSUM_BIT,
+					  NETIF_F_TSO6_BIT);
 		segs = skb_gso_segment(skb, features);
 		if (IS_ERR(segs) || !segs)
 			goto drop;
@@ -9667,17 +9670,24 @@ 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_set(netdev, 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);
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_set(netdev, 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);
+	netdev_vlan_features_zero(netdev);
+	netdev_vlan_features_set_set(netdev, 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);
 
 	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..d598ef577c47 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -1478,8 +1479,9 @@ 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_set(dev->net, NETIF_F_IP_CSUM_BIT,
+				   NETIF_F_IPV6_CSUM_BIT, NETIF_F_RXCSUM_BIT);
 
 	ret = smsc75xx_wait_ready(dev, 0);
 	if (ret < 0) {
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index bfb58c91db04..47dd1651f49d 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -1085,7 +1086,9 @@ 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;
+	netdev_hw_features_zero(dev->net);
+	netdev_hw_features_set_set(dev->net, NETIF_F_IP_CSUM_BIT,
+				   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 550c85a366a0..bb88eb1d465a 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/slab.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
@@ -1616,14 +1617,10 @@ 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 void veth_setup(struct net_device *dev)
 {
+	netdev_features_t veth_features;
+
 	ether_setup(dev);
 
 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
@@ -1633,8 +1630,17 @@ 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_set(veth_features, 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);
 	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 |
@@ -1644,8 +1650,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/virtio_net.c b/drivers/net/virtio_net.c
index e0e57083d442..0ec2e7d1d757 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/module.h>
@@ -3719,10 +3720,11 @@ 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;
+		netdev_hw_features_set_set(dev, NETIF_F_HW_CSUM_BIT,
+					   NETIF_F_SG_BIT);
 		if (csum)
-			dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
-
+			netdev_active_features_set_set(dev, NETIF_F_HW_CSUM_BIT,
+						       NETIF_F_SG_BIT);
 		if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
 			dev->hw_features |= NETIF_F_TSO
 				| NETIF_F_TSO_ECN | NETIF_F_TSO6;
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 53b3b241e027..ea9c6f618ef9 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3301,26 +3301,34 @@ vmxnet3_change_mtu(struct net_device *netdev, int new_mtu)
 	return err;
 }
 
-
 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_set(netdev, 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);
 
 	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_features_set_set(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT,
+					   NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+		netdev_hw_enc_features_zero(netdev);
+		netdev_hw_enc_features_set_set(netdev,
+					       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);
 	}
 
 	if (VMXNET3_VERSION_GE_7(adapter)) {
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 18cf7c723201..7f44673ceb2e 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -303,10 +303,14 @@ static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_feat
 	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_set(netdev, 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);
 		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 +368,16 @@ 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_set(netdev, 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);
 	}
 	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..82d661d919f6 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_feature_helpers.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 badf6f09ae51..34d6c183931f 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ip.h>
 #include <linux/init.h>
@@ -1688,8 +1689,11 @@ 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_set(dev, 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);
 
 	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..1eb173aa9ab5 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_feature_helpers.h>
 #include <net/rtnetlink.h>
 #include <net/sock.h>
 #include <net/af_vsock.h>
@@ -106,8 +107,10 @@ 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_set(dev, NETIF_F_SG_BIT,
+				       NETIF_F_FRAGLIST_BIT,
+				       NETIF_F_HIGHDMA_BIT, NETIF_F_LLTX_BIT);
 
 	dev->flags = IFF_NOARP;
 
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 6ab669dcd1c6..f8bb383779e1 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_feature_helpers.h>
 #include <net/arp.h>
 #include <net/ndisc.h>
 #include <net/gro.h>
@@ -3162,14 +3163,15 @@ 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_set(dev, NETIF_F_LLTX_BIT, NETIF_F_SG_BIT,
+				       NETIF_F_HW_CSUM_BIT,
+				       NETIF_F_FRAGLIST_BIT,
+				       NETIF_F_RXCSUM_BIT);
 	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_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_FRAGLIST_BIT, NETIF_F_RXCSUM_BIT);
 	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 32831d40d757..87a1675843ce 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_feature_helpers.h>
 #include <linux/inetdevice.h>
 #include <linux/if_arp.h>
 #include <linux/icmp.h>
@@ -275,11 +276,9 @@ static const struct device_type device_type = { .name = KBUILD_MODNAME };
 static void wg_setup(struct net_device *dev)
 {
 	struct wg_device *wg = netdev_priv(dev);
-	netdev_features_t wg_netdev_features =
-		NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
-		NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA;
 	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;
@@ -291,6 +290,10 @@ 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;
+	wg_netdev_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_set(wg_netdev_features, NETIF_F_HW_CSUM_BIT,
+				NETIF_F_RXCSUM_BIT, NETIF_F_SG_BIT,
+				NETIF_F_GSO_BIT, NETIF_F_HIGHDMA_BIT);
 	dev->features |= wg_netdev_features;
 	dev->hw_features |= wg_netdev_features;
 	dev->hw_enc_features |= wg_netdev_features;
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 77e052336eb5..75c3d7b6346f 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_feature_helpers.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 d3aa9e7a37c2..946c8fbae08a 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1305,7 +1305,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 | NETIF_F_RXCSUM;
+		netdev_hw_features_set_set(dev, NETIF_F_IP_CSUM_BIT,
+					   NETIF_F_RXCSUM_BIT);
 
 	return;
 }
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index e76b38ad1d44..4b61525f5853 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_feature_helpers.h>
 #include <linux/rtnetlink.h>
 #include "wil6210.h"
 #include "txrx.h"
@@ -335,9 +336,11 @@ 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_set(ndev, 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);
 
 	ndev->features |= ndev->hw_features;
 	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
index f4070fddc8c7..e7d855826bbc 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 
@@ -96,8 +97,11 @@ 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) {
+		netdev_features_zero(hw->netdev_features);
+		netdev_features_set_set(hw->netdev_features,
+					NETIF_F_HIGHDMA_BIT, NETIF_F_SG_BIT);
+	}
 
 	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 5eb28f8ee87e..c8d523acec7d 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ip.h>
 #include <linux/if_arp.h>
@@ -318,8 +319,11 @@ 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) {
+		netdev_features_zero(hw->netdev_features);
+		netdev_features_set_set(hw->netdev_features,
+					NETIF_F_HIGHDMA_BIT, NETIF_F_SG_BIT);
+	}
 
 	hw->queues = IEEE80211_NUM_ACS;
 	hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index fb32ae82d9b0..81a4c99fb60e 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_feature_helpers.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
 #include <linux/vmalloc.h>
@@ -522,9 +523,10 @@ 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_set(dev, 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);
 	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..1003233f8cc1 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
@@ -1728,11 +1729,14 @@ 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_set(netdev, NETIF_F_IP_CSUM_BIT,
+				       NETIF_F_RXCSUM_BIT,
+				       NETIF_F_GSO_ROBUST_BIT);
+	netdev_hw_features_zero(netdev);
+	netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT,
+				   NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT,
+				   NETIF_F_TSO6_BIT);
 
 	/*
          * 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..430856ad17ea 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1868,10 +1868,14 @@ 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_set(card->dev,
+						   NETIF_F_TSO_BIT,
+						   NETIF_F_RXCSUM_BIT,
+						   NETIF_F_IP_CSUM_BIT);
+			netdev_vlan_features_set_set(card->dev,
+						     NETIF_F_TSO_BIT,
+						    NETIF_F_RXCSUM_BIT,
+						    NETIF_F_IP_CSUM_BIT);
 		}
 
 		if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index f662739137b5..d3d9745d9e64 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/phy.h>
 #include <linux/slab.h>
@@ -422,7 +423,8 @@ int cvm_oct_common_init(struct net_device *dev)
 		priv->queue = -1;
 
 	if (priv->queue != -1)
-		dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+		netdev_active_features_set_set(dev, NETIF_F_SG_BIT,
+					       NETIF_F_IP_CSUM_BIT);
 
 	/* We do our own locking, Linux doesn't need to */
 	dev->features |= NETIF_F_LLTX;
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index ca6b966f5dd3..bf685aee0fbf 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
@@ -4567,14 +4568,15 @@ 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_set(ndev, 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);
 	ndev->features = ndev->hw_features;
 	ndev->vlan_features = ndev->hw_features;
 	/* vlan gets same features (except vlan filter) */
diff --git a/include/linux/netdev_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index 132bf0de1523..7faea4c39bca 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -594,49 +594,49 @@ static inline bool __netdev_features_subset(const netdev_features_t *feats1,
 
 #define __netdev_active_features_set_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_active_features_set_array(ndev, uniq);	\
+	__netdev_features_set_array(&(uniq), &(ndev)->features);	\
 })
 #define netdev_active_features_set_set(ndev, ...)		\
 	__netdev_active_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_hw_features_set_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_hw_features_set_array(ndev, uniq);	\
+	__netdev_features_set_array(&(uniq), &(ndev)->hw_features);	\
 })
 #define netdev_hw_features_set_set(ndev, ...)		\
 	__netdev_hw_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_wanted_features_set_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_wanted_features_set_array(ndev, uniq);	\
+	__netdev_features_set_array(&(uniq), &(ndev)->wanted_features);	\
 })
 #define netdev_wanted_features_set_set(ndev, ...)		\
 	__netdev_wanted_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_vlan_features_set_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_vlan_features_set_array(ndev, uniq);	\
+	__netdev_features_set_array(&(uniq), &(ndev)->vlan_features);	\
 })
 #define netdev_vlan_features_set_set(ndev, ...)		\
 	__netdev_vlan_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_hw_enc_features_set_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_hw_enc_features_set_array(ndev, uniq);	\
+	__netdev_features_set_array(&(uniq), &(ndev)->hw_enc_features);	\
 })
 #define netdev_hw_enc_features_set_set(ndev, ...)		\
 	__netdev_hw_enc_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_mpls_features_set_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_mpls_features_set_array(ndev, uniq);	\
+	__netdev_features_set_array(&(uniq), &(ndev)->mpls_features);	\
 })
 #define netdev_mpls_features_set_set(ndev, ...)		\
 	__netdev_mpls_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_gso_partial_features_set_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_gso_partial_features_set_array(ndev, uniq);	\
+	__netdev_features_set_array(&(uniq), &(ndev)->gso_partial_features);	\
 })
 #define netdev_gso_partial_features_set_set(ndev, ...)		\
 	__netdev_gso_partial_features_set_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
@@ -650,49 +650,49 @@ static inline bool __netdev_features_subset(const netdev_features_t *feats1,
 
 #define __netdev_active_features_clear_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_active_features_clear_array(ndev, uniq);	\
+	__netdev_features_clear_array(&(uniq), &(ndev)->features);	\
 })
 #define netdev_active_features_clear_set(ndev, ...)		\
 	__netdev_active_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_hw_features_clear_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_hw_features_clear_array(ndev, uniq);	\
+	__netdev_features_clear_array(&(uniq), &(ndev)->hw_features);	\
 })
 #define netdev_hw_features_clear_set(ndev, ...)		\
 	__netdev_hw_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_wanted_features_clear_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_wanted_features_clear_array(ndev, uniq);	\
+	__netdev_features_clear_array(&(uniq), &(ndev)->wanted_features);	\
 })
 #define netdev_wanted_features_clear_set(ndev, ...)		\
 		__netdev_wanted_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_vlan_features_clear_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_vlan_features_clear_array(ndev, uniq);	\
+	__netdev_features_clear_array(&(uniq), &(ndev)->vlan_features);	\
 })
 #define netdev_vlan_features_clear_set(ndev, ...)		\
 	__netdev_vlan_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_hw_enc_features_clear_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_hw_enc_features_clear_array(ndev, uniq);	\
+	__netdev_features_clear_array(&(uniq), &(ndev)->hw_enc_features);	\
 })
 #define netdev_hw_enc_features_clear_set(ndev, ...)		\
 	__netdev_hw_enc_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_mpls_features_clear_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_mpls_features_clear_array(ndev, uniq);	\
+	__netdev_features_clear_array(&(uniq), &(ndev)->mpls_features);	\
 })
 #define netdev_mpls_features_clear_set(ndev, ...)		\
 	__netdev_mpls_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
 #define __netdev_gso_partial_features_clear_set(ndev, uniq, ...) ({	\
 	static DECLARE_NETDEV_FEATURE_SET(uniq, __VA_ARGS__);	\
-	netdev_gso_partial_features_clear_array(ndev, uniq);	\
+	__netdev_features_clear_array(&(uniq), &(ndev)->gso_partial_features);	\
 })
 #define netdev_gso_partial_features_clear_set(ndev, ...)		\
 	__netdev_gso_partial_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
diff --git a/include/net/bonding.h b/include/net/bonding.h
index afd606df149a..ac54b5b6850a 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 7940074bdb27..c98828e28e0d 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -567,11 +567,13 @@ 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_set(dev, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_SG_BIT,
+				   NETIF_F_FRAGLIST_BIT,
+				   NETIF_F_HIGHDMA_BIT,
+				   NETIF_F_SCTP_CRC_BIT);
 
 	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..7d986b56bb08 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_feature_helpers.h>
 #include <linux/netlink.h>
 #include <linux/percpu.h>
 #include <linux/random.h>
@@ -1003,8 +1004,9 @@ 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_set(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+				       NETIF_F_NETNS_LOCAL_BIT,
+				       NETIF_F_LLTX_BIT);
 	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 b82906fc999a..aa67b4a1270a 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_feature_helpers.h>
 #include <linux/netpoll.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -18,9 +19,6 @@
 #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)
-
 const struct nf_br_ops __rcu *nf_br_ops __read_mostly;
 EXPORT_SYMBOL_GPL(nf_br_ops);
 
@@ -482,6 +480,7 @@ static struct device_type br_type = {
 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 +491,18 @@ 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_set(common_features, NETIF_F_SG_BIT,
+				NETIF_F_FRAGLIST_BIT, NETIF_F_HIGHDMA_BIT,
+				NETIF_F_HW_CSUM_BIT);
+	dev->features = common_features;
+	netdev_active_features_set_set(dev, NETIF_F_LLTX_BIT,
+				       NETIF_F_NETNS_LOCAL_BIT,
+				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
+				       NETIF_F_HW_VLAN_STAG_TX_BIT);
+	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/core/dev.c b/net/core/dev.c
index 491130bdbbad..a7da9862540d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10057,7 +10057,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;
+	netdev_hw_enc_features_set_set(dev, NETIF_F_SG_BIT,
+				       NETIF_F_GSO_PARTIAL_BIT);
 
 	/* Make NETIF_F_SG inheritable to MPLS.
 	 */
diff --git a/net/core/sock.c b/net/core/sock.c
index eeb6cbac6f49..377c29ee985e 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -102,6 +102,7 @@
 #include <linux/string.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -2380,7 +2381,9 @@ 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;
+			netdev_features_set_set(sk->sk_route_caps,
+						NETIF_F_SG_BIT,
+						NETIF_F_HW_CSUM_BIT);
 			/* 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 345106b1ed78..5d9d1d83754c 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_feature_helpers.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
 #include <linux/phylink.h>
@@ -2291,7 +2292,8 @@ void dsa_slave_setup_tagger(struct net_device *slave)
 	slave->hw_features |= NETIF_F_HW_TC;
 	slave->features |= NETIF_F_LLTX;
 	if (slave->needed_tailroom)
-		slave->features &= ~(NETIF_F_SG | NETIF_F_FRAGLIST);
+		netdev_active_features_clear_set(slave, NETIF_F_SG_BIT,
+						 NETIF_F_FRAGLIST_BIT);
 	if (ds->needs_standalone_vlan_filtering)
 		slave->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 }
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 9298eb3251cb..01d3e3478a5d 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_feature_helpers.h>
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/bitops.h>
@@ -288,9 +289,6 @@ 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 u32 __ethtool_get_flags(struct net_device *dev)
 {
@@ -313,6 +311,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 +327,14 @@ 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_set(eth_all_features, 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);
+
 	/* 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..bd58b20f1679 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/skbuff.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
@@ -448,9 +449,10 @@ 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_set(dev, NETIF_F_SG_BIT, NETIF_F_FRAGLIST_BIT,
+				   NETIF_F_HIGHDMA_BIT, NETIF_F_HW_CSUM_BIT,
+				   NETIF_F_HW_VLAN_CTAG_TX_BIT);
 
 	dev->features = dev->hw_features;
 
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index f866d6282b2b..6ee63ea39eb5 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_feature_helpers.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..7b17560db559 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_feature_helpers.h>
 #include <linux/in.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
@@ -354,14 +355,10 @@ 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 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 +368,13 @@ 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_set(ipip_features, NETIF_F_SG_BIT,
+				NETIF_F_FRAGLIST_BIT,
+				NETIF_F_HIGHDMA_BIT,
+				NETIF_F_HW_CSUM_BIT);
+	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 48b4ff0294f6..05af9e3d6b05 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_feature_helpers.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 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_set(dev, NETIF_F_SG_BIT,
+				       NETIF_F_FRAGLIST_BIT,
+				       NETIF_F_HIGHDMA_BIT,
+				       NETIF_F_HW_CSUM_BIT);
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
+	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT,
+				   NETIF_F_FRAGLIST_BIT,
+				   NETIF_F_HIGHDMA_BIT,
+				   NETIF_F_HW_CSUM_BIT);
 
 	flags = nt->parms.o_flags;
 
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 9e97f3b4c7e8..2e499393d966 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_feature_helpers.h>
 #include <linux/if_arp.h>
 #include <linux/icmpv6.h>
 #include <linux/init.h>
@@ -1809,12 +1810,6 @@ 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)
-
 /**
  * ip6_tnl_dev_setup - setup virtual tunnel device
  *   @dev: virtual device associated with tunnel
@@ -1825,6 +1820,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;
@@ -1836,8 +1833,13 @@ 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_set(ipxipx_features, NETIF_F_SG_BIT,
+				NETIF_F_FRAGLIST_BIT,
+				NETIF_F_HIGHDMA_BIT,
+				NETIF_F_HW_CSUM_BIT);
+	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 98f1cf40746f..500acde55435 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_feature_helpers.h>
 #include <linux/if_arp.h>
 #include <linux/icmp.h>
 #include <linux/slab.h>
@@ -1407,16 +1408,11 @@ 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 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 +1426,14 @@ 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_set(sit_features, NETIF_F_SG_BIT,
+				NETIF_F_FRAGLIST_BIT,
+				NETIF_F_HIGHDMA_BIT,
+				NETIF_F_HW_CSUM_BIT);
 	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 977aea4467e0..e364caaf584c 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_feature_helpers.h>
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
 #include <linux/types.h>
@@ -1904,13 +1905,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 46f3eddc2388..3427752ecc8d 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -33,6 +33,10 @@
 #include "led.h"
 #include "debugfs.h"
 
+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;
@@ -1529,6 +1533,19 @@ 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_set(mac80211_tx_features,
+				NETIF_F_IP_CSUM_BIT,
+				NETIF_F_IPV6_CSUM_BIT,
+				NETIF_F_HW_CSUM_BIT,
+				NETIF_F_SG_BIT,
+				NETIF_F_HIGHDMA_BIT);
+	netdev_features_set_set(mac80211_rx_features, NETIF_F_RXCSUM_BIT);
+	mac80211_supported_features = mac80211_tx_features | mac80211_rx_features;
+}
+
 static int __init ieee80211_init(void)
 {
 	struct sk_buff *skb;
@@ -1546,6 +1563,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 35f42c9821c2..c3ef955e2a3a 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/skbuff.h>
@@ -108,9 +109,12 @@ 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_set(netdev, NETIF_F_LLTX_BIT,
+				       NETIF_F_SG_BIT,
+				       NETIF_F_FRAGLIST_BIT,
+				       NETIF_F_HIGHDMA_BIT,
+				       NETIF_F_HW_CSUM_BIT);
 
 	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..7d3fe0b2624c 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_feature_helpers.h>
 #include <linux/if_link.h>
 #include <linux/if_arp.h>
 #include <linux/icmpv6.h>
@@ -572,15 +573,11 @@ 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 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 +590,12 @@ static int xfrmi_dev_init(struct net_device *dev)
 		return err;
 	}
 
+	xfrmi_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_set_set(xfrmi_features, NETIF_F_SG_BIT,
+				NETIF_F_FRAGLIST_BIT, NETIF_F_HW_CSUM_BIT);
 	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] 74+ messages in thread

* [RFCv8 PATCH net-next 04/55] net: sfc: replace const features initialization with DECLARE_NETDEV_FEATURE_SET
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (2 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 03/55] treewide: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 05/55] net: atlantic: replace const features initialization with NETDEV_FEATURE_SET Jian Shen
                   ` (52 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The sfc driver uses netdev features in global structure
initialization. Changed the netdev_features_t memeber to
netdev_features_t *, and make it refer to a global constant
netdev_features_t variable.

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               | 31 ++++++++++++++++++--
 drivers/net/ethernet/sfc/falcon/efx.c        | 19 ++++++++++--
 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         | 17 +++++++++--
 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, 85 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 74f3af39f132..fdc5f6450072 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -4030,13 +4030,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,
@@ -4137,7 +4130,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 |
@@ -4275,7 +4268,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 7568230083e8..787e69216303 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -367,9 +367,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_set(net_dev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT);
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 2c8ecb2fdf98..346de672cb34 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -1169,16 +1169,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,
@@ -1267,7 +1262,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 b16c6aeb9c38..a750d9588bf7 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1001,10 +1001,10 @@ 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_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
-	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))
@@ -1299,6 +1299,31 @@ static struct pci_driver efx_pci_driver = {
 #endif
 };
 
+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_set(ef10_offload_features,
+				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);
+	netdev_features_set_set(ef100_offload_features,
+				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);
+}
+
 /**************************************************************************
  *
  * Kernel module interface
@@ -1327,6 +1352,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 0a07a52fe180..60a552d78a83 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;
 
@@ -2898,7 +2898,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_set(net_dev, NETIF_F_HW_CSUM_BIT,
@@ -3164,6 +3164,19 @@ static struct pci_driver ef4_pci_driver = {
 	.err_handler	= &ef4_err_handlers,
 };
 
+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_set(falcon_b0_offload_features,
+				NETIF_F_IP_CSUM_BIT,
+				NETIF_F_RXHASH_BIT,
+				NETIF_F_NTUPLE_BIT);
+	netdev_features_set_set(falcon_a1_offload_features,
+				NETIF_F_IP_CSUM_BIT);
+}
+
 /**************************************************************************
  *
  * Kernel module interface
@@ -3194,6 +3207,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 7a1c9337081b..046bc4522f96 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 e876ac952cbc..3c51561e200e 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 0f49fe683008..293af2027995 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 ef3c5d16c4f5..b83e60f8ebbb 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -984,10 +984,10 @@ 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_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
-	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))
@@ -1273,6 +1273,17 @@ static struct pci_driver efx_pci_driver = {
 #endif
 };
 
+netdev_features_t siena_offload_features __ro_after_init;
+
+static void __init efx_features_init(void)
+{
+	netdev_features_set_set(siena_offload_features,
+				NETIF_F_IP_CSUM_BIT,
+				NETIF_F_IPV6_CSUM_BIT,
+				NETIF_F_RXHASH_BIT,
+				  NETIF_F_NTUPLE_BIT);
+}
+
 /**************************************************************************
  *
  * Kernel module interface
@@ -1303,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] 74+ messages in thread

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

The atlantic driver uses netdev features in global structure
initialization. Changed the netdev_features_t memeber to
netdev_features_t *, and make it refer to a global constant
netdev_features_t variable.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 .../net/ethernet/aquantia/atlantic/aq_hw.h    |  2 +-
 .../net/ethernet/aquantia/atlantic/aq_main.c  | 51 ++++++++++++++++++-
 .../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, 62 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..2cee6182cc76 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_feature_helpers.h>
 #include <linux/module.h>
 #include <linux/ip.h>
 #include <linux/udp.h>
@@ -36,6 +37,10 @@ static const struct net_device_ops aq_ndev_ops;
 
 static struct workqueue_struct *aq_ndev_wq;
 
+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 +189,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 +516,48 @@ 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_set(hw_atl2_features,
+				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_set_set(hw_atl_a0_features,
+				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);
+	netdev_features_set_set(hw_atl_b0_features,
+				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 int __init aq_ndev_init_module(void)
 {
 	int ret;
@@ -527,6 +574,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 11b3425562fe..d678db5bce42 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;
@@ -372,8 +372,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_set(self->ndev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_RXCSUM_BIT, NETIF_F_RXHASH_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_LRO_BIT,
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] 74+ messages in thread

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

The iwlwifi driver use netdev features in global structure
initialization. Changed the netdev_features_t memeber to
netdev_features_t *, and make it refer to a global constant
netdev_features_t variable.

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  | 29 +++++++++++++++++++
 .../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  | 23 +++++++++++++++
 13 files changed, 90 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..e8588fa8e5df 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_feature_helpers.h>
 #include <linux/vmalloc.h>
 
 #include "iwl-drv.h"
@@ -89,6 +90,13 @@ static struct iwlwifi_opmode_table {
 
 #define IWL_DEFAULT_SCAN_CHANNELS 40
 
+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 +1837,25 @@ void iwl_opmode_deregister(const char *name)
 }
 IWL_EXPORT_SYMBOL(iwl_opmode_deregister);
 
+static void __init iwl_features_init(void)
+{
+	netdev_features_set_set(iwl_tx_csum_features,
+				NETIF_F_IPV6_CSUM_BIT,
+				NETIF_F_IP_CSUM_BIT,
+				NETIF_F_TSO_BIT,
+				NETIF_F_TSO6_BIT);
+	netdev_features_set_set(iwl_tx_csum_bz_features,
+				NETIF_F_HW_CSUM_BIT,
+				NETIF_F_TSO_BIT,
+				NETIF_F_TSO6_BIT);
+	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 +1874,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 c8d523acec7d..25176f5cf94d 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;
+	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..091c52378a95 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_feature_helpers.h>
 #include <linux/rtnetlink.h>
 #include <linux/vmalloc.h>
 #include <net/mac80211.h>
@@ -50,6 +51,26 @@ 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");
 
+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_set(mvm_tx_csum_features,
+				NETIF_F_IPV6_CSUM_BIT,
+				NETIF_F_IP_CSUM_BIT,
+				NETIF_F_TSO_BIT,
+				NETIF_F_TSO6_BIT);
+	netdev_features_set_set(mvm_tx_csum_bz_features,
+				NETIF_F_HW_CSUM_BIT,
+				NETIF_F_TSO_BIT,
+				NETIF_F_TSO6_BIT);
+	netdev_features_or(mvm_csum_features_mask, 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 +88,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] 74+ messages in thread

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

The mediatek driver use netdev features in global structure
initialization. Changed the netdev_features_t memeber to
netdev_features_t *, and make it refer to a global constant
netdev_features_t variable.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 43 ++++++++++++++++-----
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 +-----
 2 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c19c67a480ae..1e1d08248664 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -161,6 +161,10 @@ static const char * const mtk_clks_source_name[] = {
 	"sgmii_ck", "eth2pll", "wocpu0", "wocpu1", "netsys0", "netsys1"
 };
 
+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);
@@ -3366,6 +3370,24 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
 	return 0;
 }
 
+static void __init mtk_features_init(void)
+{
+	netdev_features_set_set(mtk_hw_features,
+				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);
+	netdev_features_set_set(mtk_mt7628_hw_features,
+				NETIF_F_SG_BIT,
+				NETIF_F_RXCSUM_BIT);
+	netdev_features_zero(mtk_empty_features);
+}
+
 static int __init mtk_init(struct net_device *dev)
 {
 	struct mtk_mac *mac = netdev_priv(dev);
@@ -3380,6 +3402,8 @@ static int __init mtk_init(struct net_device *dev)
 			dev->dev_addr);
 	}
 
+	mtk_features_init();
+
 	return 0;
 }
 
@@ -3872,13 +3896,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];
@@ -4174,7 +4198,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 = {
@@ -4190,7 +4214,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,
@@ -4208,7 +4232,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,
@@ -4225,7 +4249,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,
@@ -4243,7 +4267,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 = {
@@ -4260,6 +4284,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 = {
@@ -4275,7 +4300,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 ecf85e9ed824..10389a7debc0 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_feature_helpers.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
@@ -982,7 +974,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] 74+ messages in thread

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

The ravb driver use netdev features in global structure
initialization. Changed the netdev_features_t memeber to
netdev_features_t *, and make it refer to a global constant
netdev_features_t variable.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/renesas/ravb.h      |  4 ++--
 drivers/net/ethernet/renesas/ravb_main.c | 23 +++++++++++++++--------
 2 files changed, 17 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..d7ca2bf7cf3b 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/net_tstamp.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -50,6 +51,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 +2426,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 +2452,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 +2475,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 +2500,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,
@@ -2639,8 +2645,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;
+	netdev_feature_add(NETIF_F_RXCSUM_BIT, ravb_default_features);
+	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] 74+ messages in thread

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

The test_bpf uses netdev features in global structure
initialization. Changed the netdev_features_t memeber to
netdev_features_t *, and make it refer to a global constant
netdev_features_t variable.

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

diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 5820704165a6..84073b768558 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_feature_helpers.h>
 #include <linux/if_vlan.h>
 #include <linux/random.h>
 #include <linux/highmem.h>
@@ -14718,27 +14719,45 @@ 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 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_set(gso_frags_features,
+				NETIF_F_SG_BIT,
+				NETIF_F_GSO_PARTIAL_BIT,
+				NETIF_F_IP_CSUM_BIT,
+				NETIF_F_IPV6_CSUM_BIT,
+				NETIF_F_RXCSUM_BIT);
+	netdev_features_set_set(gso_linear_feature_features,
+				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 __init int test_skb_segment_single(const struct skb_segment_test *test)
 {
 	struct sk_buff *skb, *segs;
@@ -14750,7 +14769,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 +14783,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] 74+ messages in thread

* [RFCv8 PATCH net-next 10/55] treewide: replace NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK by netdev_csum_gso_features_mask
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (8 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 09/55] test_bpf: " Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 11/55] treewide: replace NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM by netdev_ip_csum_features Jian Shen
                   ` (46 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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 a737cc9d2752..57559609d116 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11391,7 +11391,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 964a98ae9556..8e36455ab9ed 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 24f9c5497b8a..9449b6b5b865 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 55c0a66acad2..35b4d335e97c 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5122,7 +5122,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 e91e1d39800d..fa773037a484 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 d0790e2b8a92..d0da306457d2 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 fd2cac55cb31..2dbe94cf3db3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13235,7 +13235,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 34d55e5b461c..3b51eacadec5 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4431,7 +4431,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 dab06a6c12d2..c3a007f720d8 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -9042,7 +9042,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 2561daf63151..c32b5f170cd6 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 c72b62f52574..7ea2f59d73ed 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 8b1be6bfb475..42dc65abfcd7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4472,7 +4472,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 e6d11d509145..4b38f3105523 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1810,7 +1810,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 ||
@@ -1819,7 +1819,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 c2224e41a694..f7ae65d53c78 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 1fd396b00bfb..c8389da6509d 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 b64ac07157df..0adc6cc0121f 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2771,7 +2771,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 7f44673ceb2e..3f5006cf8cc1 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 a7da9862540d..103e1022bb0d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3486,7 +3486,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] 74+ messages in thread

* [RFCv8 PATCH net-next 11/55] treewide: replace NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM by netdev_ip_csum_features
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (9 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 10/55] treewide: replace NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK by netdev_csum_gso_features_mask Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 12/55] treewide: replace NETIF_F_TSO | NETIF_F_TSO6 by netdev_general_tso_features Jian Shen
                   ` (45 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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    |  4 ++--
 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_feature_helpers.h               |  4 ++--
 include/net/udp.h                                    |  2 +-
 net/8021q/vlan_dev.c                                 |  2 +-
 net/core/dev.c                                       | 10 +++++-----
 16 files changed, 31 insertions(+), 36 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index e1e91f6db8f9..70b76c41e314 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 4101c9ee7c99..7fa30a2dbb51 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2205,7 +2205,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 2b79cf7b6b69..09a1e623882b 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;
@@ -4694,7 +4694,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 fa773037a484..5bd054b39dad 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -3336,7 +3336,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 1987bedb5c12..06c1b9dd25ce 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4880,8 +4880,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 be0b95342b1d..b50cfdb33f53 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 4b38f3105523..0106f759b3b3 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1682,8 +1682,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;
@@ -2361,7 +2361,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 8023a3f0d43b..fd5cb2138520 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -244,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);
@@ -345,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 fdc5f6450072..c0d6f6419228 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1351,7 +1351,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 f8e133604146..cfe715019699 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 d598ef577c47..5332bb724f98 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1474,7 +1474,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_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index 7faea4c39bca..456ebfd97632 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -702,9 +702,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 c98828e28e0d..b1aab3cd7c28 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -657,7 +657,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 103e1022bb0d..302ae1fdca85 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3641,7 +3641,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):
@@ -9607,9 +9607,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. */
@@ -9684,8 +9684,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] 74+ messages in thread

* [RFCv8 PATCH net-next 12/55] treewide: replace NETIF_F_TSO | NETIF_F_TSO6 by netdev_general_tso_features
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (10 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 11/55] treewide: replace NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM by netdev_ip_csum_features Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 13/55] treewide: replace VLAN tag feature array by const vlan features Jian Shen
                   ` (44 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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/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 +-
 19 files changed, 34 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index e07247d87407..92a0d382795b 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 cb2c12cdd0dc..22bb34ca5a9b 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 e27272328a65..b83aeaf904a8 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -7878,7 +7878,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/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 11f208e479ae..f7796d1301e4 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 */
@@ -2163,8 +2163,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 */
@@ -2346,7 +2345,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
 					   NETIF_F_RXCSUM_BIT, NETIF_F_SG_BIT,
 					   NETIF_F_GSO_BIT, NETIF_F_GRO_BIT,
 					   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
-		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 424ba4a1870c..bcbf365a7596 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;
@@ -1693,7 +1692,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 f716cefb46b4..076b04b515f1 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;
 				}
 			}
 
@@ -7319,7 +7316,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 c32b5f170cd6..98501284e3aa 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3327,7 +3327,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
 				   NETIF_F_IPV6_CSUM_BIT);
 	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 0106f759b3b3..3faf52d7b1d8 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1689,8 +1689,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
@@ -2370,7 +2370,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 fd5cb2138520..7c749e41a2d6 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 5f950dfed66c..5c49282a99d7 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1877,8 +1877,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 a68d14f6068f..a03d38d4ccfc 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1048,7 +1048,7 @@ static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
 					  NETIF_F_IPV6_CSUM_BIT);
 
 		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 c118ab110fd5..4bafef069002 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2287,8 +2287,8 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 				     NETIF_F_HIGHDMA_BIT);
 
 	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 e44a553398f2..727792b6cf26 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5268,7 +5268,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 f4e7007e1f0c..c60b47316770 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7128,7 +7128,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 cfe715019699..40afd3d89ecb 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 c82465160e4d..ab78a12218bc 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -968,7 +968,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_set(features, NETIF_F_GRO_BIT,
 					NETIF_F_LRO_BIT);
 	else
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 0ec2e7d1d757..d5be3fe5d140 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3726,8 +3726,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 			netdev_active_features_set_set(dev, NETIF_F_HW_CSUM_BIT,
 						       NETIF_F_SG_BIT);
 		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 430856ad17ea..d42303884636 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1910,7 +1910,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] 74+ messages in thread

* [RFCv8 PATCH net-next 13/55] treewide: replace VLAN tag feature array by const vlan features
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (11 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 12/55] treewide: replace NETIF_F_TSO | NETIF_F_TSO6 by netdev_general_tso_features Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 14/55] net: simplify the netdev features expressions for xxx_gso_segment Jian Shen
                   ` (43 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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     | 36 +++++++------------
 drivers/net/ethernet/intel/igb/igb_main.c     |  4 +--
 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 +-
 .../net/ethernet/mellanox/mlx4/en_netdev.c    | 10 ++----
 .../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 +-
 44 files changed, 80 insertions(+), 161 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 7cdaf25cb920..b3fadd51d733 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1484,8 +1484,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 */
@@ -5778,7 +5777,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 fb6a5f64d221..a481936e80fa 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 1b487c071cb6..a699a7b5e242 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 687e2aa9c721..37b0d0b26a26 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8591,7 +8591,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					   NETIF_F_TSO6_BIT);
 
 	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 b1b17f911300..5e979243795a 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -2194,10 +2194,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 b83aeaf904a8..153d51c7ffbf 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17755,8 +17755,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 51334509ba12..27844cf7da8a 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3591,9 +3591,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 861ecd176404..be01b71d8738 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -2117,9 +2117,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 c787b9122df8..7b0d0d95552f 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -1042,9 +1042,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					       NETIF_F_HIGHDMA_BIT);
 
 		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 9449b6b5b865..0ddc787b6381 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2885,7 +2885,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 f2d015371e6c..430b4a0e6e7d 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -3250,8 +3250,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 b2b0d3c26fcc..efb41a3eea11 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 d0da306457d2..2adc8a82be85 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1598,9 +1598,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 2dbe94cf3db3..3b5392750a0a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13687,9 +13687,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))
 		netdev_features_set_set(hw_features, NETIF_F_NTUPLE_BIT,
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 3b51eacadec5..d6e1c0438e14 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2202,20 +2202,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)) {
@@ -4351,10 +4351,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
@@ -4451,8 +4448,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;
@@ -4512,8 +4508,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;
@@ -4642,15 +4637,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 c3a007f720d8..d6a177b0f2c8 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3348,9 +3348,7 @@ static void ice_set_netdev_features(struct net_device *netdev)
 				NETIF_F_SCTP_CRC_BIT,
 				NETIF_F_IPV6_CSUM_BIT);
 
-	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)
@@ -3402,8 +3400,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;
 
 	/* Leave CRC / FCS stripping enabled by default, but allow the value to
 	 * be changed at runtime
@@ -5768,16 +5765,11 @@ 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_STRIPPING_FEATURES	(NETIF_F_HW_VLAN_CTAG_RX | \
-					 NETIF_F_HW_VLAN_STAG_RX)
+#define NETIF_VLAN_STRIPPING_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
@@ -5855,11 +5847,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;
 	}
 
 	if (!(netdev->features & NETIF_F_RXFCS) &&
@@ -5892,14 +5883,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)
@@ -5935,8 +5926,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 af656420ec4d..af90680f7329 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3320,9 +3320,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 2964afacac72..cd16e9e259c4 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2794,9 +2794,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 38f553e0411e..ea08c9fb5764 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -11026,9 +11026,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 248fb4b58166..d6c848533d04 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4635,9 +4635,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 1c94b41927a7..c4db48513cec 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -2765,11 +2765,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 7fdcf33a35e7..af0cd349e575 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -647,8 +647,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 90c5297c791f..2f7f8aef4553 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;
@@ -4649,8 +4649,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 1e1d08248664..0cf3582255bb 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]->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/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 98501284e3aa..900d1543645b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3381,14 +3381,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);
+			dev->hw_features &= ~netdev_vlan_offload_features;
+			dev->features &= ~netdev_vlan_offload_features;
 		}
 	} else {
 		if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN &&
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index 371fa995e9e0..1645e7cd17d2 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 998586872599..62e57f882b7b 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 7afbd49551bc..67c6214d19bd 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;
@@ -5820,8 +5820,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;
@@ -6123,8 +6122,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 986a12eb1d67..e79187d50c20 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 c60b47316770..69e55f3e2c12 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7178,11 +7178,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 5c94afc768b2..d5cfdb196ead 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -973,9 +973,7 @@ static int rhine_init_one_common(struct device *hwdev, u32 quirks,
 					       NETIF_F_HW_CSUM_BIT);
 
 	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 56dcf6677cdf..2fd507897cd1 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -324,8 +324,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 9adc0cbce2a8..7300e69fd509 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -745,9 +745,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 fa0fb4d074e7..0b345010195f 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1014,9 +1014,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;
@@ -2181,7 +2180,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 be2d41f0c10d..f92041e49864 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -997,9 +997,7 @@ static int tun_net_init(struct net_device *dev)
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				   NETIF_F_HW_VLAN_STAG_TX_BIT);
 	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 bb88eb1d465a..2070756c2c43 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1641,11 +1641,7 @@ static void veth_setup(struct net_device *dev)
 				NETIF_F_HW_VLAN_STAG_RX_BIT);
 	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 ea9c6f618ef9..20869331e70f 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3380,8 +3380,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 d42303884636..a857091c4248 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1906,8 +1906,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 bf685aee0fbf..11df4ec829c1 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -4580,9 +4580,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 aa67b4a1270a..7f2869ab25c6 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -500,8 +500,7 @@ void br_dev_setup(struct net_device *dev)
 				       NETIF_F_NETNS_LOCAL_BIT,
 				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				       NETIF_F_HW_VLAN_STAG_TX_BIT);
-	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 302ae1fdca85..a53e5362cc89 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3564,8 +3564,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 c3ef955e2a3a..402594e1cdb0 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -118,7 +118,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] 74+ messages in thread

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

The xxx_gso_segment functions use netdev features as input
parameter. Some of them using features handling expression
directly. Simplify these expreesions, so it can be replaced
by netdev features helpers later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/broadcom/tg3.c              | 5 +++--
 drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 4 +++-
 drivers/net/ethernet/sfc/siena/net_driver.h      | 1 +
 drivers/net/ethernet/sfc/siena/tx_common.c       | 4 +++-
 drivers/net/ethernet/sfc/tx_common.c             | 4 +++-
 drivers/net/ethernet/sun/sunvnet_common.c        | 4 +++-
 drivers/net/wireguard/device.c                   | 5 ++++-
 net/core/dev.c                                   | 8 +++++---
 net/ipv4/ip_output.c                             | 3 ++-
 net/ipv4/tcp_offload.c                           | 3 ++-
 net/ipv6/ip6_output.c                            | 3 ++-
 net/mac80211/tx.c                                | 4 +++-
 net/netfilter/nfnetlink_queue.c                  | 5 ++++-
 net/nsh/nsh.c                                    | 8 ++++++--
 net/openvswitch/datapath.c                       | 6 +++++-
 net/sched/sch_cake.c                             | 3 ++-
 net/sched/sch_netem.c                            | 3 ++-
 net/sched/sch_taprio.c                           | 3 ++-
 net/sched/sch_tbf.c                              | 3 ++-
 net/sctp/offload.c                               | 9 +++++++--
 net/xfrm/xfrm_device.c                           | 3 ++-
 net/xfrm/xfrm_output.c                           | 5 ++++-
 22 files changed, 70 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 153d51c7ffbf..c9f784ba26eb 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -7860,6 +7860,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
 {
 	u32 frag_cnt_est = skb_shinfo(skb)->gso_segs * 3;
 	struct sk_buff *segs, *seg, *next;
+	netdev_features_t features;
 
 	/* Estimate the number of fragments in the worst case */
 	if (unlikely(tg3_tx_avail(tnapi) <= frag_cnt_est)) {
@@ -7877,8 +7878,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);
+	features = tp->dev->features & ~netdev_general_tso_features;
+	segs = skb_gso_segment(skb, features);
 	if (IS_ERR(segs) || !segs)
 		goto tg3_tso_bug_end;
 
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 8873cdcadb0f..96b437f01afe 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -2894,10 +2894,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/net_driver.h b/drivers/net/ethernet/sfc/siena/net_driver.h
index 331af932e56d..36db05a3fb03 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
diff --git a/drivers/net/ethernet/sfc/siena/tx_common.c b/drivers/net/ethernet/sfc/siena/tx_common.c
index 93a32d61944f..58d87add9a46 100644
--- a/drivers/net/ethernet/sfc/siena/tx_common.c
+++ b/drivers/net/ethernet/sfc/siena/tx_common.c
@@ -432,8 +432,10 @@ int efx_siena_tx_tso_fallback(struct efx_tx_queue *tx_queue,
 			      struct sk_buff *skb)
 {
 	struct sk_buff *segments, *next;
+	netdev_features_t feats;
 
-	segments = skb_gso_segment(skb, 0);
+	netdev_features_zero(feats);
+	segments = skb_gso_segment(skb, feats);
 	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..14fa2c65fc25 100644
--- a/drivers/net/ethernet/sfc/tx_common.c
+++ b/drivers/net/ethernet/sfc/tx_common.c
@@ -449,8 +449,10 @@ unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
 int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
 {
 	struct sk_buff *segments, *next;
+	netdev_features_t feats;
 
-	segments = skb_gso_segment(skb, 0);
+	netdev_features_zero(feats);
+	segments = skb_gso_segment(skb, feats);
 	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 87a1675843ce..a6e25e8c2c91 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -176,8 +176,11 @@ 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);
+		netdev_features_t feats;
+		struct sk_buff *segs;
 
+		netdev_features_zero(feats);
+		segs = skb_gso_segment(skb, feats);
 		if (IS_ERR(segs)) {
 			ret = PTR_ERR(segs);
 			goto err_peer;
diff --git a/net/core/dev.c b/net/core/dev.c
index a53e5362cc89..5b5f53608331 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3394,11 +3394,13 @@ 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;
-		if (!skb_gso_ok(skb, features | partial_features))
+		partial_features = dev->features & dev->gso_partial_features;
+		partial_features |= NETIF_F_GSO_ROBUST;
+		partial_features |= features;
+		if (!skb_gso_ok(skb, partial_features))
 			features &= ~NETIF_F_GSO_PARTIAL;
 	}
 
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 8201cd423ff9..3c6206e2e0f4 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -264,7 +264,8 @@ 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);
+	features &= ~NETIF_F_GSO_MASK;
+	segs = skb_gso_segment(skb, features);
 	if (IS_ERR_OR_NULL(segs)) {
 		kfree_skb(skb);
 		return -ENOMEM;
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index a844a0d38482..a55e9729a438 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/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index a60176e913a8..0663be2415fe 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -149,7 +149,8 @@ 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);
+	features &= ~NETIF_F_GSO_MASK;
+	segs = skb_gso_segment(skb, features);
 	if (IS_ERR_OR_NULL(segs)) {
 		kfree_skb(skb);
 		return -ENOMEM;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 1be8c9d83d6a..28ab258da6af 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4203,9 +4203,11 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 	}
 
 	if (skb_is_gso(skb)) {
+		netdev_features_t feats;
 		struct sk_buff *segs;
 
-		segs = skb_gso_segment(skb, 0);
+		netdev_features_zero(feats);
+		segs = skb_gso_segment(skb, feats);
 		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..32644cc2b153 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/netfilter.h>
 #include <linux/proc_fs.h>
 #include <linux/netfilter_ipv4.h>
@@ -788,6 +789,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
 	int err = -ENOBUFS;
 	struct net *net = entry->state.net;
 	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
+	netdev_features_t feats;
 
 	/* rcu_read_lock()ed by nf_hook_thresh */
 	queue = instance_lookup(q, queuenum);
@@ -812,7 +814,8 @@ 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);
+	netdev_features_zero(feats);
+	segs = skb_gso_segment(skb, feats);
 	/* 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..1484394a7e4a 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_feature_helpers.h>
 #include <linux/skbuff.h>
 #include <net/nsh.h>
 #include <net/tun_proto.h>
@@ -78,6 +79,7 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int nsh_len, mac_len;
+	netdev_features_t feats;
 	__be16 proto;
 	int nhoff;
 
@@ -104,8 +106,10 @@ 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;
-	segs = skb_mac_gso_segment(skb, features);
+	netdev_features_zero(feats);
+	if (features & NETIF_F_SG)
+		feats |= NETIF_F_SG;
+	segs = skb_mac_gso_segment(skb, feats);
 	if (IS_ERR_OR_NULL(segs)) {
 		skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len,
 				     skb->network_header - nhoff,
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index c8a9075ddd0a..a7687f1f668f 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -27,6 +27,7 @@
 #include <linux/wait.h>
 #include <asm/div64.h>
 #include <linux/highmem.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/inetdevice.h>
@@ -328,10 +329,13 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
 	unsigned int gso_type = skb_shinfo(skb)->gso_type;
 	struct sw_flow_key later_key;
 	struct sk_buff *segs, *nskb;
+	netdev_features_t features;
 	int err;
 
 	BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_GSO_CB_OFFSET);
-	segs = __skb_gso_segment(skb, NETIF_F_SG, false);
+	netdev_features_zero(features);
+	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/sched/sch_cake.c b/net/sched/sch_cake.c
index 36acc95d611e..7e7585a16f11 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -1743,7 +1743,8 @@ 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);
+		features &= ~NETIF_F_GSO_MASK;
+		segs = skb_gso_segment(skb, features);
 		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 b70ac04110dd..72f99074ff58 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -415,7 +415,8 @@ 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);
+	features &= ~NETIF_F_GSO_MASK;
+	segs = skb_gso_segment(skb, features);
 
 	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 db88a692ef81..621ac3c6d505 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -463,7 +463,8 @@ 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);
+		features &= ~NETIF_F_GSO_MASK;
+		segs = skb_gso_segment(skb, features);
 		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 e031c1a41ea6..9a114fd9de4d 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -210,7 +210,8 @@ 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);
+	features &= ~NETIF_F_GSO_MASK;
+	segs = skb_gso_segment(skb, features);
 
 	if (IS_ERR_OR_NULL(segs))
 		return qdisc_drop(skb, sch, to_free);
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 9a5e79a38c67..e986c4b64902 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -8,6 +8,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/netfilter.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
@@ -618,10 +619,12 @@ static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb)
 static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
 	struct sk_buff *segs, *nskb;
+	netdev_features_t feats;
 
 	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);
+	netdev_features_zero(feats);
+	segs = skb_gso_segment(skb, feats);
 	kfree_skb(skb);
 	if (IS_ERR(segs))
 		return PTR_ERR(segs);
-- 
2.33.0


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

* [RFCv8 PATCH net-next 15/55] treewide: simplify the netdev features expression
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (13 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 14/55] net: simplify the netdev features expressions for xxx_gso_segment Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 16/55] treewide: adjust the handle for netdev features '0' Jian Shen
                   ` (41 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Split the complex opreation of netdev_features to simple ones,
and replace some feature macroes with global netdev features
variables. So they can be replaced by netdev features helpers
later.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/bonding/bond_main.c               | 10 ++--
 drivers/net/ethernet/aeroflex/greth.c         |  3 +-
 drivers/net/ethernet/altera/altera_tse_main.c |  3 +-
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  4 +-
 .../net/ethernet/atheros/atl1e/atl1e_main.c   |  3 +-
 drivers/net/ethernet/broadcom/bnx2.c          | 10 ++--
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c   |  6 ++-
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  3 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  6 ++-
 drivers/net/ethernet/cadence/macb_main.c      | 15 +++---
 .../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/cortina/gemini.c         |  3 +-
 drivers/net/ethernet/engleder/tsnep_main.c    |  3 +-
 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   | 10 ++--
 drivers/net/ethernet/intel/iavf/iavf_main.c   |  9 ++--
 drivers/net/ethernet/intel/ice/ice_main.c     | 23 +++++----
 drivers/net/ethernet/intel/igb/igb_main.c     |  8 ++--
 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 | 16 ++++---
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 10 ++--
 drivers/net/ethernet/jme.c                    |  6 ++-
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  3 +-
 drivers/net/ethernet/marvell/sky2.c           |  4 +-
 drivers/net/ethernet/mscc/ocelot_net.c        |  2 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  9 ++--
 drivers/net/ethernet/neterion/s2io.c          |  4 +-
 .../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  |  4 +-
 .../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     |  6 ++-
 .../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          |  7 ++-
 drivers/net/ethernet/sfc/siena/efx_common.c   |  7 +--
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  3 +-
 drivers/net/ethernet/sun/niu.c                |  3 +-
 drivers/net/ethernet/sun/sunhme.c             |  6 ++-
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  4 +-
 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/thunderbolt.c                     |  3 +-
 drivers/net/tun.c                             |  8 +++-
 drivers/net/veth.c                            |  6 ++-
 drivers/net/virtio_net.c                      |  7 ++-
 drivers/net/vmxnet3/vmxnet3_drv.c             |  7 +--
 drivers/net/vmxnet3/vmxnet3_ethtool.c         | 18 ++++---
 drivers/net/wireless/ath/ath6kl/main.c        |  3 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c   |  5 +-
 drivers/net/xen-netback/interface.c           |  3 +-
 include/linux/netdev_feature_helpers.h        |  7 ++-
 net/8021q/vlan.h                              | 17 ++++---
 net/8021q/vlan_dev.c                          | 14 ++++--
 net/core/dev.c                                | 48 +++++++++++++------
 net/core/pktgen.c                             |  6 ++-
 net/core/skbuff.c                             |  2 +-
 net/dccp/ipv6.c                               |  5 +-
 net/dsa/slave.c                               |  3 +-
 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 ++--
 98 files changed, 456 insertions(+), 252 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b3fadd51d733..2a5835c6e1c1 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1483,8 +1483,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 */
@@ -5771,9 +5771,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/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 6065eabcd87a..ade2b14ba53e 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1487,7 +1487,8 @@ static int greth_of_probe(struct platform_device *ofdev)
 		netdev_hw_features_set_set(dev, NETIF_F_SG_BIT,
 					   NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_RXCSUM_BIT);
-		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 89ae6d1623aa..c73df5f6ae30 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -1356,7 +1356,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/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 22bb34ca5a9b..e7ea9607981f 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2633,8 +2633,8 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT, NETIF_F_TSO_BIT,
 				   NETIF_F_TSO6_BIT);
-	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 13b5b706d1ce..88f6ffacb671 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -2273,7 +2273,8 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_TSO_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
-	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_set_set(netdev, NETIF_F_RXALL_BIT,
 				   NETIF_F_RXFCS_BIT);
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 37b0d0b26a26..336c02b28a5d 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)) &&
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index e704e42446aa..34b84317c736 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 ad2c38c261bc..ab8a362f87f6 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13254,7 +13254,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 57559609d116..2912ea0b9987 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -13625,14 +13625,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_set(dev, NETIF_F_GSO_GRE_CSUM_BIT,
 					    NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
-	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/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index fbdce0d335c2..009e8d098cf7 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -83,7 +83,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)
@@ -2149,8 +2148,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 */
@@ -2158,8 +2159,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;
 }
@@ -4053,7 +4056,7 @@ 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))
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 27844cf7da8a..0b928aaf8b14 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3582,8 +3582,8 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 					NETIF_F_RXCSUM_BIT, NETIF_F_TSO_BIT,
 					NETIF_F_TSO6_BIT, NETIF_F_LRO_BIT);
 
-		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;
 
@@ -3593,12 +3593,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 be01b71d8738..ed0ae09f9b04 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))
@@ -2111,15 +2112,16 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 					NETIF_F_RXCSUM_BIT, NETIF_F_TSO_BIT,
 					NETIF_F_TSO6_BIT, NETIF_F_LRO_BIT);
 
-		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 1e933a9220e9..91628878609c 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3309,14 +3309,15 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					   NETIF_F_TSO_ECN_BIT,
 					   NETIF_F_IPV6_CSUM_BIT,
 					   NETIF_F_HIGHDMA_BIT);
-		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_set(vlan_feat, NETIF_F_SG_BIT,
 					NETIF_F_IP_CSUM_BIT, NETIF_F_TSO_BIT,
 					NETIF_F_RXCSUM_BIT,
 					NETIF_F_HW_VLAN_CTAG_RX_BIT);
-		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 8e36455ab9ed..5f2d787b7536 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 e26142ea68de..ffbfb3a15bce 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -3073,7 +3073,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 					   NETIF_F_RXCSUM_BIT,
 					   NETIF_F_HW_VLAN_CTAG_TX_BIT,
 					   NETIF_F_HW_VLAN_CTAG_RX_BIT);
-		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_set(vlan_features, NETIF_F_SG_BIT,
 					NETIF_F_IP_CSUM_BIT, NETIF_F_GRO_BIT,
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index ee85285c4b11..6baa115150fb 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -2463,7 +2463,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/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index 19db8b1dddc4..bed01cc80b20 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -1282,7 +1282,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->hw_features = netdev->features | NETIF_F_LOOPBACK;
+	netdev->hw_features = netdev->features;
+	netdev->hw_features |= NETIF_F_LOOPBACK;
 
 	/* carrier off reporting is important to ethtool even BEFORE open */
 	netif_carrier_off(netdev);
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 430b4a0e6e7d..d91888b943ea 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 efb41a3eea11..e7384570b535 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 dd2affc863cc..5b244d141913 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1776,12 +1776,15 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 
 	netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT, NETIF_F_RXHASH_BIT,
 				   NETIF_F_RXCSUM_BIT);
-	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 5bd054b39dad..edf1162a881f 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)
@@ -3307,6 +3307,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;
 
@@ -3356,9 +3357,11 @@ static void hns3_set_default_feature(struct net_device *netdev)
 				NETIF_F_GRO_HW_BIT,
 				NETIF_F_NTUPLE_BIT,
 				NETIF_F_HW_TC_BIT);
-	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 7ae848678461..09815e4bea8f 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -931,7 +931,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_set(netdev, NETIF_F_IP_CSUM_BIT,
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index ce8e7d9be073..9883abd4c207 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -3174,7 +3174,8 @@ static int emac_probe(struct platform_device *ofdev)
 		netdev_hw_features_zero(ndev);
 		netdev_hw_features_set_set(ndev, NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_SG_BIT);
-		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 bcbf365a7596..7beb7b168dae 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 06c1b9dd25ce..0ea0f2e5c8e0 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4896,10 +4896,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 560d1d442232..deb4b810152b 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 9b96bace6707..25e74a03ffce 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 3b5392750a0a..e5f7d27e451f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13666,7 +13666,8 @@ 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_set(gso_partial_features, NETIF_F_GSO_GRE_BIT,
@@ -13676,8 +13677,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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_set(netdev, NETIF_F_SG_BIT,
 				     NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_BIT,
@@ -13695,7 +13696,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 
 	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 d6e1c0438e14..38d7ba76643a 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4753,7 +4753,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.
@@ -4769,10 +4770,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 d6a177b0f2c8..e748a58b336b 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3372,8 +3372,9 @@ static void ice_set_netdev_features(struct net_device *netdev)
 					    NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 					    NETIF_F_GSO_GRE_CSUM_BIT);
 	/* 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);
@@ -3389,10 +3390,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
@@ -5945,14 +5948,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) {
 		if ((features & NETIF_F_RXFCS) &&
 		    (features & NETIF_VLAN_STRIPPING_FEATURES)) {
 			dev_err(ice_pf_to_dev(vsi->back),
@@ -5968,7 +5972,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 af90680f7329..d59e1c85ce8d 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)) {
@@ -3301,7 +3301,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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;
@@ -3315,7 +3316,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 cd16e9e259c4..b93a14390e12 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2785,11 +2785,14 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 	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 63f30912cada..ccb343324742 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4996,7 +4996,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))
@@ -6364,7 +6364,8 @@ static int igc_probe(struct pci_dev *pdev,
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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);
@@ -6379,7 +6380,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 51e89e9aefcb..f5e886cdabae 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);
@@ -436,8 +436,8 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
-	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 ea08c9fb5764..8d35b1d7b99e 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;
@@ -10985,8 +10986,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 	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_hw_features_set_set(netdev,
@@ -11016,7 +11017,8 @@ static int ixgbe_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->hw_enc_features |= netdev->vlan_features;
 	netdev_mpls_features_set_set(netdev,
 				     NETIF_F_SG_BIT,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index d6c848533d04..657a9ee537e8 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4619,12 +4619,14 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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_set(netdev,
 				     NETIF_F_SG_BIT,
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 6eb610dce765..6ce1656734cb 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/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index b50cfdb33f53..8963eaf4a5f0 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -6849,7 +6849,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 	netdev_features_zero(features);
 	netdev_features_set_set(features, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
 				NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT);
-	dev->features = features | NETIF_F_RXCSUM;
+	dev->features = features;
+	dev->features |= NETIF_F_RXCSUM;
 	dev->hw_features |= features;
 	netdev_hw_features_set_set(dev, NETIF_F_RXCSUM_BIT, NETIF_F_GRO_BIT,
 				   NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 2f7f8aef4553..94ba7538d242 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/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index a2db1db99c4b..afa7fe88bb73 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -864,7 +864,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 96b437f01afe..cdbb7e7ab0ba 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -1285,8 +1285,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) {
@@ -3864,12 +3863,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 4d69c006dcaa..2157d22ced2b 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_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 7c749e41a2d6..def04c617c0f 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 67c6214d19bd..dfa3cc8f6dbc 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -6120,7 +6120,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 6930603e1698..6cc31f460478 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1545,7 +1545,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 5c49282a99d7..8a712acae06c 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
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index a03d38d4ccfc..e45b4e1884c3 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1075,7 +1075,8 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 						NETIF_F_IPV6_CSUM_BIT,
 						NETIF_F_TSO_BIT,
 						NETIF_F_TSO6_BIT);
-			features ^= changed & changeable;
+			changed &= changeable;
+			features ^= changed;
 		}
 	}
 
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 8543fc682d12..36cfb2cc900e 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 8c7b6b80dbd9..ff4e317538ab 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 727792b6cf26..c7edd6d7ef15 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1431,8 +1431,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;
 }
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 37428e2d4f3d..da564ad246ae 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -2111,7 +2111,8 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
 				   NETIF_F_IPV6_CSUM_BIT, NETIF_F_RXCSUM_BIT,
 				   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
 				   NETIF_F_GRO_BIT);
-	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 c0d6f6419228..7f0e59652305 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1363,7 +1363,8 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
 					NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 					NETIF_F_GSO_GRE_CSUM_BIT);
 
-		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 a750d9588bf7..1b80c2b31347 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -989,6 +989,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;
@@ -1004,7 +1005,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 	net_dev->features |= *efx->type->offload_features;
 	netdev_active_features_set_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
-	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))
@@ -1015,7 +1017,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
 				     NETIF_F_RXCSUM_BIT);
 
-	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 f7ae65d53c78..70a48ede5599 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 60a552d78a83..caf570fcf618 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.
 		 */
@@ -2898,8 +2901,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_set(net_dev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
diff --git a/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index b83e60f8ebbb..66f75c2ab9b4 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -972,6 +972,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;
@@ -987,7 +988,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 	net_dev->features |= *efx->type->offload_features;
 	netdev_active_features_set_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
-	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))
@@ -998,7 +1000,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
 				     NETIF_F_RXCSUM_BIT);
 
-	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/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index c8389da6509d..3b37d9ccfc6c 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/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 69e55f3e2c12..eb67918507c1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7174,7 +7174,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/niu.c b/drivers/net/ethernet/sun/niu.c
index 1b4d6b2f57ec..a4392cccf20f 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9739,7 +9739,8 @@ static void niu_set_basic_features(struct net_device *dev)
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_RXHASH_BIT);
-	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 fd99c2e677b1..e2b00446f171 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2787,7 +2787,8 @@ 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);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT);
-	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+	dev->features |= dev->hw_features;
+	dev->features |= NETIF_F_RXCSUM;
 
 	hp->irq = op->archdata.irqs[0];
 
@@ -3108,7 +3109,8 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
 	/* Happy Meal can do it all... */
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT);
-	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+	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 728aaba3fef2..5657d97a934e 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1982,8 +1982,8 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 	netdev_hw_features_set_set(port->ndev, NETIF_F_SG_BIT,
 				   NETIF_F_RXCSUM_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_HW_TC_BIT);
-	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/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 6da36cb8af80..bbbf391cb687 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_feature_helpers.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 2fd507897cd1..58718326083a 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -324,7 +324,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 a4f461ec1374..ef346c99e42e 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -231,13 +231,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 299879133317..57716883db82 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3478,7 +3478,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 +
@@ -3510,12 +3511,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 fa20b4b2ff0a..2a76b93fd950 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1078,15 +1078,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 2fdfb4e6ba23..877d5d1e8d39 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 0b345010195f..fd0f3d872fd0 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2174,9 +2174,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/thunderbolt.c b/drivers/net/thunderbolt.c
index b3842ff71c75..9d31135b77bb 100644
--- a/drivers/net/thunderbolt.c
+++ b/drivers/net/thunderbolt.c
@@ -1283,7 +1283,8 @@ static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id)
 				   NETIF_F_GRO_BIT,
 				   NETIF_F_IP_CSUM_BIT,
 				   NETIF_F_IPV6_CSUM_BIT);
-	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/tun.c b/drivers/net/tun.c
index f92041e49864..1c895384bf03 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -996,7 +996,8 @@ static int tun_net_init(struct net_device *dev)
 				   NETIF_F_FRAGLIST_BIT,
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				   NETIF_F_HW_VLAN_STAG_TX_BIT);
-	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) |
@@ -1167,8 +1168,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/veth.c b/drivers/net/veth.c
index 2070756c2c43..b5e207f1cd05 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)
@@ -1648,7 +1649,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 d5be3fe5d140..4423073021e5 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3739,8 +3739,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 20869331e70f..e7786f449c2a 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);
@@ -3381,7 +3381,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 3f5006cf8cc1..fa70ef3a9ea0 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -402,12 +402,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 946c8fbae08a..f7eccfa72865 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;
 		}
 	}
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 81a4c99fb60e..0df7495586cc 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -527,7 +527,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 	netdev_hw_features_set_set(dev, 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);
-	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/include/linux/netdev_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index 456ebfd97632..d7ab441e0560 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -700,7 +700,7 @@ static inline bool __netdev_features_subset(const netdev_features_t *feats1,
 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
@@ -713,7 +713,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..2cf51c2514e7 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_feature_helpers.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 b1aab3cd7c28..49ba2152a7b1 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -575,7 +575,8 @@ static int vlan_dev_init(struct net_device *dev)
 				   NETIF_F_HIGHDMA_BIT,
 				   NETIF_F_SCTP_CRC_BIT);
 
-	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");
@@ -649,10 +650,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.
@@ -660,7 +662,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 5b5f53608331..cdfe1a0608a1 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) {
@@ -11146,16 +11152,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 f1b8b20fc20b..8861d47d1c48 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4316,7 +4316,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/dccp/ipv6.c b/net/dccp/ipv6.c
index e57b43006074..9915a6d15886 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 5d9d1d83754c..7d5de3187bfe 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2288,7 +2288,8 @@ 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)
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 01d3e3478a5d..586b4ee4ee85 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();
 	}
@@ -312,6 +327,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;
@@ -334,12 +350,15 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
 				NETIF_F_NTUPLE_BIT, NETIF_F_RXHASH_BIT);
 
 	/* 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 3c6206e2e0f4..085fcf1395d2 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1013,7 +1013,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 0663be2415fe..f6f54fdce208 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 f99685e2d633..f14b0da3b9e1 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -2222,14 +2222,16 @@ 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->priv_flags |= IFF_LIVE_ADDR_CHANGE;
-		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 402594e1cdb0..6411034b46e9 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -119,7 +119,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 0f983e5f7dde..dbaf2ddcf656 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -1429,7 +1429,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] 74+ messages in thread

* [RFCv8 PATCH net-next 16/55] treewide: adjust the handle for netdev features '0'
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (14 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 15/55] treewide: simplify the netdev features expression Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 17/55] treewide: adjust features initialization Jian Shen
                   ` (40 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

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

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/hsi/clients/ssi_protocol.c            |  2 +-
 drivers/net/caif/caif_serial.c                |  3 ++-
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  4 +++-
 drivers/net/ethernet/broadcom/b44.c           |  2 +-
 drivers/net/ethernet/broadcom/tg3.c           |  4 +++-
 drivers/net/ethernet/dnet.c                   |  2 +-
 drivers/net/ethernet/ec_bhf.c                 |  3 ++-
 drivers/net/ethernet/emulex/benet/be_main.c   |  2 +-
 drivers/net/ethernet/ethoc.c                  |  2 +-
 .../net/ethernet/huawei/hinic/hinic_main.c    |  8 ++++++--
 drivers/net/ethernet/ibm/ibmvnic.c            |  8 +++++---
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 20 ++++++++++++++-----
 drivers/net/ethernet/microsoft/mana/mana_en.c |  2 +-
 drivers/net/ethernet/sfc/ef10.c               |  3 ++-
 drivers/net/tap.c                             |  3 ++-
 drivers/net/tun.c                             |  4 +++-
 drivers/net/usb/cdc-phonet.c                  |  3 ++-
 drivers/net/usb/lan78xx.c                     |  2 +-
 drivers/s390/net/qeth_core_main.c             |  3 ++-
 drivers/usb/gadget/function/f_phonet.c        |  3 ++-
 include/linux/tcp.h                           |  1 +
 net/dccp/ipv4.c                               |  2 +-
 net/dccp/ipv6.c                               |  2 +-
 net/ethtool/ioctl.c                           |  9 +++++++--
 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                    |  4 +++-
 31 files changed, 75 insertions(+), 38 deletions(-)

diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c
index 21f11a5b965b..3db5de9db626 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;
+	netdev_active_features_zero(dev);
 	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..009090b365f1 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/rtnetlink.h>
 #include <linux/tty.h>
 #include <linux/file.h>
@@ -398,7 +399,7 @@ static void caifdev_setup(struct net_device *dev)
 {
 	struct ser_device *serdev = netdev_priv(dev);
 
-	dev->features = 0;
+	netdev_active_features_zero(dev);
 	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 571dc950c863..490451fc76a9 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -4014,7 +4014,9 @@ static u32 ena_calc_max_io_queue_num(struct pci_dev *pdev,
 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_features_zero(dev_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 7821084c8fbe..153ff772b4d6 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 c9f784ba26eb..bc4ee4966da8 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17552,13 +17552,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;
 	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);
@@ -17698,6 +17698,8 @@ static int tg3_init_one(struct pci_dev *pdev,
 	} else
 		persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
 
+	netdev_features_zero(features);
+
 	/* Configure DMA attributes. */
 	if (dma_mask > DMA_BIT_MASK(32)) {
 		err = dma_set_mask(&pdev->dev, dma_mask);
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index 99e6f76f6cc0..17143e07c875 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..cc8dcd86d2ac 100644
--- a/drivers/net/ethernet/ec_bhf.c
+++ b/drivers/net/ethernet/ec_bhf.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/ip.h>
 #include <linux/skbuff.h>
@@ -525,7 +526,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;
+	netdev_active_features_zero(net_dev);
 	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 35b4d335e97c..9f0e58d34d2c 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -4025,7 +4025,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_zero(netdev);
 	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 09815e4bea8f..c4e25a34cab7 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -1063,10 +1063,11 @@ static int set_features(struct hinic_dev *nic_dev,
 {
 	netdev_features_t changed = force_change ? ~0 : pre_features ^ features;
 	u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
-	netdev_features_t failed_features = 0;
+	netdev_features_t failed_features;
 	int ret = 0;
 	int err = 0;
 
+	netdev_features_zero(failed_features);
 	if (changed & NETIF_F_TSO) {
 		ret = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ?
 					 HINIC_TSO_ENABLE : HINIC_TSO_DISABLE);
@@ -1165,6 +1166,7 @@ static int nic_dev_init(struct pci_dev *pdev)
 	struct net_device *netdev;
 	struct hinic_hwdev *hwdev;
 	struct devlink *devlink;
+	netdev_features_t feats;
 	u8 addr[ETH_ALEN];
 	int err, num_qps;
 
@@ -1284,7 +1286,9 @@ 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);
+	netdev_features_zero(feats);
+	err = set_features(nic_dev, feats,
+			   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 0ea0f2e5c8e0..7fcb8c9506dc 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4836,7 +4836,7 @@ 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;
 	struct device *dev = &adapter->vdev->dev;
-	netdev_features_t old_hw_features = 0;
+	netdev_features_t old_hw_features;
 	union ibmvnic_crq crq;
 
 	adapter->ip_offload_ctrl_tok =
@@ -4865,9 +4865,10 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 	ctrl_buf->large_rx_ipv4 = 0;
 	ctrl_buf->large_rx_ipv6 = 0;
 
+	netdev_hw_features_zero(old_hw_features);
 	if (adapter->state != VNIC_PROBING) {
 		old_hw_features = adapter->netdev->hw_features;
-		adapter->netdev->hw_features = 0;
+		netdev_hw_features_zero(adapter->netdev);
 	}
 
 	netdev_hw_features_zero(adapter->netdev);
@@ -4891,8 +4892,9 @@ 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_features_zero(tmp);
 		/* disable features no longer supported */
 		adapter->netdev->features &= adapter->netdev->hw_features;
 		/* turn on features now supported if previously enabled */
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 38d7ba76643a..39fbfe6e18e9 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2670,9 +2670,14 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
 	else
 		iavf_init_rss(adapter);
 
-	if (VLAN_V2_ALLOWED(adapter))
+	if (VLAN_V2_ALLOWED(adapter)) {
+		netdev_features_t feats;
+
+		netdev_features_zero(feats);
 		/* request initial VLAN offload settings */
-		iavf_set_vlan_offload_features(adapter, 0, netdev->features);
+		iavf_set_vlan_offload_features(adapter, feats,
+					       netdev->features);
+	}
 
 	return;
 err_mem:
@@ -3232,14 +3237,16 @@ static void iavf_adminq_task(struct work_struct *work)
 		if (adapter->netdev_registered ||
 		    !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) {
 			struct net_device *netdev = adapter->netdev;
+			netdev_features_t feats;
 
 			rtnl_lock();
 			netdev_update_features(netdev);
 			rtnl_unlock();
+			netdev_features_zero(feats);
 			/* Request VLAN offload settings */
 			if (VLAN_V2_ALLOWED(adapter))
 				iavf_set_vlan_offload_features
-					(adapter, 0, netdev->features);
+					(adapter, feats, netdev->features);
 
 			iavf_set_queue_vlan_tag_loc(adapter);
 		}
@@ -4441,7 +4448,9 @@ 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_features_zero(hw_features);
 
 	if (!adapter->vf_res || !adapter->vf_res->vf_cap_flags)
 		return hw_features;
@@ -4502,8 +4511,9 @@ 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_features_zero(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 68962a6c0bbd..8f8cc9bd5577 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2087,7 +2087,7 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
 				   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
 				   NETIF_F_RXHASH_BIT);
 	ndev->features = ndev->hw_features;
-	ndev->vlan_features = 0;
+	netdev_vlan_features_zero(ndev);
 
 	err = register_netdev(ndev);
 	if (err) {
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 7f0e59652305..a9f3b1793437 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1304,7 +1304,7 @@ static void efx_ef10_fini_nic(struct efx_nic *efx)
 static int efx_ef10_init_nic(struct efx_nic *efx)
 {
 	struct efx_ef10_nic_data *nic_data = efx->nic_data;
-	netdev_features_t hw_enc_features = 0;
+	netdev_features_t hw_enc_features;
 	int rc;
 
 	if (nic_data->must_check_datapath_caps) {
@@ -1349,6 +1349,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
 		nic_data->must_restore_piobufs = false;
 	}
 
+	netdev_features_zero(hw_enc_features);
 	/* add encapsulated checksum offload features */
 	if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx))
 		hw_enc_features |= netdev_ip_csum_features;
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index ab78a12218bc..abd499a8f289 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -938,13 +938,14 @@ static int tap_ioctl_set_queue(struct file *file, unsigned int flags)
 static int set_offload(struct tap_queue *q, unsigned long arg)
 {
 	struct tap_dev *tap;
+	netdev_features_t feature_mask;
 	netdev_features_t features;
-	netdev_features_t feature_mask = 0;
 
 	tap = rtnl_dereference(q->tap);
 	if (!tap)
 		return -ENOLINK;
 
+	netdev_features_zero(feature_mask);
 	features = tap->dev->features;
 
 	if (arg & TUN_F_CSUM) {
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 1c895384bf03..95de1f551d59 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -2858,7 +2858,9 @@ 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_features_zero(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..d7568af38f96 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_feature_helpers.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;
+	netdev_active_features_zero(dev);
 	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 381799e045e1..8f6268a2edd1 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -3457,7 +3457,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;
+	netdev_active_features_zero(dev->net);
 
 	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 8bd9fd51208c..65b9c10c1a08 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6864,8 +6864,9 @@ 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_features_zero(restricted);
 		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..b9d6445b3bbf 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_feature_helpers.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;
+	netdev_active_features_zero(dev);
 	dev->type		= ARPHRD_PHONET;
 	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
 	dev->mtu		= PHONET_DEV_MTU;
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index a9fbe22732c3..800c545f3c74 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -16,6 +16,7 @@
 
 #include <linux/skbuff.h>
 #include <linux/win_minmax.h>
+#include <linux/netdev_feature_helpers.h>
 #include <net/sock.h>
 #include <net/inet_connection_sock.h>
 #include <net/inet_timewait_sock.h>
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 6a6e121dc00c..d9d1c658245a 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -158,7 +158,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;
+	netdev_features_zero(sk->sk_route_caps);
 	inet->inet_dport = 0;
 	goto out;
 }
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 9915a6d15886..956985d3d132 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -989,7 +989,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;
+	netdev_features_zero(sk->sk_route_caps);
 	return err;
 }
 
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 586b4ee4ee85..04d0c37ba763 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -125,7 +125,8 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 {
 	struct ethtool_sfeatures cmd;
 	struct ethtool_set_features_block features[ETHTOOL_DEV_FEATURE_WORDS];
-	netdev_features_t wanted = 0, valid = 0;
+	netdev_features_t wanted;
+	netdev_features_t valid;
 	netdev_features_t tmp;
 	int i, ret = 0;
 
@@ -139,6 +140,8 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 	if (copy_from_user(features, useraddr, sizeof(features)))
 		return -EFAULT;
 
+	netdev_features_zero(wanted);
+	netdev_features_zero(valid);
 	for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) {
 		valid |= (netdev_features_t)features[i].valid << (32 * i);
 		wanted |= (netdev_features_t)features[i].requested << (32 * i);
@@ -325,13 +328,15 @@ static u32 __ethtool_get_flags(struct net_device *dev)
 
 static int __ethtool_set_flags(struct net_device *dev, u32 data)
 {
-	netdev_features_t features = 0, changed;
 	netdev_features_t eth_all_features;
+	netdev_features_t features;
+	netdev_features_t changed;
 	netdev_features_t tmp;
 
 	if (data & ~ETH_ALL_FLAGS)
 		return -EINVAL;
 
+	netdev_features_zero(features);
 	if (data & ETH_FLAG_LRO)
 		features |= NETIF_F_LRO;
 	if (data & ETH_FLAG_RXVLAN)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index d3ab1ae32ef5..1607dd056702 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1313,7 +1313,7 @@ int inet_sk_rebuild_header(struct sock *sk)
 		err = PTR_ERR(rt);
 
 		/* Routing failed... */
-		sk->sk_route_caps = 0;
+		netdev_features_zero(sk->sk_route_caps);
 		/*
 		 * 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 8230be00ecca..467a9c6aefb1 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;
+			netdev_features_zero(sk->sk_route_caps);
 		}
 	}
 	flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 01b31f5c7aba..2f21fc55261d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -343,7 +343,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;
+	netdev_features_zero(sk->sk_route_caps);
 	inet->inet_dport = 0;
 	return err;
 }
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 19732b5dce23..754599d8e1e3 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;
+			netdev_features_zero(sk->sk_route_caps);
 			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..24ff7edb9f57 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;
+		netdev_features_zero(sk->sk_route_caps);
 		kfree_skb(skb);
 		return PTR_ERR(dst);
 	}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 35013497e407..e93d739425f3 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -359,7 +359,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;
+	netdev_features_zero(sk->sk_route_caps);
 	return err;
 }
 
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index a7687f1f668f..0f21f1cdb6bc 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -417,6 +417,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 	struct ovs_header *upcall;
 	struct sk_buff *nskb = NULL;
 	struct sk_buff *user_skb = NULL; /* to be queued to userspace */
+	netdev_features_t feats;
 	struct nlattr *nla;
 	size_t len;
 	unsigned int hlen;
@@ -444,9 +445,10 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 		goto out;
 	}
 
+	netdev_features_zero(feats);
 	/* Complete checksum if needed */
 	if (skb->ip_summed == CHECKSUM_PARTIAL &&
-	    (err = skb_csum_hwoffload_help(skb, 0)))
+	    (err = skb_csum_hwoffload_help(skb, feats)))
 		goto out;
 
 	/* Older versions of OVS user space enforce alignment of the last
-- 
2.33.0


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

* [RFCv8 PATCH net-next 17/55] treewide: adjust features initialization
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (15 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 16/55] treewide: adjust the handle for netdev features '0' Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 18/55] net: mlx4: adjust the net device feature relative macroes Jian Shen
                   ` (39 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

There are many direclty assignment to netdev features with singe
feature bit. Replace them as to two expressions, one to reset
them to empty, one to set the feature bit.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/firewire/net.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/aquantia/atlantic/aq_nic.c     | 3 ++-
 drivers/net/ethernet/atheros/atlx/atl2.c            | 4 +++-
 drivers/net/ethernet/cadence/macb_main.c            | 3 ++-
 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   | 3 ++-
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 6 ++++--
 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/toshiba/ps3_gelic_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/virtio_net.c                            | 3 ++-
 drivers/net/wireless/ath/ath10k/mac.c               | 7 +++++--
 drivers/net/wireless/ath/ath11k/mac.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                   | 9 +++++++--
 include/net/udp.h                                   | 5 ++++-
 net/phonet/pep-gprs.c                               | 4 +++-
 36 files changed, 104 insertions(+), 40 deletions(-)

diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index af22be84034b..f13e72d1bdc6 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_feature_helpers.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/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 2396ba3b03bd..665e4cb5adbd 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -568,7 +568,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..b571c4aff3b5 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_feature_helpers.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 4cea61f16be3..54db3f827745 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_feature_helpers.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/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index d678db5bce42..3e7afde26d4c 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -378,7 +378,8 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 				     NETIF_F_RXCSUM_BIT, NETIF_F_RXHASH_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_LRO_BIT,
 				     NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
-	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 a699a7b5e242..dca59c1943fe 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_feature_helpers.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 009e8d098cf7..138f385887b5 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -4052,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/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index bed01cc80b20..f454f7f9a0c5 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_feature_helpers.h>
 #include <linux/phy.h>
 #include <linux/iopoll.h>
 
@@ -1281,7 +1282,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;
 	netdev->hw_features |= NETIF_F_LOOPBACK;
 
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 7beb7b168dae..f8802bb1e117 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1679,7 +1679,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_set(netdev, NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_IPV6_CSUM_BIT,
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index 97f080c66dd4..f9c945ecb133 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_feature_helpers.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 900d1543645b..1b224f28f1f1 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3337,7 +3337,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 		netdev_active_features_set_set(dev, NETIF_F_GSO_UDP_TUNNEL_BIT,
 					       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 					       NETIF_F_GSO_PARTIAL_BIT);
-		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_set(dev, NETIF_F_IP_CSUM_BIT,
 					       NETIF_F_IPV6_CSUM_BIT,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 42dc65abfcd7..a73d730ad55d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4925,7 +4925,8 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 		netdev_hw_enc_features_set_set(netdev,
 					       NETIF_F_GSO_UDP_TUNNEL_BIT,
 					       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
-		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_set_set(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT,
 					     NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 3faf52d7b1d8..befbb4ed1152 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2355,7 +2355,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;
@@ -2382,7 +2383,8 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 						   NETIF_F_GSO_UDP_TUNNEL_BIT,
 						   NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 						   NETIF_F_GSO_PARTIAL_BIT);
-			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 def04c617c0f..75a3ad2bc241 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 cf2929fa525e..e72d43de2b5c 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_feature_helpers.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..e650e83ffae1 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_feature_helpers.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/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 9e9eb2f4efda..4b00ff0760f7 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -1465,7 +1465,8 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
 	netdev_hw_features_set_set(netdev, NETIF_F_IP_CSUM_BIT,
 				   NETIF_F_RXCSUM_BIT);
 
-	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/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..5ea65e482bc1 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_feature_helpers.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 9fde5941a469..1a8c17e18977 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_feature_helpers.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/of_platform.h>
@@ -1861,7 +1862,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..6151308474df 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_feature_helpers.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 f438a98cd2f4..c19f659dbb4c 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1165,7 +1165,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..92b19130db17 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_feature_helpers.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 464d88ca8ab0..99a59be05310 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_feature_helpers.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 fbcb9d05da64..cc854ef32160 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_feature_helpers.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 abd499a8f289..ae374e68dcc7 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -949,7 +949,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/virtio_net.c b/drivers/net/virtio_net.c
index 4423073021e5..c8c520953ef0 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3712,7 +3712,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 23381a9db6ae..d15d0588362a 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_feature_helpers.h>
 
 #include "hif.h"
 #include "core.h"
@@ -10214,8 +10215,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..fe8b61c8ad70 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_feature_helpers.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/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 07a1fea94f66..031feef1f19f 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_feature_helpers.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..243d06f2cb0a 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_feature_helpers.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..8335cef92528 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_feature_helpers.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..c68ec3f186df 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_feature_helpers.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 65b9c10c1a08..7307f08e6688 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6765,8 +6765,13 @@ 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_features_t ipv4_features;
+
+	netdev_features_zero(ipv6_features);
+	netdev_features_zero(ipv4_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..0fdf944b3675 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -457,9 +457,12 @@ 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;
 	struct sk_buff *segs;
 
+	netdev_features_zero(features);
+	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..954bad64a451 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_feature_helpers.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] 74+ messages in thread

* [RFCv8 PATCH net-next 18/55] net: mlx4: adjust the net device feature relative macroes
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (16 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 17/55] treewide: adjust features initialization Jian Shen
@ 2022-09-18  9:42 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 19/55] net: mlx5e: adjust " Jian Shen
                   ` (38 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:42 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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 later.

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 1b224f28f1f1..044ec3f7bae1 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);
@@ -3508,11 +3508,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");
@@ -3539,7 +3539,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
@@ -3554,7 +3554,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] 74+ messages in thread

* [RFCv8 PATCH net-next 19/55] net: mlx5e: adjust net device feature relative macroes
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (17 preceding siblings ...)
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 18/55] net: mlx4: adjust the net device feature relative macroes Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 20/55] net: mlxsw: adjust input parameter for function mlxsw_sp_handle_feature Jian Shen
                   ` (37 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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 a73d730ad55d..56cefb49b396 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);
@@ -3839,21 +3839,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;
 	}
 
@@ -3865,21 +3865,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] 74+ messages in thread

* [RFCv8 PATCH net-next 20/55] net: mlxsw: adjust input parameter for function mlxsw_sp_handle_feature
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (18 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 19/55] net: mlx5e: adjust " Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 21/55] net: iavf: adjust net device features relative macroes Jian Shen
                   ` (36 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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 72aa22236ffa..702edcfa25a3 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] 74+ messages in thread

* [RFCv8 PATCH net-next 21/55] net: iavf: adjust net device features relative macroes
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (19 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 20/55] net: mlxsw: adjust input parameter for function mlxsw_sp_handle_feature Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 22/55] net: core: adjust netdev_sync_xxx_features Jian Shen
                   ` (35 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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 39fbfe6e18e9..31d4825c8a6c 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4601,8 +4601,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
@@ -4620,31 +4620,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] 74+ messages in thread

* [RFCv8 PATCH net-next 22/55] net: core: adjust netdev_sync_xxx_features
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (20 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 21/55] net: iavf: adjust net device features relative macroes Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 23/55] net: adjust the build check for net_gso_ok() Jian Shen
                   ` (34 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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 cdfe1a0608a1..61e0a9f99ff8 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] 74+ messages in thread

* [RFCv8 PATCH net-next 23/55] net: adjust the build check for net_gso_ok()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (21 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 22/55] net: core: adjust netdev_sync_xxx_features Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 24/55] treewide: use netdev_feature_add helpers Jian Shen
                   ` (33 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

So far all gso feature bits are defined continuously, and can
be mapped to gso type bits with specified "NETIF_F_GSO_SHIFT".
But once new gso type bit being introduced, the new gso feature
bit can not using this "NETIF_F_GSO_SHIFT". Change the build
check conditions, checkint the gso type bit, instead of gso type.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 include/linux/netdevice.h | 50 ++++++++++++++++++-------------
 include/linux/skbuff.h    | 63 +++++++++++++++++++++++++++------------
 2 files changed, 74 insertions(+), 39 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9bbab3856347..78e26b2e94b4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4917,28 +4917,38 @@ netdev_features_t netif_skb_features(struct sk_buff *skb);
 
 static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 {
-	netdev_features_t feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT;
+#define ASSERT_GSO_TYPE(fl, feat)	\
+		static_assert((fl) == (feat) - NETIF_F_GSO_SHIFT)
+
+	u64 classic_gso_type = gso_type & CLASSIC_GSO_FIELD;
+	u64 new_gso_type = gso_type & ~CLASSIC_GSO_FIELD;
+	netdev_features_t feature;
 
 	/* check flags correspondence */
-	BUILD_BUG_ON(SKB_GSO_TCPV4   != (NETIF_F_TSO >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_DODGY   != (NETIF_F_GSO_ROBUST >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_TCP_FIXEDID != (NETIF_F_TSO_MANGLEID >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_TCPV6   != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_FCOE    != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_GRE     != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_IPXIP4  != (NETIF_F_GSO_IPXIP4 >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_IPXIP6  != (NETIF_F_GSO_IPXIP6 >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_SCTP    != (NETIF_F_GSO_SCTP >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_ESP != (NETIF_F_GSO_ESP >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_UDP != (NETIF_F_GSO_UDP >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_UDP_L4 != (NETIF_F_GSO_UDP_L4 >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_FRAGLIST != (NETIF_F_GSO_FRAGLIST >> NETIF_F_GSO_SHIFT));
+	ASSERT_GSO_TYPE(SKB_GSO_TCPV4_BIT, NETIF_F_TSO_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_DODGY_BIT, NETIF_F_GSO_ROBUST_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_TCP_ECN_BIT, NETIF_F_TSO_ECN_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_TCP_FIXEDID_BIT, NETIF_F_TSO_MANGLEID_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_TCPV6_BIT, NETIF_F_TSO6_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_FCOE_BIT, NETIF_F_FSO_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_GRE_BIT, NETIF_F_GSO_GRE_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_GRE_CSUM_BIT, NETIF_F_GSO_GRE_CSUM_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_IPXIP4_BIT, NETIF_F_GSO_IPXIP4_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_IPXIP6_BIT, NETIF_F_GSO_IPXIP6_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_UDP_TUNNEL_BIT, NETIF_F_GSO_UDP_TUNNEL_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_UDP_TUNNEL_CSUM_BIT, NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_TUNNEL_REMCSUM_BIT, NETIF_F_GSO_TUNNEL_REMCSUM_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_SCTP_BIT, NETIF_F_GSO_SCTP_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_ESP_BIT, NETIF_F_GSO_ESP_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_UDP_BIT, NETIF_F_GSO_UDP_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_UDP_L4_BIT, NETIF_F_GSO_UDP_L4_BIT);
+	ASSERT_GSO_TYPE(SKB_GSO_FRAGLIST_BIT, NETIF_F_GSO_FRAGLIST_BIT);
+
+	if (classic_gso_type)
+		feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT;
+
+	if (new_gso_type) { /* placeholder for new gso type */
+	}
 
 	return (features & feature) == feature;
 }
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f15d5b62539b..8b030517f4d3 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -626,46 +626,71 @@ enum {
 	SKB_FCLONE_CLONE,	/* companion fclone skb (from fclone_cache) */
 };
 
+#define CLASSIC_GSO_FIELD	0x7FF
+#define __SKB_GSO_FLAG(x)	(1ULL << (SKB_GSO_##x##_BIT))
+
+enum {
+	SKB_GSO_TCPV4_BIT = 0,
+	SKB_GSO_DODGY_BIT = 1,
+	SKB_GSO_TCP_ECN_BIT = 2,
+	SKB_GSO_TCP_FIXEDID_BIT = 3,
+	SKB_GSO_TCPV6_BIT = 4,
+	SKB_GSO_FCOE_BIT = 5,
+	SKB_GSO_GRE_BIT = 6,
+	SKB_GSO_GRE_CSUM_BIT = 7,
+	SKB_GSO_IPXIP4_BIT =  8,
+	SKB_GSO_IPXIP6_BIT = 9,
+	SKB_GSO_UDP_TUNNEL_BIT = 10,
+	SKB_GSO_UDP_TUNNEL_CSUM_BIT = 11,
+	SKB_GSO_PARTIAL_BIT = 12,
+	SKB_GSO_TUNNEL_REMCSUM_BIT = 13,
+	SKB_GSO_SCTP_BIT = 14,
+	SKB_GSO_ESP_BIT = 15,
+	SKB_GSO_UDP_BIT = 16,
+	SKB_GSO_UDP_L4_BIT = 17,
+	SKB_GSO_FRAGLIST_BIT = 18,
+};
+
 enum {
-	SKB_GSO_TCPV4 = 1 << 0,
+	SKB_GSO_TCPV4 = __SKB_GSO_FLAG(TCPV4),
 
 	/* This indicates the skb is from an untrusted source. */
-	SKB_GSO_DODGY = 1 << 1,
+	SKB_GSO_DODGY = __SKB_GSO_FLAG(DODGY),
 
 	/* This indicates the tcp segment has CWR set. */
-	SKB_GSO_TCP_ECN = 1 << 2,
+	SKB_GSO_TCP_ECN = __SKB_GSO_FLAG(TCP_ECN),
 
-	SKB_GSO_TCP_FIXEDID = 1 << 3,
+	SKB_GSO_TCP_FIXEDID = __SKB_GSO_FLAG(TCP_FIXEDID),
 
-	SKB_GSO_TCPV6 = 1 << 4,
+	SKB_GSO_TCPV6 = __SKB_GSO_FLAG(TCPV6),
 
-	SKB_GSO_FCOE = 1 << 5,
+	SKB_GSO_FCOE = __SKB_GSO_FLAG(FCOE),
 
-	SKB_GSO_GRE = 1 << 6,
+	SKB_GSO_GRE = __SKB_GSO_FLAG(GRE),
 
-	SKB_GSO_GRE_CSUM = 1 << 7,
+	SKB_GSO_GRE_CSUM = __SKB_GSO_FLAG(GRE_CSUM),
 
-	SKB_GSO_IPXIP4 = 1 << 8,
+	SKB_GSO_IPXIP4 = __SKB_GSO_FLAG(IPXIP4),
 
-	SKB_GSO_IPXIP6 = 1 << 9,
+	SKB_GSO_IPXIP6 = __SKB_GSO_FLAG(IPXIP6),
 
-	SKB_GSO_UDP_TUNNEL = 1 << 10,
+	SKB_GSO_UDP_TUNNEL = __SKB_GSO_FLAG(UDP_TUNNEL),
 
-	SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11,
+	SKB_GSO_UDP_TUNNEL_CSUM = __SKB_GSO_FLAG(UDP_TUNNEL_CSUM),
 
-	SKB_GSO_PARTIAL = 1 << 12,
+	SKB_GSO_PARTIAL = __SKB_GSO_FLAG(PARTIAL),
 
-	SKB_GSO_TUNNEL_REMCSUM = 1 << 13,
+	SKB_GSO_TUNNEL_REMCSUM = __SKB_GSO_FLAG(TUNNEL_REMCSUM),
 
-	SKB_GSO_SCTP = 1 << 14,
+	SKB_GSO_SCTP = __SKB_GSO_FLAG(SCTP),
 
-	SKB_GSO_ESP = 1 << 15,
+	SKB_GSO_ESP = __SKB_GSO_FLAG(ESP),
 
-	SKB_GSO_UDP = 1 << 16,
+	SKB_GSO_UDP = __SKB_GSO_FLAG(UDP),
 
-	SKB_GSO_UDP_L4 = 1 << 17,
+	SKB_GSO_UDP_L4 = __SKB_GSO_FLAG(UDP_L4),
 
-	SKB_GSO_FRAGLIST = 1 << 18,
+	SKB_GSO_FRAGLIST = __SKB_GSO_FLAG(FRAGLIST),
 };
 
 #if BITS_PER_LONG > 32
-- 
2.33.0


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

* [RFCv8 PATCH net-next 24/55] treewide: use netdev_feature_add helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (22 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 23/55] net: adjust the build check for net_gso_ok() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 25/55] treewide: use netdev_features_or/set helpers Jian Shen
                   ` (32 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

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

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/firewire/net.c                        |  2 +-
 drivers/infiniband/ulp/ipoib/ipoib_main.c     |  2 +-
 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/adaptec/starfire.c       |  2 +-
 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      |  5 +-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c     |  2 +-
 .../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   |  4 +-
 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          |  2 +-
 .../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 |  2 +-
 drivers/net/ethernet/broadcom/tg3.c           | 12 +--
 drivers/net/ethernet/cadence/macb_main.c      |  6 +-
 .../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 ++-
 .../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   |  8 +-
 drivers/net/ethernet/cortina/gemini.c         |  2 +-
 drivers/net/ethernet/emulex/benet/be_main.c   |  2 +-
 drivers/net/ethernet/engleder/tsnep_main.c    |  4 +-
 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    |  4 +-
 .../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 ++--
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  4 +-
 drivers/net/ethernet/intel/fm10k/fm10k_pci.c  |  8 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c   | 15 ++--
 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     | 12 +--
 drivers/net/ethernet/intel/ice/ice_repr.c     |  2 +-
 drivers/net/ethernet/intel/igb/igb_main.c     | 14 ++--
 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_fcoe.c |  3 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 10 +--
 .../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  |  6 +-
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  6 +-
 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    | 27 ++++---
 .../mellanox/mlx5/core/en_accel/ipsec.c       | 16 ++--
 .../mellanox/mlx5/core/en_accel/ktls.c        |  6 +-
 .../mellanox/mlx5/core/en_accel/macsec.c      |  6 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 73 ++++++++++---------
 .../net/ethernet/mellanox/mlx5/core/en_rep.c  | 20 ++---
 .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 16 ++--
 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 +-
 .../ethernet/netronome/nfp/nfp_net_common.c   | 24 +++---
 .../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  |  8 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c  |  4 +-
 drivers/net/ethernet/qlogic/qla3xxx.c         |  2 +-
 .../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     | 10 +--
 drivers/net/ethernet/renesas/sh_eth.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/ef100_rep.c          |  4 +-
 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 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 15 ++--
 drivers/net/ethernet/sun/cassini.c            |  2 +-
 drivers/net/ethernet/sun/niu.c                |  4 +-
 drivers/net/ethernet/sun/sungem.c             |  2 +-
 drivers/net/ethernet/sun/sunhme.c             |  4 +-
 .../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/netcp_core.c          |  6 +-
 drivers/net/ethernet/toshiba/ps3_gelic_net.c  |  6 +-
 drivers/net/ethernet/toshiba/spider_net.c     |  2 +-
 drivers/net/ethernet/tundra/tsi108_eth.c      |  2 +-
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c |  3 +-
 .../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   | 37 ++++++----
 .../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                          |  6 +-
 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                 |  2 +-
 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/lan78xx.c                     | 10 ++-
 drivers/net/usb/smsc75xx.c                    |  2 +-
 drivers/net/usb/smsc95xx.c                    |  4 +-
 drivers/net/veth.c                            |  9 ++-
 drivers/net/virtio_net.c                      | 23 +++---
 drivers/net/vmxnet3/vmxnet3_drv.c             |  6 +-
 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         |  3 +-
 drivers/net/wireless/ath/ath11k/mac.c         |  3 +-
 drivers/net/wireless/ath/ath6kl/main.c        |  2 +-
 .../broadcom/brcm80211/brcmfmac/core.c        |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c   |  2 +-
 .../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             |  2 +-
 drivers/staging/qlge/qlge_main.c              |  2 +-
 include/net/udp.h                             |  2 +-
 net/8021q/vlan.h                              |  2 +-
 net/8021q/vlan_dev.c                          |  8 +-
 net/core/dev.c                                | 22 +++---
 net/core/sock.c                               |  2 +-
 net/dsa/slave.c                               | 12 +--
 net/ethtool/ioctl.c                           | 24 +++---
 net/hsr/hsr_device.c                          |  6 +-
 net/ieee802154/6lowpan/core.c                 |  2 +-
 net/ieee802154/core.c                         |  9 ++-
 net/ipv4/ip_tunnel.c                          |  3 +-
 net/ipv4/ip_vti.c                             |  2 +-
 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                              |  2 +-
 net/ipv6/sit.c                                |  5 +-
 net/ipv6/udp_offload.c                        |  2 +-
 net/l2tp/l2tp_eth.c                           |  2 +-
 net/nsh/nsh.c                                 |  2 +-
 net/openvswitch/datapath.c                    |  2 +-
 net/openvswitch/vport-internal_dev.c          |  2 +-
 net/phonet/pep-gprs.c                         |  2 +-
 net/sctp/offload.c                            |  4 +-
 net/wireless/core.c                           |  9 ++-
 net/xfrm/xfrm_interface.c                     |  2 +-
 207 files changed, 770 insertions(+), 657 deletions(-)

diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index f13e72d1bdc6..f47934e3572e 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/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 7ec6c1fedfa1..11be19e299a3 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1860,7 +1860,7 @@ static void ipoib_set_dev_features(struct ipoib_dev_priv *priv)
 					   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 665e4cb5adbd..547761658b7b 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -569,7 +569,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 2a5835c6e1c1..c769e401bc9d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5759,7 +5759,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
@@ -5769,11 +5769,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 b571c4aff3b5..caf76a3147d1 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/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index 408be86d6c88..8f7b69f9df27 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -695,7 +695,7 @@ static int starfire_init_one(struct pci_dev *pdev,
 				       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 ade2b14ba53e..ae768c5cdc59 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1488,7 +1488,7 @@ static int greth_of_probe(struct platform_device *ofdev)
 					   NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_RXCSUM_BIT);
 		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 54db3f827745..8c0d2c0c2265 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 a3c6dcc6d57b..2ebc7300bc59 100644
--- a/drivers/net/ethernet/alteon/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -592,7 +592,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 c73df5f6ae30..5bd9744abed7 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_feature_helpers.h>
 #include <linux/of_device.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
@@ -1357,13 +1358,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 490451fc76a9..a0ddc4b694af 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -4021,28 +4021,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_set(netdev, NETIF_F_SG_BIT,
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 7fa30a2dbb51..e2b841080e13 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2195,7 +2195,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 */
@@ -2209,7 +2209,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 912335f684e5..0ee584af4971 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -352,7 +352,7 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
 				   NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	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);
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..caacc4fc19aa 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_feature_helpers.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 3e7afde26d4c..fad7c338c0f5 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -379,7 +379,7 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 				     NETIF_F_SG_BIT, NETIF_F_LRO_BIT,
 				     NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 	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 e7ea9607981f..2fcd85924dfa 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;
 
@@ -2634,7 +2634,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT, NETIF_F_TSO_BIT,
 				   NETIF_F_TSO6_BIT);
 	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 88f6ffacb671..36ee563aa633 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;
 
@@ -2274,7 +2274,7 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 				   NETIF_F_TSO_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	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_set_set(netdev, NETIF_F_RXALL_BIT,
 				   NETIF_F_RXFCS_BIT);
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index a7e3ae45b5af..745ff416f095 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -3000,7 +3000,7 @@ static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	/* 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 dca59c1943fe..e674272efb37 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..5a295d8b1cd7 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 336c02b28a5d..be0798756045 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,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 34b84317c736..823a335a607b 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 ab8a362f87f6..5d0a9cbd48ac 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13248,20 +13248,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;
@@ -13976,8 +13977,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 2912ea0b9987..524640db4e92 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -12260,10 +12260,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);
 		}
 	}
 }
@@ -13607,7 +13607,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   NETIF_F_RXCSUM_BIT, NETIF_F_GRO_BIT);
 
 	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_set(dev, NETIF_F_IP_CSUM_BIT,
@@ -13626,15 +13626,15 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_gso_partial_features_set_set(dev, NETIF_F_GSO_GRE_CSUM_BIT,
 					    NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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 c3065ec0a479..28b8efe736f5 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -431,7 +431,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 bc4ee4966da8..8f18ddb0b6ad 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17704,7 +17704,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) {
@@ -17734,7 +17734,7 @@ static int tg3_init_one(struct pci_dev *pdev,
 					NETIF_F_RXCSUM_BIT);
 
 		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.
@@ -17745,17 +17745,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;
@@ -17770,7 +17770,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 138f385887b5..0f5eae9b0722 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -4053,11 +4053,11 @@ 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))
@@ -4083,7 +4083,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 0b928aaf8b14..3ce097733695 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3587,7 +3587,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 30250252dac5..c2b1db842af2 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -2211,10 +2211,10 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   NETIF_F_IPV6_CSUM_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
-	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_vlan_features_set_set(netdev, NETIF_F_SG_BIT,
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 7b0d0d95552f..f1e69dbe2b73 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;
 
@@ -1043,12 +1043,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 91628878609c..d2048a131987 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;
 
@@ -3310,7 +3311,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					   NETIF_F_IPV6_CSUM_BIT,
 					   NETIF_F_HIGHDMA_BIT);
 		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_set(vlan_feat, NETIF_F_SG_BIT,
 					NETIF_F_IP_CSUM_BIT, NETIF_F_TSO_BIT,
@@ -3319,7 +3320,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		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_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 5f2d787b7536..ebbb41ccd278 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6854,7 +6854,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);
@@ -6862,8 +6862,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 ffbfb3a15bce..f487990850f6 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;
 
@@ -3074,7 +3074,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 					   NETIF_F_HW_VLAN_CTAG_TX_BIT,
 					   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);
 		vlan_features = tso_features;
 		netdev_features_set_set(vlan_features, NETIF_F_SG_BIT,
 					NETIF_F_IP_CSUM_BIT, NETIF_F_GRO_BIT,
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 0ddc787b6381..a2bd70f6cae0 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2900,9 +2900,9 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 					   NETIF_F_TSO6_BIT,
 					   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;
@@ -2951,11 +2951,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 6baa115150fb..d8a0cc9ed5d3 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -2464,7 +2464,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/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 9f0e58d34d2c..7848b7d31b2a 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5194,7 +5194,7 @@ static void be_netdev_init(struct net_device *netdev)
 				   NETIF_F_RXCSUM_BIT,
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT);
 	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_set(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT,
diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index f454f7f9a0c5..555ccc62d6d5 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -1283,9 +1283,9 @@ 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;
-	netdev->hw_features |= NETIF_F_LOOPBACK;
+	netdev_hw_feature_add(netdev, NETIF_F_LOOPBACK_BIT);
 
 	/* carrier off reporting is important to ethtool even BEFORE open */
 	netif_carrier_off(netdev);
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index f3cdbd10af8a..30f93d01b4d7 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1938,7 +1938,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT);
 
 	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 ea97e40b4194..9cd1a51fd60c 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -235,8 +235,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 09a1e623882b..51a5105da784 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -4399,7 +4399,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 19c00607ff7c..726f73bb3653 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -781,14 +781,14 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 				     NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 
 	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 d9899932de67..461f296b83fb 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -139,7 +139,7 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 				     NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 
 	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 a594e7e90378..5bd71fb7ea80 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3636,7 +3636,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 5b760436bb01..5629860a6b47 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 d91888b943ea..846ea4800301 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -3252,7 +3252,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..dcc9a9332012 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_ktls.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_ktls.c
@@ -140,8 +140,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 5b244d141913..c0426ee6aeed 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1777,14 +1777,14 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 	netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT, NETIF_F_RXHASH_BIT,
 				   NETIF_F_RXCSUM_BIT);
 	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..f8a2f206d5c1 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_feature_helpers.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..5e4b13f3aead 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_feature_helpers.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 edf1162a881f..0b35c3d3f6fb 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -3311,7 +3311,7 @@ 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_set(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				       NETIF_F_HW_VLAN_CTAG_RX_BIT,
@@ -3326,24 +3326,25 @@ static void hns3_set_default_feature(struct net_device *netdev)
 				       NETIF_F_FRAGLIST_BIT);
 
 	if (hnae3_ae_dev_gro_supported(ae_dev))
-		netdev->features |= NETIF_F_GRO_HW;
+		netdev_active_feature_add(netdev, NETIF_F_GRO_HW_BIT);
 
 	if (hnae3_ae_dev_fd_supported(ae_dev))
-		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))
@@ -3361,7 +3362,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 c4e25a34cab7..14a8ec0e33f9 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -932,7 +932,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_set(netdev, NETIF_F_IP_CSUM_BIT,
@@ -1073,7 +1073,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);
 		}
 	}
 
@@ -1081,7 +1081,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);
 		}
 	}
 
@@ -1092,7 +1093,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);
 		}
 	}
 
@@ -1102,7 +1103,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 9883abd4c207..42bea854c367 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -3175,7 +3175,7 @@ static int emac_probe(struct platform_device *ofdev)
 		netdev_hw_features_set_set(ndev, NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_SG_BIT);
 		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 f8802bb1e117..460f31f9b8cb 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1680,7 +1680,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_set(netdev, NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_IPV6_CSUM_BIT,
@@ -1696,14 +1696,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 7fcb8c9506dc..0df1835faa9f 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4876,18 +4876,18 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 				   NETIF_F_GSO_BIT, NETIF_F_GRO_BIT);
 
 	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;
@@ -5407,7 +5407,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 deb4b810152b..802016d61d54 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_feature_helpers.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 25e74a03ffce..0840cf57aa1a 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;
 
@@ -1048,7 +1048,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;
 
@@ -1059,8 +1059,8 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   NETIF_F_RXFCS_BIT);
 
 	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_set(netdev,
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 076b04b515f1..a8e3417c179a 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;
 
@@ -7535,20 +7535,21 @@ 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_set(netdev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
 				     NETIF_F_TSO6_BIT, NETIF_F_HW_CSUM_BIT);
 
 	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_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 2adc8a82be85..bffb7c0313d0 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1580,7 +1580,7 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
 					       NETIF_F_IPV6_CSUM_BIT,
 					       NETIF_F_SG_BIT);
 
-		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;
 	}
@@ -1589,7 +1589,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..15ff28cef749 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -4,6 +4,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/aer.h>
+#include <linux/netdev_feature_helpers.h>
 
 #include "fm10k.h"
 
@@ -307,7 +308,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 +2012,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 e5f7d27e451f..64723ab03eaf 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13657,17 +13657,18 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 				NETIF_F_RXHASH_BIT, NETIF_F_RXCSUM_BIT);
 
 	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_set(gso_partial_features, NETIF_F_GSO_GRE_BIT,
@@ -13677,7 +13678,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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_set(netdev, NETIF_F_SG_BIT,
@@ -13686,7 +13687,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	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;
 
@@ -13697,8 +13698,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	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 31d4825c8a6c..95acdb5fb492 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4470,31 +4470,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);
 		}
 	}
 
@@ -4538,17 +4544,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
@@ -4558,17 +4567,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
@@ -4579,21 +4591,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);
 		}
 	}
 
@@ -4755,16 +4771,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.
@@ -4776,9 +4793,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;
@@ -4788,7 +4805,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 e748a58b336b..ff0c4cecb092 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3352,7 +3352,8 @@ 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_set(tso_features,
@@ -3386,8 +3387,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;
@@ -3408,7 +3409,7 @@ static void ice_set_netdev_features(struct net_device *netdev)
 	/* Leave CRC / FCS stripping enabled by default, but allow the value to
 	 * be changed at runtime
 	 */
-	netdev->hw_features |= NETIF_F_RXFCS;
+	netdev_hw_feature_add(netdev, NETIF_F_RXFCS_BIT);
 }
 
 /**
@@ -5846,7 +5847,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 d59e1c85ce8d..ab1c72753033 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;
 
@@ -3290,7 +3290,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 					       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_set(gso_partial_features,
@@ -3301,7 +3301,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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 */
@@ -3312,13 +3312,13 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   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 b93a14390e12..56d1dee40f51 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2785,15 +2785,15 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 	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 ccb343324742..798b932eebb5 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4979,7 +4979,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;
 
@@ -6364,7 +6364,7 @@ static int igc_probe(struct pci_dev *pdev,
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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 */
@@ -6373,16 +6373,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 f5e886cdabae..1346ed31319c 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -437,11 +437,11 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	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_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index 7311bd545acf..9b47129624f9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -5,6 +5,7 @@
 #include <linux/if_ether.h>
 #include <linux/gfp.h>
 #include <linux/if_vlan.h>
+#include <linux/netdev_feature_helpers.h>
 #include <generated/utsrelease.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -858,7 +859,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 8d35b1d7b99e..53d27e7ba43d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -10986,7 +10986,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
 	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)
@@ -11015,10 +11015,10 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 					       NETIF_F_NTUPLE_BIT,
 					       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_set(netdev,
 				     NETIF_F_SG_BIT,
@@ -11066,9 +11066,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 657a9ee537e8..2bc6092309ea 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4619,14 +4619,14 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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_set(netdev,
 				     NETIF_F_SG_BIT,
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 6ce1656734cb..cc984ad132f5 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2976,7 +2976,7 @@ jme_init_one(struct pci_dev *pdev,
 				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				       NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	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;
@@ -3039,7 +3039,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 0891bbe7d95e..0f8e364522e8 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -3206,7 +3206,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 				       NETIF_F_TSO_BIT);
 	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 8963eaf4a5f0..5cdf778d8af8 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -6850,14 +6850,14 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 	netdev_features_set_set(features, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
 				NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT);
 	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_set(dev, NETIF_F_RXCSUM_BIT, NETIF_F_GRO_BIT,
 				   NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	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 f9c945ecb133..64490b2a90b6 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 c4db48513cec..686d8e122a40 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1909,7 +1909,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;
 
@@ -2758,7 +2758,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;
@@ -2772,7 +2772,7 @@ 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_set_set(netdev, NETIF_F_LOOPBACK_BIT,
 				   NETIF_F_RXALL_BIT);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index af0cd349e575..dc9848c5b3d5 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -650,9 +650,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/skge.c b/drivers/net/ethernet/marvell/skge.c
index 424bd88a0946..2b01ed5c6913 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3830,7 +3830,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 94ba7538d242..9410f898671e 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;
@@ -4621,7 +4621,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;
 
@@ -4644,11 +4644,11 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 				   NETIF_F_TSO_BIT);
 
 	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 0cf3582255bb..b4de9b45540d 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2707,7 +2707,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);
 		}
 	}
 
@@ -3898,7 +3898,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 044ec3f7bae1..65a1d1c65de2 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;
 
@@ -3338,7 +3338,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 					       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 					       NETIF_F_GSO_PARTIAL_BIT);
 		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_set(dev, NETIF_F_IP_CSUM_BIT,
 					       NETIF_F_IPV6_CSUM_BIT,
@@ -3367,7 +3368,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN)) {
 		netdev_active_features_set_set(dev, NETIF_F_HW_VLAN_STAG_RX_BIT,
 					       NETIF_F_HW_VLAN_STAG_FILTER_BIT);
-		dev->hw_features |= NETIF_F_HW_VLAN_STAG_RX;
+		netdev_hw_feature_add(dev, NETIF_F_HW_VLAN_STAG_RX_BIT);
 	}
 
 	if (mlx4_is_slave(mdev->dev)) {
@@ -3376,7 +3377,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,
@@ -3389,19 +3391,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;
@@ -3541,7 +3544,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) {
@@ -3549,14 +3553,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 c0b77963cc7c..90268776942d 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_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
index d9d18b039d8c..906673b3bce6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
@@ -1249,7 +1249,7 @@ void mlx5e_macsec_build_netdev(struct mlx5e_priv *priv)
 	/* Enable MACsec */
 	mlx5_core_dbg(priv->mdev, "mlx5e: MACsec acceleration enabled\n");
 	netdev->macsec_ops = &macsec_offload_ops;
-	netdev->features |= NETIF_F_HW_MACSEC;
+	netdev_active_feature_add(netdev, NETIF_F_HW_MACSEC_BIT);
 	netif_keep_dst(netdev);
 }
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 56cefb49b396..ab3b082d5eac 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4880,22 +4880,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
@@ -4906,19 +4906,19 @@ 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)) {
@@ -4928,7 +4928,8 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 					       NETIF_F_GSO_UDP_TUNNEL_BIT,
 					       NETIF_F_GSO_UDP_TUNNEL_CSUM_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_vlan_features_set_set(netdev, NETIF_F_GSO_UDP_TUNNEL_BIT,
 					     NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	}
@@ -4952,20 +4953,20 @@ static void mlx5e_build_nic_netdev(struct net_device *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 +4983,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 83b2febe8a7b..6f27aa24b6e2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -725,18 +725,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,
@@ -1140,7 +1140,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/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
index 35f797cfd21e..7deeb58d8da1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -88,14 +88,14 @@ 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_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_hw_feature_add(netdev, NETIF_F_RXHASH_BIT);
 
 	netdev->netdev_ops = &mlx5i_netdev_ops;
 	netdev->ethtool_ops = &mlx5i_ethtool_ops;
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 02c666cc48e6..be05d2a60177 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -6714,7 +6714,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 cdbb7e7ab0ba..01e2799dafe1 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -695,7 +695,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);
@@ -3864,13 +3864,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 62e57f882b7b..fdc883ba136b 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_feature_helpers.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_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index befbb4ed1152..0cd76ae68ddb 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2356,9 +2356,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) {
@@ -2366,7 +2366,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) ||
@@ -2376,7 +2376,7 @@ 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_set_set(netdev,
@@ -2384,14 +2384,15 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 						   NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 						   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))
@@ -2400,7 +2401,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;
 	}
@@ -2408,24 +2409,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 75a3ad2bc241..3c762f5dc8ec 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 e72d43de2b5c..462d3e84732f 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 dfa3cc8f6dbc..44d3bc6acce9 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;
 }
@@ -5794,7 +5794,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 */
@@ -5826,7 +5827,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 6cc31f460478..ac83523c3baa 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1500,48 +1500,49 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
 				NETIF_F_TSO_ECN_BIT);
 
 	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 8a712acae06c..85e57a012bec 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1361,15 +1361,15 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
 	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 7fc2fed4472f..45e07e50d83a 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -859,14 +859,14 @@ static void qede_init_ndev(struct qede_dev *edev)
 				NETIF_F_HW_TC_BIT);
 
 	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_set(ndev, NETIF_F_IP_CSUM_BIT,
 					       NETIF_F_IPV6_CSUM_BIT,
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 5777ca67a327..3dd7012ba0a4 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -3795,7 +3795,7 @@ 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)
 		netdev_active_features_set_set(ndev, NETIF_F_IP_CSUM_BIT,
 					       NETIF_F_SG_BIT);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index e45b4e1884c3..b4f65851dff3 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1035,12 +1035,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_set(features, NETIF_F_RXCSUM_BIT,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 4bafef069002..0ccc4496c08c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2292,16 +2292,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_hw_enc_features_zero(netdev);
@@ -2312,7 +2313,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 3532f47190bc..02588e93a0c8 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 36cfb2cc900e..ce4ff91f240a 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1966,8 +1966,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) {
@@ -1998,7 +1998,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 				       NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 	if (pci_using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
+		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
 				   NETIF_F_TSO_BIT, NETIF_F_HW_VLAN_CTAG_TX_BIT,
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index ff4e317538ab..702b4b111729 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -1013,8 +1013,8 @@ static int rtl8139_init_one(struct pci_dev *pdev,
 				       NETIF_F_HIGHDMA_BIT);
 	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 c7edd6d7ef15..3f7dacbd08df 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5217,7 +5217,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);
 
@@ -5260,7 +5260,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;
 
@@ -5270,7 +5270,7 @@ 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);
@@ -5281,8 +5281,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		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/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index e650e83ffae1..72aa825bfc03 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/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index da564ad246ae..9a0e1af76ebc 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -2112,7 +2112,7 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
 				   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
 				   NETIF_F_GRO_BIT);
 	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 a9f3b1793437..fc7cdea99654 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)
@@ -1365,7 +1365,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
 					NETIF_F_GSO_GRE_CSUM_BIT);
 
 		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 346de672cb34..183d3df49a2a 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -203,7 +203,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/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/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c
index 9aae0d8b713f..5dfe8ac0e43e 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 1b80c2b31347..3efa720b9355 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1007,7 +1007,7 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
 	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;
@@ -1070,7 +1070,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 caf570fcf618..d26a8334b844 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2879,7 +2879,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);
@@ -2902,8 +2902,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_set(net_dev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
diff --git a/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index 66f75c2ab9b4..8905065f575f 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -990,7 +990,7 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
 	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;
@@ -1044,7 +1044,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/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index eb67918507c1..754a1df0099e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7124,19 +7124,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");
@@ -7175,7 +7175,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 */
@@ -7183,9 +7183,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);
@@ -7197,7 +7198,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 0f5a60bb69fa..80e3265194e7 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -5061,7 +5061,7 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_active_features_set_set(dev, NETIF_F_HW_CSUM_BIT,
 					       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 a4392cccf20f..ded37de7e450 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9740,7 +9740,7 @@ static void niu_set_basic_features(struct net_device *dev)
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_RXHASH_BIT);
 	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,
@@ -9806,7 +9806,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 443537075d55..7418e4400763 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -2995,7 +2995,7 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   NETIF_F_RXCSUM_BIT);
 	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 e2b00446f171..29f66d042d48 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_features_set_set(dev, NETIF_F_SG_BIT, 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];
 
@@ -3110,7 +3110,7 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, 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 40afd3d89ecb..c985c67596f8 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..b7783e8f2790 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_feature_helpers.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 b0dee4f3f23f..1097f3c28198 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -2025,7 +2025,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 5657d97a934e..5562b0d504af 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1983,8 +1983,8 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 				   NETIF_F_RXCSUM_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_HW_TC_BIT);
 	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/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 4b00ff0760f7..54df79fe38ff 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -1466,9 +1466,9 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
 				   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 0d02fc2cdfff..f78387987793 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -2279,7 +2279,7 @@ spider_net_setup_netdev(struct spider_net_card *card)
 	netdev_hw_features_set_set(netdev, NETIF_F_RXCSUM_BIT,
 				   NETIF_F_IP_CSUM_BIT);
 	if (SPIDER_NET_RX_CSUM_DEFAULT)
-		netdev->features |= NETIF_F_RXCSUM;
+		netdev_active_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 	netdev_active_features_set_set(netdev, NETIF_F_IP_CSUM_BIT,
 				       NETIF_F_LLTX_BIT);
 	/* some time: NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
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/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index 7674cb6e5700..3359f3c98fa2 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/string.h>
 #include <linux/aer.h>
 #include <linux/etherdevice.h>
@@ -120,7 +121,7 @@ static int ngbe_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/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index d3b9f73ecba4..74f767656619 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_feature_helpers.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 634946e87e5f..0a4a48f14d24 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_feature_helpers.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 b0958fe8111e..02af101ce163 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_feature_helpers.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 5ea65e482bc1..28697276a5d7 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -1397,21 +1397,32 @@ 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
-	ndev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4. */
-	ndev->features |= NETIF_F_HW_CSUM; /* Can checksum all the packets. */
-	ndev->features |= NETIF_F_IPV6_CSUM; /* Can checksum IPV6 TCP/UDP */
-	ndev->features |= NETIF_F_HIGHDMA; /* Can DMA to high memory. */
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_TX; /* Transmit VLAN hw accel */
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; /* Receive VLAN hw acceleration */
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; /* Receive VLAN filtering */
-	ndev->features |= NETIF_F_VLAN_CHALLENGED; /* cannot handle VLAN pkts */
-	ndev->features |= NETIF_F_GSO; /* Enable software GSO. */
-	ndev->features |= NETIF_F_MULTI_QUEUE; /* Has multiple TX/RX queues */
-	ndev->features |= NETIF_F_LRO; /* large receive offload */
+	/* Can checksum TCP/UDP over IPv4. */
+	netdev_active_feature_add(ndev, NETIF_F_IP_CSUM_BIT);
+	/* Can checksum all the packets. */
+	netdev_active_feature_add(ndev, NETIF_F_HW_CSUM_BIT);
+	/* Can checksum IPV6 TCP/UDP */
+	netdev_active_feature_add(ndev, NETIF_F_IPV6_CSUM_BIT);
+	/* Can DMA to high memory. */
+	netdev_active_feature_add(ndev, NETIF_F_HIGHDMA_BIT);
+	/* Transmit VLAN hw accel */
+	netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
+	/* Receive VLAN hw acceleration */
+	netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
+	/* Receive VLAN filtering */
+	netdev_active_feature_add(ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
+	/* cannot handle VLAN pkts */
+	netdev_active_feature_add(ndev, NETIF_F_VLAN_CHALLENGED_BIT);
+	/* Enable software GSO. */
+	netdev_active_feature_add(ndev, NETIF_F_GSO_BIT);
+	/* Has multiple TX/RX queues */
+	netdev_active_feature_add(ndev, NETIF_F_MULTI_QUEUE_BIT);
+	/* large receive offload */
+	netdev_active_feature_add(ndev, NETIF_F_LRO_BIT);
 #endif
 
 	/* setup temac private info structure */
@@ -1483,7 +1494,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 1a8c17e18977..c87207bd1927 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1863,7 +1863,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;
 
@@ -1932,14 +1932,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..b175aba2d9cf 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_feature_helpers.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 15c7dc82107f..47e2793a8e51 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 6151308474df..a2a01b5f69c6 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 c19f659dbb4c..52e9ae11f237 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1166,7 +1166,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 bbbf391cb687..e8c5d5d3e3d8 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 92b19130db17..79db953f2015 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 57716883db82..197037f22d27 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3478,7 +3478,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;
 	}
 
@@ -3520,7 +3520,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;
 }
@@ -4403,7 +4403,7 @@ static void __init macsec_features_init(void)
 				NETIF_F_HIGHDMA_BIT, NETIF_F_FRAGLIST_BIT);
 
 	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 2a76b93fd950..d58d585d73bf 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -897,7 +897,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 7300e69fd509..26232f59a94e 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -739,10 +739,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 877d5d1e8d39..f2c03b964f54 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -292,7 +292,7 @@ static void nsim_setup(struct net_device *dev)
 	netdev_active_features_set_set(dev, NETIF_F_HIGHDMA_BIT,
 				       NETIF_F_SG_BIT, NETIF_F_FRAGLIST_BIT,
 				       NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_BIT);
-	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 99a59be05310..a116b21ae741 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..302a576c0ef9 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -1616,7 +1616,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 cc854ef32160..86631b501b0f 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 ae374e68dcc7..4959b22551e4 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -949,15 +949,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 fd0f3d872fd0..d1f39c5ce632 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2168,15 +2168,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 9d31135b77bb..cd446c8242b4 100644
--- a/drivers/net/thunderbolt.c
+++ b/drivers/net/thunderbolt.c
@@ -1284,7 +1284,7 @@ static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id)
 				   NETIF_F_IP_CSUM_BIT,
 				   NETIF_F_IPV6_CSUM_BIT);
 	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 95de1f551d59..ba9a8f6c5fd9 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -997,7 +997,7 @@ static int tun_net_init(struct net_device *dev)
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				   NETIF_F_HW_VLAN_STAG_TX_BIT);
 	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) |
@@ -2863,18 +2863,20 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
 	netdev_features_zero(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/lan78xx.c b/drivers/net/usb/lan78xx.c
index 8f6268a2edd1..0eb9fe07c333 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -3460,10 +3460,10 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
 	netdev_active_features_zero(dev->net);
 
 	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_set(dev->net, NETIF_F_TSO_BIT,
@@ -3471,10 +3471,12 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
 					       NETIF_F_SG_BIT);
 
 	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 5332bb724f98..b973c0d3c6e1 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1477,7 +1477,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_set(dev->net, NETIF_F_IP_CSUM_BIT,
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 47dd1651f49d..8f667e5eb246 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1082,9 +1082,9 @@ 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);
 	netdev_hw_features_set_set(dev->net, NETIF_F_IP_CSUM_BIT,
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index b5e207f1cd05..ae6d20365e47 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1141,7 +1141,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);
 			}
 		}
@@ -1462,7 +1463,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;
 }
@@ -1640,7 +1641,7 @@ static void veth_setup(struct net_device *dev)
 				NETIF_F_HW_VLAN_CTAG_RX_BIT,
 				NETIF_F_HW_VLAN_STAG_TX_BIT,
 				NETIF_F_HW_VLAN_STAG_RX_BIT);
-	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;
@@ -1650,7 +1651,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 c8c520953ef0..eca9d6b28b75 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3493,7 +3493,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++) {
@@ -3713,7 +3714,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);
@@ -3728,17 +3729,17 @@ static int virtnet_probe(struct virtio_device *vdev)
 						       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;
@@ -3748,12 +3749,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;
 
@@ -3819,7 +3820,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 e7786f449c2a..35199c48ed3a 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3382,7 +3382,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);
 }
 
 
@@ -3860,8 +3860,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 fa70ef3a9ea0..752329ed9ea5 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -312,9 +312,11 @@ static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_feat
 					       NETIF_F_TSO6_BIT,
 					       NETIF_F_LRO_BIT);
 		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;
@@ -406,8 +408,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 34d6c183931f..5b3088b0b6f7 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1679,13 +1679,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 a6e25e8c2c91..99ec1a71a8d9 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -292,7 +292,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_set(wg_netdev_features, NETIF_F_HW_CSUM_BIT,
 				NETIF_F_RXCSUM_BIT, NETIF_F_SG_BIT,
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index d15d0588362a..133096f71ca8 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -10217,7 +10217,8 @@ 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 fe8b61c8ad70..3245821a8b77 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -8897,7 +8897,8 @@ 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/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index f7eccfa72865..eda112d8bcca 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;
 		}
 	}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 2627221c90de..05ae1cfb740b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -605,7 +605,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/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 3283c346fbe7..81645e3b47c8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -891,7 +891,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 031feef1f19f..08c15ac6efdd 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 243d06f2cb0a..f45313a04209 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 8335cef92528..ede4bf0fdc94 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 c68ec3f186df..90dfa74721a8 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 0df7495586cc..e8f2cbbdd734 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -528,7 +528,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 				   NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT,
 				   NETIF_F_TSO6_BIT, NETIF_F_FRAGLIST_BIT);
 	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 7307f08e6688..33f2fad0b9b9 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6288,10 +6288,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;
 }
@@ -6752,7 +6752,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)
@@ -6770,13 +6771,13 @@ static void qeth_check_restricted_features(struct qeth_card *card,
 
 	netdev_features_zero(ipv6_features);
 	netdev_features_zero(ipv4_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);
@@ -6878,14 +6879,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 a857091c4248..614859697a96 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1867,7 +1867,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_set(card->dev,
 						   NETIF_F_TSO_BIT,
 						   NETIF_F_RXCSUM_BIT,
@@ -1879,12 +1879,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 d3d9745d9e64..c07602f24af8 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -427,7 +427,7 @@ int cvm_oct_common_init(struct net_device *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 11df4ec829c1..6745a3a75041 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->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 0fdf944b3675..f6bfe025f865 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -461,7 +461,7 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk,
 	struct sk_buff *segs;
 
 	netdev_features_zero(features);
-	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 2cf51c2514e7..70e92a44cbb0 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 49ba2152a7b1..d1ba565425d0 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -576,7 +576,7 @@ static int vlan_dev_init(struct net_device *dev)
 				   NETIF_F_SCTP_CRC_BIT);
 
 	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");
@@ -653,19 +653,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 61e0a9f99ff8..5c6839083b21 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,
 		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);
 		partial_features |= features;
 		if (!skb_gso_ok(skb, 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,17 +10047,17 @@ 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.
 	 */
@@ -10066,7 +10066,7 @@ int register_netdevice(struct net_device *dev)
 
 	/* 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);
@@ -11153,7 +11153,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 377c29ee985e..62b560e30296 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2372,7 +2372,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))
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 7d5de3187bfe..7502543a076a 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1672,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) {
@@ -2289,14 +2290,15 @@ 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)
 		netdev_active_features_clear_set(slave, NETIF_F_SG_BIT,
 						 NETIF_F_FRAGLIST_BIT);
 	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 04d0c37ba763..672ffa3ba2e1 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -239,28 +239,28 @@ static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd)
 	case ETHTOOL_GTXCSUM:
 	case ETHTOOL_STXCSUM:
 		tmp = NETIF_F_CSUM_MASK;
-		tmp |= NETIF_F_FCOE_CRC;
-		tmp |= NETIF_F_SCTP_CRC;
+		netdev_feature_add(NETIF_F_FCOE_CRC_BIT, tmp);
+		netdev_feature_add(NETIF_F_SCTP_CRC_BIT, tmp);
 		return tmp;
 	case ETHTOOL_GRXCSUM:
 	case ETHTOOL_SRXCSUM:
-		tmp |= NETIF_F_RXCSUM;
+		netdev_feature_add(NETIF_F_RXCSUM_BIT, tmp);
 		return tmp;
 	case ETHTOOL_GSG:
 	case ETHTOOL_SSG:
-		tmp |= NETIF_F_SG;
-		tmp |= NETIF_F_FRAGLIST;
+		netdev_feature_add(NETIF_F_SG_BIT, tmp);
+		netdev_feature_add(NETIF_F_FRAGLIST_BIT, tmp);
 		return tmp;
 	case ETHTOOL_GTSO:
 	case ETHTOOL_STSO:
 		return NETIF_F_ALL_TSO;
 	case ETHTOOL_GGSO:
 	case ETHTOOL_SGSO:
-		tmp |= NETIF_F_GSO;
+		netdev_feature_add(NETIF_F_GSO_BIT, tmp);
 		return tmp;
 	case ETHTOOL_GGRO:
 	case ETHTOOL_SGRO:
-		tmp |= NETIF_F_GRO;
+		netdev_feature_add(NETIF_F_GRO_BIT, tmp);
 		return tmp;
 	default:
 		BUG();
@@ -338,15 +338,15 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
 
 	netdev_features_zero(features);
 	if (data & ETH_FLAG_LRO)
-		features |= NETIF_F_LRO;
+		netdev_feature_add(NETIF_F_LRO_BIT, features);
 	if (data & ETH_FLAG_RXVLAN)
-		features |= NETIF_F_HW_VLAN_CTAG_RX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT, features);
 	if (data & ETH_FLAG_TXVLAN)
-		features |= NETIF_F_HW_VLAN_CTAG_TX;
+		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
 	if (data & ETH_FLAG_NTUPLE)
-		features |= NETIF_F_NTUPLE;
+		netdev_feature_add(NETIF_F_NTUPLE_BIT, features);
 	if (data & ETH_FLAG_RXHASH)
-		features |= NETIF_F_RXHASH;
+		netdev_feature_add(NETIF_F_RXHASH_BIT, features);
 
 	netdev_features_zero(eth_all_features);
 	netdev_features_set_set(eth_all_features, NETIF_F_LRO_BIT,
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index bd58b20f1679..3747f69d48a2 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -457,15 +457,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..0b4af213502c 100644
--- a/net/ieee802154/6lowpan/core.c
+++ b/net/ieee802154/6lowpan/core.c
@@ -116,7 +116,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..659dd31c43fb 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -6,6 +6,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/device.h>
 
 #include <net/cfg802154.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 019f3b0839c5..3a0369b82ca5 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -1075,7 +1075,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..defc5d0b46fc 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -430,7 +430,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 7b17560db559..8e54d5b20f1e 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -365,7 +365,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 95eefbe2e142..af7345517f0f 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 a55e9729a438..e5d161cb0810 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..79df762b20f1 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 05af9e3d6b05..ca36765bd453 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 2e499393d966..04c0db84bdc6 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1830,7 +1830,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;
@@ -2282,7 +2282,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 516e83b52f26..ffb52a85cb9b 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -640,7 +640,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 500acde55435..2d39f53c81a4 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1431,7 +1431,7 @@ static void ipip6_tunnel_setup(struct net_device *dev)
 				NETIF_F_FRAGLIST_BIT,
 				NETIF_F_HIGHDMA_BIT,
 				NETIF_F_HW_CSUM_BIT);
-	dev->features		|= NETIF_F_LLTX;
+	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	dev->features		|= sit_features;
 	dev->hw_features	|= sit_features;
 }
@@ -1911,7 +1911,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..77a0c17b1894 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 f2ae03c40473..1454f5b8ffa5 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 1484394a7e4a..fc6aff0922dc 100644
--- a/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -108,7 +108,7 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
 
 	netdev_features_zero(feats);
 	if (features & NETIF_F_SG)
-		feats |= NETIF_F_SG;
+		netdev_feature_add(NETIF_F_SG_BIT, feats);
 	segs = skb_mac_gso_segment(skb, feats);
 	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 0f21f1cdb6bc..f349f13c8029 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -334,7 +334,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
 
 	BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_GSO_CB_OFFSET);
 	netdev_features_zero(features);
-	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 6411034b46e9..2bf22a159aae 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -158,7 +158,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 954bad64a451..b21fa0d9555a 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..cb8faf3eaf5e 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -51,7 +51,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 +71,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 5b0c4d5b80cf..f4d8c40a8828 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_feature_helpers.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;
@@ -1428,7 +1431,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 7d3fe0b2624c..9ef68486816a 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -593,7 +593,7 @@ static int xfrmi_dev_init(struct net_device *dev)
 	xfrmi_features = NETIF_F_GSO_SOFTWARE;
 	netdev_features_set_set(xfrmi_features, NETIF_F_SG_BIT,
 				NETIF_F_FRAGLIST_BIT, NETIF_F_HW_CSUM_BIT);
-	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] 74+ messages in thread

* [RFCv8 PATCH net-next 25/55] treewide: use netdev_features_or/set helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (23 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 24/55] treewide: use netdev_feature_add helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 26/55] treewide: use netdev_feature_change helpers Jian Shen
                   ` (31 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the "f1 = f2 | f2" features expressions with
netdev_features_or helpers, and replace the "f1 |= f2"
features expressions with netdev_featues_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            |  4 +--
 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 |  2 +-
 .../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   |  3 +-
 .../ethernet/cavium/liquidio/lio_vf_main.c    |  3 +-
 .../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   |  8 ++---
 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   | 24 ++++++++-------
 drivers/net/ethernet/intel/ice/ice_main.c     | 29 ++++++++++---------
 drivers/net/ethernet/intel/igb/igb_main.c     | 10 +++----
 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 |  2 +-
 .../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  |  5 +++-
 drivers/net/ethernet/sfc/net_driver.h         |  5 +++-
 drivers/net/ethernet/sfc/siena/efx.c          |  8 ++---
 drivers/net/ethernet/sfc/siena/efx_common.c   |  4 +--
 drivers/net/ethernet/sfc/siena/net_driver.h   |  5 +++-
 .../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                          |  7 +++--
 drivers/net/macvlan.c                         | 17 ++++++-----
 drivers/net/net_failover.c                    | 10 +++----
 drivers/net/tap.c                             |  2 +-
 drivers/net/team/team.c                       | 13 +++++----
 drivers/net/tun.c                             |  2 +-
 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_feature_helpers.h        |  7 +++--
 include/net/udp.h                             |  2 +-
 net/8021q/vlan.h                              |  4 +--
 net/8021q/vlan_dev.c                          | 10 +++----
 net/bridge/br_device.c                        |  2 +-
 net/core/dev.c                                | 19 ++++++------
 net/core/sock.c                               |  2 +-
 net/ethtool/common.h                          |  1 +
 net/ethtool/features.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                        |  6 ++--
 net/xfrm/xfrm_interface.c                     |  4 +--
 139 files changed, 385 insertions(+), 339 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 11be19e299a3..de878f4f7963 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1862,7 +1862,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 f3cd014f93d0..30a2aa83a4b0 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -3106,10 +3106,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_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	netdev_active_features_set_set(dev, NETIF_F_LLTX_BIT,
 				       NETIF_F_NETNS_LOCAL_BIT);
-	dev->hw_features	|= NETIF_F_GSO_SOFTWARE;
+	netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_FRAGLIST_BIT, NETIF_F_RXCSUM_BIT);
 	eth_hw_addr_random(dev);
diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
index c71190b54118..3b91d4256f76 100644
--- a/drivers/net/bareudp.c
+++ b/drivers/net/bareudp.c
@@ -546,10 +546,10 @@ static void bareudp_setup(struct net_device *dev)
 	netdev_active_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				       NETIF_F_RXCSUM_BIT, NETIF_F_FRAGLIST_BIT,
 				       NETIF_F_LLTX_BIT);
-	dev->features    |= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_FRAGLIST_BIT, NETIF_F_RXCSUM_BIT);
-	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 c769e401bc9d..0756d00f09e5 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1406,7 +1406,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
@@ -1414,7 +1414,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,
@@ -1483,10 +1483,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;
+	netdev_hw_enc_features_or(bond_dev, 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);
@@ -5775,18 +5776,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..31fa1a65231d 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -835,7 +835,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 +848,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 8bee9d473b78..801925bd0cd4 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -127,10 +127,10 @@ static void dummy_setup(struct net_device *dev)
 	netdev_active_features_set_set(dev, NETIF_F_SG_BIT,
 				       NETIF_F_FRAGLIST_BIT, NETIF_F_HW_CSUM_BIT,
 				       NETIF_F_HIGHDMA_BIT, NETIF_F_LLTX_BIT);
-	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 8c0d2c0c2265..65ec23d1763e 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 5bd9744abed7..b5598ce80465 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -1357,7 +1357,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 a0ddc4b694af..50470e55cbe5 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -4048,8 +4048,8 @@ static void ena_set_dev_offloads(struct ena_com_dev_get_features_ctx *feat,
 	netdev_active_features_set_set(netdev, NETIF_F_SG_BIT,
 				       NETIF_F_RXHASH_BIT, NETIF_F_HIGHDMA_BIT);
 
-	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 a481936e80fa..38beb91beb85 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_feature_helpers.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 e2b841080e13..1c66e9a7bb5e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2202,7 +2202,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 0ee584af4971..79a4a8c1471e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -376,7 +376,7 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
 				     NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT,
 				     NETIF_F_TSO_BIT, NETIF_F_TSO6_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/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index fad7c338c0f5..963aa9359257 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -372,7 +372,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_set(self->ndev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_RXCSUM_BIT, NETIF_F_RXHASH_BIT,
diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c
index 9996030a2e5d..ee4428ef59fb 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 e674272efb37..cbbb0ac2e1f3 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 153ff772b4d6..78d562d80022 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_feature_helpers.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 e7b2840a3db9..784f46970f8b 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -2575,8 +2575,8 @@ static int bcm_sysport_probe(struct platform_device *pdev)
 				       NETIF_F_HIGHDMA_BIT, NETIF_F_IP_CSUM_BIT,
 				       NETIF_F_IPV6_CSUM_BIT,
 				       NETIF_F_HW_VLAN_CTAG_TX_BIT);
-	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 be0798756045..3655af27b665 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;
 	}
@@ -8595,8 +8595,8 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					   NETIF_F_TSO6_BIT);
 
 	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 5d0a9cbd48ac..19a164e96a2b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13255,7 +13255,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 524640db4e92..6cb58b0c21aa 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11197,7 +11197,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)
@@ -13628,12 +13629,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 fcc65890820a..beba73d73f3f 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -472,7 +472,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 4912fe1a027d..d72dca1bbaf6 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -4028,8 +4028,8 @@ static int bcmgenet_probe(struct platform_device *pdev)
 	/* Set default features */
 	netdev_active_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
 				       NETIF_F_HW_CSUM_BIT, NETIF_F_RXCSUM_BIT);
-	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 8f18ddb0b6ad..5e1ede8bd049 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17758,9 +17758,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
@@ -17772,7 +17772,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 ae3f2656c268..ca543079316a 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3435,7 +3435,7 @@ bnad_netdev_init(struct bnad *bnad)
 				     NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT,
 				     NETIF_F_TSO6_BIT);
 
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 	netdev_active_features_set_set(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				       NETIF_F_HIGHDMA_BIT);
 
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 8d379803e2fb..531686bf9426 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1781,7 +1781,7 @@ static int xgmac_probe(struct platform_device *pdev)
 		netdev_hw_features_set_set(ndev, NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_IPV6_CSUM_BIT,
 					   NETIF_F_RXCSUM_BIT);
-	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 3ce097733695..41de76874bfb 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3592,7 +3592,8 @@ 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 ed0ae09f9b04..dc847580d4c7 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -2118,7 +2118,8 @@ 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 c2b1db842af2..7818d35545d2 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -2213,7 +2213,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 f1e69dbe2b73..b326156e3605 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -1042,7 +1042,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					       NETIF_F_HIGHDMA_BIT);
 
 		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 d2048a131987..04dcb4c3c043 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3310,7 +3310,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					   NETIF_F_TSO_ECN_BIT,
 					   NETIF_F_IPV6_CSUM_BIT,
 					   NETIF_F_HIGHDMA_BIT);
-		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_set(vlan_feat, NETIF_F_SG_BIT,
@@ -3318,7 +3318,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					NETIF_F_RXCSUM_BIT,
 					NETIF_F_HW_VLAN_CTAG_RX_BIT);
 		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 ebbb41ccd278..3a610e650db9 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6845,7 +6845,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_set(vlan_features, NETIF_F_SG_BIT,
 					NETIF_F_IP_CSUM_BIT, NETIF_F_GRO_BIT,
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index a2bd70f6cae0..d9c2b84d7231 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2885,7 +2885,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;
@@ -2914,7 +2914,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 					       NETIF_F_GSO_UDP_TUNNEL_BIT,
 					       NETIF_F_HW_CSUM_BIT,
 					       NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
-		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
@@ -2947,8 +2947,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 d8a0cc9ed5d3..2bd0892f5f53 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -2463,7 +2463,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 6e274878b962..f16bb16bf892 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_features_set_set(ndev, NETIF_F_RXCSUM_BIT,
 					   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 17143e07c875..7dcf42dd6e61 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_feature_helpers.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 7848b7d31b2a..e41adc6136c2 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5196,7 +5196,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_set(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT,
 				       NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				       NETIF_F_HIGHDMA_BIT);
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 3ced63aaa6cb..64d94cc8d263 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_feature_helpers.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 30f93d01b4d7..b71e8d37e48e 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1951,7 +1951,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
 	if (np && of_get_property(np, "no-hw-checksum", NULL))
 		netdev_hw_features_clear_set(netdev, NETIF_F_HW_CSUM_BIT,
 					     NETIF_F_RXCSUM_BIT);
-	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 9cd1a51fd60c..abfe54500719 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -242,7 +242,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 846ea4800301..7a4de2bd3418 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -3251,7 +3251,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 c0426ee6aeed..57734fae1c1e 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1769,7 +1769,7 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 	netdev_features_set_set(tso_flags, NETIF_F_TSO_BIT,
 				NETIF_F_TSO6_BIT, NETIF_F_TSO_ECN_BIT,
 				NETIF_F_GSO_UDP_L4_BIT);
-	vlan_feat = gso_encap_flags | tso_flags;
+	netdev_features_or(vlan_feat, gso_encap_flags, tso_flags);
 	netdev_features_set_set(vlan_feat, NETIF_F_SG_BIT,
 				NETIF_F_HW_CSUM_BIT,
 				NETIF_F_HIGHDMA_BIT);
@@ -1778,12 +1778,12 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 				   NETIF_F_RXCSUM_BIT);
 	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 5e4b13f3aead..239b1ff2c322 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 f7796d1301e4..6c4a37fae478 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -2345,7 +2345,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
 					   NETIF_F_RXCSUM_BIT, NETIF_F_SG_BIT,
 					   NETIF_F_GSO_BIT, NETIF_F_GRO_BIT,
 					   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
-		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 0b35c3d3f6fb..cf2a2e123279 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -3337,7 +3337,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,
@@ -3346,7 +3346,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;
 
@@ -3359,9 +3359,9 @@ static void hns3_set_default_feature(struct net_device *netdev)
 				NETIF_F_NTUPLE_BIT,
 				NETIF_F_HW_TC_BIT);
 	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 42bea854c367..3c97e9ae9cb2 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -3174,7 +3174,7 @@ static int emac_probe(struct platform_device *ofdev)
 		netdev_hw_features_zero(ndev);
 		netdev_hw_features_set_set(ndev, NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_SG_BIT);
-		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 460f31f9b8cb..6155eb06dfe8 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1686,15 +1686,15 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 					   NETIF_F_IPV6_CSUM_BIT,
 					   NETIF_F_RXCSUM_BIT);
 
-	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 0df1835faa9f..e6b46fcf3a57 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4890,7 +4890,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;
 
@@ -4901,7 +4902,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 0840cf57aa1a..f1c7f42c59c1 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -1052,7 +1052,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_set(netdev,
 				   NETIF_F_RXCSUM_BIT,
 				   NETIF_F_RXALL_BIT,
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index a8e3417c179a..e78b7b99a124 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 bffb7c0313d0..9346cf8cdf45 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1592,17 +1592,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 64723ab03eaf..a6ad3df2c745 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13664,10 +13664,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);
@@ -13679,25 +13679,26 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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_set(netdev, NETIF_F_SG_BIT,
 				     NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_BIT,
 				     NETIF_F_TSO6_BIT);
-	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;
+	netdev_features_or(hw_features, hw_enc_features,
+			   netdev_ctag_vlan_offload_features);
 
 	if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
 		netdev_features_set_set(hw_features, NETIF_F_NTUPLE_BIT,
 					NETIF_F_HW_TC_BIT);
 
-	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 95acdb5fb492..523e8c9252ab 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4457,7 +4457,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;
@@ -4524,7 +4525,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;
@@ -4630,9 +4631,12 @@ iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
 			      netdev_features_t requested_features)
 {
 	netdev_features_t allowed_features;
+	netdev_features_t vlan_hw_features;
+	netdev_features_t vlan_features;
 
-	allowed_features = iavf_get_netdev_vlan_hw_features(adapter) |
-		iavf_get_netdev_vlan_features(adapter);
+	vlan_hw_features = iavf_get_netdev_vlan_hw_features(adapter);
+	vlan_features = iavf_get_netdev_vlan_features(adapter);
+	netdev_features_or(allowed_features, vlan_hw_features, vlan_features);
 
 	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
 					      allowed_features,
@@ -4777,10 +4781,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
@@ -4797,12 +4801,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 ff0c4cecb092..974693a0e067 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3373,9 +3373,9 @@ static void ice_set_netdev_features(struct net_device *netdev)
 					    NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 					    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_or(netdev, 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);
@@ -3385,18 +3385,18 @@ static void ice_set_netdev_features(struct net_device *netdev)
 				     NETIF_F_TSO6_BIT);
 
 	/* 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
@@ -3404,7 +3404,8 @@ 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);
 
 	/* Leave CRC / FCS stripping enabled by default, but allow the value to
 	 * be changed at runtime
@@ -5830,12 +5831,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 ab1c72753033..a31fd2db8263 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3302,10 +3302,10 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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_set(netdev, netdev->features);
 	netdev_hw_features_set_set(netdev,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT,
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
@@ -3316,13 +3316,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 56d1dee40f51..e09e31a94ae5 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2786,18 +2786,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 798b932eebb5..e76e095e051b 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6365,7 +6365,7 @@ static int igc_probe(struct pci_dev *pdev,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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);
@@ -6376,14 +6376,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 53d27e7ba43d..6eac56f0cd69 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -10987,7 +10987,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_hw_features_set_set(netdev,
@@ -11002,7 +11002,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 					       NETIF_F_GSO_ESP_BIT);
 #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_set(netdev,
 				   NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT,
@@ -11017,18 +11017,18 @@ 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_set(netdev,
 				     NETIF_F_SG_BIT,
 				     NETIF_F_TSO_BIT,
 				     NETIF_F_TSO6_BIT,
 				     NETIF_F_HW_CSUM_BIT);
-	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 2bc6092309ea..172c0488687f 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4620,12 +4620,12 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 	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_set(netdev,
@@ -4633,11 +4633,11 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				     NETIF_F_TSO_BIT,
 				     NETIF_F_TSO6_BIT,
 				     NETIF_F_HW_CSUM_BIT);
-	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 cb54394aad51..08297329cc9c 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -5618,8 +5618,8 @@ static int mvneta_probe(struct platform_device *pdev)
 	netdev_active_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
 				       NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT,
 				       NETIF_F_RXCSUM_BIT);
-	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 5cdf778d8af8..5a533a4e726f 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);
 		}
 	}
 
@@ -6851,7 +6852,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 				NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT);
 	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_set(dev, NETIF_F_RXCSUM_BIT, NETIF_F_GRO_BIT,
 				   NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
@@ -6863,7 +6864,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 64490b2a90b6..b5234cf6716e 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 686d8e122a40..d6075630525c 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -2751,7 +2751,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 				   NETIF_F_RXHASH_BIT, NETIF_F_SG_BIT,
 				   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
 				   NETIF_F_GSO_UDP_L4_BIT);
-	netdev->features |= netdev->hw_features;
+	netdev_active_features_set(netdev, netdev->hw_features);
 
 	err = otx2_mcam_flow_init(pf);
 	if (err)
@@ -2764,11 +2764,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 dc9848c5b3d5..87870bab4893 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -646,9 +646,9 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 				   NETIF_F_GSO_UDP_L4_BIT);
 	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 2b01ed5c6913..2a761f09d267 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3864,7 +3864,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 		netdev_hw_features_zero(dev);
 		netdev_hw_features_set_set(dev, NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_SG_BIT, NETIF_F_RXCSUM_BIT);
-		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 9410f898671e..d17b56857ffe 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4651,11 +4651,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 b4de9b45540d..1cb707c987fa 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3902,7 +3902,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 65a1d1c65de2..a2550be0a1b1 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3327,7 +3327,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
 				   NETIF_F_IPV6_CSUM_BIT);
 	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 6f27aa24b6e2..bf3e53acd5d2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -735,7 +735,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 be05d2a60177..91b8f9a15018 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -6716,7 +6716,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 1645e7cd17d2..c4c4c282890e 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -753,7 +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 |= 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 01e2799dafe1..39ddccd62afe 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -3872,7 +3872,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 fdc883ba136b..0335a389bb01 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 2157d22ced2b..dbc46e260969 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -7859,7 +7859,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 				   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
 				   NETIF_F_RXCSUM_BIT, NETIF_F_LRO_BIT,
 				   NETIF_F_SG_BIT);
-	dev->features |= dev->hw_features;
+	netdev_active_features_set(dev, dev->hw_features);
 	netdev_active_features_set_set(dev, NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				       NETIF_F_HW_VLAN_CTAG_RX_BIT,
 				       NETIF_F_HIGHDMA_BIT);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 0cd76ae68ddb..bcd348fc501e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2362,7 +2362,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) {
@@ -2371,7 +2371,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 3c762f5dc8ec..476a91ef99b9 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 44d3bc6acce9..acf3b88f9edb 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -5821,10 +5821,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 ac83523c3baa..eaebaac13180 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1544,10 +1544,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 85e57a012bec..3ab48fccd634 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1358,7 +1358,7 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
 		netdev_hw_features_set_set(netdev, NETIF_F_IPV6_CSUM_BIT,
 					   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);
@@ -1371,7 +1371,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 0ccc4496c08c..590efc540e4f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2287,8 +2287,9 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 				     NETIF_F_HIGHDMA_BIT);
 
 	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 3f7dacbd08df..97cb15d48fc6 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5262,7 +5262,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.
@@ -5271,7 +5271,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 9a0e1af76ebc..624079763107 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -2111,7 +2111,7 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
 				   NETIF_F_IPV6_CSUM_BIT, NETIF_F_RXCSUM_BIT,
 				   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
 				   NETIF_F_GRO_BIT);
-	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 fc7cdea99654..7c4338bddab3 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1352,7 +1352,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
 	netdev_features_zero(hw_enc_features);
 	/* add encapsulated checksum offload features */
 	if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx))
-		hw_enc_features |= netdev_ip_csum_features;
+		netdev_features_set(hw_enc_features, netdev_ip_csum_features);
 	/* add encapsulated TSO features */
 	if (efx_has_cap(efx, TX_TSO_V2_ENCAP)) {
 		netdev_features_t encap_tso_features;
@@ -1364,9 +1364,9 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
 					NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 					NETIF_F_GSO_GRE_CSUM_BIT);
 
-		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 787e69216303..8314049ff340 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -367,10 +367,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_set(net_dev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT);
 	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 183d3df49a2a..7fda289809f4 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -197,9 +197,9 @@ int efx_ef100_init_datapath_caps(struct efx_nic *efx)
 					NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
 					NETIF_F_GSO_GRE_BIT,
 					NETIF_F_GSO_GRE_CSUM_BIT);
-		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 3efa720b9355..03319eb81cfa 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1002,7 +1002,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_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
 	if ((*efx->type->offload_features & NETIF_F_IPV6_CSUM) ||
@@ -1012,13 +1012,13 @@ 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_set(net_dev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
 				     NETIF_F_RXCSUM_BIT);
 
 	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;
@@ -1028,7 +1028,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 70a48ede5599..71f90a2c341c 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 d26a8334b844..bfcb7d2c66fd 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);
 
@@ -2901,7 +2901,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 */
@@ -2915,7 +2915,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 3c51561e200e..35fa95504a5f 100644
--- a/drivers/net/ethernet/sfc/falcon/net_driver.h
+++ b/drivers/net/ethernet/sfc/falcon/net_driver.h
@@ -1302,8 +1302,11 @@ static inline struct ef4_rx_buffer *ef4_rx_buffer(struct ef4_rx_queue *rx_queue,
 static inline netdev_features_t ef4_supported_features(const struct ef4_nic *efx)
 {
 	const struct net_device *net_dev = efx->net_dev;
+	netdev_features_t features;
 
-	return net_dev->features | net_dev->hw_features;
+	netdev_features_or(features, net_dev->features, net_dev->hw_features);
+
+	return 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 293af2027995..dae500645595 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1753,8 +1753,11 @@ efx_channel_tx_old_fill_level(struct efx_channel *channel)
 static inline netdev_features_t efx_supported_features(const struct efx_nic *efx)
 {
 	const struct net_device *net_dev = efx->net_dev;
+	netdev_features_t features;
 
-	return net_dev->features | net_dev->hw_features;
+	netdev_features_or(features, net_dev->features, net_dev->hw_features);
+
+	return 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 8905065f575f..98de7d4da0aa 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -985,7 +985,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_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
 	if ((*efx->type->offload_features & NETIF_F_IPV6_CSUM) ||
@@ -995,13 +995,13 @@ 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_set(net_dev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
 				     NETIF_F_RXCSUM_BIT);
 
 	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;
@@ -1011,7 +1011,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 3b37d9ccfc6c..1c2c7500848e 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 36db05a3fb03..7040cfccd556 100644
--- a/drivers/net/ethernet/sfc/siena/net_driver.h
+++ b/drivers/net/ethernet/sfc/siena/net_driver.h
@@ -1681,8 +1681,11 @@ efx_channel_tx_old_fill_level(struct efx_channel *channel)
 static inline netdev_features_t efx_supported_features(const struct efx_nic *efx)
 {
 	const struct net_device *net_dev = efx->net_dev;
+	netdev_features_t features;
 
-	return net_dev->features | net_dev->hw_features;
+	netdev_features_or(features, net_dev->features, net_dev->hw_features);
+
+	return 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 754a1df0099e..72328ed81ae1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7128,7 +7128,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;
@@ -7174,14 +7174,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 ded37de7e450..1fae42ea9879 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9739,7 +9739,7 @@ static void niu_set_basic_features(struct net_device *dev)
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_RXHASH_BIT);
-	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 29f66d042d48..adf00230329c 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2787,7 +2787,7 @@ 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);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, 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];
@@ -3109,7 +3109,7 @@ static int happy_meal_pci_probe(struct pci_dev *pdev,
 	/* Happy Meal can do it all... */
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, 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 c985c67596f8..d81a3b69ec47 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 d5cfdb196ead..5a9a9c1cf1fd 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -973,7 +973,7 @@ static int rhine_init_one_common(struct device *hwdev, u32 quirks,
 					       NETIF_F_HW_CSUM_BIT);
 
 	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 bdf8624995f5..4bf2d7dce38f 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -1250,11 +1250,11 @@ static void geneve_setup(struct net_device *dev)
 				       NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				       NETIF_F_FRAGLIST_BIT,
 				       NETIF_F_RXCSUM_BIT);
-	dev->features    |= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_FRAGLIST_BIT, NETIF_F_RXCSUM_BIT);
-	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 e8c5d5d3e3d8..2be3039acf20 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 58718326083a..37c660df9a39 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -315,17 +315,18 @@ 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;
+	netdev_features_or(ifb_features, NETIF_F_GSO_SOFTWARE,
+			   NETIF_F_GSO_ENCAP_ALL);
 	netdev_features_set_set(ifb_features, 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);
-	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 ef346c99e42e..c9993c6d0cec 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -129,10 +129,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;
 
@@ -233,15 +233,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);
+	netdev_features_or(tmp, IPVLAN_FEATURES, IPVLAN_ALWAYS_ON);
 	features &= tmp;
 
 	return features;
@@ -1020,7 +1020,8 @@ static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
 static void __init ipvlan_features_init(void)
 {
 	/* NETIF_F_GSO_ENCAP_ALL NETIF_F_GSO_SOFTWARE Newly added */
-	ipvlan_offload_features = NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev_features_or(ipvlan_offload_features, NETIF_F_GSO_SOFTWARE,
+			   NETIF_F_GSO_ENCAP_ALL);
 	netdev_features_set_set(ipvlan_offload_features,
 				NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				NETIF_F_GSO_ROBUST_BIT);
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 197037f22d27..dfe6b39f1fc7 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3479,7 +3479,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 +
@@ -3517,8 +3517,9 @@ 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 d58d585d73bf..d1423617ff0c 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -896,11 +896,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);
@@ -1080,10 +1080,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;
 
@@ -1091,8 +1091,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);
+	netdev_features_or(tmp, ALWAYS_ON_FEATURES, MACVLAN_FEATURES);
 	features &= tmp;
 
 	return features;
@@ -1819,7 +1819,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;
+	netdev_features_or(macvlan_offload_features, NETIF_F_GSO_SOFTWARE,
+			   NETIF_F_GSO_ENCAP_ALL);
 	netdev_features_set_set(macvlan_offload_features,
 				NETIF_F_SG_BIT,
 				NETIF_F_HW_CSUM_BIT,
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index 26232f59a94e..2bea292328a5 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -425,7 +425,7 @@ 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;
+	netdev_hw_enc_features_or(dev, enc_features, NETIF_F_GSO_ENCAP_ALL);
 	dev->hard_header_len = max_hard_header_len;
 
 	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
@@ -744,11 +744,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;
+	netdev_hw_features_or(failover_dev, 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 4959b22551e4..db31ebdb6b64 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -340,7 +340,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 d1f39c5ce632..41e8af2325dd 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1014,8 +1014,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;
+	netdev_hw_enc_features_or(team->dev, 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;
@@ -2007,7 +2008,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) {
@@ -2178,9 +2179,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 ba9a8f6c5fd9..c0f0cff917ce 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -2890,7 +2890,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 ac430e2d19b4..88a57c8ad62f 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1298,7 +1298,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
 				       NETIF_F_RXCSUM_BIT,
 				       NETIF_F_TSO_BIT);
 
-	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 b973c0d3c6e1..2d216c0d74de 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1474,7 +1474,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 ae6d20365e47..5c2218f5fbed 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1571,7 +1571,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;
 			}
 		}
@@ -1632,7 +1633,8 @@ 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_or(veth_features, NETIF_F_GSO_SOFTWARE,
+			   NETIF_F_GSO_ENCAP_ALL);
 	netdev_features_set_set(veth_features, NETIF_F_SG_BIT,
 				NETIF_F_FRAGLIST_BIT, NETIF_F_HW_CSUM_BIT,
 				NETIF_F_RXCSUM_BIT, NETIF_F_SCTP_CRC_BIT,
@@ -1642,7 +1644,7 @@ static void veth_setup(struct net_device *dev)
 				NETIF_F_HW_VLAN_STAG_TX_BIT,
 				NETIF_F_HW_VLAN_STAG_RX_BIT);
 	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 eca9d6b28b75..4900ab1bdea6 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3728,7 +3728,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 			netdev_active_features_set_set(dev, NETIF_F_HW_CSUM_BIT,
 						       NETIF_F_SG_BIT);
 		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? */
@@ -3744,7 +3745,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 5b3088b0b6f7..c7fd71f66b2e 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1688,7 +1688,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_set(dev, NETIF_F_RXCSUM_BIT,
 				       NETIF_F_HW_CSUM_BIT,
 				       NETIF_F_SCTP_CRC_BIT, NETIF_F_SG_BIT,
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index f8bb383779e1..e179c780b761 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3167,12 +3167,12 @@ static void vxlan_setup(struct net_device *dev)
 				       NETIF_F_HW_CSUM_BIT,
 				       NETIF_F_FRAGLIST_BIT,
 				       NETIF_F_RXCSUM_BIT);
-	dev->features   |= NETIF_F_GSO_SOFTWARE;
+	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 
 	dev->vlan_features = dev->features;
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_FRAGLIST_BIT, NETIF_F_RXCSUM_BIT);
-	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 99ec1a71a8d9..6930f0882b0d 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -297,9 +297,9 @@ static void wg_setup(struct net_device *dev)
 	netdev_features_set_set(wg_netdev_features, NETIF_F_HW_CSUM_BIT,
 				NETIF_F_RXCSUM_BIT, NETIF_F_SG_BIT,
 				NETIF_F_GSO_BIT, NETIF_F_HIGHDMA_BIT);
-	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 4b61525f5853..b1af33ed0a35 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -342,7 +342,7 @@ wil_vif_alloc(struct wil6210_priv *wil, const char *name,
 				   NETIF_F_GRO_BIT, NETIF_F_TSO_BIT,
 				   NETIF_F_TSO6_BIT);
 
-	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 25176f5cf94d..603fa9183816 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 1003233f8cc1..00bd7be507db 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1744,7 +1744,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 33f2fad0b9b9..c2b6f2d8dcd5 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6874,7 +6874,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 
 		netdev_features_zero(restricted);
 		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 614859697a96..e7484986d94f 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1908,7 +1908,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_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index d7ab441e0560..d5ceaf4b52d3 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -702,9 +702,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;
@@ -716,7 +716,8 @@ netdev_get_wanted_features(struct net_device *dev)
 	netdev_features_t tmp;
 
 	tmp = dev->features & ~dev->hw_features;
-	return dev->wanted_features | tmp;
+	netdev_features_set(tmp, dev->wanted_features);
+	return tmp;
 }
 
 #endif
diff --git a/include/net/udp.h b/include/net/udp.h
index f6bfe025f865..ecdf76e4318f 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 70e92a44cbb0..07b70cf135ef 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;
+	netdev_features_or(ret, 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 d1ba565425d0..72e72a799943 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -567,15 +567,15 @@ 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;
+	netdev_hw_features_or(dev, NETIF_F_GSO_SOFTWARE, NETIF_F_GSO_ENCAP_ALL);
+	netdev_hw_features_set(dev, NETIF_F_ALL_FCOE);
 	netdev_hw_features_set_set(dev, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_SG_BIT,
 				   NETIF_F_FRAGLIST_BIT,
 				   NETIF_F_HIGHDMA_BIT,
 				   NETIF_F_SCTP_CRC_BIT);
 
-	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)
@@ -662,9 +662,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;
+	netdev_features_or(tmp, 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 7f2869ab25c6..f1d851deb536 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -500,7 +500,7 @@ void br_dev_setup(struct net_device *dev)
 				       NETIF_F_NETNS_LOCAL_BIT,
 				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				       NETIF_F_HW_VLAN_STAG_TX_BIT);
-	dev->hw_features = common_features | netdev_tx_vlan_features;
+	netdev_hw_features_or(dev, 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 5c6839083b21..f396d6a63b9f 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,
 
 		partial_features = dev->features & dev->gso_partial_features;
 		netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, partial_features);
-		partial_features |= features;
+		netdev_features_set(partial_features, features);
 		if (!skb_gso_ok(skb, partial_features))
 			features &= ~NETIF_F_GSO_PARTIAL;
 	}
@@ -3565,7 +3565,8 @@ 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;
+		netdev_features_or(tmp, dev->vlan_features,
+				   netdev_tx_vlan_features);
 		features = netdev_intersect_features(features, tmp);
 	}
 
@@ -10027,9 +10028,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);
@@ -11152,17 +11153,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;
+	netdev_features_or(tmp, 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 62b560e30296..61e8dc0d65d9 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2374,7 +2374,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/common.h b/net/ethtool/common.h
index 2dc2b80aea5f..d2faec777289 100644
--- a/net/ethtool/common.h
+++ b/net/ethtool/common.h
@@ -4,6 +4,7 @@
 #define _ETHTOOL_COMMON_H
 
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #include <linux/ethtool.h>
 
 #define ETHTOOL_DEV_FEATURE_WORDS	DIV_ROUND_UP(NETDEV_FEATURE_COUNT, 32)
diff --git a/net/ethtool/features.c b/net/ethtool/features.c
index 67a837d44491..51e4702c2b6d 100644
--- a/net/ethtool/features.c
+++ b/net/ethtool/features.c
@@ -255,7 +255,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
 	if (!bitmap_equal(req_wanted, old_wanted, NETDEV_FEATURE_COUNT)) {
 		dev->wanted_features &= ~dev->hw_features;
 		tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features;
-		dev->wanted_features |= tmp;
+		netdev_wanted_features_set(dev, tmp);
 		__netdev_update_features(dev);
 	}
 	ethnl_features_to_bitmap(new_active, dev->features);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 672ffa3ba2e1..052edfd2bee1 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -159,7 +159,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 
 	dev->wanted_features &= ~valid;
 	tmp = wanted & valid;
-	dev->wanted_features |= tmp;
+	netdev_wanted_features_set(dev, tmp);
 	__netdev_update_features(dev);
 
 	tmp = dev->wanted_features ^ dev->features;
@@ -296,7 +296,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;
 
@@ -363,7 +363,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 6ee63ea39eb5..480754eadf4b 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 8e54d5b20f1e..fc7835e24717 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -373,8 +373,8 @@ static void ipip_tunnel_setup(struct net_device *dev)
 				NETIF_F_FRAGLIST_BIT,
 				NETIF_F_HIGHDMA_BIT,
 				NETIF_F_HW_CSUM_BIT);
-	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 ca36765bd453..b36ec1e215ae 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 04c0db84bdc6..86c7052a3dd3 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1838,8 +1838,8 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
 				NETIF_F_FRAGLIST_BIT,
 				NETIF_F_HIGHDMA_BIT,
 				NETIF_F_HW_CSUM_BIT);
-	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 2d39f53c81a4..15b0a28d339b 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1432,8 +1432,8 @@ static void ipip6_tunnel_setup(struct net_device *dev)
 				NETIF_F_HIGHDMA_BIT,
 				NETIF_F_HW_CSUM_BIT);
 	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 f14b0da3b9e1..d2227c0af028 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -2228,10 +2228,10 @@ 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);
 		ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 		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 3427752ecc8d..d5607d4cf903 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1543,7 +1543,8 @@ static void __init ieee80211_features_init(void)
 				NETIF_F_SG_BIT,
 				NETIF_F_HIGHDMA_BIT);
 	netdev_features_set_set(mac80211_rx_features, NETIF_F_RXCSUM_BIT);
-	mac80211_supported_features = mac80211_tx_features | mac80211_rx_features;
+	netdev_features_or(mac80211_supported_features, 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 2bf22a159aae..7af99c4758c1 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -109,7 +109,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_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
+	netdev_active_features_or(netdev, NETIF_F_GSO_SOFTWARE,
+				  NETIF_F_GSO_ENCAP_ALL);
 	netdev_active_features_set_set(netdev, NETIF_F_LLTX_BIT,
 				       NETIF_F_SG_BIT,
 				       NETIF_F_FRAGLIST_BIT,
@@ -118,7 +119,7 @@ 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_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..c0c7df416ce6 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -156,7 +156,8 @@ 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,8 @@ 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 9ef68486816a..3d5b8c6377d7 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -594,8 +594,8 @@ static int xfrmi_dev_init(struct net_device *dev)
 	netdev_features_set_set(xfrmi_features, NETIF_F_SG_BIT,
 				NETIF_F_FRAGLIST_BIT, NETIF_F_HW_CSUM_BIT);
 	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] 74+ messages in thread

* [RFCv8 PATCH net-next 26/55] treewide: use netdev_feature_change helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (24 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 25/55] treewide: use netdev_features_or/set helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 27/55] treewide: use netdev_feature_del helpers Jian Shen
                   ` (30 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the 'f1 ^= f2' 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 3a610e650db9..5d0b0f665dbb 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 df3a8b786c7a..bfc1d0a173af 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 b4f65851dff3..37de6de15b15 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1097,7 +1097,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 52e9ae11f237..6c39c7def645 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1912,7 +1912,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");
 	}
 
@@ -1948,7 +1948,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 c2b6f2d8dcd5..c4f1734fa490 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6799,31 +6799,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] 74+ messages in thread

* [RFCv8 PATCH net-next 27/55] treewide: use netdev_feature_del helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (25 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 26/55] treewide: use netdev_feature_change helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 28/55] treewide: use netdev_features_andnot/clear helpers Jian Shen
                   ` (29 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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/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  |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 18 ++++-----
 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      |  4 +-
 .../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 +-
 .../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                               |  6 ++-
 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 +--
 90 files changed, 275 insertions(+), 234 deletions(-)

diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index b5598ce80465..379b3d809f9e 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -1356,7 +1356,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 1c66e9a7bb5e..93ddf9a66be3 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2216,7 +2216,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 2cee6182cc76..aac5d0936912 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -231,13 +231,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;
@@ -466,7 +466,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 2fcd85924dfa..946f7edc0b8e 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 36ee563aa633..8da6938e2335 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 cbbb0ac2e1f3..f428181b9d0b 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 5a295d8b1cd7..b87d4bf67747 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 3655af27b665..39d9ac51ca62 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8602,7 +8602,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 823a335a607b..a957ec4f60fd 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 19a164e96a2b..a46c7bbb7e9b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13259,7 +13259,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 6cb58b0c21aa..a6d66ca75886 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,17 +11177,17 @@ 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) || bp->xdp_prog)
 		netdev_features_clear_set(features, NETIF_F_LRO_BIT,
 					  NETIF_F_GRO_HW_BIT);
 
 	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.
@@ -12257,8 +12257,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);
@@ -13637,7 +13637,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 0f5eae9b0722..c76bd2b4d245 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;
 		}
 	}
@@ -4064,7 +4064,7 @@ static int macb_init(struct platform_device *pdev)
 		netdev_hw_features_set_set(dev, NETIF_F_HW_CSUM_BIT,
 					   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 41de76874bfb..182c2b8d8aec 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;
 }
@@ -3583,7 +3583,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 					NETIF_F_TSO6_BIT, NETIF_F_LRO_BIT);
 
 		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;
 
@@ -3596,11 +3596,11 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 				    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 dc847580d4c7..232dc5d31db6 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;
 }
@@ -2113,7 +2113,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 					NETIF_F_TSO6_BIT, NETIF_F_LRO_BIT);
 
 		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;
@@ -2122,10 +2122,10 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 				    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 7818d35545d2..d43da69d2213 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 b326156e3605..243990dc9c09 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 04dcb4c3c043..17c26c54a71e 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 5d0b0f665dbb..4ca7dc2bbf12 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 f487990850f6..63fdfe40b813 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 d9c2b84d7231..dc8a4b63d461 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2887,7 +2887,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 e41adc6136c2..bbfa177199c8 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5077,7 +5077,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 b71e8d37e48e..0a8c6bcff3fb 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1942,11 +1942,11 @@ 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_clear_set(netdev, NETIF_F_HW_CSUM_BIT,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index cf2a2e123279..2073d6899106 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -3348,7 +3348,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_set(vlan_off_features,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 14a8ec0e33f9..dc1f7c6d8049 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 6155eb06dfe8..215121bbc375 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 f1c7f42c59c1..0021ff6ea0a0 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 e78b7b99a124..4f8fbe326b71 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 15ff28cef749..0e8f0a44f6b4 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -306,7 +306,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 a6ad3df2c745..1ad68869cfe9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13702,7 +13702,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 523e8c9252ab..b1e768a8b757 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4641,31 +4641,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) &&
@@ -4820,16 +4826,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 a31fd2db8263..8596c3e925a3 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;
 }
@@ -2538,7 +2538,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 e09e31a94ae5..edf03bfe8914 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2651,7 +2651,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 e76e095e051b..fd1db5a1f12d 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4981,7 +4981,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;
 }
@@ -5044,7 +5044,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 1346ed31319c..5d72dcf1dcb3 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 9b47129624f9..00f4e95fcd31 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -899,7 +899,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 6eac56f0cd69..6f908468fdeb 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;
@@ -10254,7 +10254,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 172c0488687f..124d2396a2ba 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4432,7 +4432,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/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index bc3e6aae6efa..cb0102417a68 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_feature_helpers.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 d6075630525c..f2a975e2a75a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1911,7 +1911,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 d17b56857ffe..a8b3999a275d 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 a2550be0a1b1..c81c54f6627e 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;
 }
@@ -3547,7 +3547,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
@@ -3556,14 +3557,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 !
@@ -3573,7 +3575,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 1892ccb889b3..7cf11c1b93a2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -1311,7 +1311,7 @@ int mlx5e_create_flow_steering(struct mlx5e_flow_steering *fs,
 				       !!(netdev->hw_features & NETIF_F_NTUPLE));
 	if (err) {
 		fs_err(fs, "Failed to create arfs tables, err=%d\n", err);
-		netdev->hw_features &= ~NETIF_F_NTUPLE;
+		netdev_hw_feature_del(netdev, NETIF_F_NTUPLE_BIT);
 	}
 
 	err = mlx5e_create_inner_ttc_table(fs, rx_res);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index ab3b082d5eac..bd4b6ce608bd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3894,19 +3894,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");
 
@@ -3928,7 +3928,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");
 	}
@@ -3936,22 +3936,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);
 		}
 	}
 
@@ -3959,23 +3959,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);
 		}
 	}
 
@@ -4972,10 +4972,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 7deeb58d8da1..ac983e9c2b3c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -335,7 +335,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->fs, priv->rx_res);
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 39ddccd62afe..9f65201a1f70 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -2897,7 +2897,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;
@@ -3874,9 +3874,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 bcd348fc501e..ca0c08673ada 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1762,13 +1762,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");
 		}
@@ -2432,7 +2436,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 476a91ef99b9..ae960254296b 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 3ab48fccd634..99d8e3c17510 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 8034d812d5a0..1154960b5563 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_feature_helpers.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..53565295b73c 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 45e07e50d83a..49e2278e3e8a 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1567,7 +1567,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 */
@@ -2456,7 +2456,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 37de6de15b15..3149f46d603d 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1033,12 +1033,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);
@@ -1082,7 +1083,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 ce4ff91f240a..7d97b3e012e5 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 97cb15d48fc6..bf6da741ac44 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5257,7 +5257,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 5dfe8ac0e43e..a97232d88647 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 03319eb81cfa..9ea5f6507deb 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1021,13 +1021,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 bfcb7d2c66fd..b30b7ccbc701 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2914,7 +2914,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..64d01b301585 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 98de7d4da0aa..cc988436a108 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -1004,13 +1004,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/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 72328ed81ae1..d0b7bc8acee3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5591,7 +5591,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..9bdbaf691201 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 5562b0d504af..6bac37951b65 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2017,7 +2017,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 d1423617ff0c..e8b59097b176 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1088,7 +1088,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 0adc6cc0121f..43b75c14d4a3 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -9690,8 +9690,8 @@ static int rtl8152_probe(struct usb_interface *intf,
 				     NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO6_BIT);
 
 	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 5c2218f5fbed..9f9bc0008d9c 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1171,7 +1171,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);
 		}
 	}
@@ -1681,8 +1681,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 35199c48ed3a..0be19d8ad6e6 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3369,13 +3369,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 752329ed9ea5..2e3a795818b9 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;
 }
@@ -356,11 +356,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 eda112d8bcca..756c2c8a8b96 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 05ae1cfb740b..e354913f64d9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -607,7 +607,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 e8f2cbbdd734..0de51ba7bed3 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 00bd7be507db..ef885d29fe45 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 c4f1734fa490..5684903171e2 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6751,7 +6751,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);
 	}
@@ -6845,16 +6846,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;
@@ -6913,7 +6914,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 e7484986d94f..34a64b5f4502 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 f396d6a63b9f..a6368c620028 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1585,7 +1585,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))
@@ -1606,7 +1606,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,
 		netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, partial_features);
 		netdev_features_set(partial_features, features);
 		if (!skb_gso_ok(skb, 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;
@@ -9623,30 +9624,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 */
@@ -9665,7 +9666,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);
 		}
 	}
 
@@ -9673,18 +9674,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) {
@@ -9694,13 +9695,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;
@@ -11169,7 +11170,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 8861d47d1c48..d1df34d68943 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -46,6 +46,7 @@
 #include <linux/udp.h>
 #include <linux/sctp.h>
 #include <linux/netdevice.h>
+#include <linux/netdev_feature_helpers.h>
 #ifdef CONFIG_NET_CLS_ACT
 #include <net/pkt_sched.h>
 #endif
@@ -4048,7 +4049,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 956985d3d132..b916f4d6930f 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/netdev_feature_helpers.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 7502543a076a..fd54b586f851 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;
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index 659dd31c43fb..bd999b399347 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..82534cf1fe4f 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 2b9cb5398335..c9a90bed4ce4 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 79df762b20f1..8a09a951db80 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..cc0ca80ac569 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 7af99c4758c1..bf332718aeab 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->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 cb8faf3eaf5e..f4a528febbdc 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -72,7 +72,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 f4d8c40a8828..b8256c0e0a57 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 c0c7df416ce6..eb68ef0cfb54 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -114,7 +114,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;
 	}
 
@@ -141,8 +141,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] 74+ messages in thread

* [RFCv8 PATCH net-next 28/55] treewide: use netdev_features_andnot/clear helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (26 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 27/55] treewide: use netdev_feature_del helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 29/55] treewide: use netdev_features_xor/toggle helpers Jian Shen
                   ` (28 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the 'f1 = f2 & ~f3' features expressions by
netdev_features_andnot helpers, and replace the
'f1 &= ~f2' 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               |  4 ++--
 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   |  3 ++-
 drivers/net/ethernet/broadcom/bnx2.c          |  2 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  8 ++++---
 drivers/net/ethernet/broadcom/tg3.c           |  5 ++--
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  3 ++-
 drivers/net/ethernet/cisco/enic/enic_main.c   |  3 ++-
 drivers/net/ethernet/cortina/gemini.c         |  2 +-
 drivers/net/ethernet/emulex/benet/be_main.c   |  8 ++++---
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   |  5 ++--
 drivers/net/ethernet/ibm/ibmveth.c            | 11 +++++----
 drivers/net/ethernet/ibm/ibmvnic.c            |  2 +-
 drivers/net/ethernet/intel/e1000e/netdev.c    |  6 +++--
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   |  3 ++-
 drivers/net/ethernet/intel/i40e/i40e_main.c   |  5 ++--
 drivers/net/ethernet/intel/iavf/iavf_main.c   |  8 ++++---
 drivers/net/ethernet/intel/ice/ice_main.c     | 17 ++++++++-----
 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   |  4 ++--
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  9 ++++---
 .../mellanox/mlx5/core/en_accel/ipsec_rxtx.h  |  8 +++++--
 .../net/ethernet/mellanox/mlx5/core/en_main.c |  3 ++-
 .../ethernet/netronome/nfp/nfp_net_common.c   | 11 +++++----
 .../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    | 11 ++++++---
 .../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          |  5 ++--
 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                          | 16 +++++++++----
 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                       |  5 ++--
 drivers/net/veth.c                            |  7 +++---
 drivers/net/vmxnet3/vmxnet3_drv.c             |  4 ++--
 drivers/net/vmxnet3/vmxnet3_ethtool.c         | 12 +++++++---
 .../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_feature_helpers.h        |  2 +-
 include/net/sock.h                            |  3 ++-
 include/net/vxlan.h                           |  6 +++--
 net/8021q/vlan.h                              |  2 +-
 net/8021q/vlan_dev.c                          |  3 ++-
 net/bridge/br_if.c                            |  2 +-
 net/core/dev.c                                | 24 +++++++++++--------
 net/core/sock.c                               |  5 ++--
 net/ethtool/features.c                        |  2 +-
 net/ethtool/ioctl.c                           | 12 +++++-----
 net/hsr/hsr_device.c                          |  2 +-
 net/ipv4/esp4_offload.c                       |  6 +++--
 net/ipv4/ip_gre.c                             |  4 ++--
 net/ipv4/ip_output.c                          |  2 +-
 net/ipv4/udp_offload.c                        |  2 +-
 net/ipv6/esp6_offload.c                       |  6 +++--
 net/ipv6/ip6_output.c                         |  2 +-
 net/mac80211/main.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/xfrm/xfrm_device.c                        |  2 +-
 80 files changed, 246 insertions(+), 166 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 70b76c41e314..9920c4cb8aa3 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 0756d00f09e5..b8f8ba623c9e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1408,12 +1408,12 @@ 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 31fa1a65231d..020e5478c039 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -837,7 +837,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;
 }
@@ -850,7 +850,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 d72f1ef73484..6fb1efbe674f 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 92a0d382795b..db35ffb830de 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 946f7edc0b8e..2562f5e443b0 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -521,7 +521,8 @@ 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 39d9ac51ca62..d1e45b7752d0 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 a46c7bbb7e9b..5466966a2243 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 a6d66ca75886..d1664fdfc980 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11195,14 +11195,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;
 }
@@ -11392,7 +11393,8 @@ static netdev_features_t bnxt_features_check(struct sk_buff *skb,
 			return features;
 		break;
 	}
-	return features & ~netdev_csum_gso_features_mask;
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
 }
 
 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 5e1ede8bd049..c5b75539bb7f 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -7878,7 +7878,8 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
 		netif_tx_wake_queue(txq);
 	}
 
-	features = tp->dev->features & ~netdev_general_tso_features;
+	netdev_features_andnot(features, tp->dev->features,
+			       netdev_general_tso_features);
 	segs = skb_gso_segment(skb, features);
 	if (IS_ERR(segs) || !segs)
 		goto tg3_tso_bug_end;
@@ -8309,7 +8310,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 4ca7dc2bbf12..da5989ec5bd2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3852,7 +3852,8 @@ 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;
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
 }
 
 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 dc8a4b63d461..7e1cca8b787b 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -295,7 +295,8 @@ static netdev_features_t enic_features_check(struct sk_buff *skb,
 	return features;
 
 out:
-	return features & ~netdev_csum_gso_features_mask;
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
 }
 
 int enic_is_dynamic(struct enic *enic)
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 2bd0892f5f53..96423bf6ed2d 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -1982,7 +1982,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 bbfa177199c8..fc1345fa42f6 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5086,7 +5086,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
@@ -5121,8 +5121,10 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
 	    skb_inner_mac_header(skb) - skb_transport_header(skb) !=
 		sizeof(struct udphdr) + sizeof(struct vxlanhdr) ||
 	    !adapter->vxlan_port ||
-	    udp_hdr(skb)->dest != adapter->vxlan_port)
-		return features & ~netdev_csum_gso_features_mask;
+	    udp_hdr(skb)->dest != adapter->vxlan_port) {
+		netdev_features_clear(features, netdev_csum_gso_features_mask);
+		return features;
+	}
 
 	return features;
 }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 2073d6899106..bf7bafd465b4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2476,7 +2476,8 @@ static netdev_features_t hns3_features_check(struct sk_buff *skb,
 	 * len of 480 bytes.
 	 */
 	if (len > HNS3_MAX_HDR_LEN)
-		features &= ~netdev_csum_gso_features_mask;
+		netdev_features_clear(features,
+				      netdev_csum_gso_features_mask);
 
 	return features;
 }
@@ -3358,7 +3359,7 @@ static void hns3_set_default_feature(struct net_device *netdev)
 				NETIF_F_GRO_HW_BIT,
 				NETIF_F_NTUPLE_BIT,
 				NETIF_F_HW_TC_BIT);
-	features = netdev->features & ~vlan_off_features;
+	netdev_features_andnot(features, netdev->features, 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 215121bbc375..99f76b0c3031 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,8 @@ 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;
+			netdev_active_features_andnot(dev, features,
+						      NETIF_F_CSUM_MASK);
 			netdev_active_feature_del(dev, NETIF_F_RXCSUM_BIT);
 		}
 	}
@@ -917,7 +919,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;
+			netdev_active_features_andnot(dev, 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 e6b46fcf3a57..32e09372fe0d 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 4f8fbe326b71..7bbab2dca5c0 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 9346cf8cdf45..da65c5487599 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1512,7 +1512,8 @@ 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;
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
 }
 
 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 1ad68869cfe9..30ab7f26b72d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13203,7 +13203,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;
@@ -13235,7 +13235,8 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
 
 	return features;
 out_err:
-	return features & ~netdev_csum_gso_features_mask;
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index b1e768a8b757..03f1dd9d296d 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4403,7 +4403,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;
@@ -4435,7 +4435,8 @@ static netdev_features_t iavf_features_check(struct sk_buff *skb,
 
 	return features;
 out_err:
-	return features & ~netdev_csum_gso_features_mask;
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
 }
 
 /**
@@ -4678,7 +4679,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 974693a0e067..0a4ffc45cc70 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5834,7 +5834,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,
@@ -5842,7 +5843,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 {
@@ -5858,7 +5860,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);
 	}
 
 	if (!(netdev->features & NETIF_F_RXFCS) &&
@@ -5866,7 +5869,8 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 	    (features & NETIF_VLAN_STRIPPING_FEATURES) &&
 	    !ice_vsi_has_non_zero_vlans(np->vsi)) {
 		netdev_warn(netdev, "Disabling VLAN stripping as FCS/CRC stripping is also disabled and there is no VLAN configured\n");
-		features &= ~NETIF_VLAN_STRIPPING_FEATURES;
+		netdev_features_clear(features,
+				      NETIF_VLAN_STRIPPING_FEATURES);
 	}
 
 	return features;
@@ -9011,7 +9015,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)
@@ -9042,7 +9046,8 @@ ice_features_check(struct sk_buff *skb,
 
 	return features;
 out_rm_features:
-	return features & ~netdev_csum_gso_features_mask;
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
 }
 
 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 cc984ad132f5..13d0de32c6f7 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 5a533a4e726f..369aa0a80212 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 a8b3999a275d..0e2908c8f8b2 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 1cb707c987fa..50cebfe2a426 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3900,8 +3900,8 @@ 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;
+	netdev_vlan_features_andnot(eth->netdev[id], *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 c81c54f6627e..36a1d28998b3 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;
@@ -3384,8 +3385,10 @@ 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 &= ~netdev_vlan_offload_features;
-			dev->features &= ~netdev_vlan_offload_features;
+			netdev_hw_features_clear(dev,
+						 netdev_vlan_offload_features);
+			netdev_active_features_clear(dev,
+						     netdev_vlan_offload_features);
 		}
 	} else {
 		if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN &&
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 7ea2f59d73ed..6f83eb46d18a 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,8 @@ 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;
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
 }
 
 static inline bool
@@ -161,7 +162,10 @@ 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; }
+{
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
+}
 
 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 bd4b6ce608bd..70ac775a53e6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4474,7 +4474,8 @@ 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;
+	netdev_features_clear(features, netdev_csum_gso_features_mask);
+	return features;
 }
 
 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 ca0c08673ada..943598704e9a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1802,7 +1802,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 */
@@ -1814,7 +1814,8 @@ 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;
+		netdev_features_clear(features, netdev_csum_gso_features_mask);
+		return features;
 	}
 
 	if (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
@@ -1822,8 +1823,10 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
 	    (l4_hdr != IPPROTO_UDP && l4_hdr != IPPROTO_GRE) ||
 	    (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;
+	      sizeof(struct udphdr) + sizeof(struct vxlanhdr)))) {
+		netdev_features_clear(features, netdev_csum_gso_features_mask);
+		return features;
+	}
 
 	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 eaebaac13180..7a68744b7011 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1546,7 +1546,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;
+	netdev_features_andnot(features, netdev->features,
+			       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..2bbbc7591965 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -1789,13 +1789,18 @@ netdev_features_t qede_features_check(struct sk_buff *skb,
 			if ((skb_inner_mac_header(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;
+			      ntohs(udp_hdr(skb)->dest) != gnv_port)) {
+				netdev_features_clear(features,
+						      netdev_csum_gso_features_mask);
+				return features;
+			}
 		} 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;
+			netdev_features_clear(features,
+					      netdev_csum_gso_features_mask);
+			return features;
 		}
 	}
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 3149f46d603d..e2b74569ae82 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1050,7 +1050,8 @@ static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
 					  NETIF_F_IPV6_CSUM_BIT);
 
 		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 bf6da741ac44..4fe234ef92a0 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1428,12 +1428,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;
@@ -4270,15 +4270,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;
 }
@@ -4295,18 +4295,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 9ea5f6507deb..9f6c4a971c48 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1010,14 +1010,14 @@ 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_set(net_dev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
 				     NETIF_F_RXCSUM_BIT);
 
-	tmp = net_dev->features & ~efx->fixed_features;
+	netdev_features_andnot(tmp, net_dev->features, 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 71f90a2c341c..9fcad774a052 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;
+	netdev_features_andnot(tmp, net_dev->features, 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 b30b7ccbc701..016c459a3cfd 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;
+	netdev_features_andnot(tmp, net_dev->features, data);
 	if (tmp & NETIF_F_NTUPLE) {
 		rc = efx->type->filter_clear_rx(efx, EF4_FILTER_PRI_MANUAL);
 		if (rc)
@@ -2908,7 +2908,8 @@ static int ef4_pci_probe(struct pci_dev *pci_dev,
 	netdev_vlan_features_set_set(net_dev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
 				     NETIF_F_RXCSUM_BIT);
-	net_dev->hw_features = net_dev->features & ~efx->fixed_features;
+	netdev_hw_features_andnot(net_dev, net_dev->features,
+				  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 cc988436a108..e5937694bbb1 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -993,14 +993,15 @@ 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_set(net_dev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_SG_BIT, NETIF_F_HIGHDMA_BIT,
 				     NETIF_F_RXCSUM_BIT);
 
-	tmp = net_dev->features & ~efx->fixed_features;
+	netdev_features_andnot(tmp, net_dev->features,
+			       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/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 1c2c7500848e..808104cf5220 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 d0b7bc8acee3..49a314e709ff 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5594,7 +5594,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
@@ -5602,7 +5602,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 2be3039acf20..29b2376f9ef3 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 37c660df9a39..3a5cbb491487 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -325,7 +325,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 c9993c6d0cec..5bb952c2b30d 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -235,7 +235,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 dfe6b39f1fc7..f81674c5a3de 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3455,8 +3455,12 @@ static netdev_features_t sw_macsec_features __ro_after_init;
  *   VLAN_FEATURES - they require additional ops
  *   HW_MACSEC - no reason to report it
  */
-#define REAL_DEV_FEATURES(dev) \
-	((dev)->features & ~macsec_no_inherit_features)
+static void macsec_real_dev_features(struct net_device *dev,
+				     netdev_features_t *features)
+{
+	netdev_features_andnot(*features, dev->features,
+			       macsec_no_inherit_features);
+}
 
 static int macsec_dev_init(struct net_device *dev)
 {
@@ -3475,7 +3479,7 @@ static int macsec_dev_init(struct net_device *dev)
 	}
 
 	if (macsec_is_offloaded(macsec)) {
-		dev->features = REAL_DEV_FEATURES(real_dev);
+		macsec_real_dev_features(real_dev, &dev->features);
 	} else {
 		dev->features = real_dev->features & SW_MACSEC_FEATURES;
 		netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
@@ -3513,8 +3517,10 @@ static netdev_features_t macsec_fix_features(struct net_device *dev,
 	struct net_device *real_dev = macsec->real_dev;
 	netdev_features_t tmp;
 
-	if (macsec_is_offloaded(macsec))
-		return REAL_DEV_FEATURES(real_dev);
+	if (macsec_is_offloaded(macsec)) {
+		macsec_real_dev_features(real_dev, &tmp);
+		return tmp;
+	}
 
 	tmp = real_dev->features & SW_MACSEC_FEATURES;
 	netdev_features_set(tmp, NETIF_F_GSO_SOFTWARE);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index e8b59097b176..498cb6e04a87 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1082,7 +1082,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 41e8af2325dd..dc6df0ba0a26 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2007,7 +2007,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 c0f0cff917ce..caf449e9e666 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -998,7 +998,8 @@ static int tun_net_init(struct net_device *dev)
 				   NETIF_F_HW_VLAN_STAG_TX_BIT);
 	dev->features = dev->hw_features;
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
-	dev->vlan_features = dev->features & ~netdev_tx_vlan_features;
+	netdev_vlan_features_andnot(dev, dev->features,
+				    netdev_tx_vlan_features);
 
 	tun->flags = (tun->flags & ~TUN_FEATURES) |
 		      (ifr->ifr_flags & TUN_FEATURES);
@@ -1171,7 +1172,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;
+	netdev_features_andnot(tmp2, features, TUN_USER_FEATURES);
 	return tmp1 | tmp2;
 }
 
@@ -2889,7 +2890,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 0eb9fe07c333..027a1c5103f8 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -4291,7 +4291,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 43b75c14d4a3..510531a79221 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2771,9 +2771,10 @@ 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 9f9bc0008d9c..cde2f29ce9a6 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1460,7 +1460,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);
@@ -1560,7 +1560,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;
 		}
 	}
@@ -1645,7 +1645,8 @@ static void veth_setup(struct net_device *dev)
 				NETIF_F_HW_VLAN_STAG_RX_BIT);
 	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;
+	netdev_vlan_features_andnot(dev, 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 0be19d8ad6e6..ccead2500579 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3383,8 +3383,8 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 		}
 	}
 
-	netdev->vlan_features = netdev->hw_features &
-				~netdev_ctag_vlan_offload_features;
+	netdev_vlan_features_andnot(netdev, netdev->hw_features,
+				    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 2e3a795818b9..d9be2fc80de2 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -277,7 +277,9 @@ 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;
+			netdev_features_clear(features,
+					      netdev_csum_gso_features_mask);
+			return features;
 		}
 
 		switch (l4_proto) {
@@ -288,11 +290,15 @@ 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;
+				netdev_features_clear(features,
+						      netdev_csum_gso_features_mask);
+				return features;
 			}
 			break;
 		default:
-			return features & ~netdev_csum_gso_features_mask;
+			netdev_features_clear(features,
+					      netdev_csum_gso_features_mask);
+			return features;
 		}
 	}
 	return features;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 603fa9183816..4a8a0870caa2 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 81645e3b47c8..ca2814ebe0d4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -908,7 +908,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 5684903171e2..762968b23edc 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6748,7 +6748,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,
@@ -6884,7 +6884,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)
@@ -6892,7 +6892,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 6745a3a75041..4b248fe59e67 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -4580,7 +4580,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_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index d5ceaf4b52d3..97b0edf5d2f7 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -715,7 +715,7 @@ netdev_get_wanted_features(struct net_device *dev)
 {
 	netdev_features_t tmp;
 
-	tmp = dev->features & ~dev->hw_features;
+	netdev_features_andnot(tmp, dev->features, dev->hw_features);
 	netdev_features_set(tmp, dev->wanted_features);
 	return tmp;
 }
diff --git a/include/net/sock.h b/include/net/sock.h
index 96a31026e35d..624ed56a43bf 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_feature_helpers.h>
 #include <linux/skbuff.h>	/* struct sk_buff */
 #include <linux/mm.h>
 #include <linux/security.h>
@@ -2244,7 +2245,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..d0e4729acebc 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -372,8 +372,10 @@ static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
 	     (skb_inner_mac_header(skb) - skb_transport_header(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;
+	      !can_checksum_protocol(features, inner_eth_hdr(skb)->h_proto)))) {
+		netdev_features_clear(features, netdev_csum_gso_features_mask);
+		return features;
+	}
 
 	return features;
 }
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 07b70cf135ef..d8ff9230cc53 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 72e72a799943..21dfdaf1389d 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -581,7 +581,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;
+	netdev_vlan_features_andnot(dev, real_dev->vlan_features,
+				    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 efbd93e92ce2..ef8dd8a91164 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 a6368c620028..fb32cd8e8c3e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3488,7 +3488,8 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
 
 	if (skb->ip_summed != CHECKSUM_NONE &&
 	    !can_checksum_protocol(features, type)) {
-		features &= ~netdev_csum_gso_features_mask;
+		netdev_features_clear(features,
+				      netdev_csum_gso_features_mask);
 	}
 	if (illegal_highdma(skb->dev, skb))
 		netdev_feature_del(NETIF_F_SG_BIT, features);
@@ -3517,12 +3518,15 @@ 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;
+	if (gso_segs > READ_ONCE(dev->gso_max_segs)) {
+		netdev_features_clear(features, NETIF_F_GSO_MASK);
+		return features;
+	}
 
 	if (!skb_shinfo(skb)->gso_type) {
 		skb_warn_bad_offload(skb);
-		return features & ~NETIF_F_GSO_MASK;
+		netdev_features_clear(features, NETIF_F_GSO_MASK);
+		return features;
 	}
 
 	/* Support for GSO partial features requires software
@@ -3532,7 +3536,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.
@@ -9612,13 +9616,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) &&
@@ -9655,7 +9659,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)) {
@@ -11163,7 +11167,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;
 
@@ -11171,7 +11175,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 61e8dc0d65d9..5b89b03660b9 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2376,10 +2376,11 @@ 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_features_set_set(sk->sk_route_caps,
 						NETIF_F_SG_BIT,
diff --git a/net/ethtool/features.c b/net/ethtool/features.c
index 51e4702c2b6d..769d77cbeb16 100644
--- a/net/ethtool/features.c
+++ b/net/ethtool/features.c
@@ -253,7 +253,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
 	bitmap_andnot(new_wanted, old_wanted, req_mask, NETDEV_FEATURE_COUNT);
 	bitmap_or(req_wanted, new_wanted, req_wanted, NETDEV_FEATURE_COUNT);
 	if (!bitmap_equal(req_wanted, old_wanted, NETDEV_FEATURE_COUNT)) {
-		dev->wanted_features &= ~dev->hw_features;
+		netdev_wanted_features_clear(dev, dev->hw_features);
 		tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features;
 		netdev_wanted_features_set(dev, tmp);
 		__netdev_update_features(dev);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 052edfd2bee1..21045ba78350 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -147,17 +147,17 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 		wanted |= (netdev_features_t)features[i].requested << (32 * i);
 	}
 
-	tmp = valid & ~NETIF_F_ETHTOOL_BITS;
+	netdev_features_andnot(tmp, valid, NETIF_F_ETHTOOL_BITS);
 	if (tmp)
 		return -EINVAL;
 
-	tmp = valid & ~dev->hw_features;
+	netdev_features_andnot(tmp, valid, dev->hw_features);
 	if (tmp) {
 		valid &= dev->hw_features;
 		ret |= ETHTOOL_F_UNSUPPORTED;
 	}
 
-	dev->wanted_features &= ~valid;
+	netdev_wanted_features_clear(dev, valid);
 	tmp = wanted & valid;
 	netdev_wanted_features_set(dev, tmp);
 	__netdev_update_features(dev);
@@ -298,7 +298,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);
 
@@ -357,11 +357,11 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
 	/* allow changing only bits set in hw_features */
 	changed = dev->features ^ features;
 	changed &= eth_all_features;
-	tmp = changed & ~dev->hw_features;
+	netdev_features_andnot(tmp, changed, dev->hw_features);
 	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 3747f69d48a2..0e37ba6e1569 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 82534cf1fe4f..5aeebbc1d349 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -219,12 +219,14 @@ 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;
+		netdev_features_andnot(esp_features, 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;
+		netdev_features_andnot(esp_features, 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 480754eadf4b..381c98fb2ed4 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 085fcf1395d2..8353875a9506 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);
-	features &= ~NETIF_F_GSO_MASK;
+	netdev_features_clear(features, NETIF_F_GSO_MASK);
 	segs = skb_gso_segment(skb, features);
 	if (IS_ERR_OR_NULL(segs)) {
 		kfree_skb(skb);
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 8a09a951db80..908670adfdfc 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 cc0ca80ac569..19f685f6b378 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -257,11 +257,13 @@ 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;
+		netdev_features_andnot(esp_features, 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;
+		netdev_features_andnot(esp_features, 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 f6f54fdce208..28239182d820 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);
-	features &= ~NETIF_F_GSO_MASK;
+	netdev_features_clear(features, NETIF_F_GSO_MASK);
 	segs = skb_gso_segment(skb, features);
 	if (IS_ERR_OR_NULL(segs)) {
 		kfree_skb(skb);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d5607d4cf903..f2f55129d639 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -945,6 +945,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	int channels, max_bitrates;
 	bool supp_ht, supp_vht, supp_he, supp_eht;
 	struct cfg80211_chan_def dflt_chandef = {};
+	netdev_features_t features;
 
 	if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
 	    (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
@@ -1040,7 +1041,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_andnot(features, hw->netdev_features,
+					   MAC80211_SUPPORTED_FEATURES)))
 		return -EINVAL;
 
 	if (hw->max_report_rates == 0)
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index 7e7585a16f11..022fd85394e8 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;
 
-		features &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(features, NETIF_F_GSO_MASK);
 		segs = skb_gso_segment(skb, features);
 		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 72f99074ff58..55084f0f2f57 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);
 
-	features &= ~NETIF_F_GSO_MASK;
+	netdev_features_clear(features, NETIF_F_GSO_MASK);
 	segs = skb_gso_segment(skb, features);
 
 	if (IS_ERR_OR_NULL(segs)) {
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 621ac3c6d505..dc8b114388e2 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;
 
-		features &= ~NETIF_F_GSO_MASK;
+		netdev_features_clear(features, NETIF_F_GSO_MASK);
 		segs = skb_gso_segment(skb, features);
 		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 9a114fd9de4d..5c883b639ed7 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -13,6 +13,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
+#include <linux/netdev_feature_helpers.h>
 #include <net/netlink.h>
 #include <net/sch_generic.h>
 #include <net/pkt_cls.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;
 
-	features &= ~NETIF_F_GSO_MASK;
+	netdev_features_clear(features, NETIF_F_GSO_MASK);
 	segs = skb_gso_segment(skb, features);
 
 	if (IS_ERR_OR_NULL(segs))
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index eb68ef0cfb54..78ebbccbd616 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;
 		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] 74+ messages in thread

* [RFCv8 PATCH net-next 29/55] treewide: use netdev_features_xor/toggle helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (27 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 28/55] treewide: use netdev_features_andnot/clear helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 30/55] treewide: use netdev_feature_test helpers Jian Shen
                   ` (27 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the 'f1 = f2 ^ f3' features expressions by
netdev_features_xor helpers, and replace the 'f1 ^= f2'
feautres expressions by netdev_features_toggle helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/aquantia/atlantic/aq_main.c   |  4 +++-
 drivers/net/ethernet/asix/ax88796c_main.c          |  3 ++-
 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    |  7 +++++--
 drivers/net/ethernet/broadcom/tg3.c                |  3 ++-
 drivers/net/ethernet/brocade/bna/bnad.c            |  3 ++-
 drivers/net/ethernet/cadence/macb_main.c           |  4 +++-
 drivers/net/ethernet/calxeda/xgmac.c               |  3 ++-
 drivers/net/ethernet/cavium/liquidio/lio_vf_main.c |  3 ++-
 drivers/net/ethernet/cavium/thunder/nicvf_main.c   |  3 ++-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c          |  3 ++-
 drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c    |  3 ++-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |  3 ++-
 .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c    |  3 ++-
 drivers/net/ethernet/davicom/dm9000.c              |  3 ++-
 drivers/net/ethernet/engleder/tsnep_main.c         |  3 ++-
 drivers/net/ethernet/faraday/ftgmac100.c           |  3 ++-
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c   |  3 ++-
 drivers/net/ethernet/freescale/enetc/enetc.c       |  3 ++-
 drivers/net/ethernet/freescale/enetc/enetc_pf.c    |  3 ++-
 drivers/net/ethernet/freescale/fec_main.c          |  6 ++++--
 drivers/net/ethernet/freescale/gianfar_ethtool.c   |  4 +++-
 drivers/net/ethernet/hisilicon/hns3/hns3_enet.c    |  3 ++-
 drivers/net/ethernet/huawei/hinic/hinic_main.c     | 10 ++++++++--
 drivers/net/ethernet/ibm/ibmvnic.c                 |  3 ++-
 drivers/net/ethernet/intel/e100.c                  |  3 ++-
 drivers/net/ethernet/intel/e1000/e1000_main.c      |  3 ++-
 drivers/net/ethernet/intel/e1000e/netdev.c         |  3 ++-
 drivers/net/ethernet/intel/ice/ice_main.c          | 10 +++++++---
 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        |  3 ++-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      |  4 +++-
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c    |  3 ++-
 .../ethernet/marvell/octeontx2/nic/otx2_common.c   |  3 ++-
 .../net/ethernet/marvell/octeontx2/nic/otx2_pf.c   |  3 ++-
 drivers/net/ethernet/marvell/sky2.c                |  3 ++-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c        |  4 +++-
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c  |  3 ++-
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c     |  3 ++-
 drivers/net/ethernet/mscc/ocelot_net.c             |  3 ++-
 drivers/net/ethernet/neterion/s2io.c               |  3 ++-
 .../net/ethernet/netronome/nfp/nfp_net_common.c    |  3 ++-
 drivers/net/ethernet/nvidia/forcedeth.c            |  3 ++-
 .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c   |  3 ++-
 .../net/ethernet/qlogic/netxen/netxen_nic_main.c   |  2 +-
 drivers/net/ethernet/qlogic/qede/qede_filter.c     |  3 ++-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c     |  8 +++++---
 drivers/net/ethernet/qualcomm/emac/emac.c          |  3 ++-
 drivers/net/ethernet/realtek/8139cp.c              |  3 ++-
 drivers/net/ethernet/realtek/8139too.c             |  3 ++-
 drivers/net/ethernet/renesas/ravb_main.c           |  3 ++-
 drivers/net/ethernet/renesas/sh_eth.c              |  3 ++-
 drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c    |  3 ++-
 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                    |  3 ++-
 drivers/net/usb/aqc111.c                           |  3 ++-
 drivers/net/usb/ax88179_178a.c                     |  3 ++-
 drivers/net/usb/r8152.c                            |  4 +++-
 drivers/net/veth.c                                 |  3 ++-
 drivers/net/virtio_net.c                           |  6 ++++--
 drivers/net/vmxnet3/vmxnet3_ethtool.c              |  3 ++-
 drivers/s390/net/qeth_core_main.c                  | 14 +++++++++-----
 drivers/staging/qlge/qlge_main.c                   |  3 ++-
 net/core/dev.c                                     |  3 ++-
 net/ethtool/ioctl.c                                |  5 +++--
 71 files changed, 173 insertions(+), 84 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
index aac5d0936912..b7867dcd5289 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -167,6 +167,7 @@ static int aq_ndev_set_features(struct net_device *ndev,
 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 	bool need_ndev_restart = false;
 	struct aq_nic_cfg_s *aq_cfg;
+	netdev_features_t changed;
 	bool is_lro = false;
 	int err = 0;
 
@@ -198,7 +199,8 @@ static int aq_ndev_set_features(struct net_device *ndev,
 		}
 	}
 
-	if ((aq_nic->ndev->features ^ features) & NETIF_F_RXCSUM) {
+	netdev_features_xor(changed, aq_nic->ndev->features, features);
+	if (changed & 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 ee4428ef59fb..8ad92c2f92cb 100644
--- a/drivers/net/ethernet/asix/ax88796c_main.c
+++ b/drivers/net/ethernet/asix/ax88796c_main.c
@@ -924,8 +924,9 @@ 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_features_xor(changed, ndev->features, 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 2562f5e443b0..8cffd89c855e 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -531,8 +531,9 @@ 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_features_xor(changed, netdev->features, 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 8da6938e2335..b1fdc855ae84 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -400,8 +400,9 @@ 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_features_xor(changed, netdev->features, 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 f428181b9d0b..4dde0f0b5620 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -390,8 +390,9 @@ 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_features_xor(changed, netdev->features, 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 b87d4bf67747..24679d304234 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -255,8 +255,9 @@ 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_features_xor(changed, netdev->features, 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 a957ec4f60fd..44c4d94ad7e3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4905,8 +4905,9 @@ 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_features_xor(changed, dev->features, features);
 		/* Revert the requested changes in features if they
 		 * would require internal reload of PF in bnx2x_set_features().
 		 */
@@ -4940,10 +4941,12 @@ 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;
 	bool bnx2x_reload = false;
 	int rc;
 
+	netdev_features_xor(changes, features, dev->features);
+
 	/* VFs or non SRIOV PFs should be able to change loopback feature */
 	if (!pci_num_vf(bp->pdev)) {
 		if (features & NETIF_F_LOOPBACK) {
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index c5b75539bb7f..720c48bd117f 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -8317,8 +8317,9 @@ 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_features_xor(changed, dev->features, 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 ca543079316a..b0f1da5175ca 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3347,8 +3347,9 @@ 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_features_xor(changed, dev->features, 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 c76bd2b4d245..e608f0c41071 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -3743,7 +3743,9 @@ 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_features_xor(changed, netdev->features, 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 531686bf9426..5405aeb04200 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1492,8 +1492,9 @@ 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_features_xor(changed, dev->features, 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 232dc5d31db6..c9807b759702 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);
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if (!(changed & NETIF_F_LRO))
 		return 0;
 
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index d43da69d2213..0c1a0eb9d1a6 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1789,8 +1789,9 @@ 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_features_xor(changed, netdev->features, 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 243990dc9c09..00e2492d944b 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -880,9 +880,10 @@ 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;
 	struct adapter *adapter = dev->ml_priv;
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, dev->features, features);
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		t1_vlan_mode(adapter, features);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 17c26c54a71e..7c3c4729363a 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -2605,8 +2605,9 @@ 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_features_xor(changed, dev->features, 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 da5989ec5bd2..10aa8786c4d3 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1273,10 +1273,11 @@ 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;
 	const struct port_info *pi = netdev_priv(dev);
+	netdev_features_t changed;
 	int err;
 
+	netdev_features_xor(changed, dev->features, features);
 	if (!(changed & NETIF_F_HW_VLAN_CTAG_RX))
 		return 0;
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 63fdfe40b813..64de70b13ded 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -1193,8 +1193,9 @@ 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_features_xor(changed, dev->features, features);
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		t4vf_set_rxmode(pi->adapter, pi->viid, -1, -1, -1, -1,
 				features & NETIF_F_HW_VLAN_CTAG_TX, 0);
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index f16bb16bf892..f859ea1e8fdb 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -587,9 +587,10 @@ 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;
 	unsigned long flags;
 
+	netdev_features_xor(changed, dev->features, features);
 	if (!(changed & NETIF_F_RXCSUM))
 		return 0;
 
diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index 555ccc62d6d5..4d1dc4c82541 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -1056,10 +1056,11 @@ static int tsnep_netdev_set_features(struct net_device *netdev,
 				     netdev_features_t features)
 {
 	struct tsnep_adapter *adapter = netdev_priv(netdev);
-	netdev_features_t changed = netdev->features ^ features;
+	netdev_features_t changed;
 	bool enable;
 	int retval = 0;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if (changed & NETIF_F_LOOPBACK) {
 		enable = !!(features & NETIF_F_LOOPBACK);
 		retval = tsnep_phy_loopback(adapter, enable);
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 0a8c6bcff3fb..0ba3df97b8c8 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1597,11 +1597,12 @@ 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;
 
 	if (!netif_running(netdev))
 		return 0;
 
+	netdev_features_xor(changed, netdev->features, features);
 	/* Update the vlan filtering bit */
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
 		u32 maccr;
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 51a5105da784..ebba24e81ff9 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -2422,10 +2422,11 @@ 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;
 	bool enable;
 	int err;
 
+	netdev_features_xor(changed, net_dev->features, features);
 	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
 		enable = !!(features & NETIF_F_HW_VLAN_CTAG_FILTER);
 		err = dpaa2_eth_set_rx_vlan_filtering(priv, enable);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 4470a4a3e4c3..171c13c01658 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2644,9 +2644,10 @@ 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;
 	int err = 0;
 
+	netdev_features_xor(changed, ndev->features, features);
 	if (changed & NETIF_F_RXHASH)
 		enetc_set_rss(ndev, !!(features & NETIF_F_RXHASH));
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 726f73bb3653..6cac44808e60 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -708,9 +708,10 @@ 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;
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, ndev->features, features);
 	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
 		struct enetc_pf *pf = enetc_si_priv(priv->si);
 
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 5bd71fb7ea80..6a1513c91e77 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3450,8 +3450,9 @@ 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_features_xor(changed, netdev->features, features);
 	netdev->features = features;
 
 	/* Receive checksum has been changed */
@@ -3467,8 +3468,9 @@ 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_features_xor(changed, netdev->features, features);
 	if (netif_running(netdev) && changed & NETIF_F_RXCSUM) {
 		napi_disable(&fep->napi);
 		netif_tx_lock_bh(netdev);
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index e7384570b535..6bb30e21d8db 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_feature_helpers.h>
 #include <linux/etherdevice.h>
 #include <linux/net_tstamp.h>
 #include <linux/skbuff.h>
@@ -507,10 +508,11 @@ 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;
 	struct gfar_private *priv = netdev_priv(dev);
+	netdev_features_t changed;
 	int err = 0;
 
+	netdev_features_xor(changed, dev->features, features);
 	if (!(changed & netdev_ctag_vlan_offload_features) &&
 	    !(changed & NETIF_F_RXCSUM))
 		return 0;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index bf7bafd465b4..31d8da9aeb5f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2405,12 +2405,13 @@ static int hns3_nic_do_ioctl(struct net_device *netdev,
 static int hns3_nic_set_features(struct net_device *netdev,
 				 netdev_features_t features)
 {
-	netdev_features_t changed = netdev->features ^ features;
 	struct hns3_nic_priv *priv = netdev_priv(netdev);
 	struct hnae3_handle *h = priv->ae_handle;
+	netdev_features_t changed;
 	bool enable;
 	int ret;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if (changed & NETIF_F_GRO_HW && h->ae_algo->ops->set_gro_en) {
 		enable = !!(features & NETIF_F_GRO_HW);
 		ret = h->ae_algo->ops->set_gro_en(h, enable);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index dc1f7c6d8049..d04e95313da7 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -1061,12 +1061,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;
 	u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
 	netdev_features_t failed_features;
+	netdev_features_t changed;
 	int ret = 0;
 	int err = 0;
 
+	if (force_change)
+		netdev_features_fill(changed);
+	else
+		netdev_features_xor(changed, pre_features, features);
+
 	netdev_features_zero(failed_features);
 	if (changed & NETIF_F_TSO) {
 		ret = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ?
@@ -1109,7 +1114,8 @@ static int set_features(struct hinic_dev *nic_dev,
 	}
 
 	if (err) {
-		nic_dev->netdev->features = features ^ failed_features;
+		netdev_active_features_xor(nic_dev->netdev, features,
+					   failed_features);
 		return -EIO;
 	}
 
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 32e09372fe0d..23bc8c228ce8 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4899,7 +4899,8 @@ 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;
+		netdev_features_xor(tmp, old_hw_features,
+				    adapter->netdev->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 802016d61d54..a715fcb2b3f2 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2804,8 +2804,9 @@ 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_features_xor(changed, netdev->features, 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 0021ff6ea0a0..f3d8c71354e5 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -805,8 +805,9 @@ 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_features_xor(changed, netdev->features, 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 7bbab2dca5c0..f7c201d06e54 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -7316,9 +7316,10 @@ 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;
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if (changed & netdev_general_tso_features)
 		adapter->flags |= FLAG_TSO_FORCE;
 
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 0a4ffc45cc70..6e4dd1aae6d5 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5964,7 +5964,8 @@ 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;
+	netdev_features_xor(diff, current_vlan_features,
+			    requested_vlan_features);
 	if (diff) {
 		if ((features & NETIF_F_RXFCS) &&
 		    (features & NETIF_VLAN_STRIPPING_FEATURES)) {
@@ -5981,7 +5982,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;
-	diff = current_vlan_features ^ requested_vlan_features;
+	netdev_features_xor(diff, current_vlan_features,
+			    requested_vlan_features);
 	if (diff) {
 		err = ice_set_vlan_filtering_features(vsi, features);
 		if (err)
@@ -6025,10 +6027,10 @@ 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;
 	struct ice_netdev_priv *np = netdev_priv(netdev);
 	struct ice_vsi *vsi = np->vsi;
 	struct ice_pf *pf = vsi->back;
+	netdev_features_t changed;
 	int ret = 0;
 
 	/* Don't set any netdev advanced features with device in Safe Mode */
@@ -6045,6 +6047,8 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
 		return -EBUSY;
 	}
 
+	netdev_features_xor(changed, netdev->features, features);
+
 	/* Multiple features can be changed in one call so keep features in
 	 * separate if/else statements to guarantee each feature is checked
 	 */
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 8596c3e925a3..2a03b70bac35 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2449,9 +2449,10 @@ 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;
 	struct igb_adapter *adapter = netdev_priv(netdev);
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		igb_vlan_mode(netdev, features);
 
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index fd1db5a1f12d..781555d4d9a7 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4989,9 +4989,10 @@ 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;
 	struct igc_adapter *adapter = netdev_priv(netdev);
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
 		igc_vlan_mode(netdev, features);
 
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 5d72dcf1dcb3..0b324849ccd0 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -311,8 +311,9 @@ 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_features_xor(changed, netdev->features, 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 6f908468fdeb..288384161dac 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9871,9 +9871,11 @@ 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;
 	bool need_reset = false;
 
+	netdev_features_xor(changed, netdev->features, features);
+
 	/* Make sure RSC matches LRO, reset if change */
 	if (!(features & NETIF_F_LRO)) {
 		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 369aa0a80212..1c73afaeed86 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -5279,9 +5279,10 @@ 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;
 	struct mvpp2_port *port = netdev_priv(dev);
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, dev->features, features);
 	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
 		if (features & NETIF_F_HW_VLAN_CTAG_FILTER) {
 			mvpp2_prs_vid_enable_filtering(port);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index cb0102417a68..eb95fbb32b6d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -1769,11 +1769,12 @@ 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;
 	struct otx2_nic *pfvf = netdev_priv(netdev);
 	bool ntuple = !!(features & NETIF_F_NTUPLE);
 	bool tc = !!(features & NETIF_F_HW_TC);
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if ((changed & NETIF_F_NTUPLE) && !ntuple)
 		otx2_destroy_ntuple_flows(pfvf);
 
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index f2a975e2a75a..f3cdef7edff4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1933,9 +1933,10 @@ 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;
 	struct otx2_nic *pf = netdev_priv(netdev);
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if ((changed & NETIF_F_LOOPBACK) && netif_running(netdev))
 		return otx2_cgx_config_loopback(pf,
 						features & NETIF_F_LOOPBACK);
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 0e2908c8f8b2..c601bbf8eeb7 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4335,8 +4335,9 @@ 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_features_xor(changed, dev->features, features);
 	if ((changed & NETIF_F_RXCSUM) &&
 	    !(sky2->hw->flags & SKY2_HW_NEW_LE)) {
 		sky2_write32(sky2->hw,
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 50cebfe2a426..6f8564886a55 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2716,9 +2716,11 @@ static netdev_features_t mtk_fix_features(struct net_device *dev,
 
 static int mtk_set_features(struct net_device *dev, netdev_features_t features)
 {
+	netdev_features_t changed;
 	int err = 0;
 
-	if (!((dev->features ^ features) & NETIF_F_LRO))
+	netdev_features_xor(changed, dev->features, features);
+	if (!(changed & 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 70ac775a53e6..a67b7be0e500 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3842,10 +3842,11 @@ 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;
 	bool enable = netdev_feature_test(feature_bit, *features);
+	netdev_features_t changes;
 	int err;
 
+	netdev_features_xor(changes, netdev->features, *features);
 	if (!netdev_feature_test(feature_bit, changes))
 		return 0;
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 702edcfa25a3..9b1934a897e0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1220,10 +1220,11 @@ 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;
 	bool enable = netdev_feature_test(feature_bit, wanted_features);
+	netdev_features_t changes;
 	int err;
 
+	netdev_features_xor(changes, dev->features, wanted_features);
 	if (!netdev_feature_test(feature_bit, changes))
 		return 0;
 
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index afa7fe88bb73..254958b08505 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -859,11 +859,12 @@ 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;
 	struct ocelot_port_private *priv = netdev_priv(dev);
 	struct ocelot *ocelot = priv->port.ocelot;
 	int port = priv->port.index;
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, dev->features, features);
 	if ((dev->features & NETIF_F_HW_TC) && !(features & NETIF_F_HW_TC) &&
 	    priv->tc.offload_cnt) {
 		netdev_err(dev,
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index dbc46e260969..c6002fe4d2d3 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -6571,8 +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;
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, dev->features, 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 943598704e9a..7af1dd2709ac 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1666,8 +1666,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;
 	struct nfp_net *nn = netdev_priv(netdev);
+	netdev_features_t changed;
 	u32 new_ctrl;
 	int err;
 
@@ -1675,6 +1675,7 @@ static int nfp_net_set_features(struct net_device *netdev,
 
 	new_ctrl = nn->dp.ctrl;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if (changed & NETIF_F_RXCSUM) {
 		if (features & NETIF_F_RXCSUM)
 			new_ctrl |= nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY;
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index acf3b88f9edb..528bcedda177 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4962,9 +4962,10 @@ 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;
 	int retval;
 
+	netdev_features_xor(changed, dev->features, features);
 	if ((changed & NETIF_F_LOOPBACK) && netif_running(dev)) {
 		retval = nv_set_loopback(dev, features);
 		if (retval != 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 ab519deead53..0062c75e7d84 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,8 +2206,9 @@ 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_features_xor(changed, netdev->features, 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 99d8e3c17510..1d34037c9bc8 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;
+	netdev_features_xor(changed, dev->features, 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 53565295b73c..a3635890a0e2 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -925,9 +925,10 @@ 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;
 	bool need_reload = false;
 
+	netdev_features_xor(changes, dev->features, features);
 	if (changes & NETIF_F_GRO_HW)
 		need_reload = true;
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index e2b74569ae82..abfe0de86ff9 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1070,7 +1070,8 @@ 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;
+			netdev_features_xor(changed, netdev->features,
+					    features);
 			netdev_features_zero(changeable);
 			netdev_features_set_set(changeable,
 						NETIF_F_RXCSUM_BIT,
@@ -1079,7 +1080,7 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 						NETIF_F_TSO_BIT,
 						NETIF_F_TSO6_BIT);
 			changed &= changeable;
-			features ^= changed;
+			netdev_features_toggle(features, changed);
 		}
 	}
 
@@ -1093,9 +1094,10 @@ 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;
 	int hw_lro = (features & NETIF_F_LRO) ? QLCNIC_LRO_ENABLED : 0;
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if (!(changed & NETIF_F_LRO))
 		return 0;
 
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index e79187d50c20..de4803b911cd 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -176,9 +176,10 @@ 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;
 	struct emac_adapter *adpt = netdev_priv(netdev);
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, netdev->features, features);
 	/* We only need to reprogram the hardware if the VLAN tag features
 	 * have changed, and if it's already running.
 	 */
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 7d97b3e012e5..eb0fec232e04 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);
+	netdev_features_t changed;
 	unsigned long flags;
 
+	netdev_features_xor(changed, dev->features, features);
 	if (!(changed & NETIF_F_RXCSUM))
 		return 0;
 
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 702b4b111729..e90df0de255e 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -902,9 +902,10 @@ 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;
 	void __iomem *ioaddr = tp->mmio_addr;
 
+	netdev_features_xor(changed, dev->features, features);
 	if (!(changed & NETIF_F_RXALL))
 		return 0;
 
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index d7ca2bf7cf3b..d7d6f2798d88 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -2336,8 +2336,9 @@ 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_features_xor(changed, ndev->features, 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 72aa825bfc03..b01318964100 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2932,9 +2932,10 @@ 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;
 	struct sh_eth_private *mdp = netdev_priv(ndev);
+	netdev_features_t changed;
 
+	netdev_features_xor(changed, ndev->features, features);
 	if (changed & NETIF_F_RXCSUM && mdp->cd->rx_csum)
 		sh_eth_set_rx_csum(ndev, features & NETIF_F_RXCSUM);
 
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 624079763107..97f884c1993b 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -1779,8 +1779,9 @@ 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_features_xor(changed, dev->features, features);
 	if (changed & NETIF_F_RXCSUM) {
 		if (features & NETIF_F_RXCSUM) {
 			priv->hw->mac->enable_rx_csum(priv->ioaddr);
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index 9fcad774a052..3d57a23022b7 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;
+	netdev_features_xor(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
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c
index 016c459a3cfd..854e1bca7ac9 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;
+	netdev_features_xor(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.
diff --git a/drivers/net/ethernet/sfc/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 808104cf5220..2693b2386916 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;
+	netdev_features_xor(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/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 6c39c7def645..e9d8ffa45703 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1922,16 +1922,17 @@ 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;
 	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);
 	struct ndis_offload_params offloads;
+	netdev_features_t change;
 	int ret = 0;
 
 	if (!nvdev || nvdev->destroy)
 		return -ENODEV;
 
+	netdev_features_xor(change, ndev->features, features);
 	if (!(change & NETIF_F_LRO))
 		goto syncvf;
 
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index bf6d429b31f2..134de64d4be7 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -593,10 +593,11 @@ 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;
 	u16 reg16 = 0;
 	u8 reg8 = 0;
 
+	netdev_features_xor(changed, net->features, features);
 	if (changed & NETIF_F_IP_CSUM) {
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
 		reg8 ^= SFR_TXCOE_TCP | SFR_TXCOE_UDP;
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 88a57c8ad62f..755d99e1815a 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -898,8 +898,9 @@ 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_features_xor(changed, net->features, features);
 	if (changed & NETIF_F_IP_CSUM) {
 		ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
 		tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP;
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 510531a79221..ba71a6d9a9da 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -3255,14 +3255,16 @@ 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;
 	struct r8152 *tp = netdev_priv(dev);
+	netdev_features_t changed;
 	int ret;
 
 	ret = usb_autopm_get_interface(tp->intf);
 	if (ret < 0)
 		goto out;
 
+	netdev_features_xor(changed, dev->features, features);
+
 	mutex_lock(&tp->control);
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index cde2f29ce9a6..1b6d33903a47 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1471,10 +1471,11 @@ 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;
 	struct veth_priv *priv = netdev_priv(dev);
+	netdev_features_t changed;
 	int err;
 
+	netdev_features_xor(changed, dev->features, features);
 	if (!(changed & NETIF_F_GRO) || !(dev->flags & IFF_UP) || priv->_xdp_prog)
 		return 0;
 
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 4900ab1bdea6..ad16d382af9c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3212,10 +3212,12 @@ static int virtnet_set_features(struct net_device *dev,
 				netdev_features_t features)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
+	netdev_features_t changed;
 	u64 offloads;
 	int err;
 
-	if ((dev->features ^ features) & NETIF_F_GRO_HW) {
+	netdev_features_xor(changed, dev->features, features);
+	if (changed & NETIF_F_GRO_HW) {
 		if (vi->xdp_enabled)
 			return -EBUSY;
 
@@ -3231,7 +3233,7 @@ static int virtnet_set_features(struct net_device *dev,
 		vi->guest_offloads = offloads;
 	}
 
-	if ((dev->features ^ features) & NETIF_F_RXHASH) {
+	if (changed & 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 d9be2fc80de2..8d664a9e4bd9 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -411,8 +411,8 @@ 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;
+	netdev_features_t changed;
 	u8 udp_tun_enabled;
 
 	netdev_features_zero(tun_offload_mask);
@@ -420,6 +420,7 @@ 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;
 
+	netdev_features_xor(changed, netdev->features, features);
 	if (changed & NETIF_F_RXCSUM ||
 	    changed & NETIF_F_LRO ||
 	    changed & NETIF_F_HW_VLAN_CTAG_RX ||
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 762968b23edc..6105c02a723b 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6789,12 +6789,15 @@ 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_features_t diff1;
+	netdev_features_t diff2;
 	int rc = 0;
 
 	QETH_CARD_TEXT(card, 2, "setfeat");
 	QETH_CARD_HEX(card, 2, &features, sizeof(features));
 
+	netdev_features_xor(changed, dev->features, features);
 	if ((changed & NETIF_F_IP_CSUM)) {
 		rc = qeth_set_ipa_csum(card, features & NETIF_F_IP_CSUM,
 				       IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV4,
@@ -6827,14 +6830,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);
+	netdev_features_xor(diff1, dev->features, features);
+	netdev_features_xor(diff2, dev->features, changed);
+	qeth_check_restricted_features(card, diff1, diff2);
 
 	/* everything changed successfully? */
-	if ((dev->features ^ features) == changed)
+	if (diff1 == 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 4b248fe59e67..6bcf77c35bab 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -2270,9 +2270,10 @@ 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;
 	int err;
 
+	netdev_features_xor(changed, ndev->features, features);
 	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
 		/* Update the behavior of vlan accel in the adapter */
 		err = qlge_update_hw_vlan_features(ndev, features);
diff --git a/net/core/dev.c b/net/core/dev.c
index fb32cd8e8c3e..528c7da47a44 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9761,8 +9761,9 @@ int __netdev_update_features(struct net_device *dev)
 		netdev_sync_lower_features(dev, lower, features);
 
 	if (!err) {
-		netdev_features_t diff = features ^ dev->features;
+		netdev_features_t diff;
 
+		netdev_features_xor(diff, dev->features, features);
 		if (diff & NETIF_F_RX_UDP_TUNNEL_PORT) {
 			/* udp_tunnel_{get,drop}_rx_info both need
 			 * NETIF_F_RX_UDP_TUNNEL_PORT enabled on the
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 21045ba78350..595b8dae7fa3 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -162,7 +162,8 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 	netdev_wanted_features_set(dev, tmp);
 	__netdev_update_features(dev);
 
-	tmp = dev->wanted_features ^ dev->features;
+	netdev_features_xor(tmp, dev->wanted_features, dev->features);
+
 	if (tmp & valid)
 		ret |= ETHTOOL_F_WISH;
 
@@ -355,7 +356,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
 				NETIF_F_NTUPLE_BIT, NETIF_F_RXHASH_BIT);
 
 	/* allow changing only bits set in hw_features */
-	changed = dev->features ^ features;
+	netdev_features_xor(changed, dev->features, features);
 	changed &= eth_all_features;
 	netdev_features_andnot(tmp, changed, dev->hw_features);
 	if (tmp)
-- 
2.33.0


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

* [RFCv8 PATCH net-next 30/55] treewide: use netdev_feature_test helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (28 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 29/55] treewide: use netdev_features_xor/toggle helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 31/55] treewide: use netdev_features_intersects helpers Jian Shen
                   ` (26 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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      | 38 ++++----
 .../net/ethernet/apm/xgene/xgene_enet_main.c  |  6 +-
 .../ethernet/aquantia/atlantic/aq_filters.c   |  8 +-
 .../net/ethernet/aquantia/atlantic/aq_main.c  | 25 ++---
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |  6 +-
 .../net/ethernet/aquantia/atlantic/aq_ring.c  |  2 +-
 .../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          | 17 ++--
 .../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   | 65 +++++++------
 .../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   | 16 ++--
 drivers/net/ethernet/chelsio/cxgb3/sge.c      |  8 +-
 .../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   |  6 +-
 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/engleder/tsnep_main.c    |  4 +-
 drivers/net/ethernet/faraday/ftgmac100.c      | 10 +-
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  4 +-
 .../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   | 21 +++--
 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_lib.c      |  5 +-
 drivers/net/ethernet/intel/ice/ice_main.c     | 57 +++++++-----
 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 | 46 ++++-----
 .../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   | 20 ++--
 .../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 +-
 .../ethernet/mellanox/mlx5/core/en_ethtool.c  |  2 +-
 .../net/ethernet/mellanox/mlx5/core/en_fs.c   |  5 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 30 +++---
 .../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 |  6 +-
 drivers/net/ethernet/micrel/ksz884x.c         |  2 +-
 drivers/net/ethernet/microchip/lan743x_main.c |  5 +-
 .../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       | 26 +++---
 .../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  | 10 +-
 .../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_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         |  7 +-
 drivers/net/ethernet/sfc/falcon/rx.c          |  4 +-
 drivers/net/ethernet/sfc/mcdi_filters.c       |  8 +-
 drivers/net/ethernet/sfc/mcdi_port_common.c   |  2 +-
 drivers/net/ethernet/sfc/rx.c                 |  2 +-
 drivers/net/ethernet/sfc/rx_common.c          |  4 +-
 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                      | 12 +--
 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_feature_helpers.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                                | 93 ++++++++++---------
 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                          | 20 ++--
 net/ipv4/tcp.c                                |  8 +-
 net/ipv4/udp_offload.c                        | 10 +-
 net/ipv6/esp6_offload.c                       |  6 +-
 net/ipv6/ip6_output.c                         | 16 ++--
 net/netfilter/ipvs/ip_vs_proto_sctp.c         |  3 +-
 net/nsh/nsh.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                        |  4 +-
 245 files changed, 1156 insertions(+), 1044 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 9920c4cb8aa3..4ac7af5a635d 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 ed25061fac62..2c631c7d6b13 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 b8f8ba623c9e..6db8d834c3e4 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1813,7 +1813,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,
@@ -1826,7 +1826,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
@@ -2121,7 +2121,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,
@@ -2423,8 +2423,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 66eb2d9fe576..acd2a729be7b 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 ae768c5cdc59..0e424ac95a65 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 379b3d809f9e..100b71152659 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -340,7 +340,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 50470e55cbe5..5d287e960a2a 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..f9664f194a6a 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 93ddf9a66be3..88e09b177c03 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2191,8 +2191,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);
@@ -2206,14 +2206,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,
@@ -2232,31 +2232,33 @@ static int xgbe_set_features(struct net_device *netdev,
 	netdev_features_t 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;
@@ -2598,8 +2600,8 @@ 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) &&
-		    (skb->protocol == htons(ETH_P_8021Q)))
+		if (!netdev_active_feature_test(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
+		    skb->protocol == htons(ETH_P_8021Q))
 			max_len += VLAN_HLEN;
 
 		if (skb->len > max_len) {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index a6709e94f31d..2f03cdebb00d 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 b7867dcd5289..c331631d82c0 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -162,8 +162,8 @@ 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;
@@ -173,15 +173,15 @@ static int aq_ndev_set_features(struct net_device *ndev,
 
 	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;
@@ -190,8 +190,9 @@ 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;
@@ -200,7 +201,7 @@ static int aq_ndev_set_features(struct net_device *ndev,
 	}
 
 	netdev_features_xor(changed, aq_nic->ndev->features, features);
-	if (changed & NETIF_F_RXCSUM) {
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		err = aq_nic->aq_hw_ops->hw_set_offload(aq_nic->aq_hw,
 							aq_cfg);
 
@@ -232,12 +233,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);
 	}
@@ -465,7 +466,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 963aa9359257..bc9649ea37e9 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..2e8255586e93 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
@@ -369,7 +369,7 @@ 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_active_feature_test(self->aq_nic->ndev, NETIF_F_RXCSUM_BIT))
 		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 8ad92c2f92cb..49e2d061348d 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 db35ffb830de..d780a32ca51d 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 8cffd89c855e..202cc99ac334 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);
@@ -534,7 +534,7 @@ static int atl1c_set_features(struct net_device *netdev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, 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 b1fdc855ae84..ebc1606368d0 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_features_xor(changed, netdev->features, 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 4dde0f0b5620..b43c193dc433 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_features_xor(changed, netdev->features, 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 24679d304234..d840713c8ad8 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_features_xor(changed, netdev->features, 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 784f46970f8b..28190575d0d4 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.
@@ -185,7 +185,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);
 }
 
@@ -1550,7 +1550,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 d1e45b7752d0..59658e99bdc3 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -3259,15 +3259,14 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
 		}
 
 		skb_checksum_none_assert(skb);
-		if ((bp->dev->features & NETIF_F_RXCSUM) &&
-			(status & (L2_FHDR_STATUS_TCP_SEGMENT |
-			L2_FHDR_STATUS_UDP_DATAGRAM))) {
+		if (netdev_active_feature_test(bp->dev, NETIF_F_RXCSUM_BIT) &&
+		    (status & (L2_FHDR_STATUS_TCP_SEGMENT | L2_FHDR_STATUS_UDP_DATAGRAM))) {
 
 			if (likely((status & (L2_FHDR_ERRORS_TCP_XSUM |
 					      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,8 +3586,8 @@ 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) &&
-	     (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
+	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) {
 		/* Promiscuous mode. */
@@ -7754,7 +7753,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 +7762,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 44c4d94ad7e3..1095cfb0783a 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;
@@ -4949,7 +4949,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 5466966a2243..2a3b18665054 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;
 
@@ -13258,7 +13258,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 d1664fdfc980..87d25669c673 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,17 +11176,17 @@ 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) || bp->xdp_prog)
 		netdev_features_clear_set(features, NETIF_F_LRO_BIT,
 					  NETIF_F_GRO_HW_BIT);
 
-	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
@@ -11218,9 +11218,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)
@@ -11229,7 +11229,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;
@@ -13638,7 +13638,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 28b8efe736f5..cd8676723ba1 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -473,7 +473,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 d72dca1bbaf6..711dddfcc1d1 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 720c48bd117f..00f887601a1a 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))
@@ -8282,7 +8282,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;
 
@@ -8320,7 +8320,7 @@ static int tg3_set_features(struct net_device *dev, netdev_features_t features)
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, 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;
@@ -11648,7 +11648,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;
@@ -17746,10 +17746,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 ||
@@ -17910,7 +17910,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),
 		    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 b0f1da5175ca..087aa63598bd 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;
 }
 
@@ -3350,12 +3350,12 @@ static int bnad_set_features(struct net_device *dev, netdev_features_t features)
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, 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 e608f0c41071..31b258a47077 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,
@@ -3748,15 +3749,15 @@ static int macb_set_features(struct net_device *netdev,
 	netdev_features_xor(changed, netdev->features, 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 5405aeb04200..a626fa1d13d4 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);
 
@@ -1495,11 +1495,11 @@ static int xgmac_set_features(struct net_device *dev, netdev_features_t features
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, 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..4353cd50d297 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 182c2b8d8aec..a2e18f493d7e 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2720,30 +2720,35 @@ 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 +2764,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);
 
@@ -3668,7 +3673,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 c9807b759702..51d202c0bf52 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,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, features);
-	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->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);
 
@@ -2190,7 +2195,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 0c1a0eb9d1a6..979a03faca7a 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);
 
@@ -1792,10 +1792,10 @@ static int nicvf_set_features(struct net_device *netdev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, 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 00e2492d944b..30e371efcb77 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);
@@ -884,7 +884,7 @@ static int t1_set_features(struct net_device *dev, netdev_features_t features)
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, features);
-	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;
@@ -1057,7 +1057,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 861edff5ed89..0e1afce8d3a5 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -728,7 +728,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;
@@ -913,7 +913,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);
@@ -937,7 +937,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++;
@@ -1377,7 +1377,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 7c3c4729363a..3b7348ffc71d 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -1184,15 +1184,15 @@ 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 i, have_vlans = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+								 features);
 
 		for_each_port(adapter, i)
-			have_vlans |=
-				adapter->port[i]->features &
-				NETIF_F_HW_VLAN_CTAG_RX;
+			have_vlans |= netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+							  adapter->port[i]->features);
 
 		t3_set_vlan_accel(adapter, 1, have_vlans);
 	}
@@ -2286,7 +2286,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 +2595,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);
@@ -2608,7 +2608,7 @@ static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, 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..45448ff151a1 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,8 +2177,8 @@ 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) &&
-		     cpl->csum_valid && cpl->csum == htons(0xffff)) {
+		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]++;
 		} else
@@ -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 10aa8786c4d3..ec054538e224 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);
@@ -1278,12 +1279,13 @@ static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 	int err;
 
 	netdev_features_xor(changed, dev->features, features);
-	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);
@@ -1464,7 +1466,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",
@@ -3861,7 +3864,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..a33661d36211 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..e47042f56ef0 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 64de70b13ded..1dc39903d87c 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);
@@ -1196,9 +1196,10 @@ static int cxgb4vf_set_features(struct net_device *dev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, 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 1e55b12fee51..5c521ed8175f 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 7e1cca8b787b..9ad7c5b0734a 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1360,7 +1360,7 @@ 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 &&
+		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:
@@ -1403,7 +1403,7 @@ 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 &&
+		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;
@@ -1414,7 +1414,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 96423bf6ed2d..cc3865fb7d83 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -1991,7 +1991,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 f859ea1e8fdb..650c37096cfe 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -591,11 +591,12 @@ static int dm9000_set_features(struct net_device *dev,
 	unsigned long flags;
 
 	netdev_features_xor(changed, dev->features, features);
-	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;
@@ -913,9 +914,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);
@@ -1171,7 +1172,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 fc1345fa42f6..6ea623d6ddf4 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/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index 4d1dc4c82541..1792c85ca043 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -1061,8 +1061,8 @@ static int tsnep_netdev_set_features(struct net_device *netdev,
 	int retval = 0;
 
 	netdev_features_xor(changed, netdev->features, features);
-	if (changed & NETIF_F_LOOPBACK) {
-		enable = !!(features & NETIF_F_LOOPBACK);
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed)) {
+		enable = netdev_feature_test(NETIF_F_LOOPBACK_BIT, features);
 		retval = tsnep_phy_loopback(adapter, enable);
 	}
 
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 0ba3df97b8c8..1b6fcc214160 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,
 
 	netdev_features_xor(changed, netdev->features, features);
 	/* 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 abfe54500719..546002f864d0 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -1735,7 +1735,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;
 
@@ -2734,7 +2734,7 @@ 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 ebba24e81ff9..ec4cfea8b170 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 */
@@ -2427,15 +2427,15 @@ static int dpaa2_eth_set_features(struct net_device *net_dev,
 	int err;
 
 	netdev_features_xor(changed, net_dev->features, features);
-	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;
@@ -4691,7 +4691,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 171c13c01658..f0edb74e509d 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);
@@ -2648,19 +2648,21 @@ int enetc_set_features(struct net_device *ndev,
 	int err = 0;
 
 	netdev_features_xor(changed, ndev->features, features);
-	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 6cac44808e60..c181e3db7962 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -712,17 +712,18 @@ static int enetc_pf_set_features(struct net_device *ndev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, ndev->features, features);
-	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 6a1513c91e77..cdffbf75e9ca 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1632,7 +1632,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 */
@@ -3456,8 +3456,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;
@@ -3471,7 +3471,7 @@ static int fec_set_features(struct net_device *netdev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, 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 7a4de2bd3418..62b5df3e3fda 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));
@@ -3265,7 +3265,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 6bb30e21d8db..2b8ecdab0f53 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -514,7 +514,7 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features)
 
 	netdev_features_xor(changed, dev->features, features);
 	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 f8a2f206d5c1..9e5a28b8ddc4 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 bfc1d0a173af..d86b6004580a 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 6c4a37fae478..d47e01652a91 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 31d8da9aeb5f..b098d070deef 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,
 	int ret;
 
 	netdev_features_xor(changed, netdev->features, features);
-	if (changed & NETIF_F_GRO_HW && h->ae_algo->ops->set_gro_en) {
-		enable = !!(features & NETIF_F_GRO_HW);
+	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, changed) &&
+	    h->ae_algo->ops->set_gro_en) {
+		enable = netdev_feature_test(NETIF_F_GRO_HW_BIT, features);
 		ret = h->ae_algo->ops->set_gro_en(h, enable);
 		if (ret)
 			return ret;
 	}
 
-	if ((changed & NETIF_F_HW_VLAN_CTAG_RX) &&
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed) &&
 	    h->ae_algo->ops->enable_hw_strip_rxvtag) {
-		enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX);
+		enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
+					     features);
 		ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, enable);
 		if (ret)
 			return ret;
 	}
 
-	if ((changed & NETIF_F_NTUPLE) && h->ae_algo->ops->enable_fd) {
-		enable = !!(features & NETIF_F_NTUPLE);
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed) &&
+	    h->ae_algo->ops->enable_fd) {
+		enable = netdev_feature_test(NETIF_F_NTUPLE_BIT, features);
 		h->ae_algo->ops->enable_fd(h, enable);
 	}
 
-	if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
+	if (netdev_active_feature_test(netdev, NETIF_F_HW_TC_BIT) &&
+	    !netdev_feature_test(NETIF_F_HW_TC_BIT, features) &&
 	    h->ae_algo->ops->cls_flower_active(h)) {
 		netdev_err(netdev,
 			   "there are offloaded TC filters active, cannot disable HW TC offload");
 		return -EINVAL;
 	}
 
-	if ((changed & NETIF_F_HW_VLAN_CTAG_FILTER) &&
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed) &&
 	    h->ae_algo->ops->enable_vlan_filter) {
-		enable = !!(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+		enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+					     features);
 		ret = h->ae_algo->ops->enable_vlan_filter(h, enable);
 		if (ret)
 			return ret;
@@ -3938,7 +3944,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))
@@ -4229,7 +4235,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 45cd19ef3c5b..6efae0ac751e 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 d04e95313da7..59475894676e 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);
 	}
@@ -1073,8 +1073,9 @@ static int set_features(struct hinic_dev *nic_dev,
 		netdev_features_xor(changed, pre_features, features);
 
 	netdev_features_zero(failed_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;
@@ -1082,7 +1083,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;
@@ -1091,9 +1092,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) {
@@ -1102,10 +1103,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 e5828a658caf..9d1cebbeffec 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 99f76b0c3031..d524d76a09eb 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 a715fcb2b3f2..636c386d6761 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++;
@@ -2807,7 +2807,8 @@ static int e100_set_features(struct net_device *netdev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, 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 f3d8c71354e5..a1a0cdb3cf2e 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);
@@ -808,14 +808,15 @@ static int e1000_set_features(struct net_device *netdev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, 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);
@@ -1831,7 +1832,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
 		 */
@@ -4187,7 +4188,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
@@ -4238,7 +4239,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);
@@ -4284,7 +4286,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++;
 
@@ -4439,7 +4441,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);
@@ -4451,7 +4453,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
 			 */
@@ -4899,7 +4901,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 f7c201d06e54..60b545597f01 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);
@@ -7331,8 +7331,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 30ab7f26b72d..0f2cfb6e9ce9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -3235,7 +3235,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);
@@ -12853,7 +12853,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;
@@ -12922,25 +12922,28 @@ 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 69e67eb6aea7..da6f09f89412 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 03f1dd9d296d..e3dd3d359245 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2649,7 +2649,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);
@@ -4826,17 +4826,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_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index d126f4cb3ba8..bdd2157d2f25 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -3296,8 +3296,9 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
 
 		/* disable or enable CRC stripping */
 		if (vsi->netdev)
-			ice_vsi_cfg_crc_strip(vsi, !!(vsi->netdev->features &
-					      NETIF_F_RXFCS));
+			ice_vsi_cfg_crc_strip(vsi,
+					      netdev_active_feature_test(vsi->netdev,
+									 NETIF_F_RXFCS_BIT));
 
 		break;
 	case ICE_VSI_VF:
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 6e4dd1aae6d5..8e36b4d799c3 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -435,8 +435,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);
 			}
 		}
@@ -5821,12 +5821,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)) {
@@ -5848,10 +5852,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);
 		}
@@ -5864,8 +5868,8 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 				      netdev_stag_vlan_offload_features);
 	}
 
-	if (!(netdev->features & NETIF_F_RXFCS) &&
-	    (features & NETIF_F_RXFCS) &&
+	if (!netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT) &&
+	    netdev_feature_test(NETIF_F_RXFCS_BIT, features) &&
 	    (features & NETIF_VLAN_STRIPPING_FEATURES) &&
 	    !ice_vsi_has_non_zero_vlans(np->vsi)) {
 		netdev_warn(netdev, "Disabling VLAN stripping as FCS/CRC stripping is also disabled and there is no VLAN configured\n");
@@ -5967,7 +5971,7 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 	netdev_features_xor(diff, current_vlan_features,
 			    requested_vlan_features);
 	if (diff) {
-		if ((features & NETIF_F_RXFCS) &&
+		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features) &&
 		    (features & NETIF_VLAN_STRIPPING_FEATURES)) {
 			dev_err(ice_pf_to_dev(vsi->back),
 				"To enable VLAN stripping, you must first enable FCS/CRC stripping\n");
@@ -6052,8 +6056,9 @@ 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)
@@ -6062,42 +6067,44 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
 	/* Turn on receive of FCS aka CRC, and after setting this
 	 * flag the packet data will have the 4 byte CRC appended
 	 */
-	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) &&
 		    (features & NETIF_VLAN_STRIPPING_FEATURES)) {
 			dev_err(ice_pf_to_dev(vsi->back),
 				"To disable FCS/CRC stripping, you must first disable VLAN stripping\n");
 			return -EIO;
 		}
 
-		ice_vsi_cfg_crc_strip(vsi, !!(features & NETIF_F_RXFCS));
+		ice_vsi_cfg_crc_strip(vsi,
+				      netdev_feature_test(NETIF_F_RXFCS_BIT, features));
 		ret = ice_down_up(vsi);
 		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;
 }
@@ -8331,7 +8338,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);
@@ -8611,7 +8618,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 42df686e0215..f8bd43b70542 100644
--- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
@@ -1672,7 +1672,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 e5f3e7680dc6..a0e93dbbdd57 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 2a03b70bac35..01af57d888c3 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,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, features);
-	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;
 
@@ -2538,7 +2539,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;
@@ -4568,7 +4569,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
 		 */
@@ -5077,7 +5078,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:
@@ -5249,7 +5250,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;
@@ -8615,7 +8616,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 */
@@ -8648,7 +8649,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);
@@ -8706,7 +8707,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;
 		}
@@ -8743,7 +8744,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;
 
@@ -9167,7 +9168,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 edf03bfe8914..00cdc7432d85 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;
@@ -2650,7 +2650,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..6d7ac6cfa1ac 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 781555d4d9a7..67849c8d1877 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;
 		}
@@ -4978,7 +4978,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);
@@ -4993,14 +4993,15 @@ static int igc_set_features(struct net_device *netdev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, features);
-	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;
@@ -5044,7 +5045,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 0b324849ccd0..0caf35886a95 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;
@@ -314,10 +314,11 @@ ixgb_set_features(struct net_device *netdev, netdev_features_t features)
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, 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);
@@ -1097,7 +1098,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 e88e3dfac8c2..0c0a9dc8b6d6 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -2394,7 +2394,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 00f4e95fcd31..98da6d4d5ba0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -645,7 +645,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 288384161dac..f3b1d4777c3f 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);
 	}
@@ -9877,7 +9877,7 @@ static int ixgbe_set_features(struct net_device *netdev,
 	netdev_features_xor(changed, netdev->features, features);
 
 	/* 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;
@@ -9887,7 +9887,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");
 		}
@@ -9897,7 +9898,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;
@@ -9924,17 +9926,17 @@ 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;
@@ -10252,7 +10254,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 ae7ec049e020..88f98ac608a2 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 124d2396a2ba..50b920ae83e1 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;
 		}
@@ -4431,7 +4431,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 13d0de32c6f7..8a9918e34249 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 0f8e364522e8..b66895090e87 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 08297329cc9c..bf6b662c2c91 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 1c73afaeed86..054946f8fa6e 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);
@@ -5283,8 +5283,8 @@ static int mvpp2_set_features(struct net_device *dev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, features);
-	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
@@ -5296,8 +5296,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 eb95fbb32b6d..a77a0ebb0286 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -1770,15 +1770,15 @@ EXPORT_SYMBOL(otx2_get_max_mtu);
 int otx2_handle_ntuple_tc_features(struct net_device *netdev, netdev_features_t 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);
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, 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");
@@ -1786,7 +1786,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");
@@ -1794,21 +1794,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 5bd16e95370b..1aed3e03afba 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 f3cdef7edff4..c500f6f44569 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1908,7 +1908,7 @@ static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
 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);
@@ -1937,13 +1937,17 @@ static int otx2_set_features(struct net_device *netdev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, features);
-	if ((changed & NETIF_F_LOOPBACK) && netif_running(netdev))
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed) &&
+	    netif_running(netdev))
 		return otx2_cgx_config_loopback(pf,
-						features & NETIF_F_LOOPBACK);
+						netdev_feature_test(NETIF_F_LOOPBACK_BIT,
+								    features));
 
-	if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && netif_running(netdev))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed) &&
+	    netif_running(netdev))
 		return otx2_enable_rxvlan(pf,
-					  features & NETIF_F_HW_VLAN_CTAG_RX);
+					  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 2a761f09d267..09845ffe3d80 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 c601bbf8eeb7..077c8ab05eb1 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);
 	}
@@ -4338,15 +4338,15 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features)
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, 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 6f8564886a55..5c76433a70ab 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1921,7 +1921,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 		if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
 			mtk_ppe_check_skb(eth->ppe, skb, hash);
 
-		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,
@@ -2700,7 +2700,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);
 
@@ -2720,10 +2720,10 @@ static int mtk_set_features(struct net_device *dev, netdev_features_t features)
 	int err = 0;
 
 	netdev_features_xor(changed, dev->features, features);
-	if (!(changed & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, changed))
 		return 0;
 
-	if (!(features & NETIF_F_LRO))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, features))
 		mtk_hwlro_netdev_disable(dev);
 
 	return err;
@@ -3708,13 +3708,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;
@@ -3722,11 +3722,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;
@@ -3743,11 +3743,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 7d45f1d55f79..788ec4986217 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 ff4395638546..bc4b88cc81e3 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 36a1d28998b3..a7e3ec4f034d 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);
 	}
 
@@ -3519,7 +3519,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;
@@ -3546,7 +3546,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
@@ -3556,7 +3556,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
@@ -3565,7 +3565,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);
@@ -3576,7 +3576,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..193bfc0e17b2 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..266f119a93c4 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 90268776942d..08d556f8fef3 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->fs);
 		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->fs);
 
 	destroy_workqueue(priv->tls->rx_wq);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 29ed20abc3da..adeea7a0bd78 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -493,7 +493,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->fs);
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
index 7cf11c1b93a2..d043952123a6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -1308,7 +1308,7 @@ int mlx5e_create_flow_steering(struct mlx5e_flow_steering *fs,
 
 	mlx5e_fs_set_ns(fs, ns, false);
 	err = mlx5e_arfs_create_tables(fs, rx_res,
-				       !!(netdev->hw_features & NETIF_F_NTUPLE));
+				       netdev_hw_feature_test(netdev, NETIF_F_NTUPLE_BIT));
 	if (err) {
 		fs_err(fs, "Failed to create arfs tables, err=%d\n", err);
 		netdev_hw_feature_del(netdev, NETIF_F_NTUPLE_BIT);
@@ -1355,7 +1355,8 @@ int mlx5e_create_flow_steering(struct mlx5e_flow_steering *fs,
 err_destroy_inner_ttc_table:
 	mlx5e_destroy_inner_ttc_table(fs);
 err_destroy_arfs_tables:
-	mlx5e_arfs_destroy_tables(fs, !!(netdev->hw_features & NETIF_F_NTUPLE));
+	mlx5e_arfs_destroy_tables(fs,
+				  netdev_hw_feature_test(netdev, NETIF_F_NTUPLE_BIT));
 
 	return err;
 }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index a67b7be0e500..411cba30ebb6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3896,19 +3896,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;
@@ -3935,34 +3935,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);
@@ -3971,10 +3971,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);
 		}
@@ -5140,7 +5140,8 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
 err_tc_nic_cleanup:
 	mlx5e_tc_nic_cleanup(priv);
 err_destroy_flow_steering:
-	mlx5e_destroy_flow_steering(priv->fs, !!(priv->netdev->hw_features & NETIF_F_NTUPLE),
+	mlx5e_destroy_flow_steering(priv->fs,
+				    netdev_hw_feature_test(priv->netdev, NETIF_F_NTUPLE_BIT),
 				    priv->profile);
 err_destroy_rx_res:
 	mlx5e_rx_res_destroy(priv->rx_res);
@@ -5157,7 +5158,8 @@ static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv)
 {
 	mlx5e_accel_cleanup_rx(priv);
 	mlx5e_tc_nic_cleanup(priv);
-	mlx5e_destroy_flow_steering(priv->fs, !!(priv->netdev->hw_features & NETIF_F_NTUPLE),
+	mlx5e_destroy_flow_steering(priv->fs,
+				    netdev_hw_feature_test(priv->netdev, NETIF_F_NTUPLE_BIT),
 				    priv->profile);
 	mlx5e_rx_res_destroy(priv->rx_res);
 	mlx5e_close_drop_rq(&priv->drop_rq);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 4d3e7897b51b..990c497e17c2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -1344,7 +1344,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) {
@@ -1441,7 +1441,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)) {
@@ -2316,7 +2316,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++;
@@ -2330,7 +2330,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 0872a214d2a3..2a28051d03d7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -4831,7 +4831,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/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
index ac983e9c2b3c..28473094921d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -331,7 +331,7 @@ static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
 
 	mlx5e_fs_set_ns(priv->fs, ns, false);
 	err = mlx5e_arfs_create_tables(priv->fs, priv->rx_res,
-				       !!(priv->netdev->hw_features & NETIF_F_NTUPLE));
+				       netdev_hw_feature_test(priv->netdev, NETIF_F_NTUPLE_BIT));
 	if (err) {
 		netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n",
 			   err);
@@ -351,7 +351,7 @@ static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
 
 err_destroy_arfs_tables:
 	mlx5e_arfs_destroy_tables(priv->fs,
-				  !!(priv->netdev->hw_features & NETIF_F_NTUPLE));
+				  netdev_hw_feature_test(priv->netdev, NETIF_F_NTUPLE_BIT));
 
 	return err;
 }
@@ -360,7 +360,7 @@ static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv)
 {
 	mlx5e_destroy_ttc_table(priv->fs);
 	mlx5e_arfs_destroy_tables(priv->fs,
-				  !!(priv->netdev->hw_features & NETIF_F_NTUPLE));
+				  netdev_hw_feature_test(priv->netdev, NETIF_F_NTUPLE_BIT));
 	mlx5e_ethtool_cleanup_steering(priv->fs);
 }
 
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 91b8f9a15018..50789716b1c7 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/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 934d9e2c4008..594afe94874e 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -1586,7 +1586,7 @@ static void lan743x_rfe_set_multicast(struct lan743x_adapter *adapter)
 			rfctl |= RFE_CTL_AM_;
 	}
 
-	if (netdev->features & NETIF_F_RXCSUM)
+	if (netdev_active_feature_test(netdev, NETIF_F_RXCSUM_BIT))
 		rfctl |= RFE_CTL_IP_COE_ | RFE_CTL_TCP_UDP_COE_;
 
 	memset(hash_table, 0, DP_SEL_VHF_HASH_LEN * sizeof(u32));
@@ -2669,7 +2669,8 @@ static int lan743x_rx_process_buffer(struct lan743x_rx *rx)
 	if (is_last && rx->skb_head) {
 		rx->skb_head->protocol = eth_type_trans(rx->skb_head,
 							rx->adapter->netdev);
-		if (rx->adapter->netdev->features & NETIF_F_RXCSUM) {
+		if (netdev_active_feature_test(rx->adapter->netdev,
+					       NETIF_F_RXCSUM_BIT)) {
 			if (!is_ice && !is_tce && !is_icsm)
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
 		}
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
index 51f8a0816377..23593a7ac617 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
@@ -431,7 +431,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 c4c4c282890e..87e144b8bbc9 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -641,7 +641,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 8f8cc9bd5577..888d494bbeda 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 874fb2a5874e..0828c3d23f82 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1042,7 +1042,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 254958b08505..828fa985f398 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -849,7 +849,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);
@@ -865,14 +865,15 @@ static int ocelot_set_features(struct net_device *dev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, features);
-	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 9f65201a1f70..301edf3f6cc1 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -1285,7 +1285,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) {
@@ -1363,7 +1363,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 0335a389bb01..2f418dc090d9 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 c6002fe4d2d3..951dd5045ecb 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -6574,7 +6574,7 @@ static int s2io_set_features(struct net_device *dev, netdev_features_t features)
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, 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);
@@ -7125,7 +7125,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",
@@ -7159,7 +7159,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 */
@@ -7371,7 +7371,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..2f5a4ec628b1 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..b21e5bbb59f5 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 7af1dd2709ac..0f93a60655cb 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1676,8 +1676,8 @@ static int nfp_net_set_features(struct net_device *netdev,
 	new_ctrl = nn->dp.ctrl;
 
 	netdev_features_xor(changed, netdev->features, 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))
 			new_ctrl |= nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_RXCSUM_ANY;
@@ -1698,38 +1698,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;
@@ -1760,16 +1760,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 528bcedda177..9a76c5919d35 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;
@@ -4966,16 +4966,17 @@ static int nv_set_features(struct net_device *dev, netdev_features_t features)
 	int retval;
 
 	netdev_features_xor(changed, dev->features, features);
-	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;
@@ -5617,7 +5618,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;
@@ -6121,12 +6122,13 @@ 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 0062c75e7d84..452d3fae2f0e 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
@@ -2209,7 +2209,7 @@ static int pch_gbe_set_features(struct net_device *netdev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, 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 7a68744b7011..081c54db89ef 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);
@@ -2046,7 +2046,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);
@@ -3130,7 +3130,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 1d34037c9bc8..2ca440255aa7 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,16 @@ static int netxen_set_features(struct net_device *dev,
 	int hw_lro;
 
 	netdev_features_xor(changed, dev->features, 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
+	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 +1123,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 a3635890a0e2..4fb113d9713e 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;
@@ -929,7 +929,7 @@ int qede_set_features(struct net_device *dev, netdev_features_t features)
 	bool need_reload = false;
 
 	netdev_features_xor(changes, dev->features, features);
-	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 49e2278e3e8a..61cc3fb2e808 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1608,7 +1608,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:
@@ -2791,9 +2791,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 abfe0de86ff9..8228e1d55e38 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1084,7 +1084,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;
@@ -1094,11 +1094,11 @@ 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);
-	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;
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, features);
-	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 590efc540e4f..3115a942a865 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 eb0fec232e04..56c9e0627577 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1466,17 +1466,17 @@ static int cp_set_features(struct net_device *dev, netdev_features_t features)
 	unsigned long flags;
 
 	netdev_features_xor(changed, dev->features, features);
-	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 e90df0de255e..24b30873c38d 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -906,14 +906,14 @@ static int rtl8139_set_features(struct net_device *dev, netdev_features_t featur
 	void __iomem *ioaddr = tp->mmio_addr;
 
 	netdev_features_xor(changed, dev->features, features);
-	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);
@@ -1972,7 +1972,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;
@@ -2013,7 +2013,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))) {
@@ -2584,7 +2584,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 4fe234ef92a0..81d7a4eb2a5a 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1444,13 +1444,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;
@@ -1466,13 +1466,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;
@@ -4432,14 +4432,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 d7d6f2798d88..49c2d8aa3c25 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++;
@@ -2339,8 +2339,9 @@ static int ravb_set_features_rcar(struct net_device *ndev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, ndev->features, 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 b01318964100..4a55c969241c 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++;
@@ -2936,8 +2936,9 @@ static int sh_eth_set_features(struct net_device *ndev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, ndev->features, features);
-	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 97f884c1993b..da2f375ad180 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -1782,8 +1782,8 @@ static int sxgbe_set_features(struct net_device *dev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, dev->features, 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 7c4338bddab3..3aefa37ae5ce 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -2713,7 +2713,7 @@ static u16 efx_ef10_handle_rx_event_errors(struct efx_channel *channel,
 	bool handled = false;
 
 	if (EFX_QWORD_FIELD(*event, ESF_DZ_RX_ECRC_ERR)) {
-		if (!(efx->net_dev->features & NETIF_F_RXALL)) {
+		if (!netdev_active_feature_test(efx->net_dev, NETIF_F_RXALL_BIT)) {
 			if (!efx->loopback_selftest)
 				channel->n_rx_eth_crc_err += n_packets;
 			return EFX_RX_PKT_DISCARD;
diff --git a/drivers/net/ethernet/sfc/ef100_rx.c b/drivers/net/ethernet/sfc/ef100_rx.c
index 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 9f6c4a971c48..b723b9851544 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1005,8 +1005,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 	netdev_active_features_set(net_dev, *efx->type->offload_features);
 	netdev_active_features_set_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
-	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 3d57a23022b7..f106c9e995a6 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 */
 	netdev_features_andnot(tmp, net_dev->features, 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.
 	 */
 	netdev_features_xor(tmp, net_dev->features, 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 854e1bca7ac9..8b37fc2e134e 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -1689,7 +1689,8 @@ static int ef4_probe_filters(struct ef4_nic *efx)
 		goto out_unlock;
 
 #ifdef CONFIG_RFS_ACCEL
-	if (*efx->type->offload_features & NETIF_F_NTUPLE) {
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT,
+				*efx->type->offload_features)) {
 		struct ef4_channel *channel;
 		int i, success = 1;
 
@@ -2187,7 +2188,7 @@ static int ef4_set_features(struct net_device *net_dev, netdev_features_t data)
 
 	/* If disabling RX n-tuple filtering, clear existing filters */
 	netdev_features_andnot(tmp, net_dev->features, 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 +2196,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 */
 	netdev_features_xor(tmp, net_dev->features, 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 64d01b301585..fb4db91f4d8f 100644
--- a/drivers/net/ethernet/sfc/mcdi_filters.c
+++ b/drivers/net/ethernet/sfc/mcdi_filters.c
@@ -1302,6 +1302,7 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining)
 {
 	struct net_device *net_dev = efx->net_dev;
 	struct efx_mcdi_filter_table *table;
+	netdev_features_t feats;
 	int rc;
 
 	if (!efx_rwsem_assert_write_locked(&efx->filter_sem))
@@ -1323,7 +1324,8 @@ 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) &&
+	feats = efx_supported_features(efx);
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, feats) &&
 	    !(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 +1349,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 +1766,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..ba6296325f38 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,7 @@ int efx_probe_filters(struct efx_nic *efx)
 		goto out_unlock;
 
 #ifdef CONFIG_RFS_ACCEL
-	if (*efx->type->offload_features & NETIF_F_NTUPLE) {
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, *efx->type->offload_features)) {
 		struct efx_channel *channel;
 		int i, success = 1;
 
diff --git a/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index e5937694bbb1..0583c4be58ce 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -988,8 +988,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
 	netdev_active_features_set(net_dev, *efx->type->offload_features);
 	netdev_active_features_set_set(net_dev, NETIF_F_SG_BIT, NETIF_F_TSO_BIT,
 				       NETIF_F_RXCSUM_BIT, NETIF_F_RXALL_BIT);
-	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 2693b2386916..f37dd541a593 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.
 	 */
 	netdev_features_xor(features, net_dev->features, 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 de799075704a..57cc1b3ddd72 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 af4fc0b60a7e..d594f6b312f2 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 c25bfecb4a2d..3e5e259198b2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -718,7 +718,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 49a314e709ff..05dc3483757d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3158,7 +3158,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;
@@ -4532,9 +4532,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);
@@ -5606,7 +5606,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;
@@ -5621,7 +5621,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 1fae42ea9879..c95c5d2f31f2 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 7418e4400763..ccd06f237ef9 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..7bdab63032a1 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..302304ccb41f 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
@@ -884,31 +884,33 @@ static int xlgmac_set_features(struct net_device *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;
-
-	if ((features & NETIF_F_RXHASH) && !rxhash)
+	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 (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 6bac37951b65..a64c450ce149 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -664,7 +664,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 54df79fe38ff..6a90ced12df5 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 f78387987793..4edb4efee977 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 e9d8ffa45703..98e2b649fabf 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -846,13 +846,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) {
@@ -1911,7 +1913,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");
 	}
@@ -1933,12 +1935,12 @@ static int netvsc_set_features(struct net_device *ndev,
 		return -ENODEV;
 
 	netdev_features_xor(change, ndev->features, features);
-	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 29b2376f9ef3..d5d94b6a7a0c 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 f81674c5a3de..0527988c4daf 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -344,7 +344,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 498cb6e04a87..0207298835a0 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 2bea292328a5..962a0a9c0307 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -489,7 +489,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 f2c03b964f54..00f660d89c82 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 db31ebdb6b64..90dd849cb6c9 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -547,7 +547,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 dc6df0ba0a26..7e1c22c955ca 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1167,7 +1167,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",
@@ -1232,7 +1232,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 134de64d4be7..6687081c5e37 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -598,23 +598,23 @@ static int aqc111_set_features(struct net_device *net,
 	u8 reg8 = 0;
 
 	netdev_features_xor(changed, net->features, features);
-	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);
@@ -627,8 +627,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++) {
@@ -908,17 +908,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);
@@ -935,7 +935,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,
@@ -1241,7 +1241,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 755d99e1815a..3f3c7da6f758 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -901,19 +901,19 @@ ax88179_set_features(struct net_device *net, netdev_features_t features)
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, net->features, 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;
@@ -1481,7 +1481,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 027a1c5103f8..db7eae1b976e 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_;
@@ -3542,10 +3542,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_));
@@ -3557,7 +3557,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 ba71a6d9a9da..e835a7be2a67 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2349,7 +2349,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);
@@ -3267,8 +3267,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);
@@ -5447,7 +5447,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);
 
@@ -5892,7 +5893,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);
 
@@ -6403,7 +6405,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);
 
@@ -6495,7 +6498,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 2d216c0d74de..d3f64cdadfd4 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);
@@ -2170,7 +2170,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 8f667e5eb246..43ba97ab1a82 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 1b6d33903a47..9d972158bf7b 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)
@@ -1059,7 +1059,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,
@@ -1476,10 +1476,11 @@ static int veth_set_features(struct net_device *dev,
 	int err;
 
 	netdev_features_xor(changed, dev->features, features);
-	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 ad16d382af9c..917df26f3794 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1267,7 +1267,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)
@@ -2582,7 +2582,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);
 	}
 
@@ -3217,11 +3217,11 @@ static int virtnet_set_features(struct net_device *dev,
 	int err;
 
 	netdev_features_xor(changed, dev->features, features);
-	if (changed & NETIF_F_GRO_HW) {
+	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, changed)) {
 		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 &
@@ -3233,8 +3233,8 @@ static int virtnet_set_features(struct net_device *dev,
 		vi->guest_offloads = offloads;
 	}
 
-	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))
 			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 ccead2500579..e9671df05780 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 8d664a9e4bd9..25daec280b1a 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;
@@ -317,10 +317,10 @@ static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_feat
 					       NETIF_F_TSO_BIT,
 					       NETIF_F_TSO6_BIT,
 					       NETIF_F_LRO_BIT);
-		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);
 	}
@@ -421,11 +421,11 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 	udp_tun_enabled = (netdev->features & tun_offload_mask) != 0;
 
 	netdev_features_xor(changed, netdev->features, features);
-	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
@@ -433,14 +433,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 756c2c8a8b96..9ae4af581545 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..ab32745f9732 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 ef885d29fe45..ace8ebaaaabf 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 6105c02a723b..d4005c2cca70 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -5501,7 +5501,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 {
@@ -6798,33 +6798,38 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
 	QETH_CARD_HEX(card, 2, &features, sizeof(features));
 
 	netdev_features_xor(changed, dev->features, 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 34a64b5f4502..28f21ea7bb81 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1890,9 +1890,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 6ec296321ffc..e9cc09187b6e 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);
 	}
@@ -1548,7 +1548,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),
@@ -1863,7 +1863,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 6bcf77c35bab..5e158dbf987f 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 {
@@ -2274,7 +2274,7 @@ static int qlge_set_features(struct net_device *ndev,
 	int err;
 
 	netdev_features_xor(changed, ndev->features, features);
-	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)
@@ -3573,7 +3573,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_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index 97b0edf5d2f7..0650d003ccf0 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -700,8 +700,9 @@ static inline bool __netdev_features_subset(const netdev_features_t *feats1,
 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 78e26b2e94b4..a9e231ea116e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2377,7 +2377,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;
 }
@@ -4407,7 +4407,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);		\
@@ -4415,12 +4415,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);		\
@@ -4812,20 +4812,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;
 	}
@@ -4956,7 +4956,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 624ed56a43bf..35404aedf51c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2257,7 +2257,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 72394f441dad..0b1ebe087921 100644
--- a/include/net/udp_tunnel.h
+++ b/include/net/udp_tunnel.h
@@ -133,7 +133,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);
 }
@@ -141,7 +141,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);
 }
@@ -330,7 +330,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);
@@ -339,7 +339,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..aec2e74ccfd9 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 0beb44f2fe1f..0c47445367bd 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 528c7da47a44..c2bfbb30fea5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1588,7 +1588,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)
@@ -1609,7 +1609,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");
 }
 
@@ -3393,7 +3393,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];
 
@@ -3643,10 +3643,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) {
@@ -4410,7 +4410,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))
@@ -9613,89 +9613,97 @@ 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");
@@ -9703,7 +9711,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);
 	}
@@ -9764,7 +9773,7 @@ int __netdev_update_features(struct net_device *dev)
 		netdev_features_t diff;
 
 		netdev_features_xor(diff, dev->features, 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.
@@ -9772,7 +9781,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 {
@@ -9780,8 +9789,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 {
@@ -9789,8 +9798,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 {
@@ -10016,8 +10025,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");
@@ -10053,13 +10062,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.
@@ -10960,7 +10969,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 */
@@ -11158,7 +11167,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);
 
@@ -11173,7 +11182,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);
@@ -11331,7 +11340,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 d1df34d68943..0e40de13de3f 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4057,11 +4057,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;
 
@@ -4317,7 +4317,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 188f8558d27d..f08ad75d72ac 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -387,7 +387,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 5b89b03660b9..89f99b42b179 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2373,7 +2373,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 595b8dae7fa3..88d5b1ba6e42 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -313,15 +313,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 5aeebbc1d349..b3d5cc34e3ec 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -217,14 +217,14 @@ 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) {
 		netdev_features_andnot(esp_features, 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)) {
 		netdev_features_andnot(esp_features, features,
 				       NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, esp_features);
@@ -268,8 +268,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 c9a90bed4ce4..cea677526304 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 8353875a9506..e128d2957d3f 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1013,10 +1013,11 @@ 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) {
@@ -1029,7 +1030,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;
@@ -1040,7 +1041,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;
@@ -1105,11 +1106,12 @@ 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 {
 				alloclen = fragheaderlen + transhdrlen;
@@ -1197,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;
 
@@ -1375,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 467a9c6aefb1..8a8dbe2f7ddc 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,16 @@ 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 908670adfdfc..0cbe51ad0803 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 19f685f6b378..5d8642b40a66 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -256,12 +256,12 @@ 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) {
 		netdev_features_andnot(esp_features, 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)) {
 		netdev_features_andnot(esp_features, features,
 				       NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, esp_features);
@@ -305,7 +305,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 28239182d820..40ca76257ec1 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,13 @@ 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 {
 				alloclen = fragheaderlen + transhdrlen;
@@ -1751,7 +1753,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..e8e10d13df1b 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -172,7 +172,8 @@ 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/nsh/nsh.c b/net/nsh/nsh.c
index fc6aff0922dc..cc38680a2982 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_features_zero(feats);
-	if (features & NETIF_F_SG)
+	if (netdev_feature_test(NETIF_F_SG_BIT, features))
 		netdev_feature_add(NETIF_F_SG_BIT, feats);
 	segs = skb_mac_gso_segment(skb, feats);
 	if (IS_ERR_OR_NULL(segs)) {
diff --git a/net/sctp/offload.c b/net/sctp/offload.c
index f4a528febbdc..c3d81154771e 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -78,7 +78,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 d4a362c9e4b3..1fda340afe9b 100644
--- a/net/sunrpc/sunrpc.h
+++ b/net/sunrpc/sunrpc.h
@@ -30,7 +30,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 dbaf2ddcf656..1d1782e83ccb 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -1086,7 +1086,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;
 	}
@@ -1255,7 +1255,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;
 	}
@@ -1437,7 +1437,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 78ebbccbd616..0ec7a813fab3 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -112,7 +112,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);
@@ -374,18 +374,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
 
@@ -394,7 +394,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 e986c4b64902..9ade97734543 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -748,7 +748,9 @@ 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] 74+ messages in thread

* [RFCv8 PATCH net-next 31/55] treewide: use netdev_features_intersects helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (29 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 30/55] treewide: use netdev_feature_test helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 32/55] treewide: use netdev_features_and/mask helpers Jian Shen
                   ` (25 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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     | 21 ++++++++++---------
 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                                | 10 ++++-----
 net/ethtool/ioctl.c                           |  5 +++--
 net/tls/tls_device.c                          |  2 +-
 34 files changed, 91 insertions(+), 81 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 88e09b177c03..212826228890 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2205,7 +2205,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 49e2d061348d..e61aa93c7c74 100644
--- a/drivers/net/ethernet/asix/ax88796c_main.c
+++ b/drivers/net/ethernet/asix/ax88796c_main.c
@@ -927,12 +927,12 @@ ax88796c_set_features(struct net_device *ndev, netdev_features_t features)
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, ndev->features, 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 28190575d0d4..64dec1d1217b 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -168,7 +168,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 87d25669c673..e4b12810148a 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 >>
@@ -11194,7 +11194,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)
@@ -11226,7 +11226,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))
@@ -13693,7 +13693,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 ec4cfea8b170..45723c5356cb 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -2441,8 +2441,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;
@@ -4697,7 +4698,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 2b8ecdab0f53..0c2d97e1154a 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;
 
 	netdev_features_xor(changed, dev->features, features);
-	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 d47e01652a91..6147864b0322 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 */
@@ -2163,7 +2163,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 d524d76a09eb..90402227dbd4 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 23bc8c228ce8..126444297e5d 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4881,7 +4881,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 60b545597f01..dc286f57a683 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -7320,7 +7320,7 @@ static int e1000_set_features(struct net_device *netdev,
 	netdev_features_t changed;
 
 	netdev_features_xor(changed, netdev->features, features);
-	if (changed & netdev_general_tso_features)
+	if (netdev_features_intersects(changed, netdev_general_tso_features))
 		adapter->flags |= FLAG_TSO_FORCE;
 
 	netdev_features_zero(changeable);
@@ -7328,7 +7328,7 @@ static int e1000_set_features(struct net_device *netdev,
 				NETIF_F_HW_VLAN_CTAG_TX_BIT, NETIF_F_RXCSUM_BIT,
 				NETIF_F_RXHASH_BIT, NETIF_F_RXFCS_BIT,
 				NETIF_F_RXALL_BIT);
-	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 e3dd3d359245..955f9f8ce66e 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2202,20 +2202,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)) {
@@ -4372,8 +4372,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);
 
@@ -4674,8 +4674,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 8e36b4d799c3..7ee3a32d36e1 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5861,8 +5861,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);
@@ -5870,7 +5870,7 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 
 	if (!netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT) &&
 	    netdev_feature_test(NETIF_F_RXFCS_BIT, features) &&
-	    (features & NETIF_VLAN_STRIPPING_FEATURES) &&
+	    netdev_features_intersects(features, NETIF_VLAN_STRIPPING_FEATURES) &&
 	    !ice_vsi_has_non_zero_vlans(np->vsi)) {
 		netdev_warn(netdev, "Disabling VLAN stripping as FCS/CRC stripping is also disabled and there is no VLAN configured\n");
 		netdev_features_clear(features,
@@ -5899,14 +5899,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)
@@ -5942,7 +5942,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);
@@ -5972,7 +5972,8 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 			    requested_vlan_features);
 	if (diff) {
 		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features) &&
-		    (features & NETIF_VLAN_STRIPPING_FEATURES)) {
+		    netdev_features_intersects(features,
+					       NETIF_VLAN_STRIPPING_FEATURES)) {
 			dev_err(ice_pf_to_dev(vsi->back),
 				"To enable VLAN stripping, you must first enable FCS/CRC stripping\n");
 			return -EIO;
@@ -6069,7 +6070,7 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
 	 */
 	if (netdev_feature_test(NETIF_F_RXFCS_BIT, changed)) {
 		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features) &&
-		    (features & NETIF_VLAN_STRIPPING_FEATURES)) {
+		    netdev_features_intersects(features, NETIF_VLAN_STRIPPING_FEATURES)) {
 			dev_err(ice_pf_to_dev(vsi->back),
 				"To disable FCS/CRC stripping, you must first disable VLAN stripping\n");
 			return -EIO;
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 077c8ab05eb1..959456dcc505 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4349,7 +4349,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 411cba30ebb6..7d9f8863d921 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4490,7 +4490,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 0f93a60655cb..eb96078ebff1 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1683,15 +1683,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 ae960254296b..2c56ca19f25c 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 9a76c5919d35..c6bce7f847b7 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;
@@ -4987,7 +4987,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;
@@ -6126,8 +6126,8 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 		 (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 2ca440255aa7..15dc30e0dff5 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1879,7 +1879,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 de4803b911cd..f74079e9c43a 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -183,7 +183,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 f106c9e995a6..8e6a86be924e 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 f37dd541a593..dcbb23a71c4d 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 90dd849cb6c9..ab8555799574 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -375,7 +375,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;
@@ -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 & netdev_general_tso_features)
+	if (netdev_features_intersects(feature_mask, netdev_general_tso_features))
 		netdev_features_set_set(features, NETIF_F_GRO_BIT,
 					NETIF_F_LRO_BIT);
 	else
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 9d972158bf7b..0e5bfe2ebfd2 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 25daec280b1a..ff1d4218135f 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -418,13 +418,13 @@ 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);
 
 	netdev_features_xor(changed, netdev->features, features);
 	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;
@@ -447,11 +447,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 ca2814ebe0d4..bdb6a599aa9f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -53,7 +53,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 d4005c2cca70..c7c0b8853452 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6780,9 +6780,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 28f21ea7bb81..ecc32a217e31 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1912,7 +1912,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 d8ff9230cc53..bab506759c1b 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 21dfdaf1389d..3adecc9a803f 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -578,7 +578,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");
 
 	netdev_vlan_features_andnot(dev, real_dev->vlan_features,
@@ -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 & 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);
 	netdev_features_or(tmp, NETIF_F_SOFT_FEATURES, NETIF_F_GSO_SOFTWARE);
diff --git a/net/core/dev.c b/net/core/dev.c
index c2bfbb30fea5..428f30bed9b6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3649,7 +3649,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):
@@ -9614,13 +9614,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);
@@ -9649,7 +9649,7 @@ 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) &&
+	if (!netdev_features_intersects(features, tmp) &&
 	    netdev_feature_test(NETIF_F_TSO_ECN_BIT, features))
 		netdev_feature_del(NETIF_F_TSO_ECN_BIT, features);
 
@@ -9661,7 +9661,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 88d5b1ba6e42..9819bb5b6165 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -274,7 +274,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;
 	netdev_features_andnot(tmp, changed, dev->hw_features);
 	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 1d1782e83ccb..e09a489c9aa7 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -1429,7 +1429,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] 74+ messages in thread

* [RFCv8 PATCH net-next 32/55] treewide: use netdev_features_and/mask helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (30 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 31/55] treewide: use netdev_features_intersects helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 33/55] treewide: use netdev_features_subset helpers Jian Shen
                   ` (24 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the 'f1 = f2 & f3' features expressions by
netdev_features_and helpers, and replace the 'f1 &= f2'
features 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     |  3 ++-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  2 +-
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  3 ++-
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  3 ++-
 .../ethernet/fungible/funeth/funeth_main.c    |  2 +-
 drivers/net/ethernet/ibm/ibmvnic.c            |  7 ++++---
 drivers/net/ethernet/intel/ice/ice_main.c     | 19 ++++++++++++-------
 .../ethernet/netronome/nfp/nfp_net_common.c   |  4 +++-
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  2 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  2 +-
 drivers/net/hyperv/rndis_filter.c             |  2 +-
 drivers/net/ipvlan/ipvlan_main.c              |  8 ++++----
 drivers/net/macsec.c                          |  7 ++++---
 drivers/net/macvlan.c                         | 11 ++++++-----
 drivers/net/net_failover.c                    |  6 ++++--
 drivers/net/team/team.c                       |  6 ++++--
 drivers/net/tun.c                             |  2 +-
 drivers/net/virtio_net.c                      |  4 +++-
 include/linux/if_vlan.h                       |  4 +++-
 include/linux/netdev_feature_helpers.h        |  5 ++++-
 net/8021q/vlan.h                              |  2 +-
 net/8021q/vlan_dev.c                          |  2 +-
 net/core/dev.c                                | 17 +++++++++--------
 net/ethtool/features.c                        |  3 ++-
 net/ethtool/ioctl.c                           | 10 +++++-----
 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 ++-
 33 files changed, 92 insertions(+), 64 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6db8d834c3e4..769ae7a6b800 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1451,8 +1451,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 59658e99bdc3..558d6a2f4e0a 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -7756,7 +7756,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;
+		netdev_features_and(tso, dev->hw_features, 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 e4b12810148a..ce886feeefdc 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11192,7 +11192,8 @@ 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;
+	netdev_features_and(vlan_features, 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 3b7348ffc71d..a1d6279886a7 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3319,7 +3319,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					NETIF_F_IP_CSUM_BIT, NETIF_F_TSO_BIT,
 					NETIF_F_RXCSUM_BIT,
 					NETIF_F_HW_VLAN_CTAG_RX_BIT);
-		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 ec054538e224..a4b06645861a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6856,7 +6856,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 					NETIF_F_IP_CSUM_BIT, NETIF_F_GRO_BIT,
 					NETIF_F_IPV6_CSUM_BIT,
 					NETIF_F_HIGHDMA_BIT);
-		netdev->vlan_features = netdev->features & vlan_features;
+		netdev_vlan_features_and(netdev, netdev->features,
+					 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 1dc39903d87c..94f253feda79 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -3082,7 +3082,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 					NETIF_F_IP_CSUM_BIT, NETIF_F_GRO_BIT,
 					NETIF_F_IPV6_CSUM_BIT,
 					NETIF_F_HIGHDMA_BIT);
-		netdev->vlan_features = netdev->features & vlan_features;
+		netdev_vlan_features_and(netdev, netdev->features,
+					 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 57734fae1c1e..ea5863db61ed 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1785,7 +1785,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_and(netdev, netdev->features, 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 126444297e5d..9c6fb5e21cb4 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4897,12 +4897,13 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 
 		netdev_features_zero(tmp);
 		/* 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 */
 		netdev_features_xor(tmp, old_hw_features,
 				    adapter->netdev->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 7ee3a32d36e1..ec148c43c130 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5820,13 +5820,15 @@ 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;
+	netdev_features_and(cur_vlan_fltr, netdev->features,
+			    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;
+	netdev_features_and(req_vlan_fltr, 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,
@@ -5966,8 +5968,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;
+	netdev_features_and(current_vlan_features, netdev->features,
+			    NETIF_VLAN_OFFLOAD_FEATURES);
+	netdev_features_and(requested_vlan_features, features,
+			    NETIF_VLAN_OFFLOAD_FEATURES);
 	netdev_features_xor(diff, current_vlan_features,
 			    requested_vlan_features);
 	if (diff) {
@@ -5984,9 +5988,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;
+	netdev_features_and(current_vlan_features, netdev->features,
+			    NETIF_VLAN_FILTERING_FEATURES);
+	netdev_features_and(requested_vlan_features, features,
+			    NETIF_VLAN_FILTERING_FEATURES);
 	netdev_features_xor(diff, current_vlan_features,
 			    requested_vlan_features);
 	if (diff) {
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index eb96078ebff1..e2ae7c147e45 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1785,10 +1785,12 @@ static netdev_features_t
 nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
 		       netdev_features_t features)
 {
+	netdev_features_t feats;
 	u8 l4_hdr;
 
 	/* We can't do TSO over double tagged packets (802.1AD) */
-	features &= vlan_features_check(skb, features);
+	feats = vlan_features_check(skb, features);
+	netdev_features_mask(features, feats);
 
 	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 2c56ca19f25c..8a15ec010282 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 8228e1d55e38..b97bbb07d06a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1079,7 +1079,7 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 						NETIF_F_IPV6_CSUM_BIT,
 						NETIF_F_TSO_BIT,
 						NETIF_F_TSO6_BIT);
-			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 d5d94b6a7a0c..3cfe04cf0b3d 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 5bb952c2b30d..d2c56abbaf5c 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -128,9 +128,9 @@ 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;
+	netdev_active_features_and(dev, phy_dev->features, IPVLAN_FEATURES);
 	netdev_active_features_set(dev, IPVLAN_ALWAYS_ON);
-	dev->vlan_features = phy_dev->vlan_features & IPVLAN_FEATURES;
+	netdev_vlan_features_and(dev, phy_dev->vlan_features, 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);
@@ -237,12 +237,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);
 	netdev_features_or(tmp, 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 0527988c4daf..b5d263c6469f 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3482,7 +3482,8 @@ static int macsec_dev_init(struct net_device *dev)
 	if (macsec_is_offloaded(macsec)) {
 		macsec_real_dev_features(real_dev, &dev->features);
 	} else {
-		dev->features = real_dev->features & SW_MACSEC_FEATURES;
+		netdev_active_features_and(dev, real_dev->features,
+					   SW_MACSEC_FEATURES);
 		netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 		netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 	}
@@ -3523,11 +3524,11 @@ static netdev_features_t macsec_fix_features(struct net_device *dev,
 		return tmp;
 	}
 
-	tmp = real_dev->features & SW_MACSEC_FEATURES;
+	netdev_features_and(tmp, real_dev->features, 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 0207298835a0..858eb9329945 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -895,10 +895,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;
+	netdev_active_features_and(dev, lowerdev->features, 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;
+	netdev_vlan_features_and(dev, lowerdev->vlan_features,
+				 MACVLAN_FEATURES);
 	netdev_vlan_features_set(dev, ALWAYS_ON_OFFLOADS);
 	netdev_hw_enc_features_set(dev, dev->features);
 	netif_inherit_tso_max(dev, lowerdev);
@@ -1084,16 +1085,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);
 	netdev_features_or(tmp, 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 962a0a9c0307..eed4e0ac18be 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -383,14 +383,16 @@ 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 enc_features  = FAILOVER_ENC_FEATURES;
 	unsigned short max_hard_header_len = ETH_HLEN;
 	unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
 					IFF_XMIT_DST_RELEASE_PERM;
 	struct net_failover_info *nfo_info = netdev_priv(dev);
 	struct net_device *primary_dev, *standby_dev;
+	netdev_features_t vlan_features;
+
+	netdev_features_and(vlan_features, FAILOVER_VLAN_FEATURES,
+			    NETIF_F_ALL_FOR_ALL);
 
 	primary_dev = rcu_dereference(nfo_info->primary_dev);
 	if (primary_dev) {
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 7e1c22c955ca..7c9e16d9e16b 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -989,12 +989,14 @@ 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 enc_features  = TEAM_ENC_FEATURES;
 	unsigned short max_hard_header_len = ETH_HLEN;
 	unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
 					IFF_XMIT_DST_RELEASE_PERM;
+	netdev_features_t vlan_features;
+
+	netdev_features_and(vlan_features, TEAM_VLAN_FEATURES,
+			    NETIF_F_ALL_FOR_ALL);
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(port, &team->port_list, list) {
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index caf449e9e666..b9bc7ff7c283 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1171,7 +1171,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;
+	netdev_features_and(tmp1, features, tun->set_features);
 	netdev_features_andnot(tmp2, features, TUN_USER_FEATURES);
 	return tmp1 | tmp2;
 }
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 917df26f3794..f10bfe07d48d 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3745,8 +3745,10 @@ 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_features_and(tmp, dev->hw_features,
+					    NETIF_F_ALL_TSO);
 			netdev_active_features_set(dev, tmp);
 		}
 		/* (!csum && gso) case will be fixed by register_netdev() */
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 173bf09b4cad..7adac714c78b 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_feature_helpers.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_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index 0650d003ccf0..31f52db00fa5 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -700,6 +700,8 @@ static inline bool __netdev_features_subset(const netdev_features_t *feats1,
 static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
 							  netdev_features_t f2)
 {
+	netdev_features_t ret;
+
 	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))
@@ -708,7 +710,8 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
 			netdev_features_set(f2, netdev_ip_csum_features);
 	}
 
-	return f1 & f2;
+	netdev_features_and(ret, f1, f2);
+	return ret;
 }
 
 static inline netdev_features_t
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index bab506759c1b..2acb89660ab5 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)
 
 	netdev_features_or(ret, 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 3adecc9a803f..04588800df24 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -664,7 +664,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);
 	netdev_features_or(tmp, 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 428f30bed9b6..10e74f33147e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3397,7 +3397,8 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
 		netdev_features_t partial_features;
 		struct net_device *dev = skb->dev;
 
-		partial_features = dev->features & dev->gso_partial_features;
+		netdev_features_and(partial_features, dev->features,
+				    dev->gso_partial_features);
 		netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, partial_features);
 		netdev_features_set(partial_features, features);
 		if (!skb_gso_ok(skb, partial_features))
@@ -3465,7 +3466,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;
 }
@@ -3567,7 +3568,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)) {
 		netdev_features_or(tmp, dev->vlan_features,
@@ -3579,7 +3580,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);
 }
@@ -10052,7 +10053,7 @@ 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;
+	netdev_wanted_features_and(dev, dev->features, dev->hw_features);
 
 	if (!(dev->flags & IFF_LOOPBACK))
 		netdev_hw_feature_add(dev, NETIF_F_NOCACHE_COPY_BIT);
@@ -11172,14 +11173,14 @@ netdev_features_t netdev_increment_features(netdev_features_t all,
 	netdev_feature_add(NETIF_F_VLAN_CHALLENGED_BIT, mask);
 
 	netdev_features_or(tmp, NETIF_F_ONE_FOR_ALL, NETIF_F_CSUM_MASK);
-	tmp &= one;
-	tmp &= mask;
+	netdev_features_mask(tmp, one);
+	netdev_features_mask(tmp, mask);
 	netdev_features_set(all, tmp);
 
 	netdev_features_fill(tmp);
 	netdev_features_clear(tmp, NETIF_F_ALL_FOR_ALL);
 	netdev_features_set(tmp, one);
-	all &= tmp;
+	netdev_features_mask(all, tmp);
 
 	/* If one device supports hw checksumming, set for all. */
 	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, all)) {
diff --git a/net/ethtool/features.c b/net/ethtool/features.c
index 769d77cbeb16..496dfd45faac 100644
--- a/net/ethtool/features.c
+++ b/net/ethtool/features.c
@@ -254,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)) {
 		netdev_wanted_features_clear(dev, dev->hw_features);
-		tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features;
+		tmp = ethnl_bitmap_to_features(req_wanted);
+		netdev_features_mask(tmp, dev->hw_features);
 		netdev_wanted_features_set(dev, tmp);
 		__netdev_update_features(dev);
 	}
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 9819bb5b6165..a094c9e14d3d 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -153,12 +153,12 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 
 	netdev_features_andnot(tmp, valid, dev->hw_features);
 	if (tmp) {
-		valid &= dev->hw_features;
+		netdev_features_mask(valid, dev->hw_features);
 		ret |= ETHTOOL_F_UNSUPPORTED;
 	}
 
 	netdev_wanted_features_clear(dev, valid);
-	tmp = wanted & valid;
+	netdev_features_and(tmp, wanted, valid);
 	netdev_wanted_features_set(dev, tmp);
 	__netdev_update_features(dev);
 
@@ -292,7 +292,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 */
 	netdev_features_xor(changed, dev->features, features);
-	changed &= eth_all_features;
+	netdev_features_mask(changed, eth_all_features);
 	netdev_features_andnot(tmp, changed, dev->hw_features);
 	if (tmp)
 		return netdev_hw_features_intersects(dev, changed) ?
 			-EINVAL : -EOPNOTSUPP;
 
 	netdev_wanted_features_clear(dev, changed);
-	tmp = features & changed;
+	netdev_features_and(tmp, 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 1607dd056702..67f71417032a 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1375,7 +1375,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 cea677526304..2434e7099190 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 0cbe51ad0803..107a80518f61 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 d37a8c97e6de..db7737bac5c3 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 d2227c0af028..799fbbabe6eb 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -2230,7 +2230,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
 		netdev_active_features_set(ndev, local->hw.netdev_features);
 		ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
-		tmp = ndev->features & MAC80211_SUPPORTED_FEATURES_TX;
+		netdev_features_and(tmp, ndev->features,
+				    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..4cf6a6c2eaaa 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_feature_helpers.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;
+	netdev_features_and(mpls_features, skb->dev->mpls_features, 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,
-- 
2.33.0


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

* [RFCv8 PATCH net-next 33/55] treewide: use netdev_features_subset helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (31 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 32/55] treewide: use netdev_features_and/mask helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 34/55] treewide: use netdev_features_equal helpers Jian Shen
                   ` (23 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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 212826228890..92e722c356e0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2199,7 +2199,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 10e74f33147e..8d1dc83182a2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9701,8 +9701,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] 74+ messages in thread

* [RFCv8 PATCH net-next 34/55] treewide: use netdev_features_equal helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (32 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 33/55] treewide: use netdev_features_subset helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 35/55] treewide: use netdev_features_empty helpers Jian Shen
                   ` (22 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the 'f1 == f2' and 'f1 != f2' features expressions 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 ce886feeefdc..27a45adb7672 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11194,7 +11194,7 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 	 */
 	netdev_features_and(vlan_features, 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 9c6fb5e21cb4..6f84086ddfe2 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4892,7 +4892,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_features_zero(tmp);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index ec148c43c130..d52775c16a81 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5834,7 +5834,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 8e6a86be924e..9a52492f3f06 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 8b37fc2e134e..232e8fde0a81 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 dcbb23a71c4d..5360c6d6c026 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 c7c0b8853452..72c487009c33 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6757,7 +6757,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");
 }
@@ -6842,7 +6842,7 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
 	qeth_check_restricted_features(card, diff1, diff2);
 
 	/* everything changed successfully? */
-	if (diff1 == changed)
+	if (netdev_features_equal(diff1, changed))
 		return 0;
 	/* something went wrong. save changed features and return error */
 	netdev_active_features_toggle(dev, changed);
diff --git a/net/core/dev.c b/net/core/dev.c
index 8d1dc83182a2..f790f1986dd3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9741,7 +9741,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 a094c9e14d3d..e3897766781f 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] 74+ messages in thread

* [RFCv8 PATCH net-next 35/55] treewide: use netdev_features_empty helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (33 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 34/55] treewide: use netdev_features_equal helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 36/55] net: adjust the prototype of netdev_increment_features() Jian Shen
                   ` (21 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace the empty checking expressions of features by
netdev_features_empty 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 1095cfb0783a..53b6ed00e124 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4965,7 +4965,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 27a45adb7672..e8ccccb07045 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,
 		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 955f9f8ce66e..2cc85f1a81df 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4825,7 +4825,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 d52775c16a81..b69357c220d9 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5974,7 +5974,7 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 			    NETIF_VLAN_OFFLOAD_FEATURES);
 	netdev_features_xor(diff, current_vlan_features,
 			    requested_vlan_features);
-	if (diff) {
+	if (!netdev_features_empty(diff)) {
 		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features) &&
 		    netdev_features_intersects(features,
 					       NETIF_VLAN_STRIPPING_FEATURES)) {
@@ -5994,7 +5994,7 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 			    NETIF_VLAN_FILTERING_FEATURES);
 	netdev_features_xor(diff, 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 e3897766781f..c4154666e82a 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -293,7 +293,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)
 	netdev_features_xor(changed, dev->features, features);
 	netdev_features_mask(changed, eth_all_features);
 	netdev_features_andnot(tmp, changed, dev->hw_features);
-	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] 74+ messages in thread

* [RFCv8 PATCH net-next 36/55] net: adjust the prototype of netdev_increment_features()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (34 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 35/55] treewide: use netdev_features_empty helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 37/55] net: adjust the prototype of netdev_add_tso_features() Jian Shen
                   ` (20 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function netdev_increment_features() returns netdev_features_t
directly. For the prototype of netdev_features_t will be extended
to be larger than 8 bytes, so change the prototype of the function,
return the features pointer as output parameters.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/bonding/bond_main.c  | 28 +++++++++++-----------
 drivers/net/ipvlan/ipvlan_main.c |  4 ++--
 drivers/net/macvlan.c            |  3 ++-
 drivers/net/net_failover.c       | 28 ++++++++++------------
 drivers/net/team/team.c          | 18 +++++++-------
 include/linux/netdevice.h        |  9 ++++---
 net/bridge/br_if.c               |  4 ++--
 net/core/dev.c                   | 40 +++++++++++++++++++-------------
 net/hsr/hsr_device.c             |  5 ++--
 9 files changed, 72 insertions(+), 67 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 769ae7a6b800..5c76a55392aa 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1417,9 +1417,8 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 	netdev_features_set(features, NETIF_F_ALL_FOR_ALL);
 
 	bond_for_each_slave(bond, slave, iter) {
-		features = netdev_increment_features(features,
-						     slave->dev->features,
-						     mask);
+		netdev_increment_features(&features, &features,
+					  &slave->dev->features, &mask);
 	}
 	features = netdev_add_tso_features(features, mask);
 
@@ -1455,22 +1454,23 @@ static void bond_compute_features(struct bonding *bond)
 	netdev_features_mask(mpls_features, NETIF_F_ALL_FOR_ALL);
 
 	bond_for_each_slave(bond, slave, iter) {
-		vlan_features = netdev_increment_features(vlan_features,
-			slave->dev->vlan_features, BOND_VLAN_FEATURES);
+		netdev_increment_features(&vlan_features, &vlan_features,
+					  &slave->dev->vlan_features,
+					  &BOND_VLAN_FEATURES);
 
-		enc_features = netdev_increment_features(enc_features,
-							 slave->dev->hw_enc_features,
-							 BOND_ENC_FEATURES);
+		netdev_increment_features(&enc_features, &enc_features,
+					  &slave->dev->hw_enc_features,
+					  &BOND_ENC_FEATURES);
 
 #ifdef CONFIG_XFRM_OFFLOAD
-		xfrm_features = netdev_increment_features(xfrm_features,
-							  slave->dev->hw_enc_features,
-							  BOND_XFRM_FEATURES);
+		netdev_increment_features(&xfrm_features, &xfrm_features,
+					  &slave->dev->hw_enc_features,
+					  &BOND_XFRM_FEATURES);
 #endif /* CONFIG_XFRM_OFFLOAD */
 
-		mpls_features = netdev_increment_features(mpls_features,
-							  slave->dev->mpls_features,
-							  BOND_MPLS_FEATURES);
+		netdev_increment_features(&mpls_features, &mpls_features,
+					  &slave->dev->mpls_features,
+					  &BOND_MPLS_FEATURES);
 
 		dst_release_flag &= slave->dev->priv_flags;
 		if (slave->dev->hard_header_len > max_hard_header_len)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index d2c56abbaf5c..e7737e7938fd 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -238,8 +238,8 @@ static netdev_features_t ipvlan_fix_features(struct net_device *dev,
 	netdev_features_clear(tmp, IPVLAN_FEATURES);
 	netdev_features_set(tmp, ipvlan->sfeatures);
 	netdev_features_mask(features, tmp);
-	features = netdev_increment_features(ipvlan->phy_dev->features,
-					     features, features);
+	netdev_increment_features(&features, &ipvlan->phy_dev->features,
+				  &features, &features);
 	netdev_features_set(features, IPVLAN_ALWAYS_ON);
 	netdev_features_or(tmp, IPVLAN_FEATURES, IPVLAN_ALWAYS_ON);
 	netdev_features_mask(features, tmp);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 858eb9329945..1e357643fd43 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1091,7 +1091,8 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
 	tmp = features;
 	netdev_feature_del(NETIF_F_LRO_BIT, tmp);
 	netdev_features_mask(lowerdev_features, tmp);
-	features = netdev_increment_features(lowerdev_features, features, mask);
+	netdev_increment_features(&features, &lowerdev_features, &features,
+				  &mask);
 	netdev_features_set(features, ALWAYS_ON_FEATURES);
 	netdev_features_or(tmp, ALWAYS_ON_FEATURES, MACVLAN_FEATURES);
 	netdev_features_mask(features, tmp);
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index eed4e0ac18be..d0b72fd696d3 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -396,14 +396,12 @@ static void net_failover_compute_features(struct net_device *dev)
 
 	primary_dev = rcu_dereference(nfo_info->primary_dev);
 	if (primary_dev) {
-		vlan_features =
-			netdev_increment_features(vlan_features,
-						  primary_dev->vlan_features,
-						  FAILOVER_VLAN_FEATURES);
-		enc_features =
-			netdev_increment_features(enc_features,
-						  primary_dev->hw_enc_features,
-						  FAILOVER_ENC_FEATURES);
+		netdev_increment_features(&vlan_features, &vlan_features,
+					  &primary_dev->vlan_features,
+					  &FAILOVER_VLAN_FEATURES);
+		netdev_increment_features(&enc_features, &enc_features,
+					  &primary_dev->hw_enc_features,
+					  &FAILOVER_ENC_FEATURES);
 
 		dst_release_flag &= primary_dev->priv_flags;
 		if (primary_dev->hard_header_len > max_hard_header_len)
@@ -412,14 +410,12 @@ static void net_failover_compute_features(struct net_device *dev)
 
 	standby_dev = rcu_dereference(nfo_info->standby_dev);
 	if (standby_dev) {
-		vlan_features =
-			netdev_increment_features(vlan_features,
-						  standby_dev->vlan_features,
-						  FAILOVER_VLAN_FEATURES);
-		enc_features =
-			netdev_increment_features(enc_features,
-						  standby_dev->hw_enc_features,
-						  FAILOVER_ENC_FEATURES);
+		netdev_increment_features(&vlan_features, &vlan_features,
+					  &standby_dev->vlan_features,
+					  &FAILOVER_VLAN_FEATURES);
+		netdev_increment_features(&enc_features, &enc_features,
+					  &standby_dev->hw_enc_features,
+					  &FAILOVER_ENC_FEATURES);
 
 		dst_release_flag &= standby_dev->priv_flags;
 		if (standby_dev->hard_header_len > max_hard_header_len)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 7c9e16d9e16b..8d3a97d2d1dc 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1000,13 +1000,12 @@ static void __team_compute_features(struct team *team)
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(port, &team->port_list, list) {
-		vlan_features = netdev_increment_features(vlan_features,
-					port->dev->vlan_features,
-					TEAM_VLAN_FEATURES);
-		enc_features =
-			netdev_increment_features(enc_features,
-						  port->dev->hw_enc_features,
-						  TEAM_ENC_FEATURES);
+		netdev_increment_features(&vlan_features, &vlan_features,
+					  &port->dev->vlan_features,
+					  &TEAM_VLAN_FEATURES);
+		netdev_increment_features(&enc_features, &enc_features,
+					  &port->dev->hw_enc_features,
+					  &TEAM_ENC_FEATURES);
 
 
 		dst_release_flag &= port->dev->priv_flags;
@@ -2014,9 +2013,8 @@ static netdev_features_t team_fix_features(struct net_device *dev,
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(port, &team->port_list, list) {
-		features = netdev_increment_features(features,
-						     port->dev->features,
-						     mask);
+		netdev_increment_features(&features, &features,
+					  &port->dev->features, &mask);
 	}
 	rcu_read_unlock();
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a9e231ea116e..3f451906d62c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4890,8 +4890,10 @@ extern const struct kobj_ns_type_operations net_ns_type_operations;
 
 const char *netdev_drivername(const struct net_device *dev);
 
-netdev_features_t netdev_increment_features(netdev_features_t all,
-	netdev_features_t one, netdev_features_t mask);
+void netdev_increment_features(netdev_features_t *ret,
+			       const netdev_features_t *all,
+			       const netdev_features_t *one,
+			       const netdev_features_t *mask);
 
 /* Allow TSO being used on stacked device :
  * Performing the GSO segmentation before last device
@@ -4900,7 +4902,8 @@ netdev_features_t netdev_increment_features(netdev_features_t all,
 static inline netdev_features_t netdev_add_tso_features(netdev_features_t features,
 							netdev_features_t mask)
 {
-	return netdev_increment_features(features, NETIF_F_ALL_TSO, mask);
+	netdev_increment_features(&features, &features, &NETIF_F_ALL_TSO, &mask);
+	return features;
 }
 
 int __netdev_update_features(struct net_device *dev);
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index ef8dd8a91164..fa348a984aa9 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -545,8 +545,8 @@ netdev_features_t br_features_recompute(struct net_bridge *br,
 	netdev_features_clear(features, NETIF_F_ONE_FOR_ALL);
 
 	list_for_each_entry(p, &br->port_list, list) {
-		features = netdev_increment_features(features,
-						     p->dev->features, mask);
+		netdev_increment_features(&features, &features,
+					  &p->dev->features, &mask);
 	}
 	features = netdev_add_tso_features(features, mask);
 
diff --git a/net/core/dev.c b/net/core/dev.c
index f790f1986dd3..327f99fbae73 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11154,41 +11154,49 @@ static int dev_cpu_dead(unsigned int oldcpu)
 
 /**
  *	netdev_increment_features - increment feature set by one
+ *	@ret: result feature set
  *	@all: current feature set
  *	@one: new feature set
  *	@mask: mask feature set
  *
  *	Computes a new feature set after adding a device with feature set
  *	@one to the master device with current feature set @all.  Will not
- *	enable anything that is off in @mask. Returns the new feature set.
+ *	enable anything that is off in @mask. Returns the new feature set by
+ *	@ret.
  */
-netdev_features_t netdev_increment_features(netdev_features_t all,
-	netdev_features_t one, netdev_features_t mask)
+void netdev_increment_features(netdev_features_t *ret,
+			       const netdev_features_t *all,
+			       const netdev_features_t *one,
+			       const netdev_features_t *mask)
 {
+	netdev_features_t local_mask;
+	netdev_features_t local_one;
 	netdev_features_t tmp;
 
-	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);
+	netdev_features_copy(*ret, *all);
+	netdev_features_copy(local_one, *one);
+	netdev_features_copy(local_mask, *mask);
+
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, local_mask))
+		netdev_features_set(local_mask, NETIF_F_CSUM_MASK);
+	netdev_feature_add(NETIF_F_VLAN_CHALLENGED_BIT, local_mask);
 
 	netdev_features_or(tmp, NETIF_F_ONE_FOR_ALL, NETIF_F_CSUM_MASK);
-	netdev_features_mask(tmp, one);
-	netdev_features_mask(tmp, mask);
-	netdev_features_set(all, tmp);
+	netdev_features_mask(tmp, local_one);
+	netdev_features_mask(tmp, local_mask);
+	netdev_features_set(*ret, tmp);
 
 	netdev_features_fill(tmp);
 	netdev_features_clear(tmp, NETIF_F_ALL_FOR_ALL);
-	netdev_features_set(tmp, one);
-	netdev_features_mask(all, tmp);
+	netdev_features_set(tmp, local_one);
+	netdev_features_mask(*ret, tmp);
 
 	/* If one device supports hw checksumming, set for all. */
-	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, all)) {
-		tmp = NETIF_F_CSUM_MASK;
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, *ret)) {
+		netdev_features_copy(tmp, NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_HW_CSUM_BIT, tmp);
-		netdev_features_clear(all, tmp);
+		netdev_features_clear(*ret, tmp);
 	}
-
-	return all;
 }
 EXPORT_SYMBOL(netdev_increment_features);
 
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index 0e37ba6e1569..ae0261a450e6 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -195,9 +195,8 @@ static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr,
 	 */
 	netdev_features_clear(features, NETIF_F_ONE_FOR_ALL);
 	hsr_for_each_port(hsr, port)
-		features = netdev_increment_features(features,
-						     port->dev->features,
-						     mask);
+		netdev_increment_features(&features, &features,
+					  &port->dev->features, &mask);
 
 	return features;
 }
-- 
2.33.0


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

* [RFCv8 PATCH net-next 37/55] net: adjust the prototype of netdev_add_tso_features()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (35 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 36/55] net: adjust the prototype of netdev_increment_features() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 38/55] net: core: adjust prototype of several functions used in net/core/dev.c Jian Shen
                   ` (19 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function netdev_add_tos_features() using netdev_features_t
as parameters, and returns netdev_features_t directly. For the
prototype of netdev_features_t will be extended to be larger
than 8 bytes, so change the prototype of the function, change
the prototype of input features to ‘netdev_features_t *',
and return the features pointer as output parameters.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/bonding/bond_main.c | 2 +-
 drivers/net/team/team.c         | 2 +-
 include/linux/netdevice.h       | 7 +++----
 net/bridge/br_if.c              | 2 +-
 4 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 5c76a55392aa..a50f8935658a 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1420,7 +1420,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 		netdev_increment_features(&features, &features,
 					  &slave->dev->features, &mask);
 	}
-	features = netdev_add_tso_features(features, mask);
+	netdev_add_tso_features(&features, &mask);
 
 	return features;
 }
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 8d3a97d2d1dc..508424471c28 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2018,7 +2018,7 @@ static netdev_features_t team_fix_features(struct net_device *dev,
 	}
 	rcu_read_unlock();
 
-	features = netdev_add_tso_features(features, mask);
+	netdev_add_tso_features(&features, &mask);
 
 	return features;
 }
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3f451906d62c..ec9e7cf7efbc 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4899,11 +4899,10 @@ void netdev_increment_features(netdev_features_t *ret,
  * Performing the GSO segmentation before last device
  * is a performance improvement.
  */
-static inline netdev_features_t netdev_add_tso_features(netdev_features_t features,
-							netdev_features_t mask)
+static inline void netdev_add_tso_features(netdev_features_t *features,
+					   const netdev_features_t *mask)
 {
-	netdev_increment_features(&features, &features, &NETIF_F_ALL_TSO, &mask);
-	return features;
+	netdev_increment_features(features, features, &NETIF_F_ALL_TSO, mask);
 }
 
 int __netdev_update_features(struct net_device *dev);
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index fa348a984aa9..2a9b564ff234 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -548,7 +548,7 @@ netdev_features_t br_features_recompute(struct net_bridge *br,
 		netdev_increment_features(&features, &features,
 					  &p->dev->features, &mask);
 	}
-	features = netdev_add_tso_features(features, mask);
+	netdev_add_tso_features(&features, &mask);
 
 	return features;
 }
-- 
2.33.0


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

* [RFCv8 PATCH net-next 38/55] net: core: adjust prototype of several functions used in net/core/dev.c
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (36 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 37/55] net: adjust the prototype of netdev_add_tso_features() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 39/55] net: adjust the prototype of netdev_intersect_features() Jian Shen
                   ` (18 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

There are several functions in net/core/dev.c using
netdev_features_t as parameters, or returns netdev_features_t
directly, or both. For the prototype of netdev_features_t will
be extended to be larger than 8 bytes, so change the prototype
of the function, change the prototype of input features to
'netdev_features_t *', and return the features pointer as output
parameters.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 include/linux/netdev_feature_helpers.h |  11 +-
 include/linux/netdevice.h              |   2 +-
 net/core/dev.c                         | 160 ++++++++++++-------------
 net/openvswitch/datapath.c             |   2 +-
 4 files changed, 81 insertions(+), 94 deletions(-)

diff --git a/include/linux/netdev_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index 31f52db00fa5..60bc021648e4 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -714,14 +714,11 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
 	return ret;
 }
 
-static inline netdev_features_t
-netdev_get_wanted_features(struct net_device *dev)
+static inline void
+netdev_get_wanted_features(struct net_device *dev, netdev_features_t *wanted)
 {
-	netdev_features_t tmp;
-
-	netdev_features_andnot(tmp, dev->features, dev->hw_features);
-	netdev_features_set(tmp, dev->wanted_features);
-	return tmp;
+	netdev_features_andnot(*wanted, dev->features, dev->hw_features);
+	netdev_features_set(*wanted, dev->wanted_features);
 }
 
 #endif
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ec9e7cf7efbc..68f950f5a36b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4770,7 +4770,7 @@ void netdev_rss_key_fill(void *buffer, size_t len);
 int skb_checksum_help(struct sk_buff *skb);
 int skb_crc32c_csum_help(struct sk_buff *skb);
 int skb_csum_hwoffload_help(struct sk_buff *skb,
-			    const netdev_features_t features);
+			    const netdev_features_t *features);
 
 struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
 				  netdev_features_t features, bool tx_path);
diff --git a/net/core/dev.c b/net/core/dev.c
index 327f99fbae73..ac53e727d88f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3461,41 +3461,33 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
  * instead of standard features for the netdev.
  */
 #if IS_ENABLED(CONFIG_NET_MPLS_GSO)
-static netdev_features_t net_mpls_features(struct sk_buff *skb,
-					   netdev_features_t features,
-					   __be16 type)
+static void net_mpls_features(struct sk_buff *skb, netdev_features_t *features,
+			      __be16 type)
 {
 	if (eth_p_mpls(type))
-		netdev_features_mask(features, skb->dev->mpls_features);
-
-	return features;
+		netdev_features_mask(*features, skb->dev->mpls_features);
 }
 #else
-static netdev_features_t net_mpls_features(struct sk_buff *skb,
-					   netdev_features_t features,
-					   __be16 type)
+static void net_mpls_features(struct sk_buff *skb, netdev_features_t *features,
+			      __be16 type)
 {
-	return features;
 }
 #endif
 
-static netdev_features_t harmonize_features(struct sk_buff *skb,
-	netdev_features_t features)
+static void harmonize_features(struct sk_buff *skb, netdev_features_t *features)
 {
 	__be16 type;
 
 	type = skb_network_protocol(skb, NULL);
-	features = net_mpls_features(skb, features, type);
+	net_mpls_features(skb, features, type);
 
 	if (skb->ip_summed != CHECKSUM_NONE &&
-	    !can_checksum_protocol(features, type)) {
-		netdev_features_clear(features,
+	    !can_checksum_protocol(*features, type)) {
+		netdev_features_clear(*features,
 				      netdev_csum_gso_features_mask);
 	}
 	if (illegal_highdma(skb->dev, skb))
-		netdev_feature_del(NETIF_F_SG_BIT, features);
-
-	return features;
+		netdev_feature_del(NETIF_F_SG_BIT, *features);
 }
 
 netdev_features_t passthru_features_check(struct sk_buff *skb,
@@ -3582,7 +3574,8 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
 		tmp = dflt_features_check(skb, dev, features);
 	netdev_features_mask(features, tmp);
 
-	return harmonize_features(skb, features);
+	harmonize_features(skb, &features);
+	return features;
 }
 EXPORT_SYMBOL(netif_skb_features);
 
@@ -3641,16 +3634,16 @@ static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb,
 }
 
 int skb_csum_hwoffload_help(struct sk_buff *skb,
-			    const netdev_features_t features)
+			    const netdev_features_t *features)
 {
 	if (unlikely(skb_csum_is_sctp(skb)))
-		return netdev_feature_test(NETIF_F_SCTP_CRC_BIT, features) ? 0 :
+		return netdev_feature_test(NETIF_F_SCTP_CRC_BIT, *features) ? 0 :
 			skb_crc32c_csum_help(skb);
 
-	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, *features))
 		return 0;
 
-	if (netdev_features_intersects(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):
@@ -3701,7 +3694,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
 			else
 				skb_set_transport_header(skb,
 							 skb_checksum_start_offset(skb));
-			if (skb_csum_hwoffload_help(skb, features))
+			if (skb_csum_hwoffload_help(skb, &features))
 				goto out_kfree_skb;
 		}
 	}
@@ -9567,32 +9560,31 @@ static void net_set_todo(struct net_device *dev)
 	atomic_inc(&dev_net(dev)->dev_unreg_count);
 }
 
-static netdev_features_t netdev_sync_upper_features(struct net_device *lower,
-	struct net_device *upper, netdev_features_t features)
+static void 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;
 	int feature_bit;
 
 	for_each_netdev_feature(upper_disables, feature_bit) {
 		if (!netdev_wanted_feature_test(upper, feature_bit) &&
-		    netdev_feature_test(feature_bit, features)) {
+		    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);
+			netdev_feature_del(feature_bit, *features);
 		}
 	}
-
-	return features;
 }
 
 static void netdev_sync_lower_features(struct net_device *upper,
-	struct net_device *lower, netdev_features_t features)
+	struct net_device *lower, netdev_features_t *features)
 {
 	netdev_features_t upper_disables = NETIF_F_UPPER_DISABLES;
 	int feature_bit;
 
 	for_each_netdev_feature(upper_disables, feature_bit) {
-		if (!netdev_feature_test(feature_bit, features) &&
+		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);
@@ -9608,116 +9600,114 @@ 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)
+static void netdev_fix_features(struct net_device *dev,
+				netdev_features_t *features)
 {
 	netdev_features_t tmp;
 
 	/* Fix illegal checksum combinations */
-	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features) &&
-	    netdev_features_intersects(features, netdev_ip_csum_features)) {
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, *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);
+		netdev_features_clear(*features, netdev_ip_csum_features);
 	}
 
 	/* TSO requires that SG is present as well. */
-	if (netdev_features_intersects(features, NETIF_F_ALL_TSO) &&
-	    !netdev_feature_test(NETIF_F_SG_BIT, features)) {
+	if (netdev_features_intersects(*features, NETIF_F_ALL_TSO) &&
+	    !netdev_feature_test(NETIF_F_SG_BIT, *features)) {
 		netdev_dbg(dev, "Dropping TSO features since no SG feature.\n");
-		netdev_features_clear(features, NETIF_F_ALL_TSO);
+		netdev_features_clear(*features, NETIF_F_ALL_TSO);
 	}
 
-	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)) {
+	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);
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
+		netdev_feature_del(NETIF_F_TSO_ECN_BIT, *features);
 	}
 
-	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)) {
+	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);
+		netdev_feature_del(NETIF_F_TSO6_BIT, *features);
 	}
 
 	/* TSO with IPv4 ID mangling requires IPv4 TSO be enabled */
-	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);
+	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 (!netdev_features_intersects(features, tmp) &&
-	    netdev_feature_test(NETIF_F_TSO_ECN_BIT, features))
-		netdev_feature_del(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. */
-	if (netdev_feature_test(NETIF_F_GSO_BIT, features) &&
-	    !netdev_feature_test(NETIF_F_SG_BIT, features)) {
+	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);
+		netdev_feature_del(NETIF_F_GSO_BIT, *features);
 	}
 
 	/* GSO partial features require GSO partial be set */
-	if (netdev_gso_partial_features_intersects(dev, features) &&
-	    !netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, 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");
-		netdev_features_clear(features, dev->gso_partial_features);
+		netdev_features_clear(*features, dev->gso_partial_features);
 	}
 
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
+	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 (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) {
+		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);
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 		}
 	}
 
 	/* LRO/HW-GRO features cannot be combined with RX-FCS */
-	if (netdev_feature_test(NETIF_F_RXFCS_BIT, features)) {
-		if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+	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);
+			netdev_feature_del(NETIF_F_LRO_BIT, *features);
 		}
 
-		if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) {
+		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);
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 		}
 	}
 
-	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features) &&
-	    netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+	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);
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 	}
 
-	if (netdev_feature_test(NETIF_F_HW_TLS_TX_BIT, features)) {
-		bool ip_csum = netdev_features_subset(netdev_ip_csum_features, features);
+	if (netdev_feature_test(NETIF_F_HW_TLS_TX_BIT, *features)) {
+		bool ip_csum = netdev_features_subset(netdev_ip_csum_features, *features);
 		bool hw_csum = netdev_feature_test(NETIF_F_HW_CSUM_BIT,
-						   features);
+						   *features);
 
 		if (!ip_csum && !hw_csum) {
 			netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n");
-			netdev_feature_del(NETIF_F_HW_TLS_TX_BIT, features);
+			netdev_feature_del(NETIF_F_HW_TLS_TX_BIT, *features);
 		}
 	}
 
-	if (netdev_feature_test(NETIF_F_HW_TLS_RX_BIT, features) &&
-	    !netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
+	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);
+		netdev_feature_del(NETIF_F_HW_TLS_RX_BIT, *features);
 	}
-
-	return features;
 }
 
 int __netdev_update_features(struct net_device *dev)
@@ -9729,17 +9719,17 @@ int __netdev_update_features(struct net_device *dev)
 
 	ASSERT_RTNL();
 
-	features = netdev_get_wanted_features(dev);
+	netdev_get_wanted_features(dev, &features);
 
 	if (dev->netdev_ops->ndo_fix_features)
 		features = dev->netdev_ops->ndo_fix_features(dev, features);
 
 	/* driver might be less strict about feature dependencies */
-	features = netdev_fix_features(dev, features);
+	netdev_fix_features(dev, &features);
 
 	/* some features can't be enabled if they're off on an upper device */
 	netdev_for_each_upper_dev_rcu(dev, upper, iter)
-		features = netdev_sync_upper_features(dev, upper, features);
+		netdev_sync_upper_features(dev, upper, &features);
 
 	if (netdev_active_features_equal(dev, features))
 		goto sync_lower;
@@ -9767,7 +9757,7 @@ int __netdev_update_features(struct net_device *dev)
 	 * on an upper device (think: bonding master or bridge)
 	 */
 	netdev_for_each_lower_dev(dev, lower, iter)
-		netdev_sync_lower_features(dev, lower, features);
+		netdev_sync_lower_features(dev, lower, &features);
 
 	if (!err) {
 		netdev_features_t diff;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index f349f13c8029..8885188e8e19 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -448,7 +448,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 	netdev_features_zero(feats);
 	/* Complete checksum if needed */
 	if (skb->ip_summed == CHECKSUM_PARTIAL &&
-	    (err = skb_csum_hwoffload_help(skb, feats)))
+	    (err = skb_csum_hwoffload_help(skb, &feats)))
 		goto out;
 
 	/* Older versions of OVS user space enforce alignment of the last
-- 
2.33.0


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

* [RFCv8 PATCH net-next 39/55] net: adjust the prototype of netdev_intersect_features()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (37 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 38/55] net: core: adjust prototype of several functions used in net/core/dev.c Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 40/55] net: adjust the prototype of netif_skb_features() Jian Shen
                   ` (17 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The fcuntion netdev_intersect_features() using netdev_features_t
as parameters, and returns netdev_features_t directly. For the
prototype of netdev_features_t will be extended to be larger than
8 bytes, so change the prototype of the function, change the
prototype of input features to 'netdev_features_t *', and return
the features pointer as output parameters.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  2 +-
 include/linux/netdev_feature_helpers.h        | 25 +++++++++++--------
 net/8021q/vlan_dev.c                          |  4 +--
 net/core/dev.c                                |  2 +-
 4 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 8a15ec010282..0ab4f1b5e547 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -248,7 +248,7 @@ nfp_repr_fix_features(struct net_device *netdev, netdev_features_t 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);
+	netdev_intersect_features(&features, &features, &lower_features);
 	tmp = NETIF_F_SOFT_FEATURES;
 	netdev_feature_add(NETIF_F_HW_TC_BIT, tmp);
 	netdev_features_mask(tmp, old_features);
diff --git a/include/linux/netdev_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index 60bc021648e4..a15bd3a3b574 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -697,21 +697,24 @@ static inline bool __netdev_features_subset(const netdev_features_t *feats1,
 #define netdev_gso_partial_features_clear_set(ndev, ...)		\
 	__netdev_gso_partial_features_clear_set(ndev, __UNIQUE_ID(feat_set), __VA_ARGS__)
 
-static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
-							  netdev_features_t f2)
+static inline void netdev_intersect_features(netdev_features_t *ret,
+					     const netdev_features_t *f1,
+					     const netdev_features_t *f2)
 {
-	netdev_features_t ret;
-
-	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);
+	netdev_features_t local_f1;
+	netdev_features_t local_f2;
+
+	netdev_features_copy(local_f1, *f1);
+	netdev_features_copy(local_f2, *f2);
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, local_f1) !=
+	    netdev_feature_test(NETIF_F_HW_CSUM_BIT, local_f2)) {
+		if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, local_f1))
+			netdev_features_set(local_f1, netdev_ip_csum_features);
 		else
-			netdev_features_set(f2, netdev_ip_csum_features);
+			netdev_features_set(local_f2, netdev_ip_csum_features);
 	}
 
-	netdev_features_and(ret, f1, f2);
-	return ret;
+	netdev_features_and(*ret, local_f1, local_f2);
 }
 
 static inline void
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 04588800df24..d03348e29f36 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -655,14 +655,14 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
 
 	tmp = real_dev->vlan_features;
 	netdev_feature_add(NETIF_F_RXCSUM_BIT, tmp);
-	lower_features = netdev_intersect_features(tmp, real_dev->features);
+	netdev_intersect_features(&lower_features, &tmp, &real_dev->features);
 
 	/* Add HW_CSUM setting to preserve user ability to control
 	 * checksum offload on the vlan device.
 	 */
 	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);
+	netdev_intersect_features(&features, &features, &lower_features);
 	netdev_features_or(tmp, NETIF_F_SOFT_FEATURES, NETIF_F_GSO_SOFTWARE);
 	netdev_features_mask(tmp, old_features);
 	netdev_features_set(features, tmp);
diff --git a/net/core/dev.c b/net/core/dev.c
index ac53e727d88f..e36347e0abe7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3565,7 +3565,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
 	if (skb_vlan_tagged(skb)) {
 		netdev_features_or(tmp, dev->vlan_features,
 				   netdev_tx_vlan_features);
-		features = netdev_intersect_features(features, tmp);
+		netdev_intersect_features(&features, &features, &tmp);
 	}
 
 	if (dev->netdev_ops->ndo_features_check)
-- 
2.33.0


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

* [RFCv8 PATCH net-next 40/55] net: adjust the prototype of netif_skb_features()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (38 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 39/55] net: adjust the prototype of netdev_intersect_features() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 41/55] net: adjust the prototype of xxx_features_check() Jian Shen
                   ` (16 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The fcuntion netif_skb_features() using netdev_features_t as
parameters, and returns netdev_features_t directly. For the
prototype of netdev_features_t will be extended to be larger
than 8 bytes, so change the prototype of the function, change
the prototype of input features to 'netdev_features_t *', and
return the features pointer as output parameters.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/xen-netfront.c |  4 +++-
 include/linux/netdevice.h  |  2 +-
 net/core/dev.c             | 22 +++++++++++-----------
 net/core/netpoll.c         |  2 +-
 net/ipv4/ip_output.c       |  2 +-
 net/ipv6/ip6_output.c      |  2 +-
 net/sched/sch_cake.c       |  3 ++-
 net/sched/sch_netem.c      |  3 ++-
 net/sched/sch_taprio.c     |  3 ++-
 net/sched/sch_tbf.c        |  3 ++-
 10 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index ace8ebaaaabf..fedbd35aa1c1 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -719,6 +719,7 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
 	struct netfront_queue *queue = NULL;
 	struct xennet_gnttab_make_txreq info = { };
 	unsigned int num_queues = dev->real_num_tx_queues;
+	netdev_features_t features;
 	u16 queue_index;
 	struct sk_buff *nskb;
 
@@ -773,9 +774,10 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
 
 	spin_lock_irqsave(&queue->tx_lock, flags);
 
+	netif_skb_features(skb, &features);
 	if (unlikely(!netif_carrier_ok(dev) ||
 		     (slots > 1 && !xennet_can_sg(dev)) ||
-		     netif_needs_gso(skb, netif_skb_features(skb)))) {
+		     netif_needs_gso(skb, features))) {
 		spin_unlock_irqrestore(&queue->tx_lock, flags);
 		goto drop;
 	}
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 68f950f5a36b..75a839cf5cd2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4915,7 +4915,7 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev,
 netdev_features_t passthru_features_check(struct sk_buff *skb,
 					  struct net_device *dev,
 					  netdev_features_t features);
-netdev_features_t netif_skb_features(struct sk_buff *skb);
+void netif_skb_features(struct sk_buff *skb, netdev_features_t *features);
 
 static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 {
diff --git a/net/core/dev.c b/net/core/dev.c
index e36347e0abe7..695b724a4054 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3546,36 +3546,36 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb,
 	return features;
 }
 
-netdev_features_t netif_skb_features(struct sk_buff *skb)
+void netif_skb_features(struct sk_buff *skb, netdev_features_t *features)
 {
 	struct net_device *dev = skb->dev;
-	netdev_features_t features = dev->features;
 	netdev_features_t tmp;
 
+	netdev_features_copy(*features, dev->features);
+
 	if (skb_is_gso(skb))
-		features = gso_features_check(skb, dev, features);
+		*features = gso_features_check(skb, dev, *features);
 
 	/* If encapsulation offload request, verify we are testing
 	 * hardware encapsulation features instead of standard
 	 * features for the netdev
 	 */
 	if (skb->encapsulation)
-		netdev_features_mask(features, dev->hw_enc_features);
+		netdev_features_mask(*features, dev->hw_enc_features);
 
 	if (skb_vlan_tagged(skb)) {
 		netdev_features_or(tmp, dev->vlan_features,
 				   netdev_tx_vlan_features);
-		netdev_intersect_features(&features, &features, &tmp);
+		netdev_intersect_features(features, features, &tmp);
 	}
 
 	if (dev->netdev_ops->ndo_features_check)
-		tmp = dev->netdev_ops->ndo_features_check(skb, dev, features);
+		tmp = dev->netdev_ops->ndo_features_check(skb, dev, *features);
 	else
-		tmp = dflt_features_check(skb, dev, features);
-	netdev_features_mask(features, tmp);
+		tmp = dflt_features_check(skb, dev, *features);
+	netdev_features_mask(*features, tmp);
 
-	harmonize_features(skb, &features);
-	return features;
+	harmonize_features(skb, features);
 }
 EXPORT_SYMBOL(netif_skb_features);
 
@@ -3659,7 +3659,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
 {
 	netdev_features_t features;
 
-	features = netif_skb_features(skb);
+	netif_skb_features(skb, &features);
 	skb = validate_xmit_vlan(skb, features);
 	if (unlikely(!skb))
 		goto out_null;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 9be762e1d042..94dd11aa1b83 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -77,7 +77,7 @@ static netdev_tx_t netpoll_start_xmit(struct sk_buff *skb,
 	netdev_tx_t status = NETDEV_TX_OK;
 	netdev_features_t features;
 
-	features = netif_skb_features(skb);
+	netif_skb_features(skb, &features);
 
 	if (skb_vlan_tag_present(skb) &&
 	    !vlan_hw_offload_capable(features, skb->vlan_proto)) {
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index e128d2957d3f..8e9993eae1a4 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -262,7 +262,7 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk,
 	 *    bridged to a NETIF_F_TSO tunnel stacked over an interface with an
 	 *    insufficient MTU.
 	 */
-	features = netif_skb_features(skb);
+	netif_skb_features(skb, &features);
 	BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_GSO_CB_OFFSET);
 	netdev_features_clear(features, NETIF_F_GSO_MASK);
 	segs = skb_gso_segment(skb, features);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 40ca76257ec1..0ac686957ab7 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -148,7 +148,7 @@ ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk,
 	 * describing the cases where GSO segment length exceeds the
 	 * egress MTU.
 	 */
-	features = netif_skb_features(skb);
+	netif_skb_features(skb, &features);
 	netdev_features_clear(features, NETIF_F_GSO_MASK);
 	segs = skb_gso_segment(skb, features);
 	if (IS_ERR_OR_NULL(segs)) {
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index 022fd85394e8..837efd4c786f 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -1740,9 +1740,10 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 
 	if (skb_is_gso(skb) && q->rate_flags & CAKE_FLAG_SPLIT_GSO) {
 		struct sk_buff *segs, *nskb;
-		netdev_features_t features = netif_skb_features(skb);
+		netdev_features_t features;
 		unsigned int slen = 0, numsegs = 0;
 
+		netif_skb_features(skb, &features);
 		netdev_features_clear(features, NETIF_F_GSO_MASK);
 		segs = skb_gso_segment(skb, features);
 		if (IS_ERR_OR_NULL(segs))
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 55084f0f2f57..cb253eb3a936 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -412,9 +412,10 @@ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
 static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch,
 				     struct sk_buff **to_free)
 {
+	netdev_features_t features;
 	struct sk_buff *segs;
-	netdev_features_t features = netif_skb_features(skb);
 
+	netif_skb_features(skb, &features);
 	netdev_features_clear(features, NETIF_F_GSO_MASK);
 	segs = skb_gso_segment(skb, features);
 
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index dc8b114388e2..96bff2fdeecb 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -459,10 +459,11 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 	 */
 	if (skb_is_gso(skb) && !FULL_OFFLOAD_IS_ENABLED(q->flags)) {
 		unsigned int slen = 0, numsegs = 0, len = qdisc_pkt_len(skb);
-		netdev_features_t features = netif_skb_features(skb);
 		struct sk_buff *segs, *nskb;
+		netdev_features_t features;
 		int ret;
 
+		netif_skb_features(skb, &features);
 		netdev_features_clear(features, NETIF_F_GSO_MASK);
 		segs = skb_gso_segment(skb, features);
 		if (IS_ERR_OR_NULL(segs))
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 5c883b639ed7..ce0bb68b02f3 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -207,10 +207,11 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
 {
 	struct tbf_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *segs, *nskb;
-	netdev_features_t features = netif_skb_features(skb);
+	netdev_features_t features;
 	unsigned int len = 0, prev_len = qdisc_pkt_len(skb);
 	int ret, nb;
 
+	netif_skb_features(skb, &features);
 	netdev_features_clear(features, NETIF_F_GSO_MASK);
 	segs = skb_gso_segment(skb, features);
 
-- 
2.33.0


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

* [RFCv8 PATCH net-next 41/55] net: adjust the prototype of xxx_features_check()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (39 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 40/55] net: adjust the prototype of netif_skb_features() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 42/55] net: adjust the prototype of ndo_fix_features Jian Shen
                   ` (15 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function net_device_ops.ndo_features_check() using
netdev_features_t as parameters, and returns netdev_features_t
directly. For the prototype of netdev_features_t will be extended
to be larger than 8 bytes, so change the prototype of the function,
 change the prototype of input features to'netdev_features_t *',
and return the features pointer as output parameter. So changes
all the implement for this function of all the netdev drivers, and
relative functions.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/3com/typhoon.c           | 12 +++---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      | 11 ++---
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  | 11 +++--
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 16 ++++----
 drivers/net/ethernet/cadence/macb_main.c      | 16 ++++----
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   | 12 +++---
 drivers/net/ethernet/cisco/enic/enic_main.c   | 14 +++----
 drivers/net/ethernet/emulex/benet/be_main.c   | 21 +++++-----
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   | 11 ++---
 drivers/net/ethernet/ibm/ibmvnic.c            |  9 ++---
 .../net/ethernet/intel/fm10k/fm10k_netdev.c   | 10 ++---
 drivers/net/ethernet/intel/i40e/i40e_main.c   | 14 +++----
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 14 +++----
 drivers/net/ethernet/intel/ice/ice_main.c     | 13 +++---
 drivers/net/ethernet/intel/igb/igb_main.c     | 18 ++++-----
 drivers/net/ethernet/intel/igbvf/netdev.c     | 18 ++++-----
 drivers/net/ethernet/intel/igc/igc_main.c     | 18 ++++-----
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 18 ++++-----
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 18 ++++-----
 .../net/ethernet/mellanox/mlx4/en_netdev.c    | 13 +++---
 drivers/net/ethernet/mellanox/mlx5/core/en.h  |  5 +--
 .../mellanox/mlx5/core/en_accel/ipsec_rxtx.h  | 16 ++++----
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 37 ++++++++---------
 .../ethernet/netronome/nfp/nfp_net_common.c   | 22 +++++-----
 drivers/net/ethernet/qlogic/qede/qede.h       |  5 +--
 drivers/net/ethernet/qlogic/qede/qede_fp.c    | 17 ++++----
 .../net/ethernet/qlogic/qlcnic/qlcnic_main.c  |  9 ++---
 drivers/net/ethernet/realtek/8139cp.c         |  9 ++---
 drivers/net/ethernet/realtek/r8169_main.c     | 28 ++++++-------
 drivers/net/ethernet/sfc/efx_common.c         | 13 +++---
 drivers/net/ethernet/sfc/efx_common.h         |  4 +-
 drivers/net/ethernet/sfc/siena/efx_common.c   | 14 +++----
 drivers/net/ethernet/sfc/siena/efx_common.h   |  5 +--
 drivers/net/usb/lan78xx.c                     | 14 +++----
 drivers/net/usb/r8152.c                       | 10 ++---
 drivers/net/vmxnet3/vmxnet3_ethtool.c         | 18 ++++-----
 drivers/net/vmxnet3/vmxnet3_int.h             |  4 +-
 drivers/s390/net/qeth_core.h                  |  5 +--
 drivers/s390/net/qeth_core_main.c             | 17 ++++----
 drivers/s390/net/qeth_l3_main.c               | 10 ++---
 include/linux/if_vlan.h                       | 13 +++---
 include/linux/netdevice.h                     |  9 ++---
 include/net/vxlan.h                           | 16 ++++----
 net/core/dev.c                                | 40 ++++++++-----------
 44 files changed, 272 insertions(+), 355 deletions(-)

diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index 6fb1efbe674f..694400423285 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -2261,15 +2261,15 @@ typhoon_test_mmio(struct pci_dev *pdev)
 
 #include <net/vxlan.h>
 
-static netdev_features_t typhoon_features_check(struct sk_buff *skb,
-						struct net_device *dev,
-						netdev_features_t features)
+static void typhoon_features_check(struct sk_buff *skb,
+				   struct net_device *dev,
+				   netdev_features_t *features)
 {
 	if (skb_shinfo(skb)->nr_frags > 32 && skb_is_gso(skb))
-		netdev_features_clear(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);
+	vlan_features_check(skb, features);
+	vxlan_features_check(skb, features);
 }
 #endif
 
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 92e722c356e0..5ecd0904aacc 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2268,14 +2268,11 @@ static int xgbe_set_features(struct net_device *netdev,
 	return 0;
 }
 
-static netdev_features_t xgbe_features_check(struct sk_buff *skb,
-					     struct net_device *netdev,
-					     netdev_features_t features)
+static void xgbe_features_check(struct sk_buff *skb, struct net_device *netdev,
+				netdev_features_t *features)
 {
-	features = vlan_features_check(skb, features);
-	features = vxlan_features_check(skb, features);
-
-	return features;
+	vlan_features_check(skb, features);
+	vxlan_features_check(skb, features);
 }
 
 static const struct net_device_ops xgbe_netdev_ops = {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 2a3b18665054..13055ba8b443 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12854,9 +12854,8 @@ static int bnx2x_get_phys_port_id(struct net_device *netdev,
 	return 0;
 }
 
-static netdev_features_t bnx2x_features_check(struct sk_buff *skb,
-					      struct net_device *dev,
-					      netdev_features_t features)
+static void bnx2x_features_check(struct sk_buff *skb, struct net_device *dev,
+				 netdev_features_t *features)
 {
 	/*
 	 * A skb with gso_size + header length > 9700 will cause a
@@ -12874,10 +12873,10 @@ 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)))
-		netdev_features_clear(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);
+	vlan_features_check(skb, features);
+	vxlan_features_check(skb, features);
 }
 
 static int __bnx2x_vlan_configure_vid(struct bnx2x *bp, u16 vid, bool add)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index e8ccccb07045..97a108fdf693 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11370,32 +11370,30 @@ static bool bnxt_tunl_check(struct bnxt *bp, struct sk_buff *skb, u8 l4_proto)
 	return false;
 }
 
-static netdev_features_t bnxt_features_check(struct sk_buff *skb,
-					     struct net_device *dev,
-					     netdev_features_t features)
+static void bnxt_features_check(struct sk_buff *skb, struct net_device *dev,
+				netdev_features_t *features)
 {
 	struct bnxt *bp = netdev_priv(dev);
 	u8 *l4_proto;
 
-	features = vlan_features_check(skb, features);
+	vlan_features_check(skb, features);
 	switch (vlan_get_protocol(skb)) {
 	case htons(ETH_P_IP):
 		if (!skb->encapsulation)
-			return features;
+			return;
 		l4_proto = &ip_hdr(skb)->protocol;
 		if (bnxt_tunl_check(bp, skb, *l4_proto))
-			return features;
+			return;
 		break;
 	case htons(ETH_P_IPV6):
 		if (!bnxt_exthdr_check(bp, skb, skb_network_offset(skb),
 				       &l4_proto))
 			break;
 		if (!l4_proto || bnxt_tunl_check(bp, skb, *l4_proto))
-			return features;
+			return;
 		break;
 	}
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*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/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 31b258a47077..7b49abf30def 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -2128,9 +2128,8 @@ static unsigned int macb_tx_map(struct macb *bp,
 	return 0;
 }
 
-static netdev_features_t macb_features_check(struct sk_buff *skb,
-					     struct net_device *dev,
-					     netdev_features_t features)
+static void macb_features_check(struct sk_buff *skb, struct net_device *dev,
+				netdev_features_t *features)
 {
 	unsigned int nr_frags, f;
 	unsigned int hdrlen;
@@ -2139,7 +2138,7 @@ static netdev_features_t macb_features_check(struct sk_buff *skb,
 
 	/* there is only one buffer or protocol is not UDP */
 	if (!skb_is_nonlinear(skb) || (ip_hdr(skb)->protocol != IPPROTO_UDP))
-		return features;
+		return;
 
 	/* length of header */
 	hdrlen = skb_transport_offset(skb);
@@ -2149,8 +2148,8 @@ 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)) {
-		netdev_feature_del(NETIF_F_TSO_BIT, features);
-		return features;
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
+		return;
 	}
 
 	nr_frags = skb_shinfo(skb)->nr_frags;
@@ -2160,11 +2159,10 @@ 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)) {
-			netdev_feature_del(NETIF_F_TSO_BIT, features);
-			return features;
+			netdev_feature_del(NETIF_F_TSO_BIT, *features);
+			return;
 		}
 	}
-	return features;
 }
 
 static inline int macb_clear_csum(struct sk_buff *skb)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index a4b06645861a..08ce0b730ec4 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3841,23 +3841,21 @@ static const struct udp_tunnel_nic_info cxgb_udp_tunnels = {
 	},
 };
 
-static netdev_features_t cxgb_features_check(struct sk_buff *skb,
-					     struct net_device *dev,
-					     netdev_features_t features)
+static void cxgb_features_check(struct sk_buff *skb, struct net_device *dev,
+				netdev_features_t *features)
 {
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
 
 	if (CHELSIO_CHIP_VERSION(adapter->params.chip) < CHELSIO_T6)
-		return features;
+		return;
 
 	/* Check if hw supports offload for this packet */
 	if (!skb->encapsulation || cxgb_encap_offload_supported(skb))
-		return features;
+		return;
 
 	/* Offload is not supported for this encapsulated packet */
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*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 9ad7c5b0734a..1b737b940a00 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -241,9 +241,8 @@ static const struct udp_tunnel_nic_info enic_udp_tunnels = {
 	},
 };
 
-static netdev_features_t enic_features_check(struct sk_buff *skb,
-					     struct net_device *dev,
-					     netdev_features_t features)
+static void enic_features_check(struct sk_buff *skb, struct net_device *dev,
+				netdev_features_t *features)
 {
 	const struct ethhdr *eth = (struct ethhdr *)skb_inner_mac_header(skb);
 	struct enic *enic = netdev_priv(dev);
@@ -252,9 +251,9 @@ static netdev_features_t enic_features_check(struct sk_buff *skb,
 	u8 proto;
 
 	if (!skb->encapsulation)
-		return features;
+		return;
 
-	features = vxlan_features_check(skb, features);
+	vxlan_features_check(skb, features);
 
 	switch (vlan_get_protocol(skb)) {
 	case htons(ETH_P_IPV6):
@@ -292,11 +291,10 @@ static netdev_features_t enic_features_check(struct sk_buff *skb,
 	if (port  != enic->vxlan.vxlan_udp_port_number)
 		goto out;
 
-	return features;
+	return;
 
 out:
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*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 6ea623d6ddf4..f254f11d135a 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5065,9 +5065,8 @@ static struct be_cmd_work *be_alloc_work(struct be_adapter *adapter,
 	return work;
 }
 
-static netdev_features_t be_features_check(struct sk_buff *skb,
-					   struct net_device *dev,
-					   netdev_features_t features)
+static void be_features_check(struct sk_buff *skb, struct net_device *dev,
+			      netdev_features_t *features)
 {
 	struct be_adapter *adapter = netdev_priv(dev);
 	u8 l4_hdr = 0;
@@ -5077,7 +5076,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))
-			netdev_feature_del(NETIF_F_TSO6_BIT, features);
+			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
@@ -5086,17 +5085,17 @@ 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))
-			netdev_features_clear(features, NETIF_F_GSO_MASK);
+			netdev_features_clear(*features, NETIF_F_GSO_MASK);
 	}
 
 	/* The code below restricts offload features for some tunneled and
 	 * Q-in-Q packets.
 	 * Offload features for normal (non tunnel) packets are unchanged.
 	 */
-	features = vlan_features_check(skb, features);
+	vlan_features_check(skb, features);
 	if (!skb->encapsulation ||
 	    !(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS))
-		return features;
+		return;
 
 	/* It's an encapsulated packet and VxLAN offloads are enabled. We
 	 * should disable tunnel offload features if it's not a VxLAN packet,
@@ -5112,7 +5111,7 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
 		l4_hdr = ipv6_hdr(skb)->nexthdr;
 		break;
 	default:
-		return features;
+		return;
 	}
 
 	if (l4_hdr != IPPROTO_UDP ||
@@ -5122,11 +5121,9 @@ 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) {
-		netdev_features_clear(features, netdev_csum_gso_features_mask);
-		return features;
+		netdev_features_clear(*features, netdev_csum_gso_features_mask);
+		return;
 	}
-
-	return features;
 }
 
 static int be_get_phys_port_id(struct net_device *dev,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index b098d070deef..06c79b7cbb23 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2457,9 +2457,8 @@ static int hns3_nic_set_features(struct net_device *netdev,
 	return 0;
 }
 
-static netdev_features_t hns3_features_check(struct sk_buff *skb,
-					     struct net_device *dev,
-					     netdev_features_t features)
+static void hns3_features_check(struct sk_buff *skb, struct net_device *dev,
+				netdev_features_t *features)
 {
 #define HNS3_MAX_HDR_LEN	480U
 #define HNS3_MAX_L4_HDR_LEN	60U
@@ -2467,7 +2466,7 @@ static netdev_features_t hns3_features_check(struct sk_buff *skb,
 	size_t len;
 
 	if (skb->ip_summed != CHECKSUM_PARTIAL)
-		return features;
+		return;
 
 	if (skb->encapsulation)
 		len = skb_inner_transport_header(skb) - skb->data;
@@ -2483,10 +2482,8 @@ static netdev_features_t hns3_features_check(struct sk_buff *skb,
 	 * len of 480 bytes.
 	 */
 	if (len > HNS3_MAX_HDR_LEN)
-		netdev_features_clear(features,
+		netdev_features_clear(*features,
 				      netdev_csum_gso_features_mask);
-
-	return features;
 }
 
 static void hns3_fetch_stats(struct rtnl_link_stats64 *stats,
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 6f84086ddfe2..afef066f0647 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -3324,9 +3324,8 @@ static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu)
 	return wait_for_reset(adapter);
 }
 
-static netdev_features_t ibmvnic_features_check(struct sk_buff *skb,
-						struct net_device *dev,
-						netdev_features_t features)
+static void ibmvnic_features_check(struct sk_buff *skb, struct net_device *dev,
+				   netdev_features_t *features)
 {
 	/* Some backing hardware adapters can not
 	 * handle packets with a MSS less than 224
@@ -3335,10 +3334,8 @@ 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)
-			netdev_features_clear(features, NETIF_F_GSO_MASK);
+			netdev_features_clear(*features, NETIF_F_GSO_MASK);
 	}
-
-	return features;
 }
 
 static const struct net_device_ops ibmvnic_netdev_ops = {
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index da65c5487599..2162a2d7f3f5 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1505,15 +1505,13 @@ static void fm10k_dfwd_del_station(struct net_device *dev, void *priv)
 	}
 }
 
-static netdev_features_t fm10k_features_check(struct sk_buff *skb,
-					      struct net_device *dev,
-					      netdev_features_t features)
+static void fm10k_features_check(struct sk_buff *skb, struct net_device *dev,
+				 netdev_features_t *features)
 {
 	if (!skb->encapsulation || fm10k_tx_encap_offload(skb))
-		return features;
+		return;
 
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*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 0f2cfb6e9ce9..3bf454f234a4 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13189,9 +13189,8 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
  * @dev: This physical port's netdev
  * @features: Offload features that the stack believes apply
  **/
-static netdev_features_t i40e_features_check(struct sk_buff *skb,
-					     struct net_device *dev,
-					     netdev_features_t features)
+static void i40e_features_check(struct sk_buff *skb, struct net_device *dev,
+				netdev_features_t *features)
 {
 	size_t len;
 
@@ -13200,13 +13199,13 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
 	 * checking for CHECKSUM_PARTIAL
 	 */
 	if (skb->ip_summed != CHECKSUM_PARTIAL)
-		return features;
+		return;
 
 	/* We cannot support GSO if the MSS is going to be less than
 	 * 64 bytes.  If it is then we need to drop support for GSO.
 	 */
 	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
-		netdev_features_clear(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;
@@ -13236,10 +13235,9 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
 	 * by TCP, which is at most 15 dwords
 	 */
 
-	return features;
+	return;
 out_err:
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*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 2cc85f1a81df..9b9873d62687 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4386,9 +4386,8 @@ static int iavf_set_features(struct net_device *netdev,
  * @dev: This physical port's netdev
  * @features: Offload features that the stack believes apply
  **/
-static netdev_features_t iavf_features_check(struct sk_buff *skb,
-					     struct net_device *dev,
-					     netdev_features_t features)
+static void iavf_features_check(struct sk_buff *skb, struct net_device *dev,
+				netdev_features_t *features)
 {
 	size_t len;
 
@@ -4397,13 +4396,13 @@ static netdev_features_t iavf_features_check(struct sk_buff *skb,
 	 * checking for CHECKSUM_PARTIAL
 	 */
 	if (skb->ip_summed != CHECKSUM_PARTIAL)
-		return features;
+		return;
 
 	/* We cannot support GSO if the MSS is going to be less than
 	 * 64 bytes.  If it is then we need to drop support for GSO.
 	 */
 	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
-		netdev_features_clear(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;
@@ -4433,10 +4432,9 @@ static netdev_features_t iavf_features_check(struct sk_buff *skb,
 	 * by TCP, which is at most 15 dwords
 	 */
 
-	return features;
+	return;
 out_err:
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*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 b69357c220d9..105f49eaec4d 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -9013,10 +9013,10 @@ int ice_stop(struct net_device *netdev)
  * @netdev: This port's netdev
  * @features: Offload features that the stack believes apply
  */
-static netdev_features_t
+static void
 ice_features_check(struct sk_buff *skb,
 		   struct net_device __always_unused *netdev,
-		   netdev_features_t features)
+		   netdev_features_t *features)
 {
 	bool gso = skb_is_gso(skb);
 	size_t len;
@@ -9026,13 +9026,13 @@ ice_features_check(struct sk_buff *skb,
 	 * checking for CHECKSUM_PARTIAL
 	 */
 	if (skb->ip_summed != CHECKSUM_PARTIAL)
-		return features;
+		return;
 
 	/* We cannot support GSO if the MSS is going to be less than
 	 * 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))
-		netdev_features_clear(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)
@@ -9061,10 +9061,9 @@ ice_features_check(struct sk_buff *skb,
 			goto out_rm_features;
 	}
 
-	return features;
+	return;
 out_rm_features:
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*features, netdev_csum_gso_features_mask);
 }
 
 static const struct net_device_ops ice_netdev_safe_mode_ops = {
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 01af57d888c3..05da0d2cc21f 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2506,43 +2506,43 @@ static int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 #define IGB_MAX_MAC_HDR_LEN	127
 #define IGB_MAX_NETWORK_HDR_LEN	511
 
-static netdev_features_t
+static void
 igb_features_check(struct sk_buff *skb, struct net_device *dev,
-		   netdev_features_t features)
+		   netdev_features_t *features)
 {
 	unsigned int network_hdr_len, mac_hdr_len;
 
 	/* 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)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  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);
-		return features;
+		return;
 	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
 	if (unlikely(network_hdr_len >  IGB_MAX_NETWORK_HDR_LEN)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  NETIF_F_HW_CSUM_BIT,
 					  NETIF_F_SCTP_CRC_BIT,
 					  NETIF_F_GSO_UDP_L4_BIT,
 					  NETIF_F_TSO_BIT,
 					  NETIF_F_TSO6_BIT);
-		return features;
+		return;
 	}
 
 	/* 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 && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features))
-		netdev_feature_del(NETIF_F_TSO_BIT, features);
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, *features))
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
 
-	return features;
+	return;
 }
 
 static void igb_offload_apply(struct igb_adapter *adapter, s32 queue)
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 00cdc7432d85..11e8496236a6 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2619,41 +2619,39 @@ static int igbvf_set_features(struct net_device *netdev,
 #define IGBVF_MAX_MAC_HDR_LEN		127
 #define IGBVF_MAX_NETWORK_HDR_LEN	511
 
-static netdev_features_t
+static void
 igbvf_features_check(struct sk_buff *skb, struct net_device *dev,
-		     netdev_features_t features)
+		     netdev_features_t *features)
 {
 	unsigned int network_hdr_len, mac_hdr_len;
 
 	/* 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)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  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);
-		return features;
+		return;
 	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
 	if (unlikely(network_hdr_len >  IGBVF_MAX_NETWORK_HDR_LEN)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  NETIF_F_HW_CSUM_BIT,
 					  NETIF_F_SCTP_CRC_BIT,
 					  NETIF_F_TSO_BIT,
 					  NETIF_F_TSO6_BIT);
-		return features;
+		return;
 	}
 
 	/* 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 && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features))
-		netdev_feature_del(NETIF_F_TSO_BIT, features);
-
-	return features;
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, *features))
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
 }
 
 static const struct net_device_ops igbvf_netdev_ops = {
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 67849c8d1877..83a5f3ed7cd6 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -5014,41 +5014,39 @@ static int igc_set_features(struct net_device *netdev,
 	return 1;
 }
 
-static netdev_features_t
+static void
 igc_features_check(struct sk_buff *skb, struct net_device *dev,
-		   netdev_features_t features)
+		   netdev_features_t *features)
 {
 	unsigned int network_hdr_len, mac_hdr_len;
 
 	/* 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)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  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);
-		return features;
+		return;
 	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
 	if (unlikely(network_hdr_len >  IGC_MAX_NETWORK_HDR_LEN)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  NETIF_F_HW_CSUM_BIT,
 					  NETIF_F_SCTP_CRC_BIT,
 					  NETIF_F_TSO_BIT,
 					  NETIF_F_TSO6_BIT);
-		return features;
+		return;
 	}
 
 	/* 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 && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features))
-		netdev_feature_del(NETIF_F_TSO_BIT, features);
-
-	return features;
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, *features))
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
 }
 
 static void igc_tsync_interrupt(struct igc_adapter *adapter)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index f3b1d4777c3f..731ac302cf8e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -10219,34 +10219,34 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
 #define IXGBE_MAX_MAC_HDR_LEN		127
 #define IXGBE_MAX_NETWORK_HDR_LEN	511
 
-static netdev_features_t
+static void
 ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
-		     netdev_features_t features)
+		     netdev_features_t *features)
 {
 	unsigned int network_hdr_len, mac_hdr_len;
 
 	/* 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)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  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);
-		return features;
+		return;
 	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
 	if (unlikely(network_hdr_len >  IXGBE_MAX_NETWORK_HDR_LEN)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  NETIF_F_HW_CSUM_BIT,
 					  NETIF_F_SCTP_CRC_BIT,
 					  NETIF_F_GSO_UDP_L4_BIT,
 					  NETIF_F_TSO_BIT,
 					  NETIF_F_TSO6_BIT);
-		return features;
+		return;
 	}
 
 	/* We can only support IPV4 TSO in tunnels if we can mangle the
@@ -10254,14 +10254,12 @@ 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 && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features)) {
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, *features)) {
 #ifdef CONFIG_IXGBE_IPSEC
 		if (!secpath_exists(skb))
 #endif
-			netdev_feature_del(NETIF_F_TSO_BIT, features);
+			netdev_feature_del(NETIF_F_TSO_BIT, *features);
 	}
-
-	return features;
 }
 
 static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 50b920ae83e1..5078d723251f 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4400,41 +4400,39 @@ static void ixgbevf_get_stats(struct net_device *netdev,
 #define IXGBEVF_MAX_MAC_HDR_LEN		127
 #define IXGBEVF_MAX_NETWORK_HDR_LEN	511
 
-static netdev_features_t
+static void
 ixgbevf_features_check(struct sk_buff *skb, struct net_device *dev,
-		       netdev_features_t features)
+		       netdev_features_t *features)
 {
 	unsigned int network_hdr_len, mac_hdr_len;
 
 	/* 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)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  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);
-		return features;
+		return;
 	}
 
 	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
 	if (unlikely(network_hdr_len >  IXGBEVF_MAX_NETWORK_HDR_LEN)) {
-		netdev_features_clear_set(features,
+		netdev_features_clear_set(*features,
 					  NETIF_F_HW_CSUM_BIT,
 					  NETIF_F_SCTP_CRC_BIT,
 					  NETIF_F_TSO_BIT,
 					  NETIF_F_TSO6_BIT);
-		return features;
+		return;
 	}
 
 	/* 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 && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, features))
-		netdev_feature_del(NETIF_F_TSO_BIT, features);
-
-	return features;
+	if (skb->encapsulation && !netdev_feature_test(NETIF_F_TSO_MANGLEID_BIT, *features))
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
 }
 
 static int ixgbevf_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index a7e3ec4f034d..7cec4a97a3a1 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2677,12 +2677,11 @@ static const struct udp_tunnel_nic_info mlx4_udp_tunnels = {
 	},
 };
 
-static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
-						struct net_device *dev,
-						netdev_features_t features)
+static void mlx4_en_features_check(struct sk_buff *skb, struct net_device *dev,
+				   netdev_features_t *features)
 {
-	features = vlan_features_check(skb, features);
-	features = vxlan_features_check(skb, features);
+	vlan_features_check(skb, features);
+	vxlan_features_check(skb, features);
 
 	/* The ConnectX-3 doesn't support outer IPv6 checksums but it does
 	 * support inner IPv6 checksums and segmentation so  we need to
@@ -2695,11 +2694,9 @@ 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))
-			netdev_features_clear(features,
+			netdev_features_clear(*features,
 					      netdev_csum_gso_features_mask);
 	}
-
-	return features;
 }
 
 static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 maxrate)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 841e4fb520d7..c2dc487ac760 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -1240,9 +1240,8 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16
 void mlx5e_rx_dim_work(struct work_struct *work);
 void mlx5e_tx_dim_work(struct work_struct *work);
 
-netdev_features_t mlx5e_features_check(struct sk_buff *skb,
-				       struct net_device *netdev,
-				       netdev_features_t features);
+void mlx5e_features_check(struct sk_buff *skb, struct net_device *netdev,
+			  netdev_features_t *features);
 int mlx5e_set_features(struct net_device *netdev, netdev_features_t features);
 #ifdef CONFIG_MLX5_ESWITCH
 int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac);
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 6f83eb46d18a..c3ad54f56de6 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
@@ -90,8 +90,8 @@ static inline bool mlx5e_ipsec_eseg_meta(struct mlx5_wqe_eth_seg *eseg)
 void mlx5e_ipsec_tx_build_eseg(struct mlx5e_priv *priv, struct sk_buff *skb,
 			       struct mlx5_wqe_eth_seg *eseg);
 
-static inline netdev_features_t
-mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features)
+static inline void
+mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t *features)
 {
 	struct xfrm_offload *xo = xfrm_offload(skb);
 	struct sec_path *sp = skb_sec_path(skb);
@@ -115,14 +115,13 @@ mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features)
 				goto out_disable;
 		}
 
-		return features;
+		return;
 
 	}
 
 	/* Disable CSUM and GSO for software IPsec */
 out_disable:
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*features, netdev_csum_gso_features_mask);
 }
 
 static inline bool
@@ -160,11 +159,10 @@ 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)
+static inline void
+mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t *features)
 {
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*features, netdev_csum_gso_features_mask);
 }
 
 static inline bool
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 7d9f8863d921..7a7679262252 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4423,9 +4423,9 @@ static bool mlx5e_gre_tunnel_inner_proto_offload_supported(struct mlx5_core_dev
 	return false;
 }
 
-static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
-						     struct sk_buff *skb,
-						     netdev_features_t features)
+static void mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
+					struct sk_buff *skb,
+					netdev_features_t *features)
 {
 	unsigned int offset = 0;
 	struct udphdr *udph;
@@ -4446,12 +4446,12 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
 	switch (proto) {
 	case IPPROTO_GRE:
 		if (mlx5e_gre_tunnel_inner_proto_offload_supported(priv->mdev, skb))
-			return features;
+			return;
 		break;
 	case IPPROTO_IPIP:
 	case IPPROTO_IPV6:
 		if (mlx5e_tunnel_proto_supported_tx(priv->mdev, IPPROTO_IPIP))
-			return features;
+			return;
 		break;
 	case IPPROTO_UDP:
 		udph = udp_hdr(skb);
@@ -4459,42 +4459,39 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
 
 		/* Verify if UDP port is being offloaded by HW */
 		if (mlx5_vxlan_lookup_port(priv->mdev->vxlan, port))
-			return features;
+			return;
 
 #if IS_ENABLED(CONFIG_GENEVE)
 		/* Support Geneve offload for default UDP port */
 		if (port == GENEVE_UDP_PORT && mlx5_geneve_tx_allowed(priv->mdev))
-			return features;
+			return;
 #endif
 		break;
 #ifdef CONFIG_MLX5_EN_IPSEC
 	case IPPROTO_ESP:
-		return mlx5e_ipsec_feature_check(skb, features);
+		mlx5e_ipsec_feature_check(skb, features);
+		return;
 #endif
 	}
 
 out:
 	/* Disable CSUM and GSO if the udp dport is not offloaded by HW */
-	netdev_features_clear(features, netdev_csum_gso_features_mask);
-	return features;
+	netdev_features_clear(*features, netdev_csum_gso_features_mask);
 }
 
-netdev_features_t mlx5e_features_check(struct sk_buff *skb,
-				       struct net_device *netdev,
-				       netdev_features_t features)
+void mlx5e_features_check(struct sk_buff *skb, struct net_device *netdev,
+			  netdev_features_t *features)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 
-	features = vlan_features_check(skb, features);
-	features = vxlan_features_check(skb, features);
+	vlan_features_check(skb, features);
+	vxlan_features_check(skb, features);
 
 	/* Validate if the tunneled packet is being offloaded by HW */
 	if (skb->encapsulation &&
-	    (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;
+	    (netdev_features_intersects(*features, NETIF_F_CSUM_MASK) ||
+	     netdev_features_intersects(*features, NETIF_F_GSO_MASK)))
+		mlx5e_tunnel_features_check(priv, skb, features);
 }
 
 static void mlx5e_tx_timeout_work(struct work_struct *work)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index e2ae7c147e45..164fbeaa1ca4 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1781,19 +1781,17 @@ nfp_net_fix_features(struct net_device *netdev,
 	return features;
 }
 
-static netdev_features_t
+static void
 nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
-		       netdev_features_t features)
+		       netdev_features_t *features)
 {
-	netdev_features_t feats;
 	u8 l4_hdr;
 
 	/* We can't do TSO over double tagged packets (802.1AD) */
-	feats = vlan_features_check(skb, features);
-	netdev_features_mask(features, feats);
+	vlan_features_check(skb, features);
 
 	if (!skb->encapsulation)
-		return features;
+		return;
 
 	/* Ensure that inner L4 header offset fits into TX descriptor field */
 	if (skb_is_gso(skb)) {
@@ -1805,7 +1803,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))
-			netdev_features_clear(features, NETIF_F_GSO_MASK);
+			netdev_features_clear(*features, NETIF_F_GSO_MASK);
 	}
 
 	/* VXLAN/GRE check */
@@ -1817,8 +1815,8 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
 		l4_hdr = ipv6_hdr(skb)->nexthdr;
 		break;
 	default:
-		netdev_features_clear(features, netdev_csum_gso_features_mask);
-		return features;
+		netdev_features_clear(*features, netdev_csum_gso_features_mask);
+		return;
 	}
 
 	if (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
@@ -1827,11 +1825,9 @@ 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)))) {
-		netdev_features_clear(features, netdev_csum_gso_features_mask);
-		return features;
+		netdev_features_clear(*features, netdev_csum_gso_features_mask);
+		return;
 	}
-
-	return features;
 }
 
 static int
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index f90dcfe9ee68..c1f26a2e374d 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -527,9 +527,8 @@ int qede_xdp_transmit(struct net_device *dev, int n_frames,
 		      struct xdp_frame **frames, u32 flags);
 u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
 		      struct net_device *sb_dev);
-netdev_features_t qede_features_check(struct sk_buff *skb,
-				      struct net_device *dev,
-				      netdev_features_t features);
+void qede_features_check(struct sk_buff *skb, struct net_device *dev,
+			 netdev_features_t *features);
 int qede_alloc_rx_buffer(struct qede_rx_queue *rxq, bool allow_lazy);
 int qede_free_tx_pkt(struct qede_dev *edev,
 		     struct qede_tx_queue *txq, int *len);
diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c
index 2bbbc7591965..c947b91c42b1 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -1756,9 +1756,8 @@ u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
 /* 8B udp header + 8B base tunnel header + 32B option length */
 #define QEDE_MAX_TUN_HDR_LEN 48
 
-netdev_features_t qede_features_check(struct sk_buff *skb,
-				      struct net_device *dev,
-				      netdev_features_t features)
+void qede_features_check(struct sk_buff *skb, struct net_device *dev,
+			 netdev_features_t *features)
 {
 	if (skb->encapsulation) {
 		u8 l4_proto = 0;
@@ -1771,7 +1770,7 @@ netdev_features_t qede_features_check(struct sk_buff *skb,
 			l4_proto = ipv6_hdr(skb)->nexthdr;
 			break;
 		default:
-			return features;
+			return;
 		}
 
 		/* Disable offloads for geneve tunnels, as HW can't parse
@@ -1790,19 +1789,17 @@ 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)) {
-				netdev_features_clear(features,
+				netdev_features_clear(*features,
 						      netdev_csum_gso_features_mask);
-				return features;
+				return;
 			}
 		} 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.
 			 */
-			netdev_features_clear(features,
+			netdev_features_clear(*features,
 					      netdev_csum_gso_features_mask);
-			return features;
+			return;
 		}
 	}
-
-	return features;
 }
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 3115a942a865..94b5b96ad9fb 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -494,12 +494,11 @@ static const struct udp_tunnel_nic_info qlcnic_udp_tunnels = {
 	},
 };
 
-static netdev_features_t qlcnic_features_check(struct sk_buff *skb,
-					       struct net_device *dev,
-					       netdev_features_t features)
+static void qlcnic_features_check(struct sk_buff *skb, struct net_device *dev,
+				  netdev_features_t *features)
 {
-	features = vlan_features_check(skb, features);
-	return vxlan_features_check(skb, features);
+	vlan_features_check(skb, features);
+	vxlan_features_check(skb, features);
 }
 
 static const struct net_device_ops qlcnic_netdev_ops = {
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 56c9e0627577..65dd210b0b25 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1858,14 +1858,13 @@ static void cp_set_d3_state (struct cp_private *cp)
 	pci_set_power_state (cp->pdev, PCI_D3hot);
 }
 
-static netdev_features_t cp_features_check(struct sk_buff *skb,
-					   struct net_device *dev,
-					   netdev_features_t features)
+static void cp_features_check(struct sk_buff *skb, struct net_device *dev,
+			      netdev_features_t *features)
 {
 	if (skb_shinfo(skb)->gso_size > MSSMask)
-		netdev_feature_del(NETIF_F_TSO_BIT, features);
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
 
-	return vlan_features_check(skb, features);
+	vlan_features_check(skb, features);
 }
 static const struct net_device_ops cp_netdev_ops = {
 	.ndo_open		= cp_open,
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 81d7a4eb2a5a..7434f3c06dc6 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -4264,52 +4264,48 @@ static unsigned int rtl_last_frag_len(struct sk_buff *skb)
 }
 
 /* Workaround for hw issues with TSO on RTL8168evl */
-static netdev_features_t rtl8168evl_fix_tso(struct sk_buff *skb,
-					    netdev_features_t features)
+static void rtl8168evl_fix_tso(struct sk_buff *skb, netdev_features_t *features)
 {
 	/* IPv4 header has options field */
 	if (vlan_get_protocol(skb) == htons(ETH_P_IP) &&
 	    ip_hdrlen(skb) > sizeof(struct iphdr))
-		netdev_features_clear(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))
-		netdev_features_clear(features, NETIF_F_ALL_TSO);
+		netdev_features_clear(*features, NETIF_F_ALL_TSO);
 
 	else if (rtl_last_frag_len(skb) <= 6)
-		netdev_features_clear(features, NETIF_F_ALL_TSO);
-
-	return features;
+		netdev_features_clear(*features, NETIF_F_ALL_TSO);
 }
 
-static netdev_features_t rtl8169_features_check(struct sk_buff *skb,
-						struct net_device *dev,
-						netdev_features_t features)
+static void rtl8169_features_check(struct sk_buff *skb, struct net_device *dev,
+				   netdev_features_t *features)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 
 	if (skb_is_gso(skb)) {
 		if (tp->mac_version == RTL_GIGA_MAC_VER_34)
-			features = rtl8168evl_fix_tso(skb, features);
+			rtl8168evl_fix_tso(skb, features);
 
 		if (skb_transport_offset(skb) > GTTCPHO_MAX &&
 		    rtl_chip_supports_csum_v2(tp))
-			netdev_features_clear(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)
-			netdev_features_clear(features, NETIF_F_CSUM_MASK);
+			netdev_features_clear(*features, NETIF_F_CSUM_MASK);
 
 		if (rtl_quirk_packet_padto(tp, skb))
-			netdev_features_clear(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))
-			netdev_features_clear(features, NETIF_F_CSUM_MASK);
+			netdev_features_clear(*features, NETIF_F_CSUM_MASK);
 	}
 
-	return vlan_features_check(skb, features);
+	vlan_features_check(skb, features);
 }
 
 static void rtl8169_pcierr_interrupt(struct net_device *dev)
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index 9a52492f3f06..df921615ba5a 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -1355,26 +1355,25 @@ static bool efx_can_encap_offloads(struct efx_nic *efx, struct sk_buff *skb)
 	}
 }
 
-netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev,
-				     netdev_features_t features)
+void efx_features_check(struct sk_buff *skb, struct net_device *dev,
+			netdev_features_t *features)
 {
 	struct efx_nic *efx = efx_netdev_priv(dev);
 
 	if (skb->encapsulation) {
-		if (netdev_features_intersects(features, NETIF_F_GSO_MASK))
+		if (netdev_features_intersects(*features, NETIF_F_GSO_MASK))
 			/* Hardware can only do TSO with at most 208 bytes
 			 * of headers.
 			 */
 			if (skb_inner_transport_offset(skb) >
 			    EFX_TSO2_MAX_HDRLEN)
-				netdev_features_clear(features,
+				netdev_features_clear(*features,
 						      NETIF_F_GSO_MASK);
-		if (netdev_features_intersects(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_features_clear(*features,
 						      netdev_csum_gso_features_mask);
 	}
-	return features;
 }
 
 int efx_get_phys_port_id(struct net_device *net_dev,
diff --git a/drivers/net/ethernet/sfc/efx_common.h b/drivers/net/ethernet/sfc/efx_common.h
index 2c54dac3e662..a191f85b3f5d 100644
--- a/drivers/net/ethernet/sfc/efx_common.h
+++ b/drivers/net/ethernet/sfc/efx_common.h
@@ -103,8 +103,8 @@ int efx_change_mtu(struct net_device *net_dev, int new_mtu);
 
 extern const struct pci_error_handlers efx_err_handlers;
 
-netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev,
-				     netdev_features_t features);
+void efx_features_check(struct sk_buff *skb, struct net_device *dev,
+			netdev_features_t *features);
 
 int efx_get_phys_port_id(struct net_device *net_dev,
 			 struct netdev_phys_item_id *ppid);
diff --git a/drivers/net/ethernet/sfc/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 5360c6d6c026..12aa69a679cf 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -1367,27 +1367,25 @@ static bool efx_can_encap_offloads(struct efx_nic *efx, struct sk_buff *skb)
 	}
 }
 
-netdev_features_t efx_siena_features_check(struct sk_buff *skb,
-					   struct net_device *dev,
-					   netdev_features_t features)
+void efx_siena_features_check(struct sk_buff *skb, struct net_device *dev,
+			      netdev_features_t *features)
 {
 	struct efx_nic *efx = netdev_priv(dev);
 
 	if (skb->encapsulation) {
-		if (netdev_features_intersects(features, NETIF_F_GSO_MASK))
+		if (netdev_features_intersects(*features, NETIF_F_GSO_MASK))
 			/* Hardware can only do TSO with at most 208 bytes
 			 * of headers.
 			 */
 			if (skb_inner_transport_offset(skb) >
 			    EFX_TSO2_MAX_HDRLEN)
-				netdev_features_clear(features,
+				netdev_features_clear(*features,
 						      (NETIF_F_GSO_MASK));
-		if (netdev_features_intersects(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_features_clear(*features,
 						      netdev_csum_gso_features_mask);
 	}
-	return features;
 }
 
 int efx_siena_get_phys_port_id(struct net_device *net_dev,
diff --git a/drivers/net/ethernet/sfc/siena/efx_common.h b/drivers/net/ethernet/sfc/siena/efx_common.h
index aeb92f4e34b7..d0e2cefba6cb 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.h
+++ b/drivers/net/ethernet/sfc/siena/efx_common.h
@@ -106,9 +106,8 @@ int efx_siena_change_mtu(struct net_device *net_dev, int new_mtu);
 
 extern const struct pci_error_handlers efx_siena_err_handlers;
 
-netdev_features_t efx_siena_features_check(struct sk_buff *skb,
-					   struct net_device *dev,
-					   netdev_features_t features);
+void efx_siena_features_check(struct sk_buff *skb, struct net_device *dev,
+			      netdev_features_t *features);
 
 int efx_siena_get_phys_port_id(struct net_device *net_dev,
 			       struct netdev_phys_item_id *ppid);
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index db7eae1b976e..6cf85b19d4ac 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -4284,19 +4284,17 @@ static void lan78xx_tx_timeout(struct net_device *net, unsigned int txqueue)
 	napi_schedule(&dev->napi);
 }
 
-static netdev_features_t lan78xx_features_check(struct sk_buff *skb,
-						struct net_device *netdev,
-						netdev_features_t features)
+static void lan78xx_features_check(struct sk_buff *skb,
+				   struct net_device *netdev,
+				   netdev_features_t *features)
 {
 	struct lan78xx_net *dev = netdev_priv(netdev);
 
 	if (skb->len > LAN78XX_TSO_SIZE(dev))
-		netdev_features_clear(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);
-
-	return features;
+	vlan_features_check(skb, features);
+	vxlan_features_check(skb, features);
 }
 
 static const struct net_device_ops lan78xx_netdev_ops = {
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index e835a7be2a67..edce2a0d3dd7 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2762,21 +2762,19 @@ static void _rtl8152_set_rx_mode(struct net_device *netdev)
 	netif_wake_queue(netdev);
 }
 
-static netdev_features_t
+static void
 rtl8152_features_check(struct sk_buff *skb, struct net_device *dev,
-		       netdev_features_t features)
+		       netdev_features_t *features)
 {
 	u32 mss = skb_shinfo(skb)->gso_size;
 	int max_offset = mss ? GTTCPHO_MAX : TCPHO_MAX;
 
 	if ((mss || skb->ip_summed == CHECKSUM_PARTIAL) &&
 	    skb_transport_offset(skb) > max_offset)
-		netdev_features_clear(features,
+		netdev_features_clear(*features,
 				      netdev_csum_gso_features_mask);
 	else if ((skb->len + sizeof(struct tx_desc)) > agg_buf_sz)
-		netdev_features_clear(features, NETIF_F_GSO_MASK);
-
-	return features;
+		netdev_features_clear(*features, NETIF_F_GSO_MASK);
 }
 
 static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index ff1d4218135f..9b7adc83c210 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -256,9 +256,8 @@ netdev_features_t vmxnet3_fix_features(struct net_device *netdev,
 	return features;
 }
 
-netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
-					 struct net_device *netdev,
-					 netdev_features_t features)
+void vmxnet3_features_check(struct sk_buff *skb, struct net_device *netdev,
+			    netdev_features_t *features)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
@@ -277,9 +276,9 @@ netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
 			l4_proto = ipv6_hdr(skb)->nexthdr;
 			break;
 		default:
-			netdev_features_clear(features,
+			netdev_features_clear(*features,
 					      netdev_csum_gso_features_mask);
-			return features;
+			return;
 		}
 
 		switch (l4_proto) {
@@ -290,18 +289,17 @@ netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
 			if (port != GENEVE_UDP_PORT &&
 			    port != IANA_VXLAN_UDP_PORT &&
 			    port != VXLAN_UDP_PORT) {
-				netdev_features_clear(features,
+				netdev_features_clear(*features,
 						      netdev_csum_gso_features_mask);
-				return features;
+				return;
 			}
 			break;
 		default:
-			netdev_features_clear(features,
+			netdev_features_clear(*features,
 					      netdev_csum_gso_features_mask);
-			return features;
+			return;
 		}
 	}
-	return features;
 }
 
 static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_features_t features)
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 82d661d919f6..4fe7be614c05 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -494,9 +494,9 @@ vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter);
 netdev_features_t
 vmxnet3_fix_features(struct net_device *netdev, netdev_features_t features);
 
-netdev_features_t
+void
 vmxnet3_features_check(struct sk_buff *skb,
-		       struct net_device *netdev, netdev_features_t features);
+		       struct net_device *netdev, netdev_features_t *features);
 
 int
 vmxnet3_set_features(struct net_device *netdev, netdev_features_t features);
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 1d195429753d..3015edb0ac66 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -1088,9 +1088,8 @@ int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
 int qeth_set_features(struct net_device *, netdev_features_t);
 void qeth_enable_hw_features(struct net_device *dev);
 netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t);
-netdev_features_t qeth_features_check(struct sk_buff *skb,
-				      struct net_device *dev,
-				      netdev_features_t features);
+void qeth_features_check(struct sk_buff *skb, struct net_device *dev,
+			 netdev_features_t *features);
 void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats);
 int qeth_set_real_num_tx_queues(struct qeth_card *card, unsigned int count);
 u16 qeth_iqd_select_queue(struct net_device *dev, struct sk_buff *skb,
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 72c487009c33..9bed9ba8f6c4 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6873,9 +6873,8 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
 }
 EXPORT_SYMBOL_GPL(qeth_fix_features);
 
-netdev_features_t qeth_features_check(struct sk_buff *skb,
-				      struct net_device *dev,
-				      netdev_features_t features)
+void qeth_features_check(struct sk_buff *skb, struct net_device *dev,
+			 netdev_features_t *features)
 {
 	struct qeth_card *card = dev->ml_priv;
 
@@ -6885,7 +6884,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 		netdev_features_t restricted;
 
 		netdev_features_zero(restricted);
-		if (skb_is_gso(skb) && !netif_needs_gso(skb, features))
+		if (skb_is_gso(skb) && !netif_needs_gso(skb, *features))
 			netdev_features_set(restricted, NETIF_F_ALL_TSO);
 
 		switch (vlan_get_protocol(skb)) {
@@ -6895,7 +6894,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 						   restricted);
 
 			if (restricted && qeth_next_hop_is_local_v4(card, skb))
-				netdev_features_clear(features, restricted);
+				netdev_features_clear(*features, restricted);
 			break;
 		case htons(ETH_P_IPV6):
 			if (!card->info.has_lp2lp_cso_v6)
@@ -6903,7 +6902,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 						   restricted);
 
 			if (restricted && qeth_next_hop_is_local_v6(card, skb))
-				netdev_features_clear(features, restricted);
+				netdev_features_clear(*features, restricted);
 			break;
 		default:
 			break;
@@ -6917,7 +6916,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
 	 * additional buffer element. This reduces buffer utilization, and
 	 * hurts throughput. So compress small segments into one element.
 	 */
-	if (netif_needs_gso(skb, features)) {
+	if (netif_needs_gso(skb, *features)) {
 		/* match skb_segment(): */
 		unsigned int doffset = skb->data - skb_mac_header(skb);
 		unsigned int hsize = skb_shinfo(skb)->gso_size;
@@ -6925,10 +6924,10 @@ 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))
-			netdev_feature_del(NETIF_F_SG_BIT, features);
+			netdev_feature_del(NETIF_F_SG_BIT, *features);
 	}
 
-	return vlan_features_check(skb, features);
+	vlan_features_check(skb, features);
 }
 EXPORT_SYMBOL_GPL(qeth_features_check);
 
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index ecc32a217e31..a3a9fcf459ee 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1804,13 +1804,13 @@ qeth_l3_neigh_setup(struct net_device *dev, struct neigh_parms *np)
 	return 0;
 }
 
-static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb,
-						    struct net_device *dev,
-						    netdev_features_t features)
+static void qeth_l3_osa_features_check(struct sk_buff *skb,
+				       struct net_device *dev,
+				       netdev_features_t *features)
 {
 	if (vlan_get_protocol(skb) != htons(ETH_P_IP))
-		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
-	return qeth_features_check(skb, dev, features);
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
+	qeth_features_check(skb, dev, features);
 }
 
 static u16 qeth_l3_iqd_select_queue(struct net_device *dev, struct sk_buff *skb,
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 7adac714c78b..4fef74864267 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -731,12 +731,11 @@ static inline bool skb_vlan_tagged_multi(struct sk_buff *skb)
 /**
  * vlan_features_check - drop unsafe features for skb with multiple tags.
  * @skb: skbuff to query
- * @features: features to be checked
- *
- * Returns features without unsafe ones if the skb has multiple tags.
+ * @features: features to be checked, returns features without unsafe ones
+ *	if the skb has multiple tags.
  */
-static inline netdev_features_t vlan_features_check(struct sk_buff *skb,
-						    netdev_features_t features)
+static inline void vlan_features_check(struct sk_buff *skb,
+				       netdev_features_t *features)
 {
 	if (skb_vlan_tagged_multi(skb)) {
 		/* In the case of multi-tagged packets, use a direct mask
@@ -744,11 +743,9 @@ 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.
 		 */
-		netdev_features_mask(features,
+		netdev_features_mask(*features,
 				     netdev_multi_tags_features_mask);
 	}
-
-	return features;
 }
 
 /**
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 75a839cf5cd2..78b0c501a24a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1385,9 +1385,9 @@ struct net_device_ops {
 	int			(*ndo_stop)(struct net_device *dev);
 	netdev_tx_t		(*ndo_start_xmit)(struct sk_buff *skb,
 						  struct net_device *dev);
-	netdev_features_t	(*ndo_features_check)(struct sk_buff *skb,
+	void			(*ndo_features_check)(struct sk_buff *skb,
 						      struct net_device *dev,
-						      netdev_features_t features);
+						      netdev_features_t *features);
 	u16			(*ndo_select_queue)(struct net_device *dev,
 						    struct sk_buff *skb,
 						    struct net_device *sb_dev);
@@ -4912,9 +4912,8 @@ void netdev_change_features(struct net_device *dev);
 void netif_stacked_transfer_operstate(const struct net_device *rootdev,
 					struct net_device *dev);
 
-netdev_features_t passthru_features_check(struct sk_buff *skb,
-					  struct net_device *dev,
-					  netdev_features_t features);
+void passthru_features_check(struct sk_buff *skb, struct net_device *dev,
+			     netdev_features_t *features);
 void netif_skb_features(struct sk_buff *skb, netdev_features_t *features);
 
 static inline bool net_gso_ok(netdev_features_t features, int gso_type)
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index d0e4729acebc..25d2bc8015c7 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -347,13 +347,13 @@ struct vxlan_dev {
 struct net_device *vxlan_dev_create(struct net *net, const char *name,
 				    u8 name_assign_type, struct vxlan_config *conf);
 
-static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
-						     netdev_features_t features)
+static inline void vxlan_features_check(struct sk_buff *skb,
+					netdev_features_t *features)
 {
 	u8 l4_hdr = 0;
 
 	if (!skb->encapsulation)
-		return features;
+		return;
 
 	switch (vlan_get_protocol(skb)) {
 	case htons(ETH_P_IP):
@@ -363,7 +363,7 @@ static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
 		l4_hdr = ipv6_hdr(skb)->nexthdr;
 		break;
 	default:
-		return features;
+		return;
 	}
 
 	if ((l4_hdr == IPPROTO_UDP) &&
@@ -372,12 +372,10 @@ static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
 	     (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
 	      sizeof(struct udphdr) + sizeof(struct vxlanhdr)) ||
 	     (skb->ip_summed != CHECKSUM_NONE &&
-	      !can_checksum_protocol(features, inner_eth_hdr(skb)->h_proto)))) {
-		netdev_features_clear(features, netdev_csum_gso_features_mask);
-		return features;
+	      !can_checksum_protocol(*features, inner_eth_hdr(skb)->h_proto)))) {
+		netdev_features_clear(*features, netdev_csum_gso_features_mask);
+		return;
 	}
-
-	return features;
 }
 
 /* IP header + UDP + VXLAN + Ethernet header */
diff --git a/net/core/dev.c b/net/core/dev.c
index 695b724a4054..5e84fdc8c7f5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3490,36 +3490,33 @@ static void harmonize_features(struct sk_buff *skb, netdev_features_t *features)
 		netdev_feature_del(NETIF_F_SG_BIT, *features);
 }
 
-netdev_features_t passthru_features_check(struct sk_buff *skb,
-					  struct net_device *dev,
-					  netdev_features_t features)
+void passthru_features_check(struct sk_buff *skb, struct net_device *dev,
+			     netdev_features_t *features)
 {
-	return features;
 }
 EXPORT_SYMBOL(passthru_features_check);
 
-static netdev_features_t dflt_features_check(struct sk_buff *skb,
-					     struct net_device *dev,
-					     netdev_features_t features)
+static void dflt_features_check(struct sk_buff *skb, struct net_device *dev,
+				netdev_features_t *features)
 {
-	return vlan_features_check(skb, features);
+	vlan_features_check(skb, features);
 }
 
-static netdev_features_t gso_features_check(const struct sk_buff *skb,
-					    struct net_device *dev,
-					    netdev_features_t features)
+static void gso_features_check(const struct sk_buff *skb,
+			       struct net_device *dev,
+			       netdev_features_t *features)
 {
 	u16 gso_segs = skb_shinfo(skb)->gso_segs;
 
 	if (gso_segs > READ_ONCE(dev->gso_max_segs)) {
-		netdev_features_clear(features, NETIF_F_GSO_MASK);
-		return features;
+		netdev_features_clear(*features, NETIF_F_GSO_MASK);
+		return;
 	}
 
 	if (!skb_shinfo(skb)->gso_type) {
 		skb_warn_bad_offload(skb);
-		netdev_features_clear(features, NETIF_F_GSO_MASK);
-		return features;
+		netdev_features_clear(*features, NETIF_F_GSO_MASK);
+		return;
 	}
 
 	/* Support for GSO partial features requires software
@@ -3529,7 +3526,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))
-		netdev_features_clear(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.
@@ -3540,10 +3537,8 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb,
 
 		if (!(iph->frag_off & htons(IP_DF)))
 			netdev_feature_del(NETIF_F_TSO_MANGLEID_BIT,
-					   features);
+					   *features);
 	}
-
-	return features;
 }
 
 void netif_skb_features(struct sk_buff *skb, netdev_features_t *features)
@@ -3554,7 +3549,7 @@ void netif_skb_features(struct sk_buff *skb, netdev_features_t *features)
 	netdev_features_copy(*features, dev->features);
 
 	if (skb_is_gso(skb))
-		*features = gso_features_check(skb, dev, *features);
+		gso_features_check(skb, dev, features);
 
 	/* If encapsulation offload request, verify we are testing
 	 * hardware encapsulation features instead of standard
@@ -3570,10 +3565,9 @@ void netif_skb_features(struct sk_buff *skb, netdev_features_t *features)
 	}
 
 	if (dev->netdev_ops->ndo_features_check)
-		tmp = dev->netdev_ops->ndo_features_check(skb, dev, *features);
+		dev->netdev_ops->ndo_features_check(skb, dev, features);
 	else
-		tmp = dflt_features_check(skb, dev, *features);
-	netdev_features_mask(*features, tmp);
+		dflt_features_check(skb, dev, features);
 
 	harmonize_features(skb, features);
 }
-- 
2.33.0


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

* [RFCv8 PATCH net-next 42/55] net: adjust the prototype of ndo_fix_features
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (40 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 41/55] net: adjust the prototype of xxx_features_check() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 43/55] net: adjust the prototype of xxx_set_features() Jian Shen
                   ` (14 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function net_device_ops.ndo_fix_features() using
netdev_features_t as parameters, and returns netdev_features_t
directly. For the prototype of netdev_features_t will be extended
to be larger than 8 bytes, so change the prototype of the function,
change the prototype of input features to'netdev_features_t *',
and return the features pointer as output parameter. So changes
all the implement for this function of all the netdev drivers, and
relative functions.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 arch/um/drivers/vector_kern.c                 |   7 +-
 drivers/infiniband/ulp/ipoib/ipoib_main.c     |   6 +-
 drivers/net/bonding/bond_main.c               |  20 ++-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |  28 ++---
 .../net/ethernet/aquantia/atlantic/aq_main.c  |  14 +--
 drivers/net/ethernet/atheros/alx/main.c       |   8 +-
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  14 +--
 .../net/ethernet/atheros/atl1e/atl1e_main.c   |  12 +-
 drivers/net/ethernet/atheros/atlx/atl2.c      |  12 +-
 drivers/net/ethernet/atheros/atlx/atlx.c      |  12 +-
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c   |  29 ++---
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h   |   3 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  27 ++---
 drivers/net/ethernet/broadcom/tg3.c           |   8 +-
 .../net/ethernet/cavium/liquidio/lio_main.c   |  34 +++---
 .../ethernet/cavium/liquidio/lio_vf_main.c    |  30 +++--
 .../net/ethernet/cavium/thunder/nicvf_main.c  |  10 +-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  11 +-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  12 +-
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  10 +-
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  12 +-
 drivers/net/ethernet/cortina/gemini.c         |   8 +-
 drivers/net/ethernet/hisilicon/hns/hns_enet.c |   7 +-
 .../net/ethernet/huawei/hinic/hinic_main.c    |  10 +-
 drivers/net/ethernet/ibm/ibmveth.c            |  10 +-
 drivers/net/ethernet/intel/e1000/e1000_main.c |  12 +-
 drivers/net/ethernet/intel/e1000e/netdev.c    |  14 +--
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 114 +++++++++---------
 drivers/net/ethernet/intel/ice/ice_main.c     |  30 +++--
 drivers/net/ethernet/intel/igb/igb_main.c     |  12 +-
 drivers/net/ethernet/intel/igc/igc_main.c     |  12 +-
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  10 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |  16 ++-
 drivers/net/ethernet/jme.c                    |   9 +-
 drivers/net/ethernet/marvell/mvneta.c         |   8 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  12 +-
 drivers/net/ethernet/marvell/sky2.c           |  18 ++-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  10 +-
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  12 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c |  54 ++++-----
 .../ethernet/netronome/nfp/nfp_net_common.c   |  13 +-
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |  15 ++-
 drivers/net/ethernet/nvidia/forcedeth.c       |   9 +-
 .../ethernet/qlogic/netxen/netxen_nic_main.c  |  10 +-
 drivers/net/ethernet/qlogic/qede/qede.h       |   3 +-
 .../net/ethernet/qlogic/qede/qede_filter.c    |   9 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h   |   4 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  35 +++---
 drivers/net/ethernet/realtek/r8169_main.c     |  12 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  14 +--
 drivers/net/hyperv/netvsc_drv.c               |  12 +-
 drivers/net/ipvlan/ipvlan_main.c              |  18 ++-
 drivers/net/macsec.c                          |  14 +--
 drivers/net/macvlan.c                         |  20 ++-
 drivers/net/team/team.c                       |  16 ++-
 drivers/net/tun.c                             |  10 +-
 drivers/net/veth.c                            |  10 +-
 drivers/net/vmxnet3/vmxnet3_ethtool.c         |  10 +-
 drivers/net/vmxnet3/vmxnet3_int.h             |   4 +-
 drivers/net/xen-netback/interface.c           |  16 ++-
 drivers/net/xen-netfront.c                    |  22 ++--
 drivers/s390/net/qeth_core.h                  |   2 +-
 drivers/s390/net/qeth_core_main.c             |  16 ++-
 include/linux/netdevice.h                     |   4 +-
 net/8021q/vlan_dev.c                          |  15 ++-
 net/bridge/br_device.c                        |   5 +-
 net/bridge/br_if.c                            |  15 +--
 net/bridge/br_private.h                       |   3 +-
 net/core/dev.c                                |   2 +-
 net/hsr/hsr_device.c                          |  18 ++-
 70 files changed, 461 insertions(+), 592 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 4ac7af5a635d..d41ac42762ed 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1336,11 +1336,10 @@ static void vector_net_tx_timeout(struct net_device *dev, unsigned int txqueue)
 	schedule_work(&vp->reset_tx);
 }
 
-static netdev_features_t vector_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void vector_fix_features(struct net_device *dev,
+				netdev_features_t *features)
 {
-	netdev_features_clear(features, netdev_ip_csum_features);
-	return features;
+	netdev_features_clear(*features, netdev_ip_csum_features);
 }
 
 static int vector_set_features(struct net_device *dev,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index de878f4f7963..f802022f53fb 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -214,15 +214,13 @@ static int ipoib_stop(struct net_device *dev)
 	return 0;
 }
 
-static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_features_t features)
+static void ipoib_fix_features(struct net_device *dev, netdev_features_t *features)
 {
 	struct ipoib_dev_priv *priv = ipoib_priv(dev);
 
 	if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags))
-		netdev_features_clear_set(features, NETIF_F_IP_CSUM_BIT,
+		netdev_features_clear_set(*features, NETIF_F_IP_CSUM_BIT,
 					  NETIF_F_TSO_BIT);
-
-	return features;
 }
 
 static int ipoib_change_mtu(struct net_device *dev, int new_mtu)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a50f8935658a..cd7c8d81ba0c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1396,8 +1396,8 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)
 
 /*---------------------------------- IOCTL ----------------------------------*/
 
-static netdev_features_t bond_fix_features(struct net_device *dev,
-					   netdev_features_t features)
+static void bond_fix_features(struct net_device *dev,
+			      netdev_features_t *features)
 {
 	struct bonding *bond = netdev_priv(dev);
 	struct list_head *iter;
@@ -1406,23 +1406,21 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
 
 #if IS_ENABLED(CONFIG_TLS_DEVICE)
 	if (bond_sk_check(bond))
-		netdev_features_set(features, BOND_TLS_FEATURES);
+		netdev_features_set(*features, BOND_TLS_FEATURES);
 	else
-		netdev_features_clear(features, BOND_TLS_FEATURES);
+		netdev_features_clear(*features, BOND_TLS_FEATURES);
 #endif
 
-	mask = features;
+	netdev_features_copy(mask, *features);
 
-	netdev_features_clear(features, NETIF_F_ONE_FOR_ALL);
-	netdev_features_set(features, NETIF_F_ALL_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) {
-		netdev_increment_features(&features, &features,
+		netdev_increment_features(features, features,
 					  &slave->dev->features, &mask);
 	}
-	netdev_add_tso_features(&features, &mask);
-
-	return features;
+	netdev_add_tso_features(features, &mask);
 }
 
 #define BOND_VLAN_FEATURES	bond_vlan_features
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 5ecd0904aacc..e84a69fb4812 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2177,8 +2177,8 @@ static int xgbe_setup_tc(struct net_device *netdev, enum tc_setup_type type,
 	return 0;
 }
 
-static netdev_features_t xgbe_fix_features(struct net_device *netdev,
-					   netdev_features_t features)
+static void xgbe_fix_features(struct net_device *netdev,
+			      netdev_features_t *features)
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
 	netdev_features_t vxlan_base;
@@ -2188,40 +2188,38 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
 				NETIF_F_RX_UDP_TUNNEL_PORT_BIT);
 
 	if (!pdata->hw_feat.vxn)
-		return features;
+		return;
 
 	/* VXLAN CSUM requires VXLAN base */
-	if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features) &&
-	    !netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_BIT, features)) {
+	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);
+		netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_BIT, *features);
 	}
 
 	/* Can't do one without doing the other */
-	if (!netdev_features_subset(vxlan_base, features)) {
+	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);
+		netdev_features_set(*features, vxlan_base);
 	}
 
-	if (netdev_features_intersects(features, netdev_ip_csum_features)) {
-		if (!netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, 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");
 			netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,
-					   features);
+					   *features);
 		}
 	} else {
-		if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features)) {
+		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,
-					   features);
+					   *features);
 		}
 	}
-
-	return features;
 }
 
 static int xgbe_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
index c331631d82c0..cd714a6cdf27 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -227,23 +227,21 @@ static int aq_ndev_set_features(struct net_device *ndev,
 	return err;
 }
 
-static netdev_features_t aq_ndev_fix_features(struct net_device *ndev,
-					      netdev_features_t features)
+static void aq_ndev_fix_features(struct net_device *ndev,
+				 netdev_features_t *features)
 {
 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
 	struct bpf_prog *prog;
 
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
-		netdev_feature_del(NETIF_F_LRO_BIT, features);
+	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 && netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+	    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);
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 	}
-
-	return features;
 }
 
 static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index d780a32ca51d..96a28cb8c6a4 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -1098,13 +1098,11 @@ static int alx_init_sw(struct alx_priv *alx)
 }
 
 
-static netdev_features_t alx_fix_features(struct net_device *netdev,
-					  netdev_features_t features)
+static void alx_fix_features(struct net_device *netdev,
+			     netdev_features_t *features)
 {
 	if (netdev->mtu > ALX_MAX_TSO_PKT_SIZE)
-		netdev_features_clear(features, netdev_general_tso_features);
-
-	return features;
+		netdev_features_clear(*features, netdev_general_tso_features);
 }
 
 static void alx_netif_stop(struct alx_priv *alx)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 202cc99ac334..b38b508db29c 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -504,8 +504,8 @@ static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
 	adapter->rx_frag_size = roundup_pow_of_two(head_size);
 }
 
-static netdev_features_t atl1c_fix_features(struct net_device *netdev,
-	netdev_features_t features)
+static void atl1c_fix_features(struct net_device *netdev,
+			       netdev_features_t *features)
 {
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 	struct atl1c_hw *hw = &adapter->hw;
@@ -514,18 +514,16 @@ 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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 
 	if (hw->nic_type != athr_mt) {
 		if (netdev->mtu > MAX_TSO_FRAME_SIZE)
-			netdev_features_clear(features,
+			netdev_features_clear(*features,
 					      netdev_general_tso_features);
 	}
-
-	return features;
 }
 
 static int atl1c_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index ebc1606368d0..fef2ba816451 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -382,19 +382,17 @@ static int atl1e_set_mac_addr(struct net_device *netdev, void *p)
 	return 0;
 }
 
-static netdev_features_t atl1e_fix_features(struct net_device *netdev,
-	netdev_features_t features)
+static void atl1e_fix_features(struct net_device *netdev,
+			       netdev_features_t *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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int atl1e_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index b43c193dc433..589c9f38e3ae 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -372,19 +372,17 @@ static void atl2_restore_vlan(struct atl2_adapter *adapter)
 	atl2_vlan_mode(adapter->netdev, adapter->netdev->features);
 }
 
-static netdev_features_t atl2_fix_features(struct net_device *netdev,
-	netdev_features_t features)
+static void atl2_fix_features(struct net_device *netdev,
+			      netdev_features_t *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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int atl2_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index d840713c8ad8..1943f97e8283 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -237,19 +237,17 @@ static void atlx_restore_vlan(struct atlx_adapter *adapter)
 	atlx_vlan_mode(adapter->netdev, adapter->netdev->features);
 }
 
-static netdev_features_t atlx_fix_features(struct net_device *netdev,
-	netdev_features_t features)
+static void atlx_fix_features(struct net_device *netdev,
+			      netdev_features_t *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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int atlx_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 53b6ed00e124..23a9746c6e55 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4899,43 +4899,40 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
 	return bnx2x_reload_if_running(dev);
 }
 
-netdev_features_t bnx2x_fix_features(struct net_device *dev,
-				     netdev_features_t features)
+void bnx2x_fix_features(struct net_device *dev, netdev_features_t *features)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 
 	if (pci_num_vf(bp->pdev)) {
 		netdev_features_t changed;
 
-		netdev_features_xor(changed, dev->features, features);
+		netdev_features_xor(changed, dev->features, *features);
 		/* Revert the requested changes in features if they
 		 * would require internal reload of PF in bnx2x_set_features().
 		 */
-		if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && !bp->disable_tpa) {
-			netdev_feature_del(NETIF_F_RXCSUM_BIT, features);
+		if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, *features) && !bp->disable_tpa) {
+			netdev_feature_del(NETIF_F_RXCSUM_BIT, *features);
 			if (netdev_active_feature_test(dev, NETIF_F_RXCSUM_BIT))
 				netdev_feature_add(NETIF_F_RXCSUM_BIT,
-						   features);
+						   *features);
 		}
 
 		if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed)) {
-			netdev_feature_del(NETIF_F_LOOPBACK_BIT, features);
+			netdev_feature_del(NETIF_F_LOOPBACK_BIT, *features);
 			if (netdev_active_feature_test(dev, NETIF_F_LOOPBACK_BIT))
 				netdev_feature_add(NETIF_F_LOOPBACK_BIT,
-						   features);
+						   *features);
 		}
 	}
 
 	/* TPA requires Rx CSUM offloading */
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
-		netdev_feature_del(NETIF_F_LRO_BIT, features);
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 
-	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 (netdev_feature_test(NETIF_F_GRO_HW_BIT, features))
-		netdev_feature_del(NETIF_F_LRO_BIT, features);
-
-	return features;
+	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 (netdev_feature_test(NETIF_F_GRO_HW_BIT, *features))
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 }
 
 int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index d8b1824c334d..4c66ef3e04bf 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -606,8 +606,7 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
 int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type);
 #endif
 
-netdev_features_t bnx2x_fix_features(struct net_device *dev,
-				     netdev_features_t features);
+void bnx2x_fix_features(struct net_device *dev, netdev_features_t *features);
 int bnx2x_set_features(struct net_device *dev, netdev_features_t features);
 
 /**
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 97a108fdf693..b6ca502a3af1 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11170,43 +11170,42 @@ static bool bnxt_rfs_capable(struct bnxt *bp)
 #endif
 }
 
-static netdev_features_t bnxt_fix_features(struct net_device *dev,
-					   netdev_features_t features)
+static void bnxt_fix_features(struct net_device *dev,
+			      netdev_features_t *features)
 {
 	struct bnxt *bp = netdev_priv(dev);
 	netdev_features_t vlan_features;
 
-	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, features) && !bnxt_rfs_capable(bp))
-		netdev_feature_del(NETIF_F_NTUPLE_BIT, features);
+	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) || bp->xdp_prog)
-		netdev_features_clear_set(features, NETIF_F_LRO_BIT,
+		netdev_features_clear_set(*features, NETIF_F_LRO_BIT,
 					  NETIF_F_GRO_HW_BIT);
 
-	if (!netdev_feature_test(NETIF_F_GRO_BIT, features))
-		netdev_feature_del(NETIF_F_GRO_HW_BIT, features);
+	if (!netdev_feature_test(NETIF_F_GRO_BIT, *features))
+		netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 
-	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features))
-		netdev_feature_del(NETIF_F_LRO_BIT, features);
+	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
 	 * turned on or off together.
 	 */
-	netdev_features_and(vlan_features, features,
+	netdev_features_and(vlan_features, *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,
+			netdev_features_clear(*features,
 					      BNXT_HW_FEATURE_VLAN_ALL_RX);
 		else if (!netdev_features_empty(vlan_features))
-			netdev_features_set(features,
+			netdev_features_set(*features,
 					    BNXT_HW_FEATURE_VLAN_ALL_RX);
 	}
 #ifdef CONFIG_BNXT_SRIOV
 	if (BNXT_VF(bp) && bp->vf.vlan)
-		netdev_features_clear(features, BNXT_HW_FEATURE_VLAN_ALL_RX);
+		netdev_features_clear(*features, BNXT_HW_FEATURE_VLAN_ALL_RX);
 #endif
-	return features;
 }
 
 static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 00f887601a1a..be6d69b9c3c1 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -8304,15 +8304,13 @@ static void tg3_set_loopback(struct net_device *dev, netdev_features_t features)
 	}
 }
 
-static netdev_features_t tg3_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void tg3_fix_features(struct net_device *dev,
+			     netdev_features_t *features)
 {
 	struct tg3 *tp = netdev_priv(dev);
 
 	if (dev->mtu > ETH_DATA_LEN && tg3_flag(tp, 5780_CLASS))
-		netdev_features_clear(features, NETIF_F_ALL_TSO);
-
-	return features;
+		netdev_features_clear(*features, NETIF_F_ALL_TSO);
 }
 
 static int tg3_set_features(struct net_device *dev, netdev_features_t features)
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index a2e18f493d7e..cb0cc8a5c268 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2715,43 +2715,41 @@ static const struct udp_tunnel_nic_info liquidio_udp_tunnels = {
  * @request: features requested
  * Return: updated features list
  */
-static netdev_features_t liquidio_fix_features(struct net_device *netdev,
-					       netdev_features_t request)
+static void liquidio_fix_features(struct net_device *netdev,
+				  netdev_features_t *request)
 {
 	struct lio *lio = netdev_priv(netdev);
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_RXCSUM_BIT, *request);
 
-	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_HW_CSUM_BIT, *request);
 
-	if (netdev_feature_test(NETIF_F_TSO_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_TSO_BIT, *request);
 
-	if (netdev_feature_test(NETIF_F_TSO6_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_TSO6_BIT, *request);
 
-	if (netdev_feature_test(NETIF_F_LRO_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_LRO_BIT, *request);
 
 	/*Disable LRO if RXCSUM is off */
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_LRO_BIT, *request);
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, request) &&
+	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;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, *request);
 }
 
 /**
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 51d202c0bf52..8cf64202846b 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -1813,38 +1813,36 @@ static const struct udp_tunnel_nic_info liquidio_udp_tunnels = {
  * @param request features requested
  * @returns updated features list
  */
-static netdev_features_t liquidio_fix_features(struct net_device *netdev,
-					       netdev_features_t request)
+static void liquidio_fix_features(struct net_device *netdev,
+				  netdev_features_t *request)
 {
 	struct lio *lio = netdev_priv(netdev);
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_RXCSUM_BIT, *request);
 
-	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_HW_CSUM_BIT, *request);
 
-	if (netdev_feature_test(NETIF_F_TSO_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_TSO_BIT, *request);
 
-	if (netdev_feature_test(NETIF_F_TSO6_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_TSO6_BIT, *request);
 
-	if (netdev_feature_test(NETIF_F_LRO_BIT, request) &&
+	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);
+		netdev_feature_del(NETIF_F_LRO_BIT, *request);
 
 	/* Disable LRO if RXCSUM is off */
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, request) &&
+	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;
+		netdev_feature_del(NETIF_F_LRO_BIT, *request);
 }
 
 /** \brief Net device set features
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 979a03faca7a..994608dde650 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1773,16 +1773,14 @@ static int nicvf_config_loopback(struct nicvf *nic,
 	return nicvf_send_msg_to_pf(nic, &mbx);
 }
 
-static netdev_features_t nicvf_fix_features(struct net_device *netdev,
-					    netdev_features_t features)
+static void nicvf_fix_features(struct net_device *netdev,
+			       netdev_features_t *features)
 {
 	struct nicvf *nic = netdev_priv(netdev);
 
-	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features) &&
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, *features) &&
 	    netif_running(netdev) && !nic->loopback_supported)
-		netdev_feature_del(NETIF_F_LOOPBACK_BIT, features);
-
-	return features;
+		netdev_feature_del(NETIF_F_LOOPBACK_BIT, *features);
 }
 
 static int nicvf_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 30e371efcb77..23dcdc7bde05 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -863,19 +863,16 @@ static int t1_set_mac_addr(struct net_device *dev, void *p)
 	return 0;
 }
 
-static netdev_features_t t1_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void t1_fix_features(struct net_device *dev, netdev_features_t *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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int t1_set_features(struct net_device *dev, netdev_features_t features)
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index a1d6279886a7..56bba53a8dd6 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -2588,19 +2588,17 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p)
 	return 0;
 }
 
-static netdev_features_t cxgb_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void cxgb_fix_features(struct net_device *dev,
+			      netdev_features_t *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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 08ce0b730ec4..c96b11d6c5d8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3858,14 +3858,12 @@ static void cxgb_features_check(struct sk_buff *skb, struct net_device *dev,
 	netdev_features_clear(*features, netdev_csum_gso_features_mask);
 }
 
-static netdev_features_t cxgb_fix_features(struct net_device *dev,
-					   netdev_features_t features)
+static void cxgb_fix_features(struct net_device *dev,
+			      netdev_features_t *features)
 {
 	/* Disable GRO, if RX_CSUM is disabled */
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
-		netdev_feature_del(NETIF_F_GRO_BIT, features);
-
-	return features;
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
+		netdev_feature_del(NETIF_F_GRO_BIT, *features);
 }
 
 static const struct net_device_ops cxgb4_netdev_ops = {
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 94f253feda79..7941946e512d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -1174,19 +1174,17 @@ static int cxgb4vf_change_mtu(struct net_device *dev, int new_mtu)
 	return ret;
 }
 
-static netdev_features_t cxgb4vf_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void cxgb4vf_fix_features(struct net_device *dev,
+				 netdev_features_t *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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int cxgb4vf_set_features(struct net_device *dev,
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index cc3865fb7d83..4da024437808 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -1978,13 +1978,11 @@ static int gmac_change_mtu(struct net_device *netdev, int new_mtu)
 	return 0;
 }
 
-static netdev_features_t gmac_fix_features(struct net_device *netdev,
-					   netdev_features_t features)
+static void gmac_fix_features(struct net_device *netdev,
+			      netdev_features_t *features)
 {
 	if (netdev->mtu + ETH_HLEN + VLAN_HLEN > MTU_SIZE_BIT_MASK)
-		netdev_features_clear(features, GMAC_OFFLOAD_FEATURES);
-
-	return features;
+		netdev_features_clear(*features, GMAC_OFFLOAD_FEATURES);
 }
 
 static int gmac_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 6147864b0322..c29f2eab3d5f 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1792,21 +1792,20 @@ static int hns_nic_set_features(struct net_device *netdev,
 	return 0;
 }
 
-static netdev_features_t hns_nic_fix_features(
-		struct net_device *netdev, netdev_features_t features)
+static void hns_nic_fix_features(struct net_device *netdev,
+				 netdev_features_t *features)
 {
 	struct hns_nic_priv *priv = netdev_priv(netdev);
 
 	switch (priv->enet_ver) {
 	case AE_VERSION_1:
-		netdev_features_clear_set(features, NETIF_F_TSO_BIT,
+		netdev_features_clear_set(*features, NETIF_F_TSO_BIT,
 					  NETIF_F_TSO6_BIT,
 					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 		break;
 	default:
 		break;
 	}
-	return features;
 }
 
 static int hns_nic_uc_sync(struct net_device *netdev, const unsigned char *addr)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 59475894676e..035b77c95cf0 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -864,18 +864,16 @@ static int hinic_set_features(struct net_device *netdev,
 			    features, false);
 }
 
-static netdev_features_t hinic_fix_features(struct net_device *netdev,
-					    netdev_features_t features)
+static void hinic_fix_features(struct net_device *netdev,
+			       netdev_features_t *features)
 {
 	struct hinic_dev *nic_dev = netdev_priv(netdev);
 
 	/* If Rx checksum is disabled, then LRO should also be disabled */
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
+	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);
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 	}
-
-	return features;
 }
 
 static const struct net_device_ops hinic_netdev_ops = {
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 90402227dbd4..3658783641c7 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -731,8 +731,8 @@ static void netdev_get_drvinfo(struct net_device *dev,
 	strscpy(info->version, ibmveth_driver_version, sizeof(info->version));
 }
 
-static netdev_features_t ibmveth_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void ibmveth_fix_features(struct net_device *dev,
+				 netdev_features_t *features)
 {
 	/*
 	 * Since the ibmveth firmware interface does not have the
@@ -743,10 +743,8 @@ static netdev_features_t ibmveth_fix_features(struct net_device *dev,
 	 * checksummed.
 	 */
 
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
-		netdev_features_clear(features, NETIF_F_CSUM_MASK);
-
-	return features;
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
+		netdev_features_clear(*features, NETIF_F_CSUM_MASK);
 }
 
 static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index a1a0cdb3cf2e..a689aba72050 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -787,18 +787,16 @@ static int e1000_is_need_ioport(struct pci_dev *pdev)
 	}
 }
 
-static netdev_features_t e1000_fix_features(struct net_device *netdev,
-	netdev_features_t features)
+static void e1000_fix_features(struct net_device *netdev,
+			       netdev_features_t *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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int e1000_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index dc286f57a683..d5b022b309aa 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -7291,25 +7291,23 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
 	}
 }
 
-static netdev_features_t e1000_fix_features(struct net_device *netdev,
-					    netdev_features_t features)
+static void e1000_fix_features(struct net_device *netdev,
+			       netdev_features_t *features)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
 	/* Jumbo frame workaround on 82579 and newer requires CRC be stripped */
 	if ((hw->mac.type >= e1000_pch2lan) && (netdev->mtu > ETH_DATA_LEN))
-		netdev_feature_del(NETIF_F_RXFCS_BIT, features);
+		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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int e1000_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 9b9873d62687..bc9b963a3bd9 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4440,23 +4440,23 @@ static void iavf_features_check(struct sk_buff *skb, struct net_device *dev,
 /**
  * iavf_get_netdev_vlan_hw_features - get NETDEV VLAN features that can toggle on/off
  * @adapter: board private structure
+ * @hw_features: hw vlan features
  *
  * Depending on whether VIRTHCNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2
  * were negotiated determine the VLAN features that can be toggled on and off.
  **/
-static netdev_features_t
-iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter)
+static void
+iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter,
+				 netdev_features_t *hw_features)
 {
-	netdev_features_t hw_features;
-
-	netdev_features_zero(hw_features);
+	netdev_features_zero(*hw_features);
 
 	if (!adapter->vf_res || !adapter->vf_res->vf_cap_flags)
-		return hw_features;
+		return;
 
 	/* Enable VLAN features if supported */
 	if (VLAN_ALLOWED(adapter)) {
-		netdev_features_set(hw_features,
+		netdev_features_set(*hw_features,
 				    netdev_ctag_vlan_offload_features);
 	} else if (VLAN_V2_ALLOWED(adapter)) {
 		struct virtchnl_vlan_caps *vlan_v2_caps =
@@ -4471,18 +4471,18 @@ iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter)
 			if (stripping_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
-						   hw_features);
+						   *hw_features);
 			if (stripping_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_88A8)
 				netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT,
-						   hw_features);
+						   *hw_features);
 		} else if (stripping_support->inner !=
 			   VIRTCHNL_VLAN_UNSUPPORTED &&
 			   stripping_support->inner & VIRTCHNL_VLAN_TOGGLE) {
 			if (stripping_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
-						   hw_features);
+						   *hw_features);
 		}
 
 		if (insertion_support->outer != VIRTCHNL_VLAN_UNSUPPORTED &&
@@ -4490,41 +4490,39 @@ iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter)
 			if (insertion_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT,
-						   hw_features);
+						   *hw_features);
 			if (insertion_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_88A8)
 				netdev_feature_add(NETIF_F_HW_VLAN_STAG_TX_BIT,
-						   hw_features);
+						   *hw_features);
 		} else if (insertion_support->inner &&
 			   insertion_support->inner & VIRTCHNL_VLAN_TOGGLE) {
 			if (insertion_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT,
-						   hw_features);
+						   *hw_features);
 		}
 	}
-
-	return hw_features;
 }
 
 /**
  * iavf_get_netdev_vlan_features - get the enabled NETDEV VLAN fetures
  * @adapter: board private structure
+ * @features: vlan features
  *
  * Depending on whether VIRTHCNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2
  * were negotiated determine the VLAN features that are enabled by default.
  **/
-static netdev_features_t
-iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
+static void
+iavf_get_netdev_vlan_features(struct iavf_adapter *adapter,
+			      netdev_features_t *features)
 {
-	netdev_features_t features;
-
-	netdev_features_zero(features);
+	netdev_features_zero(*features);
 	if (!adapter->vf_res || !adapter->vf_res->vf_cap_flags)
-		return features;
+		return;
 
 	if (VLAN_ALLOWED(adapter)) {
-		netdev_features_set(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;
@@ -4545,19 +4543,19 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
-						   features);
+						   *features);
 			else if (stripping_support->outer &
 				 VIRTCHNL_VLAN_ETHERTYPE_88A8 &&
 				 ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8)
 				netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT,
-						   features);
+						   *features);
 		} else if (stripping_support->inner !=
 			   VIRTCHNL_VLAN_UNSUPPORTED) {
 			if (stripping_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
-						   features);
+						   *features);
 		}
 
 		/* give priority to outer insertion and don't support both outer
@@ -4568,19 +4566,19 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT,
-						   features);
+						   *features);
 			else if (insertion_support->outer &
 				 VIRTCHNL_VLAN_ETHERTYPE_88A8 &&
 				 ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8)
 				netdev_feature_add(NETIF_F_HW_VLAN_STAG_TX_BIT,
-						   features);
+						   *features);
 		} else if (insertion_support->inner !=
 			   VIRTCHNL_VLAN_UNSUPPORTED) {
 			if (insertion_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT,
-						   features);
+						   *features);
 		}
 
 		/* give priority to outer filtering and don't bother if both
@@ -4592,28 +4590,26 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
-						   features);
+						   *features);
 			if (filtering_support->outer &
 			    VIRTCHNL_VLAN_ETHERTYPE_88A8 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8)
 				netdev_feature_add(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
-						   features);
+						   *features);
 		} else if (filtering_support->inner !=
 			   VIRTCHNL_VLAN_UNSUPPORTED) {
 			if (filtering_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_8100 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100)
 				netdev_feature_add(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
-						   features);
+						   *features);
 			if (filtering_support->inner &
 			    VIRTCHNL_VLAN_ETHERTYPE_88A8 &&
 			    ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8)
 				netdev_feature_add(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
-						   features);
+						   *features);
 		}
 	}
-
-	return features;
 }
 
 #define IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested, allowed, feature_bit) \
@@ -4625,63 +4621,61 @@ iavf_get_netdev_vlan_features(struct iavf_adapter *adapter)
  * @adapter: board private structure
  * @requested_features: stack requested NETDEV features
  **/
-static netdev_features_t
+static void
 iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
-			      netdev_features_t requested_features)
+			      netdev_features_t *requested_features)
 {
 	netdev_features_t allowed_features;
 	netdev_features_t vlan_hw_features;
 	netdev_features_t vlan_features;
 
-	vlan_hw_features = iavf_get_netdev_vlan_hw_features(adapter);
-	vlan_features = iavf_get_netdev_vlan_features(adapter);
+	iavf_get_netdev_vlan_hw_features(adapter, &vlan_hw_features);
+	iavf_get_netdev_vlan_features(adapter, &vlan_features);
 	netdev_features_or(allowed_features, vlan_hw_features, vlan_features);
 
-	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
+	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(*requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_CTAG_TX_BIT))
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT,
-				   requested_features);
+				   *requested_features);
 
-	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
+	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(*requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_CTAG_RX_BIT))
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_RX_BIT,
-				   requested_features);
+				   *requested_features);
 
-	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
+	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(*requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_STAG_TX_BIT))
 		netdev_feature_del(NETIF_F_HW_VLAN_STAG_TX_BIT,
-				   requested_features);
-	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
+				   *requested_features);
+	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(*requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_STAG_RX_BIT))
 		netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT,
-				   requested_features);
+				   *requested_features);
 
-	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
+	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(*requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_CTAG_FILTER_BIT))
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
-				   requested_features);
+				   *requested_features);
 
-	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested_features,
+	if (!IAVF_NETDEV_VLAN_FEATURE_ALLOWED(*requested_features,
 					      allowed_features,
 					      NETIF_F_HW_VLAN_STAG_FILTER_BIT))
 		netdev_feature_del(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
-				   requested_features);
+				   *requested_features);
 
-	if (netdev_features_intersects(requested_features, netdev_ctag_vlan_offload_features) &&
-	    netdev_features_intersects(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");
-		netdev_features_clear(requested_features,
+		netdev_features_clear(*requested_features,
 				      netdev_stag_vlan_offload_features);
 	}
-
-	return requested_features;
 }
 
 /**
@@ -4691,12 +4685,12 @@ iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
  *
  * Returns fixed-up features bits
  **/
-static netdev_features_t iavf_fix_features(struct net_device *netdev,
-					   netdev_features_t features)
+static void iavf_fix_features(struct net_device *netdev,
+			      netdev_features_t *features)
 {
 	struct iavf_adapter *adapter = netdev_priv(netdev);
 
-	return iavf_fix_netdev_vlan_features(adapter, features);
+	iavf_fix_netdev_vlan_features(adapter, features);
 }
 
 static const struct net_device_ops iavf_netdev_ops = {
@@ -4799,7 +4793,7 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	hw_features = hw_enc_features;
 
 	/* get HW VLAN features that can be toggled */
-	hw_vlan_features = iavf_get_netdev_vlan_hw_features(adapter);
+	iavf_get_netdev_vlan_hw_features(adapter, &hw_vlan_features);
 
 	/* Enable cloud filter if ADQ is supported */
 	if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ)
@@ -4809,7 +4803,7 @@ int iavf_process_config(struct iavf_adapter *adapter)
 
 	netdev_hw_features_set(netdev, hw_features);
 	netdev_hw_features_set(netdev, hw_vlan_features);
-	vlan_features = iavf_get_netdev_vlan_features(adapter);
+	iavf_get_netdev_vlan_features(adapter, &vlan_features);
 
 	netdev_active_features_set(netdev, hw_features);
 	netdev_active_features_set(netdev, vlan_features);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 105f49eaec4d..cce947660cfd 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5813,8 +5813,8 @@ ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
  *	enable/disable VLAN filtering based on VLAN ethertype when using VLAN
  *	prune rules.
  */
-static netdev_features_t
-ice_fix_features(struct net_device *netdev, netdev_features_t features)
+static void
+ice_fix_features(struct net_device *netdev, netdev_features_t *features)
 {
 	struct ice_netdev_priv *np = netdev_priv(netdev);
 	netdev_features_t req_vlan_fltr, cur_vlan_fltr;
@@ -5827,7 +5827,7 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 	cur_stag = netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
 				       cur_vlan_fltr);
 
-	netdev_features_and(req_vlan_fltr, features,
+	netdev_features_and(req_vlan_fltr, *features,
 			    NETIF_VLAN_FILTERING_FEATURES);
 	req_ctag = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				       req_vlan_fltr);
@@ -5837,19 +5837,19 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 	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,
+				netdev_features_set(*features,
 						    NETIF_VLAN_FILTERING_FEATURES);
 			} else if (!req_ctag && !req_stag) {
-				netdev_features_clear(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,
+				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)) {
-				netdev_features_clear(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");
 			}
@@ -5859,27 +5859,25 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
 
 			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);
+						   *features);
 		}
 	}
 
-	if (netdev_features_intersects(features, netdev_ctag_vlan_offload_features) &&
-	    netdev_features_intersects(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_features_clear(*features,
 				      netdev_stag_vlan_offload_features);
 	}
 
 	if (!netdev_active_feature_test(netdev, NETIF_F_RXFCS_BIT) &&
-	    netdev_feature_test(NETIF_F_RXFCS_BIT, features) &&
-	    netdev_features_intersects(features, NETIF_VLAN_STRIPPING_FEATURES) &&
+	    netdev_feature_test(NETIF_F_RXFCS_BIT, *features) &&
+	    netdev_features_intersects(*features, NETIF_VLAN_STRIPPING_FEATURES) &&
 	    !ice_vsi_has_non_zero_vlans(np->vsi)) {
 		netdev_warn(netdev, "Disabling VLAN stripping as FCS/CRC stripping is also disabled and there is no VLAN configured\n");
-		netdev_features_clear(features,
+		netdev_features_clear(*features,
 				      NETIF_VLAN_STRIPPING_FEATURES);
 	}
-
-	return features;
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 05da0d2cc21f..a93e52cf01b3 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2432,18 +2432,16 @@ void igb_reset(struct igb_adapter *adapter)
 	igb_get_phy_info(hw);
 }
 
-static netdev_features_t igb_fix_features(struct net_device *netdev,
-	netdev_features_t features)
+static void igb_fix_features(struct net_device *netdev,
+			     netdev_features_t *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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int igb_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 83a5f3ed7cd6..65eb629cda99 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4972,18 +4972,16 @@ static void igc_get_stats64(struct net_device *netdev,
 	spin_unlock(&adapter->stats64_lock);
 }
 
-static netdev_features_t igc_fix_features(struct net_device *netdev,
-					  netdev_features_t features)
+static void igc_fix_features(struct net_device *netdev,
+			     netdev_features_t *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.
 	 */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int igc_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 0caf35886a95..bb0ce65cd025 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -294,17 +294,15 @@ ixgb_reset(struct ixgb_adapter *adapter)
 	}
 }
 
-static netdev_features_t
-ixgb_fix_features(struct net_device *netdev, netdev_features_t features)
+static void
+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 (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, features);
-
-	return features;
+	if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features))
+		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
 static int
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 731ac302cf8e..139eec69f5b9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9830,25 +9830,23 @@ void ixgbe_do_reset(struct net_device *netdev)
 		ixgbe_reset(adapter);
 }
 
-static netdev_features_t ixgbe_fix_features(struct net_device *netdev,
-					    netdev_features_t features)
+static void ixgbe_fix_features(struct net_device *netdev,
+			       netdev_features_t *features)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
 	/* If Rx checksum is disabled, then RSC/LRO should also be disabled */
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
-		netdev_feature_del(NETIF_F_LRO_BIT, features);
+	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);
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 
-	if (adapter->xdp_prog && netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+	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);
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 	}
-
-	return features;
 }
 
 static void ixgbe_reset_l2fw_offload(struct ixgbe_adapter *adapter)
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 8a9918e34249..fc967f35f8a7 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2661,14 +2661,13 @@ jme_set_msglevel(struct net_device *netdev, u32 value)
 	jme->msg_enable = value;
 }
 
-static netdev_features_t
-jme_fix_features(struct net_device *netdev, netdev_features_t features)
+static void
+jme_fix_features(struct net_device *netdev, netdev_features_t *features)
 {
 	if (netdev->mtu > 1900) {
-		netdev_features_clear(features, NETIF_F_ALL_TSO);
-		netdev_features_clear(features, NETIF_F_CSUM_MASK);
+		netdev_features_clear(*features, NETIF_F_ALL_TSO);
+		netdev_features_clear(*features, NETIF_F_CSUM_MASK);
 	}
-	return features;
 }
 
 static int
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index bf6b662c2c91..c5e56dff4311 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -3842,20 +3842,18 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu)
 	return 0;
 }
 
-static netdev_features_t mvneta_fix_features(struct net_device *dev,
-					     netdev_features_t features)
+static void mvneta_fix_features(struct net_device *dev,
+				netdev_features_t *features)
 {
 	struct mvneta_port *pp = netdev_priv(dev);
 
 	if (pp->tx_csum_limit && dev->mtu > pp->tx_csum_limit) {
-		netdev_features_clear_set(features, NETIF_F_IP_CSUM_BIT,
+		netdev_features_clear_set(*features, NETIF_F_IP_CSUM_BIT,
 					  NETIF_F_TSO_BIT);
 		netdev_info(dev,
 			    "Disable IP checksum for MTU greater than %dB\n",
 			    pp->tx_csum_limit);
 	}
-
-	return features;
 }
 
 /* Get mac address */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index c500f6f44569..839350458bc1 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1905,15 +1905,13 @@ static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
 	return netdev_pick_tx(netdev, skb, NULL);
 }
 
-static netdev_features_t otx2_fix_features(struct net_device *dev,
-					   netdev_features_t features)
+static void otx2_fix_features(struct net_device *dev,
+			      netdev_features_t *features)
 {
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
-		netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT, features);
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT, *features);
 }
 
 static void otx2_set_rx_mode(struct net_device *netdev)
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 959456dcc505..afa6234cdd8f 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4305,8 +4305,8 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
 	return rc < 0 ? rc : 0;
 }
 
-static netdev_features_t sky2_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void sky2_fix_features(struct net_device *dev,
+			      netdev_features_t *features)
 {
 	const struct sky2_port *sky2 = netdev_priv(dev);
 	const struct sky2_hw *hw = sky2->hw;
@@ -4316,20 +4316,18 @@ 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");
-		netdev_feature_del(NETIF_F_TSO_BIT, features);
-		netdev_feature_del(NETIF_F_SG_BIT, features);
-		netdev_features_clear(features, NETIF_F_CSUM_MASK);
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
+		netdev_feature_del(NETIF_F_SG_BIT, *features);
+		netdev_features_clear(*features, NETIF_F_CSUM_MASK);
 	}
 
 	/* Some hardware requires receive checksum for RSS to work. */
-	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features) &&
-	    !netdev_feature_test(NETIF_F_RXCSUM_BIT, features) &&
+	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);
+		netdev_feature_add(NETIF_F_RXCSUM_BIT, *features);
 	}
-
-	return features;
 }
 
 static int sky2_set_features(struct net_device *dev, netdev_features_t features)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 5c76433a70ab..c1236dd59f56 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2697,21 +2697,19 @@ static int mtk_hwlro_get_fdir_all(struct net_device *dev,
 	return 0;
 }
 
-static netdev_features_t mtk_fix_features(struct net_device *dev,
-					  netdev_features_t features)
+static void mtk_fix_features(struct net_device *dev,
+			     netdev_features_t *features)
 {
-	if (!netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+	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);
 
 		if (ip_cnt) {
 			netdev_info(dev, "RX flow is programmed, LRO should keep on\n");
 
-			netdev_feature_add(NETIF_F_LRO_BIT, features);
+			netdev_feature_add(NETIF_F_LRO_BIT, *features);
 		}
 	}
-
-	return features;
 }
 
 static int mtk_set_features(struct net_device *dev, netdev_features_t features)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 7cec4a97a3a1..3ace17bbbae0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2496,8 +2496,8 @@ static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	}
 }
 
-static netdev_features_t mlx4_en_fix_features(struct net_device *netdev,
-					      netdev_features_t features)
+static void mlx4_en_fix_features(struct net_device *netdev,
+				 netdev_features_t *features)
 {
 	struct mlx4_en_priv *en_priv = netdev_priv(netdev);
 	struct mlx4_en_dev *mdev = en_priv->mdev;
@@ -2506,13 +2506,11 @@ 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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) &&
+	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);
+		netdev_feature_add(NETIF_F_HW_VLAN_STAG_RX_BIT, *features);
 	else
-		netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT, features);
-
-	return features;
+		netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT, *features);
 }
 
 static int mlx4_en_set_features(struct net_device *netdev,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 7a7679262252..d6cc33d2079b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3892,30 +3892,28 @@ int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
 	return 0;
 }
 
-static netdev_features_t mlx5e_fix_uplink_rep_features(struct net_device *netdev,
-						       netdev_features_t features)
+static void mlx5e_fix_uplink_rep_features(struct net_device *netdev,
+					  netdev_features_t *features)
 {
-	netdev_feature_del(NETIF_F_HW_TLS_RX_BIT, features);
+	netdev_feature_del(NETIF_F_HW_TLS_RX_BIT, *features);
 	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);
+	netdev_feature_del(NETIF_F_HW_TLS_TX_BIT, *features);
 	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);
+	netdev_feature_del(NETIF_F_NTUPLE_BIT, *features);
 	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);
+	netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 	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;
 }
 
-static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
-					    netdev_features_t features)
+static void mlx5e_fix_features(struct net_device *netdev,
+			       netdev_features_t *features)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 	struct mlx5e_vlan_table *vlan;
@@ -3929,63 +3927,61 @@ 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.
 		 */
-		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_RX_BIT, features);
+		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");
 	}
 
 	if (!MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ)) {
-		if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+		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);
+			netdev_feature_del(NETIF_F_LRO_BIT, *features);
 		}
-		if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) {
+		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);
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 		}
 	}
 
 	if (params->xdp_prog) {
-		if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+		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);
+			netdev_feature_del(NETIF_F_LRO_BIT, *features);
 		}
-		if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) {
+		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);
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 		}
 	}
 
 	if (priv->xsk.refcnt) {
-		if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+		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);
+			netdev_feature_del(NETIF_F_LRO_BIT, *features);
 		}
-		if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) {
+		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);
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 		}
 	}
 
 	if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
-		netdev_feature_del(NETIF_F_RXHASH_BIT, features);
+		netdev_feature_del(NETIF_F_RXHASH_BIT, *features);
 		if (netdev_active_feature_test(netdev, NETIF_F_RXHASH_BIT))
 			netdev_warn(netdev, "Disabling rxhash, not supported when CQE compress is active\n");
 
-		if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features)) {
+		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);
+			netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 		}
 	}
 
 	if (mlx5e_is_uplink_rep(priv))
-		features = mlx5e_fix_uplink_rep_features(netdev, features);
+		mlx5e_fix_uplink_rep_features(netdev, features);
 
 	mutex_unlock(&priv->state_lock);
-
-	return features;
 }
 
 static bool mlx5e_xsk_validate_mtu(struct net_device *netdev,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 164fbeaa1ca4..754179c46769 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1756,29 +1756,28 @@ static int nfp_net_set_features(struct net_device *netdev,
 	return 0;
 }
 
-static netdev_features_t
+static void
 nfp_net_fix_features(struct net_device *netdev,
-		     netdev_features_t features)
+		     netdev_features_t *features)
 {
-	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_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);
+					   *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_active_feature_test(netdev, NETIF_F_HW_VLAN_STAG_RX_BIT)) {
 			netdev_feature_del(NETIF_F_HW_VLAN_STAG_RX_BIT,
-					   features);
+					   *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");
 		}
 	}
-	return features;
 }
 
 static void
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 0ab4f1b5e547..bb310a247e4b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -233,12 +233,12 @@ static int nfp_repr_open(struct net_device *netdev)
 	return err;
 }
 
-static netdev_features_t
-nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
+static void
+nfp_repr_fix_features(struct net_device *netdev, netdev_features_t *features)
 {
 	struct nfp_repr *repr = netdev_priv(netdev);
-	netdev_features_t old_features = features;
 	netdev_features_t lower_features;
+	netdev_features_t old_features;
 	struct net_device *lower_dev;
 	netdev_features_t tmp;
 
@@ -248,14 +248,13 @@ nfp_repr_fix_features(struct net_device *netdev, netdev_features_t features)
 	if (netdev_features_intersects(lower_features, netdev_ip_csum_features))
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, lower_features);
 
-	netdev_intersect_features(&features, &features, &lower_features);
+	netdev_features_copy(old_features, *features);
+	netdev_intersect_features(features, features, &lower_features);
 	tmp = NETIF_F_SOFT_FEATURES;
 	netdev_feature_add(NETIF_F_HW_TC_BIT, tmp);
 	netdev_features_mask(tmp, old_features);
-	netdev_features_set(features, tmp);
-	netdev_feature_add(NETIF_F_LLTX_BIT, features);
-
-	return features;
+	netdev_features_set(*features, tmp);
+	netdev_feature_add(NETIF_F_LLTX_BIT, *features);
 }
 
 const struct net_device_ops nfp_repr_netdev_ops = {
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index c6bce7f847b7..82bccdfcfa50 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4927,14 +4927,11 @@ static int nv_set_loopback(struct net_device *dev, netdev_features_t features)
 	return retval;
 }
 
-static netdev_features_t nv_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void nv_fix_features(struct net_device *dev, netdev_features_t *features)
 {
 	/* vlan is dependent on rx checksum offload */
-	if (netdev_features_intersects(features, netdev_ctag_vlan_offload_features))
-		netdev_feature_add(NETIF_F_RXCSUM_BIT, features);
-
-	return features;
+	if (netdev_features_intersects(*features, netdev_ctag_vlan_offload_features))
+		netdev_feature_add(NETIF_F_RXCSUM_BIT, *features);
 }
 
 static void nv_vlan_mode(struct net_device *dev, netdev_features_t features)
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 15dc30e0dff5..e2af570cda6e 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -520,16 +520,14 @@ static void netxen_set_multicast_list(struct net_device *dev)
 	adapter->set_multi(dev);
 }
 
-static netdev_features_t netxen_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void netxen_fix_features(struct net_device *dev,
+				netdev_features_t *features)
 {
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
+	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);
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 	}
-
-	return features;
 }
 
 static int netxen_set_features(struct net_device *dev,
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index c1f26a2e374d..ada71452d454 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -545,8 +545,7 @@ int qede_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid);
 void qede_vlan_mark_nonconfigured(struct qede_dev *edev);
 int qede_configure_vlan_filters(struct qede_dev *edev);
 
-netdev_features_t qede_fix_features(struct net_device *dev,
-				    netdev_features_t features);
+void qede_fix_features(struct net_device *dev, netdev_features_t *features);
 int qede_set_features(struct net_device *dev, netdev_features_t features);
 void qede_set_rx_mode(struct net_device *ndev);
 void qede_config_rx_mode(struct net_device *ndev);
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index 4fb113d9713e..b6d6ce69929c 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -910,16 +910,13 @@ static void qede_set_features_reload(struct qede_dev *edev,
 	edev->ndev->features = args->u.features;
 }
 
-netdev_features_t qede_fix_features(struct net_device *dev,
-				    netdev_features_t features)
+void qede_fix_features(struct net_device *dev, netdev_features_t *features)
 {
 	struct qede_dev *edev = netdev_priv(dev);
 
 	if (edev->xdp_prog || edev->ndev->mtu > PAGE_SIZE ||
-	    !netdev_feature_test(NETIF_F_GRO_BIT, features))
-		netdev_feature_del(NETIF_F_GRO_HW_BIT, features);
-
-	return features;
+	    !netdev_feature_test(NETIF_F_GRO_BIT, *features))
+		netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 }
 
 int qede_set_features(struct net_device *dev, netdev_features_t features)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index b25102fded7b..9b41e2f5c82c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1622,8 +1622,8 @@ int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *);
 int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu);
 int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *, u32);
 int qlcnic_change_mtu(struct net_device *netdev, int new_mtu);
-netdev_features_t qlcnic_fix_features(struct net_device *netdev,
-	netdev_features_t features);
+void qlcnic_fix_features(struct net_device *netdev,
+			 netdev_features_t *features);
 int qlcnic_set_features(struct net_device *netdev, netdev_features_t features);
 int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
 void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index b97bbb07d06a..3efc9f294712 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1021,45 +1021,42 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
 	return rc;
 }
 
-static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
-					      netdev_features_t features)
+static void qlcnic_process_flags(struct qlcnic_adapter *adapter,
+				 netdev_features_t *features)
 {
 	u32 offload_flags = adapter->offload_flags;
 
 	if (offload_flags & BIT_0) {
-		netdev_features_set_set(features, NETIF_F_RXCSUM_BIT,
+		netdev_features_set_set(*features, NETIF_F_RXCSUM_BIT,
 					NETIF_F_IP_CSUM_BIT,
 					NETIF_F_IPV6_CSUM_BIT);
 		adapter->rx_csum = 1;
 		if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
 			if (!(offload_flags & BIT_1))
-				netdev_feature_del(NETIF_F_TSO_BIT, features);
+				netdev_feature_del(NETIF_F_TSO_BIT, *features);
 			else
-				netdev_feature_add(NETIF_F_TSO_BIT, features);
+				netdev_feature_add(NETIF_F_TSO_BIT, *features);
 
 			if (!(offload_flags & BIT_2))
 				netdev_feature_del(NETIF_F_TSO6_BIT,
-						   features);
+						   *features);
 			else
 				netdev_feature_add(NETIF_F_TSO6_BIT,
-						   features);
+						   *features);
 		}
 	} else {
-		netdev_features_clear_set(features, NETIF_F_RXCSUM_BIT,
+		netdev_features_clear_set(*features, NETIF_F_RXCSUM_BIT,
 					  NETIF_F_IP_CSUM_BIT,
 					  NETIF_F_IPV6_CSUM_BIT);
 
 		if (QLCNIC_IS_TSO_CAPABLE(adapter))
-			netdev_features_clear(features,
+			netdev_features_clear(*features,
 					      netdev_general_tso_features);
 		adapter->rx_csum = 0;
 	}
-
-	return features;
 }
 
-netdev_features_t qlcnic_fix_features(struct net_device *netdev,
-	netdev_features_t features)
+void qlcnic_fix_features(struct net_device *netdev, netdev_features_t *features)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changeable;
@@ -1068,10 +1065,10 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 	if (qlcnic_82xx_check(adapter) &&
 	    (adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
 		if (adapter->flags & QLCNIC_APP_CHANGED_FLAGS) {
-			features = qlcnic_process_flags(adapter, features);
+			qlcnic_process_flags(adapter, features);
 		} else {
 			netdev_features_xor(changed, netdev->features,
-					    features);
+					    *features);
 			netdev_features_zero(changeable);
 			netdev_features_set_set(changeable,
 						NETIF_F_RXCSUM_BIT,
@@ -1080,14 +1077,12 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 						NETIF_F_TSO_BIT,
 						NETIF_F_TSO6_BIT);
 			netdev_features_mask(changed, changeable);
-			netdev_features_toggle(features, changed);
+			netdev_features_toggle(*features, changed);
 		}
 	}
 
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
-		netdev_feature_del(NETIF_F_LRO_BIT, features);
-
-	return features;
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 }
 
 
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 7434f3c06dc6..7f1dd10b6387 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1422,21 +1422,19 @@ static int rtl8169_get_regs_len(struct net_device *dev)
 	return R8169_REGS_SIZE;
 }
 
-static netdev_features_t rtl8169_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void rtl8169_fix_features(struct net_device *dev,
+				 netdev_features_t *features)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 
 	if (dev->mtu > TD_MSS_MAX)
-		netdev_features_clear(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) {
-		netdev_features_clear(features, NETIF_F_CSUM_MASK);
-		netdev_features_clear(features, NETIF_F_ALL_TSO);
+		netdev_features_clear(*features, NETIF_F_CSUM_MASK);
+		netdev_features_clear(*features, NETIF_F_ALL_TSO);
 	}
-
-	return features;
 }
 
 static void rtl_set_rx_config_features(struct rtl8169_private *tp,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 05dc3483757d..c70f297c1653 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5585,16 +5585,16 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
 	return 0;
 }
 
-static netdev_features_t stmmac_fix_features(struct net_device *dev,
-					     netdev_features_t features)
+static void stmmac_fix_features(struct net_device *dev,
+				netdev_features_t *features)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
-		netdev_feature_del(NETIF_F_RXCSUM_BIT, features);
+		netdev_feature_del(NETIF_F_RXCSUM_BIT, *features);
 
 	if (!priv->plat->tx_coe)
-		netdev_features_clear(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
@@ -5602,17 +5602,15 @@ 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))
-		netdev_features_clear(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)) {
-		if (netdev_feature_test(NETIF_F_TSO_BIT, features))
+		if (netdev_feature_test(NETIF_F_TSO_BIT, *features))
 			priv->tso = true;
 		else
 			priv->tso = false;
 	}
-
-	return features;
 }
 
 static int stmmac_set_features(struct net_device *netdev,
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 98e2b649fabf..e89fcfc52247 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1904,21 +1904,19 @@ static int netvsc_set_ringparam(struct net_device *ndev,
 	return ret;
 }
 
-static netdev_features_t netvsc_fix_features(struct net_device *ndev,
-					     netdev_features_t features)
+static void netvsc_fix_features(struct net_device *ndev,
+				netdev_features_t *features)
 {
 	struct net_device_context *ndevctx = netdev_priv(ndev);
 	struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
 
 	if (!nvdev || nvdev->destroy)
-		return features;
+		return;
 
-	if (netdev_feature_test(NETIF_F_LRO_BIT, features) && netvsc_xdp_get(nvdev)) {
-		netdev_feature_change(NETIF_F_LRO_BIT, features);
+	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");
 	}
-
-	return features;
 }
 
 static int netvsc_set_features(struct net_device *ndev,
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index e7737e7938fd..31d5e203e035 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -227,24 +227,22 @@ static netdev_tx_t ipvlan_start_xmit(struct sk_buff *skb,
 	return ret;
 }
 
-static netdev_features_t ipvlan_fix_features(struct net_device *dev,
-					     netdev_features_t features)
+static void ipvlan_fix_features(struct net_device *dev,
+				netdev_features_t *features)
 {
 	struct ipvl_dev *ipvlan = netdev_priv(dev);
 	netdev_features_t tmp;
 
-	netdev_features_set(features, NETIF_F_ALL_FOR_ALL);
+	netdev_features_set(*features, NETIF_F_ALL_FOR_ALL);
 	netdev_features_fill(tmp);
 	netdev_features_clear(tmp, IPVLAN_FEATURES);
 	netdev_features_set(tmp, ipvlan->sfeatures);
-	netdev_features_mask(features, tmp);
-	netdev_increment_features(&features, &ipvlan->phy_dev->features,
-				  &features, &features);
-	netdev_features_set(features, IPVLAN_ALWAYS_ON);
+	netdev_features_mask(*features, tmp);
+	netdev_increment_features(features, &ipvlan->phy_dev->features,
+				  features, features);
+	netdev_features_set(*features, IPVLAN_ALWAYS_ON);
 	netdev_features_or(tmp, IPVLAN_FEATURES, IPVLAN_ALWAYS_ON);
-	netdev_features_mask(features, tmp);
-
-	return features;
+	netdev_features_mask(*features, tmp);
 }
 
 static void ipvlan_change_rx_flags(struct net_device *dev, int change)
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index b5d263c6469f..513e1ff7a2a0 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3512,26 +3512,24 @@ static void macsec_dev_uninit(struct net_device *dev)
 	free_percpu(dev->tstats);
 }
 
-static netdev_features_t macsec_fix_features(struct net_device *dev,
-					     netdev_features_t features)
+static void macsec_fix_features(struct net_device *dev,
+				netdev_features_t *features)
 {
 	struct macsec_dev *macsec = macsec_priv(dev);
 	struct net_device *real_dev = macsec->real_dev;
 	netdev_features_t tmp;
 
 	if (macsec_is_offloaded(macsec)) {
-		macsec_real_dev_features(real_dev, &tmp);
-		return tmp;
+		macsec_real_dev_features(real_dev, features);
+		return;
 	}
 
 	netdev_features_and(tmp, real_dev->features, SW_MACSEC_FEATURES);
 	netdev_features_set(tmp, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set(tmp, NETIF_F_SOFT_FEATURES);
 
-	netdev_features_mask(features, tmp);
-	netdev_feature_add(NETIF_F_LLTX_BIT, features);
-
-	return features;
+	netdev_features_mask(*features, tmp);
+	netdev_feature_add(NETIF_F_LLTX_BIT, *features);
 }
 
 static int macsec_dev_open(struct net_device *dev)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 1e357643fd43..21071335c0ac 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1073,31 +1073,29 @@ static int macvlan_ethtool_get_ts_info(struct net_device *dev,
 	return 0;
 }
 
-static netdev_features_t macvlan_fix_features(struct net_device *dev,
-					      netdev_features_t features)
+static void macvlan_fix_features(struct net_device *dev,
+				 netdev_features_t *features)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	netdev_features_t lowerdev_features = vlan->lowerdev->features;
 	netdev_features_t mask;
 	netdev_features_t tmp;
 
-	netdev_features_set(features, NETIF_F_ALL_FOR_ALL);
+	netdev_features_set(*features, NETIF_F_ALL_FOR_ALL);
 	netdev_features_fill(tmp);
 	netdev_features_clear(tmp, MACVLAN_FEATURES);
 	netdev_features_set(tmp, vlan->set_features);
-	netdev_features_mask(features, tmp);
-	mask = features;
+	netdev_features_mask(*features, tmp);
+	netdev_features_copy(mask, *features);
 
-	tmp = features;
+	netdev_features_copy(tmp, *features);
 	netdev_feature_del(NETIF_F_LRO_BIT, tmp);
 	netdev_features_mask(lowerdev_features, tmp);
-	netdev_increment_features(&features, &lowerdev_features, &features,
+	netdev_increment_features(features, &lowerdev_features, features,
 				  &mask);
-	netdev_features_set(features, ALWAYS_ON_FEATURES);
+	netdev_features_set(*features, ALWAYS_ON_FEATURES);
 	netdev_features_or(tmp, ALWAYS_ON_FEATURES, MACVLAN_FEATURES);
-	netdev_features_mask(features, tmp);
-
-	return features;
+	netdev_features_mask(*features, tmp);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 508424471c28..1f9642b400ec 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2000,27 +2000,25 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
 	return err;
 }
 
-static netdev_features_t team_fix_features(struct net_device *dev,
-					   netdev_features_t features)
+static void team_fix_features(struct net_device *dev,
+			      netdev_features_t *features)
 {
 	struct team_port *port;
 	struct team *team = netdev_priv(dev);
 	netdev_features_t mask;
 
-	mask = features;
-	netdev_features_clear(features, NETIF_F_ONE_FOR_ALL);
-	netdev_features_set(features, NETIF_F_ALL_FOR_ALL);
+	netdev_features_copy(mask, *features);
+	netdev_features_clear(*features, NETIF_F_ONE_FOR_ALL);
+	netdev_features_set(*features, NETIF_F_ALL_FOR_ALL);
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(port, &team->port_list, list) {
-		netdev_increment_features(&features, &features,
+		netdev_increment_features(features, features,
 					  &port->dev->features, &mask);
 	}
 	rcu_read_unlock();
 
-	netdev_add_tso_features(&features, &mask);
-
-	return features;
+	netdev_add_tso_features(features, &mask);
 }
 
 static int team_change_carrier(struct net_device *dev, bool new_carrier)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index b9bc7ff7c283..d2e6bfb5edd4 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1165,15 +1165,15 @@ static void tun_net_mclist(struct net_device *dev)
 	 */
 }
 
-static netdev_features_t tun_net_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void tun_net_fix_features(struct net_device *dev,
+				 netdev_features_t *features)
 {
 	struct tun_struct *tun = netdev_priv(dev);
 	netdev_features_t tmp1, tmp2;
 
-	netdev_features_and(tmp1, features, tun->set_features);
-	netdev_features_andnot(tmp2, features, TUN_USER_FEATURES);
-	return tmp1 | tmp2;
+	netdev_features_and(tmp1, *features, tun->set_features);
+	netdev_features_andnot(tmp2, *features, TUN_USER_FEATURES);
+	netdev_features_or(*features, tmp1, tmp2);
 }
 
 static void tun_set_headroom(struct net_device *dev, int new_hr)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 0e5bfe2ebfd2..ac7a6ebadf00 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1449,8 +1449,8 @@ static int veth_get_iflink(const struct net_device *dev)
 	return iflink;
 }
 
-static netdev_features_t veth_fix_features(struct net_device *dev,
-					   netdev_features_t features)
+static void veth_fix_features(struct net_device *dev,
+			      netdev_features_t *features)
 {
 	struct veth_priv *priv = netdev_priv(dev);
 	struct net_device *peer;
@@ -1460,12 +1460,10 @@ static netdev_features_t veth_fix_features(struct net_device *dev,
 		struct veth_priv *peer_priv = netdev_priv(peer);
 
 		if (peer_priv->_xdp_prog)
-			netdev_features_clear(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);
-
-	return features;
+		netdev_feature_add(NETIF_F_GRO_BIT, *features);
 }
 
 static int veth_set_features(struct net_device *dev,
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 9b7adc83c210..6f6338a22c31 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -246,14 +246,12 @@ vmxnet3_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
 		ethtool_sprintf(&buf, vmxnet3_global_stats[i].desc);
 }
 
-netdev_features_t vmxnet3_fix_features(struct net_device *netdev,
-				       netdev_features_t features)
+void vmxnet3_fix_features(struct net_device *netdev,
+			  netdev_features_t *features)
 {
 	/* If Rx checksum is disabled, then LRO should also be disabled */
-	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
-		netdev_feature_del(NETIF_F_LRO_BIT, features);
-
-	return features;
+	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
+		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 }
 
 void vmxnet3_features_check(struct sk_buff *skb, struct net_device *netdev,
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 4fe7be614c05..c9aac6a8e65c 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -491,8 +491,8 @@ vmxnet3_tq_destroy_all(struct vmxnet3_adapter *adapter);
 void
 vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter);
 
-netdev_features_t
-vmxnet3_fix_features(struct net_device *netdev, netdev_features_t features);
+void
+vmxnet3_fix_features(struct net_device *netdev, netdev_features_t *features);
 
 void
 vmxnet3_features_check(struct sk_buff *skb,
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 0de51ba7bed3..62677a757409 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -360,23 +360,21 @@ static int xenvif_change_mtu(struct net_device *dev, int mtu)
 	return 0;
 }
 
-static netdev_features_t xenvif_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void xenvif_fix_features(struct net_device *dev,
+				netdev_features_t *features)
 {
 	struct xenvif *vif = netdev_priv(dev);
 
 	if (!vif->can_sg)
-		netdev_feature_del(NETIF_F_SG_BIT, features);
+		netdev_feature_del(NETIF_F_SG_BIT, *features);
 	if (~(vif->gso_mask) & GSO_BIT(TCPV4))
-		netdev_feature_del(NETIF_F_TSO_BIT, features);
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
 	if (~(vif->gso_mask) & GSO_BIT(TCPV6))
-		netdev_feature_del(NETIF_F_TSO6_BIT, features);
+		netdev_feature_del(NETIF_F_TSO6_BIT, *features);
 	if (!vif->ip_csum)
-		netdev_feature_del(NETIF_F_IP_CSUM_BIT, features);
+		netdev_feature_del(NETIF_F_IP_CSUM_BIT, *features);
 	if (!vif->ipv6_csum)
-		netdev_feature_del(NETIF_F_IPV6_CSUM_BIT, features);
-
-	return features;
+		netdev_feature_del(NETIF_F_IPV6_CSUM_BIT, *features);
 }
 
 static const struct xenvif_stat {
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index fedbd35aa1c1..f83a5e3c6de9 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1471,29 +1471,27 @@ static void xennet_release_rx_bufs(struct netfront_queue *queue)
 	spin_unlock_bh(&queue->rx_lock);
 }
 
-static netdev_features_t xennet_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void xennet_fix_features(struct net_device *dev,
+				netdev_features_t *features)
 {
 	struct netfront_info *np = netdev_priv(dev);
 
-	if (netdev_feature_test(NETIF_F_SG_BIT, features) &&
+	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);
+		netdev_feature_del(NETIF_F_SG_BIT, *features);
 
-	if (netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, features) &&
+	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);
+		netdev_feature_del(NETIF_F_IPV6_CSUM_BIT, *features);
 
-	if (netdev_feature_test(NETIF_F_TSO_BIT, features) &&
+	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);
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
 
-	if (netdev_feature_test(NETIF_F_TSO6_BIT, features) &&
+	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);
-
-	return features;
+		netdev_feature_del(NETIF_F_TSO6_BIT, *features);
 }
 
 static int xennet_set_features(struct net_device *dev,
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 3015edb0ac66..6214f7f0d5ae 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -1087,7 +1087,7 @@ int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
 int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
 int qeth_set_features(struct net_device *, netdev_features_t);
 void qeth_enable_hw_features(struct net_device *dev);
-netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t);
+void qeth_fix_features(struct net_device *, netdev_features_t *);
 void qeth_features_check(struct sk_buff *skb, struct net_device *dev,
 			 netdev_features_t *features);
 void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 9bed9ba8f6c4..31326e81344f 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6850,26 +6850,24 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
 }
 EXPORT_SYMBOL_GPL(qeth_set_features);
 
-netdev_features_t qeth_fix_features(struct net_device *dev,
-				    netdev_features_t features)
+void qeth_fix_features(struct net_device *dev, netdev_features_t *features)
 {
 	struct qeth_card *card = dev->ml_priv;
 
 	QETH_CARD_TEXT(card, 2, "fixfeat");
 	if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
-		netdev_feature_del(NETIF_F_IP_CSUM_BIT, features);
+		netdev_feature_del(NETIF_F_IP_CSUM_BIT, *features);
 	if (!qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6))
-		netdev_feature_del(NETIF_F_IPV6_CSUM_BIT, features);
+		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))
-		netdev_feature_del(NETIF_F_RXCSUM_BIT, features);
+		netdev_feature_del(NETIF_F_RXCSUM_BIT, *features);
 	if (!qeth_is_supported(card, IPA_OUTBOUND_TSO))
-		netdev_feature_del(NETIF_F_TSO_BIT, features);
+		netdev_feature_del(NETIF_F_TSO_BIT, *features);
 	if (!qeth_is_supported6(card, IPA_OUTBOUND_TSO))
-		netdev_feature_del(NETIF_F_TSO6_BIT, features);
+		netdev_feature_del(NETIF_F_TSO6_BIT, *features);
 
-	QETH_CARD_HEX(card, 2, &features, sizeof(features));
-	return features;
+	QETH_CARD_HEX(card, 2, features, sizeof(*features));
 }
 EXPORT_SYMBOL_GPL(qeth_fix_features);
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 78b0c501a24a..63e97effa858 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1514,8 +1514,8 @@ struct net_device_ops {
 						      bool all_slaves);
 	struct net_device*	(*ndo_sk_get_lower_dev)(struct net_device *dev,
 							struct sock *sk);
-	netdev_features_t	(*ndo_fix_features)(struct net_device *dev,
-						    netdev_features_t features);
+	void			(*ndo_fix_features)(struct net_device *dev,
+						    netdev_features_t *features);
 	int			(*ndo_set_features)(struct net_device *dev,
 						    netdev_features_t features);
 	int			(*ndo_neigh_construct)(struct net_device *dev,
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index d03348e29f36..2fa0b4ea260b 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -645,30 +645,29 @@ static void vlan_dev_uninit(struct net_device *dev)
 	vlan_dev_free_egress_priority(dev);
 }
 
-static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void vlan_dev_fix_features(struct net_device *dev,
+				  netdev_features_t *features)
 {
 	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 old_features;
 	netdev_features_t tmp;
 
 	tmp = real_dev->vlan_features;
 	netdev_feature_add(NETIF_F_RXCSUM_BIT, tmp);
 	netdev_intersect_features(&lower_features, &tmp, &real_dev->features);
 
+	netdev_features_copy(old_features, *features);
 	/* Add HW_CSUM setting to preserve user ability to control
 	 * checksum offload on the vlan device.
 	 */
 	if (netdev_features_intersects(lower_features, netdev_ip_csum_features))
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, lower_features);
-	netdev_intersect_features(&features, &features, &lower_features);
+	netdev_intersect_features(features, features, &lower_features);
 	netdev_features_or(tmp, NETIF_F_SOFT_FEATURES, NETIF_F_GSO_SOFTWARE);
 	netdev_features_mask(tmp, old_features);
-	netdev_features_set(features, tmp);
-	netdev_feature_add(NETIF_F_LLTX_BIT, features);
-
-	return features;
+	netdev_features_set(*features, tmp);
+	netdev_feature_add(NETIF_F_LLTX_BIT, *features);
 }
 
 static int vlan_ethtool_get_link_ksettings(struct net_device *dev,
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index f1d851deb536..fafcc67ca3bc 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -286,12 +286,11 @@ static int br_get_link_ksettings(struct net_device *dev,
 	return 0;
 }
 
-static netdev_features_t br_fix_features(struct net_device *dev,
-	netdev_features_t features)
+static void br_fix_features(struct net_device *dev, netdev_features_t *features)
 {
 	struct net_bridge *br = netdev_priv(dev);
 
-	return br_features_recompute(br, features);
+	br_features_recompute(br, features);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 2a9b564ff234..a971650b52e4 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -532,25 +532,22 @@ static void br_set_gso_limits(struct net_bridge *br)
 /*
  * Recomputes features using slave's features
  */
-netdev_features_t br_features_recompute(struct net_bridge *br,
-	netdev_features_t features)
+void br_features_recompute(struct net_bridge *br, netdev_features_t *features)
 {
 	struct net_bridge_port *p;
 	netdev_features_t mask;
 
 	if (list_empty(&br->port_list))
-		return features;
+		return;
 
-	mask = features;
-	netdev_features_clear(features, NETIF_F_ONE_FOR_ALL);
+	netdev_features_copy(mask, *features);
+	netdev_features_clear(*features, NETIF_F_ONE_FOR_ALL);
 
 	list_for_each_entry(p, &br->port_list, list) {
-		netdev_increment_features(&features, &features,
+		netdev_increment_features(features, features,
 					  &p->dev->features, &mask);
 	}
-	netdev_add_tso_features(&features, &mask);
-
-	return features;
+	netdev_add_tso_features(features, &mask);
 }
 
 /* called with RTNL */
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 06e5f6faa431..e6ccd246c325 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -846,8 +846,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
 	      struct netlink_ext_ack *extack);
 int br_del_if(struct net_bridge *br, struct net_device *dev);
 void br_mtu_auto_adjust(struct net_bridge *br);
-netdev_features_t br_features_recompute(struct net_bridge *br,
-					netdev_features_t features);
+void br_features_recompute(struct net_bridge *br, netdev_features_t *features);
 void br_port_flags_change(struct net_bridge_port *port, unsigned long mask);
 void br_manage_promisc(struct net_bridge *br);
 int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 5e84fdc8c7f5..0d5df1d4f712 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9716,7 +9716,7 @@ int __netdev_update_features(struct net_device *dev)
 	netdev_get_wanted_features(dev, &features);
 
 	if (dev->netdev_ops->ndo_fix_features)
-		features = dev->netdev_ops->ndo_fix_features(dev, features);
+		dev->netdev_ops->ndo_fix_features(dev, &features);
 
 	/* driver might be less strict about feature dependencies */
 	netdev_fix_features(dev, &features);
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index ae0261a450e6..7d89d3a72e54 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -178,13 +178,13 @@ static int hsr_dev_close(struct net_device *dev)
 	return 0;
 }
 
-static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr,
-						netdev_features_t features)
+static void hsr_features_recompute(struct hsr_priv *hsr,
+				   netdev_features_t *features)
 {
 	netdev_features_t mask;
 	struct hsr_port *port;
 
-	mask = features;
+	netdev_features_copy(mask, *features);
 
 	/* Mask out all features that, if supported by one device, should be
 	 * enabled for all devices (see NETIF_F_ONE_FOR_ALL).
@@ -193,20 +193,18 @@ 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.
 	 */
-	netdev_features_clear(features, NETIF_F_ONE_FOR_ALL);
+	netdev_features_clear(*features, NETIF_F_ONE_FOR_ALL);
 	hsr_for_each_port(hsr, port)
-		netdev_increment_features(&features, &features,
+		netdev_increment_features(features, features,
 					  &port->dev->features, &mask);
-
-	return features;
 }
 
-static netdev_features_t hsr_fix_features(struct net_device *dev,
-					  netdev_features_t features)
+static void hsr_fix_features(struct net_device *dev,
+			     netdev_features_t *features)
 {
 	struct hsr_priv *hsr = netdev_priv(dev);
 
-	return hsr_features_recompute(hsr, features);
+	hsr_features_recompute(hsr, features);
 }
 
 static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-- 
2.33.0


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

* [RFCv8 PATCH net-next 43/55] net: adjust the prototype of xxx_set_features()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (41 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 42/55] net: adjust the prototype of ndo_fix_features Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 44/55] net: adjust the prototype fo xxx_gso_segment() family Jian Shen
                   ` (13 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function net_device_ops.ndo_set_features() using
netdev_features_t as parameters. For the prototype of
netdev_features_t will be extended to be larger than 8
bytes, so change the prototype of the function, change
the prototype of input features to'netdev_features_t *'.

So changes all the implement for this function of all
the netdev drivers, and relative functions.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 arch/um/drivers/vector_kern.c                 |  4 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      | 20 ++++----
 .../net/ethernet/aquantia/atlantic/aq_main.c  | 16 +++---
 drivers/net/ethernet/asix/ax88796c_main.c     |  6 +--
 .../net/ethernet/atheros/atl1c/atl1c_main.c   | 13 ++---
 .../net/ethernet/atheros/atl1e/atl1e_main.c   | 24 +++++----
 drivers/net/ethernet/atheros/atlx/atl1.c      |  4 +-
 drivers/net/ethernet/atheros/atlx/atl2.c      | 14 ++---
 drivers/net/ethernet/atheros/atlx/atlx.c      | 12 ++---
 drivers/net/ethernet/broadcom/bcmsysport.c    | 16 +++---
 drivers/net/ethernet/broadcom/bnx2.c          |  8 +--
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c   |  8 +--
 .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h   |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 11 ++--
 .../net/ethernet/broadcom/genet/bcmgenet.c    |  6 +--
 drivers/net/ethernet/broadcom/tg3.c           | 12 +++--
 drivers/net/ethernet/brocade/bna/bnad.c       |  7 +--
 drivers/net/ethernet/cadence/macb_main.c      | 23 +++++----
 drivers/net/ethernet/calxeda/xgmac.c          |  7 +--
 .../net/ethernet/cavium/liquidio/lio_main.c   | 14 ++---
 .../ethernet/cavium/liquidio/lio_vf_main.c    | 12 ++---
 .../net/ethernet/cavium/thunder/nicvf_main.c  |  8 +--
 .../ethernet/cavium/thunder/nicvf_queues.c    |  7 +--
 .../ethernet/cavium/thunder/nicvf_queues.h    |  2 +-
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c     |  7 +--
 drivers/net/ethernet/chelsio/cxgb/sge.c       |  4 +-
 drivers/net/ethernet/chelsio/cxgb/sge.h       |  2 +-
 .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   | 14 ++---
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  9 ++--
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  6 +--
 drivers/net/ethernet/cortina/gemini.c         |  4 +-
 drivers/net/ethernet/davicom/dm9000.c         |  6 +--
 drivers/net/ethernet/engleder/tsnep_main.c    |  6 +--
 drivers/net/ethernet/faraday/ftgmac100.c      |  4 +-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 10 ++--
 drivers/net/ethernet/freescale/enetc/enetc.c  | 12 ++---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +-
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  8 +--
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  2 +-
 drivers/net/ethernet/freescale/fec_main.c     | 12 ++---
 drivers/net/ethernet/freescale/gianfar.h      |  2 +-
 .../net/ethernet/freescale/gianfar_ethtool.c  |  6 +--
 drivers/net/ethernet/google/gve/gve_main.c    |  4 +-
 drivers/net/ethernet/hisilicon/hns/hns_enet.c |  8 +--
 .../net/ethernet/hisilicon/hns3/hns3_enet.c   | 16 +++---
 .../net/ethernet/huawei/hinic/hinic_main.c    | 26 +++++-----
 drivers/net/ethernet/ibm/ibmveth.c            | 12 ++---
 drivers/net/ethernet/intel/e100.c             |  6 +--
 drivers/net/ethernet/intel/e1000/e1000_main.c | 18 +++----
 drivers/net/ethernet/intel/e1000e/netdev.c    |  8 +--
 drivers/net/ethernet/intel/i40e/i40e.h        |  2 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c   | 16 +++---
 drivers/net/ethernet/intel/iavf/iavf.h        |  4 +-
 drivers/net/ethernet/intel/iavf/iavf_main.c   | 28 +++++-----
 drivers/net/ethernet/intel/ice/ice_main.c     | 51 ++++++++++---------
 drivers/net/ethernet/intel/igb/igb_main.c     | 17 ++++---
 drivers/net/ethernet/intel/igbvf/netdev.c     |  4 +-
 drivers/net/ethernet/intel/igc/igc_main.c     | 15 +++---
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  7 +--
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 14 ++---
 drivers/net/ethernet/jme.c                    |  5 +-
 drivers/net/ethernet/marvell/mv643xx_eth.c    |  7 +--
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  8 +--
 .../marvell/octeontx2/nic/otx2_common.c       |  9 ++--
 .../marvell/octeontx2/nic/otx2_common.h       |  2 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  8 +--
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  2 +-
 drivers/net/ethernet/marvell/sky2.c           | 22 ++++----
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  7 +--
 .../net/ethernet/mellanox/mlx4/en_netdev.c    | 48 ++++++++---------
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h  |  2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en.h  |  2 +-
 .../net/ethernet/mellanox/mlx5/core/en_main.c |  7 ++-
 .../net/ethernet/mellanox/mlxsw/spectrum.c    | 10 ++--
 drivers/net/ethernet/micrel/ksz884x.c         |  4 +-
 drivers/net/ethernet/mscc/ocelot_net.c        | 10 ++--
 drivers/net/ethernet/neterion/s2io.c          |  7 +--
 .../ethernet/netronome/nfp/nfp_net_common.c   | 22 ++++----
 drivers/net/ethernet/netronome/nfp/nfp_port.c |  5 +-
 drivers/net/ethernet/netronome/nfp/nfp_port.h |  3 +-
 drivers/net/ethernet/nvidia/forcedeth.c       | 23 +++++----
 .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  4 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 42 +++++++--------
 .../ethernet/qlogic/netxen/netxen_nic_main.c  |  8 +--
 drivers/net/ethernet/qlogic/qede/qede.h       |  2 +-
 .../net/ethernet/qlogic/qede/qede_filter.c    |  6 +--
 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h   |  3 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |  7 +--
 drivers/net/ethernet/qualcomm/emac/emac.c     |  6 +--
 drivers/net/ethernet/realtek/8139cp.c         |  9 ++--
 drivers/net/ethernet/realtek/8139too.c        |  7 +--
 drivers/net/ethernet/realtek/r8169_main.c     | 16 +++---
 drivers/net/ethernet/renesas/ravb.h           |  3 +-
 drivers/net/ethernet/renesas/ravb_main.c      | 12 ++---
 drivers/net/ethernet/renesas/sh_eth.c         |  8 +--
 .../net/ethernet/samsung/sxgbe/sxgbe_main.c   |  6 +--
 drivers/net/ethernet/sfc/efx_common.c         |  6 +--
 drivers/net/ethernet/sfc/efx_common.h         |  2 +-
 drivers/net/ethernet/sfc/falcon/efx.c         |  7 +--
 drivers/net/ethernet/sfc/siena/efx_common.c   |  7 +--
 drivers/net/ethernet/sfc/siena/efx_common.h   |  2 +-
 drivers/net/ethernet/socionext/netsec.c       |  5 +-
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  4 +-
 .../net/ethernet/synopsys/dwc-xlgmac-net.c    | 20 ++++----
 drivers/net/hyperv/netvsc_drv.c               | 14 ++---
 drivers/net/netdevsim/netdev.c                |  4 +-
 drivers/net/usb/aqc111.c                      |  8 +--
 drivers/net/usb/ax88179_178a.c                |  4 +-
 drivers/net/usb/lan78xx.c                     | 10 ++--
 drivers/net/usb/r8152.c                       |  6 +--
 drivers/net/usb/smsc75xx.c                    |  6 +--
 drivers/net/usb/smsc95xx.c                    |  8 +--
 drivers/net/veth.c                            |  6 +--
 drivers/net/virtio_net.c                      |  8 +--
 drivers/net/vmxnet3/vmxnet3_ethtool.c         | 22 ++++----
 drivers/net/vmxnet3/vmxnet3_int.h             |  3 +-
 drivers/net/wireless/ath/ath6kl/main.c        | 10 ++--
 drivers/net/xen-netfront.c                    |  4 +-
 drivers/s390/net/qeth_core.h                  |  2 +-
 drivers/s390/net/qeth_core_main.c             | 18 +++----
 drivers/staging/qlge/qlge_main.c              | 13 ++---
 include/linux/netdevice.h                     |  2 +-
 net/core/dev.c                                |  2 +-
 123 files changed, 616 insertions(+), 567 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index d41ac42762ed..7b4b9bed8979 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1343,14 +1343,14 @@ static void vector_fix_features(struct net_device *dev,
 }
 
 static int vector_set_features(struct net_device *dev,
-	netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	struct vector_private *vp = netdev_priv(dev);
 	/* Adjust buffer sizes for GSO/GRO. Unfortunately, there is
 	 * no way to negotiate it on raw sockets, so we can change
 	 * only our side.
 	 */
-	if (netdev_feature_test(NETIF_F_GRO_BIT, features))
+	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/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index e84a69fb4812..3709f8674724 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2223,7 +2223,7 @@ static void xgbe_fix_features(struct net_device *netdev,
 }
 
 static int xgbe_set_features(struct net_device *netdev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
 	struct xgbe_hw_if *hw_if = &pdata->hw_if;
@@ -2237,29 +2237,29 @@ static int xgbe_set_features(struct net_device *netdev,
 	rxvlan_filter = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 					    pdata->netdev_features);
 
-	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features) && !rxhash)
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, *features) && !rxhash)
 		ret = hw_if->enable_rss(pdata);
-	else if (!netdev_feature_test(NETIF_F_RXHASH_BIT, features) && rxhash)
+	else if (!netdev_feature_test(NETIF_F_RXHASH_BIT, *features) && rxhash)
 		ret = hw_if->disable_rss(pdata);
 	if (ret)
 		return ret;
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && !rxcsum)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features) && !rxcsum)
 		hw_if->enable_rx_csum(pdata);
-	else if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && rxcsum)
+	else if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, *features) && rxcsum)
 		hw_if->disable_rx_csum(pdata);
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) && !rxvlan)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features) && !rxvlan)
 		hw_if->enable_rx_vlan_stripping(pdata);
-	else if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) && rxvlan)
+	else if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features) && rxvlan)
 		hw_if->disable_rx_vlan_stripping(pdata);
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) && !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 (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) && 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;
+	netdev_features_copy(pdata->netdev_features, *features);
 
 	DBGPR("<--xgbe_set_features\n");
 
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
index cd714a6cdf27..486f54186806 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -160,10 +160,10 @@ 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)
+				const netdev_features_t *features)
 {
-	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);
+	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;
@@ -173,14 +173,14 @@ static int aq_ndev_set_features(struct net_device *ndev,
 
 	aq_cfg = aq_nic_get_cfg(aq_nic);
 
-	if (!netdev_feature_test(NETIF_F_NTUPLE_BIT, features)) {
+	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 (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) {
+	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))
@@ -188,11 +188,11 @@ static int aq_ndev_set_features(struct net_device *ndev,
 		}
 	}
 
-	aq_cfg->features = features;
+	netdev_features_copy(aq_cfg->features, *features);
 
 	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);
+		is_lro = netdev_feature_test(NETIF_F_LRO_BIT, *features);
 
 		if (aq_cfg->is_lro != is_lro) {
 			aq_cfg->is_lro = is_lro;
@@ -200,7 +200,7 @@ static int aq_ndev_set_features(struct net_device *ndev,
 		}
 	}
 
-	netdev_features_xor(changed, aq_nic->ndev->features, features);
+	netdev_features_xor(changed, aq_nic->ndev->features, *features);
 	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		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 e61aa93c7c74..164437975599 100644
--- a/drivers/net/ethernet/asix/ax88796c_main.c
+++ b/drivers/net/ethernet/asix/ax88796c_main.c
@@ -921,16 +921,16 @@ ax88796c_close(struct net_device *ndev)
 }
 
 static int
-ax88796c_set_features(struct net_device *ndev, netdev_features_t features)
+ax88796c_set_features(struct net_device *ndev, const netdev_features_t *features)
 {
 	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, ndev->features, features);
+	netdev_features_xor(changed, ndev->features, *features);
 	if (!netdev_features_intersects(changed, ax88796c_features))
 		return 0;
 
-	ndev->features = features;
+	netdev_active_features_copy(ndev, *features);
 
 	if (netdev_features_intersects(changed, ax88796c_features))
 		ax88796c_set_csums(ax_local);
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index b38b508db29c..4ce52ea0833f 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -427,9 +427,10 @@ static void atl1c_set_multi(struct net_device *netdev)
 	}
 }
 
-static void __atl1c_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data)
+static void __atl1c_vlan_mode(const netdev_features_t *features,
+			      u32 *mac_ctrl_data)
 {
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
+	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 {
@@ -439,7 +440,7 @@ static void __atl1c_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data)
 }
 
 static void atl1c_vlan_mode(struct net_device *netdev,
-	netdev_features_t features)
+			    const netdev_features_t *features)
 {
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 	struct pci_dev *pdev = adapter->pdev;
@@ -461,7 +462,7 @@ static void atl1c_restore_vlan(struct atl1c_adapter *adapter)
 
 	if (netif_msg_pktdata(adapter))
 		dev_dbg(&pdev->dev, "atl1c_restore_vlan\n");
-	atl1c_vlan_mode(adapter->netdev, adapter->netdev->features);
+	atl1c_vlan_mode(adapter->netdev, &adapter->netdev->features);
 }
 
 /**
@@ -527,11 +528,11 @@ static void atl1c_fix_features(struct net_device *netdev,
 }
 
 static int atl1c_set_features(struct net_device *netdev,
-	netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		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 fef2ba816451..29245ecea761 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -296,10 +296,11 @@ static void atl1e_set_multi(struct net_device *netdev)
 	}
 }
 
-static void __atl1e_rx_mode(netdev_features_t features, u32 *mac_ctrl_data)
+static void __atl1e_rx_mode(const netdev_features_t *features,
+			    u32 *mac_ctrl_data)
 {
 
-	if (netdev_feature_test(NETIF_F_RXALL_BIT, features)) {
+	if (netdev_feature_test(NETIF_F_RXALL_BIT, *features)) {
 		/* enable RX of ALL frames */
 		*mac_ctrl_data |= MAC_CTRL_DBG;
 	} else {
@@ -309,7 +310,7 @@ static void __atl1e_rx_mode(netdev_features_t features, u32 *mac_ctrl_data)
 }
 
 static void atl1e_rx_mode(struct net_device *netdev,
-	netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	struct atl1e_adapter *adapter = netdev_priv(netdev);
 	u32 mac_ctrl_data = 0;
@@ -324,9 +325,10 @@ static void atl1e_rx_mode(struct net_device *netdev,
 }
 
 
-static void __atl1e_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data)
+static void __atl1e_vlan_mode(const netdev_features_t *features,
+			      u32 *mac_ctrl_data)
 {
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
+	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 {
@@ -336,7 +338,7 @@ static void __atl1e_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data)
 }
 
 static void atl1e_vlan_mode(struct net_device *netdev,
-	netdev_features_t features)
+			    const netdev_features_t *features)
 {
 	struct atl1e_adapter *adapter = netdev_priv(netdev);
 	u32 mac_ctrl_data = 0;
@@ -353,7 +355,7 @@ static void atl1e_vlan_mode(struct net_device *netdev,
 static void atl1e_restore_vlan(struct atl1e_adapter *adapter)
 {
 	netdev_dbg(adapter->netdev, "%s\n", __func__);
-	atl1e_vlan_mode(adapter->netdev, adapter->netdev->features);
+	atl1e_vlan_mode(adapter->netdev, &adapter->netdev->features);
 }
 
 /**
@@ -396,11 +398,11 @@ static void atl1e_fix_features(struct net_device *netdev,
 }
 
 static int atl1e_set_features(struct net_device *netdev,
-	netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		atl1e_vlan_mode(netdev, features);
 
@@ -1059,7 +1061,7 @@ static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
 	value |= (((u32)adapter->hw.preamble_len &
 		  MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
 
-	__atl1e_vlan_mode(netdev->features, &value);
+	__atl1e_vlan_mode(&netdev->features, &value);
 
 	value |= MAC_CTRL_BC_EN;
 	if (netdev->flags & IFF_PROMISC)
@@ -2142,7 +2144,7 @@ static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state)
 				 MAC_CTRL_PRMLEN_MASK) <<
 				 MAC_CTRL_PRMLEN_SHIFT);
 
-		__atl1e_vlan_mode(netdev->features, &mac_ctrl_data);
+		__atl1e_vlan_mode(&netdev->features, &mac_ctrl_data);
 
 		/* magic packet maybe Broadcast&multicast&Unicast frame */
 		if (wufc & AT_WUFC_MAG)
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 745ff416f095..20c8828864ee 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -1261,7 +1261,7 @@ static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
 	value |= (((u32) adapter->hw.preamble_len
 		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
 	/* vlan */
-	__atlx_vlan_mode(netdev->features, &value);
+	__atlx_vlan_mode(&netdev->features, &value);
 	/* rx checksum
 	   if (adapter->rx_csum)
 	   value |= MAC_CTRL_RX_CHKSUM_EN;
@@ -2799,7 +2799,7 @@ static int atl1_suspend(struct device *dev)
 			ctrl |= MAC_CTRL_DUPLX;
 		ctrl |= (((u32)adapter->hw.preamble_len &
 			MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
-		__atlx_vlan_mode(netdev->features, &ctrl);
+		__atlx_vlan_mode(&netdev->features, &ctrl);
 		if (wufc & ATLX_WUFC_MAG)
 			ctrl |= MAC_CTRL_BC_EN;
 		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 589c9f38e3ae..2bc574a1cc25 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -341,9 +341,9 @@ static inline void atl2_irq_disable(struct atl2_adapter *adapter)
     synchronize_irq(adapter->pdev->irq);
 }
 
-static void __atl2_vlan_mode(netdev_features_t features, u32 *ctrl)
+static void __atl2_vlan_mode(const netdev_features_t *features, u32 *ctrl)
 {
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features)) {
 		/* enable VLAN tag insert/strip */
 		*ctrl |= MAC_CTRL_RMV_VLAN;
 	} else {
@@ -353,7 +353,7 @@ static void __atl2_vlan_mode(netdev_features_t features, u32 *ctrl)
 }
 
 static void atl2_vlan_mode(struct net_device *netdev,
-	netdev_features_t features)
+			   const netdev_features_t *features)
 {
 	struct atl2_adapter *adapter = netdev_priv(netdev);
 	u32 ctrl;
@@ -369,7 +369,7 @@ static void atl2_vlan_mode(struct net_device *netdev,
 
 static void atl2_restore_vlan(struct atl2_adapter *adapter)
 {
-	atl2_vlan_mode(adapter->netdev, adapter->netdev->features);
+	atl2_vlan_mode(adapter->netdev, &adapter->netdev->features);
 }
 
 static void atl2_fix_features(struct net_device *netdev,
@@ -386,11 +386,11 @@ static void atl2_fix_features(struct net_device *netdev,
 }
 
 static int atl2_set_features(struct net_device *netdev,
-	netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		atl2_vlan_mode(netdev, features);
 
@@ -1125,7 +1125,7 @@ static void atl2_setup_mac_ctrl(struct atl2_adapter *adapter)
 		MAC_CTRL_PRMLEN_SHIFT);
 
 	/* vlan */
-	__atl2_vlan_mode(netdev->features, &value);
+	__atl2_vlan_mode(&netdev->features, &value);
 
 	/* filter mode */
 	value |= MAC_CTRL_BC_EN;
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index 1943f97e8283..c0b49b5d20b4 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -205,9 +205,9 @@ static void atlx_link_chg_task(struct work_struct *work)
 	spin_unlock_irqrestore(&adapter->lock, flags);
 }
 
-static void __atlx_vlan_mode(netdev_features_t features, u32 *ctrl)
+static void __atlx_vlan_mode(const netdev_features_t *features, u32 *ctrl)
 {
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features)) {
 		/* enable VLAN tag insert/strip */
 		*ctrl |= MAC_CTRL_RMV_VLAN;
 	} else {
@@ -217,7 +217,7 @@ static void __atlx_vlan_mode(netdev_features_t features, u32 *ctrl)
 }
 
 static void atlx_vlan_mode(struct net_device *netdev,
-	netdev_features_t features)
+			   const netdev_features_t *features)
 {
 	struct atlx_adapter *adapter = netdev_priv(netdev);
 	unsigned long flags;
@@ -234,7 +234,7 @@ static void atlx_vlan_mode(struct net_device *netdev,
 
 static void atlx_restore_vlan(struct atlx_adapter *adapter)
 {
-	atlx_vlan_mode(adapter->netdev, adapter->netdev->features);
+	atlx_vlan_mode(adapter->netdev, &adapter->netdev->features);
 }
 
 static void atlx_fix_features(struct net_device *netdev,
@@ -251,11 +251,11 @@ static void atlx_fix_features(struct net_device *netdev,
 }
 
 static int atlx_set_features(struct net_device *netdev,
-	netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		atlx_vlan_mode(netdev, features);
 
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 64dec1d1217b..e6c8c6a9df1f 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -118,12 +118,12 @@ static inline void dma_desc_set_addr(struct bcm_sysport_priv *priv,
 
 /* Ethtool operations */
 static void bcm_sysport_set_rx_csum(struct net_device *dev,
-				    netdev_features_t wanted)
+				    const netdev_features_t *wanted)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	u32 reg;
 
-	priv->rx_chk_en = netdev_feature_test(NETIF_F_RXCSUM_BIT, wanted);
+	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.
@@ -155,7 +155,7 @@ static void bcm_sysport_set_rx_csum(struct net_device *dev,
 }
 
 static void bcm_sysport_set_tx_csum(struct net_device *dev,
-				    netdev_features_t wanted)
+				    const netdev_features_t *wanted)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	netdev_features_t tx_csum_features;
@@ -168,7 +168,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 = netdev_features_intersects(tx_csum_features, wanted);
+	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);
@@ -185,12 +185,12 @@ 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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, wanted))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, *wanted))
 		tdma_writel(priv, ETH_P_8021Q, TDMA_TPID);
 }
 
 static int bcm_sysport_set_features(struct net_device *dev,
-				    netdev_features_t features)
+				    const netdev_features_t *features)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	int ret;
@@ -1983,7 +1983,7 @@ static int bcm_sysport_open(struct net_device *dev)
 	/* Apply features again in case we changed them while interface was
 	 * down
 	 */
-	bcm_sysport_set_features(dev, dev->features);
+	bcm_sysport_set_features(dev, &dev->features);
 
 	/* Set MAC address */
 	umac_set_hw_addr(priv, dev->dev_addr);
@@ -2845,7 +2845,7 @@ static int __maybe_unused bcm_sysport_resume(struct device *d)
 	}
 
 	/* Restore enabled features */
-	bcm_sysport_set_features(dev, dev->features);
+	bcm_sysport_set_features(dev, &dev->features);
 
 	rbuf_init(priv);
 
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 558d6a2f4e0a..7ea525d1dc11 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -7748,12 +7748,12 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
 }
 
 static int
-bnx2_set_features(struct net_device *dev, netdev_features_t features)
+bnx2_set_features(struct net_device *dev, const netdev_features_t *features)
 {
 	struct bnx2 *bp = netdev_priv(dev);
 
 	/* TSO with VLAN tag won't work with current firmware */
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features)) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features)) {
 		netdev_features_t tso;
 
 		netdev_features_and(tso, dev->hw_features, NETIF_F_ALL_TSO);
@@ -7762,11 +7762,11 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
 		netdev_vlan_features_clear(dev, NETIF_F_ALL_TSO);
 	}
 
-	if ((netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) !=
+	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;
+		netdev_active_features_copy(dev, *features);
 		bnx2_set_rx_mode(dev);
 		bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
 		bnx2_netif_start(bp, false);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 23a9746c6e55..cb20d2ad72f0 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4935,18 +4935,18 @@ void bnx2x_fix_features(struct net_device *dev, netdev_features_t *features)
 		netdev_feature_del(NETIF_F_LRO_BIT, *features);
 }
 
-int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
+int bnx2x_set_features(struct net_device *dev, const netdev_features_t *features)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	netdev_features_t changes;
 	bool bnx2x_reload = false;
 	int rc;
 
-	netdev_features_xor(changes, features, dev->features);
+	netdev_features_xor(changes, *features, dev->features);
 
 	/* VFs or non SRIOV PFs should be able to change loopback feature */
 	if (!pci_num_vf(bp->pdev)) {
-		if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features)) {
+		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;
@@ -4967,7 +4967,7 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
 
 	if (bnx2x_reload) {
 		if (bp->recovery_state == BNX2X_RECOVERY_DONE) {
-			dev->features = features;
+			netdev_active_features_copy(dev, *features);
 			rc = bnx2x_reload_if_running(dev);
 			return rc ? rc : 1;
 		}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 4c66ef3e04bf..34b140ed0d7b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -607,7 +607,7 @@ int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type);
 #endif
 
 void bnx2x_fix_features(struct net_device *dev, netdev_features_t *features);
-int bnx2x_set_features(struct net_device *dev, netdev_features_t features);
+int bnx2x_set_features(struct net_device *dev, const netdev_features_t *features);
 
 /**
  * bnx2x_tx_timeout - tx timeout netdev callback
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index b6ca502a3af1..e62d5f9cc211 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -11208,7 +11208,8 @@ static void bnxt_fix_features(struct net_device *dev,
 #endif
 }
 
-static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
+static int bnxt_set_features(struct net_device *dev,
+			     const netdev_features_t *features)
 {
 	struct bnxt *bp = netdev_priv(dev);
 	u32 flags = bp->flags;
@@ -11218,18 +11219,18 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
 	bool update_tpa = false;
 
 	flags &= ~BNXT_FLAG_ALL_CONFIG_FEATS;
-	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features))
+	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, *features))
 		flags |= BNXT_FLAG_GRO;
-	else if (netdev_feature_test(NETIF_F_LRO_BIT, features))
+	else if (netdev_feature_test(NETIF_F_LRO_BIT, *features))
 		flags |= BNXT_FLAG_LRO;
 
 	if (bp->flags & BNXT_FLAG_NO_AGG_RINGS)
 		flags &= ~BNXT_FLAG_TPA;
 
-	if (netdev_features_intersects(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))
+	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, *features))
 		flags |= BNXT_FLAG_RFS;
 
 	changes = flags ^ bp->flags;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 711dddfcc1d1..c69fd3b2a542 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -795,7 +795,7 @@ static int bcmgenet_set_link_ksettings(struct net_device *dev,
 }
 
 static int bcmgenet_set_features(struct net_device *dev,
-				 netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	u32 reg;
@@ -3377,7 +3377,7 @@ static int bcmgenet_open(struct net_device *dev)
 	/* Apply features again in case we changed them while interface was
 	 * down
 	 */
-	bcmgenet_set_features(dev, dev->features);
+	bcmgenet_set_features(dev, &dev->features);
 
 	bcmgenet_set_hw_addr(priv, dev->dev_addr);
 
@@ -4241,7 +4241,7 @@ static int bcmgenet_resume(struct device *d)
 	bcmgenet_mii_config(priv->dev, false);
 
 	/* Restore enabled features */
-	bcmgenet_set_features(dev, dev->features);
+	bcmgenet_set_features(dev, &dev->features);
 
 	bcmgenet_set_hw_addr(priv, dev->dev_addr);
 
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index be6d69b9c3c1..e4fa6f2fdc72 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -8278,11 +8278,12 @@ static int tg3_phy_lpbk_set(struct tg3 *tp, u32 speed, bool extlpbk)
 	return 0;
 }
 
-static void tg3_set_loopback(struct net_device *dev, netdev_features_t features)
+static void tg3_set_loopback(struct net_device *dev,
+			     const netdev_features_t *features)
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features)) {
+	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, *features)) {
 		if (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)
 			return;
 
@@ -8313,11 +8314,12 @@ static void tg3_fix_features(struct net_device *dev,
 		netdev_features_clear(*features, NETIF_F_ALL_TSO);
 }
 
-static int tg3_set_features(struct net_device *dev, netdev_features_t features)
+static int tg3_set_features(struct net_device *dev,
+			    const netdev_features_t *features)
 {
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed) && netif_running(dev))
 		tg3_set_loopback(dev, features);
 
@@ -11647,7 +11649,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
 	 * make sure that it's installed properly now.
 	 */
 	if (netdev_active_feature_test(dev, NETIF_F_LOOPBACK_BIT))
-		tg3_set_loopback(dev, dev->features);
+		tg3_set_loopback(dev, &dev->features);
 
 	return 0;
 
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 087aa63598bd..cef5f7704d69 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3344,18 +3344,19 @@ bnad_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
 	return 0;
 }
 
-static int bnad_set_features(struct net_device *dev, netdev_features_t features)
+static int bnad_set_features(struct net_device *dev,
+			     const netdev_features_t *features)
 {
 	struct bnad *bnad = netdev_priv(dev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+		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 7b49abf30def..9b31b70309c7 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -3694,7 +3694,7 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 }
 
 static inline void macb_set_txcsum_feature(struct macb *bp,
-					   netdev_features_t features)
+					   const netdev_features_t *features)
 {
 	u32 val;
 
@@ -3702,7 +3702,7 @@ static inline void macb_set_txcsum_feature(struct macb *bp,
 		return;
 
 	val = gem_readl(bp, DMACFG);
-	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, *features))
 		val |= GEM_BIT(TXCOEN);
 	else
 		val &= ~GEM_BIT(TXCOEN);
@@ -3711,7 +3711,7 @@ static inline void macb_set_txcsum_feature(struct macb *bp,
 }
 
 static inline void macb_set_rxcsum_feature(struct macb *bp,
-					   netdev_features_t features)
+					   const netdev_features_t *features)
 {
 	struct net_device *netdev = bp->dev;
 	u32 val;
@@ -3720,7 +3720,8 @@ static inline void macb_set_rxcsum_feature(struct macb *bp,
 		return;
 
 	val = gem_readl(bp, NCFGR);
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && !(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);
@@ -3729,22 +3730,22 @@ static inline void macb_set_rxcsum_feature(struct macb *bp,
 }
 
 static inline void macb_set_rxflow_feature(struct macb *bp,
-					   netdev_features_t features)
+					   const netdev_features_t *features)
 {
 	if (!macb_is_gem(bp))
 		return;
 
 	gem_enable_flow_filters(bp,
-				netdev_feature_test(NETIF_F_NTUPLE_BIT, features));
+				netdev_feature_test(NETIF_F_NTUPLE_BIT, *features));
 }
 
 static int macb_set_features(struct net_device *netdev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct macb *bp = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 
 	/* TX checksum offload */
 	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, changed))
@@ -3768,16 +3769,16 @@ static void macb_restore_features(struct macb *bp)
 	struct ethtool_rx_fs_item *item;
 
 	/* TX checksum offload */
-	macb_set_txcsum_feature(bp, features);
+	macb_set_txcsum_feature(bp, &features);
 
 	/* RX checksum offload */
-	macb_set_rxcsum_feature(bp, features);
+	macb_set_rxcsum_feature(bp, &features);
 
 	/* RX Flow Filters */
 	list_for_each_entry(item, &bp->rx_fs_list.list, list)
 		gem_prog_cmp_regs(bp, &item->fs);
 
-	macb_set_rxflow_feature(bp, features);
+	macb_set_rxflow_feature(bp, &features);
 }
 
 static const struct net_device_ops macb_netdev_ops = {
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index a626fa1d13d4..6891fe90c16b 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1487,19 +1487,20 @@ static int xgmac_set_mac_address(struct net_device *dev, void *p)
 	return 0;
 }
 
-static int xgmac_set_features(struct net_device *dev, netdev_features_t features)
+static int xgmac_set_features(struct net_device *dev,
+			      const netdev_features_t *features)
 {
 	u32 ctrl;
 	struct xgmac_priv *priv = netdev_priv(dev);
 	void __iomem *ioaddr = priv->base;
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
 	ctrl = readl(ioaddr + XGMAC_CONTROL);
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	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_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index cb0cc8a5c268..7e4c749aa8b0 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2758,16 +2758,16 @@ static void liquidio_fix_features(struct net_device *netdev,
  * @features: features to enable/disable
  */
 static int liquidio_set_features(struct net_device *netdev,
-				 netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	struct lio *lio = netdev_priv(netdev);
 
-	if (netdev_feature_test(NETIF_F_LRO_BIT, features) &&
+	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 (!netdev_feature_test(NETIF_F_LRO_BIT, features) &&
+	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,
@@ -2778,22 +2778,22 @@ static int liquidio_set_features(struct net_device *netdev,
 	 */
 	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))
+	    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_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))
+		 !netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
 					    OCTNET_CMD_RXCSUM_DISABLE);
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) &&
+	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 (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) &&
+	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,
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 8cf64202846b..cd0f6a7de629 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -1850,31 +1850,31 @@ static void liquidio_fix_features(struct net_device *netdev,
  * @param features features to enable/disable
  */
 static int liquidio_set_features(struct net_device *netdev,
-				 netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	struct lio *lio = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (!netdev_feature_test(NETIF_F_LRO_BIT, changed))
 		return 0;
 
-	if (netdev_feature_test(NETIF_F_LRO_BIT, features) &&
+	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 (!netdev_feature_test(NETIF_F_LRO_BIT, features) &&
+	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_active_feature_test(netdev, NETIF_F_RXCSUM_BIT) &&
 	    netdev_feature_test(NETIF_F_RXCSUM_BIT, lio->dev_capability) &&
-	    netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	    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_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))
+		 !netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
 					    OCTNET_CMD_RXCSUM_DISABLE);
 
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 994608dde650..78ec909c5a0b 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1762,13 +1762,13 @@ static void nicvf_reset_task(struct work_struct *work)
 }
 
 static int nicvf_config_loopback(struct nicvf *nic,
-				 netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	union nic_mbx mbx = {};
 
 	mbx.lbk.msg = NIC_MBOX_MSG_LOOPBACK;
 	mbx.lbk.vf_id = nic->vf_id;
-	mbx.lbk.enable = netdev_feature_test(NETIF_F_LOOPBACK_BIT, features);
+	mbx.lbk.enable = netdev_feature_test(NETIF_F_LOOPBACK_BIT, *features);
 
 	return nicvf_send_msg_to_pf(nic, &mbx);
 }
@@ -1784,12 +1784,12 @@ static void nicvf_fix_features(struct net_device *netdev,
 }
 
 static int nicvf_set_features(struct net_device *netdev,
-			      netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	struct nicvf *nic = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		nicvf_config_vlan_stripping(nic, features);
 
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index c9080dbccca1..5d07fb88060d 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -707,7 +707,8 @@ static void nicvf_reclaim_rbdr(struct nicvf *nic,
 		return;
 }
 
-void nicvf_config_vlan_stripping(struct nicvf *nic, netdev_features_t features)
+void nicvf_config_vlan_stripping(struct nicvf *nic,
+				 const netdev_features_t *features)
 {
 	u64 rq_cfg;
 	int sqs;
@@ -715,7 +716,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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features))
 		rq_cfg |= (1ULL << 25);
 	else
 		rq_cfg &= ~(1ULL << 25);
@@ -804,7 +805,7 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
 		 */
 		nicvf_queue_reg_write(nic, NIC_QSET_RQ_GEN_CFG, 0,
 				      (BIT(24) | BIT(23) | BIT(21) | BIT(20)));
-		nicvf_config_vlan_stripping(nic, nic->netdev->features);
+		nicvf_config_vlan_stripping(nic, &nic->netdev->features);
 	}
 
 	/* Enable Receive queue */
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
index 8453defc296c..fa578d477d24 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
@@ -328,7 +328,7 @@ static inline u64 nicvf_iova_to_phys(struct nicvf *nic, dma_addr_t dma_addr)
 void nicvf_unmap_sndq_buffers(struct nicvf *nic, struct snd_queue *sq,
 			      int hdr_sqe, u8 subdesc_cnt);
 void nicvf_config_vlan_stripping(struct nicvf *nic,
-				 netdev_features_t features);
+				 const netdev_features_t *features);
 int nicvf_set_qset_resources(struct nicvf *nic);
 int nicvf_config_data_transfer(struct nicvf *nic, bool enable);
 void nicvf_qset_config(struct nicvf *nic, bool enable);
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 23dcdc7bde05..c84969e6e343 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -260,7 +260,7 @@ static int cxgb_open(struct net_device *dev)
 		schedule_mac_stats_update(adapter,
 					  adapter->params.stats_update_period);
 
-	t1_vlan_mode(adapter, dev->features);
+	t1_vlan_mode(adapter, &dev->features);
 	return 0;
 }
 
@@ -875,12 +875,13 @@ static void t1_fix_features(struct net_device *dev, netdev_features_t *features)
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
-static int t1_set_features(struct net_device *dev, netdev_features_t features)
+static int t1_set_features(struct net_device *dev,
+			   const netdev_features_t *features)
 {
 	struct adapter *adapter = dev->ml_priv;
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		t1_vlan_mode(adapter, features);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c
index 0e1afce8d3a5..7b10266d9005 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -724,11 +724,11 @@ static inline void setup_ring_params(struct adapter *adapter, u64 addr,
 /*
  * Enable/disable VLAN acceleration.
  */
-void t1_vlan_mode(struct adapter *adapter, netdev_features_t features)
+void t1_vlan_mode(struct adapter *adapter, const netdev_features_t *features)
 {
 	struct sge *sge = adapter->sge;
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+	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;
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.h b/drivers/net/ethernet/chelsio/cxgb/sge.h
index f7e6f64040ea..c34b69636aba 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.h
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.h
@@ -70,7 +70,7 @@ irqreturn_t t1_interrupt(int irq, void *cookie);
 int t1_poll(struct napi_struct *, int);
 
 netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
-void t1_vlan_mode(struct adapter *adapter, netdev_features_t features);
+void t1_vlan_mode(struct adapter *adapter, const netdev_features_t *features);
 void t1_sge_start(struct sge *);
 void t1_sge_stop(struct sge *);
 bool t1_sge_intr_error_handler(struct sge *sge);
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 56bba53a8dd6..92e8a8855a47 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -1177,18 +1177,19 @@ static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
 	}
 }
 
-static void cxgb_vlan_mode(struct net_device *dev, netdev_features_t features)
+static void cxgb_vlan_mode(struct net_device *dev,
+			   const netdev_features_t *features)
 {
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
 
 	if (adapter->params.rev > 0) {
 		t3_set_vlan_accel(adapter, 1 << pi->port_id,
-				  netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features));
+				  netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features));
 	} else {
 		/* single control for all ports */
 		unsigned int i, have_vlans = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
-								 features);
+								 *features);
 
 		for_each_port(adapter, i)
 			have_vlans |= netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
@@ -1249,7 +1250,7 @@ static int cxgb_up(struct adapter *adap)
 			goto out;
 
 		for_each_port(adap, i)
-			cxgb_vlan_mode(adap->port[i], adap->port[i]->features);
+			cxgb_vlan_mode(adap->port[i], &adap->port[i]->features);
 
 		setup_rss(adap);
 		if (!(adap->flags & NAPI_INIT))
@@ -2601,11 +2602,12 @@ static void cxgb_fix_features(struct net_device *dev,
 		netdev_feature_del(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features);
 }
 
-static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
+static int cxgb_set_features(struct net_device *dev,
+			     const netdev_features_t *features)
 {
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		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 c96b11d6c5d8..8d578c120641 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1272,22 +1272,23 @@ int cxgb4_set_rspq_intr_params(struct sge_rspq *q,
 	return 0;
 }
 
-static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
+static int cxgb_set_features(struct net_device *dev,
+			     const netdev_features_t *features)
 {
 	const struct port_info *pi = netdev_priv(dev);
 	netdev_features_t changed;
 	int err;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	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,
-			    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features),
+			    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features),
 			    true);
 	if (unlikely(err)) {
-		dev->features = features;
+		netdev_active_features_copy(dev, *features);
 		netdev_active_feature_change(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	}
 	return err;
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index 7941946e512d..a2e8135490d2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -1188,15 +1188,15 @@ static void cxgb4vf_fix_features(struct net_device *dev,
 }
 
 static int cxgb4vf_set_features(struct net_device *dev,
-	netdev_features_t features)
+				const netdev_features_t *features)
 {
 	struct port_info *pi = netdev_priv(dev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		t4vf_set_rxmode(pi->adapter, pi->viid, -1, -1, -1, -1,
-				netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features),
+				netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features),
 				0);
 
 	return 0;
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 4da024437808..f66ef5bf8d94 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -1986,10 +1986,10 @@ static void gmac_fix_features(struct net_device *netdev,
 }
 
 static int gmac_set_features(struct net_device *netdev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct gemini_ethernet_port *port = netdev_priv(netdev);
-	int enable = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
+	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 650c37096cfe..9cd2c6e10995 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -584,19 +584,19 @@ static int dm9000_nway_reset(struct net_device *dev)
 }
 
 static int dm9000_set_features(struct net_device *dev,
-	netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	struct board_info *dm = to_dm9000_board(dev);
 	netdev_features_t changed;
 	unsigned long flags;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
 	spin_lock_irqsave(&dm->lock, flags);
 	iow(dm, DM9000_RCSR,
-	    netdev_feature_test(NETIF_F_RXCSUM_BIT, features) ? RCSR_CSUM : 0);
+	    netdev_feature_test(NETIF_F_RXCSUM_BIT, *features) ? RCSR_CSUM : 0);
 	spin_unlock_irqrestore(&dm->lock, flags);
 
 	return 0;
diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index 1792c85ca043..5a86b671ba3d 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -1053,16 +1053,16 @@ static int tsnep_netdev_set_mac_address(struct net_device *netdev, void *addr)
 }
 
 static int tsnep_netdev_set_features(struct net_device *netdev,
-				     netdev_features_t features)
+				     const netdev_features_t *features)
 {
 	struct tsnep_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed;
 	bool enable;
 	int retval = 0;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed)) {
-		enable = netdev_feature_test(NETIF_F_LOOPBACK_BIT, features);
+		enable = netdev_feature_test(NETIF_F_LOOPBACK_BIT, *features);
 		retval = tsnep_phy_loopback(adapter, enable);
 	}
 
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 1b6fcc214160..b3c2eb85ad64 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1594,7 +1594,7 @@ static void ftgmac100_tx_timeout(struct net_device *netdev, unsigned int txqueue
 }
 
 static int ftgmac100_set_features(struct net_device *netdev,
-				  netdev_features_t features)
+				  const netdev_features_t *features)
 {
 	struct ftgmac100 *priv = netdev_priv(netdev);
 	netdev_features_t changed;
@@ -1602,7 +1602,7 @@ static int ftgmac100_set_features(struct net_device *netdev,
 	if (!netif_running(netdev))
 		return 0;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	/* Update the vlan filtering bit */
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed)) {
 		u32 maccr;
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 45723c5356cb..fdd0bda2c461 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -2419,30 +2419,30 @@ static void dpaa2_eth_set_rx_mode(struct net_device *net_dev)
 }
 
 static int dpaa2_eth_set_features(struct net_device *net_dev,
-				  netdev_features_t features)
+				  const netdev_features_t *features)
 {
 	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 	netdev_features_t changed;
 	bool enable;
 	int err;
 
-	netdev_features_xor(changed, net_dev->features, features);
+	netdev_features_xor(changed, net_dev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed)) {
-		enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features);
+		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 (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
-		enable = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
+		enable = netdev_feature_test(NETIF_F_RXCSUM_BIT, *features);
 		err = dpaa2_eth_set_rx_csum(priv, enable);
 		if (err)
 			return err;
 	}
 
 	if (netdev_features_intersects(changed, netdev_ip_csum_features)) {
-		enable = netdev_features_intersects(features,
+		enable = netdev_features_intersects(*features,
 						    netdev_ip_csum_features);
 		err = dpaa2_eth_set_tx_csum(priv, enable);
 		if (err)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index f0edb74e509d..836ff64b9b8c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2642,27 +2642,27 @@ static void enetc_enable_txvlan(struct net_device *ndev, bool en)
 }
 
 int enetc_set_features(struct net_device *ndev,
-		       netdev_features_t features)
+		       const netdev_features_t *features)
 {
 	netdev_features_t changed;
 	int err = 0;
 
-	netdev_features_xor(changed, ndev->features, features);
+	netdev_features_xor(changed, ndev->features, *features);
 	if (netdev_feature_test(NETIF_F_RXHASH_BIT, changed))
 		enetc_set_rss(ndev,
-			      netdev_feature_test(NETIF_F_RXHASH_BIT, features));
+			      netdev_feature_test(NETIF_F_RXHASH_BIT, *features));
 
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		enetc_enable_rxvlan(ndev,
-				    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features));
+				    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features));
 
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, changed))
 		enetc_enable_txvlan(ndev,
-				    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features));
+				    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features));
 
 	if (netdev_feature_test(NETIF_F_HW_TC_BIT, changed))
 		err = enetc_set_psfp(ndev,
-				     netdev_feature_test(NETIF_F_HW_TC_BIT, features));
+				     netdev_feature_test(NETIF_F_HW_TC_BIT, *features));
 
 	return err;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 29922c20531f..a690eb623be7 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -394,7 +394,7 @@ void enetc_stop(struct net_device *ndev);
 netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev);
 struct net_device_stats *enetc_get_stats(struct net_device *ndev);
 int enetc_set_features(struct net_device *ndev,
-		       netdev_features_t features);
+		       const netdev_features_t *features);
 int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd);
 int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
 		   void *type_data);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index c181e3db7962..5f5479253e5b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -706,16 +706,16 @@ static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs)
 #endif
 
 static int enetc_pf_set_features(struct net_device *ndev,
-				 netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, ndev->features, features);
+	netdev_features_xor(changed, ndev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed)) {
 		struct enetc_pf *pf = enetc_si_priv(priv->si);
 
-		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
+		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);
@@ -723,7 +723,7 @@ static int enetc_pf_set_features(struct net_device *ndev,
 
 	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed))
 		enetc_set_loopback(ndev,
-				   netdev_feature_test(NETIF_F_LOOPBACK_BIT, features));
+				   netdev_feature_test(NETIF_F_LOOPBACK_BIT, *features));
 
 	return enetc_set_features(ndev, features);
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 461f296b83fb..74b5af9c9eb5 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -87,7 +87,7 @@ static int enetc_vf_set_mac_addr(struct net_device *ndev, void *addr)
 }
 
 static int enetc_vf_set_features(struct net_device *ndev,
-				 netdev_features_t features)
+				 const netdev_features_t *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 cdffbf75e9ca..90094816a6c8 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3447,17 +3447,17 @@ static void fec_poll_controller(struct net_device *dev)
 #endif
 
 static inline void fec_enet_set_netdev_features(struct net_device *netdev,
-	netdev_features_t features)
+						const netdev_features_t *features)
 {
 	struct fec_enet_private *fep = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
-	netdev->features = features;
+	netdev_features_xor(changed, netdev->features, *features);
+	netdev_active_features_copy(netdev, *features);
 
 	/* Receive checksum has been changed */
 	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 			fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
 		else
 			fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;
@@ -3465,12 +3465,12 @@ static inline void fec_enet_set_netdev_features(struct net_device *netdev,
 }
 
 static int fec_set_features(struct net_device *netdev,
-	netdev_features_t features)
+			    const netdev_features_t *features)
 {
 	struct fec_enet_private *fep = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netif_running(netdev) && netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		napi_disable(&fep->napi);
 		netif_tx_lock_bh(netdev);
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 68b59d3202e3..24c11f85857c 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1341,7 +1341,7 @@ static inline u32 gfar_rxbd_dma_lastfree(struct gfar_priv_rx_q *rxq)
 int startup_gfar(struct net_device *dev);
 void stop_gfar(struct net_device *dev);
 void gfar_mac_reset(struct gfar_private *priv);
-int gfar_set_features(struct net_device *dev, netdev_features_t features);
+int gfar_set_features(struct net_device *dev, const netdev_features_t *features);
 
 extern const struct ethtool_ops gfar_ethtool_ops;
 
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 0c2d97e1154a..dc894803d8cc 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -506,13 +506,13 @@ static int gfar_spauseparam(struct net_device *dev,
 	return 0;
 }
 
-int gfar_set_features(struct net_device *dev, netdev_features_t features)
+int gfar_set_features(struct net_device *dev, const netdev_features_t *features)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	netdev_features_t changed;
 	int err = 0;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (!netdev_features_intersects(changed, netdev_ctag_vlan_offload_features) &&
 	    !netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
@@ -520,7 +520,7 @@ int gfar_set_features(struct net_device *dev, netdev_features_t features)
 	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
 		cpu_relax();
 
-	dev->features = features;
+	netdev_active_features_copy(dev, *features);
 
 	if (dev->flags & IFF_UP) {
 		/* Now we take down the rings to rebuild them */
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index d86b6004580a..31d749796b49 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -1179,14 +1179,14 @@ static void gve_tx_timeout(struct net_device *dev, unsigned int txqueue)
 }
 
 static int gve_set_features(struct net_device *netdev,
-			    netdev_features_t features)
+			    const netdev_features_t *features)
 {
 	const netdev_features_t orig_features = netdev->features;
 	struct gve_priv *priv = netdev_priv(netdev);
 	int err;
 
 	if (netdev_active_feature_test(netdev, NETIF_F_LRO_BIT) !=
-	    netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+	    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/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index c29f2eab3d5f..271bc134581a 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1767,17 +1767,17 @@ static int hns_nic_change_mtu(struct net_device *ndev, int new_mtu)
 }
 
 static int hns_nic_set_features(struct net_device *netdev,
-				netdev_features_t features)
+				const netdev_features_t *features)
 {
 	struct hns_nic_priv *priv = netdev_priv(netdev);
 
 	switch (priv->enet_ver) {
 	case AE_VERSION_1:
-		if (netdev_features_intersects(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 (netdev_features_intersects(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 */
@@ -1788,7 +1788,7 @@ static int hns_nic_set_features(struct net_device *netdev,
 		}
 		break;
 	}
-	netdev->features = features;
+	netdev_active_features_copy(netdev, *features);
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 06c79b7cbb23..326ee0c13b65 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2404,7 +2404,7 @@ static int hns3_nic_do_ioctl(struct net_device *netdev,
 }
 
 static int hns3_nic_set_features(struct net_device *netdev,
-				 netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	struct hns3_nic_priv *priv = netdev_priv(netdev);
 	struct hnae3_handle *h = priv->ae_handle;
@@ -2412,10 +2412,10 @@ static int hns3_nic_set_features(struct net_device *netdev,
 	bool enable;
 	int ret;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	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);
+		enable = netdev_feature_test(NETIF_F_GRO_HW_BIT, *features);
 		ret = h->ae_algo->ops->set_gro_en(h, enable);
 		if (ret)
 			return ret;
@@ -2424,7 +2424,7 @@ static int hns3_nic_set_features(struct net_device *netdev,
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed) &&
 	    h->ae_algo->ops->enable_hw_strip_rxvtag) {
 		enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
-					     features);
+					     *features);
 		ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, enable);
 		if (ret)
 			return ret;
@@ -2432,12 +2432,12 @@ static int hns3_nic_set_features(struct net_device *netdev,
 
 	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed) &&
 	    h->ae_algo->ops->enable_fd) {
-		enable = netdev_feature_test(NETIF_F_NTUPLE_BIT, features);
+		enable = netdev_feature_test(NETIF_F_NTUPLE_BIT, *features);
 		h->ae_algo->ops->enable_fd(h, enable);
 	}
 
 	if (netdev_active_feature_test(netdev, NETIF_F_HW_TC_BIT) &&
-	    !netdev_feature_test(NETIF_F_HW_TC_BIT, features) &&
+	    !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");
@@ -2447,13 +2447,13 @@ static int hns3_nic_set_features(struct net_device *netdev,
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed) &&
 	    h->ae_algo->ops->enable_vlan_filter) {
 		enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
-					     features);
+					     *features);
 		ret = h->ae_algo->ops->enable_vlan_filter(h, enable);
 		if (ret)
 			return ret;
 	}
 
-	netdev->features = features;
+	netdev_active_features_copy(netdev, *features);
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 035b77c95cf0..ecb3d345ff2e 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -78,8 +78,8 @@ MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)");
 static int change_mac_addr(struct net_device *netdev, const u8 *addr);
 
 static int set_features(struct hinic_dev *nic_dev,
-			netdev_features_t pre_features,
-			netdev_features_t features, bool force_change);
+			const netdev_features_t *pre_features,
+			const netdev_features_t *features, bool force_change);
 
 static void gather_rx_stats(struct hinic_rxq_stats *nic_rx_stats, struct hinic_rxq *rxq)
 {
@@ -856,11 +856,11 @@ static void hinic_get_stats64(struct net_device *netdev,
 }
 
 static int hinic_set_features(struct net_device *netdev,
-			      netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	struct hinic_dev *nic_dev = netdev_priv(netdev);
 
-	return set_features(nic_dev, nic_dev->netdev->features,
+	return set_features(nic_dev, &nic_dev->netdev->features,
 			    features, false);
 }
 
@@ -1056,8 +1056,8 @@ static void link_err_event(void *handle,
 }
 
 static int set_features(struct hinic_dev *nic_dev,
-			netdev_features_t pre_features,
-			netdev_features_t features, bool force_change)
+			const netdev_features_t *pre_features,
+			const netdev_features_t *features, bool force_change)
 {
 	u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
 	netdev_features_t failed_features;
@@ -1068,12 +1068,12 @@ static int set_features(struct hinic_dev *nic_dev,
 	if (force_change)
 		netdev_features_fill(changed);
 	else
-		netdev_features_xor(changed, pre_features, features);
+		netdev_features_xor(changed, *pre_features, *features);
 
 	netdev_features_zero(failed_features);
 	if (netdev_feature_test(NETIF_F_TSO_BIT, changed)) {
 		ret = hinic_port_set_tso(nic_dev,
-					 netdev_feature_test(NETIF_F_TSO_BIT, features) ?
+					 netdev_feature_test(NETIF_F_TSO_BIT, *features) ?
 					 HINIC_TSO_ENABLE : HINIC_TSO_DISABLE);
 		if (ret) {
 			err = ret;
@@ -1092,7 +1092,7 @@ static int set_features(struct hinic_dev *nic_dev,
 
 	if (netdev_feature_test(NETIF_F_LRO_BIT, changed)) {
 		ret = hinic_set_rx_lro_state(nic_dev,
-					     netdev_feature_test(NETIF_F_LRO_BIT, features),
+					     netdev_feature_test(NETIF_F_LRO_BIT, *features),
 					     HINIC_LRO_RX_TIMER_DEFAULT,
 					     HINIC_LRO_MAX_WQE_NUM_DEFAULT);
 		if (ret) {
@@ -1104,7 +1104,7 @@ static int set_features(struct hinic_dev *nic_dev,
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed)) {
 		ret = hinic_set_rx_vlan_offload(nic_dev,
 						netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT,
-								    features));
+								    *features));
 		if (ret) {
 			err = ret;
 			netdev_feature_add(NETIF_F_HW_VLAN_CTAG_RX_BIT,
@@ -1113,7 +1113,7 @@ static int set_features(struct hinic_dev *nic_dev,
 	}
 
 	if (err) {
-		netdev_active_features_xor(nic_dev->netdev, features,
+		netdev_active_features_xor(nic_dev->netdev, *features,
 					   failed_features);
 		return -EIO;
 	}
@@ -1294,8 +1294,8 @@ static int nic_dev_init(struct pci_dev *pdev)
 				nic_dev, link_err_event);
 
 	netdev_features_zero(feats);
-	err = set_features(nic_dev, feats,
-			   nic_dev->netdev->features, true);
+	err = set_features(nic_dev, &feats,
+			   &nic_dev->netdev->features, true);
 	if (err)
 		goto err_set_features;
 
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 3658783641c7..01ff163aa261 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -898,18 +898,18 @@ static int ibmveth_set_tso(struct net_device *dev, u32 data)
 }
 
 static int ibmveth_set_features(struct net_device *dev,
-	netdev_features_t features)
+				const netdev_features_t *features)
 {
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
-	int rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
-	int large_send = netdev_features_intersects(features,
+	int rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, *features);
+	int large_send = netdev_features_intersects(*features,
 						    netdev_general_tso_features);
 	int rc1 = 0, rc2 = 0;
 
 	if (rx_csum != adapter->rx_csum) {
 		rc1 = ibmveth_set_csum_offload(dev, rx_csum);
 		if (rc1 && !adapter->rx_csum) {
-			netdev_active_features_andnot(dev, features,
+			netdev_active_features_andnot(dev, *features,
 						      NETIF_F_CSUM_MASK);
 			netdev_active_feature_del(dev, NETIF_F_RXCSUM_BIT);
 		}
@@ -918,7 +918,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)
-			netdev_active_features_andnot(dev, features,
+			netdev_active_features_andnot(dev, *features,
 						      netdev_general_tso_features);
 	}
 
@@ -1734,7 +1734,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 	netdev_dbg(netdev, "adapter @ 0x%p\n", adapter);
 	netdev_dbg(netdev, "registering netdev...\n");
 
-	ibmveth_set_features(netdev, netdev->features);
+	ibmveth_set_features(netdev, &netdev->features);
 
 	rc = register_netdev(netdev);
 
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 636c386d6761..e1f01fae54f3 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2801,17 +2801,17 @@ static int e100_close(struct net_device *netdev)
 }
 
 static int e100_set_features(struct net_device *netdev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct nic *nic = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (!(netdev_feature_test(NETIF_F_RXFCS_BIT, changed) &&
 	      netdev_feature_test(NETIF_F_RXALL_BIT, changed)))
 		return 0;
 
-	netdev->features = features;
+	netdev_active_features_copy(netdev, *features);
 	e100_exec_cb(nic, NULL, e100_configure);
 	return 1;
 }
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index a689aba72050..0f06f320e579 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -140,7 +140,7 @@ static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
 
 static bool e1000_vlan_used(struct e1000_adapter *adapter);
 static void e1000_vlan_mode(struct net_device *netdev,
-			    netdev_features_t features);
+			    const netdev_features_t *features);
 static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
 				     bool filter_on);
 static int e1000_vlan_rx_add_vid(struct net_device *netdev,
@@ -800,12 +800,12 @@ static void e1000_fix_features(struct net_device *netdev,
 }
 
 static int e1000_set_features(struct net_device *netdev,
-	netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		e1000_vlan_mode(netdev, features);
 
@@ -813,8 +813,8 @@ static int e1000_set_features(struct net_device *netdev,
 	      netdev_feature_test(NETIF_F_RXALL_BIT, changed)))
 		return 0;
 
-	netdev->features = features;
-	adapter->rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
+	netdev_active_features_copy(netdev, *features);
+	adapter->rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, *features);
 
 	if (netif_running(netdev))
 		e1000_reinit_locked(adapter);
@@ -4893,13 +4893,13 @@ static bool e1000_vlan_used(struct e1000_adapter *adapter)
 }
 
 static void __e1000_vlan_mode(struct e1000_adapter *adapter,
-			      netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl;
 
 	ctrl = er32(CTRL);
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features)) {
 		/* enable VLAN tag insert/strip */
 		ctrl |= E1000_CTRL_VME;
 	} else {
@@ -4917,7 +4917,7 @@ static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
 	if (!test_bit(__E1000_DOWN, &adapter->flags))
 		e1000_irq_disable(adapter);
 
-	__e1000_vlan_mode(adapter, adapter->netdev->features);
+	__e1000_vlan_mode(adapter, &adapter->netdev->features);
 	if (filter_on) {
 		/* enable VLAN receive filtering */
 		rctl = er32(RCTL);
@@ -4938,7 +4938,7 @@ static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
 }
 
 static void e1000_vlan_mode(struct net_device *netdev,
-			    netdev_features_t features)
+			    const netdev_features_t *features)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index d5b022b309aa..95fe8df96d5a 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -7311,13 +7311,13 @@ static void e1000_fix_features(struct net_device *netdev,
 }
 
 static int e1000_set_features(struct net_device *netdev,
-			      netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changeable;
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_features_intersects(changed, netdev_general_tso_features))
 		adapter->flags |= FLAG_TSO_FORCE;
 
@@ -7330,7 +7330,7 @@ static int e1000_set_features(struct net_device *netdev,
 		return 0;
 
 	if (netdev_feature_test(NETIF_F_RXFCS_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features)) {
+		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
@@ -7343,7 +7343,7 @@ static int e1000_set_features(struct net_device *netdev,
 		}
 	}
 
-	netdev->features = features;
+	netdev_active_features_copy(netdev, *features);
 
 	if (netif_running(netdev))
 		e1000e_reinit_locked(adapter);
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 9a60d6b207f7..f8b25a4d9339 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -1167,7 +1167,7 @@ u32 i40e_get_current_fd_count(struct i40e_pf *pf);
 u32 i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf);
 u32 i40e_get_current_atr_cnt(struct i40e_pf *pf);
 u32 i40e_get_global_fd_count(struct i40e_pf *pf);
-bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
+bool i40e_set_ntuple(struct i40e_pf *pf, const netdev_features_t *features);
 void i40e_set_ethtool_ops(struct net_device *netdev);
 struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
 					const u8 *macaddr, s16 vlan);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 3bf454f234a4..86e63041f2cc 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -12846,14 +12846,14 @@ static int i40e_sw_init(struct i40e_pf *pf)
  *
  * returns a bool to indicate if reset needs to happen
  **/
-bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features)
+bool i40e_set_ntuple(struct i40e_pf *pf, const netdev_features_t *features)
 {
 	bool need_reset = false;
 
 	/* Check if Flow Director n-tuple support was enabled or disabled.  If
 	 * the state changed, we need to reset.
 	 */
-	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, features)) {
+	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;
@@ -12915,26 +12915,26 @@ static void i40e_clear_rss_lut(struct i40e_vsi *vsi)
  * Note: expects to be called while under rtnl_lock()
  **/
 static int i40e_set_features(struct net_device *netdev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_vsi *vsi = np->vsi;
 	struct i40e_pf *pf = vsi->back;
 	bool need_reset;
 
-	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features) &&
+	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 (!netdev_feature_test(NETIF_F_RXHASH_BIT, features) &&
+	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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features))
 		i40e_vlan_stripping_enable(vsi);
 	else
 		i40e_vlan_stripping_disable(vsi);
 
-	if (!netdev_feature_test(NETIF_F_HW_TC_BIT, features) &&
+	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,
@@ -12942,7 +12942,7 @@ static int i40e_set_features(struct net_device *netdev,
 		return -EINVAL;
 	}
 
-	if (!netdev_feature_test(NETIF_F_HW_L2FW_DOFFLOAD_BIT, features) &&
+	if (!netdev_feature_test(NETIF_F_HW_L2FW_DOFFLOAD_BIT, *features) &&
 	    vsi->macvlan_cnt)
 		i40e_del_all_macvlans(vsi);
 
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
index 5f19135f50d2..c9b9a2141771 100644
--- a/drivers/net/ethernet/intel/iavf/iavf.h
+++ b/drivers/net/ethernet/intel/iavf/iavf.h
@@ -581,8 +581,8 @@ int iavf_replace_primary_mac(struct iavf_adapter *adapter,
 			     const u8 *new_mac);
 void
 iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
-			       netdev_features_t prev_features,
-			       netdev_features_t features);
+			       const netdev_features_t *prev_features,
+			       const netdev_features_t *features);
 void iavf_add_fdir_filter(struct iavf_adapter *adapter);
 void iavf_del_fdir_filter(struct iavf_adapter *adapter);
 void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index bc9b963a3bd9..456bb30ce086 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2189,8 +2189,8 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
  **/
 void
 iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
-			       netdev_features_t prev_features,
-			       netdev_features_t features)
+			       const netdev_features_t *prev_features,
+			       const netdev_features_t *features)
 {
 	bool enable_stripping = true, enable_insertion = true;
 	u16 vlan_ethertype = 0;
@@ -2202,20 +2202,20 @@ iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
 	 * ETH_P_8021Q so an ethertype is specified if disabling insertion and
 	 * stripping.
 	 */
-	if (netdev_features_intersects(features, netdev_stag_vlan_offload_features))
+	if (netdev_features_intersects(*features, netdev_stag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021AD;
-	else if (netdev_features_intersects(features, netdev_ctag_vlan_offload_features))
+	else if (netdev_features_intersects(*features, netdev_ctag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021Q;
-	else if (netdev_features_intersects(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 (netdev_features_intersects(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 (!netdev_features_intersects(features, netdev_rx_vlan_features))
+	if (!netdev_features_intersects(*features, netdev_rx_vlan_features))
 		enable_stripping = false;
-	if (!netdev_features_intersects(features, netdev_tx_vlan_features))
+	if (!netdev_features_intersects(*features, netdev_tx_vlan_features))
 		enable_insertion = false;
 
 	if (VLAN_ALLOWED(adapter)) {
@@ -2675,8 +2675,8 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
 
 		netdev_features_zero(feats);
 		/* request initial VLAN offload settings */
-		iavf_set_vlan_offload_features(adapter, feats,
-					       netdev->features);
+		iavf_set_vlan_offload_features(adapter, &feats,
+					       &netdev->features);
 	}
 
 	return;
@@ -3246,7 +3246,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, feats, netdev->features);
+					(adapter, &feats, &netdev->features);
 
 			iavf_set_queue_vlan_tag_loc(adapter);
 		}
@@ -4367,14 +4367,14 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
  * Note: expects to be called while under rtnl_lock()
  **/
 static int iavf_set_features(struct net_device *netdev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct iavf_adapter *adapter = netdev_priv(netdev);
 
 	/* trigger update on any VLAN feature change */
 	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,
+	    netdev_features_intersects(*features, NETIF_VLAN_OFFLOAD_FEATURES))
+		iavf_set_vlan_offload_features(adapter, &netdev->features,
 					       features);
 
 	return 0;
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index cce947660cfd..d4f77da1ddd7 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5890,7 +5890,8 @@ ice_fix_features(struct net_device *netdev, netdev_features_t *features)
  * disabled. Finally enable or disable VLAN stripping and insertion.
  */
 static int
-ice_set_vlan_offload_features(struct ice_vsi *vsi, netdev_features_t features)
+ice_set_vlan_offload_features(struct ice_vsi *vsi,
+			      const netdev_features_t *features)
 {
 	bool enable_stripping = true, enable_insertion = true;
 	struct ice_vsi_vlan_ops *vlan_ops;
@@ -5899,14 +5900,14 @@ ice_set_vlan_offload_features(struct ice_vsi *vsi, netdev_features_t features)
 
 	vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
 
-	if (netdev_features_intersects(features, netdev_stag_vlan_offload_features))
+	if (netdev_features_intersects(*features, netdev_stag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021AD;
-	else if (netdev_features_intersects(features, netdev_ctag_vlan_offload_features))
+	else if (netdev_features_intersects(*features, netdev_ctag_vlan_offload_features))
 		vlan_ethertype = ETH_P_8021Q;
 
-	if (!netdev_features_intersects(features, netdev_rx_vlan_features))
+	if (!netdev_features_intersects(*features, netdev_rx_vlan_features))
 		enable_stripping = false;
-	if (!netdev_features_intersects(features, netdev_tx_vlan_features))
+	if (!netdev_features_intersects(*features, netdev_tx_vlan_features))
 		enable_insertion = false;
 
 	if (enable_stripping)
@@ -5934,7 +5935,8 @@ ice_set_vlan_offload_features(struct ice_vsi *vsi, netdev_features_t features)
  * features.
  */
 static int
-ice_set_vlan_filtering_features(struct ice_vsi *vsi, netdev_features_t features)
+ice_set_vlan_filtering_features(struct ice_vsi *vsi,
+				const netdev_features_t *features)
 {
 	struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
 	int err = 0;
@@ -5942,7 +5944,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 (netdev_features_intersects(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);
@@ -5959,7 +5961,8 @@ ice_set_vlan_filtering_features(struct ice_vsi *vsi, netdev_features_t features)
  * the current_vlan_features.
  */
 static int
-ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
+ice_set_vlan_features(struct net_device *netdev,
+		      const netdev_features_t *features)
 {
 	netdev_features_t current_vlan_features, requested_vlan_features, diff;
 	struct ice_netdev_priv *np = netdev_priv(netdev);
@@ -5968,13 +5971,13 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 
 	netdev_features_and(current_vlan_features, netdev->features,
 			    NETIF_VLAN_OFFLOAD_FEATURES);
-	netdev_features_and(requested_vlan_features, features,
+	netdev_features_and(requested_vlan_features, *features,
 			    NETIF_VLAN_OFFLOAD_FEATURES);
 	netdev_features_xor(diff, current_vlan_features,
 			    requested_vlan_features);
 	if (!netdev_features_empty(diff)) {
-		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features) &&
-		    netdev_features_intersects(features,
+		if (netdev_feature_test(NETIF_F_RXFCS_BIT, *features) &&
+		    netdev_features_intersects(*features,
 					       NETIF_VLAN_STRIPPING_FEATURES)) {
 			dev_err(ice_pf_to_dev(vsi->back),
 				"To enable VLAN stripping, you must first enable FCS/CRC stripping\n");
@@ -5988,7 +5991,7 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
 
 	netdev_features_and(current_vlan_features, netdev->features,
 			    NETIF_VLAN_FILTERING_FEATURES);
-	netdev_features_and(requested_vlan_features, features,
+	netdev_features_and(requested_vlan_features, *features,
 			    NETIF_VLAN_FILTERING_FEATURES);
 	netdev_features_xor(diff, current_vlan_features,
 			    requested_vlan_features);
@@ -6033,7 +6036,7 @@ static int ice_set_loopback(struct ice_vsi *vsi, bool ena)
  * @features: the feature set that the stack is suggesting
  */
 static int
-ice_set_features(struct net_device *netdev, netdev_features_t features)
+ice_set_features(struct net_device *netdev, const netdev_features_t *features)
 {
 	struct ice_netdev_priv *np = netdev_priv(netdev);
 	struct ice_vsi *vsi = np->vsi;
@@ -6055,14 +6058,14 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
 		return -EBUSY;
 	}
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 
 	/* Multiple features can be changed in one call so keep features in
 	 * separate if/else statements to guarantee each feature is checked
 	 */
 	if (netdev_feature_test(NETIF_F_RXHASH_BIT, changed))
 		ice_vsi_manage_rss_lut(vsi,
-				       netdev_feature_test(NETIF_F_RXHASH_BIT, features));
+				       netdev_feature_test(NETIF_F_RXHASH_BIT, *features));
 
 	ret = ice_set_vlan_features(netdev, features);
 	if (ret)
@@ -6072,35 +6075,35 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
 	 * flag the packet data will have the 4 byte CRC appended
 	 */
 	if (netdev_feature_test(NETIF_F_RXFCS_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features) &&
-		    netdev_features_intersects(features, NETIF_VLAN_STRIPPING_FEATURES)) {
+		if (netdev_feature_test(NETIF_F_RXFCS_BIT, *features) &&
+		    netdev_features_intersects(*features, NETIF_VLAN_STRIPPING_FEATURES)) {
 			dev_err(ice_pf_to_dev(vsi->back),
 				"To disable FCS/CRC stripping, you must first disable VLAN stripping\n");
 			return -EIO;
 		}
 
 		ice_vsi_cfg_crc_strip(vsi,
-				      netdev_feature_test(NETIF_F_RXFCS_BIT, features));
+				      netdev_feature_test(NETIF_F_RXFCS_BIT, *features));
 		ret = ice_down_up(vsi);
 		if (ret)
 			return ret;
 	}
 
 	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed)) {
-		bool ena = netdev_feature_test(NETIF_F_NTUPLE_BIT, features);
+		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 (!netdev_feature_test(NETIF_F_HW_TC_BIT, features) && 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 (netdev_feature_test(NETIF_F_HW_TC_BIT, changed)) {
-		bool ena = netdev_feature_test(NETIF_F_HW_TC_BIT, features);
+		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);
@@ -6108,7 +6111,7 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
 
 	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed))
 		ret = ice_set_loopback(vsi,
-				       netdev_feature_test(NETIF_F_LOOPBACK_BIT, features));
+				       netdev_feature_test(NETIF_F_LOOPBACK_BIT, *features));
 
 	return ret;
 }
@@ -6121,11 +6124,11 @@ static int ice_vsi_vlan_setup(struct ice_vsi *vsi)
 {
 	int err;
 
-	err = ice_set_vlan_offload_features(vsi, vsi->netdev->features);
+	err = ice_set_vlan_offload_features(vsi, &vsi->netdev->features);
 	if (err)
 		return err;
 
-	err = ice_set_vlan_filtering_features(vsi, vsi->netdev->features);
+	err = ice_set_vlan_filtering_features(vsi, &vsi->netdev->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 a93e52cf01b3..87c55e4c7649 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -145,7 +145,7 @@ static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
 static void igb_tx_timeout(struct net_device *, unsigned int txqueue);
 static void igb_reset_task(struct work_struct *);
 static void igb_vlan_mode(struct net_device *netdev,
-			  netdev_features_t features);
+			  const netdev_features_t *features);
 static int igb_vlan_rx_add_vid(struct net_device *, __be16, u16);
 static int igb_vlan_rx_kill_vid(struct net_device *, __be16, u16);
 static void igb_restore_vlan(struct igb_adapter *);
@@ -2445,12 +2445,12 @@ static void igb_fix_features(struct net_device *netdev,
 }
 
 static int igb_set_features(struct net_device *netdev,
-	netdev_features_t features)
+			    const netdev_features_t *features)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		igb_vlan_mode(netdev, features);
 
@@ -2458,7 +2458,7 @@ static int igb_set_features(struct net_device *netdev,
 	    !netdev_feature_test(NETIF_F_NTUPLE_BIT, changed))
 		return 0;
 
-	if (!netdev_feature_test(NETIF_F_NTUPLE_BIT, features)) {
+	if (!netdev_feature_test(NETIF_F_NTUPLE_BIT, *features)) {
 		struct hlist_node *node2;
 		struct igb_nfc_filter *rule;
 
@@ -2473,7 +2473,7 @@ static int igb_set_features(struct net_device *netdev,
 		adapter->nfc_filter_count = 0;
 	}
 
-	netdev->features = features;
+	netdev_active_features_copy(netdev, *features);
 
 	if (netif_running(netdev))
 		igb_reinit_locked(adapter);
@@ -9161,12 +9161,13 @@ s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
 	return 0;
 }
 
-static void igb_vlan_mode(struct net_device *netdev, netdev_features_t features)
+static void igb_vlan_mode(struct net_device *netdev,
+			  const netdev_features_t *features)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl, rctl;
-	bool enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features);
+	bool enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features);
 
 	if (enable) {
 		/* enable VLAN tag insert/strip */
@@ -9224,7 +9225,7 @@ static void igb_restore_vlan(struct igb_adapter *adapter)
 {
 	u16 vid = 1;
 
-	igb_vlan_mode(adapter->netdev, adapter->netdev->features);
+	igb_vlan_mode(adapter->netdev, &adapter->netdev->features);
 	igb_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), 0);
 
 	for_each_set_bit_from(vid, adapter->active_vlans, VLAN_N_VID)
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 11e8496236a6..a812b3fae712 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2604,11 +2604,11 @@ static void igbvf_print_device_info(struct igbvf_adapter *adapter)
 }
 
 static int igbvf_set_features(struct net_device *netdev,
-			      netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	struct igbvf_adapter *adapter = netdev_priv(netdev);
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 		adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
 	else
 		adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 65eb629cda99..c0305237a620 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -1614,9 +1614,10 @@ static void igc_process_skb_fields(struct igc_ring *rx_ring,
 	skb->protocol = eth_type_trans(skb, rx_ring->netdev);
 }
 
-static void igc_vlan_mode(struct net_device *netdev, netdev_features_t features)
+static void igc_vlan_mode(struct net_device *netdev,
+			  const netdev_features_t *features)
 {
-	bool enable = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features);
+	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;
@@ -1635,7 +1636,7 @@ static void igc_vlan_mode(struct net_device *netdev, netdev_features_t features)
 
 static void igc_restore_vlan(struct igc_adapter *adapter)
 {
-	igc_vlan_mode(adapter->netdev, adapter->netdev->features);
+	igc_vlan_mode(adapter->netdev, &adapter->netdev->features);
 }
 
 static struct igc_rx_buffer *igc_get_rx_buffer(struct igc_ring *rx_ring,
@@ -4985,12 +4986,12 @@ static void igc_fix_features(struct net_device *netdev,
 }
 
 static int igc_set_features(struct net_device *netdev,
-			    netdev_features_t features)
+			    const netdev_features_t *features)
 {
 	struct igc_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed))
 		igc_vlan_mode(netdev, features);
 
@@ -4999,10 +5000,10 @@ static int igc_set_features(struct net_device *netdev,
 	    !netdev_feature_test(NETIF_F_NTUPLE_BIT, changed))
 		return 0;
 
-	if (!netdev_feature_test(NETIF_F_NTUPLE_BIT, features))
+	if (!netdev_feature_test(NETIF_F_NTUPLE_BIT, *features))
 		igc_flush_nfc_rules(adapter);
 
-	netdev->features = features;
+	netdev_active_features_copy(netdev, *features);
 
 	if (netif_running(netdev))
 		igc_reinit_locked(adapter);
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index bb0ce65cd025..d8d88bb41c38 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -306,17 +306,18 @@ ixgb_fix_features(struct net_device *netdev, netdev_features_t *features)
 }
 
 static int
-ixgb_set_features(struct net_device *netdev, netdev_features_t features)
+ixgb_set_features(struct net_device *netdev,
+		  const netdev_features_t *features)
 {
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	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 = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
+	adapter->rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, *features);
 
 	if (netif_running(netdev)) {
 		ixgb_down(adapter, true);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 139eec69f5b9..7faec783bfcc 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9866,16 +9866,16 @@ static void ixgbe_reset_l2fw_offload(struct ixgbe_adapter *adapter)
 }
 
 static int ixgbe_set_features(struct net_device *netdev,
-			      netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed;
 	bool need_reset = false;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 
 	/* Make sure RSC matches LRO, reset if change */
-	if (!netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+	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,7 @@ static int ixgbe_set_features(struct net_device *netdev,
 			adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
 			need_reset = true;
 		} else if (netdev_feature_test(NETIF_F_LRO_BIT, changed) !=
-			   netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+			   netdev_feature_test(NETIF_F_LRO_BIT, *features)) {
 			e_info(probe, "rx-usecs set too low, "
 			       "disabling RSC\n");
 		}
@@ -9896,8 +9896,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 (netdev_feature_test(NETIF_F_NTUPLE_BIT, features) ||
-	    netdev_feature_test(NETIF_F_HW_TC_BIT, features)) {
+	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;
@@ -9927,7 +9927,7 @@ static int ixgbe_set_features(struct net_device *netdev,
 	if (netdev_feature_test(NETIF_F_RXALL_BIT, changed))
 		need_reset = true;
 
-	netdev->features = features;
+	netdev_active_features_copy(netdev, *features);
 
 	if (netdev_feature_test(NETIF_F_HW_L2FW_DOFFLOAD_BIT, changed) && adapter->num_rx_pools > 1)
 		ixgbe_reset_l2fw_offload(adapter);
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index fc967f35f8a7..f051cc448abc 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2671,12 +2671,13 @@ jme_fix_features(struct net_device *netdev, netdev_features_t *features)
 }
 
 static int
-jme_set_features(struct net_device *netdev, netdev_features_t features)
+jme_set_features(struct net_device *netdev,
+		 const netdev_features_t *features)
 {
 	struct jme_adapter *jme = netdev_priv(netdev);
 
 	spin_lock_bh(&jme->rxmcs_lock);
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	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 b66895090e87..4bf7b2fbf728 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -1683,10 +1683,11 @@ mv643xx_eth_set_ringparam(struct net_device *dev, struct ethtool_ringparam *er,
 
 
 static int
-mv643xx_eth_set_features(struct net_device *dev, netdev_features_t features)
+mv643xx_eth_set_features(struct net_device *dev,
+			 const netdev_features_t *features)
 {
 	struct mv643xx_eth_private *mp = netdev_priv(dev);
-	bool rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
+	bool rx_csum = netdev_feature_test(NETIF_F_RXCSUM_BIT, *features);
 
 	wrlp(mp, PORT_CONFIG, rx_csum ? 0x02000000 : 0x00000000);
 
@@ -2364,7 +2365,7 @@ static void port_start(struct mv643xx_eth_private *mp)
 	 * frames to RX queue #0, and include the pseudo-header when
 	 * calculating receive checksums.
 	 */
-	mv643xx_eth_set_features(mp->dev, mp->dev->features);
+	mv643xx_eth_set_features(mp->dev, &mp->dev->features);
 
 	/*
 	 * Treat BPDUs as normal multicasts, and disable partition mode.
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 054946f8fa6e..cc6699715171 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -5277,14 +5277,14 @@ 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)
+			      const netdev_features_t *features)
 {
 	struct mvpp2_port *port = netdev_priv(dev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) {
+		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
@@ -5297,7 +5297,7 @@ static int mvpp2_set_features(struct net_device *dev,
 	}
 
 	if (netdev_feature_test(NETIF_F_RXHASH_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_RXHASH_BIT, features))
+		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 a77a0ebb0286..c1c012bf1d43 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -1767,14 +1767,15 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
 }
 EXPORT_SYMBOL(otx2_get_max_mtu);
 
-int otx2_handle_ntuple_tc_features(struct net_device *netdev, netdev_features_t features)
+int otx2_handle_ntuple_tc_features(struct net_device *netdev,
+				   const netdev_features_t *features)
 {
 	struct otx2_nic *pfvf = netdev_priv(netdev);
-	bool ntuple = netdev_feature_test(NETIF_F_NTUPLE_BIT, features);
-	bool tc = netdev_feature_test(NETIF_F_HW_TC_BIT, features);
+	bool ntuple = netdev_feature_test(NETIF_F_NTUPLE_BIT, *features);
+	bool tc = netdev_feature_test(NETIF_F_HW_TC_BIT, *features);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, changed) && !ntuple)
 		otx2_destroy_ntuple_flows(pfvf);
 
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 23948626b1ef..e721517e6597 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -904,7 +904,7 @@ int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf);
 bool otx2_xdp_sq_append_pkt(struct otx2_nic *pfvf, u64 iova, int len, u16 qidx);
 u16 otx2_get_max_mtu(struct otx2_nic *pfvf);
 int otx2_handle_ntuple_tc_features(struct net_device *netdev,
-				   netdev_features_t features);
+				   const netdev_features_t *features);
 int otx2_smq_flush(struct otx2_nic *pfvf, int smq);
 
 /* tc support */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 839350458bc1..f7cc10dcc9ea 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1929,23 +1929,23 @@ static void otx2_rx_mode_wrk_handler(struct work_struct *work)
 }
 
 static int otx2_set_features(struct net_device *netdev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct otx2_nic *pf = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	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));
+								    *features));
 
 	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));
+							      *features));
 
 	return otx2_handle_ntuple_tc_features(netdev, features);
 }
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 87870bab4893..0acfc16a08ae 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -471,7 +471,7 @@ static void otx2vf_reset_task(struct work_struct *work)
 }
 
 static int otx2vf_set_features(struct net_device *netdev,
-			       netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	return otx2_handle_ntuple_tc_features(netdev, features);
 }
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index afa6234cdd8f..e0257fff2663 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -1279,7 +1279,7 @@ static void rx_set_checksum(struct sky2_port *sky2)
 }
 
 /* Enable/disable receive hash calculation (RSS) */
-static void rx_set_rss(struct net_device *dev, netdev_features_t features)
+static void rx_set_rss(struct net_device *dev, const netdev_features_t *features)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 	struct sky2_hw *hw = sky2->hw;
@@ -1292,7 +1292,7 @@ static void rx_set_rss(struct net_device *dev, netdev_features_t features)
 	}
 
 	/* Program RSS initial values */
-	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features)) {
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, *features)) {
 		u32 rss_key[10];
 
 		netdev_rss_key_fill(rss_key, sizeof(rss_key));
@@ -1404,20 +1404,21 @@ static DECLARE_NETDEV_FEATURE_SET(sky2_vlan_feature_set,
 				  NETIF_F_SG_BIT,
 				  NETIF_F_TSO_BIT);
 
-static void sky2_vlan_mode(struct net_device *dev, netdev_features_t features)
+static void sky2_vlan_mode(struct net_device *dev,
+			   const netdev_features_t *features)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 	struct sky2_hw *hw = sky2->hw;
 	u16 port = sky2->port;
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+	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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features)) {
+	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);
 
@@ -1545,7 +1546,7 @@ static void sky2_rx_start(struct sky2_port *sky2)
 		rx_set_checksum(sky2);
 
 	if (!(hw->flags & SKY2_HW_RSS_BROKEN))
-		rx_set_rss(sky2->netdev, sky2->netdev->features);
+		rx_set_rss(sky2->netdev, &sky2->netdev->features);
 
 	/* submit Rx ring */
 	for (i = 0; i < sky2->rx_pending; i++) {
@@ -1706,7 +1707,7 @@ static void sky2_hw_up(struct sky2_port *sky2)
 	sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
 			   sky2->tx_ring_size - 1);
 
-	sky2_vlan_mode(sky2->netdev, sky2->netdev->features);
+	sky2_vlan_mode(sky2->netdev, &sky2->netdev->features);
 	netdev_update_features(sky2->netdev);
 
 	sky2_rx_start(sky2);
@@ -4330,17 +4331,18 @@ static void sky2_fix_features(struct net_device *dev,
 	}
 }
 
-static int sky2_set_features(struct net_device *dev, netdev_features_t features)
+static int sky2_set_features(struct net_device *dev,
+			     const netdev_features_t *features)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	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),
-			     netdev_feature_test(NETIF_F_RXCSUM_BIT, features)
+			     netdev_feature_test(NETIF_F_RXCSUM_BIT, *features)
 			     ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
 	}
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c1236dd59f56..ae3a18119fef 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2712,16 +2712,17 @@ static void mtk_fix_features(struct net_device *dev,
 	}
 }
 
-static int mtk_set_features(struct net_device *dev, netdev_features_t features)
+static int mtk_set_features(struct net_device *dev,
+			    const netdev_features_t *features)
 {
 	netdev_features_t changed;
 	int err = 0;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (!netdev_feature_test(NETIF_F_LRO_BIT, changed))
 		return 0;
 
-	if (!netdev_feature_test(NETIF_F_LRO_BIT, features))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, *features))
 		mtk_hwlro_netdev_disable(dev);
 
 	return err;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 3ace17bbbae0..a93cd318d19d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2467,7 +2467,7 @@ static int mlx4_en_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
 		return -ERANGE;
 	}
 
-	if (mlx4_en_reset_config(dev, config, dev->features)) {
+	if (mlx4_en_reset_config(dev, config, &dev->features)) {
 		config.tx_type = HWTSTAMP_TX_OFF;
 		config.rx_filter = HWTSTAMP_FILTER_NONE;
 	}
@@ -2514,20 +2514,20 @@ static void mlx4_en_fix_features(struct net_device *netdev,
 }
 
 static int mlx4_en_set_features(struct net_device *netdev,
-		netdev_features_t features)
+				const netdev_features_t *features)
 {
 	struct mlx4_en_priv *priv = netdev_priv(netdev);
 	bool reset = false;
 	int ret = 0;
 
-	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_RXFCS_BIT)) {
+	if (DEV_FEATURE_CHANGED(netdev, *features, NETIF_F_RXFCS_BIT)) {
 		en_info(priv, "Turn %s RX-FCS\n",
-			netdev_feature_test(NETIF_F_RXFCS_BIT, features) ? "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 = netdev_feature_test(NETIF_F_RXALL_BIT, features) ? 1 : 0;
+	if (DEV_FEATURE_CHANGED(netdev, *features, NETIF_F_RXALL_BIT)) {
+		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");
@@ -2537,24 +2537,24 @@ static int mlx4_en_set_features(struct net_device *netdev,
 			return ret;
 	}
 
-	if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
+	if (DEV_FEATURE_CHANGED(netdev, *features, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
 		en_info(priv, "Turn %s RX vlan strip offload\n",
-			netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) ? "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))
+	if (DEV_FEATURE_CHANGED(netdev, *features, NETIF_F_HW_VLAN_CTAG_TX_BIT))
 		en_info(priv, "Turn %s TX vlan strip offload\n",
-			netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features) ? "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))
+	if (DEV_FEATURE_CHANGED(netdev, *features, NETIF_F_HW_VLAN_STAG_TX_BIT))
 		en_info(priv, "Turn %s TX S-VLAN strip offload\n",
-			netdev_feature_test(NETIF_F_HW_VLAN_STAG_TX_BIT, features) ? "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)) {
+	if (DEV_FEATURE_CHANGED(netdev, *features, NETIF_F_LOOPBACK_BIT)) {
 		en_info(priv, "Turn %s loopback\n",
-			netdev_feature_test(NETIF_F_LOOPBACK_BIT, features) ? "ON" : "OFF");
-		mlx4_en_update_loopback_state(netdev, features);
+			netdev_feature_test(NETIF_F_LOOPBACK_BIT, *features) ? "ON" : "OFF");
+		mlx4_en_update_loopback_state(netdev, *features);
 	}
 
 	if (reset) {
@@ -3498,7 +3498,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 
 int mlx4_en_reset_config(struct net_device *dev,
 			 struct hwtstamp_config ts_config,
-			 netdev_features_t features)
+			 const netdev_features_t *features)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
@@ -3509,12 +3509,12 @@ 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_BIT) &&
-	    !DEV_FEATURE_CHANGED(dev, features, NETIF_F_RXFCS_BIT))
+	    !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_BIT) &&
-	    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) &&
+	if (DEV_FEATURE_CHANGED(dev, *features, NETIF_F_HW_VLAN_CTAG_RX_BIT) &&
+	    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;
@@ -3540,8 +3540,8 @@ 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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+	if (DEV_FEATURE_CHANGED(dev, *features, NETIF_F_HW_VLAN_CTAG_RX_BIT)) {
+		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
@@ -3559,8 +3559,8 @@ int mlx4_en_reset_config(struct net_device *dev,
 						  NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	}
 
-	if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_RXFCS_BIT)) {
-		if (netdev_feature_test(NETIF_F_RXFCS_BIT, features))
+	if (DEV_FEATURE_CHANGED(dev, *features, NETIF_F_RXFCS_BIT)) {
+		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);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 29b0ac52c6a9..c514fb785e62 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -781,7 +781,7 @@ void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev);
 int mlx4_en_moderation_update(struct mlx4_en_priv *priv);
 int mlx4_en_reset_config(struct net_device *dev,
 			 struct hwtstamp_config ts_config,
-			 netdev_features_t new_features);
+			 const netdev_features_t *new_features);
 void mlx4_en_update_pfc_stats_bitmap(struct mlx4_dev *dev,
 				     struct mlx4_en_stats_bitmap *stats_bitmap,
 				     u8 rx_ppp, u8 rx_pause,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index c2dc487ac760..f70f6b9513aa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -1242,7 +1242,7 @@ void mlx5e_tx_dim_work(struct work_struct *work);
 
 void mlx5e_features_check(struct sk_buff *skb, struct net_device *netdev,
 			  netdev_features_t *features);
-int mlx5e_set_features(struct net_device *netdev, netdev_features_t features);
+int mlx5e_set_features(struct net_device *netdev, const netdev_features_t *features);
 #ifdef CONFIG_MLX5_ESWITCH
 int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac);
 int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate, int max_tx_rate);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index d6cc33d2079b..44a3ef2d8cd1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3861,11 +3861,14 @@ static int mlx5e_handle_feature(struct net_device *netdev,
 	return 0;
 }
 
-int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
+int mlx5e_set_features(struct net_device *netdev,
+		       const netdev_features_t *features)
 {
-	netdev_features_t oper_features = features;
+	netdev_features_t oper_features;
 	int err = 0;
 
+	netdev_features_copy(oper_features, *features);
+
 #define MLX5E_HANDLE_FEATURE(feature_bit, handler) \
 	mlx5e_handle_feature(netdev, &oper_features, feature_bit, handler)
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 9b1934a897e0..ccdc585b6e4c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1216,15 +1216,15 @@ static int mlxsw_sp_feature_loopback(struct net_device *dev, bool enable)
 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,
+				   const netdev_features_t *wanted_features,
 				   int feature_bit,
 				   mlxsw_sp_feature_handler feature_handler)
 {
-	bool enable = netdev_feature_test(feature_bit, wanted_features);
+	bool enable = netdev_feature_test(feature_bit, *wanted_features);
 	netdev_features_t changes;
 	int err;
 
-	netdev_features_xor(changes, dev->features, wanted_features);
+	netdev_features_xor(changes, dev->features, *wanted_features);
 	if (!netdev_feature_test(feature_bit, changes))
 		return 0;
 
@@ -1243,7 +1243,7 @@ static int mlxsw_sp_handle_feature(struct net_device *dev,
 	return 0;
 }
 static int mlxsw_sp_set_features(struct net_device *dev,
-				 netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	netdev_features_t oper_features = dev->features;
 	int err = 0;
@@ -1254,7 +1254,7 @@ static int mlxsw_sp_set_features(struct net_device *dev,
 				       mlxsw_sp_feature_loopback);
 
 	if (err) {
-		dev->features = oper_features;
+		netdev_active_features_copy(dev, oper_features);
 		return -EINVAL;
 	}
 
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 50789716b1c7..a917aaeed046 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -6498,7 +6498,7 @@ static void netdev_get_ethtool_stats(struct net_device *dev,
  * Return 0 if successful; otherwise an error code.
  */
 static int netdev_set_features(struct net_device *dev,
-	netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	struct dev_priv *priv = netdev_priv(dev);
 	struct dev_info *hw_priv = priv->adapter;
@@ -6507,7 +6507,7 @@ static int netdev_set_features(struct net_device *dev,
 	mutex_lock(&hw_priv->lock);
 
 	/* see note in hw_setup() */
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	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/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 828fa985f398..cfeb18cbe91b 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -843,13 +843,13 @@ static int ocelot_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
 }
 
 static void ocelot_vlan_mode(struct ocelot *ocelot, int port,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	u32 val;
 
 	/* Filtering */
 	val = ocelot_read(ocelot, ANA_VLANMASK);
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, *features))
 		val |= BIT(port);
 	else
 		val &= ~BIT(port);
@@ -857,16 +857,16 @@ static void ocelot_vlan_mode(struct ocelot *ocelot, int port,
 }
 
 static int ocelot_set_features(struct net_device *dev,
-			       netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	struct ocelot_port_private *priv = netdev_priv(dev);
 	struct ocelot *ocelot = priv->port.ocelot;
 	int port = priv->port.index;
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_active_feature_test(dev, NETIF_F_HW_TC_BIT) &&
-	    !netdev_feature_test(NETIF_F_HW_TC_BIT, features) &&
+	    !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");
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 951dd5045ecb..cd0f86d07ac4 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -6568,18 +6568,19 @@ static void s2io_ethtool_get_strings(struct net_device *dev,
 	}
 }
 
-static int s2io_set_features(struct net_device *dev, netdev_features_t features)
+static int s2io_set_features(struct net_device *dev,
+			     const netdev_features_t *features)
 {
 	struct s2io_nic *sp = netdev_priv(dev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_LRO_BIT, changed) && netif_running(dev)) {
 		int rc;
 
 		s2io_stop_all_tx_queue(sp);
 		s2io_card_down(sp);
-		dev->features = features;
+		netdev_active_features_copy(dev, *features);
 		rc = s2io_card_up(sp);
 		if (rc)
 			s2io_reset(sp);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 754179c46769..723ee0225c9f 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1664,7 +1664,7 @@ static void nfp_net_stat64(struct net_device *netdev,
 }
 
 static int nfp_net_set_features(struct net_device *netdev,
-				netdev_features_t features)
+				const netdev_features_t *features)
 {
 	struct nfp_net *nn = netdev_priv(netdev);
 	netdev_features_t changed;
@@ -1675,23 +1675,23 @@ static int nfp_net_set_features(struct net_device *netdev,
 
 	new_ctrl = nn->dp.ctrl;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+		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;
 	}
 
 	if (netdev_features_intersects(changed, netdev_ip_csum_features)) {
-		if (netdev_features_intersects(features, 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 (netdev_features_intersects(changed, netdev_general_tso_features)) {
-		if (netdev_features_intersects(features, 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
@@ -1699,7 +1699,7 @@ static int nfp_net_set_features(struct net_device *netdev,
 	}
 
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+		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
@@ -1707,7 +1707,7 @@ static int nfp_net_set_features(struct net_device *netdev,
 	}
 
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features))
+		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
@@ -1715,21 +1715,21 @@ static int nfp_net_set_features(struct net_device *netdev,
 	}
 
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
+		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 (netdev_feature_test(NETIF_F_HW_VLAN_STAG_RX_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_RX_BIT, features))
+		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 (netdev_feature_test(NETIF_F_SG_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_SG_BIT, features))
+		if (netdev_feature_test(NETIF_F_SG_BIT, *features))
 			new_ctrl |= NFP_NET_CFG_CTRL_GATHER;
 		else
 			new_ctrl &= ~NFP_NET_CFG_CTRL_GATHER;
@@ -1740,7 +1740,7 @@ static int nfp_net_set_features(struct net_device *netdev,
 		return err;
 
 	nn_dbg(nn, "Feature change 0x%llx -> 0x%llx (changed=0x%llx)\n",
-	       netdev->features, features, changed);
+	       netdev->features, *features, changed);
 
 	if (new_ctrl == nn->dp.ctrl)
 		return 0;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c
index 01a1fbf9aa0d..8cfda24f5171 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c
@@ -58,7 +58,8 @@ int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
 	return nfp_app_setup_tc(port->app, netdev, type, type_data);
 }
 
-int nfp_port_set_features(struct net_device *netdev, netdev_features_t features)
+int nfp_port_set_features(struct net_device *netdev,
+			  const netdev_features_t *features)
 {
 	struct nfp_port *port;
 
@@ -67,7 +68,7 @@ int nfp_port_set_features(struct net_device *netdev, netdev_features_t features)
 		return 0;
 
 	if (netdev_active_feature_test(netdev, NETIF_F_HW_TC_BIT) &&
-	    !netdev_feature_test(NETIF_F_HW_TC_BIT, features) &&
+	    !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/netronome/nfp/nfp_port.h b/drivers/net/ethernet/netronome/nfp/nfp_port.h
index 6793cdf9ff11..49acddc4474e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.h
@@ -103,7 +103,8 @@ static inline bool nfp_port_is_vnic(const struct nfp_port *port)
 }
 
 int
-nfp_port_set_features(struct net_device *netdev, netdev_features_t features);
+nfp_port_set_features(struct net_device *netdev,
+		      const netdev_features_t *features);
 
 struct nfp_port *nfp_port_from_netdev(struct net_device *netdev);
 int nfp_port_get_port_parent_id(struct net_device *netdev,
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 82bccdfcfa50..c1fc2d3f3109 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4872,7 +4872,8 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
 	return 0;
 }
 
-static int nv_set_loopback(struct net_device *dev, netdev_features_t features)
+static int nv_set_loopback(struct net_device *dev,
+			   const netdev_features_t *features)
 {
 	struct fe_priv *np = netdev_priv(dev);
 	unsigned long flags;
@@ -4881,7 +4882,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 (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features)) {
+	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");
@@ -4934,18 +4935,19 @@ static void nv_fix_features(struct net_device *dev, netdev_features_t *features)
 		netdev_feature_add(NETIF_F_RXCSUM_BIT, *features);
 }
 
-static void nv_vlan_mode(struct net_device *dev, netdev_features_t features)
+static void nv_vlan_mode(struct net_device *dev,
+			 const netdev_features_t *features)
 {
 	struct fe_priv *np = get_nvpriv(dev);
 
 	spin_lock_irq(&np->lock);
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+	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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features))
+	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;
@@ -4955,14 +4957,15 @@ static void nv_vlan_mode(struct net_device *dev, netdev_features_t features)
 	spin_unlock_irq(&np->lock);
 }
 
-static int nv_set_features(struct net_device *dev, netdev_features_t features)
+static int nv_set_features(struct net_device *dev,
+			   const netdev_features_t *features)
 {
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	netdev_features_t changed;
 	int retval;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, changed) &&
 	    netif_running(dev)) {
 		retval = nv_set_loopback(dev, features);
@@ -4973,7 +4976,7 @@ static int nv_set_features(struct net_device *dev, netdev_features_t features)
 	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		spin_lock_irq(&np->lock);
 
-		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 			np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
 		else
 			np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK;
@@ -5616,7 +5619,7 @@ static int nv_open(struct net_device *dev)
 	 * that it's set correctly now.
 	 */
 	if (netdev_active_feature_test(dev, NETIF_F_LOOPBACK_BIT))
-		nv_set_loopback(dev, dev->features);
+		nv_set_loopback(dev, &dev->features);
 
 	return 0;
 out_drain:
@@ -6113,7 +6116,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 	nv_stop_tx(dev);
 
 	if (id->driver_data & DEV_HAS_VLAN)
-		nv_vlan_mode(dev, dev->features);
+		nv_vlan_mode(dev, &dev->features);
 
 	dev_info(&pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, addr %pM\n",
 		 dev->name, np->phy_oui, np->phyaddr, dev->dev_addr);
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 452d3fae2f0e..b41db2d70812 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
@@ -2203,12 +2203,12 @@ static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu)
  *	0:		HW state updated successfully
  */
 static int pch_gbe_set_features(struct net_device *netdev,
-	netdev_features_t features)
+				const netdev_features_t *features)
 {
 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 081c54db89ef..79f5d936a49f 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1364,48 +1364,48 @@ static void ionic_ndo_set_rx_mode(struct net_device *netdev)
 	ionic_lif_deferred_enqueue(&lif->deferred, work);
 }
 
-static __le64 ionic_netdev_features_to_nic(netdev_features_t features)
+static __le64 ionic_netdev_features_to_nic(const netdev_features_t *features)
 {
 	u64 wanted = 0;
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features))
 		wanted |= IONIC_ETH_HW_VLAN_TX_TAG;
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features))
 		wanted |= IONIC_ETH_HW_VLAN_RX_STRIP;
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, *features))
 		wanted |= IONIC_ETH_HW_VLAN_RX_FILTER;
-	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features))
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, *features))
 		wanted |= IONIC_ETH_HW_RX_HASH;
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 		wanted |= IONIC_ETH_HW_RX_CSUM;
-	if (netdev_feature_test(NETIF_F_SG_BIT, features))
+	if (netdev_feature_test(NETIF_F_SG_BIT, *features))
 		wanted |= IONIC_ETH_HW_TX_SG;
-	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, *features))
 		wanted |= IONIC_ETH_HW_TX_CSUM;
-	if (netdev_feature_test(NETIF_F_TSO_BIT, features))
+	if (netdev_feature_test(NETIF_F_TSO_BIT, *features))
 		wanted |= IONIC_ETH_HW_TSO;
-	if (netdev_feature_test(NETIF_F_TSO6_BIT, features))
+	if (netdev_feature_test(NETIF_F_TSO6_BIT, *features))
 		wanted |= IONIC_ETH_HW_TSO_IPV6;
-	if (netdev_feature_test(NETIF_F_TSO_ECN_BIT, features))
+	if (netdev_feature_test(NETIF_F_TSO_ECN_BIT, *features))
 		wanted |= IONIC_ETH_HW_TSO_ECN;
-	if (netdev_feature_test(NETIF_F_GSO_GRE_BIT, features))
+	if (netdev_feature_test(NETIF_F_GSO_GRE_BIT, *features))
 		wanted |= IONIC_ETH_HW_TSO_GRE;
-	if (netdev_feature_test(NETIF_F_GSO_GRE_CSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_GSO_GRE_CSUM_BIT, *features))
 		wanted |= IONIC_ETH_HW_TSO_GRE_CSUM;
-	if (netdev_feature_test(NETIF_F_GSO_IPXIP4_BIT, features))
+	if (netdev_feature_test(NETIF_F_GSO_IPXIP4_BIT, *features))
 		wanted |= IONIC_ETH_HW_TSO_IPXIP4;
-	if (netdev_feature_test(NETIF_F_GSO_IPXIP6_BIT, features))
+	if (netdev_feature_test(NETIF_F_GSO_IPXIP6_BIT, *features))
 		wanted |= IONIC_ETH_HW_TSO_IPXIP6;
-	if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_BIT, features))
+	if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_BIT, *features))
 		wanted |= IONIC_ETH_HW_TSO_UDP;
-	if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, *features))
 		wanted |= IONIC_ETH_HW_TSO_UDP_CSUM;
 
 	return cpu_to_le64(wanted);
 }
 
 static int ionic_set_nic_features(struct ionic_lif *lif,
-				  netdev_features_t features)
+				  const netdev_features_t *features)
 {
 	struct device *dev = lif->ionic->dev;
 	struct ionic_admin_ctx ctx = {
@@ -1502,7 +1502,7 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
 	if (lif->nxqs > 1)
 		netdev_feature_add(NETIF_F_RXHASH_BIT, features);
 
-	err = ionic_set_nic_features(lif, features);
+	err = ionic_set_nic_features(lif, &features);
 	if (err)
 		return err;
 
@@ -1557,13 +1557,13 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
 }
 
 static int ionic_set_features(struct net_device *netdev,
-			      netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	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);
+		   __func__, (u64)lif->netdev->features, (u64)*features);
 
 	err = ionic_set_nic_features(lif, features);
 
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index e2af570cda6e..61b1636e8f86 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -531,23 +531,23 @@ static void netxen_fix_features(struct net_device *dev,
 }
 
 static int netxen_set_features(struct net_device *dev,
-	netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
 	netdev_features_t changed;
 	int hw_lro;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (!netdev_feature_test(NETIF_F_LRO_BIT, changed))
 		return 0;
 
-	hw_lro = (netdev_feature_test(NETIF_F_LRO_BIT, features)) ? NETXEN_NIC_LRO_ENABLED
+	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 (!netdev_feature_test(NETIF_F_LRO_BIT, features) && netxen_send_lro_cleanup(adapter))
+	if (!netdev_feature_test(NETIF_F_LRO_BIT, *features) && netxen_send_lro_cleanup(adapter))
 		return -EIO;
 
 	return 0;
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index ada71452d454..de6c226fa6ab 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -546,7 +546,7 @@ void qede_vlan_mark_nonconfigured(struct qede_dev *edev);
 int qede_configure_vlan_filters(struct qede_dev *edev);
 
 void qede_fix_features(struct net_device *dev, netdev_features_t *features);
-int qede_set_features(struct net_device *dev, netdev_features_t features);
+int qede_set_features(struct net_device *dev, const netdev_features_t *features);
 void qede_set_rx_mode(struct net_device *ndev);
 void qede_config_rx_mode(struct net_device *ndev);
 void qede_fill_rss_params(struct qede_dev *edev,
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index b6d6ce69929c..0f391d75d9be 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -919,20 +919,20 @@ void qede_fix_features(struct net_device *dev, netdev_features_t *features)
 		netdev_feature_del(NETIF_F_GRO_HW_BIT, *features);
 }
 
-int qede_set_features(struct net_device *dev, netdev_features_t features)
+int qede_set_features(struct net_device *dev, const netdev_features_t *features)
 {
 	struct qede_dev *edev = netdev_priv(dev);
 	netdev_features_t changes;
 	bool need_reload = false;
 
-	netdev_features_xor(changes, dev->features, features);
+	netdev_features_xor(changes, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, changes))
 		need_reload = true;
 
 	if (need_reload) {
 		struct qede_reload_args args;
 
-		args.u.features = features;
+		netdev_features_copy(args.u.features, *features);
 		args.func = &qede_set_features_reload;
 
 		/* Make sure that we definitely need to reload.
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 9b41e2f5c82c..4d8f2292c1d7 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1624,7 +1624,8 @@ int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *, u32);
 int qlcnic_change_mtu(struct net_device *netdev, int new_mtu);
 void qlcnic_fix_features(struct net_device *netdev,
 			 netdev_features_t *features);
-int qlcnic_set_features(struct net_device *netdev, netdev_features_t features);
+int qlcnic_set_features(struct net_device *netdev,
+			const netdev_features_t *features);
 int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
 void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *);
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 3efc9f294712..4cb6dce41ad3 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1086,13 +1086,14 @@ void qlcnic_fix_features(struct net_device *netdev, netdev_features_t *features)
 }
 
 
-int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
+int qlcnic_set_features(struct net_device *netdev,
+			const netdev_features_t *features)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
-	int hw_lro = netdev_feature_test(NETIF_F_LRO_BIT, features) ? QLCNIC_LRO_ENABLED : 0;
+	int hw_lro = netdev_feature_test(NETIF_F_LRO_BIT, *features) ? QLCNIC_LRO_ENABLED : 0;
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	if (!netdev_feature_test(NETIF_F_LRO_BIT, changed))
 		return 0;
 
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index f74079e9c43a..3a5f9c93edb8 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -174,12 +174,12 @@ static irqreturn_t emac_isr(int _irq, void *data)
 
 /* Configure VLAN tag strip/insert feature */
 static int emac_set_features(struct net_device *netdev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct emac_adapter *adpt = netdev_priv(netdev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	/* We only need to reprogram the hardware if the VLAN tag features
 	 * have changed, and if it's already running.
 	 */
@@ -192,7 +192,7 @@ static int emac_set_features(struct net_device *netdev,
 	/* emac_mac_mode_config() uses netdev->features to configure the EMAC,
 	 * so make sure it's set first.
 	 */
-	netdev->features = features;
+	netdev_active_features_copy(netdev, *features);
 
 	return emac_reinit_locked(adpt);
 }
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 65dd210b0b25..098b0ee85f36 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1459,24 +1459,25 @@ static void cp_set_msglevel(struct net_device *dev, u32 value)
 	cp->msg_enable = value;
 }
 
-static int cp_set_features(struct net_device *dev, netdev_features_t features)
+static int cp_set_features(struct net_device *dev,
+			   const netdev_features_t *features)
 {
 	struct cp_private *cp = netdev_priv(dev);
 	netdev_features_t changed;
 	unsigned long flags;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		return 0;
 
 	spin_lock_irqsave(&cp->lock, flags);
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 		cp->cpcmd |= RxChkSum;
 	else
 		cp->cpcmd &= ~RxChkSum;
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+	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 24b30873c38d..c8f1622a230f 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -898,14 +898,15 @@ static struct net_device *rtl8139_init_board(struct pci_dev *pdev)
 	return ERR_PTR(rc);
 }
 
-static int rtl8139_set_features(struct net_device *dev, netdev_features_t features)
+static int rtl8139_set_features(struct net_device *dev,
+				const netdev_features_t *features)
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
 	unsigned long flags;
 	netdev_features_t changed;
 	void __iomem *ioaddr = tp->mmio_addr;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (!netdev_feature_test(NETIF_F_RXALL_BIT, changed))
 		return 0;
 
@@ -913,7 +914,7 @@ static int rtl8139_set_features(struct net_device *dev, netdev_features_t featur
 
 	if (netdev_feature_test(NETIF_F_RXALL_BIT, changed)) {
 		int rx_mode = tp->rx_config;
-		if (netdev_feature_test(NETIF_F_RXALL_BIT, features))
+		if (netdev_feature_test(NETIF_F_RXALL_BIT, *features))
 			rx_mode |= (AcceptErr | AcceptRunt);
 		else
 			rx_mode &= ~(AcceptErr | AcceptRunt);
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 7f1dd10b6387..3ae8110e1596 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1438,17 +1438,17 @@ static void rtl8169_fix_features(struct net_device *dev,
 }
 
 static void rtl_set_rx_config_features(struct rtl8169_private *tp,
-				       netdev_features_t features)
+				       const netdev_features_t *features)
 {
 	u32 rx_config = RTL_R32(tp, RxConfig);
 
-	if (netdev_feature_test(NETIF_F_RXALL_BIT, features))
+	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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features))
 			rx_config |= RX_VLAN_8125;
 		else
 			rx_config &= ~RX_VLAN_8125;
@@ -1458,19 +1458,19 @@ static void rtl_set_rx_config_features(struct rtl8169_private *tp,
 }
 
 static int rtl8169_set_features(struct net_device *dev,
-				netdev_features_t features)
+				const netdev_features_t *features)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 
 	rtl_set_rx_config_features(tp, features);
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 		tp->cp_cmd |= RxChkSum;
 	else
 		tp->cp_cmd &= ~RxChkSum;
 
 	if (!rtl_is_8125(tp)) {
-		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features))
 			tp->cp_cmd |= RxVlan;
 		else
 			tp->cp_cmd &= ~RxVlan;
@@ -3723,7 +3723,7 @@ static void rtl_hw_start(struct  rtl8169_private *tp)
 	RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb);
 	rtl_init_rxcfg(tp);
 	rtl_set_tx_config_registers(tp);
-	rtl_set_rx_config_features(tp, tp->dev->features);
+	rtl_set_rx_config_features(tp, &tp->dev->features);
 	rtl_set_rx_mode(tp->dev);
 	rtl_irq_enable(tp);
 }
@@ -5279,7 +5279,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_feature_add(dev, NETIF_F_RXFCS_BIT);
 
 	/* configure chip for default features */
-	rtl8169_set_features(dev, dev->features);
+	rtl8169_set_features(dev, &dev->features);
 
 	if (tp->dash_type == RTL_DASH_NONE) {
 		rtl_set_d3_pll_down(tp, true);
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index efd3c32b9e46..42ade12eda0f 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -1009,7 +1009,8 @@ struct ravb_hw_info {
 	void *(*alloc_rx_desc)(struct net_device *ndev, int q);
 	bool (*receive)(struct net_device *ndev, int *quota, int q);
 	void (*set_rate)(struct net_device *ndev);
-	int (*set_feature)(struct net_device *ndev, netdev_features_t features);
+	int (*set_feature)(struct net_device *ndev,
+			   const netdev_features_t *features);
 	int (*dmac_init)(struct net_device *ndev);
 	void (*emac_init)(struct net_device *ndev);
 	const char (*gstrings_stats)[ETH_GSTRING_LEN];
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 49c2d8aa3c25..5f99a06ef122 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -2327,29 +2327,29 @@ static void ravb_set_rx_csum(struct net_device *ndev, bool enable)
 }
 
 static int ravb_set_features_gbeth(struct net_device *ndev,
-				   netdev_features_t features)
+				   const netdev_features_t *features)
 {
 	/* Place holder */
 	return 0;
 }
 
 static int ravb_set_features_rcar(struct net_device *ndev,
-				  netdev_features_t features)
+				  const netdev_features_t *features)
 {
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, ndev->features, features);
+	netdev_features_xor(changed, ndev->features, *features);
 	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed))
 		ravb_set_rx_csum(ndev,
-				 netdev_feature_test(NETIF_F_RXCSUM_BIT, features));
+				 netdev_feature_test(NETIF_F_RXCSUM_BIT, *features));
 
-	ndev->features = features;
+	netdev_active_features_copy(ndev, *features);
 
 	return 0;
 }
 
 static int ravb_set_features(struct net_device *ndev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct ravb_private *priv = netdev_priv(ndev);
 	const struct ravb_hw_info *info = priv->info;
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 4a55c969241c..cf027162da71 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2930,17 +2930,17 @@ 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)
+			       const netdev_features_t *features)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, ndev->features, features);
+	netdev_features_xor(changed, ndev->features, *features);
 	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));
+				   netdev_feature_test(NETIF_F_RXCSUM_BIT, *features));
 
-	ndev->features = features;
+	netdev_active_features_copy(ndev, *features);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index da2f375ad180..d77175ab4dfa 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -1776,14 +1776,14 @@ static void sxgbe_get_stats64(struct net_device *dev,
  *  This function returns 0 after setting or resetting device features.
  */
 static int sxgbe_set_features(struct net_device *dev,
-			      netdev_features_t features)
+			      const netdev_features_t *features)
 {
 	struct sxgbe_priv_data *priv = netdev_priv(dev);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
+		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/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index df921615ba5a..670e30425447 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -210,14 +210,14 @@ void efx_set_rx_mode(struct net_device *net_dev)
 	/* Otherwise efx_start_port() will do this */
 }
 
-int efx_set_features(struct net_device *net_dev, netdev_features_t data)
+int efx_set_features(struct net_device *net_dev, const 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 */
-	netdev_features_andnot(tmp, net_dev->features, data);
+	netdev_features_andnot(tmp, net_dev->features, *data);
 	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, tmp)) {
 		rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
 		if (rc)
@@ -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.
 	 */
-	netdev_features_xor(tmp, net_dev->features, data);
+	netdev_features_xor(tmp, net_dev->features, *data);
 	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
diff --git a/drivers/net/ethernet/sfc/efx_common.h b/drivers/net/ethernet/sfc/efx_common.h
index a191f85b3f5d..3242ce0bb17f 100644
--- a/drivers/net/ethernet/sfc/efx_common.h
+++ b/drivers/net/ethernet/sfc/efx_common.h
@@ -96,7 +96,7 @@ static inline void efx_fini_mcdi_logging(struct efx_nic *efx) {}
 void efx_mac_reconfigure(struct efx_nic *efx, bool mtu_only);
 int efx_set_mac_address(struct net_device *net_dev, void *data);
 void efx_set_rx_mode(struct net_device *net_dev);
-int efx_set_features(struct net_device *net_dev, netdev_features_t data);
+int efx_set_features(struct net_device *net_dev, const netdev_features_t *data);
 void efx_link_status_changed(struct efx_nic *efx);
 unsigned int efx_xdp_max_mtu(struct efx_nic *efx);
 int efx_change_mtu(struct net_device *net_dev, int new_mtu);
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c
index 232e8fde0a81..438f8a453f32 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -2180,14 +2180,15 @@ static void ef4_set_rx_mode(struct net_device *net_dev)
 	/* Otherwise ef4_start_port() will do this */
 }
 
-static int ef4_set_features(struct net_device *net_dev, netdev_features_t data)
+static int ef4_set_features(struct net_device *net_dev,
+			    const 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 */
-	netdev_features_andnot(tmp, net_dev->features, data);
+	netdev_features_andnot(tmp, net_dev->features, *data);
 	if (netdev_feature_test(NETIF_F_NTUPLE_BIT, tmp)) {
 		rc = efx->type->filter_clear_rx(efx, EF4_FILTER_PRI_MANUAL);
 		if (rc)
@@ -2195,7 +2196,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 */
-	netdev_features_xor(tmp, net_dev->features, data);
+	netdev_features_xor(tmp, net_dev->features, *data);
 	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/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index 12aa69a679cf..fc3bf13d4b67 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -209,7 +209,8 @@ void efx_siena_set_rx_mode(struct net_device *net_dev)
 	/* Otherwise efx_start_port() will do this */
 }
 
-int efx_siena_set_features(struct net_device *net_dev, netdev_features_t data)
+int efx_siena_set_features(struct net_device *net_dev,
+			   const netdev_features_t *data)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	netdev_features_t features;
@@ -217,7 +218,7 @@ int efx_siena_set_features(struct net_device *net_dev, netdev_features_t data)
 
 	/* If disabling RX n-tuple filtering, clear existing filters */
 	if (netdev_active_feature_test(net_dev, NETIF_F_NTUPLE_BIT) &&
-	    !netdev_feature_test(NETIF_F_NTUPLE_BIT, data)) {
+	    !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,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.
 	 */
-	netdev_features_xor(features, net_dev->features, data);
+	netdev_features_xor(features, net_dev->features, *data);
 	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
diff --git a/drivers/net/ethernet/sfc/siena/efx_common.h b/drivers/net/ethernet/sfc/siena/efx_common.h
index d0e2cefba6cb..23d1163c7358 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.h
+++ b/drivers/net/ethernet/sfc/siena/efx_common.h
@@ -99,7 +99,7 @@ static inline void efx_siena_fini_mcdi_logging(struct efx_nic *efx) {}
 void efx_siena_mac_reconfigure(struct efx_nic *efx, bool mtu_only);
 int efx_siena_set_mac_address(struct net_device *net_dev, void *data);
 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);
+int efx_siena_set_features(struct net_device *net_dev, const netdev_features_t *data);
 void efx_siena_link_status_changed(struct efx_nic *efx);
 unsigned int efx_siena_xdp_max_mtu(struct efx_nic *efx);
 int efx_siena_change_mtu(struct net_device *net_dev, int new_mtu);
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index d594f6b312f2..05db1d69ae2a 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -1748,11 +1748,12 @@ static void netsec_netdev_uninit(struct net_device *ndev)
 }
 
 static int netsec_netdev_set_features(struct net_device *ndev,
-				      netdev_features_t features)
+				      const netdev_features_t *features)
 {
 	struct netsec_priv *priv = netdev_priv(ndev);
 
-	priv->rx_cksum_offload_flag = netdev_feature_test(NETIF_F_RXCSUM_BIT, features);
+	priv->rx_cksum_offload_flag = netdev_feature_test(NETIF_F_RXCSUM_BIT,
+							  *features);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c70f297c1653..4b01d03185e8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5614,12 +5614,12 @@ static void stmmac_fix_features(struct net_device *dev,
 }
 
 static int stmmac_set_features(struct net_device *netdev,
-			       netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	struct stmmac_priv *priv = netdev_priv(netdev);
 
 	/* Keep the COE Type in case of csum is supporting */
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	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/synopsys/dwc-xlgmac-net.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
index 302304ccb41f..9f283d13e4f7 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
@@ -877,7 +877,7 @@ static void xlgmac_poll_controller(struct net_device *netdev)
 #endif /* CONFIG_NET_POLL_CONTROLLER */
 
 static int xlgmac_set_features(struct net_device *netdev,
-			       netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter;
 	struct xlgmac_pdata *pdata = netdev_priv(netdev);
@@ -891,29 +891,29 @@ static int xlgmac_set_features(struct net_device *netdev,
 	rxvlan_filter = netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 					    pdata->netdev_features);
 
-	if (netdev_feature_test(NETIF_F_RXHASH_BIT, features) && !rxhash)
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, *features) && !rxhash)
 		ret = hw_ops->enable_rss(pdata);
-	else if (!netdev_feature_test(NETIF_F_RXHASH_BIT, features) && rxhash)
+	else if (!netdev_feature_test(NETIF_F_RXHASH_BIT, *features) && rxhash)
 		ret = hw_ops->disable_rss(pdata);
 	if (ret)
 		return ret;
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && !rxcsum)
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features) && !rxcsum)
 		hw_ops->enable_rx_csum(pdata);
-	else if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features) && rxcsum)
+	else if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, *features) && rxcsum)
 		hw_ops->disable_rx_csum(pdata);
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) && !rxvlan)
+	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features) && !rxvlan)
 		hw_ops->enable_rx_vlan_stripping(pdata);
-	else if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features) && rxvlan)
+	else if (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features) && rxvlan)
 		hw_ops->disable_rx_vlan_stripping(pdata);
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) && !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 (!netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features) && 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;
+	netdev_features_copy(pdata->netdev_features, *features);
 
 	return 0;
 }
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index e89fcfc52247..c96811972969 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1920,25 +1920,27 @@ static void netvsc_fix_features(struct net_device *ndev,
 }
 
 static int netvsc_set_features(struct net_device *ndev,
-			       netdev_features_t features)
+			       const netdev_features_t *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);
 	struct ndis_offload_params offloads;
 	netdev_features_t change;
+	netdev_features_t feats;
 	int ret = 0;
 
 	if (!nvdev || nvdev->destroy)
 		return -ENODEV;
 
-	netdev_features_xor(change, ndev->features, features);
+	netdev_features_copy(feats, feats);
+	netdev_features_xor(change, ndev->features, feats);
 	if (!netdev_feature_test(NETIF_F_LRO_BIT, change))
 		goto syncvf;
 
 	memset(&offloads, 0, sizeof(struct ndis_offload_params));
 
-	if (netdev_feature_test(NETIF_F_LRO_BIT, features)) {
+	if (netdev_feature_test(NETIF_F_LRO_BIT, feats)) {
 		offloads.rsc_ip_v4 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED;
 		offloads.rsc_ip_v6 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED;
 	} else {
@@ -1949,15 +1951,15 @@ static int netvsc_set_features(struct net_device *ndev,
 	ret = rndis_filter_set_offload_params(ndev, nvdev, &offloads);
 
 	if (ret) {
-		netdev_feature_change(NETIF_F_LRO_BIT, features);
-		ndev->features = features;
+		netdev_feature_change(NETIF_F_LRO_BIT, feats);
+		netdev_active_features_copy(ndev, feats);
 	}
 
 syncvf:
 	if (!vf_netdev)
 		return ret;
 
-	vf_netdev->wanted_features = features;
+	netdev_wanted_features_copy(vf_netdev, feats);
 	netdev_update_features(vf_netdev);
 
 	return ret;
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 00f660d89c82..4b5ed4452710 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -229,12 +229,12 @@ nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
 }
 
 static int
-nsim_set_features(struct net_device *dev, netdev_features_t features)
+nsim_set_features(struct net_device *dev, const netdev_features_t *features)
 {
 	struct netdevsim *ns = netdev_priv(dev);
 
 	if (netdev_active_feature_test(dev, NETIF_F_HW_TC_BIT) &&
-	    !netdev_feature_test(NETIF_F_HW_TC_BIT, features))
+	    !netdev_feature_test(NETIF_F_HW_TC_BIT, *features))
 		return nsim_bpf_disable_tc(ns);
 
 	return 0;
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 6687081c5e37..5672382dc361 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -589,7 +589,7 @@ static void aqc111_set_rx_mode(struct net_device *net)
 }
 
 static int aqc111_set_features(struct net_device *net,
-			       netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	struct usbnet *dev = netdev_priv(net);
 	struct aqc111_data *aqc111_data = dev->driver_priv;
@@ -597,7 +597,7 @@ static int aqc111_set_features(struct net_device *net,
 	u16 reg16 = 0;
 	u8 reg8 = 0;
 
-	netdev_features_xor(changed, net->features, features);
+	netdev_features_xor(changed, net->features, *features);
 	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;
@@ -614,7 +614,7 @@ static int aqc111_set_features(struct net_device *net,
 
 	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, &reg8);
-		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
+		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);
@@ -628,7 +628,7 @@ static int aqc111_set_features(struct net_device *net,
 				 1, 1, &reg8);
 	}
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) {
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, *features)) {
 			u16 i = 0;
 
 			for (i = 0; i < 256; i++) {
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 3f3c7da6f758..1ff3bd37792f 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -894,13 +894,13 @@ static void ax88179_set_multicast(struct net_device *net)
 }
 
 static int
-ax88179_set_features(struct net_device *net, netdev_features_t features)
+ax88179_set_features(struct net_device *net, const netdev_features_t *features)
 {
 	u8 tmp;
 	struct usbnet *dev = netdev_priv(net);
 	netdev_features_t changed;
 
-	netdev_features_xor(changed, net->features, features);
+	netdev_features_xor(changed, net->features, *features);
 	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;
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 6cf85b19d4ac..227ca5943007 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -2592,7 +2592,7 @@ static int lan78xx_set_mac_addr(struct net_device *netdev, void *p)
 
 /* Enable or disable Rx checksum offload engine */
 static int lan78xx_set_features(struct net_device *netdev,
-				netdev_features_t features)
+				const netdev_features_t *features)
 {
 	struct lan78xx_net *dev = netdev_priv(netdev);
 	struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
@@ -2600,7 +2600,7 @@ static int lan78xx_set_features(struct net_device *netdev,
 
 	spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features)) {
+	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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+	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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features))
+	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_;
@@ -3022,7 +3022,7 @@ static int lan78xx_reset(struct lan78xx_net *dev)
 		return ret;
 
 	/* Enable or disable checksum offload engines */
-	ret = lan78xx_set_features(dev->net, dev->net->features);
+	ret = lan78xx_set_features(dev->net, &dev->net->features);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index edce2a0d3dd7..5b4f73b7c023 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)
+				const netdev_features_t *features)
 {
 	struct r8152 *tp = netdev_priv(dev);
 	netdev_features_t changed;
@@ -3261,12 +3261,12 @@ static int rtl8152_set_features(struct net_device *dev,
 	if (ret < 0)
 		goto out;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 
 	mutex_lock(&tp->control);
 
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+		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);
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index d3f64cdadfd4..a3cd5f974f6c 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -935,7 +935,7 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
 
 /* Enable or disable Rx checksum offload engine */
 static int smsc75xx_set_features(struct net_device *netdev,
-	netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
@@ -944,7 +944,7 @@ static int smsc75xx_set_features(struct net_device *netdev,
 
 	spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	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);
@@ -1319,7 +1319,7 @@ static int smsc75xx_reset(struct usbnet *dev)
 		  pdata->rfe_ctl);
 
 	/* Enable or disable checksum offload engines */
-	smsc75xx_set_features(dev->net, dev->net->features);
+	smsc75xx_set_features(dev->net, &dev->net->features);
 
 	smsc75xx_set_multicast(dev->net);
 
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 43ba97ab1a82..c3926ae1c11d 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -591,7 +591,7 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
 
 /* Enable or disable Tx & Rx checksum offload engines */
 static int smsc95xx_set_features(struct net_device *netdev,
-	netdev_features_t features)
+				 const netdev_features_t *features)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	u32 read_buf;
@@ -601,12 +601,12 @@ static int smsc95xx_set_features(struct net_device *netdev,
 	if (ret < 0)
 		return ret;
 
-	if (netdev_feature_test(NETIF_F_IP_CSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_IP_CSUM_BIT, *features))
 		read_buf |= Tx_COE_EN_;
 	else
 		read_buf &= ~Tx_COE_EN_;
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 		read_buf |= Rx_COE_EN_;
 	else
 		read_buf &= ~Rx_COE_EN_;
@@ -992,7 +992,7 @@ static int smsc95xx_reset(struct usbnet *dev)
 		return ret;
 
 	/* Enable or disable checksum offload engines */
-	ret = smsc95xx_set_features(dev->net, dev->net->features);
+	ret = smsc95xx_set_features(dev->net, &dev->net->features);
 	if (ret < 0) {
 		netdev_warn(dev->net, "Failed to set checksum offload features\n");
 		return ret;
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index ac7a6ebadf00..8c516efa818d 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1467,18 +1467,18 @@ static void veth_fix_features(struct net_device *dev,
 }
 
 static int veth_set_features(struct net_device *dev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	struct veth_priv *priv = netdev_priv(dev);
 	netdev_features_t changed;
 	int err;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (!netdev_feature_test(NETIF_F_GRO_BIT, changed) ||
 	    !(dev->flags & IFF_UP) || priv->_xdp_prog)
 		return 0;
 
-	if (netdev_feature_test(NETIF_F_GRO_BIT, features)) {
+	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 f10bfe07d48d..d4e9ffa9695e 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3209,19 +3209,19 @@ static int virtnet_get_phys_port_name(struct net_device *dev, char *buf,
 }
 
 static int virtnet_set_features(struct net_device *dev,
-				netdev_features_t features)
+				const netdev_features_t *features)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 	netdev_features_t changed;
 	u64 offloads;
 	int err;
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	if (netdev_feature_test(NETIF_F_GRO_HW_BIT, changed)) {
 		if (vi->xdp_enabled)
 			return -EBUSY;
 
-		if (netdev_feature_test(NETIF_F_GRO_HW_BIT, features))
+		if (netdev_feature_test(NETIF_F_GRO_HW_BIT, *features))
 			offloads = vi->guest_offloads_capable;
 		else
 			offloads = vi->guest_offloads_capable &
@@ -3234,7 +3234,7 @@ static int virtnet_set_features(struct net_device *dev,
 	}
 
 	if (netdev_feature_test(NETIF_F_RXHASH_BIT, changed)) {
-		if (netdev_feature_test(NETIF_F_RXHASH_BIT, 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_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 6f6338a22c31..f16d5fa08e7e 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -300,7 +300,8 @@ void vmxnet3_features_check(struct sk_buff *skb, struct net_device *netdev,
 	}
 }
 
-static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_features_t features)
+static void vmxnet3_enable_encap_offloads(struct net_device *netdev,
+					  const netdev_features_t *features)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
@@ -313,10 +314,10 @@ static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_feat
 					       NETIF_F_TSO_BIT,
 					       NETIF_F_TSO6_BIT,
 					       NETIF_F_LRO_BIT);
-		if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_BIT, features))
+		if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_BIT, *features))
 			netdev_hw_enc_feature_add(netdev,
 						  NETIF_F_GSO_UDP_TUNNEL_BIT);
-		if (netdev_feature_test(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, features))
+		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);
 	}
@@ -403,7 +404,8 @@ static void vmxnet3_disable_encap_offloads(struct net_device *netdev)
 	}
 }
 
-int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
+int vmxnet3_set_features(struct net_device *netdev,
+			 const netdev_features_t *features)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	unsigned long flags;
@@ -416,12 +418,12 @@ 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_active_features_intersects(netdev, tun_offload_mask);
 
-	netdev_features_xor(changed, netdev->features, features);
+	netdev_features_xor(changed, netdev->features, *features);
 	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) ||
 	    netdev_features_intersects(changed, tun_offload_mask)) {
-		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features))
+		if (netdev_feature_test(NETIF_F_RXCSUM_BIT, *features))
 			adapter->shared->devRead.misc.uptFeatures |=
 			UPT1_F_RXCSUM;
 		else
@@ -429,25 +431,25 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 			~UPT1_F_RXCSUM;
 
 		/* update hardware LRO capability accordingly */
-		if (netdev_feature_test(NETIF_F_LRO_BIT, features))
+		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 (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features))
+		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, *features))
 			adapter->shared->devRead.misc.uptFeatures |=
 			UPT1_F_RXVLAN;
 		else
 			adapter->shared->devRead.misc.uptFeatures &=
 			~UPT1_F_RXVLAN;
 
-		if (netdev_features_intersects(features, tun_offload_mask)) {
+		if (netdev_features_intersects(*features, tun_offload_mask)) {
 			vmxnet3_enable_encap_offloads(netdev, features);
 			adapter->shared->devRead.misc.uptFeatures |=
 			UPT1_F_RXINNEROFLD;
-		} else if (!netdev_features_intersects(features, tun_offload_mask) &&
+		} 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/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index c9aac6a8e65c..987ffda65ee0 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -499,7 +499,8 @@ vmxnet3_features_check(struct sk_buff *skb,
 		       struct net_device *netdev, netdev_features_t *features);
 
 int
-vmxnet3_set_features(struct net_device *netdev, netdev_features_t features);
+vmxnet3_set_features(struct net_device *netdev,
+		     const netdev_features_t *features);
 
 int
 vmxnet3_create_queues(struct vmxnet3_adapter *adapter,
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 9ae4af581545..84949d124ef8 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1120,31 +1120,31 @@ static int ath6kl_close(struct net_device *dev)
 }
 
 static int ath6kl_set_features(struct net_device *dev,
-			       netdev_features_t features)
+			       const netdev_features_t *features)
 {
 	struct ath6kl_vif *vif = netdev_priv(dev);
 	struct ath6kl *ar = vif->ar;
 	int err = 0;
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, features) &&
+	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,
 							 vif->fw_vif_idx,
 							 ar->rx_meta_ver, 0, 0);
 		if (err) {
-			dev->features = features;
+			netdev_active_features_copy(dev, *features);
 			netdev_active_feature_del(dev, NETIF_F_RXCSUM_BIT);
 			return err;
 		}
-	} else if (!netdev_feature_test(NETIF_F_RXCSUM_BIT, features) &&
+	} 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,
 							 vif->fw_vif_idx,
 							 ar->rx_meta_ver, 0, 0);
 		if (err) {
-			dev->features = features;
+			netdev_active_features_copy(dev, *features);
 			netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 			return err;
 		}
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index f83a5e3c6de9..654f805f4522 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1495,9 +1495,9 @@ static void xennet_fix_features(struct net_device *dev,
 }
 
 static int xennet_set_features(struct net_device *dev,
-	netdev_features_t features)
+			       const netdev_features_t *features)
 {
-	if (!netdev_feature_test(NETIF_F_SG_BIT, features) && 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.h b/drivers/s390/net/qeth_core.h
index 6214f7f0d5ae..b0ac056aa8d0 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -1085,7 +1085,7 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
 int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
 int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
 int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
-int qeth_set_features(struct net_device *, netdev_features_t);
+int qeth_set_features(struct net_device *, const netdev_features_t *);
 void qeth_enable_hw_features(struct net_device *dev);
 void qeth_fix_features(struct net_device *, netdev_features_t *);
 void qeth_features_check(struct sk_buff *skb, struct net_device *dev,
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 31326e81344f..b3ca79930c42 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6788,7 +6788,7 @@ static void qeth_check_restricted_features(struct qeth_card *card,
 		qeth_flush_local_addrs4(card);
 }
 
-int qeth_set_features(struct net_device *dev, netdev_features_t features)
+int qeth_set_features(struct net_device *dev, const netdev_features_t *features)
 {
 	struct qeth_card *card = dev->ml_priv;
 	netdev_features_t changed;
@@ -6797,12 +6797,12 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
 	int rc = 0;
 
 	QETH_CARD_TEXT(card, 2, "setfeat");
-	QETH_CARD_HEX(card, 2, &features, sizeof(features));
+	QETH_CARD_HEX(card, 2, features, sizeof(*features));
 
-	netdev_features_xor(changed, dev->features, features);
+	netdev_features_xor(changed, dev->features, *features);
 	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),
+				       netdev_feature_test(NETIF_F_IP_CSUM_BIT, *features),
 				       IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV4,
 				       &card->info.has_lp2lp_cso_v4);
 		if (rc)
@@ -6810,7 +6810,7 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
 	}
 	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),
+				       netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, *features),
 				       IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV6,
 				       &card->info.has_lp2lp_cso_v6);
 		if (rc)
@@ -6818,26 +6818,26 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
 	}
 	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, changed)) {
 		rc = qeth_set_ipa_rx_csum(card,
-					  netdev_feature_test(NETIF_F_RXCSUM_BIT, features));
+					  netdev_feature_test(NETIF_F_RXCSUM_BIT, *features));
 		if (rc)
 			netdev_feature_change(NETIF_F_RXCSUM_BIT, changed);
 	}
 	if (netdev_feature_test(NETIF_F_TSO_BIT, changed)) {
 		rc = qeth_set_ipa_tso(card,
-				      netdev_feature_test(NETIF_F_TSO_BIT, features),
+				      netdev_feature_test(NETIF_F_TSO_BIT, *features),
 				      QETH_PROT_IPV4);
 		if (rc)
 			netdev_feature_change(NETIF_F_TSO_BIT, changed);
 	}
 	if (netdev_feature_test(NETIF_F_TSO6_BIT, changed)) {
 		rc = qeth_set_ipa_tso(card,
-				      netdev_feature_test(NETIF_F_TSO6_BIT, features),
+				      netdev_feature_test(NETIF_F_TSO6_BIT, *features),
 				      QETH_PROT_IPV6);
 		if (rc)
 			netdev_feature_change(NETIF_F_TSO6_BIT, changed);
 	}
 
-	netdev_features_xor(diff1, dev->features, features);
+	netdev_features_xor(diff1, dev->features, *features);
 	netdev_features_xor(diff2, dev->features, changed);
 	qeth_check_restricted_features(card, diff1, diff2);
 
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index 5e158dbf987f..c1140efa3413 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -2220,11 +2220,12 @@ static int qlge_napi_poll_msix(struct napi_struct *napi, int budget)
 	return work_done;
 }
 
-static void qlge_vlan_mode(struct net_device *ndev, netdev_features_t features)
+static void qlge_vlan_mode(struct net_device *ndev,
+			   const netdev_features_t *features)
 {
 	struct qlge_adapter *qdev = netdev_to_qdev(ndev);
 
-	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, features)) {
+	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 {
@@ -2237,7 +2238,7 @@ static void qlge_vlan_mode(struct net_device *ndev, netdev_features_t features)
  * based on the features to enable/disable hardware vlan accel
  */
 static int qlge_update_hw_vlan_features(struct net_device *ndev,
-					netdev_features_t features)
+					const netdev_features_t *features)
 {
 	struct qlge_adapter *qdev = netdev_to_qdev(ndev);
 	bool need_restart = netif_running(ndev);
@@ -2253,7 +2254,7 @@ static int qlge_update_hw_vlan_features(struct net_device *ndev,
 	}
 
 	/* update the features with resent change */
-	ndev->features = features;
+	netdev_active_features_copy(ndev, *features);
 
 	if (need_restart) {
 		status = qlge_adapter_up(qdev);
@@ -2268,12 +2269,12 @@ static int qlge_update_hw_vlan_features(struct net_device *ndev,
 }
 
 static int qlge_set_features(struct net_device *ndev,
-			     netdev_features_t features)
+			     const netdev_features_t *features)
 {
 	netdev_features_t changed;
 	int err;
 
-	netdev_features_xor(changed, ndev->features, features);
+	netdev_features_xor(changed, ndev->features, *features);
 	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);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 63e97effa858..d9e64b45298c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1517,7 +1517,7 @@ struct net_device_ops {
 	void			(*ndo_fix_features)(struct net_device *dev,
 						    netdev_features_t *features);
 	int			(*ndo_set_features)(struct net_device *dev,
-						    netdev_features_t features);
+						    const netdev_features_t *features);
 	int			(*ndo_neigh_construct)(struct net_device *dev,
 						       struct neighbour *n);
 	void			(*ndo_neigh_destroy)(struct net_device *dev,
diff --git a/net/core/dev.c b/net/core/dev.c
index 0d5df1d4f712..e27a8322289b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9732,7 +9732,7 @@ int __netdev_update_features(struct net_device *dev)
 		&dev->features, &features);
 
 	if (dev->netdev_ops->ndo_set_features)
-		err = dev->netdev_ops->ndo_set_features(dev, features);
+		err = dev->netdev_ops->ndo_set_features(dev, &features);
 	else
 		err = 0;
 
-- 
2.33.0


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

* [RFCv8 PATCH net-next 44/55] net: adjust the prototype fo xxx_gso_segment() family
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (42 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 43/55] net: adjust the prototype of xxx_set_features() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 45/55] net: vlan: adjust the prototype of vlan functions Jian Shen
                   ` (12 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The xxx_gso_segment() functions using netdev_features_t as
parameters. For the prototype of netdev_features_t will
be extended to be larger than 8 bytes, so change the prototype
of the function, change the prototype of input features to
'netdev_features_t *'.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/broadcom/tg3.c           |  2 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  2 +-
 drivers/net/ethernet/sfc/siena/tx_common.c    |  2 +-
 drivers/net/ethernet/sfc/tx_common.c          |  2 +-
 drivers/net/ethernet/sun/sunvnet_common.c     |  2 +-
 drivers/net/tap.c                             |  2 +-
 drivers/net/usb/r8152.c                       |  2 +-
 drivers/net/wireguard/device.c                |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c   | 10 +++----
 include/linux/netdevice.h                     | 11 ++++----
 include/linux/skbuff.h                        |  6 +++--
 include/net/inet_common.h                     |  2 +-
 include/net/tcp.h                             |  2 +-
 include/net/udp.h                             |  6 ++---
 lib/test_bpf.c                                |  2 +-
 net/core/dev.c                                |  9 ++++---
 net/core/gro.c                                |  5 ++--
 net/core/skbuff.c                             | 12 +++++----
 net/ipv4/af_inet.c                            |  9 ++++---
 net/ipv4/esp4_offload.c                       | 23 ++++++++--------
 net/ipv4/gre_offload.c                        |  6 +++--
 net/ipv4/ip_output.c                          |  2 +-
 net/ipv4/tcp_offload.c                        |  8 +++---
 net/ipv4/udp_offload.c                        | 27 +++++++++++--------
 net/ipv6/esp6_offload.c                       | 23 ++++++++--------
 net/ipv6/ip6_offload.c                        | 12 +++++----
 net/ipv6/ip6_output.c                         |  2 +-
 net/ipv6/tcpv6_offload.c                      |  2 +-
 net/ipv6/udp_offload.c                        | 11 +++++---
 net/mac80211/tx.c                             |  2 +-
 net/mpls/mpls_gso.c                           |  6 ++---
 net/netfilter/nfnetlink_queue.c               |  2 +-
 net/nsh/nsh.c                                 |  6 ++---
 net/openvswitch/datapath.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                           |  2 +-
 net/sctp/offload.c                            | 10 +++----
 net/xfrm/xfrm_device.c                        |  2 +-
 net/xfrm/xfrm_output.c                        |  2 +-
 41 files changed, 137 insertions(+), 109 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index e4fa6f2fdc72..409e99c5de5c 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -7880,7 +7880,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
 
 	netdev_features_andnot(features, tp->dev->features,
 			       netdev_general_tso_features);
-	segs = skb_gso_segment(skb, features);
+	segs = skb_gso_segment(skb, &features);
 	if (IS_ERR(segs) || !segs)
 		goto tg3_tso_bug_end;
 
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 301edf3f6cc1..08b6dc477810 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -2898,7 +2898,7 @@ static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
 	netdev_tx_t status;
 
 	netdev_feature_del(NETIF_F_TSO6_BIT, features);
-	segs = skb_gso_segment(skb, features);
+	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 58d87add9a46..08be81fc3779 100644
--- a/drivers/net/ethernet/sfc/siena/tx_common.c
+++ b/drivers/net/ethernet/sfc/siena/tx_common.c
@@ -435,7 +435,7 @@ int efx_siena_tx_tso_fallback(struct efx_tx_queue *tx_queue,
 	netdev_features_t feats;
 
 	netdev_features_zero(feats);
-	segments = skb_gso_segment(skb, feats);
+	segments = skb_gso_segment(skb, &feats);
 	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 14fa2c65fc25..db9ceb5026bd 100644
--- a/drivers/net/ethernet/sfc/tx_common.c
+++ b/drivers/net/ethernet/sfc/tx_common.c
@@ -452,7 +452,7 @@ int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
 	netdev_features_t feats;
 
 	netdev_features_zero(feats);
-	segments = skb_gso_segment(skb, feats);
+	segments = skb_gso_segment(skb, &feats);
 	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 9bdbaf691201..b0239b704e79 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.c
+++ b/drivers/net/ethernet/sun/sunvnet_common.c
@@ -1276,7 +1276,7 @@ vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb,
 		skb_shinfo(skb)->gso_segs = gso_segs;
 	}
 	netdev_feature_del(NETIF_F_TSO_BIT, features);
-	segs = skb_gso_segment(skb, features);
+	segs = skb_gso_segment(skb, &features);
 	if (IS_ERR(segs))
 		goto out_dropped;
 
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index ab8555799574..dfbfd8dfcf67 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -342,7 +342,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
 	if (q->flags & IFF_VNET_HDR)
 		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 *segs = __skb_gso_segment(skb, &features, false);
 		struct sk_buff *next;
 
 		if (IS_ERR(segs)) {
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 5b4f73b7c023..d2936ac84774 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2113,7 +2113,7 @@ static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb,
 		netdev_features_clear_set(features, NETIF_F_SG_BIT,
 					  NETIF_F_IPV6_CSUM_BIT,
 					  NETIF_F_TSO6_BIT);
-		segs = skb_gso_segment(skb, features);
+		segs = skb_gso_segment(skb, &features);
 		if (IS_ERR(segs) || !segs)
 			goto drop;
 
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index 6930f0882b0d..04145af755c9 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -180,7 +180,7 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev)
 		struct sk_buff *segs;
 
 		netdev_features_zero(feats);
-		segs = skb_gso_segment(skb, feats);
+		segs = skb_gso_segment(skb, &feats);
 		if (IS_ERR(segs)) {
 			ret = PTR_ERR(segs);
 			goto err_peer;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index bdb6a599aa9f..4ed95b179b45 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -814,7 +814,7 @@ unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
 
 static int
 iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
-		       netdev_features_t netdev_flags,
+		       const netdev_features_t *netdev_flags,
 		       struct sk_buff_head *mpdus_skb)
 {
 	struct sk_buff *tmp, *next;
@@ -900,7 +900,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
 	if (!mvmsta->max_amsdu_len ||
 	    !ieee80211_is_data_qos(hdr->frame_control) ||
 	    !mvmsta->amsdu_enabled)
-		return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb);
+		return iwl_mvm_tx_tso_segment(skb, 1, &netdev_flags, mpdus_skb);
 
 	/*
 	 * Do not build AMSDU for IPv6 with extension headers.
@@ -910,7 +910,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
 	    ((struct ipv6hdr *)skb_network_header(skb))->nexthdr !=
 	    IPPROTO_TCP) {
 		netdev_features_clear(netdev_flags, NETIF_F_CSUM_MASK);
-		return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb);
+		return iwl_mvm_tx_tso_segment(skb, 1, &netdev_flags, mpdus_skb);
 	}
 
 	tid = ieee80211_get_tid(hdr);
@@ -924,7 +924,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
 	if ((info->flags & IEEE80211_TX_CTL_AMPDU &&
 	     !mvmsta->tid_data[tid].amsdu_in_ampdu_allowed) ||
 	    !(mvmsta->amsdu_enabled & BIT(tid)))
-		return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb);
+		return iwl_mvm_tx_tso_segment(skb, 1, &netdev_flags, mpdus_skb);
 
 	/*
 	 * Take the min of ieee80211 station and mvm station
@@ -982,7 +982,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
 	 * Trick the segmentation function to make it
 	 * create SKBs that can fit into one A-MSDU.
 	 */
-	return iwl_mvm_tx_tso_segment(skb, num_subframes, netdev_flags,
+	return iwl_mvm_tx_tso_segment(skb, num_subframes, &netdev_flags,
 				      mpdus_skb);
 }
 #else /* CONFIG_INET */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d9e64b45298c..fb1f85274e3b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2659,7 +2659,7 @@ struct packet_type {
 
 struct offload_callbacks {
 	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
-						netdev_features_t features);
+						const netdev_features_t *features);
 	struct sk_buff		*(*gro_receive)(struct list_head *head,
 						struct sk_buff *skb);
 	int			(*gro_complete)(struct sk_buff *skb, int nhoff);
@@ -4773,11 +4773,11 @@ int skb_csum_hwoffload_help(struct sk_buff *skb,
 			    const netdev_features_t *features);
 
 struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
-				  netdev_features_t features, bool tx_path);
+				  const netdev_features_t *features, bool tx_path);
 struct sk_buff *skb_eth_gso_segment(struct sk_buff *skb,
-				    netdev_features_t features, __be16 type);
+				    const netdev_features_t *features, __be16 type);
 struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
-				    netdev_features_t features);
+				    const netdev_features_t *features);
 
 struct netdev_bonding_info {
 	ifslave	slave;
@@ -4802,7 +4802,8 @@ static inline void ethtool_notify(struct net_device *dev, unsigned int cmd,
 #endif
 
 static inline
-struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features)
+struct sk_buff *skb_gso_segment(struct sk_buff *skb,
+				const netdev_features_t *features)
 {
 	return __skb_gso_segment(skb, features, true);
 }
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 8b030517f4d3..2f163b12c54d 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3960,8 +3960,10 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
 void skb_scrub_packet(struct sk_buff *skb, bool xnet);
 bool skb_gso_validate_network_len(const struct sk_buff *skb, unsigned int mtu);
 bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len);
-struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features);
-struct sk_buff *skb_segment_list(struct sk_buff *skb, netdev_features_t features,
+struct sk_buff *skb_segment(struct sk_buff *skb,
+			    const netdev_features_t *features);
+struct sk_buff *skb_segment_list(struct sk_buff *skb,
+				 const netdev_features_t *features,
 				 unsigned int offset);
 struct sk_buff *skb_vlan_untag(struct sk_buff *skb);
 int skb_ensure_writable(struct sk_buff *skb, unsigned int write_len);
diff --git a/include/net/inet_common.h b/include/net/inet_common.h
index cec453c18f1d..013f52029899 100644
--- a/include/net/inet_common.h
+++ b/include/net/inet_common.h
@@ -63,7 +63,7 @@ int inet_recv_error(struct sock *sk, struct msghdr *msg, int len,
 struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb);
 int inet_gro_complete(struct sk_buff *skb, int nhoff);
 struct sk_buff *inet_gso_segment(struct sk_buff *skb,
-				 netdev_features_t features);
+				 const netdev_features_t *features);
 
 static inline void inet_ctl_sock_destroy(struct sock *sk)
 {
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 735e957f7f4b..cfcffe0e3109 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -2024,7 +2024,7 @@ extern struct request_sock_ops tcp6_request_sock_ops;
 void tcp_v4_destroy_sock(struct sock *sk);
 
 struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
-				netdev_features_t features);
+				const netdev_features_t *features);
 struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb);
 INDIRECT_CALLABLE_DECLARE(int tcp4_gro_complete(struct sk_buff *skb, int thoff));
 INDIRECT_CALLABLE_DECLARE(struct sk_buff *tcp4_gro_receive(struct list_head *head, struct sk_buff *skb));
diff --git a/include/net/udp.h b/include/net/udp.h
index ecdf76e4318f..30f8dc9f852f 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -172,7 +172,7 @@ void udp_v6_early_demux(struct sk_buff *skb);
 INDIRECT_CALLABLE_DECLARE(int udpv6_rcv(struct sk_buff *));
 
 struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
-				  netdev_features_t features, bool is_ipv6);
+				  const netdev_features_t *features, bool is_ipv6);
 
 /* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
 static inline int udp_lib_hash(struct sock *sk)
@@ -281,7 +281,7 @@ int __udp_disconnect(struct sock *sk, int flags);
 int udp_disconnect(struct sock *sk, int flags);
 __poll_t udp_poll(struct file *file, struct socket *sock, poll_table *wait);
 struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
-				       netdev_features_t features,
+				       const netdev_features_t *features,
 				       bool is_ipv6);
 int udp_lib_getsockopt(struct sock *sk, int level, int optname,
 		       char __user *optval, int __user *optlen);
@@ -483,7 +483,7 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk,
 	/* the GSO CB lays after the UDP one, no need to save and restore any
 	 * CB fragment
 	 */
-	segs = __skb_gso_segment(skb, features, false);
+	segs = __skb_gso_segment(skb, &features, false);
 	if (IS_ERR_OR_NULL(segs)) {
 		int segs_nr = skb_shinfo(skb)->gso_segs;
 
diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 84073b768558..f9bfc52a6f81 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -14769,7 +14769,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;
diff --git a/net/core/dev.c b/net/core/dev.c
index e27a8322289b..ad6202d2543e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3376,8 +3376,9 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path)
  *	Segmentation preserves SKB_GSO_CB_OFFSET bytes of previous skb cb.
  */
 struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
-				  netdev_features_t features, bool tx_path)
+				  const netdev_features_t *feats, bool tx_path)
 {
+	netdev_features_t features;
 	struct sk_buff *segs;
 
 	if (unlikely(skb_needs_check(skb, tx_path))) {
@@ -3389,6 +3390,8 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
 			return ERR_PTR(err);
 	}
 
+	netdev_features_copy(features, *feats);
+
 	/* Only report GSO partial support if it will enable us to
 	 * support segmentation on this frame without needing additional
 	 * work.
@@ -3414,7 +3417,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
 	skb_reset_mac_header(skb);
 	skb_reset_mac_len(skb);
 
-	segs = skb_mac_gso_segment(skb, features);
+	segs = skb_mac_gso_segment(skb, &features);
 
 	if (segs != skb && unlikely(skb_needs_check(skb, tx_path) && !IS_ERR(segs)))
 		skb_warn_bad_offload(skb);
@@ -3665,7 +3668,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
 	if (netif_needs_gso(skb, features)) {
 		struct sk_buff *segs;
 
-		segs = skb_gso_segment(skb, features);
+		segs = skb_gso_segment(skb, &features);
 		if (IS_ERR(segs)) {
 			goto out_kfree_skb;
 		} else if (segs) {
diff --git a/net/core/gro.c b/net/core/gro.c
index b4190eb08467..28131d091a3f 100644
--- a/net/core/gro.c
+++ b/net/core/gro.c
@@ -99,7 +99,8 @@ EXPORT_SYMBOL(dev_remove_offload);
  *	@type: Ethernet Protocol ID
  */
 struct sk_buff *skb_eth_gso_segment(struct sk_buff *skb,
-				    netdev_features_t features, __be16 type)
+				    const netdev_features_t *features,
+				    __be16 type)
 {
 	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
 	struct packet_offload *ptype;
@@ -123,7 +124,7 @@ EXPORT_SYMBOL(skb_eth_gso_segment);
  *	@features: features for the output path (see dev->features)
  */
 struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
-				    netdev_features_t features)
+				    const netdev_features_t *features)
 {
 	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
 	struct packet_offload *ptype;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 0e40de13de3f..b5916c98128b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3915,7 +3915,7 @@ static inline skb_frag_t skb_head_frag_to_page_desc(struct sk_buff *frag_skb)
 }
 
 struct sk_buff *skb_segment_list(struct sk_buff *skb,
-				 netdev_features_t features,
+				 const netdev_features_t *features,
 				 unsigned int offset)
 {
 	struct sk_buff *list_skb = skb_shinfo(skb)->frag_list;
@@ -3973,7 +3973,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
 						 nskb->data - tnl_hlen,
 						 offset + tnl_hlen);
 
-		if (skb_needs_linearize(nskb, features) &&
+		if (skb_needs_linearize(nskb, *features) &&
 		    __skb_linearize(nskb))
 			goto err_linearize;
 
@@ -3987,7 +3987,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
 
 	skb->prev = tail;
 
-	if (skb_needs_linearize(skb, features) &&
+	if (skb_needs_linearize(skb, *features) &&
 	    __skb_linearize(skb))
 		goto err_linearize;
 
@@ -4005,14 +4005,14 @@ EXPORT_SYMBOL_GPL(skb_segment_list);
 /**
  *	skb_segment - Perform protocol segmentation on skb.
  *	@head_skb: buffer to segment
- *	@features: features for the output path (see dev->features)
+ *	@feats: features for the output path (see dev->features)
  *
  *	This function performs segmentation on the given skb.  It returns
  *	a pointer to the first in a list of new skbs for the segments.
  *	In case of error it returns ERR_PTR(err).
  */
 struct sk_buff *skb_segment(struct sk_buff *head_skb,
-			    netdev_features_t features)
+			    const netdev_features_t *feats)
 {
 	struct sk_buff *segs = NULL;
 	struct sk_buff *tail = NULL;
@@ -4029,10 +4029,12 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
 	__be16 proto;
 	bool csum, sg;
 	int nfrags = skb_shinfo(head_skb)->nr_frags;
+	netdev_features_t features;
 	int err = -ENOMEM;
 	int i = 0;
 	int pos;
 
+	netdev_features_copy(features, *feats);
 	if (list_skb && !list_skb->head_frag && skb_headlen(list_skb) &&
 	    (skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY)) {
 		/* gso_size is untrusted, and we have a frag_list with a linear
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 67f71417032a..ec9d50586204 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1343,11 +1343,12 @@ void inet_sk_state_store(struct sock *sk, int newstate)
 }
 
 struct sk_buff *inet_gso_segment(struct sk_buff *skb,
-				 netdev_features_t features)
+				 const netdev_features_t *feats)
 {
 	bool udpfrag = false, fixedid = false, gso_partial, encap;
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	const struct net_offload *ops;
+	netdev_features_t features;
 	unsigned int offset = 0;
 	struct iphdr *iph;
 	int proto, tot_len;
@@ -1373,6 +1374,8 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 		goto out;
 	__skb_pull(skb, ihl);
 
+	netdev_features_copy(features, *feats);
+
 	encap = SKB_GSO_CB(skb)->encap_level > 0;
 	if (encap)
 		netdev_features_mask(features, skb->dev->hw_enc_features);
@@ -1393,7 +1396,7 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 
 	ops = rcu_dereference(inet_offloads[proto]);
 	if (likely(ops && ops->callbacks.gso_segment)) {
-		segs = ops->callbacks.gso_segment(skb, features);
+		segs = ops->callbacks.gso_segment(skb, &features);
 		if (!segs)
 			skb->network_header = skb_mac_header(skb) + nhoff - skb->head;
 	}
@@ -1442,7 +1445,7 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 }
 
 static struct sk_buff *ipip_gso_segment(struct sk_buff *skb,
-					netdev_features_t features)
+					const netdev_features_t *features)
 {
 	if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP4))
 		return ERR_PTR(-EINVAL);
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index b3d5cc34e3ec..36d76cff3075 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -108,14 +108,14 @@ static void esp4_gso_encap(struct xfrm_state *x, struct sk_buff *skb)
 
 static struct sk_buff *xfrm4_tunnel_gso_segment(struct xfrm_state *x,
 						struct sk_buff *skb,
-						netdev_features_t features)
+						const netdev_features_t *features)
 {
 	return skb_eth_gso_segment(skb, features, htons(ETH_P_IP));
 }
 
 static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
 						   struct sk_buff *skb,
-						   netdev_features_t features)
+						   const netdev_features_t *features)
 {
 	const struct net_offload *ops;
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
@@ -131,7 +131,7 @@ static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
 
 static struct sk_buff *xfrm4_beet_gso_segment(struct xfrm_state *x,
 					      struct sk_buff *skb,
-					      netdev_features_t features)
+					      const netdev_features_t *features)
 {
 	struct xfrm_offload *xo = xfrm_offload(skb);
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
@@ -172,7 +172,7 @@ static struct sk_buff *xfrm4_beet_gso_segment(struct xfrm_state *x,
 
 static struct sk_buff *xfrm4_outer_mode_gso_segment(struct xfrm_state *x,
 						    struct sk_buff *skb,
-						    netdev_features_t features)
+						    const netdev_features_t *features)
 {
 	switch (x->outer_mode.encap) {
 	case XFRM_MODE_TUNNEL:
@@ -187,12 +187,12 @@ static struct sk_buff *xfrm4_outer_mode_gso_segment(struct xfrm_state *x,
 }
 
 static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
-				        netdev_features_t features)
+					const netdev_features_t *features)
 {
 	struct xfrm_state *x;
 	struct ip_esp_hdr *esph;
 	struct crypto_aead *aead;
-	netdev_features_t esp_features = features;
+	netdev_features_t esp_features;
 	struct xfrm_offload *xo = xfrm_offload(skb);
 	struct sec_path *sp;
 
@@ -217,22 +217,23 @@ static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
 
 	skb->encap_hdr_csum = 1;
 
+	netdev_features_copy(esp_features, *features);
 	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) {
-		netdev_features_andnot(esp_features, features,
+	     !netdev_feature_test(NETIF_F_HW_ESP_BIT, *features)) || x->xso.dev != skb->dev) {
+		netdev_features_andnot(esp_features, *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 (!netdev_feature_test(NETIF_F_HW_ESP_TX_CSUM_BIT, features) &&
+	} 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)) {
-		netdev_features_andnot(esp_features, features,
+		netdev_features_andnot(esp_features, *features,
 				       NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, esp_features);
 	}
 
 	xo->flags |= XFRM_GSO_SEGMENT;
 
-	return xfrm4_outer_mode_gso_segment(x, skb, esp_features);
+	return xfrm4_outer_mode_gso_segment(x, skb, &esp_features);
 }
 
 static int esp_input_tail(struct xfrm_state *x, struct sk_buff *skb)
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 2434e7099190..5a39a390ed55 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -13,7 +13,7 @@
 #include <net/gro.h>
 
 static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
-				       netdev_features_t features)
+				       const netdev_features_t *feats)
 {
 	int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
 	bool need_csum, offload_csum, gso_partial, need_ipsec;
@@ -22,6 +22,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 	__be16 protocol = skb->protocol;
 	u16 mac_len = skb->mac_len;
 	int gre_offset, outer_hlen;
+	netdev_features_t features;
 
 	if (!skb->encapsulation)
 		goto out;
@@ -44,6 +45,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;
 
+	netdev_features_copy(features, *feats);
 	netdev_features_mask(features, skb->dev->hw_enc_features);
 	if (need_csum)
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, features);
@@ -54,7 +56,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 			  netdev_active_feature_test(skb->dev, NETIF_F_HW_CSUM_BIT));
 
 	/* segment inner packet. */
-	segs = skb_mac_gso_segment(skb, features);
+	segs = skb_mac_gso_segment(skb, &features);
 	if (IS_ERR_OR_NULL(segs)) {
 		skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset,
 				     mac_len);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 8e9993eae1a4..20371a2abd17 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -265,7 +265,7 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk,
 	netif_skb_features(skb, &features);
 	BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_GSO_CB_OFFSET);
 	netdev_features_clear(features, NETIF_F_GSO_MASK);
-	segs = skb_gso_segment(skb, features);
+	segs = skb_gso_segment(skb, &features);
 	if (IS_ERR_OR_NULL(segs)) {
 		kfree_skb(skb);
 		return -ENOMEM;
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index e5d161cb0810..930dfb9557ed 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -28,7 +28,7 @@ static void tcp_gso_tstamp(struct sk_buff *skb, unsigned int ts_seq,
 }
 
 static struct sk_buff *tcp4_gso_segment(struct sk_buff *skb,
-					netdev_features_t features)
+					const netdev_features_t *features)
 {
 	if (!(skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4))
 		return ERR_PTR(-EINVAL);
@@ -53,7 +53,7 @@ static struct sk_buff *tcp4_gso_segment(struct sk_buff *skb,
 }
 
 struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
-				netdev_features_t features)
+				const netdev_features_t *feats)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int sum_truesize = 0;
@@ -66,6 +66,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
 	struct sk_buff *gso_skb = skb;
 	__sum16 newcheck;
 	bool ooo_okay, copy_destructor;
+	netdev_features_t features;
 
 	th = tcp_hdr(skb);
 	thlen = th->doff * 4;
@@ -82,6 +83,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
 	if (unlikely(skb->len <= mss))
 		goto out;
 
+	netdev_features_copy(features, *feats);
 	netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, features);
 	if (skb_gso_ok(skb, features)) {
 		/* Packet is from an untrusted source, reset gso_segs. */
@@ -97,7 +99,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
 	/* All segments but the first should have ooo_okay cleared */
 	skb->ooo_okay = 0;
 
-	segs = skb_segment(skb, features);
+	segs = skb_segment(skb, &features);
 	if (IS_ERR(segs))
 		goto out;
 
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 107a80518f61..91be6ed356f3 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -13,9 +13,9 @@
 #include <net/inet_common.h>
 
 static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
-	netdev_features_t features,
+	const netdev_features_t *feats,
 	struct sk_buff *(*gso_inner_segment)(struct sk_buff *skb,
-					     netdev_features_t features),
+					     const netdev_features_t *features),
 	__be16 new_protocol, bool is_ipv6)
 {
 	int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
@@ -26,6 +26,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 	__be16 protocol = skb->protocol;
 	u16 mac_len = skb->mac_len;
 	int udp_offset, outer_hlen;
+	netdev_features_t features;
 	__wsum partial;
 	bool need_ipsec;
 
@@ -68,6 +69,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))));
 
+	netdev_features_copy(features, *feats);
 	netdev_features_mask(features, skb->dev->hw_enc_features);
 	if (need_csum)
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, features);
@@ -83,7 +85,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 	}
 
 	/* segment inner packet. */
-	segs = gso_inner_segment(skb, features);
+	segs = gso_inner_segment(skb, &features);
 	if (IS_ERR_OR_NULL(segs)) {
 		skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset,
 				     mac_len);
@@ -150,7 +152,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 }
 
 struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
-				       netdev_features_t features,
+				       const netdev_features_t *features,
 				       bool is_ipv6)
 {
 	const struct net_offload __rcu **offloads;
@@ -158,7 +160,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
 	const struct net_offload *ops;
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct sk_buff *(*gso_inner_segment)(struct sk_buff *skb,
-					     netdev_features_t features);
+					     const netdev_features_t *features);
 
 	rcu_read_lock();
 
@@ -247,7 +249,7 @@ static struct sk_buff *__udpv4_gso_segment_list_csum(struct sk_buff *segs)
 }
 
 static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb,
-					      netdev_features_t features,
+					      const netdev_features_t *features,
 					      bool is_ipv6)
 {
 	unsigned int mss = skb_shinfo(skb)->gso_size;
@@ -262,7 +264,7 @@ static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb,
 }
 
 struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
-				  netdev_features_t features, bool is_ipv6)
+				  const netdev_features_t *features, bool is_ipv6)
 {
 	struct sock *sk = gso_skb->sk;
 	unsigned int sum_truesize = 0;
@@ -366,18 +368,21 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
 EXPORT_SYMBOL_GPL(__udp_gso_segment);
 
 static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
-					 netdev_features_t features)
+					 const netdev_features_t *feats)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	netdev_features_t features;
 	unsigned int mss;
 	__wsum csum;
 	struct udphdr *uh;
 	struct iphdr *iph;
 
+	netdev_features_copy(features, *feats);
+
 	if (skb->encapsulation &&
 	    (skb_shinfo(skb)->gso_type &
 	     (SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM))) {
-		segs = skb_udp_tunnel_segment(skb, features, false);
+		segs = skb_udp_tunnel_segment(skb, &features, false);
 		goto out;
 	}
 
@@ -388,7 +393,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 		goto out;
 
 	if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
-		return __udp_gso_segment(skb, features, false);
+		return __udp_gso_segment(skb, &features, false);
 
 	mss = skb_shinfo(skb)->gso_size;
 	if (unlikely(skb->len <= mss))
@@ -420,7 +425,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 	/* Fragment the skb. IP headers of the fragments are updated in
 	 * inet_gso_segment()
 	 */
-	segs = skb_segment(skb, features);
+	segs = skb_segment(skb, &features);
 out:
 	return segs;
 }
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 5d8642b40a66..4956a83d409a 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -143,14 +143,14 @@ static void esp6_gso_encap(struct xfrm_state *x, struct sk_buff *skb)
 
 static struct sk_buff *xfrm6_tunnel_gso_segment(struct xfrm_state *x,
 						struct sk_buff *skb,
-						netdev_features_t features)
+						const netdev_features_t *features)
 {
 	return skb_eth_gso_segment(skb, features, htons(ETH_P_IPV6));
 }
 
 static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x,
 						   struct sk_buff *skb,
-						   netdev_features_t features)
+						   const netdev_features_t *features)
 {
 	const struct net_offload *ops;
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
@@ -166,7 +166,7 @@ static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x,
 
 static struct sk_buff *xfrm6_beet_gso_segment(struct xfrm_state *x,
 					      struct sk_buff *skb,
-					      netdev_features_t features)
+					      const netdev_features_t *features)
 {
 	struct xfrm_offload *xo = xfrm_offload(skb);
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
@@ -211,7 +211,7 @@ static struct sk_buff *xfrm6_beet_gso_segment(struct xfrm_state *x,
 
 static struct sk_buff *xfrm6_outer_mode_gso_segment(struct xfrm_state *x,
 						    struct sk_buff *skb,
-						    netdev_features_t features)
+						    const netdev_features_t *features)
 {
 	switch (x->outer_mode.encap) {
 	case XFRM_MODE_TUNNEL:
@@ -226,12 +226,12 @@ static struct sk_buff *xfrm6_outer_mode_gso_segment(struct xfrm_state *x,
 }
 
 static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
-				        netdev_features_t features)
+					const netdev_features_t *features)
 {
 	struct xfrm_state *x;
 	struct ip_esp_hdr *esph;
 	struct crypto_aead *aead;
-	netdev_features_t esp_features = features;
+	netdev_features_t esp_features;
 	struct xfrm_offload *xo = xfrm_offload(skb);
 	struct sec_path *sp;
 
@@ -256,20 +256,21 @@ static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
 
 	skb->encap_hdr_csum = 1;
 
-	if (!netdev_feature_test(NETIF_F_HW_ESP_BIT, features) || x->xso.dev != skb->dev) {
-		netdev_features_andnot(esp_features, features,
+	netdev_features_copy(esp_features, *features);
+	if (!netdev_feature_test(NETIF_F_HW_ESP_BIT, *features) || x->xso.dev != skb->dev) {
+		netdev_features_andnot(esp_features, *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 (!netdev_feature_test(NETIF_F_HW_ESP_TX_CSUM_BIT, features)) {
-		netdev_features_andnot(esp_features, features,
+	} else if (!netdev_feature_test(NETIF_F_HW_ESP_TX_CSUM_BIT, *features)) {
+		netdev_features_andnot(esp_features, *features,
 				       NETIF_F_CSUM_MASK);
 		netdev_feature_del(NETIF_F_SCTP_CRC_BIT, esp_features);
 	}
 
 	xo->flags |= XFRM_GSO_SEGMENT;
 
-	return xfrm6_outer_mode_gso_segment(x, skb, esp_features);
+	return xfrm6_outer_mode_gso_segment(x, skb, &esp_features);
 }
 
 static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb)
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index db7737bac5c3..4206aed0bb6c 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -72,11 +72,12 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
 }
 
 static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
-	netdev_features_t features)
+					const netdev_features_t *feats)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct ipv6hdr *ipv6h;
 	const struct net_offload *ops;
+	netdev_features_t features;
 	int proto, nexthdr;
 	struct frag_hdr *fptr;
 	unsigned int payload_len;
@@ -113,6 +114,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
 		goto out;
 
+	netdev_features_copy(features, *feats);
 	encap = SKB_GSO_CB(skb)->encap_level > 0;
 	if (encap)
 		netdev_features_mask(features, skb->dev->hw_enc_features);
@@ -135,7 +137,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 	ops = rcu_dereference(inet6_offloads[proto]);
 	if (likely(ops && ops->callbacks.gso_segment)) {
 		skb_reset_transport_header(skb);
-		segs = ops->callbacks.gso_segment(skb, features);
+		segs = ops->callbacks.gso_segment(skb, &features);
 		if (!segs)
 			skb->network_header = skb_mac_header(skb) + nhoff - skb->head;
 	}
@@ -419,7 +421,7 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
 };
 
 static struct sk_buff *sit_gso_segment(struct sk_buff *skb,
-				       netdev_features_t features)
+				       const netdev_features_t *features)
 {
 	if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP4))
 		return ERR_PTR(-EINVAL);
@@ -428,7 +430,7 @@ static struct sk_buff *sit_gso_segment(struct sk_buff *skb,
 }
 
 static struct sk_buff *ip4ip6_gso_segment(struct sk_buff *skb,
-					  netdev_features_t features)
+					  const netdev_features_t *features)
 {
 	if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP6))
 		return ERR_PTR(-EINVAL);
@@ -437,7 +439,7 @@ static struct sk_buff *ip4ip6_gso_segment(struct sk_buff *skb,
 }
 
 static struct sk_buff *ip6ip6_gso_segment(struct sk_buff *skb,
-					  netdev_features_t features)
+					  const netdev_features_t *features)
 {
 	if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP6))
 		return ERR_PTR(-EINVAL);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 0ac686957ab7..0343f9575d4c 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -150,7 +150,7 @@ ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk,
 	 */
 	netif_skb_features(skb, &features);
 	netdev_features_clear(features, NETIF_F_GSO_MASK);
-	segs = skb_gso_segment(skb, features);
+	segs = skb_gso_segment(skb, &features);
 	if (IS_ERR_OR_NULL(segs)) {
 		kfree_skb(skb);
 		return -ENOMEM;
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c
index 39db5a226855..a1f192fa9023 100644
--- a/net/ipv6/tcpv6_offload.c
+++ b/net/ipv6/tcpv6_offload.c
@@ -40,7 +40,7 @@ INDIRECT_CALLABLE_SCOPE int tcp6_gro_complete(struct sk_buff *skb, int thoff)
 }
 
 static struct sk_buff *tcp6_gso_segment(struct sk_buff *skb,
-					netdev_features_t features)
+					const netdev_features_t *features)
 {
 	struct tcphdr *th;
 
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 77a0c17b1894..4ea3149a8b9d 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -16,7 +16,7 @@
 #include <net/gro.h>
 
 static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
-					 netdev_features_t features)
+					 const netdev_features_t *feats)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int mss;
@@ -25,13 +25,16 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
 	u8 *packet_start, *prevhdr;
 	u8 nexthdr;
 	u8 frag_hdr_sz = sizeof(struct frag_hdr);
+	netdev_features_t features;
 	__wsum csum;
 	int tnl_hlen;
 	int err;
 
+	netdev_features_copy(features, *feats);
+
 	if (skb->encapsulation && skb_shinfo(skb)->gso_type &
 	    (SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM))
-		segs = skb_udp_tunnel_segment(skb, features, true);
+		segs = skb_udp_tunnel_segment(skb, &features, true);
 	else {
 		const struct ipv6hdr *ipv6h;
 		struct udphdr *uh;
@@ -43,7 +46,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
 			goto out;
 
 		if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
-			return __udp_gso_segment(skb, features, true);
+			return __udp_gso_segment(skb, &features, true);
 
 		mss = skb_shinfo(skb)->gso_size;
 		if (unlikely(skb->len <= mss))
@@ -105,7 +108,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
 		/* Fragment the skb. ipv6 header and the remaining fields of the
 		 * fragment header are updated in ipv6_gso_segment()
 		 */
-		segs = skb_segment(skb, features);
+		segs = skb_segment(skb, &features);
 	}
 
 out:
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 28ab258da6af..776e422e3a5a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4207,7 +4207,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 		struct sk_buff *segs;
 
 		netdev_features_zero(feats);
-		segs = skb_gso_segment(skb, feats);
+		segs = skb_gso_segment(skb, &feats);
 		if (IS_ERR(segs)) {
 			goto out_free;
 		} else if (segs) {
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c
index 4cf6a6c2eaaa..34fd4efdf4cb 100644
--- a/net/mpls/mpls_gso.c
+++ b/net/mpls/mpls_gso.c
@@ -18,7 +18,7 @@
 #include <net/mpls.h>
 
 static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
-				       netdev_features_t features)
+				       const netdev_features_t *features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	u16 mac_offset = skb->mac_header;
@@ -44,8 +44,8 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
 	skb_reset_mac_header(skb);
 
 	/* Segment inner packet. */
-	netdev_features_and(mpls_features, skb->dev->mpls_features, features);
-	segs = skb_mac_gso_segment(skb, mpls_features);
+	netdev_features_and(mpls_features, skb->dev->mpls_features, *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,
 				     mac_len);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 32644cc2b153..d3401fdb4b71 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -815,7 +815,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
 
 	nf_bridge_adjust_skb_data(skb);
 	netdev_features_zero(feats);
-	segs = skb_gso_segment(skb, feats);
+	segs = skb_gso_segment(skb, &feats);
 	/* 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 cc38680a2982..6d06e079ef3a 100644
--- a/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -75,7 +75,7 @@ int nsh_pop(struct sk_buff *skb)
 EXPORT_SYMBOL_GPL(nsh_pop);
 
 static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
-				       netdev_features_t features)
+				       const netdev_features_t *features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int nsh_len, mac_len;
@@ -107,9 +107,9 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
 	skb->protocol = proto;
 
 	netdev_features_zero(feats);
-	if (netdev_feature_test(NETIF_F_SG_BIT, features))
+	if (netdev_feature_test(NETIF_F_SG_BIT, *features))
 		netdev_feature_add(NETIF_F_SG_BIT, feats);
-	segs = skb_mac_gso_segment(skb, feats);
+	segs = skb_mac_gso_segment(skb, &feats);
 	if (IS_ERR_OR_NULL(segs)) {
 		skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len,
 				     skb->network_header - nhoff,
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 8885188e8e19..d516fadb02de 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -335,7 +335,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
 	BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_GSO_CB_OFFSET);
 	netdev_features_zero(features);
 	netdev_feature_add(NETIF_F_SG_BIT, features);
-	segs = __skb_gso_segment(skb, features, false);
+	segs = __skb_gso_segment(skb, &features, false);
 	if (IS_ERR(segs))
 		return PTR_ERR(segs);
 	if (segs == NULL)
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index 837efd4c786f..be310b947270 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -1745,7 +1745,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 
 		netif_skb_features(skb, &features);
 		netdev_features_clear(features, NETIF_F_GSO_MASK);
-		segs = skb_gso_segment(skb, features);
+		segs = skb_gso_segment(skb, &features);
 		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 cb253eb3a936..6ee054f00a74 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -417,7 +417,7 @@ static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch,
 
 	netif_skb_features(skb, &features);
 	netdev_features_clear(features, NETIF_F_GSO_MASK);
-	segs = skb_gso_segment(skb, features);
+	segs = skb_gso_segment(skb, &features);
 
 	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 96bff2fdeecb..b86c2eb285cb 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -465,7 +465,7 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 
 		netif_skb_features(skb, &features);
 		netdev_features_clear(features, NETIF_F_GSO_MASK);
-		segs = skb_gso_segment(skb, features);
+		segs = skb_gso_segment(skb, &features);
 		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 ce0bb68b02f3..12dd6e270632 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -213,7 +213,7 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
 
 	netif_skb_features(skb, &features);
 	netdev_features_clear(features, NETIF_F_GSO_MASK);
-	segs = skb_gso_segment(skb, features);
+	segs = skb_gso_segment(skb, &features);
 
 	if (IS_ERR_OR_NULL(segs))
 		return qdisc_drop(skb, sch, to_free);
diff --git a/net/sctp/offload.c b/net/sctp/offload.c
index c3d81154771e..d4e1f70e32b8 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -36,10 +36,10 @@ static __le32 sctp_gso_make_checksum(struct sk_buff *skb)
 }
 
 static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
-					netdev_features_t features)
+					const netdev_features_t *features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
-	netdev_features_t tmp = features;
+	netdev_features_t tmp;
 	struct sctphdr *sh;
 
 	if (!skb_is_gso_sctp(skb))
@@ -70,15 +70,15 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
 		goto out;
 	}
 
-	tmp = features;
+	netdev_features_copy(tmp, *features);
 	netdev_feature_add(NETIF_F_HW_CSUM_BIT, tmp);
 	netdev_feature_del(NETIF_F_SG_BIT, tmp);
-	segs = skb_segment(skb, tmp);
+	segs = skb_segment(skb, &tmp);
 	if (IS_ERR(segs))
 		goto out;
 
 	/* All that is left is update SCTP CRC if necessary */
-	if (!netdev_feature_test(NETIF_F_SCTP_CRC_BIT, features)) {
+	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/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 0ec7a813fab3..b53f142b02de 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -144,7 +144,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 		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);
+		segs = skb_gso_segment(skb, &esp_features);
 		if (IS_ERR(segs)) {
 			kfree_skb(skb);
 			dev_core_stats_tx_dropped_inc(dev);
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 9ade97734543..bd1a1dcdc003 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -624,7 +624,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);
 	netdev_features_zero(feats);
-	segs = skb_gso_segment(skb, feats);
+	segs = skb_gso_segment(skb, &feats);
 	kfree_skb(skb);
 	if (IS_ERR(segs))
 		return PTR_ERR(segs);
-- 
2.33.0


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

* [RFCv8 PATCH net-next 45/55] net: vlan: adjust the prototype of vlan functions
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (43 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 44/55] net: adjust the prototype fo xxx_gso_segment() family Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 46/55] net: adjust the prototype of netif_needs_gso() and relative functions Jian Shen
                   ` (11 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

There are some functions of vlan driver using netdev_features_t
as parameters or return netdev_features_t directly or both.

For the prototype of netdev_features_t will be extended to be
larger than 8 bytes, so change the prototype of the function,
change the prototype of input features to 'netdev_features_t *',
and return the features pointer as output parameter.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 include/linux/if_vlan.h |  6 +++---
 net/8021q/vlan.c        |  4 ++--
 net/8021q/vlan.h        | 26 ++++++++++++--------------
 net/8021q/vlan_dev.c    |  4 ++--
 net/core/dev.c          |  4 ++--
 net/core/netpoll.c      |  2 +-
 6 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 4fef74864267..3179db99ebc2 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -316,14 +316,14 @@ static inline bool eth_type_vlan(__be16 ethertype)
 	}
 }
 
-static inline bool vlan_hw_offload_capable(netdev_features_t features,
+static inline bool vlan_hw_offload_capable(const netdev_features_t *features,
 					   __be16 proto)
 {
 	if (proto == htons(ETH_P_8021Q) &&
-	    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, features))
+	    netdev_feature_test(NETIF_F_HW_VLAN_CTAG_TX_BIT, *features))
 		return true;
 	if (proto == htons(ETH_P_8021AD) &&
-	    netdev_feature_test(NETIF_F_HW_VLAN_STAG_TX_BIT, features))
+	    netdev_feature_test(NETIF_F_HW_VLAN_STAG_TX_BIT, *features))
 		return true;
 	return false;
 }
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index aec2e74ccfd9..f366f4048e3d 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -321,7 +321,7 @@ static void vlan_transfer_features(struct net_device *dev,
 
 	netif_inherit_tso_max(vlandev, dev);
 
-	if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
+	if (vlan_hw_offload_capable(&dev->features, vlan->vlan_proto))
 		vlandev->hard_header_len = dev->hard_header_len;
 	else
 		vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
@@ -332,7 +332,7 @@ static void vlan_transfer_features(struct net_device *dev,
 
 	vlandev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
 	vlandev->priv_flags |= (vlan->real_dev->priv_flags & IFF_XMIT_DST_RELEASE);
-	vlandev->hw_enc_features = vlan_tnl_features(vlan->real_dev);
+	vlan_tnl_features(vlan->real_dev, &vlandev->hw_enc_features);
 
 	netdev_update_features(vlandev);
 }
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 2acb89660ab5..c72413f438e2 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -104,22 +104,20 @@ static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
 	return NULL;
 }
 
-static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)
+static inline void vlan_tnl_features(struct net_device *real_dev,
+				     netdev_features_t *features)
 {
-	netdev_features_t ret;
-
-	netdev_features_or(ret, NETIF_F_CSUM_MASK, NETIF_F_GSO_SOFTWARE);
-	netdev_features_set(ret, NETIF_F_GSO_ENCAP_ALL);
-	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)) {
-		netdev_features_clear(ret, NETIF_F_CSUM_MASK);
-		netdev_feature_add(NETIF_F_HW_CSUM_BIT, ret);
-		return ret;
+	netdev_features_or(*features, NETIF_F_CSUM_MASK, NETIF_F_GSO_SOFTWARE);
+	netdev_features_set(*features, NETIF_F_GSO_ENCAP_ALL);
+	netdev_features_mask(*features, real_dev->hw_enc_features);
+
+	if (netdev_features_intersects(*features, NETIF_F_GSO_ENCAP_ALL) &&
+	    netdev_features_intersects(*features, NETIF_F_CSUM_MASK)) {
+		netdev_features_clear(*features, NETIF_F_CSUM_MASK);
+		netdev_feature_add(NETIF_F_HW_CSUM_BIT, *features);
+		return;
 	}
-	netdev_features_zero(ret);
-	return ret;
+	netdev_features_zero(*features);
 }
 
 #define vlan_group_for_each_dev(grp, i, dev) \
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 2fa0b4ea260b..321adf534177 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -583,7 +583,7 @@ static int vlan_dev_init(struct net_device *dev)
 
 	netdev_vlan_features_andnot(dev, real_dev->vlan_features,
 				    NETIF_F_ALL_FCOE);
-	dev->hw_enc_features = vlan_tnl_features(real_dev);
+	vlan_tnl_features(real_dev, &dev->hw_enc_features);
 	dev->mpls_features = real_dev->mpls_features;
 
 	/* ipv6 shared card related stuff */
@@ -601,7 +601,7 @@ static int vlan_dev_init(struct net_device *dev)
 #endif
 
 	dev->needed_headroom = real_dev->needed_headroom;
-	if (vlan_hw_offload_capable(real_dev->features, vlan->vlan_proto)) {
+	if (vlan_hw_offload_capable(&real_dev->features, vlan->vlan_proto)) {
 		dev->header_ops      = &vlan_passthru_header_ops;
 		dev->hard_header_len = real_dev->hard_header_len;
 	} else {
diff --git a/net/core/dev.c b/net/core/dev.c
index ad6202d2543e..21ef38eeb38a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3622,7 +3622,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *first, struct net_device *de
 }
 
 static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb,
-					  netdev_features_t features)
+					  const netdev_features_t *features)
 {
 	if (skb_vlan_tag_present(skb) &&
 	    !vlan_hw_offload_capable(features, skb->vlan_proto))
@@ -3657,7 +3657,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
 	netdev_features_t features;
 
 	netif_skb_features(skb, &features);
-	skb = validate_xmit_vlan(skb, features);
+	skb = validate_xmit_vlan(skb, &features);
 	if (unlikely(!skb))
 		goto out_null;
 
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 94dd11aa1b83..17af85316407 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -80,7 +80,7 @@ static netdev_tx_t netpoll_start_xmit(struct sk_buff *skb,
 	netif_skb_features(skb, &features);
 
 	if (skb_vlan_tag_present(skb) &&
-	    !vlan_hw_offload_capable(features, skb->vlan_proto)) {
+	    !vlan_hw_offload_capable(&features, skb->vlan_proto)) {
 		skb = __vlan_hwaccel_push_inside(skb);
 		if (unlikely(!skb)) {
 			/* This is actually a packet drop, but we
-- 
2.33.0


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

* [RFCv8 PATCH net-next 46/55] net: adjust the prototype of netif_needs_gso() and relative functions
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (44 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 45/55] net: vlan: adjust the prototype of vlan functions Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 47/55] net: adjust the prototype of skb_needs_linearize() Jian Shen
                   ` (10 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The functions netif_needs_gso(), net_gso_ok(), and skb_gso_ok()
using netdev_features_t as parameters.

For the prototype of netdev_features_t will be extended to be
larger than 8 bytes, so change the prototype of these functions,
change the prototype of input features to 'netdev_features_t *'.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/tap.c                 |  2 +-
 drivers/net/xen-netfront.c        |  2 +-
 drivers/s390/net/qeth_core_main.c |  4 ++--
 include/linux/netdevice.h         | 11 ++++++-----
 include/net/sock.h                |  2 +-
 net/core/dev.c                    |  4 ++--
 net/core/skbuff.c                 |  2 +-
 net/ipv4/tcp_offload.c            |  2 +-
 net/sctp/offload.c                |  2 +-
 9 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index dfbfd8dfcf67..e3045a7badd8 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -341,7 +341,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
 	 */
 	if (q->flags & IFF_VNET_HDR)
 		netdev_features_set(features, tap->tap_features);
-	if (netif_needs_gso(skb, 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/xen-netfront.c b/drivers/net/xen-netfront.c
index 654f805f4522..a7887060feb3 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -777,7 +777,7 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
 	netif_skb_features(skb, &features);
 	if (unlikely(!netif_carrier_ok(dev) ||
 		     (slots > 1 && !xennet_can_sg(dev)) ||
-		     netif_needs_gso(skb, features))) {
+		     netif_needs_gso(skb, &features))) {
 		spin_unlock_irqrestore(&queue->tx_lock, flags);
 		goto drop;
 	}
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index b3ca79930c42..6695f8dda8f4 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6882,7 +6882,7 @@ void qeth_features_check(struct sk_buff *skb, struct net_device *dev,
 		netdev_features_t restricted;
 
 		netdev_features_zero(restricted);
-		if (skb_is_gso(skb) && !netif_needs_gso(skb, *features))
+		if (skb_is_gso(skb) && !netif_needs_gso(skb, features))
 			netdev_features_set(restricted, NETIF_F_ALL_TSO);
 
 		switch (vlan_get_protocol(skb)) {
@@ -6914,7 +6914,7 @@ void qeth_features_check(struct sk_buff *skb, struct net_device *dev,
 	 * additional buffer element. This reduces buffer utilization, and
 	 * hurts throughput. So compress small segments into one element.
 	 */
-	if (netif_needs_gso(skb, *features)) {
+	if (netif_needs_gso(skb, features)) {
 		/* match skb_segment(): */
 		unsigned int doffset = skb->data - skb_mac_header(skb);
 		unsigned int hsize = skb_shinfo(skb)->gso_size;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index fb1f85274e3b..f0fad437bdb7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4917,7 +4917,7 @@ void passthru_features_check(struct sk_buff *skb, struct net_device *dev,
 			     netdev_features_t *features);
 void netif_skb_features(struct sk_buff *skb, netdev_features_t *features);
 
-static inline bool net_gso_ok(netdev_features_t features, int gso_type)
+static inline bool net_gso_ok(const netdev_features_t *features, int gso_type)
 {
 #define ASSERT_GSO_TYPE(fl, feat)	\
 		static_assert((fl) == (feat) - NETIF_F_GSO_SHIFT)
@@ -4952,17 +4952,18 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 	if (new_gso_type) { /* placeholder for new gso type */
 	}
 
-	return (features & feature) == feature;
+	return (*features & feature) == feature;
 }
 
-static inline bool skb_gso_ok(struct sk_buff *skb, netdev_features_t features)
+static inline bool skb_gso_ok(struct sk_buff *skb,
+			      const netdev_features_t *features)
 {
 	return net_gso_ok(features, skb_shinfo(skb)->gso_type) &&
-	       (!skb_has_frag_list(skb) || netdev_feature_test(NETIF_F_FRAGLIST_BIT, features));
+	       (!skb_has_frag_list(skb) || netdev_feature_test(NETIF_F_FRAGLIST_BIT, *features));
 }
 
 static inline bool netif_needs_gso(struct sk_buff *skb,
-				   netdev_features_t features)
+				   const netdev_features_t *features)
 {
 	return skb_is_gso(skb) && (!skb_gso_ok(skb, features) ||
 		unlikely((skb->ip_summed != CHECKSUM_PARTIAL) &&
diff --git a/include/net/sock.h b/include/net/sock.h
index 35404aedf51c..acdef93d0657 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2237,7 +2237,7 @@ bool sk_mc_loop(struct sock *sk);
 
 static inline bool sk_can_gso(const struct sock *sk)
 {
-	return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type);
+	return net_gso_ok(&sk->sk_route_caps, sk->sk_gso_type);
 }
 
 void sk_setup_caps(struct sock *sk, struct dst_entry *dst);
diff --git a/net/core/dev.c b/net/core/dev.c
index 21ef38eeb38a..3436b640db67 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3404,7 +3404,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
 				    dev->gso_partial_features);
 		netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, partial_features);
 		netdev_features_set(partial_features, features);
-		if (!skb_gso_ok(skb, partial_features))
+		if (!skb_gso_ok(skb, &partial_features))
 			netdev_feature_del(NETIF_F_GSO_PARTIAL_BIT, features);
 	}
 
@@ -3665,7 +3665,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
 	if (unlikely(!skb))
 		goto out_null;
 
-	if (netif_needs_gso(skb, features)) {
+	if (netif_needs_gso(skb, &features)) {
 		struct sk_buff *segs;
 
 		segs = skb_gso_segment(skb, &features);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index b5916c98128b..124de0e772fc 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4068,7 +4068,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
 			unsigned int frag_len;
 
 			if (!list_skb ||
-			    !net_gso_ok(features, skb_shinfo(head_skb)->gso_type))
+			    !net_gso_ok(&features, skb_shinfo(head_skb)->gso_type))
 				goto normal;
 
 			/* If we get here then all the required
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 930dfb9557ed..b6c3c3b419a5 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -85,7 +85,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
 
 	netdev_features_copy(features, *feats);
 	netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, features);
-	if (skb_gso_ok(skb, features)) {
+	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/sctp/offload.c b/net/sctp/offload.c
index d4e1f70e32b8..413642ef1221 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -52,7 +52,7 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
 	__skb_pull(skb, sizeof(*sh));
 
 	netdev_feature_add(NETIF_F_GSO_ROBUST_BIT, tmp);
-	if (skb_gso_ok(skb, tmp)) {
+	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;
-- 
2.33.0


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

* [RFCv8 PATCH net-next 47/55] net: adjust the prototype of skb_needs_linearize()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (45 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 46/55] net: adjust the prototype of netif_needs_gso() and relative functions Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 48/55] net: adjust the prototype of validate_xmit_xfrm() and relative functions Jian Shen
                   ` (9 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function skb_needs_linearize() using netdev_features_t
as parameters.

For the prototype of netdev_features_t will be extended to
be larger than 8 bytes, so change the prototype of the
function, change the prototype of input features to
'netdev_features_t *'.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 include/linux/skbuff.h | 6 +++---
 net/core/dev.c         | 2 +-
 net/core/skbuff.c      | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 2f163b12c54d..122190c334cb 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -4035,11 +4035,11 @@ skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)
  *	2. skb is fragmented and the device does not support SG.
  */
 static inline bool skb_needs_linearize(struct sk_buff *skb,
-				       netdev_features_t features)
+				       const 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) && !(*features & NETIF_F_FRAGLIST)) ||
+		(skb_shinfo(skb)->nr_frags && !(*features & NETIF_F_SG)));
 }
 
 static inline void skb_copy_from_linear_data(const struct sk_buff *skb,
diff --git a/net/core/dev.c b/net/core/dev.c
index 3436b640db67..b8bb83a65221 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3676,7 +3676,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
 			skb = segs;
 		}
 	} else {
-		if (skb_needs_linearize(skb, features) &&
+		if (skb_needs_linearize(skb, &features) &&
 		    __skb_linearize(skb))
 			goto out_kfree_skb;
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 124de0e772fc..3e6935386637 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3973,7 +3973,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
 						 nskb->data - tnl_hlen,
 						 offset + tnl_hlen);
 
-		if (skb_needs_linearize(nskb, *features) &&
+		if (skb_needs_linearize(nskb, features) &&
 		    __skb_linearize(nskb))
 			goto err_linearize;
 
@@ -3987,7 +3987,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
 
 	skb->prev = tail;
 
-	if (skb_needs_linearize(skb, *features) &&
+	if (skb_needs_linearize(skb, features) &&
 	    __skb_linearize(skb))
 		goto err_linearize;
 
-- 
2.33.0


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

* [RFCv8 PATCH net-next 48/55] net: adjust the prototype of validate_xmit_xfrm() and relative functions
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (46 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 47/55] net: adjust the prototype of skb_needs_linearize() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 49/55] net: adjust the prototype of can_checksum_protocol() Jian Shen
                   ` (8 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The functions validate_xmit_xfrm() and xfrm_type_offload.xmit()
using netdev_features_t as parameters.

For the prototype of netdev_features_t will be extended to be
larger than 8 bytes, so change the prototype of the function,
change the prototype of input features to 'netdev_features_t *'.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 include/net/xfrm.h      | 11 ++++++++---
 net/core/dev.c          |  2 +-
 net/ipv4/esp4_offload.c |  5 +++--
 net/ipv6/esp6_offload.c |  5 +++--
 net/xfrm/xfrm_device.c  | 15 +++++++++------
 5 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 6e8fa98f786f..0646a47d8b18 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -415,7 +415,8 @@ struct xfrm_type_offload {
 	u8		proto;
 	void		(*encap)(struct xfrm_state *, struct sk_buff *pskb);
 	int		(*input_tail)(struct xfrm_state *x, struct sk_buff *skb);
-	int		(*xmit)(struct xfrm_state *, struct sk_buff *pskb, netdev_features_t features);
+	int		(*xmit)(struct xfrm_state *, struct sk_buff *pskb,
+				const netdev_features_t *features);
 };
 
 int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family);
@@ -1877,7 +1878,9 @@ void __init xfrm_dev_init(void);
 #ifdef CONFIG_XFRM_OFFLOAD
 void xfrm_dev_resume(struct sk_buff *skb);
 void xfrm_dev_backlog(struct softnet_data *sd);
-struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again);
+struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb,
+				   const netdev_features_t *features,
+				   bool *again);
 int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
 		       struct xfrm_user_offload *xuo);
 bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
@@ -1937,7 +1940,9 @@ static inline void xfrm_dev_backlog(struct softnet_data *sd)
 {
 }
 
-static inline struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again)
+static inline struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb,
+						 const netdev_features_t *features,
+						 bool *again)
 {
 	return skb;
 }
diff --git a/net/core/dev.c b/net/core/dev.c
index b8bb83a65221..54cb150d9db1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3696,7 +3696,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
 		}
 	}
 
-	skb = validate_xmit_xfrm(skb, features, again);
+	skb = validate_xmit_xfrm(skb, &features, again);
 
 	return skb;
 
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 36d76cff3075..b72ec9e3447e 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -250,7 +250,8 @@ static int esp_input_tail(struct xfrm_state *x, struct sk_buff *skb)
 	return esp_input_done2(skb, 0);
 }
 
-static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb,  netdev_features_t features)
+static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb,
+		    const netdev_features_t *features)
 {
 	int err;
 	int alen;
@@ -269,7 +270,7 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb,  netdev_features_
 	if (!xo)
 		return -EINVAL;
 
-	if ((!netdev_feature_test(NETIF_F_HW_ESP_BIT, features) &&
+	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;
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 4956a83d409a..ce7d02b5e184 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -287,7 +287,8 @@ static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb)
 	return esp6_input_done2(skb, 0);
 }
 
-static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb,  netdev_features_t features)
+static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb,
+		     const netdev_features_t *features)
 {
 	int len;
 	int err;
@@ -306,7 +307,7 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb,  netdev_features
 	if (!xo)
 		return -EINVAL;
 
-	if (!netdev_feature_test(NETIF_F_HW_ESP_BIT, features) || 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/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index b53f142b02de..3a8f11aec189 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -97,23 +97,26 @@ static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
 	}
 }
 
-struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again)
+struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb,
+				   const netdev_features_t *features,
+				   bool *again)
 {
 	int err;
 	unsigned long flags;
 	struct xfrm_state *x;
 	struct softnet_data *sd;
 	struct sk_buff *skb2, *nskb, *pskb = NULL;
-	netdev_features_t esp_features = features;
 	struct xfrm_offload *xo = xfrm_offload(skb);
 	struct net_device *dev = skb->dev;
+	netdev_features_t esp_features;
 	struct sec_path *sp;
 
 	if (!xo || (xo->flags & XFRM_XMIT))
 		return skb;
 
-	if (!netdev_feature_test(NETIF_F_HW_ESP_BIT, features)) {
-		esp_features = features;
+	netdev_features_copy(esp_features, *features);
+	if (!netdev_feature_test(NETIF_F_HW_ESP_BIT, *features)) {
+		netdev_features_copy(esp_features, *features);
 		netdev_feature_del(NETIF_F_SG_BIT, esp_features);
 		netdev_features_clear(esp_features, NETIF_F_CSUM_MASK);
 	}
@@ -162,7 +165,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 
 		xo->flags |= XFRM_DEV_RESUME;
 
-		err = x->type_offload->xmit(x, skb, esp_features);
+		err = x->type_offload->xmit(x, skb, &esp_features);
 		if (err) {
 			if (err == -EINPROGRESS)
 				return NULL;
@@ -187,7 +190,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 
 		xfrm_outer_mode_prep(x, skb2);
 
-		err = x->type_offload->xmit(x, skb2, esp_features);
+		err = x->type_offload->xmit(x, skb2, &esp_features);
 		if (!err) {
 			skb2->next = nskb;
 		} else if (err != -EINPROGRESS) {
-- 
2.33.0


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

* [RFCv8 PATCH net-next 49/55] net: adjust the prototype of can_checksum_protocol()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (47 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 48/55] net: adjust the prototype of validate_xmit_xfrm() and relative functions Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 50/55] net: tap: adjust the prototype of update_features() Jian Shen
                   ` (7 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function can_checksum_protocol() using netdev_features_t
as parameters.

For the prototype of netdev_features_t will be extended to be
largerthan 8 bytes, so change the prototype of the function,
change the prototype of input features to 'netdev_features_t *'.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 include/linux/netdevice.h | 10 +++++-----
 include/net/vxlan.h       |  2 +-
 net/core/dev.c            |  2 +-
 net/core/skbuff.c         |  2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f0fad437bdb7..4620af4591fc 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4809,24 +4809,24 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb,
 }
 __be16 skb_network_protocol(struct sk_buff *skb, int *depth);
 
-static inline bool can_checksum_protocol(netdev_features_t features,
+static inline bool can_checksum_protocol(const netdev_features_t *features,
 					 __be16 protocol)
 {
 	if (protocol == htons(ETH_P_FCOE))
-		return netdev_feature_test(NETIF_F_FCOE_CRC_BIT, features);
+		return netdev_feature_test(NETIF_F_FCOE_CRC_BIT, *features);
 
 	/* Assume this is an IP checksum (not SCTP CRC) */
 
-	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, features)) {
+	if (netdev_feature_test(NETIF_F_HW_CSUM_BIT, *features)) {
 		/* Can checksum everything */
 		return true;
 	}
 
 	switch (protocol) {
 	case htons(ETH_P_IP):
-		return netdev_feature_test(NETIF_F_IP_CSUM_BIT, features);
+		return netdev_feature_test(NETIF_F_IP_CSUM_BIT, *features);
 	case htons(ETH_P_IPV6):
-		return netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, features);
+		return netdev_feature_test(NETIF_F_IPV6_CSUM_BIT, *features);
 	default:
 		return false;
 	}
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 25d2bc8015c7..b1a729c4edc1 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -372,7 +372,7 @@ static inline void vxlan_features_check(struct sk_buff *skb,
 	     (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
 	      sizeof(struct udphdr) + sizeof(struct vxlanhdr)) ||
 	     (skb->ip_summed != CHECKSUM_NONE &&
-	      !can_checksum_protocol(*features, inner_eth_hdr(skb)->h_proto)))) {
+	      !can_checksum_protocol(features, inner_eth_hdr(skb)->h_proto)))) {
 		netdev_features_clear(*features, netdev_csum_gso_features_mask);
 		return;
 	}
diff --git a/net/core/dev.c b/net/core/dev.c
index 54cb150d9db1..bed372ecef65 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3485,7 +3485,7 @@ static void harmonize_features(struct sk_buff *skb, netdev_features_t *features)
 	net_mpls_features(skb, features, type);
 
 	if (skb->ip_summed != CHECKSUM_NONE &&
-	    !can_checksum_protocol(*features, type)) {
+	    !can_checksum_protocol(features, type)) {
 		netdev_features_clear(*features,
 				      netdev_csum_gso_features_mask);
 	}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3e6935386637..ced731f87560 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4060,7 +4060,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
 		return ERR_PTR(-EINVAL);
 
 	sg = netdev_feature_test(NETIF_F_SG_BIT, features);
-	csum = !!can_checksum_protocol(features, proto);
+	csum = !!can_checksum_protocol(&features, proto);
 
 	if (sg && csum && (mss != GSO_BY_FRAGS))  {
 		if (!netdev_feature_test(NETIF_F_GSO_PARTIAL_BIT, features)) {
-- 
2.33.0


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

* [RFCv8 PATCH net-next 50/55] net: tap: adjust the prototype of update_features()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (48 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 49/55] net: adjust the prototype of can_checksum_protocol() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 51/55] net: mlx4: adjust the prototype of check_csum() and mlx4_en_update_loopback_state() Jian Shen
                   ` (6 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function tap_dev.update_features() using netdev_features_t
as parameters.

For the prototype of netdev_features_t will be extended to be
larger than 8 bytes, so change the prototype of the function,
change the prototype of input features to 'netdev_features_t *'.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ipvlan/ipvtap.c | 4 ++--
 drivers/net/macvtap.c       | 4 ++--
 drivers/net/tap.c           | 2 +-
 include/linux/if_tap.h      | 3 ++-
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ipvlan/ipvtap.c b/drivers/net/ipvlan/ipvtap.c
index ba2730ba5c1f..37988c869f6e 100644
--- a/drivers/net/ipvlan/ipvtap.c
+++ b/drivers/net/ipvlan/ipvtap.c
@@ -63,12 +63,12 @@ static void ipvtap_count_rx_dropped(struct tap_dev *tap)
 }
 
 static void ipvtap_update_features(struct tap_dev *tap,
-				   netdev_features_t features)
+				   const netdev_features_t *features)
 {
 	struct ipvtap_dev *vlantap = container_of(tap, struct ipvtap_dev, tap);
 	struct ipvl_dev *vlan = &vlantap->vlan;
 
-	vlan->sfeatures = features;
+	netdev_features_copy(vlan->sfeatures, *features);
 	netdev_update_features(vlan->dev);
 }
 
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 14f75986f4c4..1a6cbb987ad2 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -67,12 +67,12 @@ static void macvtap_count_rx_dropped(struct tap_dev *tap)
 }
 
 static void macvtap_update_features(struct tap_dev *tap,
-				    netdev_features_t features)
+				    const netdev_features_t *features)
 {
 	struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap);
 	struct macvlan_dev *vlan = &vlantap->vlan;
 
-	vlan->set_features = features;
+	netdev_features_copy(vlan->set_features, *features);
 	netdev_update_features(vlan->dev);
 }
 
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index e3045a7badd8..a13c0479079f 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -985,7 +985,7 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
 	 */
 	tap->tap_features = feature_mask;
 	if (tap->update_features)
-		tap->update_features(tap, features);
+		tap->update_features(tap, &features);
 
 	return 0;
 }
diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h
index 553552fa635c..7f5678f9df09 100644
--- a/include/linux/if_tap.h
+++ b/include/linux/if_tap.h
@@ -44,7 +44,8 @@ struct tap_dev {
 	netdev_features_t	tap_features;
 	int			minor;
 
-	void (*update_features)(struct tap_dev *tap, netdev_features_t features);
+	void (*update_features)(struct tap_dev *tap,
+				const netdev_features_t *features);
 	void (*count_tx_dropped)(struct tap_dev *tap);
 	void (*count_rx_dropped)(struct tap_dev *tap);
 };
-- 
2.33.0


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

* [RFCv8 PATCH net-next 51/55] net: mlx4: adjust the prototype of check_csum() and mlx4_en_update_loopback_state()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (49 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 50/55] net: tap: adjust the prototype of update_features() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 52/55] net: gve: adjust the prototype of gve_rx(), gve_clean_rx_done() and gve_rx_complete_skb() Jian Shen
                   ` (5 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function check_csum() and mlx4_en_update_loopback_state()
using netdev_features_t as parameters.

For the prototype of netdev_features_t will be extended to be
larger than 8 bytes, so change the prototype of the function,
change the prototype of input features to 'netdev_features_t *'.

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

diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index bc4b88cc81e3..347e98657321 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -100,11 +100,11 @@ void en_print(const char *level, const struct mlx4_en_priv *priv,
 }
 
 void mlx4_en_update_loopback_state(struct net_device *dev,
-				   netdev_features_t features)
+				   const netdev_features_t *features)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 
-	if (netdev_feature_test(NETIF_F_LOOPBACK_BIT, features))
+	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,8 @@ 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) &&
-	    !netdev_feature_test(NETIF_F_LOOPBACK_BIT, features) && !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 +132,8 @@ 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 = netdev_feature_test(NETIF_F_LOOPBACK_BIT, features);
+		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 a93cd318d19d..5c4570c3878e 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2554,7 +2554,7 @@ static int mlx4_en_set_features(struct net_device *netdev,
 	if (DEV_FEATURE_CHANGED(netdev, *features, NETIF_F_LOOPBACK_BIT)) {
 		en_info(priv, "Turn %s loopback\n",
 			netdev_feature_test(NETIF_F_LOOPBACK_BIT, *features) ? "ON" : "OFF");
-		mlx4_en_update_loopback_state(netdev, *features);
+		mlx4_en_update_loopback_state(netdev, features);
 	}
 
 	if (reset) {
@@ -3434,7 +3434,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num[TX]);
 	en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
 
-	mlx4_en_update_loopback_state(priv->dev, priv->dev->features);
+	mlx4_en_update_loopback_state(priv->dev, &priv->dev->features);
 
 	/* Configure port */
 	mlx4_en_calc_rx_buf(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 266f119a93c4..6087264fc01c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -623,7 +623,7 @@ static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb,
  * the (IPv4 | IPv6) bits are set in cqe->status.
  */
 static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va,
-		      netdev_features_t dev_features)
+		      const netdev_features_t *dev_features)
 {
 	__wsum hw_checksum = 0;
 	void *hdr;
@@ -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) &&
-	    !netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, dev_features)) {
+	    !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);
 	}
@@ -862,7 +862,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 				if (!(priv->flags & MLX4_EN_FLAG_RX_CSUM_NON_TCP_UDP &&
 				      (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IP_ANY))))
 					goto csum_none;
-				if (check_csum(cqe, skb, va, dev->features))
+				if (check_csum(cqe, skb, va, &dev->features))
 					goto csum_none;
 				ip_summed = CHECKSUM_COMPLETE;
 				hash_type = PKT_HASH_TYPE_L3;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
index 946d9db7c8c2..79547273f00a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
@@ -85,7 +85,7 @@ static int mlx4_en_test_loopback(struct mlx4_en_priv *priv)
         priv->loopback_ok = 0;
 	priv->validate_loopback = 1;
 
-	mlx4_en_update_loopback_state(priv->dev, priv->dev->features);
+	mlx4_en_update_loopback_state(priv->dev, &priv->dev->features);
 
 	/* xmit */
 	if (mlx4_en_test_loopback_xmit(priv)) {
@@ -108,7 +108,7 @@ static int mlx4_en_test_loopback(struct mlx4_en_priv *priv)
 
 	priv->validate_loopback = 0;
 
-	mlx4_en_update_loopback_state(priv->dev, priv->dev->features);
+	mlx4_en_update_loopback_state(priv->dev, &priv->dev->features);
 	return !loopback_ok;
 }
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index c514fb785e62..ec828c0f1d79 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -656,7 +656,7 @@ static inline struct mlx4_cqe *mlx4_en_get_cqe(void *buf, int idx, int cqe_sz)
 
 void mlx4_en_init_ptys2ethtool_map(void);
 void mlx4_en_update_loopback_state(struct net_device *dev,
-				   netdev_features_t features);
+				   const netdev_features_t *features);
 
 void mlx4_en_destroy_netdev(struct net_device *dev);
 int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
-- 
2.33.0


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

* [RFCv8 PATCH net-next 52/55] net: gve: adjust the prototype of gve_rx(), gve_clean_rx_done() and gve_rx_complete_skb()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (50 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 51/55] net: mlx4: adjust the prototype of check_csum() and mlx4_en_update_loopback_state() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 53/55] net: sfc: adjust the prototype of xxx_supported_features() Jian Shen
                   ` (4 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function  gve_rx(), gve_clean_rx_done() and
gve_rx_complete_skb() using netdev_features_t as parameters.

For the prototype of netdev_features_t will be extended to be
larger than 8 bytes, so change the prototype of the function,
change the prototype of input features to 'netdev_features_t *'.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/google/gve/gve_rx.c     | 10 +++++-----
 drivers/net/ethernet/google/gve/gve_rx_dqo.c |  8 ++++----
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c
index 5f479566011c..ce46739b6826 100644
--- a/drivers/net/ethernet/google/gve/gve_rx.c
+++ b/drivers/net/ethernet/google/gve/gve_rx.c
@@ -534,7 +534,7 @@ static struct sk_buff *gve_rx_skb(struct gve_priv *priv, struct gve_rx_ring *rx,
 	return skb;
 }
 
-static bool gve_rx(struct gve_rx_ring *rx, netdev_features_t feat,
+static bool gve_rx(struct gve_rx_ring *rx, const netdev_features_t *feat,
 		   u64 *packet_size_bytes, u32 *work_done)
 {
 	struct gve_rx_slot_page_info *page_info;
@@ -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(netdev_feature_test(NETIF_F_RXCSUM_BIT, feat))) {
+	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(netdev_feature_test(NETIF_F_RXHASH_BIT, feat)) &&
+	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));
@@ -702,7 +702,7 @@ static bool gve_rx_refill_buffers(struct gve_priv *priv, struct gve_rx_ring *rx)
 }
 
 static int gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
-			     netdev_features_t feat)
+			     const netdev_features_t *feat)
 {
 	u32 work_done = 0, total_packet_cnt = 0, ok_packet_cnt = 0;
 	struct gve_priv *priv = rx->gve;
@@ -783,7 +783,7 @@ int gve_rx_poll(struct gve_notify_block *block, int budget)
 		budget = INT_MAX;
 
 	if (budget > 0)
-		work_done = gve_clean_rx_done(rx, budget, feat);
+		work_done = gve_clean_rx_done(rx, budget, &feat);
 
 	return work_done;
 }
diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
index edff4d162236..e5ce1d261b03 100644
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -629,7 +629,7 @@ static int gve_rx_complete_rsc(struct sk_buff *skb,
 /* Returns 0 if skb is completed successfully, -1 otherwise. */
 static int gve_rx_complete_skb(struct gve_rx_ring *rx, struct napi_struct *napi,
 			       const struct gve_rx_compl_desc_dqo *desc,
-			       netdev_features_t feat)
+			       const netdev_features_t *feat)
 {
 	struct gve_ptype ptype =
 		rx->gve->ptype_lut_dqo->ptypes[desc->packet_type];
@@ -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 (netdev_feature_test(NETIF_F_RXHASH_BIT, feat))
+	if (netdev_feature_test(NETIF_F_RXHASH_BIT, *feat))
 		gve_rx_skb_hash(rx->ctx.skb_head, desc, ptype);
 
-	if (netdev_feature_test(NETIF_F_RXCSUM_BIT, feat))
+	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
@@ -732,7 +732,7 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget)
 			pkt_bytes += ETH_HLEN;
 
 		/* gve_rx_complete_skb() will consume skb if successful */
-		if (gve_rx_complete_skb(rx, napi, compl_desc, feat) != 0) {
+		if (gve_rx_complete_skb(rx, napi, compl_desc, &feat) != 0) {
 			gve_rx_free_skb(rx);
 			u64_stats_update_begin(&rx->statss);
 			rx->rx_desc_err_dropped_pkt++;
-- 
2.33.0


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

* [RFCv8 PATCH net-next 53/55] net: sfc: adjust the prototype of xxx_supported_features()
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (51 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 52/55] net: gve: adjust the prototype of gve_rx(), gve_clean_rx_done() and gve_rx_complete_skb() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 54/55] treewide: use netdev_features_copy helpers Jian Shen
                   ` (3 subsequent siblings)
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

The function xxx_supported_features() of sfc driver return
netdev_features_t directly.

For the prototype of netdev_features_t will be extended to be
larger than 8 bytes, so change the prototype of the function,
return the features pointer as output parameter.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 drivers/net/ethernet/sfc/falcon/net_driver.h | 8 +++-----
 drivers/net/ethernet/sfc/mcdi_filters.c      | 2 +-
 drivers/net/ethernet/sfc/net_driver.h        | 8 +++-----
 drivers/net/ethernet/sfc/siena/net_driver.h  | 8 +++-----
 4 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h
index 35fa95504a5f..d23912406c69 100644
--- a/drivers/net/ethernet/sfc/falcon/net_driver.h
+++ b/drivers/net/ethernet/sfc/falcon/net_driver.h
@@ -1299,14 +1299,12 @@ static inline struct ef4_rx_buffer *ef4_rx_buffer(struct ef4_rx_queue *rx_queue,
  * If a feature is fixed, it does not present in hw_features, but
  * always in features.
  */
-static inline netdev_features_t ef4_supported_features(const struct ef4_nic *efx)
+static inline void ef4_supported_features(const struct ef4_nic *efx,
+					  netdev_features_t *features)
 {
 	const struct net_device *net_dev = efx->net_dev;
-	netdev_features_t features;
 
-	netdev_features_or(features, net_dev->features, net_dev->hw_features);
-
-	return features;
+	netdev_features_or(*features, net_dev->features, net_dev->hw_features);
 }
 
 /* Get the current TX queue insert index. */
diff --git a/drivers/net/ethernet/sfc/mcdi_filters.c b/drivers/net/ethernet/sfc/mcdi_filters.c
index fb4db91f4d8f..99c85b51a487 100644
--- a/drivers/net/ethernet/sfc/mcdi_filters.c
+++ b/drivers/net/ethernet/sfc/mcdi_filters.c
@@ -1324,7 +1324,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;
-	feats = efx_supported_features(efx);
+	efx_supported_features(efx, &feats);
 	if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, feats) &&
 	    !(efx_mcdi_filter_match_supported(table, false,
 		(EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC)) &&
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index dae500645595..20db4472bbe9 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1750,14 +1750,12 @@ efx_channel_tx_old_fill_level(struct efx_channel *channel)
  * If a feature is fixed, it does not present in hw_features, but
  * always in features.
  */
-static inline netdev_features_t efx_supported_features(const struct efx_nic *efx)
+static inline void efx_supported_features(const struct efx_nic *efx,
+					  netdev_features_t *features)
 {
 	const struct net_device *net_dev = efx->net_dev;
-	netdev_features_t features;
 
-	netdev_features_or(features, net_dev->features, net_dev->hw_features);
-
-	return features;
+	netdev_features_or(*features, net_dev->features, net_dev->hw_features);
 }
 
 /* Get the current TX queue insert index. */
diff --git a/drivers/net/ethernet/sfc/siena/net_driver.h b/drivers/net/ethernet/sfc/siena/net_driver.h
index 7040cfccd556..1420522bd0e6 100644
--- a/drivers/net/ethernet/sfc/siena/net_driver.h
+++ b/drivers/net/ethernet/sfc/siena/net_driver.h
@@ -1678,14 +1678,12 @@ efx_channel_tx_old_fill_level(struct efx_channel *channel)
  * If a feature is fixed, it does not present in hw_features, but
  * always in features.
  */
-static inline netdev_features_t efx_supported_features(const struct efx_nic *efx)
+static inline void efx_supported_features(const struct efx_nic *efx,
+					  netdev_features_t *features)
 {
 	const struct net_device *net_dev = efx->net_dev;
-	netdev_features_t features;
 
-	netdev_features_or(features, net_dev->features, net_dev->hw_features);
-
-	return features;
+	netdev_features_or(*features, net_dev->features, net_dev->hw_features);
 }
 
 /* Get the current TX queue insert index. */
-- 
2.33.0


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

* [RFCv8 PATCH net-next 54/55] treewide: use netdev_features_copy helpers
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (52 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 53/55] net: sfc: adjust the prototype of xxx_supported_features() Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-18 12:05   ` kernel test robot
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 55/55] net: redefine the prototype of netdev_features_t Jian Shen
                   ` (2 subsequent siblings)
  56 siblings, 1 reply; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin,
	saeed, leon
  Cc: netdev, linuxarm

Replace operation 'f1 = f2' with netdev_features_copy helpers.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
---
 arch/um/drivers/vector_kern.c                 |  2 +-
 drivers/infiniband/hw/hfi1/vnic_main.c        |  4 +--
 drivers/net/bonding/bond_main.c               | 27 +++++++++++--------
 drivers/net/ethernet/3com/typhoon.c           |  2 +-
 drivers/net/ethernet/aeroflex/greth.c         |  2 +-
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  2 +-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c     |  2 +-
 drivers/net/ethernet/apm/xgene-v2/main.c      |  2 +-
 .../net/ethernet/apm/xgene/xgene_enet_main.c  |  2 +-
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |  4 +--
 .../net/ethernet/atheros/atl1c/atl1c_main.c   |  2 +-
 .../net/ethernet/atheros/atl1e/atl1e_main.c   |  2 +-
 drivers/net/ethernet/broadcom/bgmac.c         |  4 +--
 drivers/net/ethernet/broadcom/bnx2.c          |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c |  8 +++---
 drivers/net/ethernet/cadence/macb_main.c      |  6 +++--
 .../net/ethernet/cavium/liquidio/lio_main.c   |  8 +++---
 .../ethernet/cavium/liquidio/lio_vf_main.c    |  8 +++---
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   |  4 +--
 .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c   |  6 ++---
 drivers/net/ethernet/cortina/gemini.c         |  2 +-
 drivers/net/ethernet/engleder/tsnep_main.c    |  2 +-
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  2 +-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |  2 +-
 drivers/net/ethernet/freescale/fec_main.c     |  2 +-
 .../ethernet/fungible/funeth/funeth_main.c    |  4 +--
 drivers/net/ethernet/google/gve/gve_main.c    |  7 ++---
 drivers/net/ethernet/google/gve/gve_rx_dqo.c  |  3 ++-
 .../net/ethernet/huawei/hinic/hinic_main.c    |  4 +--
 drivers/net/ethernet/ibm/ibmvnic.c            |  3 ++-
 drivers/net/ethernet/intel/e1000e/netdev.c    |  2 +-
 .../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   |  4 +--
 drivers/net/ethernet/intel/ice/ice_main.c     |  4 +--
 drivers/net/ethernet/intel/ice/ice_txrx_lib.c |  3 ++-
 drivers/net/ethernet/intel/igb/igb_main.c     |  2 +-
 drivers/net/ethernet/intel/igbvf/netdev.c     |  4 +--
 drivers/net/ethernet/intel/igc/igc_main.c     |  2 +-
 drivers/net/ethernet/intel/ixgb/ixgb_main.c   |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |  5 ++--
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |  4 +--
 drivers/net/ethernet/marvell/mv643xx_eth.c    |  4 +--
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   | 14 +++++-----
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  2 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  2 +-
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  4 +--
 .../net/ethernet/mellanox/mlx5/core/en_main.c |  6 ++---
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  3 ++-
 drivers/net/ethernet/microchip/lan743x_main.c |  2 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c |  2 +-
 .../net/ethernet/myricom/myri10ge/myri10ge.c  |  7 ++---
 .../ethernet/netronome/nfp/nfp_net_common.c   |  6 ++---
 .../net/ethernet/netronome/nfp/nfp_net_repr.c | 10 +++----
 .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  2 +-
 .../net/ethernet/qlogic/qede/qede_filter.c    |  2 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c  |  6 ++---
 .../net/ethernet/qlogic/qlcnic/qlcnic_main.c  |  2 +-
 drivers/net/ethernet/qualcomm/emac/emac.c     |  2 +-
 drivers/net/ethernet/realtek/8139too.c        |  2 +-
 drivers/net/ethernet/renesas/ravb_main.c      |  4 +--
 drivers/net/ethernet/renesas/sh_eth.c         |  2 +-
 drivers/net/ethernet/sfc/ef10.c               |  2 +-
 drivers/net/ethernet/sfc/efx_common.c         |  3 ++-
 drivers/net/ethernet/sfc/falcon/efx.c         |  3 ++-
 drivers/net/ethernet/sfc/siena/efx_common.c   |  3 ++-
 drivers/net/ethernet/socionext/netsec.c       |  2 +-
 drivers/net/ethernet/sun/ldmvsw.c             |  2 +-
 drivers/net/ethernet/sun/sungem.c             |  2 +-
 drivers/net/ethernet/sun/sunvnet.c            |  4 +--
 drivers/net/ethernet/sun/sunvnet_common.c     |  3 ++-
 .../net/ethernet/synopsys/dwc-xlgmac-common.c |  6 ++---
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  2 +-
 drivers/net/ethernet/ti/netcp_core.c          |  2 +-
 drivers/net/hyperv/netvsc_drv.c               |  6 ++---
 drivers/net/ipvlan/ipvlan_main.c              |  6 ++---
 drivers/net/loopback.c                        |  4 +--
 drivers/net/macsec.c                          |  2 +-
 drivers/net/macvlan.c                         |  5 ++--
 drivers/net/net_failover.c                    |  5 ++--
 drivers/net/ntb_netdev.c                      |  2 +-
 drivers/net/tap.c                             |  4 +--
 drivers/net/team/team.c                       | 11 ++++----
 drivers/net/thunderbolt.c                     |  4 +--
 drivers/net/tun.c                             |  6 ++---
 drivers/net/usb/lan78xx.c                     |  2 +-
 drivers/net/usb/r8152.c                       |  3 ++-
 drivers/net/veth.c                            |  6 ++---
 drivers/net/virtio_net.c                      |  2 +-
 drivers/net/vmxnet3/vmxnet3_drv.c             |  2 +-
 drivers/net/vrf.c                             |  4 +--
 drivers/net/vxlan/vxlan_core.c                |  2 +-
 drivers/net/wireguard/device.c                |  2 +-
 drivers/net/wireless/intel/iwlwifi/iwl-drv.c  |  7 ++---
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c   |  2 +-
 drivers/net/xen-netback/interface.c           |  2 +-
 drivers/s390/block/dasd_devmap.c              |  2 +-
 drivers/s390/net/qeth_core_main.c             |  2 +-
 drivers/staging/qlge/qlge_main.c              |  4 +--
 net/8021q/vlan_dev.c                          |  2 +-
 net/bridge/br_device.c                        |  6 ++---
 net/core/dev.c                                | 16 ++++++-----
 net/dsa/slave.c                               |  4 +--
 net/ethtool/ioctl.c                           |  4 +--
 net/hsr/hsr_device.c                          |  4 +--
 net/ipv4/ipip.c                               |  2 +-
 net/ipv6/ip6_tunnel.c                         |  2 +-
 net/ipv6/sit.c                                |  2 +-
 net/mac80211/main.c                           |  2 +-
 net/openvswitch/vport-internal_dev.c          |  6 ++---
 net/xfrm/xfrm_interface.c                     |  2 +-
 112 files changed, 231 insertions(+), 206 deletions(-)

diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 7b4b9bed8979..e0c8b02d0051 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1630,7 +1630,7 @@ static void vector_eth_configure(
 	netdev_active_features_zero(dev);
 	netdev_active_features_set_set(dev, NETIF_F_SG_BIT,
 				       NETIF_F_FRAGLIST_BIT);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 	INIT_WORK(&vp->reset_tx, vector_reset_tx);
 
 	timer_setup(&vp->tl, vector_timer_expire, 0);
diff --git a/drivers/infiniband/hw/hfi1/vnic_main.c b/drivers/infiniband/hw/hfi1/vnic_main.c
index 949a414d4d7d..a1347daa648f 100644
--- a/drivers/infiniband/hw/hfi1/vnic_main.c
+++ b/drivers/infiniband/hw/hfi1/vnic_main.c
@@ -591,8 +591,8 @@ struct net_device *hfi1_vnic_alloc_rn(struct ib_device *device,
 	netdev_active_features_zero(netdev);
 	netdev_active_features_set_set(netdev, NETIF_F_HIGHDMA_BIT,
 				       NETIF_F_SG_BIT);
-	netdev->hw_features = netdev->features;
-	netdev->vlan_features = netdev->features;
+	netdev_hw_features_copy(netdev, netdev->features);
+	netdev_vlan_features_copy(netdev, netdev->features);
 	netdev->watchdog_timeo = msecs_to_jiffies(HFI_TX_TIMEOUT_MS);
 	netdev->netdev_ops = &hfi1_netdev_ops;
 	mutex_init(&vinfo->lock);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index cd7c8d81ba0c..1b941cac6b41 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1433,12 +1433,12 @@ static void bond_compute_features(struct bonding *bond)
 {
 	unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
 					IFF_XMIT_DST_RELEASE_PERM;
-	netdev_features_t vlan_features = BOND_VLAN_FEATURES;
-	netdev_features_t enc_features  = BOND_ENC_FEATURES;
+	netdev_features_t vlan_features;
+	netdev_features_t enc_features;
 #ifdef CONFIG_XFRM_OFFLOAD
-	netdev_features_t xfrm_features  = BOND_XFRM_FEATURES;
+	netdev_features_t xfrm_features;
 #endif /* CONFIG_XFRM_OFFLOAD */
-	netdev_features_t mpls_features  = BOND_MPLS_FEATURES;
+	netdev_features_t mpls_features;
 	struct net_device *bond_dev = bond->dev;
 	struct list_head *iter;
 	struct slave *slave;
@@ -1448,6 +1448,10 @@ static void bond_compute_features(struct bonding *bond)
 
 	if (!bond_has_slaves(bond))
 		goto done;
+	netdev_features_copy(vlan_features, BOND_VLAN_FEATURES);
+	netdev_features_copy(enc_features, BOND_ENC_FEATURES);
+	netdev_features_copy(xfrm_features, BOND_XFRM_FEATURES);
+	netdev_features_copy(mpls_features, BOND_MPLS_FEATURES);
 	netdev_features_mask(vlan_features, NETIF_F_ALL_FOR_ALL);
 	netdev_features_mask(mpls_features, NETIF_F_ALL_FOR_ALL);
 
@@ -1480,14 +1484,14 @@ static void bond_compute_features(struct bonding *bond)
 	bond_dev->hard_header_len = max_hard_header_len;
 
 done:
-	bond_dev->vlan_features = vlan_features;
+	netdev_vlan_features_copy(bond_dev, vlan_features);
 	netdev_hw_enc_features_or(bond_dev, enc_features,
 				  NETIF_F_GSO_ENCAP_ALL);
 	netdev_hw_enc_features_set(bond_dev, netdev_tx_vlan_features);
 #ifdef CONFIG_XFRM_OFFLOAD
 	netdev_hw_enc_features_set(bond_dev, xfrm_features);
 #endif /* CONFIG_XFRM_OFFLOAD */
-	bond_dev->mpls_features = mpls_features;
+	netdev_mpls_features_copy(bond_dev, mpls_features);
 	netif_set_tso_max_segs(bond_dev, tso_max_segs);
 	netif_set_tso_max_size(bond_dev, tso_max_size);
 
@@ -2317,7 +2321,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 	struct slave *slave, *oldcurrent;
 	struct sockaddr_storage ss;
 	int old_flags = bond_dev->flags;
-	netdev_features_t old_features = bond_dev->features;
+	netdev_features_t old_features;
 
 	/* slave is not a slave or master is not master of this slave */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
@@ -2420,6 +2424,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 		call_netdevice_notifiers(NETDEV_RELEASE, bond->dev);
 	}
 
+	netdev_features_copy(old_features, bond_dev->features);
 	bond_compute_features(bond);
 	if (!netdev_active_feature_test(bond_dev, NETIF_F_VLAN_CHALLENGED_BIT) &&
 	    netdev_feature_test(NETIF_F_VLAN_CHALLENGED_BIT, old_features))
@@ -5770,7 +5775,7 @@ void bond_setup(struct net_device *bond_dev)
 	/* Don't allow bond devices to change network namespaces. */
 	netdev_active_feature_add(bond_dev, NETIF_F_NETNS_LOCAL_BIT);
 
-	bond_dev->hw_features = BOND_VLAN_FEATURES;
+	netdev_hw_features_copy(bond_dev, BOND_VLAN_FEATURES);
 	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);
 
@@ -6216,16 +6221,16 @@ static int bond_check_params(struct bond_params *params)
 
 static void __init bond_netdev_features_init(void)
 {
-	bond_vlan_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(bond_vlan_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(bond_vlan_features, NETIF_F_HW_CSUM_BIT,
 				NETIF_F_SG_BIT, NETIF_F_FRAGLIST_BIT,
 				NETIF_F_HIGHDMA_BIT, NETIF_F_LRO_BIT);
 
-	bond_enc_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(bond_enc_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(bond_enc_features, NETIF_F_HW_CSUM_BIT,
 				NETIF_F_SG_BIT, NETIF_F_RXCSUM_BIT);
 
-	bond_mpls_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(bond_mpls_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(bond_mpls_features,  NETIF_F_HW_CSUM_BIT,
 				NETIF_F_SG_BIT);
 }
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index 694400423285..d42a53748f40 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -2481,7 +2481,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
 				   NETIF_F_TSO_BIT,
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 	netdev_active_features_set_set(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT,
 				       NETIF_F_RXCSUM_BIT);
 
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 0e424ac95a65..0a8aa16d0ce1 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1488,7 +1488,7 @@ static int greth_of_probe(struct platform_device *ofdev)
 		netdev_hw_features_set_set(dev, NETIF_F_SG_BIT,
 					   NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_RXCSUM_BIT);
-		dev->features = dev->hw_features;
+		netdev_active_features_copy(dev, dev->hw_features);
 		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/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index 5d287e960a2a..47beaab0d963 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -4044,7 +4044,7 @@ static void ena_set_dev_offloads(struct ena_com_dev_get_features_ctx *feat,
 		ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV6_CSUM_MASK)
 		netdev_feature_add(NETIF_F_RXCSUM_BIT, dev_features);
 
-	netdev->features = dev_features;
+	netdev_active_features_copy(netdev, dev_features);
 	netdev_active_features_set_set(netdev, NETIF_F_SG_BIT,
 				       NETIF_F_RXHASH_BIT, NETIF_F_HIGHDMA_BIT);
 
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 79a4a8c1471e..1e717fda866f 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -377,7 +377,7 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
 				     NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT);
 
 	netdev_active_features_set(netdev, netdev->hw_features);
-	pdata->netdev_features = netdev->features;
+	netdev_features_copy(pdata->netdev_features, netdev->features);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 	netdev->min_mtu = 0;
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c
index c33d9f810953..aa1df1785c55 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -654,7 +654,7 @@ static int xge_probe(struct platform_device *pdev)
 	if (ret)
 		goto err;
 
-	ndev->hw_features = ndev->features;
+	netdev_hw_features_copy(ndev, ndev->features);
 	xge_set_ethtool_ops(ndev);
 
 	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 2f03cdebb00d..e817344ef385 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -2069,7 +2069,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
 					       NETIF_F_RXCSUM_BIT);
 		spin_lock_init(&pdata->mss_lock);
 	}
-	ndev->hw_features = ndev->features;
+	netdev_hw_features_copy(ndev, ndev->features);
 
 	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
 	if (ret) {
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index bc9649ea37e9..09f5f2b37359 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;
+	netdev_features_copy(cfg->features, *cfg->aq_hw_caps->hw_features);
 	cfg->is_vlan_rx_strip =
 		netdev_feature_test(NETIF_F_HW_VLAN_CTAG_RX_BIT, cfg->features);
 	cfg->is_vlan_tx_insert =
@@ -375,7 +375,7 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 	struct aq_nic_cfg_s *aq_nic_cfg = &self->aq_nic_cfg;
 
 	netdev_hw_features_set(self->ndev, *aq_hw_caps->hw_features);
-	self->ndev->features = *aq_hw_caps->hw_features;
+	netdev_active_features_copy(self->ndev, *aq_hw_caps->hw_features);
 	netdev_vlan_features_set_set(self->ndev, NETIF_F_HW_CSUM_BIT,
 				     NETIF_F_RXCSUM_BIT, NETIF_F_RXHASH_BIT,
 				     NETIF_F_SG_BIT, 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 4ce52ea0833f..2cadd62e034d 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2634,7 +2634,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT, NETIF_F_TSO_BIT,
 				   NETIF_F_TSO6_BIT);
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	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 29245ecea761..422fe8c2f47e 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -2274,7 +2274,7 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_TSO_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_TX_BIT);
 	/* not enabled by default */
 	netdev_hw_features_set_set(netdev, NETIF_F_RXALL_BIT,
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 2c902c0b4ffe..b36c8c4a68c5 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1540,8 +1540,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)
 	netdev_active_features_set_set(net_dev, NETIF_F_SG_BIT,
 				       NETIF_F_IP_CSUM_BIT,
 				       NETIF_F_IPV6_CSUM_BIT);
-	net_dev->hw_features = net_dev->features;
-	net_dev->vlan_features = net_dev->features;
+	netdev_hw_features_copy(net_dev, net_dev->features);
+	netdev_vlan_features_copy(net_dev, net_dev->features);
 
 	/* Omit FCS from max MTU size */
 	net_dev->max_mtu = BGMAC_RX_MAX_FRAME_SIZE - ETH_FCS_LEN;
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 7ea525d1dc11..f9cbce85f083 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8593,7 +8593,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_hw_features_set_set(dev, NETIF_F_IPV6_CSUM_BIT,
 					   NETIF_F_TSO6_BIT);
 
-	dev->vlan_features = dev->hw_features;
+	netdev_vlan_features_copy(dev, 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;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index e62d5f9cc211..516623df4f2b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -13627,7 +13627,7 @@ 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_set(dev, NETIF_F_GSO_GRE_CSUM_BIT,
 					    NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
-	dev->vlan_features = dev->hw_features;
+	netdev_vlan_features_copy(dev, dev->hw_features);
 	netdev_vlan_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	if (bp->fw_cap & BNXT_FW_CAP_VLAN_RX_STRIP)
 		netdev_hw_features_set(dev, BNXT_HW_FEATURE_VLAN_ALL_RX);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index beba73d73f3f..c5a064629fad 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -468,10 +468,10 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
 	/* Just inherit all the featues of the parent PF as the VF-R
 	 * uses the RX/TX rings of the parent PF
 	 */
-	dev->hw_features = pf_dev->hw_features;
-	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;
+	netdev_hw_features_copy(dev, pf_dev->hw_features);
+	netdev_gso_partial_features_copy(dev, pf_dev->gso_partial_features);
+	netdev_vlan_features_copy(dev, pf_dev->vlan_features);
+	netdev_hw_enc_features_copy(dev, pf_dev->hw_enc_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);
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 9b31b70309c7..22a03aa03f36 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -3765,8 +3765,10 @@ static int macb_set_features(struct net_device *netdev,
 static void macb_restore_features(struct macb *bp)
 {
 	struct net_device *netdev = bp->dev;
-	netdev_features_t features = netdev->features;
 	struct ethtool_rx_fs_item *item;
+	netdev_features_t features;
+
+	netdev_features_copy(features, netdev->features);
 
 	/* TX checksum offload */
 	macb_set_txcsum_feature(bp, &features);
@@ -4067,7 +4069,7 @@ static int macb_init(struct platform_device *pdev)
 					   NETIF_F_RXCSUM_BIT);
 	if (bp->caps & MACB_CAPS_SG_DISABLED)
 		netdev_hw_feature_del(dev, NETIF_F_SG_BIT);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 
 	/* Check RX Flow Filters support.
 	 * Max Rx flows set by availability of screeners & compare regs:
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 7e4c749aa8b0..9bc430aea6af 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3585,7 +3585,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 					NETIF_F_RXCSUM_BIT, NETIF_F_TSO_BIT,
 					NETIF_F_TSO6_BIT, NETIF_F_LRO_BIT);
 
-		netdev->hw_enc_features = lio->enc_dev_capability;
+		netdev_hw_enc_features_copy(netdev, lio->enc_dev_capability);
 		netdev_hw_enc_feature_del(netdev, NETIF_F_LRO_BIT);
 
 		netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
@@ -3593,15 +3593,15 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 		netdev_feature_add(NETIF_F_GSO_UDP_TUNNEL_BIT,
 				   lio->dev_capability);
 
-		netdev->vlan_features = lio->dev_capability;
+		netdev_vlan_features_copy(netdev, lio->dev_capability);
 		/* Add any unchangeable hw features */
 		netdev_features_set(lio->dev_capability,
 				    netdev_ctag_vlan_features);
 
-		netdev->features = lio->dev_capability;
+		netdev_active_features_copy(netdev, lio->dev_capability);
 		netdev_active_feature_del(netdev, NETIF_F_LRO_BIT);
 
-		netdev->hw_features = lio->dev_capability;
+		netdev_hw_features_copy(netdev, lio->dev_capability);
 		/*HW_VLAN_RX and HW_VLAN_FILTER is always on*/
 		netdev_hw_feature_del(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index cd0f6a7de629..65bbd2b38e15 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -2116,19 +2116,19 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
 					NETIF_F_RXCSUM_BIT, NETIF_F_TSO_BIT,
 					NETIF_F_TSO6_BIT, NETIF_F_LRO_BIT);
 
-		netdev->hw_enc_features = lio->enc_dev_capability;
+		netdev_hw_enc_features_copy(netdev, lio->enc_dev_capability);
 		netdev_hw_enc_feature_del(netdev, NETIF_F_LRO_BIT);
 		netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
 
-		netdev->vlan_features = lio->dev_capability;
+		netdev_vlan_features_copy(netdev, lio->dev_capability);
 		/* Add any unchangeable hw features */
 		netdev_features_set(lio->dev_capability,
 				    netdev_ctag_vlan_features);
 
-		netdev->features = lio->dev_capability;
+		netdev_active_features_copy(netdev, lio->dev_capability);
 		netdev_active_feature_del(netdev, NETIF_F_LRO_BIT);
 
-		netdev->hw_features = lio->dev_capability;
+		netdev_hw_features_copy(netdev, lio->dev_capability);
 		netdev_hw_feature_del(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
 		/* MTU range: 68 - 16000 */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 8d578c120641..d8703796721e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6816,7 +6816,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		netdev_features_set_set(tso_features, NETIF_F_TSO_BIT,
 					NETIF_F_TSO6_BIT, NETIF_F_TSO_ECN_BIT,
 					NETIF_F_GSO_UDP_L4_BIT);
-		netdev->hw_features = tso_features;
+		netdev_hw_features_copy(netdev, tso_features);
 		netdev_hw_features_set_set(netdev, NETIF_F_SG_BIT,
 					   NETIF_F_IP_CSUM_BIT,
 					   NETIF_F_IPV6_CSUM_BIT,
@@ -6848,7 +6848,7 @@ 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_copy(vlan_features, tso_features);
 		netdev_features_set_set(vlan_features, NETIF_F_SG_BIT,
 					NETIF_F_IP_CSUM_BIT, NETIF_F_GRO_BIT,
 					NETIF_F_IPV6_CSUM_BIT,
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index a2e8135490d2..be3a1cba938f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -3066,16 +3066,16 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
 		netdev_features_zero(tso_features);
 		netdev_features_set_set(tso_features, NETIF_F_TSO_BIT,
 					NETIF_F_TSO6_BIT, NETIF_F_TSO_ECN_BIT);
-		netdev->hw_features = tso_features;
+		netdev_hw_features_copy(netdev, tso_features);
 		netdev_hw_features_set_set(netdev, 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);
-		netdev->features = netdev->hw_features;
+		netdev_active_features_copy(netdev, netdev->hw_features);
 		netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
-		vlan_features = tso_features;
+		netdev_features_copy(vlan_features, tso_features);
 		netdev_features_set_set(vlan_features, NETIF_F_SG_BIT,
 					NETIF_F_IP_CSUM_BIT, NETIF_F_GRO_BIT,
 					NETIF_F_IPV6_CSUM_BIT,
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index f66ef5bf8d94..65e0d496f69a 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -2460,7 +2460,7 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
 	spin_lock_init(&port->config_lock);
 	gmac_clear_hw_stats(netdev);
 
-	netdev->hw_features = GMAC_OFFLOAD_FEATURES;
+	netdev_hw_features_copy(netdev, 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
diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index 5a86b671ba3d..fcf062e2d570 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -1285,7 +1285,7 @@ static int tsnep_probe(struct platform_device *pdev)
 	netdev->ethtool_ops = &tsnep_ethtool_ops;
 	netdev_active_features_zero(netdev);
 	netdev_active_feature_add(netdev, NETIF_F_SG_BIT);
-	netdev->hw_features = netdev->features;
+	netdev_hw_features_copy(netdev, netdev->features);
 	netdev_hw_feature_add(netdev, NETIF_F_LOOPBACK_BIT);
 
 	/* carrier off reporting is important to ethtool even BEFORE open */
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 546002f864d0..6957a9cabd85 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -243,7 +243,7 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 	net_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 
 	netdev_active_features_set(net_dev, net_dev->hw_features);
-	net_dev->vlan_features = net_dev->features;
+	netdev_vlan_features_copy(net_dev, net_dev->features);
 
 	if (is_valid_ether_addr(mac_addr)) {
 		memcpy(net_dev->perm_addr, mac_addr, net_dev->addr_len);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index fdd0bda2c461..cb89136e8c39 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -4398,7 +4398,7 @@ static int dpaa2_eth_netdev_init(struct net_device *net_dev)
 				       NETIF_F_HIGHDMA_BIT, NETIF_F_LLTX_BIT,
 				       NETIF_F_HW_TC_BIT, NETIF_F_TSO_BIT);
 	net_dev->gso_max_segs = DPAA2_ETH_ENQUEUE_MAX_FDS;
-	net_dev->hw_features = net_dev->features;
+	netdev_hw_features_copy(net_dev, net_dev->features);
 
 	if (priv->dpni_attrs.vlan_filter_entries)
 		netdev_hw_feature_add(net_dev,
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 90094816a6c8..c18b45114aff 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3656,7 +3656,7 @@ static int fec_enet_init(struct net_device *ndev)
 		fep->rx_align = 0x3f;
 	}
 
-	ndev->hw_features = ndev->features;
+	netdev_hw_features_copy(ndev, ndev->features);
 
 	fec_restart(ndev);
 
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_main.c b/drivers/net/ethernet/fungible/funeth/funeth_main.c
index ea5863db61ed..0b68fa37c1a6 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1786,8 +1786,8 @@ 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_and(netdev, netdev->features, vlan_feat);
-	netdev->mpls_features = netdev->vlan_features;
-	netdev->hw_enc_features = netdev->hw_features;
+	netdev_mpls_features_copy(netdev, netdev->vlan_features);
+	netdev_hw_enc_features_copy(netdev, netdev->hw_features);
 
 	netdev->min_mtu = ETH_MIN_MTU;
 	netdev->max_mtu = FUN_MAX_MTU;
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index 31d749796b49..148cd458494e 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -1181,10 +1181,11 @@ static void gve_tx_timeout(struct net_device *dev, unsigned int txqueue)
 static int gve_set_features(struct net_device *netdev,
 			    const netdev_features_t *features)
 {
-	const netdev_features_t orig_features = netdev->features;
 	struct gve_priv *priv = netdev_priv(netdev);
+	netdev_features_t orig_features;
 	int err;
 
+	netdev_features_copy(orig_features, netdev->features);
 	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);
@@ -1209,7 +1210,7 @@ static int gve_set_features(struct net_device *netdev,
 	return 0;
 err:
 	/* Reverts the change on error. */
-	netdev->features = orig_features;
+	netdev_active_features_copy(netdev, orig_features);
 	netif_err(priv, drv, netdev,
 		  "Set features failed! !!! DISABLING ALL QUEUES !!!\n");
 	return err;
@@ -1595,7 +1596,7 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   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);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 	dev->watchdog_timeo = 5 * HZ;
 	dev->min_mtu = ETH_MIN_MTU;
 	netif_carrier_off(dev);
diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
index e5ce1d261b03..7718f11307fc 100644
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -663,7 +663,7 @@ static int gve_rx_complete_skb(struct gve_rx_ring *rx, struct napi_struct *napi,
 int gve_rx_poll_dqo(struct gve_notify_block *block, int budget)
 {
 	struct napi_struct *napi = &block->napi;
-	netdev_features_t feat = napi->dev->features;
+	netdev_features_t feat;
 
 	struct gve_rx_ring *rx = block->rx;
 	struct gve_rx_compl_queue_dqo *complq = &rx->dqo.complq;
@@ -672,6 +672,7 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget)
 	u64 bytes = 0;
 	int err;
 
+	netdev_features_copy(feat, napi->dev->features);
 	while (work_done < budget) {
 		struct gve_rx_compl_desc_dqo *compl_desc =
 			&complq->desc_ring[complq->head];
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index ecb3d345ff2e..f1a500bf7c21 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -927,9 +927,9 @@ static void netdev_features_init(struct net_device *netdev)
 				   NETIF_F_GSO_UDP_TUNNEL_BIT,
 				   NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
-	netdev->vlan_features = netdev->hw_features;
+	netdev_vlan_features_copy(netdev, netdev->hw_features);
 
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	netdev_hw_enc_features_zero(netdev);
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index afef066f0647..e87e709c5952 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4864,7 +4864,8 @@ static void send_control_ip_offload(struct ibmvnic_adapter *adapter)
 
 	netdev_hw_features_zero(old_hw_features);
 	if (adapter->state != VNIC_PROBING) {
-		old_hw_features = adapter->netdev->hw_features;
+		netdev_features_copy(old_hw_features,
+				     adapter->netdev->hw_features);
 		netdev_hw_features_zero(adapter->netdev);
 	}
 
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 95fe8df96d5a..5bd08f884817 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -7536,7 +7536,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				       NETIF_F_HW_CSUM_BIT);
 
 	/* Set user-changeable features (subset of all device features) */
-	netdev->hw_features = netdev->features;
+	netdev_hw_features_copy(netdev, netdev->features);
 	netdev_hw_feature_add(netdev, NETIF_F_RXFCS_BIT);
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 	netdev_hw_feature_add(netdev, NETIF_F_RXALL_BIT);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 2162a2d7f3f5..1efe6fdb7c33 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1585,7 +1585,7 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
 	}
 
 	/* all features defined to this point should be changeable */
-	hw_features = dev->features;
+	netdev_features_copy(hw_features, dev->features);
 
 	/* allow user to enable L2 forwarding acceleration */
 	netdev_feature_add(NETIF_F_HW_L2FW_DOFFLOAD_BIT, hw_features);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 86e63041f2cc..eeaf336a4465 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13645,7 +13645,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	np = netdev_priv(netdev);
 	np->vsi = vsi;
 
-	hw_enc_features = NETIF_F_SOFT_FEATURES;
+	netdev_features_copy(hw_enc_features, NETIF_F_SOFT_FEATURES);
 	netdev_features_set_set(hw_enc_features, NETIF_F_SG_BIT,
 				NETIF_F_HW_CSUM_BIT, NETIF_F_HIGHDMA_BIT,
 				NETIF_F_TSO_BIT, NETIF_F_TSO_ECN_BIT,
@@ -13679,7 +13679,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 				NETIF_F_GSO_IPXIP6_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
-	netdev->gso_partial_features = gso_partial_features;
+	netdev_gso_partial_features_copy(netdev, gso_partial_features);
 	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev_active_features_set(netdev, gso_partial_features);
 
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 456bb30ce086..f0040e7dbc92 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -4747,7 +4747,7 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	netdev_features_t hw_enc_features;
 	netdev_features_t hw_features;
 
-	hw_enc_features = NETIF_F_SOFT_FEATURES;
+	netdev_features_copy(hw_enc_features, NETIF_F_SOFT_FEATURES);
 	netdev_features_set_set(hw_enc_features,
 				NETIF_F_SG_BIT,
 				NETIF_F_IP_CSUM_BIT,
@@ -4790,7 +4790,7 @@ int iavf_process_config(struct iavf_adapter *adapter)
 	/* Write features and hw_features separately to avoid polluting
 	 * with, or dropping, features that are set when we registered.
 	 */
-	hw_features = hw_enc_features;
+	netdev_features_copy(hw_features, hw_enc_features);
 
 	/* get HW VLAN features that can be toggled */
 	iavf_get_netdev_vlan_hw_features(adapter, &hw_vlan_features);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index d4f77da1ddd7..f1006743b35a 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3330,7 +3330,7 @@ static void ice_set_netdev_features(struct net_device *netdev)
 		netdev_active_features_zero(netdev);
 		netdev_active_features_set_set(netdev, NETIF_F_SG_BIT,
 					       NETIF_F_HIGHDMA_BIT);
-		netdev->hw_features = netdev->features;
+		netdev_hw_features_copy(netdev, netdev->features);
 		return;
 	}
 
@@ -3348,7 +3348,7 @@ static void ice_set_netdev_features(struct net_device *netdev)
 				NETIF_F_SCTP_CRC_BIT,
 				NETIF_F_IPV6_CSUM_BIT);
 
-	vlano_features = netdev_ctag_vlan_features;
+	netdev_features_copy(vlano_features, netdev_ctag_vlan_features);
 
 	/* Enable CTAG/STAG filtering by default in Double VLAN Mode (DVM) */
 	if (is_dvm_ena)
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
index 7bade466c0e5..ebaf2acfb089 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
@@ -209,9 +209,10 @@ ice_process_skb_fields(struct ice_rx_ring *rx_ring,
 void
 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);
+	netdev_features_t features;
 
+	netdev_features_copy(features, rx_ring->netdev->features);
 	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 (netdev_feature_test(NETIF_F_HW_VLAN_STAG_RX_BIT, features) && non_zero_vlan)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 87c55e4c7649..4b7bcd9c3d94 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3300,7 +3300,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_IPXIP6_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
-	netdev->gso_partial_features = gso_partial_features;
+	netdev_gso_partial_features_copy(netdev, gso_partial_features);
 	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev_active_features_set(netdev, gso_partial_features);
 
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index a812b3fae712..5533be0b57cf 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2782,11 +2782,11 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
-	netdev->gso_partial_features = gso_partial_features;
+	netdev_gso_partial_features_copy(netdev, gso_partial_features);
 	netdev_hw_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev_hw_features_set(netdev, gso_partial_features);
 
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev_vlan_features_set(netdev, netdev->features);
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index c0305237a620..68444500a476 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6362,7 +6362,7 @@ static int igc_probe(struct pci_dev *pdev,
 				NETIF_F_GSO_IPXIP6_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
-	netdev->gso_partial_features = gso_partial_features;
+	netdev_gso_partial_features_copy(netdev, gso_partial_features);
 	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev_active_features_set(netdev, gso_partial_features);
 
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index d8d88bb41c38..87a4ff84ce42 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -437,7 +437,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				   NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT);
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 	netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 7faec783bfcc..590902329395 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -4904,7 +4904,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 fctrl, vmolr = IXGBE_VMOLR_BAM | IXGBE_VMOLR_AUPE;
-	netdev_features_t features = netdev->features;
+	netdev_features_t features;
 	int count;
 
 	/* Check for Promiscuous and All Multicast modes */
@@ -4916,6 +4916,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
 	fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */
 	fctrl |= IXGBE_FCTRL_PMCF;
 
+	netdev_features_copy(features, netdev->features);
 	/* clear the bits we are changing the status of */
 	fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
 	if (netdev->flags & IFF_PROMISC) {
@@ -10985,7 +10986,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
 
-	netdev->gso_partial_features = gso_partial_features;
+	netdev_gso_partial_features_copy(netdev, gso_partial_features);
 	netdev_active_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev_active_features_set(netdev, gso_partial_features);
 
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 5078d723251f..5b2c501428ef 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4616,11 +4616,11 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				NETIF_F_GSO_IPXIP6_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_BIT,
 				NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
-	netdev->gso_partial_features = gso_partial_features;
+	netdev_gso_partial_features_copy(netdev, gso_partial_features);
 	netdev_hw_feature_add(netdev, NETIF_F_GSO_PARTIAL_BIT);
 	netdev_hw_features_set(netdev, gso_partial_features);
 
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev_vlan_features_set(netdev, netdev->features);
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 4bf7b2fbf728..9d0c52b6eef0 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -3205,10 +3205,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 	netdev_active_features_zero(dev);
 	netdev_active_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
 				       NETIF_F_TSO_BIT);
-	dev->vlan_features = dev->features;
+	netdev_vlan_features_copy(dev, dev->features);
 
 	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
-	dev->hw_features = dev->features;
+	netdev_hw_features_copy(dev, dev->features);
 
 	dev->priv_flags |= IFF_UNICAST_FLT;
 	netif_set_tso_max_segs(dev, MV643XX_MAX_TSO_SEGS);
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index cc6699715171..0d18fb6e8a56 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 = netdev_ip_csum_features;
+	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
@@ -1275,11 +1275,11 @@ 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) {
-		netdev_active_features_clear(port->dev, csums);
-		netdev_hw_features_clear(port->dev, 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);
+		netdev_active_features_set(port->dev, *csums);
+		netdev_hw_features_set(port->dev, *csums);
 	}
 }
 
@@ -1353,7 +1353,7 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
 
 out_set:
 	dev->mtu = mtu;
-	dev->wanted_features = dev->features;
+	netdev_wanted_features_copy(dev, dev->features);
 
 	netdev_update_features(dev);
 	return 0;
@@ -6852,7 +6852,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 	netdev_features_zero(features);
 	netdev_features_set_set(features, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
 				NETIF_F_IPV6_CSUM_BIT, NETIF_F_TSO_BIT);
-	dev->features = features;
+	netdev_active_features_copy(dev, features);
 	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	netdev_hw_features_set(dev, features);
 	netdev_hw_features_set_set(dev, NETIF_F_RXCSUM_BIT, NETIF_F_GRO_BIT,
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 0acfc16a08ae..026b44b195ed 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -644,7 +644,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 				   NETIF_F_RXHASH_BIT, NETIF_F_SG_BIT,
 				   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
 				   NETIF_F_GSO_UDP_L4_BIT);
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	/* Support TSO on tag interface */
 	netdev_vlan_features_set(netdev, netdev->features);
 	netdev_hw_features_set(netdev, netdev_tx_vlan_features);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ae3a18119fef..935f0d1f4550 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3897,7 +3897,7 @@ 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;
+	netdev_hw_features_copy(eth->netdev[id], *eth->soc->hw_features);
 	if (eth->hwlro)
 		netdev_hw_feature_add(eth->netdev[id], NETIF_F_LRO_BIT);
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 5c4570c3878e..879c96c4aa96 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3349,10 +3349,10 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 		dev->udp_tunnel_nic_info = &mlx4_udp_tunnels;
 	}
 
-	dev->vlan_features = dev->hw_features;
+	netdev_vlan_features_copy(dev, dev->hw_features);
 
 	netdev_hw_features_set_set(dev, NETIF_F_RXCSUM_BIT, NETIF_F_RXHASH_BIT);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 	netdev_active_features_set_set(dev, NETIF_F_HIGHDMA_BIT,
 				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				       NETIF_F_HW_VLAN_CTAG_RX_BIT,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 44a3ef2d8cd1..d0a9e69b24fd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3888,7 +3888,7 @@ int mlx5e_set_features(struct net_device *netdev,
 				    mlx5e_ktls_set_feature_rx);
 
 	if (err) {
-		netdev->features = oper_features;
+		netdev_active_features_copy(netdev, oper_features);
 		return -EINVAL;
 	}
 
@@ -4907,7 +4907,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 	    mlx5e_check_fragmented_striding_rq_cap(mdev))
 		netdev_vlan_feature_add(netdev, NETIF_F_LRO_BIT);
 
-	netdev->hw_features       = netdev->vlan_features;
+	netdev_hw_features_copy(netdev, netdev->vlan_features);
 	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);
@@ -4967,7 +4967,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 	if (mlx5_qos_is_supported(mdev))
 		netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
 
-	netdev->features          = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 
 	/* Defaults */
 	if (fcs_enabled)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index ccdc585b6e4c..58aab1182032 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1245,9 +1245,10 @@ static int mlxsw_sp_handle_feature(struct net_device *dev,
 static int mlxsw_sp_set_features(struct net_device *dev,
 				 const netdev_features_t *features)
 {
-	netdev_features_t oper_features = dev->features;
+	netdev_features_t oper_features;
 	int err = 0;
 
+	netdev_features_copy(oper_features, dev->features);
 	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_BIT,
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 594afe94874e..78de627c23c7 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -3400,7 +3400,7 @@ static int lan743x_pcidev_probe(struct pci_dev *pdev,
 	netdev_active_features_set_set(adapter->netdev, NETIF_F_SG_BIT,
 				       NETIF_F_TSO_BIT, NETIF_F_HW_CSUM_BIT,
 				       NETIF_F_RXCSUM_BIT);
-	adapter->netdev->hw_features = adapter->netdev->features;
+	netdev_hw_features_copy(adapter->netdev, adapter->netdev->features);
 
 	/* carrier off reporting is important to ethtool even BEFORE open */
 	netif_carrier_off(netdev);
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 888d494bbeda..778d81ae3014 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2086,7 +2086,7 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
 				   NETIF_F_IPV6_CSUM_BIT, NETIF_F_RXCSUM_BIT,
 				   NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
 				   NETIF_F_RXHASH_BIT);
-	ndev->features = ndev->hw_features;
+	netdev_active_features_copy(ndev, ndev->hw_features);
 	netdev_vlan_features_zero(ndev);
 
 	err = register_netdev(ndev);
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 08b6dc477810..81aa4254c814 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -2893,10 +2893,11 @@ 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_features_t features;
 	netdev_tx_t status;
 
+	netdev_features_copy(features, dev->features);
 	netdev_feature_del(NETIF_F_TSO6_BIT, features);
 	segs = skb_gso_segment(skb, &features);
 	if (IS_ERR(segs))
@@ -3863,13 +3864,13 @@ 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;
+	netdev_hw_features_copy(netdev, mgp->features);
 	netdev_hw_feature_add(netdev, NETIF_F_RXCSUM_BIT);
 
 	/* fake NETIF_F_HW_VLAN_CTAG_RX for good GRO performance */
 	netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HIGHDMA_BIT);
 
 	netdev_vlan_features_set(netdev, mgp->features);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 723ee0225c9f..fad9d4337eb5 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2401,9 +2401,9 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_NVGRE;
 	}
 	if (nn->cap & (NFP_NET_CFG_CTRL_VXLAN | NFP_NET_CFG_CTRL_NVGRE))
-		netdev->hw_enc_features = netdev->hw_features;
+		netdev_hw_enc_features_copy(netdev, netdev->hw_features);
 
-	netdev->vlan_features = netdev->hw_features;
+	netdev_vlan_features_copy(netdev, netdev->hw_features);
 
 	if (nn->cap & NFP_NET_CFG_CTRL_RXVLAN_ANY) {
 		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
@@ -2429,7 +2429,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 		nn->dp.ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
 	}
 
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 
 	if (nfp_app_has_tc(nn->app) && nn->port)
 		netdev_hw_feature_add(netdev, NETIF_F_HW_TC_BIT);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index bb310a247e4b..8f5433c3aac9 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -244,13 +244,13 @@ 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;
+	netdev_features_copy(lower_features, lower_dev->features);
 	if (netdev_features_intersects(lower_features, netdev_ip_csum_features))
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, lower_features);
 
 	netdev_features_copy(old_features, *features);
 	netdev_intersect_features(features, features, &lower_features);
-	tmp = NETIF_F_SOFT_FEATURES;
+	netdev_features_copy(tmp, NETIF_F_SOFT_FEATURES);
 	netdev_feature_add(NETIF_F_HW_TC_BIT, tmp);
 	netdev_features_mask(tmp, old_features);
 	netdev_features_set(*features, tmp);
@@ -367,9 +367,9 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 			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;
+		netdev_hw_enc_features_copy(netdev, netdev->hw_features);
 
-	netdev->vlan_features = netdev->hw_features;
+	netdev_vlan_features_copy(netdev, netdev->hw_features);
 
 	if (repr_cap & NFP_NET_CFG_CTRL_RXVLAN_ANY)
 		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
@@ -385,7 +385,7 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
 	if (repr_cap & NFP_NET_CFG_CTRL_RXQINQ)
 		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_STAG_RX_BIT);
 
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 
 	/* 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/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index b41db2d70812..f1c701f3f7bc 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
@@ -2523,7 +2523,7 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 	netdev_hw_features_zero(netdev);
 	netdev_hw_features_set_set(netdev, NETIF_F_RXCSUM_BIT,
 				   NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT);
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	pch_gbe_set_ethtool_ops(netdev);
 
 	/* MTU range: 46 - 10300 */
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index 0f391d75d9be..2cfae5d0b72b 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -907,7 +907,7 @@ void qede_vlan_mark_nonconfigured(struct qede_dev *edev)
 static void qede_set_features_reload(struct qede_dev *edev,
 				     struct qede_reload_args *args)
 {
-	edev->ndev->features = args->u.features;
+	netdev_active_features_copy(edev->ndev, args->u.features);
 }
 
 void qede_fix_features(struct net_device *dev, netdev_features_t *features)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 61cc3fb2e808..7531672c9f3a 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -892,10 +892,10 @@ static void qede_init_ndev(struct qede_dev *edev)
 					       NETIF_F_GSO_GRE_CSUM_BIT);
 	}
 
-	ndev->vlan_features = hw_features;
+	netdev_vlan_features_copy(ndev, hw_features);
 	netdev_vlan_features_set_set(ndev, NETIF_F_RXHASH_BIT,
 				     NETIF_F_RXCSUM_BIT, NETIF_F_HIGHDMA_BIT);
-	ndev->features = hw_features;
+	netdev_active_features_copy(ndev, hw_features);
 	netdev_active_features_set_set(ndev, NETIF_F_RXHASH_BIT,
 				       NETIF_F_RXCSUM_BIT,
 				       NETIF_F_HW_VLAN_CTAG_RX_BIT,
@@ -903,7 +903,7 @@ static void qede_init_ndev(struct qede_dev *edev)
 				       NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				       NETIF_F_HW_VLAN_CTAG_TX_BIT);
 
-	ndev->hw_features = hw_features;
+	netdev_hw_features_copy(ndev, hw_features);
 
 	/* MTU range: 46 - 9600 */
 	ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 94b5b96ad9fb..205427e0b848 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2318,7 +2318,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev)
 		netdev->udp_tunnel_nic_info = &qlcnic_udp_tunnels;
 	}
 
-	netdev->hw_features = netdev->features;
+	netdev_hw_features_copy(netdev, netdev->features);
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 	netdev->irq = adapter->msix_entries[0].vector;
 
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 3a5f9c93edb8..0cc8ede831ba 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -673,7 +673,7 @@ static int emac_probe(struct platform_device *pdev)
 				       NETIF_F_TSO_BIT, NETIF_F_TSO6_BIT,
 				       NETIF_F_HW_VLAN_CTAG_RX_BIT,
 				       NETIF_F_HW_VLAN_CTAG_TX_BIT);
-	netdev->hw_features = netdev->features;
+	netdev_hw_features_copy(netdev, netdev->features);
 
 	netdev_vlan_features_set_set(netdev, NETIF_F_SG_BIT,
 				     NETIF_F_HW_CSUM_BIT, NETIF_F_TSO_BIT,
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index c8f1622a230f..567d7393c21f 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -1013,7 +1013,7 @@ static int rtl8139_init_one(struct pci_dev *pdev,
 	 */
 	netdev_active_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				       NETIF_F_HIGHDMA_BIT);
-	dev->vlan_features = dev->features;
+	netdev_vlan_features_copy(dev, dev->features);
 
 	netdev_hw_feature_add(dev, NETIF_F_RXALL_BIT);
 	netdev_hw_feature_add(dev, NETIF_F_RXFCS_BIT);
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 5f99a06ef122..382f06aeb3da 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -2648,8 +2648,8 @@ static int ravb_probe(struct platform_device *pdev)
 	info = of_device_get_match_data(&pdev->dev);
 
 	netdev_feature_add(NETIF_F_RXCSUM_BIT, ravb_default_features);
-	ndev->features = *info->net_features;
-	ndev->hw_features = *info->net_hw_features;
+	netdev_active_features_copy(ndev, *info->net_features);
+	netdev_hw_features_copy(ndev, *info->net_hw_features);
 
 	reset_control_deassert(rstc);
 	pm_runtime_enable(&pdev->dev);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index cf027162da71..564103f1dd26 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -3296,7 +3296,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 	if (mdp->cd->rx_csum) {
 		netdev_active_features_zero(ndev);
 		netdev_active_feature_add(ndev, NETIF_F_RXCSUM_BIT);
-		ndev->hw_features = ndev->features;
+		netdev_hw_features_copy(ndev, ndev->features);
 	}
 
 	/* set function */
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 3aefa37ae5ce..1b8dccbffccd 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1368,7 +1368,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
 		netdev_feature_add(NETIF_F_TSO_BIT, hw_enc_features);
 		netdev_active_features_set(efx->net_dev, encap_tso_features);
 	}
-	efx->net_dev->hw_enc_features = hw_enc_features;
+	netdev_hw_enc_features_copy(efx->net_dev, hw_enc_features);
 
 	/* don't fail init if RSS setup doesn't work */
 	rc = efx->type->rx_push_rss_config(efx, false,
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index 670e30425447..e4423ec042b9 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -368,8 +368,8 @@ void efx_start_monitor(struct efx_nic *efx)
  */
 static void efx_start_datapath(struct efx_nic *efx)
 {
-	netdev_features_t old_features = efx->net_dev->features;
 	bool old_rx_scatter = efx->rx_scatter;
+	netdev_features_t old_features;
 	size_t rx_buf_len;
 
 	/* Calculate the rx buffer allocation parameters required to
@@ -411,6 +411,7 @@ static void efx_start_datapath(struct efx_nic *efx)
 			  efx->rx_dma_len, efx->rx_page_buf_step,
 			  efx->rx_bufs_per_page, efx->rx_pages_per_batch);
 
+	netdev_features_copy(old_features, efx->net_dev->features);
 	/* Restore previously fixed features in hw_features and remove
 	 * features which are fixed now
 	 */
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c
index 438f8a453f32..13a4463fb9d4 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -587,8 +587,8 @@ static int ef4_probe_channels(struct ef4_nic *efx)
  */
 static void ef4_start_datapath(struct ef4_nic *efx)
 {
-	netdev_features_t old_features = efx->net_dev->features;
 	bool old_rx_scatter = efx->rx_scatter;
+	netdev_features_t old_features;
 	struct ef4_tx_queue *tx_queue;
 	struct ef4_rx_queue *rx_queue;
 	struct ef4_channel *channel;
@@ -632,6 +632,7 @@ static void ef4_start_datapath(struct ef4_nic *efx)
 			  efx->rx_dma_len, efx->rx_page_buf_step,
 			  efx->rx_bufs_per_page, efx->rx_pages_per_batch);
 
+	netdev_features_copy(old_features, efx->net_dev->features);
 	/* Restore previously fixed features in hw_features and remove
 	 * features which are fixed now
 	 */
diff --git a/drivers/net/ethernet/sfc/siena/efx_common.c b/drivers/net/ethernet/sfc/siena/efx_common.c
index fc3bf13d4b67..58bd3df2e41e 100644
--- a/drivers/net/ethernet/sfc/siena/efx_common.c
+++ b/drivers/net/ethernet/sfc/siena/efx_common.c
@@ -368,8 +368,8 @@ void efx_siena_start_monitor(struct efx_nic *efx)
  */
 static void efx_start_datapath(struct efx_nic *efx)
 {
-	netdev_features_t old_features = efx->net_dev->features;
 	bool old_rx_scatter = efx->rx_scatter;
+	netdev_features_t old_features;
 	size_t rx_buf_len;
 
 	/* Calculate the rx buffer allocation parameters required to
@@ -411,6 +411,7 @@ static void efx_start_datapath(struct efx_nic *efx)
 			  efx->rx_dma_len, efx->rx_page_buf_step,
 			  efx->rx_bufs_per_page, efx->rx_pages_per_batch);
 
+	netdev_features_copy(old_features, efx->net_dev->features);
 	/* Restore previously fixed features in hw_features and remove
 	 * features which are fixed now
 	 */
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 05db1d69ae2a..928bbc48c5d3 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -2104,7 +2104,7 @@ static int netsec_probe(struct platform_device *pdev)
 				       NETIF_F_RXCSUM_BIT, NETIF_F_GSO_BIT,
 				       NETIF_F_IP_CSUM_BIT,
 				       NETIF_F_IPV6_CSUM_BIT);
-	ndev->hw_features = ndev->features;
+	netdev_hw_features_copy(ndev, ndev->features);
 
 	priv->rx_cksum_offload_flag = true;
 
diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c
index eaf2b6d8c187..1ed4eabcd9ae 100644
--- a/drivers/net/ethernet/sun/ldmvsw.c
+++ b/drivers/net/ethernet/sun/ldmvsw.c
@@ -248,7 +248,7 @@ static struct net_device *vsw_alloc_netdev(u8 hwaddr[],
 
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_set(dev, NETIF_F_HW_CSUM_BIT, NETIF_F_SG_BIT);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 
 	/* MTU range: 68 - 65535 */
 	dev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index ccd06f237ef9..bb0fb1e6f4ea 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -2993,7 +2993,7 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev_hw_features_zero(dev);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_RXCSUM_BIT);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 	if (pci_using_dac)
 		netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index 469a1f9cc2fc..9b08ad7ba286 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -314,10 +314,10 @@ 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_ALL_TSO;
+	netdev_hw_features_copy(dev, NETIF_F_ALL_TSO);
 	netdev_hw_features_set_set(dev, NETIF_F_TSO_BIT, NETIF_F_GSO_BIT,
 				   NETIF_F_HW_CSUM_BIT, NETIF_F_SG_BIT);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 
 	/* MTU range: 68 - 65535 */
 	dev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c
index b0239b704e79..e9dd32e3b8b6 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.c
+++ b/drivers/net/ethernet/sun/sunvnet_common.c
@@ -1228,7 +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;
+	netedv_features_t features;
 	int proto = IPPROTO_IP;
 
 	if (skb->protocol == htons(ETH_P_IP))
@@ -1275,6 +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;
 	}
+	netdev_features_copy(features, dev->features);
 	netdev_feature_del(NETIF_F_TSO_BIT, features);
 	segs = skb_gso_segment(skb, &features);
 	if (IS_ERR(segs))
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
index d81a3b69ec47..476293d90bfc 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
@@ -179,11 +179,11 @@ 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_copy(netdev, netdev_general_tso_features);
 		netdev_hw_feature_add(netdev, NETIF_F_SG_BIT);
 		netdev_hw_features_set(netdev, netdev_ip_csum_features);
 	} else if (pdata->hw_feat.tx_coe) {
-		netdev->hw_features = netdev_ip_csum_features;
+		netdev_hw_features_copy(netdev, netdev_ip_csum_features);
 	}
 
 	if (pdata->hw_feat.rx_coe) {
@@ -203,7 +203,7 @@ static int xlgmac_init(struct xlgmac_pdata *pdata)
 		netdev_hw_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
 	netdev_active_features_set(netdev, netdev->hw_features);
-	pdata->netdev_features = netdev->features;
+	netdev_features_copy(pdata->netdev_features, netdev->features);
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index a64c450ce149..86c3d09c194c 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1982,7 +1982,7 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 	netdev_hw_features_set_set(port->ndev, NETIF_F_SG_BIT,
 				   NETIF_F_RXCSUM_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_HW_TC_BIT);
-	port->ndev->features = port->ndev->hw_features;
+	netdev_active_features_copy(port->ndev, port->ndev->hw_features);
 	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;
diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c
index 9a513869ab66..b27f9a365b13 100644
--- a/drivers/net/ethernet/ti/netcp_core.c
+++ b/drivers/net/ethernet/ti/netcp_core.c
@@ -1977,7 +1977,7 @@ static int netcp_create_interface(struct netcp_device *netcp_device,
 
 	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;
+	netdev_hw_features_copy(ndev, ndev->features);
 	netdev_vlan_feature_add(ndev, NETIF_F_SG_BIT);
 
 	/* MTU range: 68 - 9486 */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index c96811972969..56db2c150be8 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -2374,7 +2374,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
 	if (ndev->needed_headroom < vf_netdev->needed_headroom)
 		ndev->needed_headroom = vf_netdev->needed_headroom;
 
-	vf_netdev->wanted_features = ndev->features;
+	netdev_wanted_features_copy(vf_netdev, ndev->features);
 	netdev_update_features(vf_netdev);
 
 	prog = netvsc_xdp_get(netvsc_dev);
@@ -2540,11 +2540,11 @@ 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;
+	netdev_active_features_copy(net, net->hw_features);
 	netdev_active_features_set_set(net, NETIF_F_HIGHDMA_BIT,
 				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				       NETIF_F_HW_VLAN_CTAG_RX_BIT);
-	net->vlan_features = net->features;
+	netdev_vlan_features_copy(net, net->features);
 
 	netdev_lockdep_set_classes(net);
 
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 31d5e203e035..66a892932f71 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -564,7 +564,7 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
 
 	ipvlan->phy_dev = phy_dev;
 	ipvlan->dev = dev;
-	ipvlan->sfeatures = IPVLAN_FEATURES;
+	netdev_features_copy(ipvlan->sfeatures, IPVLAN_FEATURES);
 	if (!tb[IFLA_MTU])
 		ipvlan_adjust_mtu(ipvlan, phy_dev);
 	INIT_LIST_HEAD(&ipvlan->addrs);
@@ -1024,11 +1024,11 @@ static void __init ipvlan_features_init(void)
 				NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				NETIF_F_GSO_ROBUST_BIT);
 
-	ipvlan_always_on_features = ipvlan_offload_features;
+	netdev_features_copy(ipvlan_always_on_features, ipvlan_offload_features);
 	netdev_features_set_set(ipvlan_always_on_features, NETIF_F_LLTX_BIT,
 				NETIF_F_VLAN_CHALLENGED_BIT);
 
-	ipvlan_features = NETIF_F_ALL_TSO;
+	netdev_features_copy(ipvlan_features, NETIF_F_ALL_TSO);
 	netdev_features_set_set(ipvlan_features, NETIF_F_SG_BIT,
 				NETIF_F_HW_CSUM_BIT,
 				NETIF_F_HIGHDMA_BIT,
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index f5f5cbb29766..bc35b5e2736f 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -176,8 +176,8 @@ static void gen_lo_setup(struct net_device *dev,
 	dev->flags		= IFF_LOOPBACK;
 	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_GSO_SOFTWARE;
+	netdev_hw_features_copy(dev, NETIF_F_GSO_SOFTWARE);
+	netdev_active_features_copy(dev, NETIF_F_GSO_SOFTWARE);
 	netdev_active_features_set_set(dev, NETIF_F_SG_BIT,
 				       NETIF_F_FRAGLIST_BIT,
 				       NETIF_F_HW_CSUM_BIT, NETIF_F_RXCSUM_BIT,
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 513e1ff7a2a0..3d82c7cc9f9f 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -4409,7 +4409,7 @@ static void __init macsec_features_init(void)
 	netdev_features_set_set(sw_macsec_features, NETIF_F_SG_BIT,
 				NETIF_F_HIGHDMA_BIT, NETIF_F_FRAGLIST_BIT);
 
-	macsec_no_inherit_features = NETIF_F_VLAN_FEATURES;
+	netdev_features_copy(macsec_no_inherit_features, NETIF_F_VLAN_FEATURES);
 	netdev_feature_add(NETIF_F_HW_MACSEC_BIT, macsec_no_inherit_features);
 }
 
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 21071335c0ac..1c9068be8569 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1077,10 +1077,11 @@ static void macvlan_fix_features(struct net_device *dev,
 				 netdev_features_t *features)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
-	netdev_features_t lowerdev_features = vlan->lowerdev->features;
+	netdev_features_t lowerdev_features;
 	netdev_features_t mask;
 	netdev_features_t tmp;
 
+	netdev_features_copy(lowerdev_features, vlan->lowerdev->features);
 	netdev_features_set(*features, NETIF_F_ALL_FOR_ALL);
 	netdev_features_fill(tmp);
 	netdev_features_clear(tmp, MACVLAN_FEATURES);
@@ -1826,7 +1827,7 @@ static void __init macvlan_features_init(void)
 				NETIF_F_HW_CSUM_BIT,
 				NETIF_F_GSO_ROBUST_BIT);
 
-	macvlan_always_on_features = macvlan_offload_features;
+	netdev_features_copy(macvlan_always_on_features, macvlan_offload_features);
 	netdev_features_set_set(macvlan_always_on_features, NETIF_F_LLTX_BIT);
 
 	netdev_features_set_set(macvlan_features,
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index d0b72fd696d3..0ec4113af572 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -383,14 +383,15 @@ 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 enc_features  = FAILOVER_ENC_FEATURES;
 	unsigned short max_hard_header_len = ETH_HLEN;
 	unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
 					IFF_XMIT_DST_RELEASE_PERM;
 	struct net_failover_info *nfo_info = netdev_priv(dev);
 	struct net_device *primary_dev, *standby_dev;
 	netdev_features_t vlan_features;
+	netdev_features_t enc_features;
 
+	netdev_features_copy(enc_features, FAILOVER_ENC_FEATURES);
 	netdev_features_and(vlan_features, FAILOVER_VLAN_FEATURES,
 			    NETIF_F_ALL_FOR_ALL);
 
@@ -422,7 +423,7 @@ static void net_failover_compute_features(struct net_device *dev)
 			max_hard_header_len = standby_dev->hard_header_len;
 	}
 
-	dev->vlan_features = vlan_features;
+	netdev_vlan_features_copy(dev, vlan_features);
 	netdev_hw_enc_features_or(dev, enc_features, NETIF_F_GSO_ENCAP_ALL);
 	dev->hard_header_len = max_hard_header_len;
 
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index a116b21ae741..d67083d30f4d 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -426,7 +426,7 @@ static int ntb_netdev_probe(struct device *client_dev)
 
 	ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
-	ndev->hw_features = ndev->features;
+	netdev_hw_features_copy(ndev, ndev->features);
 	ndev->watchdog_timeo = msecs_to_jiffies(NTB_TX_TIMEOUT_MS);
 
 	eth_random_addr(ndev->perm_addr);
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index a13c0479079f..fcc9ec6895a5 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -947,7 +947,7 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
 		return -ENOLINK;
 
 	netdev_features_zero(feature_mask);
-	features = tap->dev->features;
+	netdev_features_copy(features, tap->dev->features);
 
 	if (arg & TUN_F_CSUM) {
 		netdev_feature_add(NETIF_F_HW_CSUM_BIT, feature_mask);
@@ -983,7 +983,7 @@ static int set_offload(struct tap_queue *q, unsigned long arg)
 	/* tap_features are the same as features on tun/tap and
 	 * reflect user expectations.
 	 */
-	tap->tap_features = feature_mask;
+	netdev_features_copy(tap->tap_features, feature_mask);
 	if (tap->update_features)
 		tap->update_features(tap, &features);
 
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 1f9642b400ec..c32e8760e2d3 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -989,12 +989,13 @@ 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 enc_features  = TEAM_ENC_FEATURES;
 	unsigned short max_hard_header_len = ETH_HLEN;
 	unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
 					IFF_XMIT_DST_RELEASE_PERM;
 	netdev_features_t vlan_features;
+	netdev_features_t enc_features;
 
+	netdev_features_copy(enc_features, TEAM_ENC_FEATURES);
 	netdev_features_and(vlan_features, TEAM_VLAN_FEATURES,
 			    NETIF_F_ALL_FOR_ALL);
 
@@ -1014,7 +1015,7 @@ static void __team_compute_features(struct team *team)
 	}
 	rcu_read_unlock();
 
-	team->dev->vlan_features = vlan_features;
+	netdev_vlan_features_copy(team->dev, vlan_features);
 	netdev_hw_enc_features_or(team->dev, enc_features,
 				  NETIF_F_GSO_ENCAP_ALL);
 	netdev_hw_enc_features_set(team->dev, netdev_tx_vlan_features);
@@ -2173,7 +2174,7 @@ static void team_setup(struct net_device *dev)
 	/* Don't allow team devices to change network namespaces. */
 	netdev_active_feature_add(dev, NETIF_F_NETNS_LOCAL_BIT);
 
-	dev->hw_features = TEAM_VLAN_FEATURES;
+	netdev_hw_features_copy(dev, TEAM_VLAN_FEATURES);
 	netdev_hw_feature_add(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT);
 	netdev_hw_feature_add(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
@@ -2875,14 +2876,14 @@ static void team_nl_fini(void)
 
 static void __init team_features_init(void)
 {
-	team_vlan_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(team_vlan_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(team_vlan_features,
 				NETIF_F_HW_CSUM_BIT,
 				NETIF_F_SG_BIT,
 				NETIF_F_FRAGLIST_BIT,
 				NETIF_F_HIGHDMA_BIT,
 				NETIF_F_LRO_BIT);
-	team_enc_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(team_enc_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(team_enc_features, NETIF_F_HW_CSUM_BIT,
 				NETIF_F_SG_BIT, NETIF_F_RXCSUM_BIT);
 }
diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c
index cd446c8242b4..a259f8da43ec 100644
--- a/drivers/net/thunderbolt.c
+++ b/drivers/net/thunderbolt.c
@@ -1278,12 +1278,12 @@ 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_ALL_TSO;
+	netdev_hw_features_copy(dev, NETIF_F_ALL_TSO);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT,
 				   NETIF_F_GRO_BIT,
 				   NETIF_F_IP_CSUM_BIT,
 				   NETIF_F_IPV6_CSUM_BIT);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_HIGHDMA_BIT);
 	dev->hard_header_len += sizeof(struct thunderbolt_ip_frame_header);
 
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index d2e6bfb5edd4..689f704d96ba 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -991,12 +991,12 @@ static int tun_net_init(struct net_device *dev)
 
 	tun_flow_init(tun);
 
-	dev->hw_features = TUN_USER_FEATURES;
+	netdev_hw_features_copy(dev, TUN_USER_FEATURES);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT,
 				   NETIF_F_FRAGLIST_BIT,
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				   NETIF_F_HW_VLAN_STAG_TX_BIT);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netdev_vlan_features_andnot(dev, dev->features,
 				    netdev_tx_vlan_features);
@@ -2889,7 +2889,7 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
 	if (arg)
 		return -EINVAL;
 
-	tun->set_features = features;
+	netdev_features_copy(tun->set_features, 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 227ca5943007..0194eefb4581 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -3478,7 +3478,7 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
 		netdev_active_feature_add(dev->net,
 					  NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 
-	dev->net->hw_features = dev->net->features;
+	netdev_hw_features_copy(dev->net, dev->net->features);
 
 	ret = lan78xx_setup_irq_domain(dev);
 	if (ret < 0) {
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index d2936ac84774..c3fae3b595f8 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2106,10 +2106,11 @@ static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb,
 				  struct sk_buff_head *list)
 {
 	if (skb_shinfo(skb)->gso_size) {
-		netdev_features_t features = tp->netdev->features;
 		struct sk_buff *segs, *seg, *next;
 		struct sk_buff_head seg_list;
+		netdev_features_t features;
 
+		netdev_features_copy(features, tp->netdev->features);
 		netdev_features_clear_set(features, NETIF_F_SG_BIT,
 					  NETIF_F_IPV6_CSUM_BIT,
 					  NETIF_F_TSO6_BIT);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 8c516efa818d..c34dd2aefa51 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1651,9 +1651,9 @@ 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->mpls_features = NETIF_F_GSO_SOFTWARE;
+	netdev_hw_features_copy(dev, veth_features);
+	netdev_hw_enc_features_copy(dev, veth_features);
+	netdev_mpls_features_copy(dev, NETIF_F_GSO_SOFTWARE);
 	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 d4e9ffa9695e..be9febc83bc3 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3761,7 +3761,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS))
 		netdev_hw_feature_add(dev, NETIF_F_GRO_HW_BIT);
 
-	dev->vlan_features = dev->features;
+	netdev_vlan_features_copy(dev, dev->features);
 
 	/* MTU range: 68 - 65535 */
 	dev->min_mtu = MIN_MTU;
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index e9671df05780..846b6df31e34 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3385,7 +3385,7 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
 
 	netdev_vlan_features_andnot(netdev, netdev->hw_features,
 				    netdev_ctag_vlan_offload_features);
-	netdev->features = netdev->hw_features;
+	netdev_active_features_copy(netdev, netdev->hw_features);
 	netdev_active_feature_add(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
 }
 
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index c7fd71f66b2e..366ef17c4640 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1695,8 +1695,8 @@ static void vrf_setup(struct net_device *dev)
 				       NETIF_F_FRAGLIST_BIT,
 				       NETIF_F_HIGHDMA_BIT);
 
-	dev->hw_features = dev->features;
-	dev->hw_enc_features = dev->features;
+	netdev_hw_features_copy(dev, dev->features);
+	netdev_hw_enc_features_copy(dev, dev->features);
 
 	/* default to no qdisc; user can add if desired */
 	dev->priv_flags |= IFF_NO_QUEUE;
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index e179c780b761..0a520055ea32 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3169,7 +3169,7 @@ static void vxlan_setup(struct net_device *dev)
 				       NETIF_F_RXCSUM_BIT);
 	netdev_active_features_set(dev, NETIF_F_GSO_SOFTWARE);
 
-	dev->vlan_features = dev->features;
+	netdev_vlan_features_copy(dev, dev->features);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_FRAGLIST_BIT, NETIF_F_RXCSUM_BIT);
 	netdev_hw_features_set(dev, NETIF_F_GSO_SOFTWARE);
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index 04145af755c9..9561d80f5d30 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -293,7 +293,7 @@ static void wg_setup(struct net_device *dev)
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
 	dev->priv_flags |= IFF_NO_QUEUE;
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
-	wg_netdev_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(wg_netdev_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(wg_netdev_features, NETIF_F_HW_CSUM_BIT,
 				NETIF_F_RXCSUM_BIT, NETIF_F_SG_BIT,
 				NETIF_F_GSO_BIT, NETIF_F_HIGHDMA_BIT);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index e8588fa8e5df..5915ef98c611 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -1848,12 +1848,13 @@ static void __init iwl_features_init(void)
 				NETIF_F_HW_CSUM_BIT,
 				NETIF_F_TSO_BIT,
 				NETIF_F_TSO6_BIT);
-	iwl_dev_22000_comm_features = iwl_tx_csum_features;
+	netdev_features_copy(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_features_copy(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;
+	netdev_features_copy(iwl_dev_9000_comm_features,
+			     iwl_dev_22000_comm_features);
 }
 
 static int __init iwl_drv_init(void)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 4ed95b179b45..f44e1f687045 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -891,7 +891,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
 	netdev_features_t netdev_flags;
 	u8 tid;
 
-	netdev_flags = NETIF_F_CSUM_MASK;
+	netdev_features_copy(netdev_flags, NETIF_F_CSUM_MASK);
 	netdev_feature_add(NETIF_F_SG_BIT, netdev_flags);
 
 	snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) +
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 62677a757409..16b8bbe5f4f9 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -525,7 +525,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 	netdev_hw_features_set_set(dev, 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);
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 	netdev_active_feature_add(dev, NETIF_F_RXCSUM_BIT);
 	dev->ethtool_ops = &xenvif_ethtool_ops;
 
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 811e79c9f59c..efb88f979494 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -1814,7 +1814,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
 	else
 		devmap->features &= ~feature;
 	if (devmap->device)
-		devmap->device->features = devmap->features;
+		netdev_active_features_copy(devmap->device, devmap->features);
 	spin_unlock(&dasd_devmap_lock);
 	return 0;
 }
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 6695f8dda8f4..e4d04dd0bdb9 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6744,7 +6744,7 @@ void qeth_enable_hw_features(struct net_device *dev)
 	struct qeth_card *card = dev->ml_priv;
 	netdev_features_t features;
 
-	features = dev->features;
+	netdev_features_copy(features, dev->features);
 	/* force-off any feature that might need an IPA sequence.
 	 * netdev_update_features() will restart them.
 	 */
diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c
index c1140efa3413..afe06a8e169d 100644
--- a/drivers/staging/qlge/qlge_main.c
+++ b/drivers/staging/qlge/qlge_main.c
@@ -4579,8 +4579,8 @@ static int qlge_probe(struct pci_dev *pdev,
 				   NETIF_F_HW_VLAN_CTAG_RX_BIT,
 				   NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
 				   NETIF_F_RXCSUM_BIT);
-	ndev->features = ndev->hw_features;
-	ndev->vlan_features = ndev->hw_features;
+	netdev_active_features_copy(ndev, ndev->hw_features);
+	netdev_vlan_features_copy(ndev, ndev->hw_features);
 	/* vlan gets same features (except vlan filter) */
 	netdev_vlan_features_clear(ndev, netdev_ctag_vlan_features);
 
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 321adf534177..6078a52de35e 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -584,7 +584,7 @@ static int vlan_dev_init(struct net_device *dev)
 	netdev_vlan_features_andnot(dev, real_dev->vlan_features,
 				    NETIF_F_ALL_FCOE);
 	vlan_tnl_features(real_dev, &dev->hw_enc_features);
-	dev->mpls_features = real_dev->mpls_features;
+	netdev_mpls_features_copy(dev, real_dev->mpls_features);
 
 	/* ipv6 shared card related stuff */
 	dev->dev_id = real_dev->dev_id;
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index fafcc67ca3bc..7083fd686e1b 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -490,17 +490,17 @@ void br_dev_setup(struct net_device *dev)
 	SET_NETDEV_DEVTYPE(dev, &br_type);
 	dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE;
 
-	common_features = NETIF_F_GSO_MASK;
+	netdev_features_copy(common_features, NETIF_F_GSO_MASK);
 	netdev_features_set_set(common_features, NETIF_F_SG_BIT,
 				NETIF_F_FRAGLIST_BIT, NETIF_F_HIGHDMA_BIT,
 				NETIF_F_HW_CSUM_BIT);
-	dev->features = common_features;
+	netdev_active_features_copy(dev, common_features);
 	netdev_active_features_set_set(dev, NETIF_F_LLTX_BIT,
 				       NETIF_F_NETNS_LOCAL_BIT,
 				       NETIF_F_HW_VLAN_CTAG_TX_BIT,
 				       NETIF_F_HW_VLAN_STAG_TX_BIT);
 	netdev_hw_features_or(dev, common_features, netdev_tx_vlan_features);
-	dev->vlan_features = common_features;
+	netdev_vlan_features_copy(dev, common_features);
 
 	br->dev = dev;
 	spin_lock_init(&br->lock);
diff --git a/net/core/dev.c b/net/core/dev.c
index bed372ecef65..d854c643d2b2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9561,9 +9561,10 @@ static void netdev_sync_upper_features(struct net_device *lower,
 				       struct net_device *upper,
 				       netdev_features_t *features)
 {
-	netdev_features_t upper_disables = NETIF_F_UPPER_DISABLES;
+	netdev_features_t upper_disables;
 	int feature_bit;
 
+	netdev_features_copy(upper_disables, NETIF_F_UPPER_DISABLES);
 	for_each_netdev_feature(upper_disables, feature_bit) {
 		if (!netdev_wanted_feature_test(upper, feature_bit) &&
 		    netdev_feature_test(feature_bit, *features)) {
@@ -9577,9 +9578,10 @@ static void netdev_sync_upper_features(struct net_device *lower,
 static void netdev_sync_lower_features(struct net_device *upper,
 	struct net_device *lower, netdev_features_t *features)
 {
-	netdev_features_t upper_disables = NETIF_F_UPPER_DISABLES;
+	netdev_features_t upper_disables;
 	int feature_bit;
 
+	netdev_features_copy(upper_disables, NETIF_F_UPPER_DISABLES);
 	for_each_netdev_feature(upper_disables, feature_bit) {
 		if (!netdev_feature_test(feature_bit, *features) &&
 		    netdev_active_feature_test(lower, feature_bit)) {
@@ -9637,7 +9639,7 @@ static void netdev_fix_features(struct net_device *dev,
 		netdev_feature_del(NETIF_F_TSO_MANGLEID_BIT, *features);
 
 	/* TSO ECN requires that TSO is present as well. */
-	tmp = NETIF_F_ALL_TSO;
+	netdev_features_copy(tmp, NETIF_F_ALL_TSO);
 	netdev_feature_del(NETIF_F_TSO_ECN_BIT, tmp);
 	if (!netdev_features_intersects(*features, tmp) &&
 	    netdev_feature_test(NETIF_F_TSO_ECN_BIT, *features))
@@ -9769,7 +9771,7 @@ int __netdev_update_features(struct net_device *dev)
 			 * but *after* calling udp_tunnel_drop_rx_info.
 			 */
 			if (netdev_feature_test(NETIF_F_RX_UDP_TUNNEL_PORT_BIT, features)) {
-				dev->features = features;
+				netdev_active_features_copy(dev, features);
 				udp_tunnel_get_rx_info(dev);
 			} else {
 				udp_tunnel_drop_rx_info(dev);
@@ -9778,7 +9780,7 @@ int __netdev_update_features(struct net_device *dev)
 
 		if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, diff)) {
 			if (netdev_feature_test(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) {
-				dev->features = features;
+				netdev_active_features_copy(dev, features);
 				err |= vlan_get_rx_ctag_filter_info(dev);
 			} else {
 				vlan_drop_rx_ctag_filter_info(dev);
@@ -9787,14 +9789,14 @@ int __netdev_update_features(struct net_device *dev)
 
 		if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT, diff)) {
 			if (netdev_feature_test(NETIF_F_HW_VLAN_STAG_FILTER_BIT, features)) {
-				dev->features = features;
+				netdev_active_features_copy(dev, features);
 				err |= vlan_get_rx_stag_filter_info(dev);
 			} else {
 				vlan_drop_rx_stag_filter_info(dev);
 			}
 		}
 
-		dev->features = features;
+		netdev_active_features_copy(dev, features);
 	}
 
 	return err < 0 ? 0 : 1;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index fd54b586f851..02334524cb64 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2291,7 +2291,7 @@ void dsa_slave_setup_tagger(struct net_device *slave)
 
 	p->xmit = cpu_dp->tag_ops->xmit;
 
-	slave->features = master->vlan_features;
+	netdev_active_features_copy(slave, master->vlan_features);
 	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);
@@ -2372,7 +2372,7 @@ int dsa_slave_create(struct dsa_port *port)
 
 	SET_NETDEV_DEV(slave_dev, port->ds->dev);
 	slave_dev->dev.of_node = port->dn;
-	slave_dev->vlan_features = master->vlan_features;
+	netdev_vlan_features_copy(slave_dev, master->vlan_features);
 
 	p = netdev_priv(slave_dev);
 	slave_dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index c4154666e82a..12bf982a5d2d 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -239,7 +239,7 @@ static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd)
 	switch (eth_cmd) {
 	case ETHTOOL_GTXCSUM:
 	case ETHTOOL_STXCSUM:
-		tmp = NETIF_F_CSUM_MASK;
+		netdev_features_copy(tmp, NETIF_F_CSUM_MASK);
 		netdev_feature_add(NETIF_F_FCOE_CRC_BIT, tmp);
 		netdev_feature_add(NETIF_F_SCTP_CRC_BIT, tmp);
 		return tmp;
@@ -2818,7 +2818,7 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr,
 		if (rc < 0)
 			goto out;
 	}
-	old_features = dev->features;
+	netdev_features_copy(old_features, dev->features);
 
 	switch (ethcmd) {
 	case ETHTOOL_GSET:
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index 7d89d3a72e54..a85be08ff4b8 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -446,12 +446,12 @@ void hsr_dev_setup(struct net_device *dev)
 
 	dev->needs_free_netdev = true;
 
-	dev->hw_features = NETIF_F_GSO_MASK;
+	netdev_hw_features_copy(dev, NETIF_F_GSO_MASK);
 	netdev_hw_features_set_set(dev, NETIF_F_SG_BIT, NETIF_F_FRAGLIST_BIT,
 				   NETIF_F_HIGHDMA_BIT, NETIF_F_HW_CSUM_BIT,
 				   NETIF_F_HW_VLAN_CTAG_TX_BIT);
 
-	dev->features = dev->hw_features;
+	netdev_active_features_copy(dev, dev->hw_features);
 
 	/* Prevent recursive tx locking */
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index fc7835e24717..3ce0643263f9 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -368,7 +368,7 @@ static void ipip_tunnel_setup(struct net_device *dev)
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netif_keep_dst(dev);
 
-	ipip_features		= NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(ipip_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(ipip_features, NETIF_F_SG_BIT,
 				NETIF_F_FRAGLIST_BIT,
 				NETIF_F_HIGHDMA_BIT,
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 86c7052a3dd3..79c6b3b0c7cc 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1833,7 +1833,7 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
 	netif_keep_dst(dev);
 
-	ipxipx_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(ipxipx_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(ipxipx_features, NETIF_F_SG_BIT,
 				NETIF_F_FRAGLIST_BIT,
 				NETIF_F_HIGHDMA_BIT,
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 15b0a28d339b..b4468a5a039b 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1426,7 +1426,7 @@ 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_copy(sit_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(sit_features, NETIF_F_SG_BIT,
 				NETIF_F_FRAGLIST_BIT,
 				NETIF_F_HIGHDMA_BIT,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index f2f55129d639..3b58a56289f9 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1537,7 +1537,7 @@ EXPORT_SYMBOL(ieee80211_free_hw);
 
 static void __init ieee80211_features_init(void)
 {
-	mac80211_tx_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(mac80211_tx_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(mac80211_tx_features,
 				NETIF_F_IP_CSUM_BIT,
 				NETIF_F_IPV6_CSUM_BIT,
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index bf332718aeab..2f3c8d5bb486 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -117,10 +117,10 @@ static void do_setup(struct net_device *netdev)
 				       NETIF_F_HIGHDMA_BIT,
 				       NETIF_F_HW_CSUM_BIT);
 
-	netdev->vlan_features = netdev->features;
-	netdev->hw_enc_features = netdev->features;
+	netdev_vlan_features_copy(netdev, netdev->features);
+	netdev_hw_enc_features_copy(netdev, netdev->features);
 	netdev_active_features_set(netdev, netdev_tx_vlan_features);
-	netdev->hw_features = netdev->features;
+	netdev_hw_features_copy(netdev, netdev->features);
 	netdev_hw_feature_del(netdev, NETIF_F_LLTX_BIT);
 
 	eth_hw_addr_random(netdev);
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 3d5b8c6377d7..90df017678a2 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -590,7 +590,7 @@ static int xfrmi_dev_init(struct net_device *dev)
 		return err;
 	}
 
-	xfrmi_features = NETIF_F_GSO_SOFTWARE;
+	netdev_features_copy(xfrmi_features, NETIF_F_GSO_SOFTWARE);
 	netdev_features_set_set(xfrmi_features, NETIF_F_SG_BIT,
 				NETIF_F_FRAGLIST_BIT, NETIF_F_HW_CSUM_BIT);
 	netdev_active_feature_add(dev, NETIF_F_LLTX_BIT);
-- 
2.33.0


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

* [RFCv8 PATCH net-next 55/55] net: redefine the prototype of netdev_features_t
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (53 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 54/55] treewide: use netdev_features_copy helpers Jian Shen
@ 2022-09-18  9:43 ` Jian Shen
  2022-09-20 20:16 ` [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jakub Kicinski
  2022-11-25 15:44 ` Alexander Lobakin
  56 siblings, 0 replies; 74+ messages in thread
From: Jian Shen @ 2022-09-18  9:43 UTC (permalink / raw)
  To: davem, kuba, ecree.xilinx, andrew, 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.

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/3com/typhoon.c           |   7 -
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  12 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |   2 +-
 drivers/net/ethernet/atheros/atlx/atl2.c      |   4 +-
 drivers/net/ethernet/brocade/bna/bnad.c       |   2 -
 .../net/ethernet/intel/i40e/i40e_debugfs.c    |  12 +-
 .../net/ethernet/intel/ixgbe/ixgbe_sriov.c    |   2 -
 .../ethernet/netronome/nfp/nfp_net_common.c   |   4 +-
 .../net/ethernet/pensando/ionic/ionic_lif.c   |   4 +-
 .../net/ethernet/synopsys/dwc-xlgmac-net.c    |   2 +-
 include/linux/netdev_feature_helpers.h        |  37 +++---
 include/linux/netdev_features.h               |  91 +------------
 include/linux/netdevice.h                     |   6 +-
 include/linux/skbuff.h                        |   8 +-
 include/net/ip_tunnels.h                      |   3 +-
 lib/vsprintf.c                                |   9 +-
 net/ethtool/features.c                        | 123 ++++++++----------
 net/ethtool/ioctl.c                           |  33 +++--
 18 files changed, 136 insertions(+), 225 deletions(-)

diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index d42a53748f40..4f9bc14ed44b 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -315,16 +315,9 @@ enum state_values {
 #define TYPHOON_RESET_TIMEOUT_NOSLEEP	((6 * 1000000) / TYPHOON_UDELAY)
 #define TYPHOON_WAIT_TIMEOUT		((1000000 / 2) / TYPHOON_UDELAY)
 
-#if defined(NETIF_F_TSO)
 #define skb_tso_size(x)		(skb_shinfo(x)->gso_size)
 #define TSO_NUM_DESCRIPTORS	2
 #define TSO_OFFLOAD_ON		TYPHOON_OFFLOAD_TCP_SEGMENT
-#else
-#define NETIF_F_TSO 		0
-#define skb_tso_size(x) 	0
-#define TSO_NUM_DESCRIPTORS	0
-#define TSO_OFFLOAD_ON		0
-#endif
 
 static inline void
 typhoon_inc_index(u32 *index, const int count, const int num_entries)
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index 47beaab0d963..487409678cfb 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/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 3709f8674724..17647ebbfdf0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2227,7 +2227,7 @@ 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 = netdev_feature_test(NETIF_F_RXHASH_BIT, pdata->netdev_features);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 2bc574a1cc25..11d82ae06d14 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -866,7 +866,7 @@ static netdev_tx_t atl2_xmit_frame(struct sk_buff *skb,
 			skb->len-copy_len);
 		offset = ((u32)(skb->len-copy_len + 3) & ~3);
 	}
-#ifdef NETIF_F_HW_VLAN_CTAG_TX
+
 	if (skb_vlan_tag_present(skb)) {
 		u16 vlan_tag = skb_vlan_tag_get(skb);
 		vlan_tag = (vlan_tag << 4) |
@@ -875,7 +875,7 @@ static netdev_tx_t atl2_xmit_frame(struct sk_buff *skb,
 		txph->ins_vlan = 1;
 		txph->vlan = vlan_tag;
 	}
-#endif
+
 	if (offset >= adapter->txd_ring_size)
 		offset -= adapter->txd_ring_size;
 	adapter->txd_write_ptr = offset;
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index cef5f7704d69..418c52c976f0 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -2857,12 +2857,10 @@ bnad_txq_wi_prepare(struct bnad *bnad, struct bna_tcb *tcb,
 
 			if (net_proto == htons(ETH_P_IP))
 				proto = ip_hdr(skb)->protocol;
-#ifdef NETIF_F_IPV6_CSUM
 			else if (net_proto == htons(ETH_P_IPV6)) {
 				/* nexthdr may not be TCP immediately. */
 				proto = ipv6_hdr(skb)->nexthdr;
 			}
-#endif
 			if (proto == IPPROTO_TCP) {
 				flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
 				txqent->hdr.wi.l4_hdr_size_n_offset =
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/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index ae9e2259fe10..83a11924da60 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -12,9 +12,7 @@
 #include <linux/tcp.h>
 #include <linux/ipv6.h>
 #include <linux/if_bridge.h>
-#ifdef NETIF_F_HW_VLAN_CTAG_TX
 #include <linux/if_vlan.h>
-#endif
 
 #include "ixgbe.h"
 #include "ixgbe_type.h"
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index fad9d4337eb5..f10f3c0362e3 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1739,8 +1739,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 79f5d936a49f..caa6a7200790 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1562,8 +1562,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/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
index 9f283d13e4f7..ff9d21aea3aa 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
@@ -879,9 +879,9 @@ static void xlgmac_poll_controller(struct net_device *netdev)
 static int xlgmac_set_features(struct net_device *netdev,
 			       const netdev_features_t *features)
 {
-	netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter;
 	struct xlgmac_pdata *pdata = netdev_priv(netdev);
 	struct xlgmac_hw_ops *hw_ops = &pdata->hw_ops;
+	bool rxhash, rxcsum, rxvlan, rxvlan_filter;
 	int ret = 0;
 
 	rxhash = netdev_feature_test(NETIF_F_RXHASH_BIT, pdata->netdev_features);
diff --git a/include/linux/netdev_feature_helpers.h b/include/linux/netdev_feature_helpers.h
index a15bd3a3b574..4e0a84dd8017 100644
--- a/include/linux/netdev_feature_helpers.h
+++ b/include/linux/netdev_feature_helpers.h
@@ -9,7 +9,7 @@
 
 static inline void __netdev_features_zero(netdev_features_t *dst)
 {
-	*dst = 0;
+	bitmap_zero(dst->bits, NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_zero(features) __netdev_features_zero(&(features))
@@ -38,14 +38,14 @@ 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);
 }
 
 #define netdev_features_fill(features) __netdev_features_fill(&(features))
 
 static inline bool __netdev_features_empty(const netdev_features_t *src)
 {
-	return *src == 0;
+	return bitmap_empty(src->bits, NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_empty(features) __netdev_features_empty(&(features))
@@ -75,7 +75,7 @@ static inline bool __netdev_features_empty(const netdev_features_t *src)
 static inline bool __netdev_features_equal(const netdev_features_t *feats1,
 					   const netdev_features_t *feats2)
 {
-	return *feats1 == *feats2;
+	return bitmap_equal(feats1->bits, feats2->bits, NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_equal(feat1, feat2)	\
@@ -107,8 +107,7 @@ static inline bool
 __netdev_features_and(netdev_features_t *dst, const netdev_features_t *a,
 		      const netdev_features_t *b)
 {
-	*dst = *a & *b;
-	return *dst != 0;
+	return bitmap_and(dst->bits, a->bits, b->bits, NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_and(dst, a, b) __netdev_features_and(&(dst), &(a), &(b))
@@ -171,7 +170,7 @@ static inline void
 __netdev_features_or(netdev_features_t *dst, const netdev_features_t *a,
 		     const netdev_features_t *b)
 {
-	*dst = *a | *b;
+	bitmap_or(dst->bits, a->bits, b->bits, NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_or(dst, a, b) __netdev_features_or(&(dst), &(a), &(b))
@@ -230,10 +229,7 @@ __netdev_features_set(netdev_features_t *dst, const netdev_features_t *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);
+	__change_bit(nr, src->bits);
 }
 
 #define netdev_feature_change(nr, src)	\
@@ -265,7 +261,7 @@ static inline void
 __netdev_features_xor(netdev_features_t *dst, const netdev_features_t *a,
 		      const netdev_features_t *b)
 {
-	*dst = *a ^ *b;
+	bitmap_xor(dst->bits, a->bits, b->bits, NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_xor(dst, a, b) __netdev_features_xor(&(dst), &(a), &(b))
@@ -328,8 +324,7 @@ static inline bool
 __netdev_features_andnot(netdev_features_t *dst, const netdev_features_t *a,
 			 const netdev_features_t *b)
 {
-	*dst = *a & ~(*b);
-	return *dst == 0;
+	return bitmap_andnot(dst->bits, a->bits, b->bits, NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_andnot(dst, a, b)	\
@@ -360,7 +355,8 @@ static inline void
 __netdev_features_clear(netdev_features_t *dst,
 			const netdev_features_t *features)
 {
-	__netdev_features_andnot(dst, dst, features);
+	bitmap_andnot(dst->bits, dst->bits, features->bits,
+		      NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_clear(dst, __features)	\
@@ -390,7 +386,7 @@ __netdev_features_clear(netdev_features_t *dst,
 /* 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_feature_add(nr, src) __netdev_feature_add(nr, &(src))
@@ -454,7 +450,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_feature_del(nr, src) __netdev_feature_del(nr, &(src))
@@ -518,7 +514,8 @@ __netdev_features_clear_array(const struct netdev_feature_set *set,
 static inline bool __netdev_features_intersects(const netdev_features_t *feats1,
 						const netdev_features_t *feats2)
 {
-	return (*feats1 & *feats2) > 0;
+	return bitmap_intersects(feats1->bits, feats2->bits,
+				 NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_intersects(feats1, feats2)	\
@@ -549,7 +546,7 @@ static inline bool __netdev_features_intersects(const netdev_features_t *feats1,
 static inline void __netdev_features_copy(netdev_features_t *dst,
 					  const netdev_features_t *src)
 {
-	*dst = *src;
+	bitmap_copy(dst->bits, src->bits, NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_copy(dst, src)	__netdev_features_copy(&(dst), &(src))
@@ -579,7 +576,7 @@ static inline void __netdev_features_copy(netdev_features_t *dst,
 static inline bool __netdev_features_subset(const netdev_features_t *feats1,
 					    const netdev_features_t *feats2)
 {
-	return (*feats1 & *feats2) == *feats2;
+	return bitmap_subset(feats1->bits, feats2->bits, NETDEV_FEATURE_COUNT);
 }
 
 #define netdev_features_subset(feats1, feats2)	\
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 664055209b2e..d41e74748927 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;
@@ -144,94 +146,11 @@ 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;
 
-/* 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;
-}
-
 /* 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 */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4620af4591fc..33486b2aa9f1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2348,7 +2348,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_feature_test(nr, __features)	\
@@ -4947,12 +4947,12 @@ static inline bool net_gso_ok(const netdev_features_t *features, int gso_type)
 	ASSERT_GSO_TYPE(SKB_GSO_FRAGLIST_BIT, NETIF_F_GSO_FRAGLIST_BIT);
 
 	if (classic_gso_type)
-		feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT;
+		bitmap_from_u64(feature.bits, (u64)gso_type << NETIF_F_GSO_SHIFT);
 
 	if (new_gso_type) { /* placeholder for new gso type */
 	}
 
-	return (*features & feature) == feature;
+	return bitmap_subset(features->bits, feature.bits, NETDEV_FEATURE_COUNT);
 }
 
 static inline bool skb_gso_ok(struct sk_buff *skb,
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 122190c334cb..33df942ed6da 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -693,6 +693,10 @@ enum {
 	SKB_GSO_FRAGLIST = __SKB_GSO_FLAG(FRAGLIST),
 };
 
+#define SKB_GSO_ENCAP_ALL	\
+		(SKB_GSO_GRE_CSUM | SKB_GSO_GRE_CSUM | SKB_GSO_IPXIP4 |	\
+		 SKB_GSO_IPXIP6 | SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP_TUNNEL_CSUM)
+
 #if BITS_PER_LONG > 32
 #define NET_SKBUFF_DATA_USES_OFFSET 1
 #endif
@@ -4038,8 +4042,8 @@ static inline bool skb_needs_linearize(struct sk_buff *skb,
 				       const 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 ced80e2f8b58..d3f028d31e0b 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -449,8 +449,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 >>
-					       NETIF_F_GSO_SHIFT);
+		skb_shinfo(skb)->gso_type &= ~SKB_GSO_ENCAP_ALL;
 	}
 
 	skb->encapsulation = 0;
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 3c1853a9d1c0..fa1cb5ff6de2 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1732,22 +1732,21 @@ static noinline_for_stack
 char *netdev_bits(char *buf, char *end, const void *addr,
 		  struct printf_spec spec,  const char *fmt)
 {
-	unsigned long long num;
-	int size;
+	const 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 496dfd45faac..2607a8b46cee 100644
--- a/net/ethtool/features.c
+++ b/net/ethtool/features.c
@@ -25,12 +25,9 @@ const struct nla_policy ethnl_features_get_policy[] = {
 		NLA_POLICY_NESTED(ethnl_header_policy),
 };
 
-static void ethnl_features_to_bitmap32(u32 *dest, netdev_features_t src)
+static void ethnl_features_to_bitmap32(u32 *dest, const 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,
@@ -41,12 +38,12 @@ static int features_prepare_data(const struct ethnl_req_info *req_base,
 	struct net_device *dev = reply_base->dev;
 	netdev_features_t all_features;
 
-	ethnl_features_to_bitmap32(data->hw, dev->hw_features);
-	ethnl_features_to_bitmap32(data->wanted, dev->wanted_features);
-	ethnl_features_to_bitmap32(data->active, dev->features);
-	ethnl_features_to_bitmap32(data->nochange, NETIF_F_NEVER_CHANGE);
-	all_features = GENMASK_ULL(NETDEV_FEATURE_COUNT - 1, 0);
-	ethnl_features_to_bitmap32(data->all, all_features);
+	ethnl_features_to_bitmap32(data->hw, &dev->hw_features);
+	ethnl_features_to_bitmap32(data->wanted, &dev->wanted_features);
+	ethnl_features_to_bitmap32(data->active, &dev->features);
+	ethnl_features_to_bitmap32(data->nochange, &NETIF_F_NEVER_CHANGE);
+	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 = 0;
-	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,
@@ -207,18 +182,23 @@ static int features_send_reply(struct net_device *dev, struct genl_info *info,
 	return ret;
 }
 
+enum {
+	OLD_ACTIVE = 0,
+	OLD_WANTED = 1,
+	NEW_ACTIVE = 2,
+	NEW_WANTED = 3,
+	REQ_WANTED = 4,
+	REQ_MASK = 5,
+	ACTIVE_DIFF_MASK = 6,
+	WANTED_DIFF_MASK = 7,
+	FEATURES_NUM = 8
+};
+
 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 *features;
 	struct net_device *dev;
 	netdev_features_t tmp;
 	bool mod;
@@ -234,52 +214,60 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
 		return ret;
 	dev = req_info.dev;
 
+	features = kzalloc(sizeof(netdev_features_t) * FEATURES_NUM, GFP_KERNEL);
+	if (!features)
+		return -ENOMEM;
+
 	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,
+	netdev_features_copy(features[OLD_ACTIVE], dev->features);
+	netdev_features_copy(features[OLD_WANTED], dev->wanted_features);
+	ret = ethnl_parse_bitset(features[REQ_WANTED].bits, features[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(features[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)) {
+	netdev_features_mask(features[REQ_WANTED], features[REQ_MASK]);
+	netdev_features_andnot(features[NEW_WANTED], features[OLD_WANTED],
+			       features[REQ_MASK]);
+	netdev_features_set(features[REQ_WANTED], features[NEW_WANTED]);
+	if (!netdev_features_equal(features[REQ_WANTED], features[OLD_WANTED])) {
 		netdev_wanted_features_clear(dev, dev->hw_features);
-		tmp = ethnl_bitmap_to_features(req_wanted);
-		netdev_features_mask(tmp, dev->hw_features);
+		netdev_features_and(tmp, dev->hw_features, features[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);
+	netdev_features_copy(features[NEW_ACTIVE], dev->features);
+	mod = !netdev_features_equal(features[OLD_ACTIVE], features[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);
+		netdev_features_xor(features[WANTED_DIFF_MASK],
+				    features[REQ_WANTED], features[NEW_ACTIVE]);
+		netdev_features_xor(features[ACTIVE_DIFF_MASK],
+				    features[OLD_ACTIVE],
+				    features[NEW_ACTIVE]);
+		netdev_features_mask(features[WANTED_DIFF_MASK],
+				     features[REQ_MASK]);
+		netdev_features_mask(features[REQ_WANTED],
+				     features[WANTED_DIFF_MASK]);
+		netdev_features_mask(features[NEW_ACTIVE],
+				     features[ACTIVE_DIFF_MASK]);
+
+		ret = features_send_reply(dev, info, features[REQ_WANTED].bits,
+					  features[WANTED_DIFF_MASK].bits,
+					  features[NEW_ACTIVE].bits,
+					  features[ACTIVE_DIFF_MASK].bits,
+					  compact);
 	}
 	if (mod)
 		netdev_features_change(dev);
@@ -287,5 +275,6 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
 out_rtnl:
 	rtnl_unlock();
 	ethnl_parse_header_dev_put(&req_info);
+	kfree(features);
 	return ret;
 }
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 12bf982a5d2d..c4537aacc6f1 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_features_t valid;
 	netdev_features_t tmp;
@@ -143,16 +153,18 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 	netdev_features_zero(wanted);
 	netdev_features_zero(valid);
 	for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) {
-		valid |= (netdev_features_t)features[i].valid << (32 * i);
-		wanted |= (netdev_features_t)features[i].requested << (32 * i);
+		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);
 
 	netdev_features_andnot(tmp, valid, NETIF_F_ETHTOOL_BITS);
-	if (tmp)
+	if (!netdev_features_empty(tmp))
 		return -EINVAL;
 
 	netdev_features_andnot(tmp, valid, dev->hw_features);
-	if (tmp) {
+	if (!netdev_features_empty(tmp)) {
 		netdev_features_mask(valid, dev->hw_features);
 		ret |= ETHTOOL_F_UNSUPPORTED;
 	}
@@ -163,8 +175,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 	__netdev_update_features(dev);
 
 	netdev_features_xor(tmp, dev->wanted_features, dev->features);
-
-	if (tmp & valid)
+	if (netdev_features_intersects(tmp, valid))
 		ret |= ETHTOOL_F_WISH;
 
 	return ret;
-- 
2.33.0


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

* Re: [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables Jian Shen
@ 2022-09-18 12:05   ` kernel test robot
  2022-09-20 20:12   ` Jakub Kicinski
  1 sibling, 0 replies; 74+ messages in thread
From: kernel test robot @ 2022-09-18 12:05 UTC (permalink / raw)
  To: Jian Shen; +Cc: llvm, kbuild-all

Hi Jian,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on net-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Jian-Shen/net-extend-the-type-of-netdev_features_t-to-bitmap/20220918-175512
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 44a8535fb87c5503ce01121278ac3058eef701ec
config: i386-randconfig-a002 (https://download.01.org/0day-ci/archive/20220918/202209181955.ZwQVuo5F-lkp@intel.com/config)
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/d2ad321600f7e1199ffb76240a37122c72bf2b5d
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Jian-Shen/net-extend-the-type-of-netdev_features_t-to-bitmap/20220918-175512
        git checkout d2ad321600f7e1199ffb76240a37122c72bf2b5d
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash lib/ net/core/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> net/core/netdev_features.c:99:13: warning: no previous prototype for function 'netdev_features_init' [-Wmissing-prototypes]
   void __init netdev_features_init(void)
               ^
   net/core/netdev_features.c:99:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void __init netdev_features_init(void)
   ^
   static 
   1 warning generated.


vim +/netdev_features_init +99 net/core/netdev_features.c

    98	
  > 99	void __init netdev_features_init(void)

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

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

* Re: [RFCv8 PATCH net-next 54/55] treewide: use netdev_features_copy helpers
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 54/55] treewide: use netdev_features_copy helpers Jian Shen
@ 2022-09-18 12:05   ` kernel test robot
  0 siblings, 0 replies; 74+ messages in thread
From: kernel test robot @ 2022-09-18 12:05 UTC (permalink / raw)
  To: Jian Shen; +Cc: llvm, kbuild-all

Hi Jian,

[FYI, it's a private test report for your RFC patch.]
[auto build test ERROR on net-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Jian-Shen/net-extend-the-type-of-netdev_features_t-to-bitmap/20220918-175512
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 44a8535fb87c5503ce01121278ac3058eef701ec
config: x86_64-randconfig-a005 (https://download.01.org/0day-ci/archive/20220918/202209181949.aWxvqPnW-lkp@intel.com/config)
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/ffa4c285bdcbd69824e5b38b1d3e98b905fc17d8
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Jian-Shen/net-extend-the-type-of-netdev_features_t-to-bitmap/20220918-175512
        git checkout ffa4c285bdcbd69824e5b38b1d3e98b905fc17d8
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/net/bonding/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from drivers/net/bonding/bond_main.c:38:
   In file included from include/linux/filter.h:20:
   In file included from include/linux/if_vlan.h:10:
   include/linux/netdevice.h:4949:6: warning: variable 'feature' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
           if (classic_gso_type)
               ^~~~~~~~~~~~~~~~
   include/linux/netdevice.h:4955:22: note: uninitialized use occurs here
           return (*features & feature) == feature;
                               ^~~~~~~
   include/linux/netdevice.h:4949:2: note: remove the 'if' if its condition is always true
           if (classic_gso_type)
           ^~~~~~~~~~~~~~~~~~~~~
   include/linux/netdevice.h:4927:27: note: initialize the variable 'feature' to silence this warning
           netdev_features_t feature;
                                    ^
                                     = 0
>> drivers/net/bonding/bond_main.c:1453:23: error: use of undeclared identifier 'xfrm_features'
           netdev_features_copy(xfrm_features, BOND_XFRM_FEATURES);
                                ^
   1 warning and 1 error generated.


vim +/xfrm_features +1453 drivers/net/bonding/bond_main.c

  1431	
  1432	static void bond_compute_features(struct bonding *bond)
  1433	{
  1434		unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
  1435						IFF_XMIT_DST_RELEASE_PERM;
  1436		netdev_features_t vlan_features;
  1437		netdev_features_t enc_features;
  1438	#ifdef CONFIG_XFRM_OFFLOAD
  1439		netdev_features_t xfrm_features;
  1440	#endif /* CONFIG_XFRM_OFFLOAD */
  1441		netdev_features_t mpls_features;
  1442		struct net_device *bond_dev = bond->dev;
  1443		struct list_head *iter;
  1444		struct slave *slave;
  1445		unsigned short max_hard_header_len = ETH_HLEN;
  1446		unsigned int tso_max_size = TSO_MAX_SIZE;
  1447		u16 tso_max_segs = TSO_MAX_SEGS;
  1448	
  1449		if (!bond_has_slaves(bond))
  1450			goto done;
  1451		netdev_features_copy(vlan_features, BOND_VLAN_FEATURES);
  1452		netdev_features_copy(enc_features, BOND_ENC_FEATURES);
> 1453		netdev_features_copy(xfrm_features, BOND_XFRM_FEATURES);
  1454		netdev_features_copy(mpls_features, BOND_MPLS_FEATURES);
  1455		netdev_features_mask(vlan_features, NETIF_F_ALL_FOR_ALL);
  1456		netdev_features_mask(mpls_features, NETIF_F_ALL_FOR_ALL);
  1457	
  1458		bond_for_each_slave(bond, slave, iter) {
  1459			netdev_increment_features(&vlan_features, &vlan_features,
  1460						  &slave->dev->vlan_features,
  1461						  &BOND_VLAN_FEATURES);
  1462	
  1463			netdev_increment_features(&enc_features, &enc_features,
  1464						  &slave->dev->hw_enc_features,
  1465						  &BOND_ENC_FEATURES);
  1466	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

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

* Re: [RFCv8 PATCH net-next 01/55] net: introduce operation helpers for netdev features
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 01/55] net: introduce operation helpers for netdev features Jian Shen
@ 2022-09-20 20:10   ` Jakub Kicinski
  2022-09-21  3:04     ` shenjian (K)
  0 siblings, 1 reply; 74+ messages in thread
From: Jakub Kicinski @ 2022-09-20 20:10 UTC (permalink / raw)
  To: Jian Shen
  Cc: davem, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin, saeed,
	leon, netdev, linuxarm

On Sun, 18 Sep 2022 09:42:42 +0000 Jian Shen wrote:
> 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, follow the prototype changes. For the new type
> netdev_features_t maybe large than 8 bytes, use netdev_features_t
> pointer as parameter.
> 
> 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.

> diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
> index 8b77582bdfa0..8023a3f0d43b 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_feature_helpers.h>
>  #include <net/dst_metadata.h>
>  
>  #include "nfpcore/nfp_cpp.h"

We need to start breaking upstreamable chunks out of this mega-series
otherwise we won't make any progress..

Please make a patch which will move netdev_intersect_features() and
netdev_get_wanted_features() to the new linux/netdev_feature_helpers.h
header, and add the missing includes. Post it separately as soon as
possible.

> diff --git a/include/linux/netdev_feature_helpers.h b/include/linux/netdev_feature_helpers.h
> new file mode 100644
> index 000000000000..4bb5de61e4e9
> --- /dev/null
> +++ b/include/linux/netdev_feature_helpers.h
> @@ -0,0 +1,607 @@
> +/* 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;
> +}
> +
> +#define netdev_features_zero(features) __netdev_features_zero(&(features))
> +
> +/* active_feature prefer to netdev->features */
> +#define netdev_active_features_zero(ndev) \
> +		netdev_features_zero((ndev)->features)
> +

No need for empty lines between the defines of the same category, IMHO.

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


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

* Re: [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables Jian Shen
  2022-09-18 12:05   ` kernel test robot
@ 2022-09-20 20:12   ` Jakub Kicinski
  2022-09-21  6:33     ` shenjian (K)
  1 sibling, 1 reply; 74+ messages in thread
From: Jakub Kicinski @ 2022-09-20 20:12 UTC (permalink / raw)
  To: Jian Shen
  Cc: davem, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin, saeed,
	leon, netdev, linuxarm

On Sun, 18 Sep 2022 09:42:43 +0000 Jian Shen wrote:
> -#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

We shouldn't be changing all these defines here, because that breaks
the build AFAIU. Can we not use the lowercase names going forward?

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

* Re: [RFCv8 PATCH net-next 03/55] treewide: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET
  2022-09-18  9:42 ` [RFCv8 PATCH net-next 03/55] treewide: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET Jian Shen
@ 2022-09-20 20:13   ` Jakub Kicinski
  0 siblings, 0 replies; 74+ messages in thread
From: Jakub Kicinski @ 2022-09-20 20:13 UTC (permalink / raw)
  To: Jian Shen
  Cc: davem, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin, saeed,
	leon, netdev, linuxarm

On Sun, 18 Sep 2022 09:42:44 +0000 Jian Shen wrote:
> +	netdev_active_features_zero(netdev);
> +	netdev_active_features_set_set(netdev, NETIF_F_HIGHDMA_BIT,

There's a ton of those zero() + set_set(), can we combine the two into
a single init() helper?

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

* Re: [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (54 preceding siblings ...)
  2022-09-18  9:43 ` [RFCv8 PATCH net-next 55/55] net: redefine the prototype of netdev_features_t Jian Shen
@ 2022-09-20 20:16 ` Jakub Kicinski
  2022-11-25 15:44 ` Alexander Lobakin
  56 siblings, 0 replies; 74+ messages in thread
From: Jakub Kicinski @ 2022-09-20 20:16 UTC (permalink / raw)
  To: Jian Shen
  Cc: davem, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin, saeed,
	leon, netdev, linuxarm

On Sun, 18 Sep 2022 09:42:41 +0000 Jian Shen wrote:
> 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.

For v9 could you filter out all the driver changes?

Focus on adding the helpers and converting core (excluding tunnel
drivers etc.) in a way that will not break the build. That way we 
can iterate on the revisions more quickly, hopefully, and convert
the drivers once we have the helpers ironed out?

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

* Re: [RFCv8 PATCH net-next 01/55] net: introduce operation helpers for netdev features
  2022-09-20 20:10   ` Jakub Kicinski
@ 2022-09-21  3:04     ` shenjian (K)
  0 siblings, 0 replies; 74+ messages in thread
From: shenjian (K) @ 2022-09-21  3:04 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin, saeed,
	leon, netdev, linuxarm



在 2022/9/21 4:10, Jakub Kicinski 写道:
> On Sun, 18 Sep 2022 09:42:42 +0000 Jian Shen wrote:
>> 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, follow the prototype changes. For the new type
>> netdev_features_t maybe large than 8 bytes, use netdev_features_t
>> pointer as parameter.
>>
>> 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.
>> diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
>> index 8b77582bdfa0..8023a3f0d43b 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_feature_helpers.h>
>>   #include <net/dst_metadata.h>
>>   
>>   #include "nfpcore/nfp_cpp.h"
> We need to start breaking upstreamable chunks out of this mega-series
> otherwise we won't make any progress..
>
> Please make a patch which will move netdev_intersect_features() and
> netdev_get_wanted_features() to the new linux/netdev_feature_helpers.h
> header, and add the missing includes. Post it separately as soon as
> possible.
ok, will split it.
>> diff --git a/include/linux/netdev_feature_helpers.h b/include/linux/netdev_feature_helpers.h
>> new file mode 100644
>> index 000000000000..4bb5de61e4e9
>> --- /dev/null
>> +++ b/include/linux/netdev_feature_helpers.h
>> @@ -0,0 +1,607 @@
>> +/* 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;
>> +}
>> +
>> +#define netdev_features_zero(features) __netdev_features_zero(&(features))
>> +
>> +/* active_feature prefer to netdev->features */
>> +#define netdev_active_features_zero(ndev) \
>> +		netdev_features_zero((ndev)->features)
>> +
> No need for empty lines between the defines of the same category, IMHO.
ok,  will remove the unnecessary empty lines.

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


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

* Re: [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables
  2022-09-20 20:12   ` Jakub Kicinski
@ 2022-09-21  6:33     ` shenjian (K)
  2022-09-21 10:01       ` shenjian (K)
  0 siblings, 1 reply; 74+ messages in thread
From: shenjian (K) @ 2022-09-21  6:33 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin, saeed,
	leon, netdev, linuxarm



在 2022/9/21 4:12, Jakub Kicinski 写道:
> On Sun, 18 Sep 2022 09:42:43 +0000 Jian Shen wrote:
>> -#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
> We shouldn't be changing all these defines here, because that breaks
> the build AFAIU.
ok, will keep them until remove the __NETIF_F(name) macro.


>   Can we not use the lowercase names going forward?
> .
ok

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

* Re: [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables
  2022-09-21  6:33     ` shenjian (K)
@ 2022-09-21 10:01       ` shenjian (K)
  2022-09-21 12:50         ` Jakub Kicinski
  0 siblings, 1 reply; 74+ messages in thread
From: shenjian (K) @ 2022-09-21 10:01 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin, saeed,
	leon, netdev, linuxarm



在 2022/9/21 14:33, shenjian (K) 写道:
>
>
> 在 2022/9/21 4:12, Jakub Kicinski 写道:
>> On Sun, 18 Sep 2022 09:42:43 +0000 Jian Shen wrote:
>>> -#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
>> We shouldn't be changing all these defines here, because that breaks
>> the build AFAIU.
> ok, will keep them until remove the __NETIF_F(name) macro.
>
But I don't see how it break build. Do you mean the definition of

WG_NETDEV_FEATURES in drivers/net/wireguard/device.c ?

>
>>   Can we not use the lowercase names going forward?
>> .
> ok
>
> .
>


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

* Re: [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables
  2022-09-21 10:01       ` shenjian (K)
@ 2022-09-21 12:50         ` Jakub Kicinski
  2022-09-22 14:47           ` shenjian (K)
  0 siblings, 1 reply; 74+ messages in thread
From: Jakub Kicinski @ 2022-09-21 12:50 UTC (permalink / raw)
  To: shenjian (K)
  Cc: davem, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin, saeed,
	leon, netdev, linuxarm

On Wed, 21 Sep 2022 18:01:16 +0800 shenjian (K) wrote:
> 在 2022/9/21 14:33, shenjian (K) 写道:
> >> On Sun, 18 Sep 2022 09:42:43 +0000 Jian Shen wrote:  
> >> We shouldn't be changing all these defines here, because that breaks
> >> the build AFAIU.  
> > ok, will keep them until remove the __NETIF_F(name) macro.
> >  
> But I don't see how it break build. Do you mean the definition of
> 
> WG_NETDEV_FEATURES in drivers/net/wireguard/device.c ?

Oops, you're right, looks like this patch just adds a warning:

net/core/netdev_features.c:99:13: warning: no previous prototype for function 'netdev_features_init' [-Wmissing-prototypes]
void __init netdev_features_init(void)


Build is broken by the next one:

drivers/net/ethernet/microsoft/mana/mana_en.c:2084:2: error: implicit declaration of function 'netdev_hw_features_zero' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
        netdev_hw_features_zero(ndev);
        ^
drivers/net/ethernet/microsoft/mana/mana_en.c:2085:2: error: implicit declaration of function 'netdev_hw_features_set_set' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
        netdev_hw_features_set_set(ndev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
        ^
drivers/net/ethernet/microsoft/mana/mana_en.c:2085:2: note: did you mean 'netdev_hw_features_zero'?
drivers/net/ethernet/microsoft/mana/mana_en.c:2084:2: note: 'netdev_hw_features_zero' declared here
        netdev_hw_features_zero(ndev);
        ^

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

* Re: [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables
  2022-09-21 12:50         ` Jakub Kicinski
@ 2022-09-22 14:47           ` shenjian (K)
  0 siblings, 0 replies; 74+ messages in thread
From: shenjian (K) @ 2022-09-22 14:47 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, ecree.xilinx, andrew, hkallweit1, alexandr.lobakin, saeed,
	leon, netdev, linuxarm



在 2022/9/21 20:50, Jakub Kicinski 写道:
> On Wed, 21 Sep 2022 18:01:16 +0800 shenjian (K) wrote:
>> 在 2022/9/21 14:33, shenjian (K) 写道:
>>>> On Sun, 18 Sep 2022 09:42:43 +0000 Jian Shen wrote:
>>>> We shouldn't be changing all these defines here, because that breaks
>>>> the build AFAIU.
>>> ok, will keep them until remove the __NETIF_F(name) macro.
>>>   
>> But I don't see how it break build. Do you mean the definition of
>>
>> WG_NETDEV_FEATURES in drivers/net/wireguard/device.c ?
> Oops, you're right, looks like this patch just adds a warning:
>
> net/core/netdev_features.c:99:13: warning: no previous prototype for function 'netdev_features_init' yi
> void __init netdev_features_init(void)
thanks, will fix it.

>
> Build is broken by the next one:
>
> drivers/net/ethernet/microsoft/mana/mana_en.c:2084:2: error: implicit declaration of function 'netdev_hw_features_zero' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
>          netdev_hw_features_zero(ndev);
>          ^
> drivers/net/ethernet/microsoft/mana/mana_en.c:2085:2: error: implicit declaration of function 'netdev_hw_features_set_set' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
>          netdev_hw_features_set_set(ndev, NETIF_F_SG_BIT, NETIF_F_IP_CSUM_BIT,
>          ^
> drivers/net/ethernet/microsoft/mana/mana_en.c:2085:2: note: did you mean 'netdev_hw_features_zero'?
> drivers/net/ethernet/microsoft/mana/mana_en.c:2084:2: note: 'netdev_hw_features_zero' declared here
>          netdev_hw_features_zero(ndev);
>          ^
> .
Sorry, I missed include netdev_feature_helpers.h.  I only did compile 
with allmodconfig on arm64 server, it didn't report build fail.
I should do compile on x86 server too, for mana driver is only supported 
on X86_64. Thanks!



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

* Re: [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap
  2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
                   ` (55 preceding siblings ...)
  2022-09-20 20:16 ` [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jakub Kicinski
@ 2022-11-25 15:44 ` Alexander Lobakin
  2022-11-28 15:22   ` shenjian (K)
  56 siblings, 1 reply; 74+ messages in thread
From: Alexander Lobakin @ 2022-11-25 15:44 UTC (permalink / raw)
  To: Jian Shen
  Cc: Alexander Lobakin, davem, kuba, ecree.xilinx, andrew, hkallweit1,
	saeed, leon, netdev, linuxarm

From: Jian Shen <shenjian15@huawei.com>
Date: Sun, 18 Sep 2022 09:42:41 +0000

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

Hey,

what's the current status, how's going?

[...]

> -- 
> 2.33.0

Thanks,
Olek

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

* Re: [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap
  2022-11-25 15:44 ` Alexander Lobakin
@ 2022-11-28 15:22   ` shenjian (K)
  2022-11-28 15:51     ` Alexander Lobakin
  0 siblings, 1 reply; 74+ messages in thread
From: shenjian (K) @ 2022-11-28 15:22 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, ecree.xilinx, andrew, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2022/11/25 23:44, Alexander Lobakin 写道:
> From: Jian Shen <shenjian15@huawei.com>
> Date: Sun, 18 Sep 2022 09:42:41 +0000
>
>> 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]
> Hey,
>
> what's the current status, how's going?
>
> [...]
Hi, Alexander

Sorry to reply late, I'm still working on this, dealing with split the 
patchset.

Btw, could you kindly review this V8 set?  I have adjusted the protocol 
of many interfaces and helpers,
to avoiding return or pass data large than 64bits. Hope to get more 
opinions.

Thanks!

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


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

* Re: [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap
  2022-11-28 15:22   ` shenjian (K)
@ 2022-11-28 15:51     ` Alexander Lobakin
  2023-09-13 10:28       ` Alexander Lobakin
  0 siblings, 1 reply; 74+ messages in thread
From: Alexander Lobakin @ 2022-11-28 15:51 UTC (permalink / raw)
  To: shenjian (K)
  Cc: Alexander Lobakin, davem, kuba, ecree.xilinx, andrew, hkallweit1,
	saeed, leon, netdev, linuxarm

From: "shenjian (K)" <shenjian15@huawei.com>
Date: Mon, 28 Nov 2022 23:22:28 +0800

> 2022/11/25 23:44, Alexander Lobakin:
> > From: Jian Shen <shenjian15@huawei.com>
> > Date: Sun, 18 Sep 2022 09:42:41 +0000
> >
> >> 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]
> > Hey,
> >
> > what's the current status, how's going?
> >
> > [...]
> Hi, Alexander
> 
> Sorry to reply late, I'm still working on this, dealing with split the 
> patchset.

Hey, no worries. Just curious as I believe lots of new features are
waiting for new bits to be available :D

> 
> Btw, could you kindly review this V8 set? I have adjusted the protocol 
> of many interfaces and helpers,

I'll try to find some time to review it this week, will see.

> to avoiding return or pass data large than 64bits. Hope to get more 

Yes, I'd prefer to not pass more than 64 bits in one function
argument, which means functions operating with netdev_features_t
must start take pointers. Otherwise, with passing netdev_features_t
directly as a struct, the very first newly added feature will do
8 -> 16 bytes on the stack per argument, boom.

> opinions.
> 
> Thanks!
> 
> Jian
> >> -- 
> >> 2.33.0
> > Thanks,
> > Olek

Thanks,
Olek

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

* Re: [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap
  2022-11-28 15:51     ` Alexander Lobakin
@ 2023-09-13 10:28       ` Alexander Lobakin
  2023-09-16  7:20         ` shenjian (K)
  0 siblings, 1 reply; 74+ messages in thread
From: Alexander Lobakin @ 2023-09-13 10:28 UTC (permalink / raw)
  To: shenjian (K)
  Cc: davem, kuba, ecree.xilinx, andrew, hkallweit1, saeed, leon,
	netdev, linuxarm

From: Alexander Lobakin <alexandr.lobakin@intel.com>
Date: Mon, 28 Nov 2022 16:51:27 +0100

> From: "shenjian (K)" <shenjian15@huawei.com>
> Date: Mon, 28 Nov 2022 23:22:28 +0800
> 
>> 2022/11/25 23:44, Alexander Lobakin:
>>> From: Jian Shen <shenjian15@huawei.com>
>>> Date: Sun, 18 Sep 2022 09:42:41 +0000
>>>
>>>> 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]
>>> Hey,
>>>
>>> what's the current status, how's going?
>>>
>>> [...]
>> Hi, Alexander
>>
>> Sorry to reply late, I'm still working on this, dealing with split the 
>> patchset.
> 
> Hey, no worries. Just curious as I believe lots of new features are
> waiting for new bits to be available :D

Hey,

Any news?

> 
>>
>> Btw, could you kindly review this V8 set? I have adjusted the protocol 
>> of many interfaces and helpers,
> 
> I'll try to find some time to review it this week, will see.
> 
>> to avoiding return or pass data large than 64bits. Hope to get more 
> 
> Yes, I'd prefer to not pass more than 64 bits in one function
> argument, which means functions operating with netdev_features_t
> must start take pointers. Otherwise, with passing netdev_features_t
> directly as a struct, the very first newly added feature will do
> 8 -> 16 bytes on the stack per argument, boom.
> 
>> opinions.
>>
>> Thanks!
>>
>> Jian
>>>> -- 
>>>> 2.33.0
>>> Thanks,
>>> Olek
> 
> Thanks,
> Olek

Thanks,
Olek

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

* Re: [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap
  2023-09-13 10:28       ` Alexander Lobakin
@ 2023-09-16  7:20         ` shenjian (K)
  2023-09-18 14:25           ` Alexander Lobakin
  0 siblings, 1 reply; 74+ messages in thread
From: shenjian (K) @ 2023-09-16  7:20 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: davem, kuba, ecree.xilinx, andrew, hkallweit1, saeed, leon,
	netdev, linuxarm



在 2023/9/13 18:28, Alexander Lobakin 写道:
> From: Alexander Lobakin <alexandr.lobakin@intel.com>
> Date: Mon, 28 Nov 2022 16:51:27 +0100
>
>> From: "shenjian (K)" <shenjian15@huawei.com>
>> Date: Mon, 28 Nov 2022 23:22:28 +0800
>>
>>> 2022/11/25 23:44, Alexander Lobakin:
>>>> From: Jian Shen <shenjian15@huawei.com>
>>>> Date: Sun, 18 Sep 2022 09:42:41 +0000
>>>>
>>>>> 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]
>>>> Hey,
>>>>
>>>> what's the current status, how's going?
>>>>
>>>> [...]
>>> Hi, Alexander
>>>
>>> Sorry to reply late, I'm still working on this, dealing with split the
>>> patchset.
>> Hey, no worries. Just curious as I believe lots of new features are
>> waiting for new bits to be available :D
> Hey,
>
> Any news?
Sorry, Olek .

Would you like to continue the work ? I thought I could finish this work 
as soon as possible, but in fact, there is a serious time conflict.

Jian

>>> Btw, could you kindly review this V8 set? I have adjusted the protocol
>>> of many interfaces and helpers,
>> I'll try to find some time to review it this week, will see.
>>
>>> to avoiding return or pass data large than 64bits. Hope to get more
>> Yes, I'd prefer to not pass more than 64 bits in one function
>> argument, which means functions operating with netdev_features_t
>> must start take pointers. Otherwise, with passing netdev_features_t
>> directly as a struct, the very first newly added feature will do
>> 8 -> 16 bytes on the stack per argument, boom.
>>
>>> opinions.
>>>
>>> Thanks!
>>>
>>> Jian
>>>>> -- 
>>>>> 2.33.0
>>>> Thanks,
>>>> Olek
>> Thanks,
>> Olek
> Thanks,
> Olek
> .
>


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

* Re: [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap
  2023-09-16  7:20         ` shenjian (K)
@ 2023-09-18 14:25           ` Alexander Lobakin
  2023-10-03 19:28             ` Jakub Kicinski
  0 siblings, 1 reply; 74+ messages in thread
From: Alexander Lobakin @ 2023-09-18 14:25 UTC (permalink / raw)
  To: shenjian (K)
  Cc: davem, kuba, ecree.xilinx, andrew, hkallweit1, saeed, leon,
	netdev, linuxarm, Sabrina Dubroca

From: Shenjian (K) <shenjian15@huawei.com>
Date: Sat, 16 Sep 2023 15:20:27 +0800

> 
> 
> 在 2023/9/13 18:28, Alexander Lobakin 写道:
>> From: Alexander Lobakin <alexandr.lobakin@intel.com>
>> Date: Mon, 28 Nov 2022 16:51:27 +0100
>>
>>> From: "shenjian (K)" <shenjian15@huawei.com>
>>> Date: Mon, 28 Nov 2022 23:22:28 +0800
>>>
>>>> 2022/11/25 23:44, Alexander Lobakin:
>>>>> From: Jian Shen <shenjian15@huawei.com>
>>>>> Date: Sun, 18 Sep 2022 09:42:41 +0000
>>>>>
>>>>>> 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]
>>>>> Hey,
>>>>>
>>>>> what's the current status, how's going?
>>>>>
>>>>> [...]
>>>> Hi, Alexander
>>>>
>>>> Sorry to reply late, I'm still working on this, dealing with split the
>>>> patchset.
>>> Hey, no worries. Just curious as I believe lots of new features are
>>> waiting for new bits to be available :D
>> Hey,
>>
>> Any news?
> Sorry, Olek .
> 
> Would you like to continue the work ? I thought I could finish this work
> as soon as possible, but in fact, there is a serious time conflict.

Oh well, I'm kinda overloaded as well (as always) and at the same time
won't work with the code during the next month due to conferences and
a vacation :z :D
Would I take this project over, I'd start working on it no sooner than
January 2024, so I don't think that would be a good idea.

Anyone else? +Cc Sabrina, there's "netdev_features_t extension"
mentioned next to her name in one interesting spreadsheet :D

> 
> Jian

[...]

Thanks,
Olek

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

* Re: [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap
  2023-09-18 14:25           ` Alexander Lobakin
@ 2023-10-03 19:28             ` Jakub Kicinski
  0 siblings, 0 replies; 74+ messages in thread
From: Jakub Kicinski @ 2023-10-03 19:28 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: shenjian (K),
	davem, ecree.xilinx, andrew, hkallweit1, saeed, leon, netdev,
	linuxarm, Sabrina Dubroca

On Mon, 18 Sep 2023 16:25:14 +0200 Alexander Lobakin wrote:
> > Would you like to continue the work ? I thought I could finish this work
> > as soon as possible, but in fact, there is a serious time conflict.  
> 
> Oh well, I'm kinda overloaded as well (as always) and at the same time
> won't work with the code during the next month due to conferences and
> a vacation :z :D
> Would I take this project over, I'd start working on it no sooner than
> January 2024, so I don't think that would be a good idea.
> 
> Anyone else? +Cc Sabrina, there's "netdev_features_t extension"
> mentioned next to her name in one interesting spreadsheet :D

FTR Olek brought this topic up at netconf and the conclusion/Eric's
guidance was to deprioritize this work. Instead focus on cleaning up
things which are currently in features but do no need to be accessed 
in generic fast paths.

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

end of thread, other threads:[~2023-10-03 19:28 UTC | newest]

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-18  9:42 [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 01/55] net: introduce operation helpers for netdev features Jian Shen
2022-09-20 20:10   ` Jakub Kicinski
2022-09-21  3:04     ` shenjian (K)
2022-09-18  9:42 ` [RFCv8 PATCH net-next 02/55] net: replace general features macroes with global netdev_features variables Jian Shen
2022-09-18 12:05   ` kernel test robot
2022-09-20 20:12   ` Jakub Kicinski
2022-09-21  6:33     ` shenjian (K)
2022-09-21 10:01       ` shenjian (K)
2022-09-21 12:50         ` Jakub Kicinski
2022-09-22 14:47           ` shenjian (K)
2022-09-18  9:42 ` [RFCv8 PATCH net-next 03/55] treewide: replace multiple feature bits with DECLARE_NETDEV_FEATURE_SET Jian Shen
2022-09-20 20:13   ` Jakub Kicinski
2022-09-18  9:42 ` [RFCv8 PATCH net-next 04/55] net: sfc: replace const features initialization " Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 05/55] net: atlantic: replace const features initialization with NETDEV_FEATURE_SET Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 06/55] iwlwifi: " Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 07/55] net: ethernet: mtk_eth_soc: " Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 08/55] ravb: " Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 09/55] test_bpf: " Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 10/55] treewide: replace NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK by netdev_csum_gso_features_mask Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 11/55] treewide: replace NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM by netdev_ip_csum_features Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 12/55] treewide: replace NETIF_F_TSO | NETIF_F_TSO6 by netdev_general_tso_features Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 13/55] treewide: replace VLAN tag feature array by const vlan features Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 14/55] net: simplify the netdev features expressions for xxx_gso_segment Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 15/55] treewide: simplify the netdev features expression Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 16/55] treewide: adjust the handle for netdev features '0' Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 17/55] treewide: adjust features initialization Jian Shen
2022-09-18  9:42 ` [RFCv8 PATCH net-next 18/55] net: mlx4: adjust the net device feature relative macroes Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 19/55] net: mlx5e: adjust " Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 20/55] net: mlxsw: adjust input parameter for function mlxsw_sp_handle_feature Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 21/55] net: iavf: adjust net device features relative macroes Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 22/55] net: core: adjust netdev_sync_xxx_features Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 23/55] net: adjust the build check for net_gso_ok() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 24/55] treewide: use netdev_feature_add helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 25/55] treewide: use netdev_features_or/set helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 26/55] treewide: use netdev_feature_change helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 27/55] treewide: use netdev_feature_del helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 28/55] treewide: use netdev_features_andnot/clear helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 29/55] treewide: use netdev_features_xor/toggle helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 30/55] treewide: use netdev_feature_test helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 31/55] treewide: use netdev_features_intersects helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 32/55] treewide: use netdev_features_and/mask helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 33/55] treewide: use netdev_features_subset helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 34/55] treewide: use netdev_features_equal helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 35/55] treewide: use netdev_features_empty helpers Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 36/55] net: adjust the prototype of netdev_increment_features() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 37/55] net: adjust the prototype of netdev_add_tso_features() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 38/55] net: core: adjust prototype of several functions used in net/core/dev.c Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 39/55] net: adjust the prototype of netdev_intersect_features() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 40/55] net: adjust the prototype of netif_skb_features() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 41/55] net: adjust the prototype of xxx_features_check() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 42/55] net: adjust the prototype of ndo_fix_features Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 43/55] net: adjust the prototype of xxx_set_features() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 44/55] net: adjust the prototype fo xxx_gso_segment() family Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 45/55] net: vlan: adjust the prototype of vlan functions Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 46/55] net: adjust the prototype of netif_needs_gso() and relative functions Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 47/55] net: adjust the prototype of skb_needs_linearize() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 48/55] net: adjust the prototype of validate_xmit_xfrm() and relative functions Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 49/55] net: adjust the prototype of can_checksum_protocol() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 50/55] net: tap: adjust the prototype of update_features() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 51/55] net: mlx4: adjust the prototype of check_csum() and mlx4_en_update_loopback_state() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 52/55] net: gve: adjust the prototype of gve_rx(), gve_clean_rx_done() and gve_rx_complete_skb() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 53/55] net: sfc: adjust the prototype of xxx_supported_features() Jian Shen
2022-09-18  9:43 ` [RFCv8 PATCH net-next 54/55] treewide: use netdev_features_copy helpers Jian Shen
2022-09-18 12:05   ` kernel test robot
2022-09-18  9:43 ` [RFCv8 PATCH net-next 55/55] net: redefine the prototype of netdev_features_t Jian Shen
2022-09-20 20:16 ` [RFCv8 PATCH net-next 00/55] net: extend the type of netdev_features_t to bitmap Jakub Kicinski
2022-11-25 15:44 ` Alexander Lobakin
2022-11-28 15:22   ` shenjian (K)
2022-11-28 15:51     ` Alexander Lobakin
2023-09-13 10:28       ` Alexander Lobakin
2023-09-16  7:20         ` shenjian (K)
2023-09-18 14:25           ` Alexander Lobakin
2023-10-03 19:28             ` Jakub Kicinski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.