For the prototype of netdev_features_t is u64, and the number of netdevice feature bits is 64 now. So there is no space to introduce new feature bit.
This patchset try to solve it by change the prototype of netdev_features_t from u64 to structure below: typedef struct { DECLARE_BITMAP(bits, NETDEV_FEATURE_COUNT); } netdev_features_t;
With this change, it's necessary to introduce a set of bitmap operation helpers for netdev features. As the nic drivers are not supposed to modify netdev_features directly, it also introduces wrappers helpers to this. [patch 20]
There are a set of helpes named as "netdev_features_xxx", and I want to add similar helpers for netdev features members, named as netdev_XXX_features_xxx.(xxx: and/or/xor.., XXX: hw/vlan/mpls...) To make the helpers name differentiable, rename netdev->features to netdev->active_features. [patch 2] For example: #define netdev_active_features_set_bit(ndev, nr) \ netdev_features_set_bit(nr, &ndev->active_features)
To avoid mistake using NETIF_F_XXX as NETIF_F_XXX_BIT as input macroes for above helpers, remove all the macroes of NETIF_F_XXX. [patch 20]
The features group macroes in netdev_features.h are replaced by a set of const features defined in netdev_features.c. [patch 3-4] 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 5]
As suggestion from Andrew Lunn, I wrote some semantic patches to do the work(replacing the netdev features operator by helpers). [patch 8-19] To make the semantic patches simple, I split the complex opreation of netdev_features to simple logical operation. [patch 6, 7]
With the prototype is no longer u64, the implementation of print interface for netdev features(%pNF) is changed to bitmap. [patch 20]
The whole work is not complete yet. I just use these changes on several files(hns3 driver, sfc drivers, net/ethtool, net/core/dev.c), in order to show how these helpers will be used. I want to get more suggestions for this scheme, any comments would be appreciated.
The former discussion please see [1][2][3].
[1]:https://www.spinics.net/lists/netdev/msg769952.html [2]:https://www.spinics.net/lists/netdev/msg777764.html [3]:https://lore.kernel.org/netdev/20211107101519.29264-1-shenjian15@huawei.com/...
ChangeLog: 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 (20): net: rename net_device->features to net_device->active_features net: introduce operation helpers for netdev features net: replace general features macroes with global netdev_features variables net: replace multiple feature bits with netdev features array net: sfc: replace const features initialization with netdev features array net: simplify the netdev features expression net: adjust variables definition for netdev_features_t net: use netdev_features_set_bit helpers net: use netdev_features_or helpers net: use netdev_features_xor helpers net: use netdev_features_clear_bit helpers net: use netdev_features_andnot helpers net: use netdev_features_test_bit helpers net: use netdev_features_intersects helpers net: use netdev_features_and helpers net: use netdev_features_subset helpers net: use netdev_features_equal helpers net: use netdev_set_xxx_features helpers net: use netdev_xxx_features helpers net: redefine the prototype of netdev_features_t
.../net/ethernet/hisilicon/hns3/hns3_enet.c | 116 ++- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 4 +- drivers/net/ethernet/sfc/ef10.c | 43 +- drivers/net/ethernet/sfc/ef100_nic.c | 57 +- 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 | 96 ++- drivers/net/ethernet/sfc/efx_common.c | 32 +- drivers/net/ethernet/sfc/falcon/efx.c | 75 +- drivers/net/ethernet/sfc/falcon/efx.h | 3 + drivers/net/ethernet/sfc/falcon/falcon.c | 4 +- drivers/net/ethernet/sfc/falcon/net_driver.h | 4 +- drivers/net/ethernet/sfc/falcon/rx.c | 4 +- drivers/net/ethernet/sfc/farch.c | 2 +- drivers/net/ethernet/sfc/mcdi_filters.c | 13 +- drivers/net/ethernet/sfc/mcdi_port_common.c | 2 +- drivers/net/ethernet/sfc/net_driver.h | 4 +- drivers/net/ethernet/sfc/rx.c | 2 +- drivers/net/ethernet/sfc/rx_common.c | 5 +- drivers/net/ethernet/sfc/rx_common.h | 4 + drivers/net/ethernet/sfc/siena.c | 3 +- include/linux/netdev_features.h | 189 ++--- include/linux/netdevice.h | 722 +++++++++++++++++- lib/vsprintf.c | 11 +- net/core/dev.c | 419 ++++++---- net/core/netdev_features.c | 276 +++++++ net/ethtool/features.c | 77 +- net/ethtool/ioctl.c | 140 ++-- 29 files changed, 1797 insertions(+), 528 deletions(-) create mode 100644 net/core/netdev_features.c
The net_device->features indicates the active features of the net device, rename it to active_features, make it esaier to define feature helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 32 ++++++------- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 4 +- drivers/net/ethernet/sfc/ef10.c | 4 +- drivers/net/ethernet/sfc/ef100_nic.c | 4 +- drivers/net/ethernet/sfc/ef100_rx.c | 4 +- drivers/net/ethernet/sfc/ef100_tx.c | 8 ++-- drivers/net/ethernet/sfc/efx.c | 14 +++--- drivers/net/ethernet/sfc/efx_common.c | 14 +++--- drivers/net/ethernet/sfc/falcon/efx.c | 20 ++++---- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/falcon/rx.c | 4 +- drivers/net/ethernet/sfc/farch.c | 2 +- drivers/net/ethernet/sfc/mcdi_filters.c | 6 +-- drivers/net/ethernet/sfc/mcdi_port_common.c | 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- drivers/net/ethernet/sfc/rx.c | 2 +- drivers/net/ethernet/sfc/rx_common.c | 2 +- include/linux/netdevice.h | 14 +++--- net/core/dev.c | 46 +++++++++---------- net/ethtool/features.c | 6 +-- net/ethtool/ioctl.c | 22 ++++----- 21 files changed, 107 insertions(+), 107 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 0b8a73c40b12..24104eaae6d3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1492,7 +1492,7 @@ 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)) { + !(handle->kinfo.netdev->active_features & NETIF_F_HW_VLAN_CTAG_TX)) { /* 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. @@ -2394,7 +2394,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) { - netdev_features_t changed = netdev->features ^ features; + netdev_features_t changed = netdev->active_features ^ features; struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = priv->ae_handle; bool enable; @@ -2420,7 +2420,7 @@ static int hns3_nic_set_features(struct net_device *netdev, h->ae_algo->ops->enable_fd(h, enable); }
- if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) && + if ((netdev->active_features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) && h->ae_algo->ops->cls_flower_active(h)) { netdev_err(netdev, "there are offloaded TC filters active, cannot disable HW TC offload"); @@ -2435,7 +2435,7 @@ static int hns3_nic_set_features(struct net_device *netdev, return ret; }
- netdev->features = features; + netdev->active_features = features; return 0; }
@@ -3236,7 +3236,7 @@ static void hns3_set_default_feature(struct net_device *netdev)
netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
- netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | + netdev->active_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 | @@ -3244,31 +3244,31 @@ static void hns3_set_default_feature(struct net_device *netdev) NETIF_F_SCTP_CRC | NETIF_F_FRAGLIST;
if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { - netdev->features |= NETIF_F_GRO_HW; + netdev->active_features |= NETIF_F_GRO_HW;
if (!(h->flags & HNAE3_SUPPORT_VF)) - netdev->features |= NETIF_F_NTUPLE; + netdev->active_features |= NETIF_F_NTUPLE; }
if (test_bit(HNAE3_DEV_SUPPORT_UDP_GSO_B, ae_dev->caps)) - netdev->features |= NETIF_F_GSO_UDP_L4; + netdev->active_features |= NETIF_F_GSO_UDP_L4;
if (test_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps)) - netdev->features |= NETIF_F_HW_CSUM; + netdev->active_features |= NETIF_F_HW_CSUM; else - netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + netdev->active_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
if (test_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps)) - netdev->features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; + netdev->active_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
if (test_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps)) - netdev->features |= NETIF_F_HW_TC; + netdev->active_features |= NETIF_F_HW_TC;
- netdev->hw_features |= netdev->features; + netdev->hw_features |= netdev->active_features; 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 & + netdev->vlan_features |= netdev->active_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); @@ -3847,7 +3847,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_features & NETIF_F_RXCSUM)) return;
if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) @@ -4138,7 +4138,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_features & NETIF_F_HW_VLAN_CTAG_RX) { 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 6469238ae090..6db162eec2c2 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) + ndev->active_features & NETIF_F_HW_VLAN_CTAG_FILTER) 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) + ndev->active_features & NETIF_F_HW_VLAN_CTAG_FILTER) h->ae_algo->ops->enable_vlan_filter(h, true); #endif
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 50d535981a35..56303984d936 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1360,7 +1360,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx) NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM;
hw_enc_features |= encap_tso_features | NETIF_F_TSO; - efx->net_dev->features |= encap_tso_features; + efx->net_dev->active_features |= encap_tso_features; } efx->net_dev->hw_enc_features = hw_enc_features;
@@ -2694,7 +2694,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 (!(efx->net_dev->active_features & NETIF_F_RXALL)) { 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_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index a07cbf45a326..0ddd3d69bd5e 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -189,7 +189,7 @@ static int efx_ef100_init_datapath_caps(struct efx_nic *efx) NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE | NETIF_F_GSO_GRE_CSUM;
- net_dev->features |= tso; + net_dev->active_features |= tso; net_dev->hw_features |= tso; net_dev->hw_enc_features |= tso; /* EF100 HW can only offload outer checksums if they are UDP, @@ -1123,7 +1123,7 @@ static int ef100_probe_main(struct efx_nic *efx) return -ENOMEM; efx->nic_data = nic_data; nic_data->efx = efx; - net_dev->features |= efx->type->offload_features; + net_dev->active_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 | diff --git a/drivers/net/ethernet/sfc/ef100_rx.c b/drivers/net/ethernet/sfc/ef100_rx.c index 85207acf7dee..63309527fb28 100644 --- a/drivers/net/ethernet/sfc/ef100_rx.c +++ b/drivers/net/ethernet/sfc/ef100_rx.c @@ -64,7 +64,7 @@ void __ef100_rx_packet(struct efx_channel *channel) prefix = (u32 *)(eh - ESE_GZ_RX_PKT_PREFIX_LEN);
if (ef100_has_fcs_error(channel, prefix) && - unlikely(!(efx->net_dev->features & NETIF_F_RXALL))) + unlikely(!(efx->net_dev->active_features & NETIF_F_RXALL))) goto out;
rx_buf->len = le16_to_cpu((__force __le16)PREFIX_FIELD(prefix, LENGTH)); @@ -76,7 +76,7 @@ void __ef100_rx_packet(struct efx_channel *channel) goto out; }
- if (likely(efx->net_dev->features & NETIF_F_RXCSUM)) { + if (likely(efx->net_dev->active_features & NETIF_F_RXCSUM)) { if (PREFIX_FIELD(prefix, NT_OR_INNER_L3_CLASS) == 1) { ++channel->n_rx_ip_hdr_chksum_err; } else { diff --git a/drivers/net/ethernet/sfc/ef100_tx.c b/drivers/net/ethernet/sfc/ef100_tx.c index 26ef51d6b542..c388f4c7d913 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 (!(efx->net_dev->active_features & NETIF_F_TSO)) 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(efx->net_dev->active_features & NETIF_F_HW_CSUM)) ef100_set_tx_csum_partial(skb, buffer, txd); - if (efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_TX && + if (efx->net_dev->active_features & NETIF_F_HW_VLAN_CTAG_TX && 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 (efx->net_dev->active_features & NETIF_F_HW_VLAN_CTAG_TX) 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 302dc835ac3d..d7dff27a3e8e 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1004,29 +1004,29 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) }
/* Determine netdevice features */ - net_dev->features |= (efx->type->offload_features | NETIF_F_SG | + net_dev->active_features |= (efx->type->offload_features | NETIF_F_SG | NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_RXALL); if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM)) - net_dev->features |= NETIF_F_TSO6; + net_dev->active_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; + net_dev->active_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->hw_features |= net_dev->features & ~efx->fixed_features; + net_dev->hw_features |= net_dev->active_features & ~efx->fixed_features;
/* Disable receiving frames with bad FCS, by default. */ - net_dev->features &= ~NETIF_F_RXALL; + net_dev->active_features &= ~NETIF_F_RXALL;
/* 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; - net_dev->features |= efx->fixed_features; + net_dev->active_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + net_dev->active_features |= 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 af37c990217e..cee20b4a34e7 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -215,7 +215,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 */ - if (net_dev->features & ~data & NETIF_F_NTUPLE) { + if (net_dev->active_features & ~data & NETIF_F_NTUPLE) { rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); if (rc) return rc; @@ -224,8 +224,8 @@ 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)) { + if ((net_dev->active_features ^ data) & (NETIF_F_HW_VLAN_CTAG_FILTER | + NETIF_F_RXFCS)) { /* efx_set_rx_mode() will schedule MAC work to update filters * when a new features are finally set in net_dev. */ @@ -364,7 +364,7 @@ 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; + netdev_features_t old_features = efx->net_dev->active_features; bool old_rx_scatter = efx->rx_scatter; size_t rx_buf_len;
@@ -410,10 +410,10 @@ 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; + efx->net_dev->hw_features |= efx->net_dev->active_features; efx->net_dev->hw_features &= ~efx->fixed_features; - efx->net_dev->features |= efx->fixed_features; - if (efx->net_dev->features != old_features) + efx->net_dev->active_features |= efx->fixed_features; + if (efx->net_dev->active_features != 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 60c595ef7589..807ceda69c01 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -592,7 +592,7 @@ 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; + netdev_features_t old_features = efx->net_dev->active_features; bool old_rx_scatter = efx->rx_scatter; struct ef4_tx_queue *tx_queue; struct ef4_rx_queue *rx_queue; @@ -640,10 +640,10 @@ 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; + efx->net_dev->hw_features |= efx->net_dev->active_features; efx->net_dev->hw_features &= ~efx->fixed_features; - efx->net_dev->features |= efx->fixed_features; - if (efx->net_dev->features != old_features) + efx->net_dev->active_features |= efx->fixed_features; + if (efx->net_dev->active_features != old_features) netdev_features_change(efx->net_dev);
/* RX filters may also have scatter-enabled flags */ @@ -2191,14 +2191,14 @@ 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 */ - if (net_dev->features & ~data & NETIF_F_NTUPLE) { + if (net_dev->active_features & ~data & 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) { + if ((net_dev->active_features ^ data) & NETIF_F_HW_VLAN_CTAG_FILTER) { /* ef4_set_rx_mode() will schedule MAC work to update filters * when a new features are finally set in net_dev. */ @@ -2904,20 +2904,20 @@ 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->active_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);
- net_dev->hw_features = net_dev->features & ~efx->fixed_features; + net_dev->hw_features = net_dev->active_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 * receive VLAN tagged packets due to vPort restrictions). */ - net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; - net_dev->features |= efx->fixed_features; + net_dev->active_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + net_dev->active_features |= 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 a381cf9ec4f3..48fca3bccd1b 100644 --- a/drivers/net/ethernet/sfc/falcon/net_driver.h +++ b/drivers/net/ethernet/sfc/falcon/net_driver.h @@ -1302,7 +1302,7 @@ static inline netdev_features_t ef4_supported_features(const struct ef4_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return net_dev->features | net_dev->hw_features; + return net_dev->active_features | net_dev->hw_features; }
/* Get the current TX queue insert index. */ diff --git a/drivers/net/ethernet/sfc/falcon/rx.c b/drivers/net/ethernet/sfc/falcon/rx.c index 0c6cc2191369..49cc903768a6 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 (efx->net_dev->active_features & NETIF_F_RXHASH) 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(!(efx->net_dev->active_features & NETIF_F_RXCSUM))) rx_buf->flags &= ~EF4_RX_PKT_CSUMMED;
if ((rx_buf->flags & EF4_RX_PKT_TCP) && !channel->type->receive_skb) diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index 148dcd48b58d..8d0e328afb0d 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -921,7 +921,7 @@ static u16 efx_farch_handle_rx_not_ok(struct efx_rx_queue *rx_queue, (void) rx_ev_other_err; #endif
- if (efx->net_dev->features & NETIF_F_RXALL) + if (efx->net_dev->active_features & NETIF_F_RXALL) /* don't discard frame for CRC error */ rx_ev_eth_crc_err = false;
diff --git a/drivers/net/ethernet/sfc/mcdi_filters.c b/drivers/net/ethernet/sfc/mcdi_filters.c index 1523be77b9db..2ff62bc67e03 100644 --- a/drivers/net/ethernet/sfc/mcdi_filters.c +++ b/drivers/net/ethernet/sfc/mcdi_filters.c @@ -1326,7 +1326,7 @@ 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; + net_dev->active_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; } @@ -1340,7 +1340,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); + !!(efx->net_dev->active_features & NETIF_F_HW_VLAN_CTAG_FILTER); INIT_LIST_HEAD(&table->vlan_list); init_rwsem(&table->lock);
@@ -1757,7 +1757,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 = !!(net_dev->active_features & NETIF_F_HW_VLAN_CTAG_FILTER); 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..e6c8332e77fd 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)); + !!(efx->net_dev->active_features & NETIF_F_RXFCS));
switch (efx->wanted_fc) { case EFX_FC_RX | EFX_FC_TX: diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index c75dc75e2857..5aa4437a5768 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1687,7 +1687,7 @@ static inline netdev_features_t efx_supported_features(const struct efx_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return net_dev->features | net_dev->hw_features; + return net_dev->active_features | net_dev->hw_features; }
/* Get the current TX queue insert index. */ diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 2375cef577e4..1f7463d5df91 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(!(efx->net_dev->active_features & NETIF_F_RXCSUM))) 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 1b22c7be0088..c93e47f2d5bf 100644 --- a/drivers/net/ethernet/sfc/rx_common.c +++ b/drivers/net/ethernet/sfc/rx_common.c @@ -517,7 +517,7 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, return; }
- if (efx->net_dev->features & NETIF_F_RXHASH && + if (efx->net_dev->active_features & NETIF_F_RXHASH && efx_rx_buf_hash_valid(efx, eh)) skb_set_hash(skb, efx_rx_buf_hash(efx, eh), PKT_HASH_TYPE_L3); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 8cbe96ce0a2c..7307b9553bcf 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1724,7 +1724,7 @@ enum netdev_ml_priv_type { * @ptype_specific: Device-specific, protocol-specific packet handlers * * @adj_list: Directly linked devices, like slaves for bonding - * @features: Currently active device features + * @active_features: Currently active device features * @hw_features: User-changeable features * * @wanted_features: User-requested features @@ -2010,7 +2010,7 @@ struct net_device { unsigned short needed_headroom; unsigned short needed_tailroom;
- netdev_features_t features; + netdev_features_t active_features; netdev_features_t hw_features; netdev_features_t wanted_features; netdev_features_t vlan_features; @@ -2297,7 +2297,7 @@ struct net_device {
static inline bool netif_elide_gro(const struct net_device *dev) { - if (!(dev->features & NETIF_F_GRO) || dev->xdp_prog) + if (!(dev->active_features & NETIF_F_GRO) || dev->xdp_prog) return true; return false; } @@ -4318,7 +4318,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 ((dev->active_features & NETIF_F_LLTX) == 0) { \ __netif_tx_lock(txq, cpu); \ } else { \ __netif_tx_acquire(txq); \ @@ -4326,12 +4326,12 @@ static inline void netif_tx_unlock_bh(struct net_device *dev) }
#define HARD_TX_TRYLOCK(dev, txq) \ - (((dev->features & NETIF_F_LLTX) == 0) ? \ + (((dev->active_features & NETIF_F_LLTX) == 0) ? \ __netif_tx_trylock(txq) : \ __netif_tx_acquire(txq))
#define HARD_TX_UNLOCK(dev, txq) { \ - if ((dev->features & NETIF_F_LLTX) == 0) { \ + if ((dev->active_features & NETIF_F_LLTX) == 0) { \ __netif_tx_unlock(txq); \ } else { \ __netif_tx_release(txq); \ @@ -4832,7 +4832,7 @@ 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; + return (dev->active_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/core/dev.c b/net/core/dev.c index 75bab5b0dbae..a09ddbfb3086 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1580,7 +1580,7 @@ void dev_disable_lro(struct net_device *dev) dev->wanted_features &= ~NETIF_F_LRO; netdev_update_features(dev);
- if (unlikely(dev->features & NETIF_F_LRO)) + if (unlikely(dev->active_features & NETIF_F_LRO)) netdev_WARN(dev, "failed to disable LRO!\n");
netdev_for_each_lower_dev(dev, lower_dev, iter) @@ -1601,7 +1601,7 @@ static void dev_disable_gro_hw(struct net_device *dev) dev->wanted_features &= ~NETIF_F_GRO_HW; netdev_update_features(dev);
- if (unlikely(dev->features & NETIF_F_GRO_HW)) + if (unlikely(dev->active_features & NETIF_F_GRO_HW)) netdev_WARN(dev, "failed to disable GRO_HW!\n"); }
@@ -3172,7 +3172,7 @@ static void skb_warn_bad_offload(const struct sk_buff *skb) } skb_dump(KERN_WARNING, skb, false); WARN(1, "%s: caps=(%pNF, %pNF)\n", - name, dev ? &dev->features : &null_features, + name, dev ? &dev->active_features : &null_features, skb->sk ? &skb->sk->sk_route_caps : &null_features); }
@@ -3325,7 +3325,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t partial_features = NETIF_F_GSO_ROBUST; struct net_device *dev = skb->dev;
- partial_features |= dev->features & dev->gso_partial_features; + partial_features |= dev->active_features & dev->gso_partial_features; if (!skb_gso_ok(skb, features | partial_features)) features &= ~NETIF_F_GSO_PARTIAL; } @@ -3370,7 +3370,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 (!(dev->active_features & NETIF_F_HIGHDMA)) { for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -3477,7 +3477,7 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, netdev_features_t netif_skb_features(struct sk_buff *skb) { struct net_device *dev = skb->dev; - netdev_features_t features = dev->features; + netdev_features_t features = dev->active_features;
if (skb_is_gso(skb)) features = gso_features_check(skb, dev, features); @@ -4321,7 +4321,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)) + !(dev->active_features & NETIF_F_NTUPLE)) goto out; rxq_index = cpu_rmap_lookup_index(dev->rx_cpu_rmap, next_cpu); if (rxq_index == skb_get_rx_queue(skb)) @@ -9448,13 +9448,13 @@ static void netdev_sync_lower_features(struct net_device *upper,
for_each_netdev_feature(upper_disables, feature_bit) { feature = __NETIF_F_BIT(feature_bit); - if (!(features & feature) && (lower->features & feature)) { + if (!(features & feature) && (lower->active_features & feature)) { netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", &feature, lower->name); lower->wanted_features &= ~feature; __netdev_update_features(lower);
- if (unlikely(lower->features & feature)) + if (unlikely(lower->active_features & feature)) netdev_WARN(upper, "failed to disable %pNF on %s!\n", &feature, lower->name); else @@ -9584,11 +9584,11 @@ 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 (dev->active_features == features) goto sync_lower;
netdev_dbg(dev, "Features changed: %pNF -> %pNF\n", - &dev->features, &features); + &dev->active_features, &features);
if (dev->netdev_ops->ndo_set_features) err = dev->netdev_ops->ndo_set_features(dev, features); @@ -9598,7 +9598,7 @@ int __netdev_update_features(struct net_device *dev) if (unlikely(err < 0)) { netdev_err(dev, "set_features() failed (%d); wanted %pNF, left %pNF\n", - err, &features, &dev->features); + err, &features, &dev->active_features); /* return non-0 since some features might have changed and * it's better to fire a spurious notification than miss it */ @@ -9613,7 +9613,7 @@ int __netdev_update_features(struct net_device *dev) netdev_sync_lower_features(dev, lower, features);
if (!err) { - netdev_features_t diff = features ^ dev->features; + netdev_features_t diff = features ^ dev->active_features;
if (diff & NETIF_F_RX_UDP_TUNNEL_PORT) { /* udp_tunnel_{get,drop}_rx_info both need @@ -9624,7 +9624,7 @@ int __netdev_update_features(struct net_device *dev) * but *after* calling udp_tunnel_drop_rx_info. */ if (features & NETIF_F_RX_UDP_TUNNEL_PORT) { - dev->features = features; + dev->active_features = features; udp_tunnel_get_rx_info(dev); } else { udp_tunnel_drop_rx_info(dev); @@ -9633,7 +9633,7 @@ int __netdev_update_features(struct net_device *dev)
if (diff & NETIF_F_HW_VLAN_CTAG_FILTER) { if (features & NETIF_F_HW_VLAN_CTAG_FILTER) { - dev->features = features; + dev->active_features = features; err |= vlan_get_rx_ctag_filter_info(dev); } else { vlan_drop_rx_ctag_filter_info(dev); @@ -9642,14 +9642,14 @@ int __netdev_update_features(struct net_device *dev)
if (diff & NETIF_F_HW_VLAN_STAG_FILTER) { if (features & NETIF_F_HW_VLAN_STAG_FILTER) { - dev->features = features; + dev->active_features = features; err |= vlan_get_rx_stag_filter_info(dev); } else { vlan_drop_rx_stag_filter_info(dev); } }
- dev->features = features; + dev->active_features = features; }
return err < 0 ? 0 : 1; @@ -9875,7 +9875,7 @@ int register_netdevice(struct net_device *dev) } }
- if (((dev->hw_features | dev->features) & + if (((dev->hw_features | dev->active_features) & NETIF_F_HW_VLAN_CTAG_FILTER) && (!dev->netdev_ops->ndo_vlan_rx_add_vid || !dev->netdev_ops->ndo_vlan_rx_kill_vid)) { @@ -9894,14 +9894,14 @@ int register_netdevice(struct net_device *dev) * software offloads (GSO and GRO). */ dev->hw_features |= (NETIF_F_SOFT_FEATURES | NETIF_F_SOFT_FEATURES_OFF); - dev->features |= NETIF_F_SOFT_FEATURES; + dev->active_features |= NETIF_F_SOFT_FEATURES;
if (dev->udp_tunnel_nic_info) { - dev->features |= NETIF_F_RX_UDP_TUNNEL_PORT; + dev->active_features |= NETIF_F_RX_UDP_TUNNEL_PORT; dev->hw_features |= NETIF_F_RX_UDP_TUNNEL_PORT; }
- dev->wanted_features = dev->features & dev->hw_features; + dev->wanted_features = dev->active_features & dev->hw_features;
if (!(dev->flags & IFF_LOOPBACK)) dev->hw_features |= NETIF_F_NOCACHE_COPY; @@ -10817,7 +10817,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 (dev->active_features & NETIF_F_NETNS_LOCAL) goto out;
/* Ensure the device has been registrered */ @@ -11176,7 +11176,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 (dev->active_features & NETIF_F_NETNS_LOCAL) continue;
/* Leave virtual devices for the generic cleanup */ diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 55d449a2d3fc..a43f82515de8 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -43,7 +43,7 @@ static int features_prepare_data(const struct ethnl_req_info *req_base,
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->active, dev->active_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); @@ -234,7 +234,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) dev = req_info.dev;
rtnl_lock(); - ethnl_features_to_bitmap(old_active, dev->features); + ethnl_features_to_bitmap(old_active, dev->active_features); ethnl_features_to_bitmap(old_wanted, dev->wanted_features); ret = ethnl_parse_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT, tb[ETHTOOL_A_FEATURES_WANTED], @@ -256,7 +256,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) dev->wanted_features |= ethnl_bitmap_to_features(req_wanted) & dev->hw_features; __netdev_update_features(dev); } - ethnl_features_to_bitmap(new_active, dev->features); + ethnl_features_to_bitmap(new_active, dev->active_features); mod = !bitmap_equal(old_active, new_active, NETDEV_FEATURE_COUNT);
ret = 0; diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 326e14ee05db..1c7f24316b3d 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -98,7 +98,7 @@ static int ethtool_get_features(struct net_device *dev, void __user *useraddr) 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].active = (u32)(dev->active_features >> (32 * i)); features[i].never_changed = (u32)(NETIF_F_NEVER_CHANGE >> (32 * i)); } @@ -154,7 +154,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) dev->wanted_features |= wanted & valid; __netdev_update_features(dev);
- if ((dev->wanted_features ^ dev->features) & valid) + if ((dev->wanted_features ^ dev->active_features) & valid) ret |= ETHTOOL_F_WISH;
return ret; @@ -254,7 +254,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 = !!(dev->active_features & mask), };
if (copy_to_user(useraddr, &edata, sizeof(edata))) @@ -296,15 +296,15 @@ static u32 __ethtool_get_flags(struct net_device *dev) { u32 flags = 0;
- if (dev->features & NETIF_F_LRO) + if (dev->active_features & NETIF_F_LRO) flags |= ETH_FLAG_LRO; - if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) + if (dev->active_features & NETIF_F_HW_VLAN_CTAG_RX) flags |= ETH_FLAG_RXVLAN; - if (dev->features & NETIF_F_HW_VLAN_CTAG_TX) + if (dev->active_features & NETIF_F_HW_VLAN_CTAG_TX) flags |= ETH_FLAG_TXVLAN; - if (dev->features & NETIF_F_NTUPLE) + if (dev->active_features & NETIF_F_NTUPLE) flags |= ETH_FLAG_NTUPLE; - if (dev->features & NETIF_F_RXHASH) + if (dev->active_features & NETIF_F_RXHASH) flags |= ETH_FLAG_RXHASH;
return flags; @@ -329,7 +329,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) features |= NETIF_F_RXHASH;
/* allow changing only bits set in hw_features */ - changed = (features ^ dev->features) & ETH_ALL_FEATURES; + changed = (features ^ dev->active_features) & ETH_ALL_FEATURES; if (changed & ~dev->hw_features) return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
@@ -2800,7 +2800,7 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr, if (rc < 0) goto out; } - old_features = dev->features; + old_features = dev->active_features;
switch (ethcmd) { case ETHTOOL_GSET: @@ -3015,7 +3015,7 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr, if (dev->ethtool_ops->complete) dev->ethtool_ops->complete(dev);
- if (old_features != dev->features) + if (old_features != dev->active_features) netdev_features_change(dev); out: if (dev->dev.parent)
On Thu, 24 Mar 2022 23:49:13 +0800 Jian Shen wrote:
The net_device->features indicates the active features of the net device, rename it to active_features, make it esaier to define feature helpers.
This breaks the build.
On Thu, 24 Mar 2022 17:58:32 -0700 Jakub Kicinski wrote:
On Thu, 24 Mar 2022 23:49:13 +0800 Jian Shen wrote:
The net_device->features indicates the active features of the net device, rename it to active_features, make it esaier to define feature helpers.
This breaks the build.
I see you mention that the work is not complete in the cover letter. Either way this patch seems unnecessary, you can call the helpers for "active" features like you do, but don't start by renaming the existing field. The patch will be enormous.
在 2022/3/25 9:03, Jakub Kicinski 写道:
On Thu, 24 Mar 2022 17:58:32 -0700 Jakub Kicinski wrote:
On Thu, 24 Mar 2022 23:49:13 +0800 Jian Shen wrote:
The net_device->features indicates the active features of the net device, rename it to active_features, make it esaier to define feature helpers.
This breaks the build.
I see you mention that the work is not complete in the cover letter. Either way this patch seems unnecessary, you can call the helpers for "active" features like you do, but don't start by renaming the existing field. The patch will be enormous. .
I agree that this patch will be enormous, I made this patch from suggestion from Andrew Lunn in RFCv3.[1] Willit make people confused for help name inconsistent with feature name ?
On Fri, 25 Mar 2022 09:29:51 +0800 shenjian (K) wrote:
在 2022/3/25 9:03, Jakub Kicinski 写道:
I see you mention that the work is not complete in the cover letter. Either way this patch seems unnecessary, you can call the helpers for "active" features like you do, but don't start by renaming the existing field. The patch will be enormous. .
I agree that this patch will be enormous, I made this patch from suggestion from Andrew Lunn in RFCv3.[1] Willit make people confused for help name inconsistent with feature name ?
Thanks, not sure if I see a suggestion there from Andrew or just a question. Maybe you can add a comment instead to avoid surprising people?
在 2022/3/25 9:35, Jakub Kicinski 写道:
On Fri, 25 Mar 2022 09:29:51 +0800 shenjian (K) wrote:
在 2022/3/25 9:03, Jakub Kicinski 写道:
I see you mention that the work is not complete in the cover letter. Either way this patch seems unnecessary, you can call the helpers for "active" features like you do, but don't start by renaming the existing field. The patch will be enormous. .
I agree that this patch will be enormous, I made this patch from suggestion from Andrew Lunn in RFCv3.[1] Willit make people confused for help name inconsistent with feature name ?
Thanks, not sure if I see a suggestion there from Andrew or just a question. Maybe you can add a comment instead to avoid surprising people? .
ok, will drop this patch
On Thu, Mar 24, 2022 at 06:35:49PM -0700, Jakub Kicinski wrote:
On Fri, 25 Mar 2022 09:29:51 +0800 shenjian (K) wrote:
在 2022/3/25 9:03, Jakub Kicinski 写道:
I see you mention that the work is not complete in the cover letter. Either way this patch seems unnecessary, you can call the helpers for "active" features like you do, but don't start by renaming the existing field. The patch will be enormous. .
I agree that this patch will be enormous, I made this patch from suggestion from Andrew Lunn in RFCv3.[1] Willit make people confused for help name inconsistent with feature name ?
Thanks, not sure if I see a suggestion there from Andrew or just a question. Maybe you can add a comment instead to avoid surprising people?
Goes and looks at what i wrote.
Here _hw_ makes sense. But i think we need some sort of consistency. Either drop the _active_ from the function name, or rename the netdev field active_features.
So i suggested an either/or. In retrospect, the or seems like a bad idea, this patch will be enormous. So i would suggest the other option, netdev_set_active_features() gets renamed to netdev_set__features()
Andrew
On Fri, 25 Mar 2022 16:52:29 +0100 Andrew Lunn wrote:
Here _hw_ makes sense. But i think we need some sort of consistency. Either drop the _active_ from the function name, or rename the netdev field active_features.
So i suggested an either/or. In retrospect, the or seems like a bad idea, this patch will be enormous. So i would suggest the other option, netdev_set_active_features() gets renamed to netdev_set__features()
SGTM! Just clarify if you meant the double underscore or it's a coincidence? :)
On Fri, Mar 25, 2022 at 08:58:58AM -0700, Jakub Kicinski wrote:
On Fri, 25 Mar 2022 16:52:29 +0100 Andrew Lunn wrote:
Here _hw_ makes sense. But i think we need some sort of consistency. Either drop the _active_ from the function name, or rename the netdev field active_features.
So i suggested an either/or. In retrospect, the or seems like a bad idea, this patch will be enormous. So i would suggest the other option, netdev_set_active_features() gets renamed to netdev_set__features()
SGTM! Just clarify if you meant the double underscore or it's a coincidence? :)
TypO.
Andrew
Introduce a set of bitmap operation helpers for netdev features, then we can use them to replace the logical operation with them. As the nic driversare not supposed to modify netdev_features directly, it also introduces wrappers helpers to this.
The implementation of these helpers are based on the old prototype of netdev_features_t is still u64. I will rewrite them on the last patch, when the prototype changes.
Signed-off-by: Jian Shen shenjian15@huawei.com --- include/linux/netdevice.h | 597 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 597 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7307b9553bcf..0af4b26896d6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2295,6 +2295,603 @@ struct net_device { }; #define to_net_dev(d) container_of(d, struct net_device, dev)
+static inline void netdev_features_zero(netdev_features_t *dst) +{ + *dst = 0; +} + +static inline void netdev_features_fill(netdev_features_t *dst) +{ + *dst = ~0ULL; +} + +static inline bool netdev_features_empty(const netdev_features_t src) +{ + return src == 0; +} + +/* helpers for netdev features '==' operation */ +static inline bool netdev_features_equal(const netdev_features_t src1, + const netdev_features_t src2) +{ + return src1 == src2; +} + +#define netdev_active_features_equal(ndev, features) \ + netdev_features_equal(ndev->active_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->vlan_features, features) + +#define netdev_mpls_features_equal(ndev, features) \ + netdev_features_equal(ndev->vlan_features, features) + +#define netdev_gso_partial_features_equal(ndev, features) \ + netdev_features_equal(ndev->vlan_features, features) + +/* helpers for netdev features '&' operation */ +static inline netdev_features_t +netdev_features_and(const netdev_features_t a, const netdev_features_t b) +{ + return a & b; +} + +#define netdev_active_features_and(ndev, features) \ + netdev_features_and(ndev->active_features, features) + +#define netdev_hw_features_and(ndev, features) \ + netdev_features_and(ndev->hw_features, features) + +#define netdev_wanted_features_and(ndev, features) \ + netdev_features_and(ndev->wanted_features, features) + +#define netdev_vlan_features_and(ndev, features) \ + netdev_features_and(ndev->vlan_features, features) + +#define netdev_hw_enc_features_and(ndev, features) \ + netdev_features_and(ndev->hw_enc_features, features) + +#define netdev_mpls_features_and(ndev, features) \ + netdev_features_and(ndev->mpls_features, features) + +#define netdev_gso_partial_features_and(ndev, features) \ + netdev_features_and(ndev->gso_partial_features, features) + +/* helpers for netdev features '&=' operation */ +static inline void +netdev_features_direct_and(netdev_features_t *dst, + const netdev_features_t features) +{ + *dst = netdev_features_and(*dst, features); +} + +static inline void +netdev_active_features_direct_and(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->active_features = netdev_active_features_and(ndev, features); +} + +static inline void +netdev_hw_features_direct_and(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_features = netdev_hw_features_and(ndev, features); +} + +static inline void +netdev_wanted_features_direct_and(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->wanted_features = netdev_wanted_features_and(ndev, features); +} + +static inline void +netdev_vlan_features_direct_and(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->vlan_features = netdev_vlan_features_and(ndev, features); +} + +static inline void +netdev_hw_enc_features_direct_and(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_enc_features = netdev_hw_enc_features_and(ndev, features); +} + +static inline void +netdev_mpls_features_direct_and(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->mpls_features = netdev_mpls_features_and(ndev, features); +} + +static inline void +netdev_gso_partial_features_direct_and(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->gso_partial_features = netdev_mpls_features_and(ndev, features); +} + +/* helpers for netdev features '|' operation */ +static inline netdev_features_t +netdev_features_or(const netdev_features_t a, const netdev_features_t b) +{ + return a | b; +} + +#define netdev_active_features_or(ndev, features) \ + netdev_features_or(ndev->active_features, features) + +#define netdev_hw_features_or(ndev, features) \ + netdev_features_or(ndev->hw_features, features) + +#define netdev_wanted_features_or(ndev, features) \ + netdev_features_or(ndev->wanted_features, features) + +#define netdev_vlan_features_or(ndev, features) \ + netdev_features_or(ndev->vlan_features, features) + +#define netdev_hw_enc_features_or(ndev, features) \ + netdev_features_or(ndev->hw_enc_features, features) + +#define netdev_mpls_features_or(ndev, features) \ + netdev_features_or(ndev->mpls_features, features) + +#define netdev_gso_partial_features_or(ndev, features) \ + netdev_features_or(ndev->gso_partial_features, features) + +/* helpers for netdev features '|=' operation */ +static inline void +netdev_features_direct_or(netdev_features_t *dst, + const netdev_features_t features) +{ + *dst = netdev_features_or(*dst, features); +} + +static inline void +netdev_active_features_direct_or(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->active_features = netdev_active_features_or(ndev, features); +} + +static inline void +netdev_hw_features_direct_or(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_features = netdev_hw_features_or(ndev, features); +} + +static inline void +netdev_wanted_features_direct_or(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->wanted_features = netdev_wanted_features_or(ndev, features); +} + +static inline void +netdev_vlan_features_direct_or(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->vlan_features = netdev_vlan_features_or(ndev, features); +} + +static inline void +netdev_hw_enc_features_direct_or(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_enc_features = netdev_hw_enc_features_or(ndev, features); +} + +static inline void +netdev_mpls_features_direct_or(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->mpls_features = netdev_mpls_features_or(ndev, features); +} + +static inline void +netdev_gso_partial_features_direct_or(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->gso_partial_features = netdev_mpls_features_or(ndev, features); +} + +/* helpers for netdev features '^' operation */ +static inline netdev_features_t +netdev_features_xor(const netdev_features_t a, const netdev_features_t b) +{ + return a ^ b; +} + +#define netdev_active_features_xor(ndev, features) \ + netdev_features_xor(ndev->active_features, features) + +#define netdev_hw_features_xor(ndev, features) \ + netdev_features_xor(ndev->hw_features, features) + +#define netdev_wanted_features_xor(ndev, features) \ + netdev_features_xor(ndev->wanted_features, features) + +#define netdev_vlan_features_xor(ndev, features) \ + netdev_features_xor(ndev->vlan_features, features) + +#define netdev_hw_enc_features_xor(ndev, features) \ + netdev_features_xor(ndev->hw_enc_features, features) + +#define netdev_mpls_features_xor(ndev, features) \ + netdev_features_xor(ndev->mpls_features, features) + +#define netdev_gso_partial_features_xor(ndev, features) \ + netdev_features_xor(ndev->gso_partial_features, features) + +/* helpers for netdev features '^=' operation */ +static inline void +netdev_active_features_direct_xor(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->active_features = netdev_active_features_xor(ndev, features); +} + +static inline void +netdev_hw_features_direct_xor(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_features = netdev_hw_features_xor(ndev, features); +} + +static inline void +netdev_wanted_features_direct_xor(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->wanted_features = netdev_wanted_features_xor(ndev, features); +} + +static inline void +netdev_vlan_features_direct_xor(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->vlan_features = netdev_vlan_features_xor(ndev, features); +} + +static inline void +netdev_hw_enc_features_direct_xor(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_enc_features = netdev_hw_enc_features_xor(ndev, features); +} + +static inline void +netdev_mpls_features_direct_xor(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->mpls_features = netdev_mpls_features_xor(ndev, features); +} + +static inline void +netdev_gso_partial_features_direct_xor(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->gso_partial_features = + netdev_gso_partial_features_xor(ndev, features); +} + +/* helpers for netdev features '& ~' operation */ +static inline netdev_features_t +netdev_features_andnot(const netdev_features_t a, const netdev_features_t b) +{ + return a & ~b; +} + +#define netdev_active_features_andnot(ndev, features) \ + netdev_features_andnot(ndev->active_features, features) + +#define netdev_hw_features_andnot(ndev, features) \ + netdev_features_andnot(ndev->hw_features, features) + +#define netdev_wanted_features_andnot(ndev, features) \ + netdev_features_andnot(ndev->wanted_features, features) + +#define netdev_vlan_features_andnot(ndev, features) \ + netdev_features_andnot(ndev->vlan_features, features) + +#define netdev_hw_enc_features_andnot(ndev, features) \ + netdev_features_andnot(ndev->hw_enc_features, features) + +#define netdev_mpls_features_andnot(ndev, features) \ + netdev_features_andnot(ndev->mpls_features, features) + +#define netdev_gso_partial_features_andnot(ndev, features) \ + netdev_features_andnot(ndev->gso_partial_features, features) + +#define netdev_active_features_andnot_r(ndev, features) \ + netdev_features_andnot(features, ndev->active_features) + +#define netdev_hw_features_andnot_r(ndev, features) \ + netdev_features_andnot(features, ndev->hw_features) + +#define netdev_wanted_features_andnot_r(ndev, features) \ + netdev_features_andnot(features, ndev->wanted_features) + +#define netdev_vlan_features_andnot_r(ndev, features) \ + netdev_features_andnot(features, ndev->vlan_features) + +#define netdev_hw_enc_features_andnot_r(ndev, features) \ + netdev_features_andnot(features, ndev->hw_enc_features) + +#define netdev_mpls_features_andnot_r(ndev, features) \ + netdev_features_andnot(features, ndev->mpls_features) + +#define netdev_gso_partial_features_andnot_r(ndev, features) \ + netdev_features_andnot(features, ndev->gso_partial_features) + +static inline void +netdev_features_direct_andnot(netdev_features_t *dst, + const netdev_features_t features) +{ + *dst = netdev_features_andnot(*dst, features); +} + +static inline void +netdev_active_features_direct_andnot(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->active_features = netdev_active_features_andnot(ndev, features); +} + +static inline void +netdev_hw_features_direct_andnot(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_features = netdev_hw_features_andnot(ndev, features); +} + +static inline void +netdev_wanted_features_direct_andnot(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->wanted_features = netdev_wanted_features_andnot(ndev, features); +} + +static inline void +netdev_vlan_features_direct_andnot(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->vlan_features = netdev_vlan_features_andnot(ndev, features); +} + +static inline void +netdev_hw_enc_features_direct_andnot(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->hw_enc_features = netdev_hw_enc_features_andnot(ndev, features); +} + +static inline void +netdev_mpls_features_direct_andnot(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->mpls_features = netdev_mpls_features_andnot(ndev, features); +} + +static inline void +netdev_gso_partial_features_direct_andnot(struct net_device *ndev, + const netdev_features_t features) +{ + ndev->gso_partial_features = + netdev_gso_partial_features_andnot(ndev, features); +} + +/* helpers for netdev features 'set bit' operation */ +static inline void netdev_features_set_bit(int nr, netdev_features_t *src) +{ + *src |= __NETIF_F_BIT(nr); +} + +#define netdev_active_features_set_bit(ndev, nr) \ + netdev_features_set_bit(nr, &ndev->active_features) + +#define netdev_hw_features_set_bit(ndev, nr) \ + netdev_features_set_bit(nr, &ndev->hw_features) + +#define netdev_wanted_features_set_bit(ndev, nr) \ + netdev_features_set_bit(nr, &ndev->wanted_features) + +#define netdev_vlan_features_set_bit(ndev, nr) \ + netdev_features_set_bit(nr, &ndev->vlan_features) + +#define netdev_hw_enc_features_set_bit(ndev, nr) \ + netdev_features_set_bit(nr, &ndev->hw_enc_features) + +#define netdev_mpls_features_set_bit(ndev, nr) \ + netdev_features_set_bit(nr, &ndev->mpls_features) + +#define netdev_gso_partial_features_set_bit(ndev, nr) \ + netdev_features_set_bit(nr, &ndev->gso_partial_features) + +/* helpers for netdev features 'set bit array' operation */ +static inline void netdev_features_set_array(const int *array, int array_size, + netdev_features_t *dst) +{ + int i; + + for (i = 0; i < array_size; i++) + netdev_features_set_bit(array[i], dst); +} + +#define netdev_active_features_set_array(ndev, array, array_size) \ + netdev_features_set_array(array, array_size, &ndev->active_features) + +#define netdev_hw_features_set_array(ndev, array, array_size) \ + netdev_features_set_array(array, array_size, &ndev->hw_features) + +#define netdev_wanted_features_set_array(ndev, array, array_size) \ + netdev_features_set_array(array, array_size, &ndev->wanted_features) + +#define netdev_vlan_features_set_array(ndev, array, array_size) \ + netdev_features_set_array(array, array_size, &ndev->vlan_features) + +#define netdev_hw_enc_features_set_array(ndev, array, array_size) \ + netdev_features_set_array(array, array_size, &ndev->hw_enc_features) + +#define netdev_mpls_features_set_array(ndev, array, array_size) \ + netdev_features_set_array(array, array_size, &ndev->mpls_features) + +#define netdev_gso_partial_features_set_array(ndev, array, array_size) \ + netdev_features_set_array(array, array_size, &ndev->gso_partial_features) + +/* helpers for netdev features 'clear bit' operation */ +static inline void netdev_features_clear_bit(int nr, netdev_features_t *src) +{ + *src &= ~__NETIF_F_BIT(nr); +} + +#define netdev_active_features_clear_bit(ndev, nr) \ + netdev_features_clear_bit(nr, &ndev->active_features) + +#define netdev_hw_features_clear_bit(ndev, nr) \ + netdev_features_clear_bit(nr, &ndev->hw_features) + +#define netdev_wanted_features_clear_bit(ndev, nr) \ + netdev_features_clear_bit(nr, &ndev->wanted_features) + +#define netdev_vlan_features_clear_bit(ndev, nr) \ + netdev_features_clear_bit(nr, &ndev->vlan_features) + +#define netdev_hw_enc_features_clear_bit(ndev, nr) \ + netdev_features_clear_bit(nr, &ndev->hw_enc_features) + +#define netdev_mpls_features_clear_bit(ndev, nr) \ + netdev_features_clear_bit(nr, &ndev->mpls_features) + +#define netdev_gso_partial_features_clear_bit(ndev, nr) \ + netdev_features_clear_bit(nr, &ndev->gso_partial_features) + +/* helpers for netdev features 'test bit' operation */ +static inline bool netdev_features_test_bit(int nr, const netdev_features_t src) +{ + return (src & __NETIF_F_BIT(nr)) > 0; +} + +#define netdev_active_features_test_bit(ndev, nr) \ + netdev_features_test_bit(nr, ndev->active_features) + +#define netdev_hw_features_test_bit(ndev, nr) \ + netdev_features_test_bit(nr, ndev->hw_features) + +#define netdev_wanted_features_test_bit(ndev, nr) \ + netdev_features_test_bit(nr, ndev->wanted_features) + +#define netdev_vlan_features_test_bit(ndev, nr) \ + netdev_features_test_bit(nr, ndev->vlan_features) + +#define netdev_hw_enc_features_test_bit(ndev, nr) \ + netdev_features_test_bit(nr, ndev->hw_enc_features) + +#define netdev_mpls_features_test_bit(ndev, nr) \ + netdev_features_test_bit(nr, ndev->mpls_features) + +#define netdev_gso_partial_features_test_bit(ndev, nr) \ + netdev_features_test_bit(nr, ndev->gso_partial_features) + +static inline bool netdev_features_intersects(const netdev_features_t src1, + const netdev_features_t src2) +{ + return (src1 & src2) > 0; +} + +#define netdev_active_features_intersects(ndev, features) \ + netdev_features_intersects(ndev->active_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_set_active_features(struct net_device *netdev, + const netdev_features_t src) +{ + netdev->active_features = src; +} + +static inline void netdev_set_hw_features(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->hw_features = src; +} + +static inline void netdev_set_wanted_features(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->wanted_features = src; +} + +static inline void netdev_set_vlan_features(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->vlan_features = src; +} + +static inline void netdev_set_hw_enc_features(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->hw_enc_features = src; +} + +static inline void netdev_set_mpls_features(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->mpls_features = src; +} + +static inline void netdev_set_gso_partial_features(struct net_device *ndev, + const netdev_features_t src) +{ + ndev->gso_partial_features = src; +} + +/* helpers for netdev features 'get' operation */ +#define netdev_active_features(ndev) ((ndev)->active_features) +#define netdev_hw_features(ndev) ((ndev)->hw_features) +#define netdev_wanted_features(ndev) ((ndev)->wanted_features) +#define netdev_vlan_features(ndev) ((ndev)->vlan_features) +#define netdev_hw_enc_features(ndev) ((ndev)->hw_enc_features) +#define netdev_mpls_features(ndev) ((ndev)->mpls_features) +#define netdev_gso_partial_features(ndev) ((ndev)->gso_partial_features) + +/* helpers for netdev features 'subset' */ +static inline bool netdev_features_subset(const netdev_features_t src1, + const netdev_features_t src2) +{ + return (src1 & src2) == src2; +} + static inline bool netif_elide_gro(const struct net_device *dev) { if (!(dev->active_features & NETIF_F_GRO) || dev->xdp_prog)
On Thu, 24 Mar 2022 23:49:14 +0800 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. As the nic driversare not supposed to modify netdev_features directly, it also introduces wrappers helpers to this.
The implementation of these helpers are based on the old prototype of netdev_features_t is still u64. I will rewrite them on the last patch, when the prototype changes.
Signed-off-by: Jian Shen shenjian15@huawei.com
include/linux/netdevice.h | 597 ++++++++++++++++++++++++++++++++++++++
Please move these helpers to a new header file which won't be included by netdevice.h and include it at users appropriately.
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7307b9553bcf..0af4b26896d6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2295,6 +2295,603 @@ struct net_device { }; #define to_net_dev(d) container_of(d, struct net_device, dev)
+static inline void netdev_features_zero(netdev_features_t *dst) +{
- *dst = 0;
+}
+static inline void netdev_features_fill(netdev_features_t *dst) +{
- *dst = ~0ULL;
+}
+static inline bool netdev_features_empty(const netdev_features_t src)
Don't pass by value something larger than 64 bit.
+{
- return src == 0;
+}
+/* helpers for netdev features '==' operation */ +static inline bool netdev_features_equal(const netdev_features_t src1,
const netdev_features_t src2)
+{
- return src1 == src2;
+}
+/* helpers for netdev features '&=' operation */ +static inline void +netdev_features_direct_and(netdev_features_t *dst,
const netdev_features_t features)
+{
- *dst = netdev_features_and(*dst, features);
+}
+static inline void +netdev_active_features_direct_and(struct net_device *ndev,
s/direct_and/mask/ ?
const netdev_features_t features)
+{
- ndev->active_features = netdev_active_features_and(ndev, features);
+}
+/* helpers for netdev features '|' operation */ +static inline netdev_features_t +netdev_features_or(const netdev_features_t a, const netdev_features_t b) +{
- return a | b;
+}
+/* helpers for netdev features '|=' operation */ +static inline void +netdev_features_direct_or(netdev_features_t *dst,
s/direct_or/set/ ?
const netdev_features_t features)
+{
- *dst = netdev_features_or(*dst, features);
+}
+/* helpers for netdev features '^' operation */ +static inline netdev_features_t +netdev_features_xor(const netdev_features_t a, const netdev_features_t b) +{
- return a ^ b;
+}
+/* helpers for netdev features '^=' operation */ +static inline void +netdev_active_features_direct_xor(struct net_device *ndev,
s/direct_xor/toggle/ ?
+/* helpers for netdev features '& ~' operation */ +static inline netdev_features_t +netdev_features_andnot(const netdev_features_t a, const netdev_features_t b) +{
- return a & ~b;
+}
+static inline void +netdev_features_direct_andnot(netdev_features_t *dst,
s/andnot/clear/ ?
const netdev_features_t features)
+{
- *dst = netdev_features_andnot(*dst, features);
+}
+/* helpers for netdev features 'set bit' operation */ +static inline void netdev_features_set_bit(int nr, netdev_features_t *src)
s/features_set_bit/feature_add/ ?
+{
- *src |= __NETIF_F_BIT(nr);
+}
+/* helpers for netdev features 'set bit array' operation */ +static inline void netdev_features_set_array(const int *array, int array_size,
netdev_features_t *dst)
+{
- int i;
- for (i = 0; i < array_size; i++)
netdev_features_set_bit(array[i], dst);
+}
+#define netdev_active_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->active_features)
+#define netdev_hw_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->hw_features)
+#define netdev_wanted_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->wanted_features)
+#define netdev_vlan_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->vlan_features)
+#define netdev_hw_enc_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->hw_enc_features)
+#define netdev_mpls_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->mpls_features)
+#define netdev_gso_partial_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->gso_partial_features)
+/* helpers for netdev features 'clear bit' operation */ +static inline void netdev_features_clear_bit(int nr, netdev_features_t *src)
All the mentions of '_bit' are unnecessary IMHO.
在 2022/3/25 9:09, Jakub Kicinski 写道:
On Thu, 24 Mar 2022 23:49:14 +0800 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. As the nic driversare not supposed to modify netdev_features directly, it also introduces wrappers helpers to this.
The implementation of these helpers are based on the old prototype of netdev_features_t is still u64. I will rewrite them on the last patch, when the prototype changes.
Signed-off-by: Jian Shen shenjian15@huawei.com
include/linux/netdevice.h | 597 ++++++++++++++++++++++++++++++++++++++
Please move these helpers to a new header file which won't be included by netdevice.h and include it at users appropriately.
ok.
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7307b9553bcf..0af4b26896d6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2295,6 +2295,603 @@ struct net_device { }; #define to_net_dev(d) container_of(d, struct net_device, dev)
+static inline void netdev_features_zero(netdev_features_t *dst) +{
- *dst = 0;
+}
+static inline void netdev_features_fill(netdev_features_t *dst) +{
- *dst = ~0ULL;
+}
+static inline bool netdev_features_empty(const netdev_features_t src)
Don't pass by value something larger than 64 bit.
That's a problem. There are many functions in kernel already using netdev_features_t as input parameter or return value. For example:
/netdev_features_t (*ndo_fix_features)(struct net_device *dev, netdev_features_t features);/
If change the prototype of netdev_features_t from u64 to unsigned long *, we have to move the return value as a output parameter.
Is there any other way to fix this ?
+{
- return src == 0;
+}
+/* helpers for netdev features '==' operation */ +static inline bool netdev_features_equal(const netdev_features_t src1,
const netdev_features_t src2)
+{
- return src1 == src2;
+} +/* helpers for netdev features '&=' operation */ +static inline void +netdev_features_direct_and(netdev_features_t *dst,
const netdev_features_t features)
+{
- *dst = netdev_features_and(*dst, features);
+}
+static inline void +netdev_active_features_direct_and(struct net_device *ndev,
s/direct_and/mask/ ?
ok
const netdev_features_t features)
+{
- ndev->active_features = netdev_active_features_and(ndev, features);
+}
+/* helpers for netdev features '|' operation */ +static inline netdev_features_t +netdev_features_or(const netdev_features_t a, const netdev_features_t b) +{
- return a | b;
+} +/* helpers for netdev features '|=' operation */ +static inline void +netdev_features_direct_or(netdev_features_t *dst,
s/direct_or/set/ ?
ok
const netdev_features_t features)
+{
- *dst = netdev_features_or(*dst, features);
+} +/* helpers for netdev features '^' operation */ +static inline netdev_features_t +netdev_features_xor(const netdev_features_t a, const netdev_features_t b) +{
- return a ^ b;
+} +/* helpers for netdev features '^=' operation */ +static inline void +netdev_active_features_direct_xor(struct net_device *ndev,
s/direct_xor/toggle/ ?
ok
+/* helpers for netdev features '& ~' operation */ +static inline netdev_features_t +netdev_features_andnot(const netdev_features_t a, const netdev_features_t b) +{
- return a & ~b;
+} +static inline void +netdev_features_direct_andnot(netdev_features_t *dst,
s/andnot/clear/ ?
ok
const netdev_features_t features)
+{
- *dst = netdev_features_andnot(*dst, features);
+} +/* helpers for netdev features 'set bit' operation */ +static inline void netdev_features_set_bit(int nr, netdev_features_t *src)
s/features_set_bit/feature_add/ ?
It's ok to change set_bit to add, should I remove 's' for single bit ?
+{
- *src |= __NETIF_F_BIT(nr);
+} +/* helpers for netdev features 'set bit array' operation */ +static inline void netdev_features_set_array(const int *array, int array_size,
netdev_features_t *dst)
+{
- int i;
- for (i = 0; i < array_size; i++)
netdev_features_set_bit(array[i], dst);
+}
+#define netdev_active_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->active_features)
+#define netdev_hw_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->hw_features)
+#define netdev_wanted_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->wanted_features)
+#define netdev_vlan_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->vlan_features)
+#define netdev_hw_enc_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->hw_enc_features)
+#define netdev_mpls_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->mpls_features)
+#define netdev_gso_partial_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->gso_partial_features)
+/* helpers for netdev features 'clear bit' operation */ +static inline void netdev_features_clear_bit(int nr, netdev_features_t *src)
All the mentions of '_bit' are unnecessary IMHO. .
thanks, this make the name of helper more succinct.
summarize : netdev_features_direct_and -> netdev_features_mask netdev_features_direct_or -> netdev_features_set netdev_features_direct_xor -> netdev_features_toggle netdev_features_direct_andnot -> netdev_features_clear
netdev_features_set_bit -> netdev_feature_add netdev_features_clear_bit -> netdev_feature_del netdev_features_test_bit -> netdev_feature_test
在 2022/3/25 9:09, Jakub Kicinski 写道:
On Thu, 24 Mar 2022 23:49:14 +0800 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. As the nic driversare not supposed to modify netdev_features directly, it also introduces wrappers helpers to this.
The implementation of these helpers are based on the old prototype of netdev_features_t is still u64. I will rewrite them on the last patch, when the prototype changes.
Signed-off-by: Jian Shen shenjian15@huawei.com
include/linux/netdevice.h | 597 ++++++++++++++++++++++++++++++++++++++
Please move these helpers to a new header file which won't be included by netdevice.h and include it at users appropriately.
I introduced a new header file "netdev_features_helper", and moved thses helpers to it. Some helpers need to include struct net_device which defined in netdevice.h, but there are also some inline functions in netdevice.h need to use these netdev_features helpers. It's conflicted.
So far I thought 3 ways to solved it, but all of them are not satisfactory. 1) Split netdevice.h, move the definition of struct net_device and its relative definitions to a new header file A( haven't got a reasonable name). Both the netdev_features_helper.h and the netdevice include A.
2) Split netdevice.h, move the inline functions to a new header file B. The netdev_features_helper.h inlucde netdevice.h, and B include netdev_features_helper.h and netdevice.h. All the source files which using these ininline functions should include B.
3) Split netdevice.h, move the inline functions to to netdev_featurer_helper.h. The netdev_features_helper.h inlucde netdevice.h, All the source files which using these ininline functions should include netde_features_helper.h.
I'd like to get more advice to this.
Thanks!
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7307b9553bcf..0af4b26896d6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2295,6 +2295,603 @@ struct net_device { }; #define to_net_dev(d) container_of(d, struct net_device, dev)
+static inline void netdev_features_zero(netdev_features_t *dst) +{
- *dst = 0;
+}
+static inline void netdev_features_fill(netdev_features_t *dst) +{
- *dst = ~0ULL;
+}
+static inline bool netdev_features_empty(const netdev_features_t src)
Don't pass by value something larger than 64 bit.
+{
- return src == 0;
+}
+/* helpers for netdev features '==' operation */ +static inline bool netdev_features_equal(const netdev_features_t src1,
const netdev_features_t src2)
+{
- return src1 == src2;
+} +/* helpers for netdev features '&=' operation */ +static inline void +netdev_features_direct_and(netdev_features_t *dst,
const netdev_features_t features)
+{
- *dst = netdev_features_and(*dst, features);
+}
+static inline void +netdev_active_features_direct_and(struct net_device *ndev,
s/direct_and/mask/ ?
const netdev_features_t features)
+{
- ndev->active_features = netdev_active_features_and(ndev, features);
+}
+/* helpers for netdev features '|' operation */ +static inline netdev_features_t +netdev_features_or(const netdev_features_t a, const netdev_features_t b) +{
- return a | b;
+} +/* helpers for netdev features '|=' operation */ +static inline void +netdev_features_direct_or(netdev_features_t *dst,
s/direct_or/set/ ?
const netdev_features_t features)
+{
- *dst = netdev_features_or(*dst, features);
+} +/* helpers for netdev features '^' operation */ +static inline netdev_features_t +netdev_features_xor(const netdev_features_t a, const netdev_features_t b) +{
- return a ^ b;
+} +/* helpers for netdev features '^=' operation */ +static inline void +netdev_active_features_direct_xor(struct net_device *ndev,
s/direct_xor/toggle/ ?
+/* helpers for netdev features '& ~' operation */ +static inline netdev_features_t +netdev_features_andnot(const netdev_features_t a, const netdev_features_t b) +{
- return a & ~b;
+} +static inline void +netdev_features_direct_andnot(netdev_features_t *dst,
s/andnot/clear/ ?
const netdev_features_t features)
+{
- *dst = netdev_features_andnot(*dst, features);
+} +/* helpers for netdev features 'set bit' operation */ +static inline void netdev_features_set_bit(int nr, netdev_features_t *src)
s/features_set_bit/feature_add/ ?
+{
- *src |= __NETIF_F_BIT(nr);
+} +/* helpers for netdev features 'set bit array' operation */ +static inline void netdev_features_set_array(const int *array, int array_size,
netdev_features_t *dst)
+{
- int i;
- for (i = 0; i < array_size; i++)
netdev_features_set_bit(array[i], dst);
+}
+#define netdev_active_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->active_features)
+#define netdev_hw_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->hw_features)
+#define netdev_wanted_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->wanted_features)
+#define netdev_vlan_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->vlan_features)
+#define netdev_hw_enc_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->hw_enc_features)
+#define netdev_mpls_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->mpls_features)
+#define netdev_gso_partial_features_set_array(ndev, array, array_size) \
netdev_features_set_array(array, array_size, &ndev->gso_partial_features)
+/* helpers for netdev features 'clear bit' operation */ +static inline void netdev_features_clear_bit(int nr, netdev_features_t *src)
All the mentions of '_bit' are unnecessary IMHO. .
On Sat, 16 Apr 2022 11:33:58 +0800 shenjian (K) wrote:
在 2022/3/25 9:09, Jakub Kicinski 写道:
On Thu, 24 Mar 2022 23:49:14 +0800 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. As the nic driversare not supposed to modify netdev_features directly, it also introduces wrappers helpers to this.
The implementation of these helpers are based on the old prototype of netdev_features_t is still u64. I will rewrite them on the last patch, when the prototype changes.
Signed-off-by: Jian Shen shenjian15@huawei.com
include/linux/netdevice.h | 597 ++++++++++++++++++++++++++++++++++++++
Please move these helpers to a new header file which won't be included by netdevice.h and include it at users appropriately.
I introduced a new header file "netdev_features_helper", and moved thses helpers to it. Some helpers need to include struct net_device which defined in netdevice.h, but there are also some inline functions in netdevice.h need to use these netdev_features helpers. It's conflicted.
So far I thought 3 ways to solved it, but all of them are not satisfactory.
- Split netdevice.h, move the definition of struct net_device and its
relative definitions to a new header file A( haven't got a reasonable name). Both the netdev_features_helper.h and the netdevice include A.
- Split netdevice.h, move the inline functions to a new header file B.
The netdev_features_helper.h inlucde netdevice.h, and B include netdev_features_helper.h and netdevice.h. All the source files which using these ininline functions should include B.
- Split netdevice.h, move the inline functions to to
netdev_featurer_helper.h. The netdev_features_helper.h inlucde netdevice.h, All the source files which using these ininline functions should include netde_features_helper.h.
I'd like to get more advice to this.
Larger surgery is probably too much. What does netdevice.h need? Looks like it mostly needs the type and the helper for testing if feature is set. So maybe we can put those in netdevice.h and the rest in a new header? More advanced helpers like netdev_get_wanted_features() can move to the new header as well.
在 2022/4/16 15:42, Jakub Kicinski 写道:
On Sat, 16 Apr 2022 11:33:58 +0800 shenjian (K) wrote:
在 2022/3/25 9:09, Jakub Kicinski 写道:
On Thu, 24 Mar 2022 23:49:14 +0800 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. As the nic driversare not supposed to modify netdev_features directly, it also introduces wrappers helpers to this.
The implementation of these helpers are based on the old prototype of netdev_features_t is still u64. I will rewrite them on the last patch, when the prototype changes.
Signed-off-by: Jian Shen shenjian15@huawei.com
include/linux/netdevice.h | 597 ++++++++++++++++++++++++++++++++++++++
Please move these helpers to a new header file which won't be included by netdevice.h and include it at users appropriately.
I introduced a new header file "netdev_features_helper", and moved thses helpers to it. Some helpers need to include struct net_device which defined in netdevice.h, but there are also some inline functions in netdevice.h need to use these netdev_features helpers. It's conflicted.
So far I thought 3 ways to solved it, but all of them are not satisfactory.
- Split netdevice.h, move the definition of struct net_device and its
relative definitions to a new header file A( haven't got a reasonable name). Both the netdev_features_helper.h and the netdevice include A.
- Split netdevice.h, move the inline functions to a new header file B.
The netdev_features_helper.h inlucde netdevice.h, and B include netdev_features_helper.h and netdevice.h. All the source files which using these ininline functions should include B.
- Split netdevice.h, move the inline functions to to
netdev_featurer_helper.h. The netdev_features_helper.h inlucde netdevice.h, All the source files which using these ininline functions should include netde_features_helper.h.
I'd like to get more advice to this.
Larger surgery is probably too much. What does netdevice.h need? Looks like it mostly needs the type and the helper for testing if feature is set. So maybe we can put those in netdevice.h and the rest in a new header? More advanced helpers like netdev_get_wanted_features() can move to the new header as well. .
ok, got it, thanks
There are many netdev_features bits group used in kernel. The definition will be illegal when using feature bit more than 64. Replace these macroes with global netdev_features variables, initialize them when netdev module init.
Signed-off-by: Jian Shen shenjian15@huawei.com --- include/linux/netdev_features.h | 104 +++++++----- net/core/dev.c | 113 +++++++++++++ net/core/netdev_features.c | 276 ++++++++++++++++++++++++++++++++ 3 files changed, 457 insertions(+), 36 deletions(-) create mode 100644 net/core/netdev_features.c
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 2c6b9e416225..b25f2bb31f94 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -190,75 +190,107 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start) (bit) >= 0; \ (bit) = find_next_netdev_feature((mask_addr), (bit) - 1))
+extern netdev_features_t netdev_ethtool_features __ro_after_init; +extern netdev_features_t netdev_never_change_features __ro_after_init; +extern netdev_features_t netdev_gso_features_mask __ro_after_init; +extern netdev_features_t netdev_ip_csum_features __ro_after_init; +extern netdev_features_t netdev_csum_features_mask __ro_after_init; +extern netdev_features_t netdev_general_tso_features __ro_after_init; +extern netdev_features_t netdev_all_tso_features __ro_after_init; +extern netdev_features_t netdev_tso_ecn_features __ro_after_init; +extern netdev_features_t netdev_all_fcoe_features __ro_after_init; +extern netdev_features_t netdev_gso_software_features __ro_after_init; +extern netdev_features_t netdev_one_for_all_features __ro_after_init; +extern netdev_features_t netdev_all_for_all_features __ro_after_init; +extern netdev_features_t netdev_upper_disable_features __ro_after_init; +extern netdev_features_t netdev_soft_features __ro_after_init; +extern netdev_features_t netdev_soft_off_features __ro_after_init; +extern netdev_features_t netdev_all_vlan_features __ro_after_init; +extern netdev_features_t netdev_rx_vlan_features __ro_after_init; +extern netdev_features_t netdev_tx_vlan_features __ro_after_init; +extern netdev_features_t netdev_ctag_vlan_features __ro_after_init; +extern netdev_features_t netdev_stag_vlan_features __ro_after_init; +extern netdev_features_t netdev_vlan_filter_features __ro_after_init; +extern netdev_features_t netdev_gso_encap_all_features __ro_after_init; +extern netdev_features_t netdev_xfrm_features __ro_after_init; +extern netdev_features_t netdev_tls_features __ro_after_init; +extern netdev_features_t netdev_csum_gso_features_mask __ro_after_init; +extern netdev_features_t netdev_vlan_features_mask __ro_after_init; + +extern const int netif_f_never_change_array[3]; +extern const int netif_f_gso_mask_array[19]; +extern const int netif_f_ip_csum_array[2]; +extern const int netif_f_csum_mask_array[3]; +extern const int netif_f_general_tso_array[2]; +extern const int netif_f_all_tso_array[4]; +extern const int netif_f_tso_ecn_array[1]; +extern const int netif_f_all_fcoe_array[3]; +extern const int netif_f_gso_soft_array[7]; +extern const int netif_f_one_for_all_array[12]; +extern const int netif_f_all_for_all_array[2]; +extern const int netif_f_upper_disables_array[1]; +extern const int netif_f_soft_array[2]; +extern const int netif_f_soft_off_array[2]; +extern const int netif_f_vlan_array[6]; +extern const int netif_f_tx_vlan_array[2]; +extern const int netif_f_rx_vlan_array[2]; +extern const int netif_f_ctag_vlan_array[2]; +extern const int netif_f_stag_vlan_array[2]; +extern const int netif_f_vlan_filter_array[2]; +extern const int netif_f_gso_encap_array[6]; +extern const int netif_f_xfrm_array[3]; +extern const int netif_f_tls_array[2]; +extern const int netif_f_vlan_mask_array[6]; + /* 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/dev.c b/net/core/dev.c index a09ddbfb3086..67e4c67f5064 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -11229,6 +11229,117 @@ static struct pernet_operations __net_initdata default_device_ops = { .exit_batch = default_device_exit_batch, };
+static void netdev_features_init(void) +{ + netdev_features_t features; + + netdev_features_set_array(netif_f_never_change_array, + ARRAY_SIZE(netif_f_never_change_array), + &netdev_never_change_features); + + netdev_features_set_array(netif_f_gso_mask_array, + ARRAY_SIZE(netif_f_gso_mask_array), + &netdev_gso_features_mask); + + netdev_features_set_array(netif_f_ip_csum_array, + ARRAY_SIZE(netif_f_ip_csum_array), + &netdev_ip_csum_features); + + netdev_features_set_array(netif_f_csum_mask_array, + ARRAY_SIZE(netif_f_csum_mask_array), + &netdev_csum_features_mask); + + netdev_features_set_array(netif_f_general_tso_array, + ARRAY_SIZE(netif_f_general_tso_array), + &netdev_general_tso_features); + + netdev_features_set_array(netif_f_all_tso_array, + ARRAY_SIZE(netif_f_all_tso_array), + &netdev_all_tso_features); + + netdev_features_set_array(netif_f_tso_ecn_array, + ARRAY_SIZE(netif_f_tso_ecn_array), + &netdev_tso_ecn_features); + + netdev_features_set_array(netif_f_all_fcoe_array, + ARRAY_SIZE(netif_f_all_fcoe_array), + &netdev_all_fcoe_features); + + netdev_features_set_array(netif_f_gso_soft_array, + ARRAY_SIZE(netif_f_gso_soft_array), + &netdev_gso_software_features); + + netdev_features_set_array(netif_f_one_for_all_array, + ARRAY_SIZE(netif_f_one_for_all_array), + &netdev_one_for_all_features); + + netdev_features_set_array(netif_f_all_for_all_array, + ARRAY_SIZE(netif_f_all_for_all_array), + &netdev_all_for_all_features); + + netdev_features_set_array(netif_f_upper_disables_array, + ARRAY_SIZE(netif_f_upper_disables_array), + &netdev_upper_disable_features); + + netdev_features_set_array(netif_f_soft_array, + ARRAY_SIZE(netif_f_soft_array), + &netdev_soft_features); + + netdev_features_set_array(netif_f_soft_off_array, + ARRAY_SIZE(netif_f_soft_off_array), + &netdev_soft_off_features); + + netdev_features_set_array(netif_f_rx_vlan_array, + ARRAY_SIZE(netif_f_rx_vlan_array), + &netdev_rx_vlan_features); + + netdev_features_set_array(netif_f_tx_vlan_array, + ARRAY_SIZE(netif_f_tx_vlan_array), + &netdev_tx_vlan_features); + + netdev_features_set_array(netif_f_vlan_filter_array, + ARRAY_SIZE(netif_f_vlan_filter_array), + &netdev_vlan_filter_features); + + netdev_all_vlan_features = netdev_rx_vlan_features; + netdev_features_direct_or(&netdev_all_vlan_features, + netdev_tx_vlan_features); + netdev_features_direct_or(&netdev_all_vlan_features, + netdev_vlan_filter_features); + + netdev_features_set_array(netif_f_ctag_vlan_array, + ARRAY_SIZE(netif_f_ctag_vlan_array), + &netdev_ctag_vlan_features); + + netdev_features_set_array(netif_f_stag_vlan_array, + ARRAY_SIZE(netif_f_stag_vlan_array), + &netdev_stag_vlan_features); + + netdev_features_set_array(netif_f_gso_encap_array, + ARRAY_SIZE(netif_f_gso_encap_array), + &netdev_gso_encap_all_features); + + netdev_features_set_array(netif_f_xfrm_array, + ARRAY_SIZE(netif_f_xfrm_array), + &netdev_xfrm_features); + + netdev_features_set_array(netif_f_tls_array, + ARRAY_SIZE(netif_f_tls_array), + &netdev_tls_features); + + netdev_features_set_array(netif_f_vlan_mask_array, + ARRAY_SIZE(netif_f_vlan_mask_array), + &netdev_vlan_features_mask); + + netdev_csum_gso_features_mask = + netdev_features_or(netdev_gso_software_features, + netdev_csum_features_mask); + + netdev_features_fill(&features); + netdev_ethtool_features = + netdev_features_andnot(features, netdev_never_change_features); +} + /* * Initialize the DEV module. At boot time this walks the device list and * unhooks any devices that fail to initialise (normally hardware not @@ -11259,6 +11370,8 @@ static int __init net_dev_init(void) if (register_pernet_subsys(&netdev_net_ops)) goto out;
+ netdev_features_init(); + /* * Initialise the packet receive queues. */ diff --git a/net/core/netdev_features.c b/net/core/netdev_features.c new file mode 100644 index 000000000000..e92353428ee7 --- /dev/null +++ b/net/core/netdev_features.c @@ -0,0 +1,276 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Network device features. + */ + +#include <linux/netdev_features.h> + +netdev_features_t netdev_ethtool_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_ethtool_features); + +netdev_features_t netdev_never_change_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_never_change_features); + +netdev_features_t netdev_gso_features_mask __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_gso_features_mask); + +netdev_features_t netdev_ip_csum_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_ip_csum_features); + +netdev_features_t netdev_csum_features_mask __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_csum_features_mask); + +netdev_features_t netdev_general_tso_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_general_tso_features); + +netdev_features_t netdev_all_tso_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_all_tso_features); + +netdev_features_t netdev_tso_ecn_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_tso_ecn_features); + +netdev_features_t netdev_all_fcoe_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_all_fcoe_features); + +netdev_features_t netdev_gso_software_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_gso_software_features); + +netdev_features_t netdev_one_for_all_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_one_for_all_features); + +netdev_features_t netdev_all_for_all_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_all_for_all_features); + +netdev_features_t netdev_upper_disable_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_upper_disable_features); + +netdev_features_t netdev_soft_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_soft_features); + +netdev_features_t netdev_soft_off_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_soft_off_features); + +netdev_features_t netdev_all_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_all_vlan_features); + +netdev_features_t netdev_vlan_filter_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_vlan_filter_features); + +netdev_features_t netdev_rx_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_rx_vlan_features); + +netdev_features_t netdev_tx_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_tx_vlan_features); + +netdev_features_t netdev_ctag_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_ctag_vlan_features); + +netdev_features_t netdev_stag_vlan_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_stag_vlan_features); + +netdev_features_t netdev_gso_encap_all_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_gso_encap_all_features); + +netdev_features_t netdev_xfrm_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_xfrm_features); + +netdev_features_t netdev_tls_features __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_tls_features); + +netdev_features_t netdev_csum_gso_features_mask __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_csum_gso_features_mask); + +netdev_features_t netdev_vlan_features_mask __ro_after_init; +EXPORT_SYMBOL_GPL(netdev_vlan_features_mask); + +const int netif_f_never_change_array[] = { + NETIF_F_VLAN_CHALLENGED_BIT, + NETIF_F_LLTX_BIT, + NETIF_F_NETNS_LOCAL_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_never_change_array); + +const int netif_f_gso_mask_array[] = { + NETIF_F_TSO_BIT, + NETIF_F_GSO_ROBUST_BIT, + NETIF_F_TSO_ECN_BIT, + NETIF_F_TSO_MANGLEID_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_FSO_BIT, + NETIF_F_GSO_GRE_BIT, + NETIF_F_GSO_GRE_CSUM_BIT, + NETIF_F_GSO_IPXIP4_BIT, + NETIF_F_GSO_IPXIP6_BIT, + NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, + NETIF_F_GSO_PARTIAL_BIT, + NETIF_F_GSO_TUNNEL_REMCSUM_BIT, + NETIF_F_GSO_SCTP_BIT, + NETIF_F_GSO_ESP_BIT, + NETIF_F_GSO_UDP_BIT, + NETIF_F_GSO_UDP_L4_BIT, + NETIF_F_GSO_FRAGLIST_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_gso_mask_array); + +const int netif_f_ip_csum_array[] = { + NETIF_F_IP_CSUM_BIT, + NETIF_F_IPV6_CSUM_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_ip_csum_array); + +const int netif_f_csum_mask_array[] = { + NETIF_F_IP_CSUM_BIT, + NETIF_F_IPV6_CSUM_BIT, + NETIF_F_HW_CSUM_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_csum_mask_array); + +const int netif_f_general_tso_array[] = { + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_general_tso_array); + +const int netif_f_all_tso_array[] = { + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_TSO_ECN_BIT, + NETIF_F_TSO_MANGLEID_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_all_tso_array); + +const int netif_f_tso_ecn_array[] = { + NETIF_F_TSO_ECN_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_tso_ecn_array); + +const int netif_f_all_fcoe_array[] = { + NETIF_F_FCOE_CRC_BIT, + NETIF_F_FCOE_MTU_BIT, + NETIF_F_FSO_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_all_fcoe_array); + +const int netif_f_gso_soft_array[] = { + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_TSO_ECN_BIT, + NETIF_F_TSO_MANGLEID_BIT, + NETIF_F_GSO_SCTP_BIT, + NETIF_F_GSO_UDP_L4_BIT, + NETIF_F_GSO_FRAGLIST_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_gso_soft_array); + +const int netif_f_one_for_all_array[] = { + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_TSO_ECN_BIT, + NETIF_F_TSO_MANGLEID_BIT, + NETIF_F_GSO_SCTP_BIT, + NETIF_F_GSO_UDP_L4_BIT, + NETIF_F_GSO_FRAGLIST_BIT, + NETIF_F_GSO_ROBUST_BIT, + NETIF_F_SG_BIT, + NETIF_F_HIGHDMA_BIT, + NETIF_F_FRAGLIST_BIT, + NETIF_F_VLAN_CHALLENGED, +}; +EXPORT_SYMBOL_GPL(netif_f_one_for_all_array); + +const int netif_f_all_for_all_array[] = { + NETIF_F_NOCACHE_COPY_BIT, + NETIF_F_FSO_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_all_for_all_array); + +const int netif_f_upper_disables_array[] = { + NETIF_F_LRO_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_upper_disables_array); + +const int netif_f_soft_array[] = { + NETIF_F_GSO_BIT, + NETIF_F_GRO_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_soft_array); + +const int netif_f_soft_off_array[] = { + NETIF_F_GRO_FRAGLIST_BIT, + NETIF_F_GRO_UDP_FWD_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_soft_off_array); + +const int netif_f_vlan_array[] = { + NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + NETIF_F_HW_VLAN_CTAG_RX_BIT, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_HW_VLAN_STAG_FILTER_BIT, + NETIF_F_HW_VLAN_STAG_RX_BIT, + NETIF_F_HW_VLAN_STAG_TX_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_vlan_array); + +const int netif_f_tx_vlan_array[] = { + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_HW_VLAN_STAG_TX_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_tx_vlan_array); + +const int netif_f_rx_vlan_array[] = { + NETIF_F_HW_VLAN_CTAG_RX_BIT, + NETIF_F_HW_VLAN_STAG_RX_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_rx_vlan_array); + +const int netif_f_vlan_filter_array[] = { + NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + NETIF_F_HW_VLAN_STAG_FILTER_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_vlan_filter_array); + +const int netif_f_ctag_vlan_array[] = { + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_HW_VLAN_CTAG_RX_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_ctag_vlan_array); + +const int netif_f_stag_vlan_array[] = { + NETIF_F_HW_VLAN_STAG_TX_BIT, + NETIF_F_HW_VLAN_STAG_RX_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_stag_vlan_array); + +const int netif_f_gso_encap_array[] = { + NETIF_F_GSO_GRE_BIT, + NETIF_F_GSO_GRE_CSUM_BIT, + NETIF_F_GSO_IPXIP4_BIT, + NETIF_F_GSO_IPXIP6_BIT, + NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, +}; +EXPORT_SYMBOL_GPL(netif_f_gso_encap_array); + +const int netif_f_xfrm_array[] = { + NETIF_F_HW_ESP_BIT, + NETIF_F_HW_ESP_TX_CSUM_BIT, + NETIF_F_GSO_ESP_BIT +}; +EXPORT_SYMBOL_GPL(netif_f_xfrm_array); + +const int netif_f_tls_array[] = { + NETIF_F_HW_TLS_TX_BIT, + NETIF_F_HW_TLS_RX_BIT +}; +EXPORT_SYMBOL_GPL(netif_f_tls_array); + +const int netif_f_vlan_mask_array[] = { + NETIF_F_SG_BIT, + NETIF_F_HIGHDMA_BIT, + NETIF_F_HW_CSUM_BIT, + NETIF_F_FRAGLIST_BIT, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_HW_VLAN_STAG_TX_BIT +}; +EXPORT_SYMBOL_GPL(netif_f_vlan_mask_array);
There are many netdev_features bits group used in drivers, replace them with netdev features array.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 49 +++++++++++++++---- drivers/net/ethernet/sfc/ef10.c | 13 ++++- drivers/net/ethernet/sfc/ef100_nic.c | 29 +++++++++-- drivers/net/ethernet/sfc/efx.c | 25 ++++++++-- drivers/net/ethernet/sfc/falcon/efx.c | 12 +++-- net/ethtool/ioctl.c | 19 +++++-- 6 files changed, 118 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 24104eaae6d3..58df89f783fb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3225,23 +3225,51 @@ static struct pci_driver hns3_driver = { .err_handler = &hns3_err_handler, };
+static const int hns3_default_features_array[] = { + 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, +}; + +static const int hns3_vlan_off_features_array[] = { + NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + NETIF_F_HW_VLAN_CTAG_RX_BIT, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_GRO_HW_BIT, + NETIF_F_NTUPLE_BIT, + NETIF_F_HW_TC_BIT, +}; + /* set default feature to hns3 */ static void hns3_set_default_feature(struct net_device *netdev) { struct hnae3_handle *h = hns3_get_handle(netdev); struct pci_dev *pdev = h->pdev; struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev); + netdev_features_t vlan_off_features; + netdev_features_t features;
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
- netdev->active_features |= NETIF_F_HW_VLAN_CTAG_FILTER | - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO | - NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE | - NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_SCTP_CRC | NETIF_F_FRAGLIST; + netdev_features_zero(&features); + netdev_features_set_array(hns3_default_features_array, + ARRAY_SIZE(hns3_default_features_array), + &features); + + netdev->active_features |= features;
if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { netdev->active_features |= NETIF_F_GRO_HW; @@ -3268,10 +3296,11 @@ 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->active_features & - ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_GRO_HW | NETIF_F_NTUPLE | - NETIF_F_HW_TC); + netdev_features_zero(&vlan_off_features); + netdev_features_set_array(hns3_vlan_off_features_array, + ARRAY_SIZE(hns3_vlan_off_features_array), + &vlan_off_features); + netdev->vlan_features |= netdev->active_features & ~vlan_off_features;
netdev->hw_enc_features |= netdev->vlan_features | NETIF_F_TSO_MANGLEID; } diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 56303984d936..3e1876292141 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1301,6 +1301,13 @@ static void efx_ef10_fini_nic(struct efx_nic *efx) nic_data->mc_stats = NULL; }
+static const int ef10_tso_features_array[] = { + NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_GSO_GRE_BIT, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, + NETIF_F_GSO_GRE_CSUM_BIT +}; + static int efx_ef10_init_nic(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; @@ -1356,8 +1363,10 @@ static int efx_ef10_init_nic(struct efx_nic *efx) if (efx_has_cap(efx, TX_TSO_V2_ENCAP)) { netdev_features_t encap_tso_features;
- encap_tso_features = NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE | - NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM; + netdev_features_zero(&encap_tso_features); + netdev_features_set_array(ef10_tso_features_array, + ARRAY_SIZE(ef10_tso_features_array), + &encap_tso_features);
hw_enc_features |= encap_tso_features | NETIF_F_TSO; efx->net_dev->active_features |= encap_tso_features; diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index 0ddd3d69bd5e..50a5f37151f2 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -147,6 +147,16 @@ static int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address) return 0; }
+static const int ef100_tso_features_array[] = { + NETIF_F_TSO_BIT, + NETIF_F_TSO6_BIT, + NETIF_F_GSO_PARTIAL_BIT, + NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT, + NETIF_F_GSO_GRE_BIT, + NETIF_F_GSO_GRE_CSUM_BIT +}; + static int efx_ef100_init_datapath_caps(struct efx_nic *efx) { MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V7_OUT_LEN); @@ -185,10 +195,12 @@ static int efx_ef100_init_datapath_caps(struct efx_nic *efx)
if (efx_ef100_has_cap(nic_data->datapath_caps2, TX_TSO_V3)) { struct net_device *net_dev = efx->net_dev; - netdev_features_t tso = NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_PARTIAL | - NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_GSO_GRE | NETIF_F_GSO_GRE_CSUM; + netdev_features_t tso;
+ netdev_features_zero(&tso); + netdev_features_set_array(ef100_tso_features_array, + ARRAY_SIZE(ef100_tso_features_array), + &tso); net_dev->active_features |= tso; net_dev->hw_features |= tso; net_dev->hw_enc_features |= tso; @@ -1105,6 +1117,12 @@ static int ef100_check_design_params(struct efx_nic *efx) return rc; }
+static const int ef100_vlan_features_array[] = { + NETIF_F_HW_CSUM_BIT, + NETIF_F_SG_BIT, + NETIF_F_HIGHDMA_BIT +}; + /* NIC probe and remove */ static int ef100_probe_main(struct efx_nic *efx) @@ -1126,8 +1144,9 @@ static int ef100_probe_main(struct efx_nic *efx) net_dev->active_features |= efx->type->offload_features; net_dev->hw_features |= efx->type->offload_features; net_dev->hw_enc_features |= efx->type->offload_features; - net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_ALL_TSO; + net_dev->vlan_features |= NETIF_F_ALL_TSO; + netdev_vlan_features_set_array(net_dev, ef100_vlan_features_array, + ARRAY_SIZE(ef100_vlan_features_array));
/* Populate design-parameter defaults */ nic_data->tso_max_hdr_len = ESE_EF100_DP_GZ_TSO_MAX_HDR_LEN_DEFAULT; diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index d7dff27a3e8e..9f4b6e483e72 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -988,6 +988,20 @@ static int efx_pci_probe_main(struct efx_nic *efx) return rc; }
+static const int efx_active_features_array[] = { + NETIF_F_SG_BIT, + NETIF_F_TSO_BIT, + NETIF_F_RXCSUM_BIT, + NETIF_F_RXALL_BIT +}; + +static const int efx_vlan_features_array[] = { + NETIF_F_HW_CSUM_BIT, + NETIF_F_SG_BIT, + NETIF_F_HIGHDMA_BIT, + NETIF_F_RXCSUM_BIT +}; + static int efx_pci_probe_post_io(struct efx_nic *efx) { struct net_device *net_dev = efx->net_dev; @@ -1004,17 +1018,18 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) }
/* Determine netdevice features */ - net_dev->active_features |= (efx->type->offload_features | NETIF_F_SG | - NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_RXALL); + net_dev->active_features |= efx->type->offload_features; + netdev_active_features_set_array(net_dev, efx_active_features_array, + ARRAY_SIZE(efx_active_features_array)); if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM)) net_dev->active_features |= NETIF_F_TSO6; /* Check whether device supports TSO */ if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) net_dev->active_features &= ~NETIF_F_ALL_TSO; /* Mask for features that also apply to VLAN devices */ - net_dev->vlan_features |= (NETIF_F_HW_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_ALL_TSO | - NETIF_F_RXCSUM); + net_dev->vlan_features |= NETIF_F_ALL_TSO; + netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, + ARRAY_SIZE(efx_vlan_features_array));
net_dev->hw_features |= net_dev->active_features & ~efx->fixed_features;
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 807ceda69c01..177ef78fb652 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2859,6 +2859,13 @@ static int ef4_pci_probe_main(struct ef4_nic *efx) return rc; }
+static const int efx_vlan_features_array[] = { + NETIF_F_HW_CSUM_BIT, + NETIF_F_SG_BIT, + NETIF_F_HIGHDMA_BIT, + NETIF_F_RXCSUM_BIT +}; + /* NIC initialisation * * This is called at module load (or hotplug insertion, @@ -2907,9 +2914,8 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, net_dev->active_features |= (efx->type->offload_features | NETIF_F_SG | NETIF_F_RXCSUM); /* Mask for features that also apply to VLAN devices */ - net_dev->vlan_features |= (NETIF_F_HW_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_RXCSUM); - + netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, + ARRAY_SIZE(efx_vlan_features_array)); net_dev->hw_features = net_dev->active_features & ~efx->fixed_features;
/* Disable VLAN filtering by default. It may be enforced if diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 1c7f24316b3d..184ca24263f4 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -288,9 +288,14 @@ 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 const int ethtool_all_features_array[] = { + NETIF_F_LRO_BIT, + NETIF_F_HW_VLAN_CTAG_RX_BIT, + NETIF_F_HW_VLAN_CTAG_TX_BIT, + NETIF_F_NTUPLE_BIT, + NETIF_F_RXHASH_BIT +};
static u32 __ethtool_get_flags(struct net_device *dev) { @@ -313,6 +318,7 @@ static u32 __ethtool_get_flags(struct net_device *dev) static int __ethtool_set_flags(struct net_device *dev, u32 data) { netdev_features_t features = 0, changed; + netdev_features_t eth_all_features;
if (data & ~ETH_ALL_FLAGS) return -EINVAL; @@ -328,8 +334,13 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) if (data & ETH_FLAG_RXHASH) features |= NETIF_F_RXHASH;
+ netdev_features_zero(ð_all_features); + netdev_features_set_array(ethtool_all_features_array, + ARRAY_SIZE(ethtool_all_features_array), + ð_all_features); + /* allow changing only bits set in hw_features */ - changed = (features ^ dev->active_features) & ETH_ALL_FEATURES; + changed = (features ^ dev->active_features) & eth_all_features; if (changed & ~dev->hw_features) return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
On Thu, 24 Mar 2022 23:49:16 +0800 Jian Shen wrote:
There are many netdev_features bits group used in drivers, replace them with netdev features array.
Maybe we can avoid the ARRAY_SIZE calls by doing something like:
struct netdev_feature_set { unsigned int cnt; unsigned short feature_bits[]; };
#define DECLARE_NETDEV_FEATURE_SET(name, features...) \ static unsigned short __ ## name ## _s [] = {features}; \ struct netdev_feature_set name = { \ .cnt = ARRAY_SIZE(__ ## name ## _s), \ .feature_bits = {features}, \ }
Then:
DECLARE_NETDEV_FEATURE_SET(siena_offload_features, NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT, NETIF_F_RXHASH_BIT, NETIF_F_NTUPLE_BIT);
etc.?
在 2022/3/25 9:22, Jakub Kicinski 写道:
On Thu, 24 Mar 2022 23:49:16 +0800 Jian Shen wrote:
There are many netdev_features bits group used in drivers, replace them with netdev features array.
Maybe we can avoid the ARRAY_SIZE calls by doing something like:
struct netdev_feature_set { unsigned int cnt; unsigned short feature_bits[]; };
#define DECLARE_NETDEV_FEATURE_SET(name, features...) \ static unsigned short __ ## name ## _s [] = {features}; \ struct netdev_feature_set name = { \ .cnt = ARRAY_SIZE(__ ## name ## _s), \ .feature_bits = {features}, \ }
Then:
DECLARE_NETDEV_FEATURE_SET(siena_offload_features, NETIF_F_IP_CSUM_BIT, NETIF_F_IPV6_CSUM_BIT, NETIF_F_RXHASH_BIT, NETIF_F_NTUPLE_BIT);
etc.? .
Thanks, it looks good to me.
There are some drivers(e.g. sfc) use netdev_features in global structure initialization. Changed the its netdev_features_t memeber to netdev_features_t *, and make it prefer to a netdev_features_t global variables.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/sfc/ef10.c | 11 +---- drivers/net/ethernet/sfc/ef100_nic.c | 15 ++---- drivers/net/ethernet/sfc/efx.c | 52 +++++++++++++++++++- drivers/net/ethernet/sfc/falcon/efx.c | 29 ++++++++++- drivers/net/ethernet/sfc/falcon/efx.h | 3 ++ drivers/net/ethernet/sfc/falcon/falcon.c | 4 +- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- drivers/net/ethernet/sfc/rx_common.c | 2 +- drivers/net/ethernet/sfc/rx_common.h | 4 ++ drivers/net/ethernet/sfc/siena.c | 3 +- 11 files changed, 97 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 3e1876292141..84aaa4259eb7 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -4023,13 +4023,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, @@ -4130,7 +4123,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 | @@ -4268,7 +4261,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .option_descriptors = true, .min_interrupt_mode = EFX_INT_MODE_LEGACY, .timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH, - .offload_features = EF10_OFFLOAD_FEATURES, + .offload_features = &ef10_offload_features, .mcdi_max_ver = 2, .max_rx_ip_filters = EFX_MCDI_FILTER_TBL_ROWS, .hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE | diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index 50a5f37151f2..42d1d426fb4f 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -717,16 +717,11 @@ static unsigned int efx_ef100_recycle_ring_size(const struct efx_nic *efx)
/* NIC level access functions */ -#define EF100_OFFLOAD_FEATURES (NETIF_F_HW_CSUM | NETIF_F_RXCSUM | \ - NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_NTUPLE | \ - NETIF_F_RXHASH | NETIF_F_RXFCS | NETIF_F_TSO_ECN | NETIF_F_RXALL | \ - NETIF_F_HW_VLAN_CTAG_TX) - const struct efx_nic_type ef100_pf_nic_type = { .revision = EFX_REV_EF100, .is_vf = false, .probe = ef100_probe_pf, - .offload_features = EF100_OFFLOAD_FEATURES, + .offload_features = &ef100_offload_features, .mcdi_max_ver = 2, .mcdi_request = ef100_mcdi_request, .mcdi_poll_response = ef100_mcdi_poll_response, @@ -812,7 +807,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, @@ -1141,9 +1136,9 @@ static int ef100_probe_main(struct efx_nic *efx) return -ENOMEM; efx->nic_data = nic_data; nic_data->efx = efx; - net_dev->active_features |= efx->type->offload_features; - net_dev->hw_features |= efx->type->offload_features; - net_dev->hw_enc_features |= efx->type->offload_features; + net_dev->active_features |= *efx->type->offload_features; + net_dev->hw_features |= *efx->type->offload_features; + net_dev->hw_enc_features |= *efx->type->offload_features; net_dev->vlan_features |= NETIF_F_ALL_TSO; netdev_vlan_features_set_array(net_dev, ef100_vlan_features_array, ARRAY_SIZE(ef100_vlan_features_array)); diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 9f4b6e483e72..607347332bb8 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1018,10 +1018,10 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) }
/* Determine netdevice features */ - net_dev->active_features |= efx->type->offload_features; + net_dev->active_features |= *efx->type->offload_features; netdev_active_features_set_array(net_dev, efx_active_features_array, ARRAY_SIZE(efx_active_features_array)); - 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->active_features |= NETIF_F_TSO6; /* Check whether device supports TSO */ if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) @@ -1293,6 +1293,52 @@ static struct pci_driver efx_pci_driver = { #endif };
+static const int ef10_offload_features_array[] = { + NETIF_F_IP_CSUM_BIT, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + NETIF_F_IPV6_CSUM_BIT, + NETIF_F_RXHASH_BIT, + NETIF_F_NTUPLE_BIT +}; + +static const int ef100_offload_features_array[] = { + 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 +}; + +static const int siena_offload_features_array[] = { + NETIF_F_IP_CSUM_BIT, + NETIF_F_IPV6_CSUM_BIT, + NETIF_F_RXHASH_BIT, + NETIF_F_NTUPLE_BIT +}; + +netdev_features_t ef10_offload_features __ro_after_init; +netdev_features_t ef100_offload_features __ro_after_init; +netdev_features_t siena_offload_features __ro_after_init; + +static void efx_features_init(void) +{ + netdev_features_set_array(ef10_offload_features_array, + ARRAY_SIZE(ef10_offload_features_array), + &ef10_offload_features); + netdev_features_set_array(ef100_offload_features_array, + ARRAY_SIZE(ef100_offload_features_array), + &ef100_offload_features); + netdev_features_set_array(siena_offload_features_array, + ARRAY_SIZE(siena_offload_features_array), + &siena_offload_features); +} + /************************************************************************** * * Kernel module interface @@ -1327,6 +1373,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 177ef78fb652..4631706f157f 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -1694,7 +1694,7 @@ static int ef4_probe_filters(struct ef4_nic *efx) goto out_unlock;
#ifdef CONFIG_RFS_ACCEL - if (efx->type->offload_features & NETIF_F_NTUPLE) { + if (*efx->type->offload_features & NETIF_F_NTUPLE) { struct ef4_channel *channel; int i, success = 1;
@@ -2911,7 +2911,7 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, if (rc) goto fail3;
- net_dev->active_features |= (efx->type->offload_features | NETIF_F_SG | + net_dev->active_features |= (*efx->type->offload_features | NETIF_F_SG | NETIF_F_RXCSUM); /* Mask for features that also apply to VLAN devices */ netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, @@ -3176,6 +3176,29 @@ static struct pci_driver ef4_pci_driver = { .err_handler = &ef4_err_handlers, };
+static const int falcon_b0_offload_features_array[] = { + NETIF_F_IP_CSUM_BIT, + NETIF_F_RXHASH_BIT, + NETIF_F_NTUPLE_BIT +}; + +static const int falcon_a1_offload_features_array[] = { + NETIF_F_IP_CSUM_BIT +}; + +netdev_features_t falcon_b0_offload_features __ro_after_init; +netdev_features_t falcon_a1_offload_features __ro_after_init; + +static void ef4_features_init(void) +{ + netdev_features_set_array(falcon_b0_offload_features_array, + ARRAY_SIZE(falcon_b0_offload_features_array), + &falcon_b0_offload_features); + netdev_features_set_array(falcon_a1_offload_features_array, + ARRAY_SIZE(falcon_a1_offload_features_array), + &falcon_a1_offload_features); +} + /************************************************************************** * * Kernel module interface @@ -3206,6 +3229,8 @@ static int __init ef4_init_module(void) if (rc < 0) goto err_pci;
+ ef4_features_init(); + return 0;
err_pci: diff --git a/drivers/net/ethernet/sfc/falcon/efx.h b/drivers/net/ethernet/sfc/falcon/efx.h index d3b4646545fa..f31b5c6e02bc 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.h +++ b/drivers/net/ethernet/sfc/falcon/efx.h @@ -271,4 +271,7 @@ static inline bool ef4_rwsem_assert_write_locked(struct rw_semaphore *sem) return true; }
+extern netdev_features_t falcon_b0_offload_features __ro_after_init; +extern netdev_features_t falcon_a1_offload_features __ro_after_init; + #endif /* EF4_EFX_H */ diff --git a/drivers/net/ethernet/sfc/falcon/falcon.c b/drivers/net/ethernet/sfc/falcon/falcon.c index 3324a6219a09..fda25f3f8e66 100644 --- a/drivers/net/ethernet/sfc/falcon/falcon.c +++ b/drivers/net/ethernet/sfc/falcon/falcon.c @@ -2799,7 +2799,7 @@ const struct ef4_nic_type falcon_a1_nic_type = { .can_rx_scatter = false, .max_interrupt_mode = EF4_INT_MODE_MSI, .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, - .offload_features = NETIF_F_IP_CSUM, + .offload_features = &falcon_a1_offload_features, };
const struct ef4_nic_type falcon_b0_nic_type = { @@ -2898,6 +2898,6 @@ const struct ef4_nic_type falcon_b0_nic_type = { .can_rx_scatter = true, .max_interrupt_mode = EF4_INT_MODE_MSIX, .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, - .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, + .offload_features = &falcon_b0_offload_features, .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, }; diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h index 48fca3bccd1b..88d73fd078b9 100644 --- a/drivers/net/ethernet/sfc/falcon/net_driver.h +++ b/drivers/net/ethernet/sfc/falcon/net_driver.h @@ -1153,7 +1153,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 5aa4437a5768..1b6c4f29337b 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1479,7 +1479,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 c93e47f2d5bf..1c550b6178e2 100644 --- a/drivers/net/ethernet/sfc/rx_common.c +++ b/drivers/net/ethernet/sfc/rx_common.c @@ -796,7 +796,7 @@ int efx_probe_filters(struct efx_nic *efx) goto out_unlock;
#ifdef CONFIG_RFS_ACCEL - if (efx->type->offload_features & NETIF_F_NTUPLE) { + if (*efx->type->offload_features & NETIF_F_NTUPLE) { struct efx_channel *channel; int i, success = 1;
diff --git a/drivers/net/ethernet/sfc/rx_common.h b/drivers/net/ethernet/sfc/rx_common.h index fbd2769307f9..09b38b0cb401 100644 --- a/drivers/net/ethernet/sfc/rx_common.h +++ b/drivers/net/ethernet/sfc/rx_common.h @@ -113,4 +113,8 @@ bool __efx_filter_rfs_expire(struct efx_channel *channel, unsigned int quota); int efx_probe_filters(struct efx_nic *efx); void efx_remove_filters(struct efx_nic *efx);
+extern netdev_features_t ef10_offload_features __ro_after_init; +extern netdev_features_t ef100_offload_features __ro_after_init; +extern netdev_features_t siena_offload_features __ro_after_init; + #endif diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index ce3060e15b54..74e3db5ccb53 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -1095,8 +1095,7 @@ const struct efx_nic_type siena_a0_nic_type = { .option_descriptors = false, .min_interrupt_mode = EFX_INT_MODE_LEGACY, .timer_period_max = 1 << FRF_CZ_TC_TIMER_VAL_WIDTH, - .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXHASH | NETIF_F_NTUPLE), + .offload_features = &siena_offload_features, .mcdi_max_ver = 1, .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, .hwtstamp_filters = (1 << HWTSTAMP_FILTER_NONE |
To make the semantic patches simple, split the complex opreation of netdev_features to simple ones, and replace some feature macroes with global netdev features variables.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 10 +-- drivers/net/ethernet/sfc/ef10.c | 5 +- drivers/net/ethernet/sfc/efx.c | 7 +- drivers/net/ethernet/sfc/efx_common.c | 14 ++-- drivers/net/ethernet/sfc/falcon/efx.c | 12 ++-- include/linux/netdevice.h | 14 ++-- net/core/dev.c | 69 ++++++++++++------- net/ethtool/features.c | 4 +- net/ethtool/ioctl.c | 47 +++++++++---- 9 files changed, 120 insertions(+), 62 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 58df89f783fb..87cd9187884c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2465,7 +2465,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; } @@ -3284,7 +3284,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_features |= NETIF_F_HW_CSUM; else - netdev->active_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + netdev->active_features |= netdev_ip_csum_features;
if (test_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps)) netdev->active_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; @@ -3300,9 +3300,11 @@ static void hns3_set_default_feature(struct net_device *netdev) netdev_features_set_array(hns3_vlan_off_features_array, ARRAY_SIZE(hns3_vlan_off_features_array), &vlan_off_features); - netdev->vlan_features |= netdev->active_features & ~vlan_off_features; + features = netdev->active_features & ~vlan_off_features; + netdev->vlan_features |= features;
- netdev->hw_enc_features |= netdev->vlan_features | NETIF_F_TSO_MANGLEID; + netdev->hw_enc_features |= netdev->vlan_features; + netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID; }
static int hns3_alloc_buffer(struct hns3_enet_ring *ring, diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 84aaa4259eb7..0d75361f1acb 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1358,7 +1358,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
/* 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; @@ -1368,7 +1368,8 @@ static int efx_ef10_init_nic(struct efx_nic *efx) ARRAY_SIZE(ef10_tso_features_array), &encap_tso_features);
- hw_enc_features |= encap_tso_features | NETIF_F_TSO; + hw_enc_features |= encap_tso_features; + hw_enc_features |= NETIF_F_TSO; efx->net_dev->active_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 607347332bb8..139f63f93227 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1006,6 +1006,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; @@ -1021,7 +1022,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) net_dev->active_features |= *efx->type->offload_features; netdev_active_features_set_array(net_dev, efx_active_features_array, ARRAY_SIZE(efx_active_features_array)); - 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->active_features |= NETIF_F_TSO6; /* Check whether device supports TSO */ if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) @@ -1031,7 +1033,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, ARRAY_SIZE(efx_vlan_features_array));
- net_dev->hw_features |= net_dev->active_features & ~efx->fixed_features; + tmp = net_dev->active_features & ~efx->fixed_features; + net_dev->hw_features |= tmp;
/* Disable receiving frames with bad FCS, by default. */ net_dev->active_features &= ~NETIF_F_RXALL; diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index cee20b4a34e7..d5f8a2b3189a 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -212,10 +212,12 @@ void efx_set_rx_mode(struct net_device *net_dev) int efx_set_features(struct net_device *net_dev, netdev_features_t data) { struct efx_nic *efx = netdev_priv(net_dev); + netdev_features_t tmp; int rc;
/* If disabling RX n-tuple filtering, clear existing filters */ - if (net_dev->active_features & ~data & NETIF_F_NTUPLE) { + tmp = net_dev->active_features & ~data; + if (tmp & NETIF_F_NTUPLE) { rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); if (rc) return rc; @@ -224,8 +226,9 @@ int efx_set_features(struct net_device *net_dev, netdev_features_t data) /* If Rx VLAN filter is changed, update filters via mac_reconfigure. * If rx-fcs is changed, mac_reconfigure updates that too. */ - if ((net_dev->active_features ^ data) & (NETIF_F_HW_VLAN_CTAG_FILTER | - NETIF_F_RXFCS)) { + tmp = net_dev->active_features ^ data; + if (tmp & NETIF_F_HW_VLAN_CTAG_FILTER || + tmp & NETIF_F_RXFCS) { /* efx_set_rx_mode() will schedule MAC work to update filters * when a new features are finally set in net_dev. */ @@ -1367,10 +1370,9 @@ netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev if (skb_inner_transport_offset(skb) > EFX_TSO2_MAX_HDRLEN) features &= ~(NETIF_F_GSO_MASK); - if (features & (NETIF_F_GSO_MASK | NETIF_F_CSUM_MASK)) + if (features & netdev_csum_gso_features_mask) if (!efx_can_encap_offloads(efx, skb)) - features &= ~(NETIF_F_GSO_MASK | - NETIF_F_CSUM_MASK); + features &= ~netdev_csum_gso_features_mask; } return features; } diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 4631706f157f..2eae365eb7e6 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2188,17 +2188,20 @@ static void ef4_set_rx_mode(struct net_device *net_dev) static int ef4_set_features(struct net_device *net_dev, netdev_features_t data) { struct ef4_nic *efx = netdev_priv(net_dev); + netdev_features_t tmp; int rc;
/* If disabling RX n-tuple filtering, clear existing filters */ - if (net_dev->active_features & ~data & NETIF_F_NTUPLE) { + tmp = net_dev->active_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->active_features ^ data) & NETIF_F_HW_VLAN_CTAG_FILTER) { + tmp = net_dev->active_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. */ @@ -2911,8 +2914,9 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, if (rc) goto fail3;
- net_dev->active_features |= (*efx->type->offload_features | NETIF_F_SG | - NETIF_F_RXCSUM); + net_dev->active_features |= *efx->type->offload_features; + net_dev->active_features |= NETIF_F_SG; + net_dev->active_features |= NETIF_F_RXCSUM; /* Mask for features that also apply to VLAN devices */ netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, ARRAY_SIZE(efx_vlan_features_array)); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0af4b26896d6..44e6c3a02b46 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5416,11 +5416,14 @@ void linkwatch_run_queue(void); static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, netdev_features_t f2) { - if ((f1 ^ f2) & NETIF_F_HW_CSUM) { + netdev_features_t tmp; + + tmp = f1 ^ f2; + if (tmp & NETIF_F_HW_CSUM) { if (f1 & NETIF_F_HW_CSUM) - f1 |= (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); + f1 |= netdev_ip_csum_features; else - f2 |= (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); + f2 |= netdev_ip_csum_features; }
return f1 & f2; @@ -5429,7 +5432,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->active_features & ~dev->hw_features) | dev->wanted_features; + netdev_features_t tmp; + + tmp = dev->active_features & ~dev->hw_features; + return dev->wanted_features | tmp; } netdev_features_t netdev_increment_features(netdev_features_t all, netdev_features_t one, netdev_features_t mask); diff --git a/net/core/dev.c b/net/core/dev.c index 67e4c67f5064..7d170f307128 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3322,10 +3322,11 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, * work. */ if (features & NETIF_F_GSO_PARTIAL) { - netdev_features_t partial_features = NETIF_F_GSO_ROBUST; + netdev_features_t partial_features; struct net_device *dev = skb->dev;
- partial_features |= dev->active_features & dev->gso_partial_features; + partial_features = dev->active_features & dev->gso_partial_features; + partial_features |= NETIF_F_GSO_ROBUST; if (!skb_gso_ok(skb, features | partial_features)) features &= ~NETIF_F_GSO_PARTIAL; } @@ -3414,7 +3415,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; @@ -3478,6 +3479,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) { struct net_device *dev = skb->dev; netdev_features_t features = dev->active_features; + netdev_features_t tmp;
if (skb_is_gso(skb)) features = gso_features_check(skb, dev, features); @@ -3489,17 +3491,16 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) if (skb->encapsulation) features &= dev->hw_enc_features;
- if (skb_vlan_tagged(skb)) - features = netdev_intersect_features(features, - dev->vlan_features | - NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_STAG_TX); + if (skb_vlan_tagged(skb)) { + tmp = dev->vlan_features | netdev_tx_vlan_features; + features = netdev_intersect_features(features, tmp); + }
if (dev->netdev_ops->ndo_features_check) - features &= dev->netdev_ops->ndo_features_check(skb, dev, - features); + tmp = dev->netdev_ops->ndo_features_check(skb, dev, features); else - features &= dflt_features_check(skb, dev, features); + tmp = dflt_features_check(skb, dev, features); + features &= tmp;
return harmonize_features(skb, features); } @@ -3570,7 +3571,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): @@ -9466,11 +9467,13 @@ static void netdev_sync_lower_features(struct net_device *upper, static netdev_features_t netdev_fix_features(struct net_device *dev, netdev_features_t features) { + netdev_features_t tmp; + /* Fix illegal checksum combinations */ if ((features & NETIF_F_HW_CSUM) && - (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { + (features & netdev_ip_csum_features)) { netdev_warn(dev, "mixed HW and IP checksum settings.\n"); - features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); + features &= ~netdev_ip_csum_features; }
/* TSO requires that SG is present as well. */ @@ -9497,7 +9500,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. */ @@ -9545,8 +9550,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) { @@ -9875,8 +9880,8 @@ int register_netdevice(struct net_device *dev) } }
- if (((dev->hw_features | dev->active_features) & - NETIF_F_HW_VLAN_CTAG_FILTER) && + if ((dev->hw_features & NETIF_F_HW_VLAN_CTAG_FILTER || + dev->active_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"); @@ -9893,7 +9898,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->active_features |= NETIF_F_SOFT_FEATURES;
if (dev->udp_tunnel_nic_info) { @@ -9926,7 +9932,8 @@ int register_netdevice(struct net_device *dev)
/* Make NETIF_F_SG inheritable to tunnel devices. */ - dev->hw_enc_features |= NETIF_F_SG | NETIF_F_GSO_PARTIAL; + dev->hw_enc_features |= NETIF_F_SG; + dev->hw_enc_features |= NETIF_F_GSO_PARTIAL;
/* Make NETIF_F_SG inheritable to MPLS. */ @@ -11013,16 +11020,28 @@ static int dev_cpu_dead(unsigned int oldcpu) netdev_features_t netdev_increment_features(netdev_features_t all, netdev_features_t one, netdev_features_t mask) { + netdev_features_t tmp; + if (mask & NETIF_F_HW_CSUM) mask |= NETIF_F_CSUM_MASK; mask |= NETIF_F_VLAN_CHALLENGED;
- all |= one & (NETIF_F_ONE_FOR_ALL | NETIF_F_CSUM_MASK) & mask; - all &= one | ~NETIF_F_ALL_FOR_ALL; + tmp = NETIF_F_ONE_FOR_ALL | NETIF_F_CSUM_MASK; + tmp &= one; + tmp &= mask; + all |= tmp; + + netdev_features_fill(&tmp); + tmp &= ~NETIF_F_ALL_FOR_ALL; + tmp |= one; + all &= tmp;
/* If one device supports hw checksumming, set for all. */ - if (all & NETIF_F_HW_CSUM) - all &= ~(NETIF_F_CSUM_MASK & ~NETIF_F_HW_CSUM); + if (all & NETIF_F_HW_CSUM) { + tmp = NETIF_F_CSUM_MASK; + tmp &= ~NETIF_F_HW_CSUM; + all &= ~tmp; + }
return all; } diff --git a/net/ethtool/features.c b/net/ethtool/features.c index a43f82515de8..d327c6032d7b 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->active_features); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 184ca24263f4..ab003dc2cfd8 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -125,6 +125,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))) @@ -142,19 +143,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->active_features) & valid) + tmp = dev->wanted_features ^ dev->active_features; + if (tmp & valid) ret |= ETHTOOL_F_WISH;
return ret; @@ -221,28 +226,38 @@ static void __ethtool_get_strings(struct net_device *dev,
static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd) { + netdev_features_t tmp; + /* feature masks of legacy discrete ethtool ops */
+ netdev_features_zero(&tmp); switch (eth_cmd) { case ETHTOOL_GTXCSUM: case ETHTOOL_STXCSUM: - return NETIF_F_CSUM_MASK | NETIF_F_FCOE_CRC | - NETIF_F_SCTP_CRC; + tmp = NETIF_F_CSUM_MASK; + tmp |= NETIF_F_FCOE_CRC; + tmp |= NETIF_F_SCTP_CRC; + return tmp; case ETHTOOL_GRXCSUM: case ETHTOOL_SRXCSUM: - return NETIF_F_RXCSUM; + tmp |= NETIF_F_RXCSUM; + return tmp; case ETHTOOL_GSG: case ETHTOOL_SSG: - return NETIF_F_SG | NETIF_F_FRAGLIST; + tmp |= NETIF_F_SG; + tmp |= NETIF_F_FRAGLIST; + return tmp; case ETHTOOL_GTSO: case ETHTOOL_STSO: return NETIF_F_ALL_TSO; case ETHTOOL_GGSO: case ETHTOOL_SGSO: - return NETIF_F_GSO; + tmp |= NETIF_F_GSO; + return tmp; case ETHTOOL_GGRO: case ETHTOOL_SGRO: - return NETIF_F_GRO; + tmp |= NETIF_F_GRO; + return tmp; default: BUG(); } @@ -319,6 +334,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) { netdev_features_t features = 0, changed; netdev_features_t eth_all_features; + netdev_features_t tmp;
if (data & ~ETH_ALL_FLAGS) return -EINVAL; @@ -340,12 +356,15 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) ð_all_features);
/* allow changing only bits set in hw_features */ - changed = (features ^ dev->active_features) & eth_all_features; - if (changed & ~dev->hw_features) + changed = dev->active_features ^ features; + changed &= eth_all_features; + tmp = changed & ~dev->hw_features; + if (tmp) return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
- dev->wanted_features = - (dev->wanted_features & ~changed) | (features & changed); + dev->wanted_features &= ~changed; + tmp = features & changed; + dev->wanted_features |= tmp;
__netdev_update_features(dev);
For the prototype of netdev_features_t will be changed to be structure with bitmap, it's unable to be initialized when define it. So adjust it.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 +++- drivers/net/ethernet/sfc/ef10.c | 3 ++- drivers/net/ethernet/sfc/efx_common.c | 3 ++- drivers/net/ethernet/sfc/falcon/efx.c | 3 ++- net/core/dev.c | 14 ++++++++++---- net/ethtool/features.c | 3 ++- net/ethtool/ioctl.c | 14 ++++++++++---- 7 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 87cd9187884c..dcdef392ab0c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2394,12 +2394,14 @@ static int hns3_nic_do_ioctl(struct net_device *netdev, static int hns3_nic_set_features(struct net_device *netdev, netdev_features_t features) { - netdev_features_t changed = netdev->active_features ^ features; struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = priv->ae_handle; + netdev_features_t changed; bool enable; int ret;
+ changed = netdev->active_features ^ features; + if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) { enable = !!(features & NETIF_F_GRO_HW); ret = h->ae_algo->ops->set_gro_en(h, enable); diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 0d75361f1acb..c4cab9d5436d 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1311,7 +1311,7 @@ static const int ef10_tso_features_array[] = { 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) { @@ -1356,6 +1356,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx) nic_data->must_restore_piobufs = false; }
+ netdev_features_zero(&hw_enc_features); /* add encapsulated checksum offload features */ if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx)) hw_enc_features |= netdev_ip_csum_features; diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index d5f8a2b3189a..306f5cb24273 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -367,8 +367,8 @@ void efx_start_monitor(struct efx_nic *efx) */ static void efx_start_datapath(struct efx_nic *efx) { - netdev_features_t old_features = efx->net_dev->active_features; bool old_rx_scatter = efx->rx_scatter; + netdev_features_t old_features; size_t rx_buf_len;
/* Calculate the rx buffer allocation parameters required to @@ -413,6 +413,7 @@ static void efx_start_datapath(struct efx_nic *efx) /* Restore previously fixed features in hw_features and remove * features which are fixed now */ + old_features = efx->net_dev->active_features; efx->net_dev->hw_features |= efx->net_dev->active_features; efx->net_dev->hw_features &= ~efx->fixed_features; efx->net_dev->active_features |= efx->fixed_features; diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 2eae365eb7e6..0b04e7e6a002 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -592,8 +592,8 @@ static int ef4_probe_channels(struct ef4_nic *efx) */ static void ef4_start_datapath(struct ef4_nic *efx) { - netdev_features_t old_features = efx->net_dev->active_features; bool old_rx_scatter = efx->rx_scatter; + netdev_features_t old_features; struct ef4_tx_queue *tx_queue; struct ef4_rx_queue *rx_queue; struct ef4_channel *channel; @@ -640,6 +640,7 @@ static void ef4_start_datapath(struct ef4_nic *efx) /* Restore previously fixed features in hw_features and remove * features which are fixed now */ + old_features = efx->net_dev->active_features; efx->net_dev->hw_features |= efx->net_dev->active_features; efx->net_dev->hw_features &= ~efx->fixed_features; efx->net_dev->active_features |= efx->fixed_features; diff --git a/net/core/dev.c b/net/core/dev.c index 7d170f307128..5d7f8575438a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3478,9 +3478,11 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, netdev_features_t netif_skb_features(struct sk_buff *skb) { struct net_device *dev = skb->dev; - netdev_features_t features = dev->active_features; + netdev_features_t features; netdev_features_t tmp;
+ features = dev->active_features; + if (skb_is_gso(skb)) features = gso_features_check(skb, dev, features);
@@ -9423,10 +9425,11 @@ static void net_set_todo(struct net_device *dev) static netdev_features_t netdev_sync_upper_features(struct net_device *lower, struct net_device *upper, netdev_features_t features) { - netdev_features_t upper_disables = NETIF_F_UPPER_DISABLES; + netdev_features_t upper_disables; netdev_features_t feature; int feature_bit;
+ upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { feature = __NETIF_F_BIT(feature_bit); if (!(upper->wanted_features & feature) @@ -9443,10 +9446,11 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower, static void netdev_sync_lower_features(struct net_device *upper, struct net_device *lower, netdev_features_t features) { - netdev_features_t upper_disables = NETIF_F_UPPER_DISABLES; + netdev_features_t upper_disables; netdev_features_t feature; int feature_bit;
+ upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { feature = __NETIF_F_BIT(feature_bit); if (!(features & feature) && (lower->active_features & feature)) { @@ -9618,7 +9622,9 @@ int __netdev_update_features(struct net_device *dev) netdev_sync_lower_features(dev, lower, features);
if (!err) { - netdev_features_t diff = features ^ dev->active_features; + netdev_features_t diff; + + diff = features ^ dev->active_features;
if (diff & NETIF_F_RX_UDP_TUNNEL_PORT) { /* udp_tunnel_{get,drop}_rx_info both need diff --git a/net/ethtool/features.c b/net/ethtool/features.c index d327c6032d7b..c0950d181b13 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -144,9 +144,10 @@ static netdev_features_t ethnl_bitmap_to_features(unsigned long *src) { const unsigned int nft_bits = sizeof(netdev_features_t) * BITS_PER_BYTE; const unsigned int words = BITS_TO_LONGS(NETDEV_FEATURE_COUNT); - netdev_features_t ret = 0; + netdev_features_t ret; unsigned int i;
+ netdev_features_zero(&ret); for (i = 0; i < words; i++) ret |= (netdev_features_t)(src[i]) << (i * BITS_PER_LONG); ret &= ~(netdev_features_t)0 >> (nft_bits - NETDEV_FEATURE_COUNT); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index ab003dc2cfd8..2a6f5b9cf988 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -124,7 +124,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;
@@ -138,6 +139,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); @@ -266,12 +269,13 @@ static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd) static int ethtool_get_one_feature(struct net_device *dev, char __user *useraddr, u32 ethcmd) { - netdev_features_t mask = ethtool_get_feature_mask(ethcmd); + netdev_features_t mask; struct ethtool_value edata = { .cmd = ethcmd, - .data = !!(dev->active_features & mask), };
+ mask = ethtool_get_feature_mask(ethcmd); + edata.data = !!(dev->active_features & mask); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; @@ -332,13 +336,15 @@ static u32 __ethtool_get_flags(struct net_device *dev)
static int __ethtool_set_flags(struct net_device *dev, u32 data) { - netdev_features_t features = 0, changed; netdev_features_t eth_all_features; + netdev_features_t features; + netdev_features_t changed; netdev_features_t tmp;
if (data & ~ETH_ALL_FLAGS) return -EINVAL;
+ netdev_features_zero(&features); if (data & ETH_FLAG_LRO) features |= NETIF_F_LRO; if (data & ETH_FLAG_RXVLAN)
Replace the '|' and '|=' operations of single feature bit by netdev_features_set_bit helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 18 +++++++----- drivers/net/ethernet/sfc/ef10.c | 4 +-- drivers/net/ethernet/sfc/ef100_nic.c | 3 +- drivers/net/ethernet/sfc/ef10_sriov.c | 3 +- drivers/net/ethernet/sfc/efx.c | 4 +-- drivers/net/ethernet/sfc/falcon/efx.c | 6 ++-- net/core/dev.c | 29 ++++++++++--------- net/ethtool/ioctl.c | 26 +++++++++-------- 8 files changed, 51 insertions(+), 42 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index dcdef392ab0c..3261a8c8d10e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3264,7 +3264,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_features_set_bit(netdev, NETIF_F_GSO_GRE_CSUM_BIT);
netdev_features_zero(&features); netdev_features_set_array(hns3_default_features_array, @@ -3274,25 +3274,27 @@ static void hns3_set_default_feature(struct net_device *netdev) netdev->active_features |= features;
if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { - netdev->active_features |= NETIF_F_GRO_HW; + netdev_active_features_set_bit(netdev, NETIF_F_GRO_HW_BIT);
if (!(h->flags & HNAE3_SUPPORT_VF)) - netdev->active_features |= NETIF_F_NTUPLE; + netdev_active_features_set_bit(netdev, + NETIF_F_NTUPLE_BIT); }
if (test_bit(HNAE3_DEV_SUPPORT_UDP_GSO_B, ae_dev->caps)) - netdev->active_features |= NETIF_F_GSO_UDP_L4; + netdev_active_features_set_bit(netdev, NETIF_F_GSO_UDP_L4_BIT);
if (test_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps)) - netdev->active_features |= NETIF_F_HW_CSUM; + netdev_active_features_set_bit(netdev, NETIF_F_HW_CSUM_BIT); else netdev->active_features |= netdev_ip_csum_features;
if (test_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps)) - netdev->active_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; + netdev_active_features_set_bit(netdev, + NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
if (test_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps)) - netdev->active_features |= NETIF_F_HW_TC; + netdev_active_features_set_bit(netdev, NETIF_F_HW_TC_BIT);
netdev->hw_features |= netdev->active_features; if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) @@ -3306,7 +3308,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_features_set_bit(netdev, NETIF_F_TSO_MANGLEID_BIT); }
static int hns3_alloc_buffer(struct hns3_enet_ring *ring, diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index c4cab9d5436d..baad36133e11 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_features_or(efx->net_dev, NETIF_F_RXFCS_BIT);
rc = efx_mcdi_port_get_number(efx); if (rc < 0) @@ -1370,7 +1370,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx) &encap_tso_features);
hw_enc_features |= encap_tso_features; - hw_enc_features |= NETIF_F_TSO; + netdev_features_set_bit(NETIF_F_TSO_BIT, &hw_enc_features); efx->net_dev->active_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 42d1d426fb4f..ecb4f189b4ef 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -207,7 +207,8 @@ static int efx_ef100_init_datapath_caps(struct efx_nic *efx) /* EF100 HW can only offload outer checksums if they are UDP, * so for GRE_CSUM we have to use GSO_PARTIAL. */ - net_dev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM; + netdev_gso_partial_features_set_bit(net_dev, + NETIF_F_GSO_GRE_CSUM_BIT); } efx->num_mac_stats = MCDI_WORD(outbuf, GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS); diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index 7f5aa4a8c451..215a84981cbc 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_features_set_bit(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 139f63f93227..4e96984a7fff 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1024,7 +1024,7 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) ARRAY_SIZE(efx_active_features_array)); if ((*efx->type->offload_features & NETIF_F_IPV6_CSUM) || (*efx->type->offload_features & NETIF_F_HW_CSUM)) - net_dev->active_features |= NETIF_F_TSO6; + netdev_active_features_set_bit(net_dev, NETIF_F_TSO6_BIT); /* Check whether device supports TSO */ if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) net_dev->active_features &= ~NETIF_F_ALL_TSO; @@ -1077,7 +1077,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_features_set_bit(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 0b04e7e6a002..8f16c2b98fd4 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2893,7 +2893,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_features_set_bit(NETIF_F_HIGHDMA_BIT, &efx->fixed_features);
pci_set_drvdata(pci_dev, efx); SET_NETDEV_DEV(net_dev, &pci_dev->dev); @@ -2916,8 +2916,8 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, goto fail3;
net_dev->active_features |= *efx->type->offload_features; - net_dev->active_features |= NETIF_F_SG; - net_dev->active_features |= NETIF_F_RXCSUM; + netdev_active_features_set_bit(net_dev, NETIF_F_SG_BIT); + netdev_active_features_set_bit(net_dev, NETIF_F_RXCSUM_BIT); /* Mask for features that also apply to VLAN devices */ netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, ARRAY_SIZE(efx_vlan_features_array)); diff --git a/net/core/dev.c b/net/core/dev.c index 5d7f8575438a..706960c607e4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3326,7 +3326,8 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, struct net_device *dev = skb->dev;
partial_features = dev->active_features & dev->gso_partial_features; - partial_features |= NETIF_F_GSO_ROBUST; + netdev_features_set_bit(NETIF_F_GSO_ROBUST_BIT, + &partial_features); if (!skb_gso_ok(skb, features | partial_features)) features &= ~NETIF_F_GSO_PARTIAL; } @@ -9909,14 +9910,16 @@ int register_netdevice(struct net_device *dev) dev->active_features |= NETIF_F_SOFT_FEATURES;
if (dev->udp_tunnel_nic_info) { - dev->active_features |= NETIF_F_RX_UDP_TUNNEL_PORT; - dev->hw_features |= NETIF_F_RX_UDP_TUNNEL_PORT; + netdev_active_features_set_bit(dev, + NETIF_F_RX_UDP_TUNNEL_PORT_BIT); + netdev_hw_features_set_bit(dev, + NETIF_F_RX_UDP_TUNNEL_PORT_BIT); }
dev->wanted_features = dev->active_features & dev->hw_features;
if (!(dev->flags & IFF_LOOPBACK)) - dev->hw_features |= NETIF_F_NOCACHE_COPY; + netdev_hw_features_set_bit(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 @@ -9924,26 +9927,26 @@ int register_netdevice(struct net_device *dev) * feature itself but allows the user to enable it later. */ if (dev->hw_features & NETIF_F_TSO) - dev->hw_features |= NETIF_F_TSO_MANGLEID; + netdev_hw_features_set_bit(dev, NETIF_F_TSO_MANGLEID_BIT); if (dev->vlan_features & NETIF_F_TSO) - dev->vlan_features |= NETIF_F_TSO_MANGLEID; + netdev_vlan_features_set_bit(dev, NETIF_F_TSO_MANGLEID_BIT); if (dev->mpls_features & NETIF_F_TSO) - dev->mpls_features |= NETIF_F_TSO_MANGLEID; + netdev_mpls_features_set_bit(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_features_set_bit(dev, NETIF_F_TSO_MANGLEID_BIT);
/* Make NETIF_F_HIGHDMA inheritable to VLAN devices. */ - dev->vlan_features |= NETIF_F_HIGHDMA; + netdev_vlan_features_set_bit(dev, NETIF_F_HIGHDMA_BIT);
/* Make NETIF_F_SG inheritable to tunnel devices. */ - dev->hw_enc_features |= NETIF_F_SG; - dev->hw_enc_features |= NETIF_F_GSO_PARTIAL; + netdev_hw_enc_features_set_bit(dev, NETIF_F_SG_BIT); + netdev_hw_enc_features_set_bit(dev, NETIF_F_GSO_PARTIAL_BIT);
/* Make NETIF_F_SG inheritable to MPLS. */ - dev->mpls_features |= NETIF_F_SG; + netdev_mpls_features_set_bit(dev, NETIF_F_SG_BIT);
ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); ret = notifier_to_errno(ret); @@ -11030,7 +11033,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_features_set_bit(NETIF_F_VLAN_CHALLENGED_BIT, &mask);
tmp = NETIF_F_ONE_FOR_ALL | NETIF_F_CSUM_MASK; tmp &= one; diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 2a6f5b9cf988..77538c5175ec 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -238,28 +238,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_features_set_bit(NETIF_F_FCOE_CRC_BIT, &tmp); + netdev_features_set_bit(NETIF_F_SCTP_CRC_BIT, &tmp); return tmp; case ETHTOOL_GRXCSUM: case ETHTOOL_SRXCSUM: - tmp |= NETIF_F_RXCSUM; + netdev_features_set_bit(NETIF_F_RXCSUM_BIT, &tmp); return tmp; case ETHTOOL_GSG: case ETHTOOL_SSG: - tmp |= NETIF_F_SG; - tmp |= NETIF_F_FRAGLIST; + netdev_features_set_bit(NETIF_F_SG_BIT, &tmp); + netdev_features_set_bit(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_features_set_bit(NETIF_F_GSO_BIT, &tmp); return tmp; case ETHTOOL_GGRO: case ETHTOOL_SGRO: - tmp |= NETIF_F_GRO; + netdev_features_set_bit(NETIF_F_GRO_BIT, &tmp); return tmp; default: BUG(); @@ -346,15 +346,17 @@ 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_features_set_bit(NETIF_F_LRO_BIT, &features); if (data & ETH_FLAG_RXVLAN) - features |= NETIF_F_HW_VLAN_CTAG_RX; + netdev_features_set_bit(NETIF_F_HW_VLAN_CTAG_RX_BIT, + &features); if (data & ETH_FLAG_TXVLAN) - features |= NETIF_F_HW_VLAN_CTAG_TX; + netdev_features_set_bit(NETIF_F_HW_VLAN_CTAG_TX_BIT, + &features); if (data & ETH_FLAG_NTUPLE) - features |= NETIF_F_NTUPLE; + netdev_features_set_bit(NETIF_F_NTUPLE_BIT, &features); if (data & ETH_FLAG_RXHASH) - features |= NETIF_F_RXHASH; + netdev_features_set_bit(NETIF_F_RXHASH_BIT, &features);
netdev_features_zero(ð_all_features); netdev_features_set_array(ethtool_all_features_array,
Replace the '|' and '|=' operations of features by netdev_features_or helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 11 ++++++----- drivers/net/ethernet/sfc/ef10.c | 8 +++++--- drivers/net/ethernet/sfc/ef100_nic.c | 16 +++++++++------- drivers/net/ethernet/sfc/efx.c | 9 +++++---- drivers/net/ethernet/sfc/efx_common.c | 5 +++-- drivers/net/ethernet/sfc/falcon/efx.c | 10 ++++++---- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- include/linux/netdevice.h | 6 +++--- net/core/dev.c | 18 +++++++++--------- net/ethtool/features.c | 5 +++-- net/ethtool/ioctl.c | 12 +++++++----- 12 files changed, 58 insertions(+), 46 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 3261a8c8d10e..38ab3692f073 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3271,7 +3271,7 @@ static void hns3_set_default_feature(struct net_device *netdev) ARRAY_SIZE(hns3_default_features_array), &features);
- netdev->active_features |= features; + netdev_active_features_direct_or(netdev, features);
if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { netdev_active_features_set_bit(netdev, NETIF_F_GRO_HW_BIT); @@ -3287,7 +3287,8 @@ 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_features_set_bit(netdev, NETIF_F_HW_CSUM_BIT); else - netdev->active_features |= netdev_ip_csum_features; + netdev_active_features_direct_or(netdev, + netdev_ip_csum_features);
if (test_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps)) netdev_active_features_set_bit(netdev, @@ -3296,7 +3297,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_features_set_bit(netdev, NETIF_F_HW_TC_BIT);
- netdev->hw_features |= netdev->active_features; + netdev_hw_features_direct_or(netdev, netdev->active_features); if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
@@ -3305,9 +3306,9 @@ static void hns3_set_default_feature(struct net_device *netdev) ARRAY_SIZE(hns3_vlan_off_features_array), &vlan_off_features); features = netdev->active_features & ~vlan_off_features; - netdev->vlan_features |= features; + netdev_vlan_features_direct_or(netdev, features);
- netdev->hw_enc_features |= netdev->vlan_features; + netdev_hw_enc_features_direct_or(netdev, netdev->vlan_features); netdev_hw_enc_features_set_bit(netdev, NETIF_F_TSO_MANGLEID_BIT); }
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index baad36133e11..cf21be47de1b 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1359,7 +1359,8 @@ 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_direct_or(&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; @@ -1369,9 +1370,10 @@ static int efx_ef10_init_nic(struct efx_nic *efx) ARRAY_SIZE(ef10_tso_features_array), &encap_tso_features);
- hw_enc_features |= encap_tso_features; + netdev_features_direct_or(&hw_enc_features, encap_tso_features); netdev_features_set_bit(NETIF_F_TSO_BIT, &hw_enc_features); - efx->net_dev->active_features |= encap_tso_features; + netdev_active_features_direct_or(efx->net_dev, + encap_tso_features); } efx->net_dev->hw_enc_features = hw_enc_features;
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index ecb4f189b4ef..eb4e884a3f54 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -201,9 +201,9 @@ static int efx_ef100_init_datapath_caps(struct efx_nic *efx) netdev_features_set_array(ef100_tso_features_array, ARRAY_SIZE(ef100_tso_features_array), &tso); - net_dev->active_features |= tso; - net_dev->hw_features |= tso; - net_dev->hw_enc_features |= tso; + netdev_active_features_direct_or(net_dev, tso); + netdev_hw_features_direct_or(net_dev, tso); + netdev_hw_enc_features_direct_or(net_dev, tso); /* EF100 HW can only offload outer checksums if they are UDP, * so for GRE_CSUM we have to use GSO_PARTIAL. */ @@ -1137,10 +1137,12 @@ static int ef100_probe_main(struct efx_nic *efx) return -ENOMEM; efx->nic_data = nic_data; nic_data->efx = efx; - net_dev->active_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_direct_or(net_dev, + *efx->type->offload_features); + netdev_hw_features_direct_or(net_dev, *efx->type->offload_features); + netdev_hw_enc_features_direct_or(net_dev, + *efx->type->offload_features); + netdev_vlan_features_direct_or(net_dev, NETIF_F_ALL_TSO); netdev_vlan_features_set_array(net_dev, ef100_vlan_features_array, ARRAY_SIZE(ef100_vlan_features_array));
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 4e96984a7fff..c46e02ee3d14 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1019,7 +1019,8 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) }
/* Determine netdevice features */ - net_dev->active_features |= *efx->type->offload_features; + netdev_active_features_direct_or(net_dev, + *efx->type->offload_features); netdev_active_features_set_array(net_dev, efx_active_features_array, ARRAY_SIZE(efx_active_features_array)); if ((*efx->type->offload_features & NETIF_F_IPV6_CSUM) || @@ -1029,12 +1030,12 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) net_dev->active_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_direct_or(net_dev, NETIF_F_ALL_TSO); netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, ARRAY_SIZE(efx_vlan_features_array));
tmp = net_dev->active_features & ~efx->fixed_features; - net_dev->hw_features |= tmp; + netdev_hw_features_direct_or(net_dev, tmp);
/* Disable receiving frames with bad FCS, by default. */ net_dev->active_features &= ~NETIF_F_RXALL; @@ -1044,7 +1045,7 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) * receive VLAN tagged packets due to vPort restrictions). */ net_dev->active_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; - net_dev->active_features |= efx->fixed_features; + netdev_active_features_direct_or(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 306f5cb24273..f9600306813b 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -414,9 +414,10 @@ static void efx_start_datapath(struct efx_nic *efx) * features which are fixed now */ old_features = efx->net_dev->active_features; - efx->net_dev->hw_features |= efx->net_dev->active_features; + netdev_hw_features_direct_or(efx->net_dev, + efx->net_dev->active_features); efx->net_dev->hw_features &= ~efx->fixed_features; - efx->net_dev->active_features |= efx->fixed_features; + netdev_active_features_direct_or(efx->net_dev, efx->fixed_features); if (efx->net_dev->active_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 8f16c2b98fd4..ce558c1a1cbb 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -641,9 +641,10 @@ static void ef4_start_datapath(struct ef4_nic *efx) * features which are fixed now */ old_features = efx->net_dev->active_features; - efx->net_dev->hw_features |= efx->net_dev->active_features; + netdev_hw_features_direct_or(efx->net_dev, + efx->net_dev->active_features); efx->net_dev->hw_features &= ~efx->fixed_features; - efx->net_dev->active_features |= efx->fixed_features; + netdev_active_features_direct_or(efx->net_dev, efx->fixed_features); if (efx->net_dev->active_features != old_features) netdev_features_change(efx->net_dev);
@@ -2915,7 +2916,8 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, if (rc) goto fail3;
- net_dev->active_features |= *efx->type->offload_features; + netdev_active_features_direct_or(net_dev, + *efx->type->offload_features); netdev_active_features_set_bit(net_dev, NETIF_F_SG_BIT); netdev_active_features_set_bit(net_dev, NETIF_F_RXCSUM_BIT); /* Mask for features that also apply to VLAN devices */ @@ -2928,7 +2930,7 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, * receive VLAN tagged packets due to vPort restrictions). */ net_dev->active_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; - net_dev->active_features |= efx->fixed_features; + netdev_active_features_direct_or(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 88d73fd078b9..9c549e89d85e 100644 --- a/drivers/net/ethernet/sfc/falcon/net_driver.h +++ b/drivers/net/ethernet/sfc/falcon/net_driver.h @@ -1302,7 +1302,7 @@ static inline netdev_features_t ef4_supported_features(const struct ef4_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return net_dev->active_features | net_dev->hw_features; + return netdev_active_features_or(net_dev, net_dev->hw_features); }
/* Get the current TX queue insert index. */ diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 1b6c4f29337b..989f8584718b 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1687,7 +1687,7 @@ static inline netdev_features_t efx_supported_features(const struct efx_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return net_dev->active_features | net_dev->hw_features; + return netdev_active_features_or(net_dev, net_dev->hw_features); }
/* Get the current TX queue insert index. */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 44e6c3a02b46..c5b06798641c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5421,9 +5421,9 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, tmp = f1 ^ f2; if (tmp & NETIF_F_HW_CSUM) { if (f1 & NETIF_F_HW_CSUM) - f1 |= netdev_ip_csum_features; + netdev_features_direct_or(&f1, netdev_ip_csum_features); else - f2 |= netdev_ip_csum_features; + netdev_features_direct_or(&f2, netdev_ip_csum_features); }
return f1 & f2; @@ -5435,7 +5435,7 @@ static inline netdev_features_t netdev_get_wanted_features( netdev_features_t tmp;
tmp = dev->active_features & ~dev->hw_features; - return dev->wanted_features | tmp; + return netdev_wanted_features_or(dev, tmp); } netdev_features_t netdev_increment_features(netdev_features_t all, netdev_features_t one, netdev_features_t mask); diff --git a/net/core/dev.c b/net/core/dev.c index 706960c607e4..a387618f589d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3328,7 +3328,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, partial_features = dev->active_features & dev->gso_partial_features; netdev_features_set_bit(NETIF_F_GSO_ROBUST_BIT, &partial_features); - if (!skb_gso_ok(skb, features | partial_features)) + if (!skb_gso_ok(skb, netdev_features_or(features, partial_features))) features &= ~NETIF_F_GSO_PARTIAL; }
@@ -3495,7 +3495,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) features &= dev->hw_enc_features;
if (skb_vlan_tagged(skb)) { - tmp = dev->vlan_features | netdev_tx_vlan_features; + tmp = netdev_vlan_features_or(dev, netdev_tx_vlan_features); features = netdev_intersect_features(features, tmp); }
@@ -9905,9 +9905,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->active_features |= NETIF_F_SOFT_FEATURES; + netdev_hw_features_direct_or(dev, NETIF_F_SOFT_FEATURES); + netdev_hw_features_direct_or(dev, NETIF_F_SOFT_FEATURES_OFF); + netdev_active_features_direct_or(dev, NETIF_F_SOFT_FEATURES);
if (dev->udp_tunnel_nic_info) { netdev_active_features_set_bit(dev, @@ -11032,17 +11032,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_direct_or(&mask, NETIF_F_CSUM_MASK); netdev_features_set_bit(NETIF_F_VLAN_CHALLENGED_BIT, &mask);
- tmp = NETIF_F_ONE_FOR_ALL | NETIF_F_CSUM_MASK; + tmp = netdev_features_or(NETIF_F_ONE_FOR_ALL, NETIF_F_CSUM_MASK); tmp &= one; tmp &= mask; - all |= tmp; + netdev_features_direct_or(&all, tmp);
netdev_features_fill(&tmp); tmp &= ~NETIF_F_ALL_FOR_ALL; - tmp |= one; + netdev_features_direct_or(&tmp, one); all &= tmp;
/* If one device supports hw checksumming, set for all. */ diff --git a/net/ethtool/features.c b/net/ethtool/features.c index c0950d181b13..4a37ada0dcb2 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -149,7 +149,8 @@ static netdev_features_t ethnl_bitmap_to_features(unsigned long *src)
netdev_features_zero(&ret); for (i = 0; i < words; i++) - ret |= (netdev_features_t)(src[i]) << (i * BITS_PER_LONG); + netdev_features_direct_or(&ret, + (netdev_features_t)(src[i]) << (i * BITS_PER_LONG)); ret &= ~(netdev_features_t)0 >> (nft_bits - NETDEV_FEATURE_COUNT); return ret; } @@ -256,7 +257,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_direct_or(dev, tmp); __netdev_update_features(dev); } ethnl_features_to_bitmap(new_active, dev->active_features); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 77538c5175ec..6943f97fad0e 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -142,8 +142,10 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) netdev_features_zero(&wanted); netdev_features_zero(&valid); for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) { - valid |= (netdev_features_t)features[i].valid << (32 * i); - wanted |= (netdev_features_t)features[i].requested << (32 * i); + netdev_features_direct_or(&valid, + (netdev_features_t)features[i].valid << (32 * i)); + netdev_features_direct_or(&wanted, + (netdev_features_t)features[i].requested << (32 * i)); }
tmp = valid & ~NETIF_F_ETHTOOL_BITS; @@ -158,7 +160,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_direct_or(dev, tmp); __netdev_update_features(dev);
tmp = dev->wanted_features ^ dev->active_features; @@ -296,7 +298,7 @@ static int ethtool_set_one_feature(struct net_device *dev, return -EOPNOTSUPP;
if (edata.data) - dev->wanted_features |= mask; + netdev_wanted_features_direct_or(dev, mask); else dev->wanted_features &= ~mask;
@@ -372,7 +374,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_direct_or(dev, tmp);
__netdev_update_features(dev);
Replace the '^' operations of features by netdev_features_xor helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- drivers/net/ethernet/sfc/efx_common.c | 2 +- drivers/net/ethernet/sfc/falcon/efx.c | 2 +- include/linux/netdevice.h | 2 +- net/core/dev.c | 2 +- net/ethtool/ioctl.c | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 38ab3692f073..bdb430ba15de 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2400,7 +2400,7 @@ static int hns3_nic_set_features(struct net_device *netdev, bool enable; int ret;
- changed = netdev->active_features ^ features; + changed = netdev_active_features_xor(netdev, features);
if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) { enable = !!(features & NETIF_F_GRO_HW); diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index f9600306813b..771319da0cd4 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -226,7 +226,7 @@ int efx_set_features(struct net_device *net_dev, netdev_features_t data) /* If Rx VLAN filter is changed, update filters via mac_reconfigure. * If rx-fcs is changed, mac_reconfigure updates that too. */ - tmp = net_dev->active_features ^ data; + tmp = netdev_active_features_xor(net_dev, data); if (tmp & NETIF_F_HW_VLAN_CTAG_FILTER || tmp & NETIF_F_RXFCS) { /* efx_set_rx_mode() will schedule MAC work to update filters diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index ce558c1a1cbb..9f745263766d 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2202,7 +2202,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->active_features ^ data; + tmp = netdev_active_features_xor(net_dev, data); if (tmp & NETIF_F_HW_VLAN_CTAG_FILTER) { /* ef4_set_rx_mode() will schedule MAC work to update filters * when a new features are finally set in net_dev. diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c5b06798641c..f1b6cfe87166 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5418,7 +5418,7 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, { netdev_features_t tmp;
- tmp = f1 ^ f2; + tmp = netdev_features_xor(f1, f2); if (tmp & NETIF_F_HW_CSUM) { if (f1 & NETIF_F_HW_CSUM) netdev_features_direct_or(&f1, netdev_ip_csum_features); diff --git a/net/core/dev.c b/net/core/dev.c index a387618f589d..af09e138475a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9625,7 +9625,7 @@ int __netdev_update_features(struct net_device *dev) if (!err) { netdev_features_t diff;
- diff = features ^ dev->active_features; + diff = netdev_active_features_xor(dev, features);
if (diff & NETIF_F_RX_UDP_TUNNEL_PORT) { /* udp_tunnel_{get,drop}_rx_info both need diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 6943f97fad0e..ef2cde3594ad 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -163,7 +163,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) netdev_wanted_features_direct_or(dev, tmp); __netdev_update_features(dev);
- tmp = dev->wanted_features ^ dev->active_features; + tmp = netdev_wanted_features_xor(dev, dev->active_features); if (tmp & valid) ret |= ETHTOOL_F_WISH;
@@ -366,7 +366,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) ð_all_features);
/* allow changing only bits set in hw_features */ - changed = dev->active_features ^ features; + changed = netdev_active_features_xor(dev, features); changed &= eth_all_features; tmp = changed & ~dev->hw_features; if (tmp)
Replace the '&~' and '&= ~' operations of single feature bit by netdev_features_clear_bit helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 3 +- drivers/net/ethernet/sfc/ef10_sriov.c | 3 +- drivers/net/ethernet/sfc/efx.c | 5 ++- drivers/net/ethernet/sfc/falcon/efx.c | 3 +- drivers/net/ethernet/sfc/mcdi_filters.c | 9 ++-- net/core/dev.c | 43 +++++++++++-------- 6 files changed, 39 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index bdb430ba15de..7d9b72667ddb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3299,7 +3299,8 @@ static void hns3_set_default_feature(struct net_device *netdev)
netdev_hw_features_direct_or(netdev, netdev->active_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_features_clear_bit(netdev, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT);
netdev_features_zero(&vlan_off_features); netdev_features_set_array(hns3_vlan_off_features_array, diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index 215a84981cbc..6693d59321dd 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_features_set_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, &efx->fixed_features); else - efx->fixed_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + netdev_features_clear_bit(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 c46e02ee3d14..98f578841580 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1038,13 +1038,14 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) netdev_hw_features_direct_or(net_dev, tmp);
/* Disable receiving frames with bad FCS, by default. */ - net_dev->active_features &= ~NETIF_F_RXALL; + netdev_active_features_clear_bit(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->active_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + netdev_active_features_clear_bit(net_dev, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT); netdev_active_features_direct_or(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 9f745263766d..143f72575557 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2929,7 +2929,8 @@ 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->active_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + netdev_active_features_clear_bit(net_dev, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT); netdev_active_features_direct_or(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 2ff62bc67e03..10a78925c09d 100644 --- a/drivers/net/ethernet/sfc/mcdi_filters.c +++ b/drivers/net/ethernet/sfc/mcdi_filters.c @@ -1326,9 +1326,12 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining) (EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC_IG)))) { netif_info(efx, probe, net_dev, "VLAN filters are not supported in this firmware variant\n"); - net_dev->active_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_features_clear_bit(net_dev, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT); + netdev_features_clear_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + &efx->fixed_features); + netdev_hw_features_clear_bit(net_dev, + NETIF_F_HW_VLAN_CTAG_FILTER_BIT); }
table->entry = vzalloc(array_size(EFX_MCDI_FILTER_TBL_ROWS, diff --git a/net/core/dev.c b/net/core/dev.c index af09e138475a..3e7f5ac4d34a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1577,7 +1577,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_features_clear_bit(dev, NETIF_F_LRO_BIT); netdev_update_features(dev);
if (unlikely(dev->active_features & NETIF_F_LRO)) @@ -1598,7 +1598,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_features_clear_bit(dev, NETIF_F_GRO_HW_BIT); netdev_update_features(dev);
if (unlikely(dev->active_features & NETIF_F_GRO_HW)) @@ -3329,7 +3329,8 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_set_bit(NETIF_F_GSO_ROBUST_BIT, &partial_features); if (!skb_gso_ok(skb, netdev_features_or(features, partial_features))) - features &= ~NETIF_F_GSO_PARTIAL; + netdev_features_clear_bit(NETIF_F_GSO_PARTIAL_BIT, + &features); }
BUILD_BUG_ON(SKB_GSO_CB_OFFSET + @@ -3419,7 +3420,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_features_clear_bit(NETIF_F_SG_BIT, &features);
return features; } @@ -3470,7 +3471,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_features_clear_bit(NETIF_F_TSO_MANGLEID_BIT, + &features); }
return features; @@ -9490,30 +9492,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_features_clear_bit(NETIF_F_TSO_BIT, &features); + netdev_features_clear_bit(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_features_clear_bit(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_features_clear_bit(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_features_clear_bit(NETIF_F_TSO_ECN_BIT, &tmp); if (!(features & tmp) && (features & NETIF_F_TSO_ECN)) - features &= ~NETIF_F_TSO_ECN; + netdev_features_clear_bit(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_features_clear_bit(NETIF_F_GSO_BIT, &features); }
/* GSO partial features require GSO partial be set */ @@ -9532,7 +9534,8 @@ 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_features_clear_bit(NETIF_F_GRO_HW_BIT, + &features); } }
@@ -9540,18 +9543,19 @@ 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_features_clear_bit(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_features_clear_bit(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_features_clear_bit(NETIF_F_LRO_BIT, &features); }
if (features & NETIF_F_HW_TLS_TX) { @@ -9561,13 +9565,14 @@ 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_features_clear_bit(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_features_clear_bit(NETIF_F_HW_TLS_RX_BIT, &features); }
return features; @@ -11048,7 +11053,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_features_clear_bit(NETIF_F_HW_CSUM_BIT, &tmp); all &= ~tmp; }
Replace the '& ~' and '&= ~' operations of features by netdev_features_andnot helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 5 ++-- drivers/net/ethernet/sfc/efx.c | 4 +-- drivers/net/ethernet/sfc/efx_common.c | 10 ++++--- drivers/net/ethernet/sfc/falcon/efx.c | 7 ++--- include/linux/netdevice.h | 2 +- net/core/dev.c | 26 +++++++++++-------- net/ethtool/features.c | 2 +- net/ethtool/ioctl.c | 12 ++++----- 8 files changed, 38 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 7d9b72667ddb..435a4adac524 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2467,7 +2467,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_direct_andnot(&features, + netdev_csum_gso_features_mask);
return features; } @@ -3306,7 +3307,7 @@ static void hns3_set_default_feature(struct net_device *netdev) netdev_features_set_array(hns3_vlan_off_features_array, ARRAY_SIZE(hns3_vlan_off_features_array), &vlan_off_features); - features = netdev->active_features & ~vlan_off_features; + features = netdev_active_features_andnot(netdev, vlan_off_features); netdev_vlan_features_direct_or(netdev, features);
netdev_hw_enc_features_direct_or(netdev, netdev->vlan_features); diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 98f578841580..10b420dc450f 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1028,13 +1028,13 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) netdev_active_features_set_bit(net_dev, NETIF_F_TSO6_BIT); /* Check whether device supports TSO */ if (!efx->type->tso_versions || !efx->type->tso_versions(efx)) - net_dev->active_features &= ~NETIF_F_ALL_TSO; + netdev_active_features_direct_andnot(net_dev, NETIF_F_ALL_TSO); /* Mask for features that also apply to VLAN devices */ netdev_vlan_features_direct_or(net_dev, NETIF_F_ALL_TSO); netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, ARRAY_SIZE(efx_vlan_features_array));
- tmp = net_dev->active_features & ~efx->fixed_features; + tmp = netdev_active_features_andnot(net_dev, efx->fixed_features); netdev_hw_features_direct_or(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 771319da0cd4..94a3884f016e 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -216,7 +216,7 @@ int efx_set_features(struct net_device *net_dev, netdev_features_t data) int rc;
/* If disabling RX n-tuple filtering, clear existing filters */ - tmp = net_dev->active_features & ~data; + tmp = netdev_active_features_andnot(net_dev, data); if (tmp & NETIF_F_NTUPLE) { rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); if (rc) @@ -416,7 +416,7 @@ static void efx_start_datapath(struct efx_nic *efx) old_features = efx->net_dev->active_features; netdev_hw_features_direct_or(efx->net_dev, efx->net_dev->active_features); - efx->net_dev->hw_features &= ~efx->fixed_features; + netdev_hw_features_direct_andnot(efx->net_dev, efx->fixed_features); netdev_active_features_direct_or(efx->net_dev, efx->fixed_features); if (efx->net_dev->active_features != old_features) netdev_features_change(efx->net_dev); @@ -1371,10 +1371,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_direct_andnot(&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_direct_andnot(&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 143f72575557..b7217aee193f 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -643,7 +643,7 @@ static void ef4_start_datapath(struct ef4_nic *efx) old_features = efx->net_dev->active_features; netdev_hw_features_direct_or(efx->net_dev, efx->net_dev->active_features); - efx->net_dev->hw_features &= ~efx->fixed_features; + netdev_hw_features_direct_andnot(efx->net_dev, efx->fixed_features); netdev_active_features_direct_or(efx->net_dev, efx->fixed_features); if (efx->net_dev->active_features != old_features) netdev_features_change(efx->net_dev); @@ -2194,7 +2194,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->active_features & ~data; + tmp = netdev_active_features_andnot(net_dev, data); if (tmp & NETIF_F_NTUPLE) { rc = efx->type->filter_clear_rx(efx, EF4_FILTER_PRI_MANUAL); if (rc) @@ -2923,7 +2923,8 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, /* Mask for features that also apply to VLAN devices */ netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, ARRAY_SIZE(efx_vlan_features_array)); - net_dev->hw_features = net_dev->active_features & ~efx->fixed_features; + net_dev->hw_features = netdev_active_features_andnot(net_dev, + efx->fixed_features);
/* Disable VLAN filtering by default. It may be enforced if * the feature is fixed (i.e. VLAN filters are required to diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f1b6cfe87166..4f9022e02906 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5434,7 +5434,7 @@ static inline netdev_features_t netdev_get_wanted_features( { netdev_features_t tmp;
- tmp = dev->active_features & ~dev->hw_features; + tmp = netdev_active_features_andnot(dev, netdev_hw_features(dev)); return netdev_wanted_features_or(dev, tmp); } netdev_features_t netdev_increment_features(netdev_features_t all, diff --git a/net/core/dev.c b/net/core/dev.c index 3e7f5ac4d34a..d7e6f44ce62b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3417,7 +3417,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_direct_andnot(&features, + netdev_csum_gso_features_mask); } if (illegal_highdma(skb->dev, skb)) netdev_features_clear_bit(NETIF_F_SG_BIT, &features); @@ -3447,11 +3448,11 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, u16 gso_segs = skb_shinfo(skb)->gso_segs;
if (gso_segs > READ_ONCE(dev->gso_max_segs)) - return features & ~NETIF_F_GSO_MASK; + return netdev_features_andnot(features, NETIF_F_GSO_MASK);
if (!skb_shinfo(skb)->gso_type) { skb_warn_bad_offload(skb); - return features & ~NETIF_F_GSO_MASK; + return netdev_features_andnot(features, NETIF_F_GSO_MASK); }
/* Support for GSO partial features requires software @@ -3461,7 +3462,8 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, * segmented the frame. */ if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL)) - features &= ~dev->gso_partial_features; + netdev_features_direct_andnot(&features, + dev->gso_partial_features);
/* Make sure to clear the IPv4 ID mangling feature if the * IPv4 header has the potential to be fragmented. @@ -9439,7 +9441,7 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower, && (features & feature)) { netdev_dbg(lower, "Dropping feature %pNF, upper dev %s has it off.\n", &feature, upper->name); - features &= ~feature; + netdev_features_direct_andnot(&features, feature); } }
@@ -9459,7 +9461,7 @@ static void netdev_sync_lower_features(struct net_device *upper, if (!(features & feature) && (lower->active_features & feature)) { netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", &feature, lower->name); - lower->wanted_features &= ~feature; + netdev_wanted_features_direct_andnot(lower, feature); __netdev_update_features(lower);
if (unlikely(lower->active_features & feature)) @@ -9480,13 +9482,14 @@ 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_direct_andnot(&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_direct_andnot(&features, NETIF_F_ALL_TSO); }
if ((features & NETIF_F_TSO) && !(features & NETIF_F_HW_CSUM) && @@ -9523,7 +9526,8 @@ 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_direct_andnot(&features, + dev->gso_partial_features); }
if (!(features & NETIF_F_RXCSUM)) { @@ -11046,7 +11050,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all, netdev_features_direct_or(&all, tmp);
netdev_features_fill(&tmp); - tmp &= ~NETIF_F_ALL_FOR_ALL; + netdev_features_direct_andnot(&tmp, NETIF_F_ALL_FOR_ALL); netdev_features_direct_or(&tmp, one); all &= tmp;
@@ -11054,7 +11058,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all, if (all & NETIF_F_HW_CSUM) { tmp = NETIF_F_CSUM_MASK; netdev_features_clear_bit(NETIF_F_HW_CSUM_BIT, &tmp); - all &= ~tmp; + netdev_features_direct_andnot(&all, tmp); }
return all; diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 4a37ada0dcb2..5d54f45d1bfd 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) 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_direct_andnot(dev, dev->hw_features); tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features; netdev_wanted_features_direct_or(dev, tmp); __netdev_update_features(dev); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index ef2cde3594ad..2a552e16954e 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -148,17 +148,17 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) (netdev_features_t)features[i].requested << (32 * i)); }
- tmp = valid & ~NETIF_F_ETHTOOL_BITS; + tmp = netdev_features_andnot(valid, NETIF_F_ETHTOOL_BITS); if (tmp) return -EINVAL;
- tmp = valid & ~dev->hw_features; + tmp = netdev_hw_features_andnot_r(dev, valid); if (tmp) { valid &= dev->hw_features; ret |= ETHTOOL_F_UNSUPPORTED; }
- dev->wanted_features &= ~valid; + netdev_wanted_features_direct_andnot(dev, valid); tmp = wanted & valid; netdev_wanted_features_direct_or(dev, tmp); __netdev_update_features(dev); @@ -300,7 +300,7 @@ static int ethtool_set_one_feature(struct net_device *dev, if (edata.data) netdev_wanted_features_direct_or(dev, mask); else - dev->wanted_features &= ~mask; + netdev_wanted_features_direct_andnot(dev, mask);
__netdev_update_features(dev);
@@ -368,11 +368,11 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) /* allow changing only bits set in hw_features */ changed = netdev_active_features_xor(dev, features); changed &= eth_all_features; - tmp = changed & ~dev->hw_features; + tmp = netdev_hw_features_andnot_r(dev, changed); if (tmp) return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
- dev->wanted_features &= ~changed; + netdev_wanted_features_direct_andnot(dev, changed); tmp = features & changed; netdev_wanted_features_direct_or(dev, tmp);
Replace the '&' operations of single feature bit by netdev_features_test_bit helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 30 +++--- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 4 +- drivers/net/ethernet/sfc/ef10.c | 3 +- drivers/net/ethernet/sfc/ef100_rx.c | 4 +- drivers/net/ethernet/sfc/ef100_tx.c | 8 +- drivers/net/ethernet/sfc/efx.c | 6 +- drivers/net/ethernet/sfc/falcon/efx.c | 7 +- drivers/net/ethernet/sfc/falcon/rx.c | 4 +- drivers/net/ethernet/sfc/farch.c | 2 +- drivers/net/ethernet/sfc/mcdi_filters.c | 4 +- drivers/net/ethernet/sfc/mcdi_port_common.c | 2 +- drivers/net/ethernet/sfc/rx.c | 2 +- drivers/net/ethernet/sfc/rx_common.c | 5 +- include/linux/netdevice.h | 23 ++--- net/core/dev.c | 92 ++++++++++--------- net/ethtool/ioctl.c | 10 +- 16 files changed, 113 insertions(+), 93 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 435a4adac524..a1a6accf8867 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1492,7 +1492,8 @@ static int hns3_handle_vtags(struct hns3_enet_ring *tx_ring, return -EINVAL;
if (skb->protocol == htons(ETH_P_8021Q) && - !(handle->kinfo.netdev->active_features & NETIF_F_HW_VLAN_CTAG_TX)) { + !netdev_active_features_test_bit(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. @@ -2402,36 +2403,41 @@ static int hns3_nic_set_features(struct net_device *netdev,
changed = netdev_active_features_xor(netdev, features);
- if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) { - enable = !!(features & NETIF_F_GRO_HW); + if (netdev_features_test_bit(NETIF_F_GRO_HW_BIT, changed) && + h->ae_algo->ops->set_gro_en) { + enable = netdev_features_test_bit(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_features_test_bit(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_features_test_bit(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_features_test_bit(NETIF_F_NTUPLE_BIT, changed) && + h->ae_algo->ops->enable_fd) { + enable = netdev_features_test_bit(NETIF_F_NTUPLE_BIT, features); h->ae_algo->ops->enable_fd(h, enable); }
- if ((netdev->active_features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) && + if (netdev_active_features_test_bit(netdev, NETIF_F_HW_TC_BIT) && + !netdev_features_test_bit(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_features_test_bit(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_features_test_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, + features); ret = h->ae_algo->ops->enable_vlan_filter(h, enable); if (ret) return ret; @@ -3885,7 +3891,7 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
skb_checksum_none_assert(skb);
- if (!(netdev->active_features & NETIF_F_RXCSUM)) + if !(netdev_active_features_test_bit(netdev, NETIF_F_RXCSUM_BIT)) return;
if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) @@ -4176,7 +4182,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->active_features & NETIF_F_HW_VLAN_CTAG_RX) { + if (netdev_active_features_test_bit(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 6db162eec2c2..a86a402646d2 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->active_features & NETIF_F_HW_VLAN_CTAG_FILTER) + netdev_active_features_test_bit(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->active_features & NETIF_F_HW_VLAN_CTAG_FILTER) + netdev_active_features_test_bit(ndev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT)) h->ae_algo->ops->enable_vlan_filter(h, true); #endif
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index cf21be47de1b..1a92dd1a0462 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -2707,7 +2707,8 @@ 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->active_features & NETIF_F_RXALL)) { + if (!netdev_active_features_test_bit(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 63309527fb28..fe41a6f3a11b 100644 --- a/drivers/net/ethernet/sfc/ef100_rx.c +++ b/drivers/net/ethernet/sfc/ef100_rx.c @@ -64,7 +64,7 @@ void __ef100_rx_packet(struct efx_channel *channel) prefix = (u32 *)(eh - ESE_GZ_RX_PKT_PREFIX_LEN);
if (ef100_has_fcs_error(channel, prefix) && - unlikely(!(efx->net_dev->active_features & NETIF_F_RXALL))) + unlikely(!netdev_active_features_test_bit(efx->net_dev, NETIF_F_RXALL_BIT))) goto out;
rx_buf->len = le16_to_cpu((__force __le16)PREFIX_FIELD(prefix, LENGTH)); @@ -76,7 +76,7 @@ void __ef100_rx_packet(struct efx_channel *channel) goto out; }
- if (likely(efx->net_dev->active_features & NETIF_F_RXCSUM)) { + if (likely(netdev_active_features_test_bit(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 c388f4c7d913..4f6410e279a1 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->active_features & NETIF_F_TSO)) + if (!netdev_active_features_test_bit(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->active_features & NETIF_F_HW_CSUM)) + if (likely(netdev_active_features_test_bit(efx->net_dev, NETIF_F_HW_CSUM_BIT))) ef100_set_tx_csum_partial(skb, buffer, txd); - if (efx->net_dev->active_features & NETIF_F_HW_VLAN_CTAG_TX && + if (netdev_active_features_test_bit(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->active_features & NETIF_F_HW_VLAN_CTAG_TX) + if (netdev_active_features_test_bit(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 10b420dc450f..428fe5e6850b 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1023,8 +1023,10 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) *efx->type->offload_features); netdev_active_features_set_array(net_dev, efx_active_features_array, ARRAY_SIZE(efx_active_features_array)); - if ((*efx->type->offload_features & NETIF_F_IPV6_CSUM) || - (*efx->type->offload_features & NETIF_F_HW_CSUM)) + if (netdev_features_test_bit(NETIF_F_IPV6_CSUM_BIT, + *efx->type->offload_features) || + netdev_features_test_bit(NETIF_F_HW_CSUM_BIT, + *efx->type->offload_features)) netdev_active_features_set_bit(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/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index b7217aee193f..efa3054cba35 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -1696,7 +1696,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_features_test_bit(NETIF_F_NTUPLE_BIT, + *efx->type->offload_features)) { struct ef4_channel *channel; int i, success = 1;
@@ -2195,7 +2196,7 @@ static int ef4_set_features(struct net_device *net_dev, netdev_features_t data)
/* If disabling RX n-tuple filtering, clear existing filters */ tmp = netdev_active_features_andnot(net_dev, data); - if (tmp & NETIF_F_NTUPLE) { + if (netdev_features_test_bit(NETIF_F_NTUPLE_BIT, tmp)) { rc = efx->type->filter_clear_rx(efx, EF4_FILTER_PRI_MANUAL); if (rc) return rc; @@ -2203,7 +2204,7 @@ static int ef4_set_features(struct net_device *net_dev, netdev_features_t data)
/* If Rx VLAN filter is changed, update filters via mac_reconfigure */ tmp = netdev_active_features_xor(net_dev, data); - if (tmp & NETIF_F_HW_VLAN_CTAG_FILTER) { + if (netdev_features_test_bit(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 49cc903768a6..276442d1c24b 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->active_features & NETIF_F_RXHASH) + if (netdev_active_features_test_bit(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->active_features & NETIF_F_RXCSUM))) + if (unlikely(!netdev_active_features_test_bit(efx->net_dev, NETIF_F_RXCSUM_BIT))) rx_buf->flags &= ~EF4_RX_PKT_CSUMMED;
if ((rx_buf->flags & EF4_RX_PKT_TCP) && !channel->type->receive_skb) diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index 8d0e328afb0d..2434f0c16b3f 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -921,7 +921,7 @@ static u16 efx_farch_handle_rx_not_ok(struct efx_rx_queue *rx_queue, (void) rx_ev_other_err; #endif
- if (efx->net_dev->active_features & NETIF_F_RXALL) + if (netdev_active_features_test_bit(efx->net_dev, NETIF_F_RXALL_BIT)) /* don't discard frame for CRC error */ rx_ev_eth_crc_err = false;
diff --git a/drivers/net/ethernet/sfc/mcdi_filters.c b/drivers/net/ethernet/sfc/mcdi_filters.c index 10a78925c09d..eeb1a600974e 100644 --- a/drivers/net/ethernet/sfc/mcdi_filters.c +++ b/drivers/net/ethernet/sfc/mcdi_filters.c @@ -1343,7 +1343,7 @@ int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining)
table->mc_promisc_last = false; table->vlan_filter = - !!(efx->net_dev->active_features & NETIF_F_HW_VLAN_CTAG_FILTER); + netdev_active_features_test_bit(efx->net_dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT); INIT_LIST_HEAD(&table->vlan_list); init_rwsem(&table->lock);
@@ -1760,7 +1760,7 @@ void efx_mcdi_filter_sync_rx_mode(struct efx_nic *efx) * Do it in advance to avoid conflicts for unicast untagged and * VLAN 0 tagged filters. */ - vlan_filter = !!(net_dev->active_features & NETIF_F_HW_VLAN_CTAG_FILTER); + vlan_filter = netdev_active_features_test_bit(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 e6c8332e77fd..8d3d4b2b8faa 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->active_features & NETIF_F_RXFCS)); + netdev_active_features_test_bit(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 1f7463d5df91..f139a61103af 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->active_features & NETIF_F_RXCSUM))) + if (unlikely(!netdev_active_features_test_bit(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 1c550b6178e2..434730a94c7e 100644 --- a/drivers/net/ethernet/sfc/rx_common.c +++ b/drivers/net/ethernet/sfc/rx_common.c @@ -517,7 +517,7 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, return; }
- if (efx->net_dev->active_features & NETIF_F_RXHASH && + if (netdev_active_features_test_bit(efx->net_dev, NETIF_F_RXHASH_BIT) && efx_rx_buf_hash_valid(efx, eh)) skb_set_hash(skb, efx_rx_buf_hash(efx, eh), PKT_HASH_TYPE_L3); @@ -796,7 +796,8 @@ int efx_probe_filters(struct efx_nic *efx) goto out_unlock;
#ifdef CONFIG_RFS_ACCEL - if (*efx->type->offload_features & NETIF_F_NTUPLE) { + if (netdev_features_test_bit(NETIF_F_NTUPLE_BIT, + *efx->type->offload_features)) { struct efx_channel *channel; int i, success = 1;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4f9022e02906..294e902c6077 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2894,7 +2894,7 @@ static inline bool netdev_features_subset(const netdev_features_t src1,
static inline bool netif_elide_gro(const struct net_device *dev) { - if (!(dev->active_features & NETIF_F_GRO) || dev->xdp_prog) + if (!netdev_active_features_test_bit(dev, NETIF_F_GRO_BIT) || dev->xdp_prog) return true; return false; } @@ -4915,7 +4915,7 @@ static inline void netif_tx_unlock_bh(struct net_device *dev) }
#define HARD_TX_LOCK(dev, txq, cpu) { \ - if ((dev->active_features & NETIF_F_LLTX) == 0) { \ + if (!netdev_active_features_test_bit(dev, NETIF_F_LLTX_BIT)) { \ __netif_tx_lock(txq, cpu); \ } else { \ __netif_tx_acquire(txq); \ @@ -4923,12 +4923,12 @@ static inline void netif_tx_unlock_bh(struct net_device *dev) }
#define HARD_TX_TRYLOCK(dev, txq) \ - (((dev->active_features & NETIF_F_LLTX) == 0) ? \ + (!netdev_active_features_test_bit(dev, NETIF_F_LLTX_BIT) ? \ __netif_tx_trylock(txq) : \ __netif_tx_acquire(txq))
#define HARD_TX_UNLOCK(dev, txq) { \ - if ((dev->active_features & NETIF_F_LLTX) == 0) { \ + if (!netdev_active_features_test_bit(dev, NETIF_F_LLTX_BIT)) { \ __netif_tx_unlock(txq); \ } else { \ __netif_tx_release(txq); \ @@ -5339,20 +5339,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_features_test_bit(NETIF_F_FCOE_CRC_BIT, features);
/* Assume this is an IP checksum (not SCTP CRC) */
- if (features & NETIF_F_HW_CSUM) { + if (netdev_features_test_bit(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_features_test_bit(NETIF_F_IP_CSUM_BIT, features); case htons(ETH_P_IPV6): - return !!(features & NETIF_F_IPV6_CSUM); + return netdev_features_test_bit(NETIF_F_IPV6_CSUM_BIT, features); default: return false; } @@ -5419,8 +5419,8 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, netdev_features_t tmp;
tmp = netdev_features_xor(f1, f2); - if (tmp & NETIF_F_HW_CSUM) { - if (f1 & NETIF_F_HW_CSUM) + if (netdev_features_test_bit(NETIF_F_HW_CSUM_BIT, tmp)) { + if (netdev_features_test_bit(NETIF_F_HW_CSUM_BIT, f1)) netdev_features_direct_or(&f1, netdev_ip_csum_features); else netdev_features_direct_or(&f2, netdev_ip_csum_features); @@ -5493,7 +5493,8 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type) static inline bool skb_gso_ok(struct sk_buff *skb, netdev_features_t features) { return net_gso_ok(features, skb_shinfo(skb)->gso_type) && - (!skb_has_frag_list(skb) || (features & NETIF_F_FRAGLIST)); + (!skb_has_frag_list(skb) || + netdev_features_test_bit(NETIF_F_FRAGLIST_BIT, features)); }
static inline bool netif_needs_gso(struct sk_buff *skb, diff --git a/net/core/dev.c b/net/core/dev.c index d7e6f44ce62b..4bb40175e38a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1580,7 +1580,7 @@ void dev_disable_lro(struct net_device *dev) netdev_wanted_features_clear_bit(dev, NETIF_F_LRO_BIT); netdev_update_features(dev);
- if (unlikely(dev->active_features & NETIF_F_LRO)) + if (unlikely(netdev_active_features_test_bit(dev, NETIF_F_LRO_BIT))) netdev_WARN(dev, "failed to disable LRO!\n");
netdev_for_each_lower_dev(dev, lower_dev, iter) @@ -1601,7 +1601,7 @@ static void dev_disable_gro_hw(struct net_device *dev) netdev_wanted_features_clear_bit(dev, NETIF_F_GRO_HW_BIT); netdev_update_features(dev);
- if (unlikely(dev->active_features & NETIF_F_GRO_HW)) + if (unlikely(netdev_active_features_test_bit(dev, NETIF_F_GRO_HW_BIT))) netdev_WARN(dev, "failed to disable GRO_HW!\n"); }
@@ -3321,7 +3321,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_features_test_bit(NETIF_F_GSO_PARTIAL_BIT, features)) { netdev_features_t partial_features; struct net_device *dev = skb->dev;
@@ -3373,7 +3373,7 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) #ifdef CONFIG_HIGHMEM int i;
- if (!(dev->active_features & NETIF_F_HIGHDMA)) { + if (!netdev_active_features_test_bit(dev, NETIF_F_HIGHDMA_BIT)) { for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -3572,10 +3572,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_features_test_bit(NETIF_F_SCTP_CRC_BIT, features) ? 0 : skb_crc32c_csum_help(skb);
- if (features & NETIF_F_HW_CSUM) + if (netdev_features_test_bit(NETIF_F_HW_CSUM_BIT, features)) return 0;
if (features & netdev_ip_csum_features) { @@ -4329,7 +4329,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->active_features & NETIF_F_NTUPLE)) + !netdev_active_features_test_bit(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)) @@ -9479,7 +9479,7 @@ 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_features_test_bit(NETIF_F_HW_CSUM_BIT, features) && (features & netdev_ip_csum_features)) { netdev_warn(dev, "mixed HW and IP checksum settings.\n"); netdev_features_direct_andnot(&features, @@ -9487,56 +9487,61 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, }
/* 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_features_test_bit(NETIF_F_SG_BIT, features)) { netdev_dbg(dev, "Dropping TSO features since no SG feature.\n"); netdev_features_direct_andnot(&features, NETIF_F_ALL_TSO); }
- if ((features & NETIF_F_TSO) && !(features & NETIF_F_HW_CSUM) && - !(features & NETIF_F_IP_CSUM)) { + if (netdev_features_test_bit(NETIF_F_TSO_BIT, features) && + !netdev_features_test_bit(NETIF_F_HW_CSUM_BIT, features) && + !netdev_features_test_bit(NETIF_F_IP_CSUM_BIT, features)) { netdev_dbg(dev, "Dropping TSO features since no CSUM feature.\n"); netdev_features_clear_bit(NETIF_F_TSO_BIT, &features); netdev_features_clear_bit(NETIF_F_TSO_ECN_BIT, &features); }
- if ((features & NETIF_F_TSO6) && !(features & NETIF_F_HW_CSUM) && - !(features & NETIF_F_IPV6_CSUM)) { + if (netdev_features_test_bit(NETIF_F_TSO6_BIT, features) && + !netdev_features_test_bit(NETIF_F_HW_CSUM_BIT, features) && + !netdev_features_test_bit(NETIF_F_IPV6_CSUM_BIT, features)) { netdev_dbg(dev, "Dropping TSO6 features since no CSUM feature.\n"); netdev_features_clear_bit(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_features_test_bit(NETIF_F_TSO_MANGLEID_BIT, features) && + !netdev_features_test_bit(NETIF_F_TSO_BIT, features)) netdev_features_clear_bit(NETIF_F_TSO_MANGLEID_BIT, &features);
/* TSO ECN requires that TSO is present as well. */ tmp = NETIF_F_ALL_TSO; netdev_features_clear_bit(NETIF_F_TSO_ECN_BIT, &tmp); - if (!(features & tmp) && (features & NETIF_F_TSO_ECN)) + if (!(features & tmp) && + netdev_features_test_bit(NETIF_F_TSO_ECN_BIT, features)) netdev_features_clear_bit(NETIF_F_TSO_ECN_BIT, &features);
/* Software GSO depends on SG. */ - if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) { + if (netdev_features_test_bit(NETIF_F_GSO_BIT, features) && + !netdev_features_test_bit(NETIF_F_SG_BIT, features)) { netdev_dbg(dev, "Dropping NETIF_F_GSO since no SG feature.\n"); netdev_features_clear_bit(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_features_test_bit(NETIF_F_GSO_PARTIAL_BIT, features)) { netdev_dbg(dev, "Dropping partially supported GSO features since no GSO partial.\n"); netdev_features_direct_andnot(&features, dev->gso_partial_features); }
- if (!(features & NETIF_F_RXCSUM)) { + if (!netdev_features_test_bit(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_features_test_bit(NETIF_F_GRO_HW_BIT, features)) { netdev_dbg(dev, "Dropping NETIF_F_GRO_HW since no RXCSUM feature.\n"); netdev_features_clear_bit(NETIF_F_GRO_HW_BIT, &features); @@ -9544,28 +9549,30 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, }
/* LRO/HW-GRO features cannot be combined with RX-FCS */ - if (features & NETIF_F_RXFCS) { - if (features & NETIF_F_LRO) { + if (netdev_features_test_bit(NETIF_F_RXFCS_BIT, features)) { + if (netdev_features_test_bit(NETIF_F_LRO_BIT, features)) { netdev_dbg(dev, "Dropping LRO feature since RX-FCS is requested.\n"); netdev_features_clear_bit(NETIF_F_LRO_BIT, &features); }
- if (features & NETIF_F_GRO_HW) { + if (netdev_features_test_bit(NETIF_F_GRO_HW_BIT, features)) { netdev_dbg(dev, "Dropping HW-GRO feature since RX-FCS is requested.\n"); netdev_features_clear_bit(NETIF_F_GRO_HW_BIT, &features); } }
- if ((features & NETIF_F_GRO_HW) && (features & NETIF_F_LRO)) { + if (netdev_features_test_bit(NETIF_F_GRO_HW_BIT, features) && + netdev_features_test_bit(NETIF_F_LRO_BIT, features)) { netdev_dbg(dev, "Dropping LRO feature since HW-GRO is requested.\n"); netdev_features_clear_bit(NETIF_F_LRO_BIT, &features); }
- if (features & NETIF_F_HW_TLS_TX) { + if (netdev_features_test_bit(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_features_test_bit(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"); @@ -9574,7 +9581,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_features_test_bit(NETIF_F_HW_TLS_RX_BIT, features) && + !netdev_features_test_bit(NETIF_F_RXCSUM_BIT, features)) { netdev_dbg(dev, "Dropping TLS RX HW offload feature since no RXCSUM feature.\n"); netdev_features_clear_bit(NETIF_F_HW_TLS_RX_BIT, &features); } @@ -9636,7 +9644,7 @@ int __netdev_update_features(struct net_device *dev)
diff = netdev_active_features_xor(dev, features);
- if (diff & NETIF_F_RX_UDP_TUNNEL_PORT) { + if (netdev_features_test_bit(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. @@ -9644,7 +9652,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_features_test_bit(NETIF_F_RX_UDP_TUNNEL_PORT_BIT, features)) { dev->active_features = features; udp_tunnel_get_rx_info(dev); } else { @@ -9652,8 +9660,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_features_test_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, diff)) { + if (netdev_features_test_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) { dev->active_features = features; err |= vlan_get_rx_ctag_filter_info(dev); } else { @@ -9661,8 +9669,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_features_test_bit(NETIF_F_HW_VLAN_STAG_FILTER_BIT, diff)) { + if (netdev_features_test_bit(NETIF_F_HW_VLAN_STAG_FILTER_BIT, features)) { dev->active_features = features; err |= vlan_get_rx_stag_filter_info(dev); } else { @@ -9896,8 +9904,8 @@ int register_netdevice(struct net_device *dev) } }
- if ((dev->hw_features & NETIF_F_HW_VLAN_CTAG_FILTER || - dev->active_features & NETIF_F_HW_VLAN_CTAG_FILTER) && + if ((netdev_hw_features_test_bit(dev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT) || + netdev_active_features_test_bit(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"); @@ -9935,13 +9943,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_features_test_bit(dev, NETIF_F_TSO_BIT)) netdev_hw_features_set_bit(dev, NETIF_F_TSO_MANGLEID_BIT); - if (dev->vlan_features & NETIF_F_TSO) + if (netdev_vlan_features_test_bit(dev, NETIF_F_TSO_BIT)) netdev_vlan_features_set_bit(dev, NETIF_F_TSO_MANGLEID_BIT); - if (dev->mpls_features & NETIF_F_TSO) + if (netdev_mpls_features_test_bit(dev, NETIF_F_TSO_BIT)) netdev_mpls_features_set_bit(dev, NETIF_F_TSO_MANGLEID_BIT); - if (dev->hw_enc_features & NETIF_F_TSO) + if (netdev_hw_enc_features_test_bit(dev, NETIF_F_TSO_BIT)) netdev_hw_enc_features_set_bit(dev, NETIF_F_TSO_MANGLEID_BIT);
/* Make NETIF_F_HIGHDMA inheritable to VLAN devices. @@ -10842,7 +10850,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->active_features & NETIF_F_NETNS_LOCAL) + if (netdev_active_features_test_bit(dev, NETIF_F_NETNS_LOCAL_BIT)) goto out;
/* Ensure the device has been registrered */ @@ -11040,7 +11048,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all, { netdev_features_t tmp;
- if (mask & NETIF_F_HW_CSUM) + if (netdev_features_test_bit(NETIF_F_HW_CSUM_BIT, mask)) netdev_features_direct_or(&mask, NETIF_F_CSUM_MASK); netdev_features_set_bit(NETIF_F_VLAN_CHALLENGED_BIT, &mask);
@@ -11055,7 +11063,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_features_test_bit(NETIF_F_HW_CSUM_BIT, all)) { tmp = NETIF_F_CSUM_MASK; netdev_features_clear_bit(NETIF_F_HW_CSUM_BIT, &tmp); netdev_features_direct_andnot(&all, tmp); @@ -11213,7 +11221,7 @@ static void __net_exit default_device_exit_net(struct net *net) char fb_name[IFNAMSIZ];
/* Ignore unmoveable devices (i.e. loopback) */ - if (dev->active_features & NETIF_F_NETNS_LOCAL) + if (netdev_active_features_test_bit(dev, NETIF_F_NETNS_LOCAL_BIT)) continue;
/* Leave virtual devices for the generic cleanup */ diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 2a552e16954e..e6f6690b3848 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -322,15 +322,15 @@ static u32 __ethtool_get_flags(struct net_device *dev) { u32 flags = 0;
- if (dev->active_features & NETIF_F_LRO) + if (netdev_active_features_test_bit(dev, NETIF_F_LRO_BIT)) flags |= ETH_FLAG_LRO; - if (dev->active_features & NETIF_F_HW_VLAN_CTAG_RX) + if (netdev_active_features_test_bit(dev, NETIF_F_HW_VLAN_CTAG_RX_BIT)) flags |= ETH_FLAG_RXVLAN; - if (dev->active_features & NETIF_F_HW_VLAN_CTAG_TX) + if (netdev_active_features_test_bit(dev, NETIF_F_HW_VLAN_CTAG_TX_BIT)) flags |= ETH_FLAG_TXVLAN; - if (dev->active_features & NETIF_F_NTUPLE) + if (netdev_active_features_test_bit(dev, NETIF_F_NTUPLE_BIT)) flags |= ETH_FLAG_NTUPLE; - if (dev->active_features & NETIF_F_RXHASH) + if (netdev_active_features_test_bit(dev, NETIF_F_RXHASH_BIT)) flags |= ETH_FLAG_RXHASH;
return flags;
Replace the '(f1 & f2)' operations of features by netdev_features_intersects helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/sfc/efx_common.c | 4 ++-- net/core/dev.c | 20 +++++++++++--------- net/ethtool/ioctl.c | 6 +++--- 3 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index 94a3884f016e..d2874aad3ce7 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -1365,7 +1365,7 @@ netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev struct efx_nic *efx = netdev_priv(dev);
if (skb->encapsulation) { - if (features & NETIF_F_GSO_MASK) + if (netdev_features_intersects(features, NETIF_F_GSO_MASK)) /* Hardware can only do TSO with at most 208 bytes * of headers. */ @@ -1373,7 +1373,7 @@ netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev EFX_TSO2_MAX_HDRLEN) netdev_features_direct_andnot(&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_direct_andnot(&features, netdev_csum_gso_features_mask); diff --git a/net/core/dev.c b/net/core/dev.c index 4bb40175e38a..5e92261a047a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3578,7 +3578,7 @@ int skb_csum_hwoffload_help(struct sk_buff *skb, if (netdev_features_test_bit(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): @@ -9437,8 +9437,8 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower, upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { feature = __NETIF_F_BIT(feature_bit); - if (!(upper->wanted_features & feature) - && (features & feature)) { + if (!netdev_wanted_features_intersects(upper, feature) && + netdev_features_intersects(features, feature)) { netdev_dbg(lower, "Dropping feature %pNF, upper dev %s has it off.\n", &feature, upper->name); netdev_features_direct_andnot(&features, feature); @@ -9458,13 +9458,14 @@ static void netdev_sync_lower_features(struct net_device *upper, upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { feature = __NETIF_F_BIT(feature_bit); - if (!(features & feature) && (lower->active_features & feature)) { + if (!netdev_features_intersects(features, feature) && + netdev_active_features_intersects(lower, feature)) { netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", &feature, lower->name); netdev_wanted_features_direct_andnot(lower, feature); __netdev_update_features(lower);
- if (unlikely(lower->active_features & feature)) + if (unlikely(netdev_active_features_intersects(lower, feature))) netdev_WARN(upper, "failed to disable %pNF on %s!\n", &feature, lower->name); else @@ -9480,14 +9481,15 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
/* Fix illegal checksum combinations */ if (netdev_features_test_bit(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_direct_andnot(&features, netdev_ip_csum_features); }
/* TSO requires that SG is present as well. */ - if ((features & NETIF_F_ALL_TSO) && !netdev_features_test_bit(NETIF_F_SG_BIT, features)) { + if (netdev_features_intersects(features, NETIF_F_ALL_TSO) && + !netdev_features_test_bit(NETIF_F_SG_BIT, features)) { netdev_dbg(dev, "Dropping TSO features since no SG feature.\n"); netdev_features_direct_andnot(&features, NETIF_F_ALL_TSO); } @@ -9515,7 +9517,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_features_clear_bit(NETIF_F_TSO_ECN_BIT, &tmp); - if (!(features & tmp) && + if (!netdev_features_intersects(features, tmp) && netdev_features_test_bit(NETIF_F_TSO_ECN_BIT, features)) netdev_features_clear_bit(NETIF_F_TSO_ECN_BIT, &features);
@@ -9527,7 +9529,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_features_test_bit(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 e6f6690b3848..2190209b2a0c 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -164,7 +164,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) __netdev_update_features(dev);
tmp = netdev_wanted_features_xor(dev, dev->active_features); - if (tmp & valid) + if (netdev_features_intersects(tmp, valid)) ret |= ETHTOOL_F_WISH;
return ret; @@ -277,7 +277,7 @@ static int ethtool_get_one_feature(struct net_device *dev, };
mask = ethtool_get_feature_mask(ethcmd); - edata.data = !!(dev->active_features & mask); + edata.data = !!netdev_active_features_intersects(dev, mask); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; @@ -370,7 +370,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) changed &= eth_all_features; tmp = netdev_hw_features_andnot_r(dev, changed); if (tmp) - return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP; + return netdev_hw_features_intersects(dev, changed) ? -EINVAL : -EOPNOTSUPP;
netdev_wanted_features_direct_andnot(dev, changed); tmp = features & changed;
Replace the '&' and '&=' operations of features by netdev_features_and helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- include/linux/netdevice.h | 2 +- net/core/dev.c | 16 ++++++++-------- net/ethtool/features.c | 3 ++- net/ethtool/ioctl.c | 10 +++++----- 4 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 294e902c6077..ad24bd0c69a3 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5426,7 +5426,7 @@ static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, netdev_features_direct_or(&f2, netdev_ip_csum_features); }
- return f1 & f2; + return netdev_features_and(f1, f2); }
static inline netdev_features_t netdev_get_wanted_features( diff --git a/net/core/dev.c b/net/core/dev.c index 5e92261a047a..a540784c69be 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3325,7 +3325,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t partial_features; struct net_device *dev = skb->dev;
- partial_features = dev->active_features & dev->gso_partial_features; + partial_features = netdev_active_features_and(dev, dev->gso_partial_features); netdev_features_set_bit(NETIF_F_GSO_ROBUST_BIT, &partial_features); if (!skb_gso_ok(skb, netdev_features_or(features, partial_features))) @@ -3394,7 +3394,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_direct_and(&features, skb->dev->mpls_features);
return features; } @@ -3496,7 +3496,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_direct_and(&features, dev->hw_enc_features);
if (skb_vlan_tagged(skb)) { tmp = netdev_vlan_features_or(dev, netdev_tx_vlan_features); @@ -3507,7 +3507,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_direct_and(&features, tmp);
return harmonize_features(skb, features); } @@ -9935,7 +9935,7 @@ int register_netdevice(struct net_device *dev) NETIF_F_RX_UDP_TUNNEL_PORT_BIT); }
- dev->wanted_features = dev->active_features & dev->hw_features; + dev->wanted_features = netdev_active_features_and(dev, dev->hw_enc_features);
if (!(dev->flags & IFF_LOOPBACK)) netdev_hw_features_set_bit(dev, NETIF_F_NOCACHE_COPY_BIT); @@ -11055,14 +11055,14 @@ netdev_features_t netdev_increment_features(netdev_features_t all, netdev_features_set_bit(NETIF_F_VLAN_CHALLENGED_BIT, &mask);
tmp = netdev_features_or(NETIF_F_ONE_FOR_ALL, NETIF_F_CSUM_MASK); - tmp &= one; - tmp &= mask; + netdev_features_direct_and(&tmp, one); + netdev_features_direct_and(&tmp, mask); netdev_features_direct_or(&all, tmp);
netdev_features_fill(&tmp); netdev_features_direct_andnot(&tmp, NETIF_F_ALL_FOR_ALL); netdev_features_direct_or(&tmp, one); - all &= tmp; + netdev_features_direct_and(&all, tmp);
/* If one device supports hw checksumming, set for all. */ if (netdev_features_test_bit(NETIF_F_HW_CSUM_BIT, all)) { diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 5d54f45d1bfd..24b7a217f835 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -256,7 +256,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_direct_andnot(dev, dev->hw_features); - tmp = ethnl_bitmap_to_features(req_wanted) & dev->hw_features; + tmp = netdev_hw_features_and(dev, + ethnl_bitmap_to_features(req_wanted)); netdev_wanted_features_direct_or(dev, tmp); __netdev_update_features(dev); } diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 2190209b2a0c..578b8be4f03f 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -154,12 +154,12 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
tmp = netdev_hw_features_andnot_r(dev, valid); if (tmp) { - valid &= dev->hw_features; + netdev_features_direct_and(&valid, dev->hw_enc_features); ret |= ETHTOOL_F_UNSUPPORTED; }
netdev_wanted_features_direct_andnot(dev, valid); - tmp = wanted & valid; + tmp = netdev_features_and(wanted, valid); netdev_wanted_features_direct_or(dev, tmp); __netdev_update_features(dev);
@@ -293,7 +293,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_direct_and(&mask, dev->hw_enc_features); if (!mask) return -EOPNOTSUPP;
@@ -367,13 +367,13 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
/* allow changing only bits set in hw_features */ changed = netdev_active_features_xor(dev, features); - changed &= eth_all_features; + netdev_features_direct_and(&changed, eth_all_features); tmp = netdev_hw_features_andnot_r(dev, changed); if (tmp) return netdev_hw_features_intersects(dev, changed) ? -EINVAL : -EOPNOTSUPP;
netdev_wanted_features_direct_andnot(dev, changed); - tmp = features & changed; + tmp = netdev_features_and(features, changed); netdev_wanted_features_direct_or(dev, tmp);
__netdev_update_features(dev);
Replace the 'f1 & f2 == f2' operations of features by netdev_features_subset helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- include/linux/netdevice.h | 2 +- net/core/dev.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ad24bd0c69a3..13f397c5960c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -5487,7 +5487,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type) BUILD_BUG_ON(SKB_GSO_UDP_L4 != (NETIF_F_GSO_UDP_L4 >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_FRAGLIST != (NETIF_F_GSO_FRAGLIST >> NETIF_F_GSO_SHIFT));
- return (features & feature) == feature; + return netdev_features_subset(features, features); }
static inline bool skb_gso_ok(struct sk_buff *skb, netdev_features_t features) diff --git a/net/core/dev.c b/net/core/dev.c index a540784c69be..bb3c1b55cc2e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9571,8 +9571,8 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, }
if (netdev_features_test_bit(NETIF_F_HW_TLS_TX_BIT, features)) { - bool ip_csum = (features & netdev_ip_csum_features) == - netdev_ip_csum_features; + bool ip_csum = netdev_features_subset(features, + netdev_ip_csum_features); bool hw_csum = netdev_features_test_bit(NETIF_F_HW_CSUM_BIT, features);
Replace the '==' and '!=' operations of features by netdev_features_equal helpers.
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/sfc/efx_common.c | 2 +- drivers/net/ethernet/sfc/falcon/efx.c | 2 +- net/core/dev.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index d2874aad3ce7..fd6eb74b4fa6 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -418,7 +418,7 @@ static void efx_start_datapath(struct efx_nic *efx) efx->net_dev->active_features); netdev_hw_features_direct_andnot(efx->net_dev, efx->fixed_features); netdev_active_features_direct_or(efx->net_dev, efx->fixed_features); - if (efx->net_dev->active_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 efa3054cba35..22ea294a39fa 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -645,7 +645,7 @@ static void ef4_start_datapath(struct ef4_nic *efx) efx->net_dev->active_features); netdev_hw_features_direct_andnot(efx->net_dev, efx->fixed_features); netdev_active_features_direct_or(efx->net_dev, efx->fixed_features); - if (efx->net_dev->active_features != old_features) + if (!netdev_active_features_equal(efx->net_dev, old_features)) netdev_features_change(efx->net_dev);
/* RX filters may also have scatter-enabled flags */ diff --git a/net/core/dev.c b/net/core/dev.c index bb3c1b55cc2e..57409f97feb1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9613,7 +9613,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->active_features == features) + if (netdev_active_features_equal(dev, features)) goto sync_lower;
netdev_dbg(dev, "Features changed: %pNF -> %pNF\n",
Replace the direct assignment for features members of netdev with netdev_set_xxx_features helpers, for the nic drivers are not supposed to modify netdev_features directly
Signed-off-by: Jian Shen shenjian15@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- drivers/net/ethernet/sfc/ef10.c | 2 +- drivers/net/ethernet/sfc/falcon/efx.c | 4 ++-- net/core/dev.c | 11 ++++++----- 4 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index a1a6accf8867..1a98e08f0a67 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2443,7 +2443,7 @@ static int hns3_nic_set_features(struct net_device *netdev, return ret; }
- netdev->active_features = features; + netdev_set_active_features(netdev, features); return 0; }
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 1a92dd1a0462..c07650368952 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1375,7 +1375,7 @@ static int efx_ef10_init_nic(struct efx_nic *efx) netdev_active_features_direct_or(efx->net_dev, encap_tso_features); } - efx->net_dev->hw_enc_features = hw_enc_features; + netdev_set_hw_enc_features(efx->net_dev, hw_enc_features);
/* don't fail init if RSS setup doesn't work */ rc = efx->type->rx_push_rss_config(efx, false, diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 22ea294a39fa..24993c979312 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -2924,8 +2924,8 @@ static int ef4_pci_probe(struct pci_dev *pci_dev, /* Mask for features that also apply to VLAN devices */ netdev_vlan_features_set_array(net_dev, efx_vlan_features_array, ARRAY_SIZE(efx_vlan_features_array)); - net_dev->hw_features = netdev_active_features_andnot(net_dev, - efx->fixed_features); + netdev_set_hw_features(net_dev, + netdev_active_features_andnot(net_dev, efx->fixed_features));
/* Disable VLAN filtering by default. It may be enforced if * the feature is fixed (i.e. VLAN filters are required to diff --git a/net/core/dev.c b/net/core/dev.c index 57409f97feb1..62bfe12b69d9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9655,7 +9655,7 @@ int __netdev_update_features(struct net_device *dev) * but *after* calling udp_tunnel_drop_rx_info. */ if (netdev_features_test_bit(NETIF_F_RX_UDP_TUNNEL_PORT_BIT, features)) { - dev->active_features = features; + netdev_set_active_features(dev, features); udp_tunnel_get_rx_info(dev); } else { udp_tunnel_drop_rx_info(dev); @@ -9664,7 +9664,7 @@ int __netdev_update_features(struct net_device *dev)
if (netdev_features_test_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, diff)) { if (netdev_features_test_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT, features)) { - dev->active_features = features; + netdev_set_active_features(dev, features); err |= vlan_get_rx_ctag_filter_info(dev); } else { vlan_drop_rx_ctag_filter_info(dev); @@ -9673,14 +9673,14 @@ int __netdev_update_features(struct net_device *dev)
if (netdev_features_test_bit(NETIF_F_HW_VLAN_STAG_FILTER_BIT, diff)) { if (netdev_features_test_bit(NETIF_F_HW_VLAN_STAG_FILTER_BIT, features)) { - dev->active_features = features; + netdev_set_active_features(dev, features); err |= vlan_get_rx_stag_filter_info(dev); } else { vlan_drop_rx_stag_filter_info(dev); } }
- dev->active_features = features; + netdev_set_active_features(dev, features); }
return err < 0 ? 0 : 1; @@ -9935,7 +9935,8 @@ int register_netdevice(struct net_device *dev) NETIF_F_RX_UDP_TUNNEL_PORT_BIT); }
- dev->wanted_features = netdev_active_features_and(dev, dev->hw_enc_features); + netdev_set_wanted_features(dev, + netdev_active_features_and(dev, dev->hw_enc_features));
if (!(dev->flags & IFF_LOOPBACK)) netdev_hw_features_set_bit(dev, NETIF_F_NOCACHE_COPY_BIT);
Replace the direct using for features members of netdev with netdev_xxx_features helpers, for the nic drivers are not supposed to modify netdev_features directly.
I'mo not sure for this patch is necessary, just keep the same rule with others.
Signed-off-by: Jian Shen shenjian15@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 4 ++-- drivers/net/ethernet/sfc/efx_common.c | 4 ++-- drivers/net/ethernet/sfc/falcon/efx.c | 4 ++-- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- net/core/dev.c | 22 ++++++++++--------- net/ethtool/features.c | 15 +++++++------ net/ethtool/ioctl.c | 17 +++++++------- 8 files changed, 37 insertions(+), 33 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 1a98e08f0a67..99582611ab54 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3304,7 +3304,7 @@ static void hns3_set_default_feature(struct net_device *netdev) if (test_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps)) netdev_active_features_set_bit(netdev, NETIF_F_HW_TC_BIT);
- netdev_hw_features_direct_or(netdev, netdev->active_features); + netdev_hw_features_direct_or(netdev, netdev_active_features(netdev)); if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) netdev_hw_features_clear_bit(netdev, NETIF_F_HW_VLAN_CTAG_FILTER_BIT); @@ -3316,7 +3316,7 @@ static void hns3_set_default_feature(struct net_device *netdev) features = netdev_active_features_andnot(netdev, vlan_off_features); netdev_vlan_features_direct_or(netdev, features);
- netdev_hw_enc_features_direct_or(netdev, netdev->vlan_features); + netdev_hw_enc_features_direct_or(netdev, netdev_vlan_features(netdev)); netdev_hw_enc_features_set_bit(netdev, NETIF_F_TSO_MANGLEID_BIT); }
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c index fd6eb74b4fa6..fc7ab298a4db 100644 --- a/drivers/net/ethernet/sfc/efx_common.c +++ b/drivers/net/ethernet/sfc/efx_common.c @@ -413,9 +413,9 @@ static void efx_start_datapath(struct efx_nic *efx) /* Restore previously fixed features in hw_features and remove * features which are fixed now */ - old_features = efx->net_dev->active_features; + old_features = netdev_active_features(efx->net_dev); netdev_hw_features_direct_or(efx->net_dev, - efx->net_dev->active_features); + netdev_active_features(efx->net_dev)); netdev_hw_features_direct_andnot(efx->net_dev, efx->fixed_features); netdev_active_features_direct_or(efx->net_dev, efx->fixed_features); if (!netdev_active_features_equal(efx->net_dev, old_features)) diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index 24993c979312..aca275f0e989 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -640,9 +640,9 @@ static void ef4_start_datapath(struct ef4_nic *efx) /* Restore previously fixed features in hw_features and remove * features which are fixed now */ - old_features = efx->net_dev->active_features; + old_features = netdev_active_features(efx->net_dev); netdev_hw_features_direct_or(efx->net_dev, - efx->net_dev->active_features); + netdev_active_features(efx->net_dev)); netdev_hw_features_direct_andnot(efx->net_dev, efx->fixed_features); netdev_active_features_direct_or(efx->net_dev, efx->fixed_features); if (!netdev_active_features_equal(efx->net_dev, old_features)) diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h index 9c549e89d85e..662162b32429 100644 --- a/drivers/net/ethernet/sfc/falcon/net_driver.h +++ b/drivers/net/ethernet/sfc/falcon/net_driver.h @@ -1302,7 +1302,7 @@ static inline netdev_features_t ef4_supported_features(const struct ef4_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return netdev_active_features_or(net_dev, net_dev->hw_features); + return netdev_active_features_or(net_dev, netdev_hw_features(net_dev)); }
/* Get the current TX queue insert index. */ diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 989f8584718b..ca0975ad0d13 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1687,7 +1687,7 @@ static inline netdev_features_t efx_supported_features(const struct efx_nic *efx { const struct net_device *net_dev = efx->net_dev;
- return netdev_active_features_or(net_dev, net_dev->hw_features); + return netdev_active_features_or(net_dev, netdev_hw_features(net_dev)); }
/* Get the current TX queue insert index. */ diff --git a/net/core/dev.c b/net/core/dev.c index 62bfe12b69d9..c7f95ff8cf10 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3172,7 +3172,7 @@ static void skb_warn_bad_offload(const struct sk_buff *skb) } skb_dump(KERN_WARNING, skb, false); WARN(1, "%s: caps=(%pNF, %pNF)\n", - name, dev ? &dev->active_features : &null_features, + name, dev ? &netdev_active_features(dev) : &null_features, skb->sk ? &skb->sk->sk_route_caps : &null_features); }
@@ -3325,7 +3325,8 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t partial_features; struct net_device *dev = skb->dev;
- partial_features = netdev_active_features_and(dev, dev->gso_partial_features); + partial_features = netdev_active_features_and(dev, + netdev_gso_partial_features(dev)); netdev_features_set_bit(NETIF_F_GSO_ROBUST_BIT, &partial_features); if (!skb_gso_ok(skb, netdev_features_or(features, partial_features))) @@ -3394,7 +3395,8 @@ static netdev_features_t net_mpls_features(struct sk_buff *skb, __be16 type) { if (eth_p_mpls(type)) - netdev_features_direct_and(&features, skb->dev->mpls_features); + netdev_features_direct_and(&features, + netdev_mpls_features(skb->dev));
return features; } @@ -3463,7 +3465,7 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, */ if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL)) netdev_features_direct_andnot(&features, - dev->gso_partial_features); + netdev_gso_partial_features(dev));
/* Make sure to clear the IPv4 ID mangling feature if the * IPv4 header has the potential to be fragmented. @@ -3486,7 +3488,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) netdev_features_t features; netdev_features_t tmp;
- features = dev->active_features; + features = netdev_active_features(dev);
if (skb_is_gso(skb)) features = gso_features_check(skb, dev, features); @@ -3496,7 +3498,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) * features for the netdev */ if (skb->encapsulation) - netdev_features_direct_and(&features, dev->hw_enc_features); + netdev_features_direct_and(&features, netdev_hw_enc_features(dev));
if (skb_vlan_tagged(skb)) { tmp = netdev_vlan_features_or(dev, netdev_tx_vlan_features); @@ -9534,7 +9536,7 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, netdev_dbg(dev, "Dropping partially supported GSO features since no GSO partial.\n"); netdev_features_direct_andnot(&features, - dev->gso_partial_features); + netdev_gso_partial_features(dev)); }
if (!netdev_features_test_bit(NETIF_F_RXCSUM_BIT, features)) { @@ -9617,7 +9619,7 @@ int __netdev_update_features(struct net_device *dev) goto sync_lower;
netdev_dbg(dev, "Features changed: %pNF -> %pNF\n", - &dev->active_features, &features); + &netdev_active_features(dev), &features);
if (dev->netdev_ops->ndo_set_features) err = dev->netdev_ops->ndo_set_features(dev, features); @@ -9627,7 +9629,7 @@ int __netdev_update_features(struct net_device *dev) if (unlikely(err < 0)) { netdev_err(dev, "set_features() failed (%d); wanted %pNF, left %pNF\n", - err, &features, &dev->active_features); + err, &features, &netdev_active_features(dev)); /* return non-0 since some features might have changed and * it's better to fire a spurious notification than miss it */ @@ -9936,7 +9938,7 @@ int register_netdevice(struct net_device *dev) }
netdev_set_wanted_features(dev, - netdev_active_features_and(dev, dev->hw_enc_features)); + netdev_active_features_and(dev, netdev_hw_enc_features(dev)));
if (!(dev->flags & IFF_LOOPBACK)) netdev_hw_features_set_bit(dev, NETIF_F_NOCACHE_COPY_BIT); diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 24b7a217f835..01dd727299ed 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -41,9 +41,9 @@ static int features_prepare_data(const struct ethnl_req_info *req_base, struct net_device *dev = reply_base->dev; netdev_features_t all_features;
- ethnl_features_to_bitmap32(data->hw, dev->hw_features); - ethnl_features_to_bitmap32(data->wanted, dev->wanted_features); - ethnl_features_to_bitmap32(data->active, dev->active_features); + ethnl_features_to_bitmap32(data->hw, netdev_hw_features(dev)); + ethnl_features_to_bitmap32(data->wanted, netdev_wanted_features(dev)); + ethnl_features_to_bitmap32(data->active, netdev_active_features(dev)); ethnl_features_to_bitmap32(data->nochange, NETIF_F_NEVER_CHANGE); all_features = GENMASK_ULL(NETDEV_FEATURE_COUNT - 1, 0); ethnl_features_to_bitmap32(data->all, all_features); @@ -237,8 +237,8 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) dev = req_info.dev;
rtnl_lock(); - ethnl_features_to_bitmap(old_active, dev->active_features); - ethnl_features_to_bitmap(old_wanted, dev->wanted_features); + ethnl_features_to_bitmap(old_active, netdev_active_features(dev)); + ethnl_features_to_bitmap(old_wanted, netdev_wanted_features(dev)); ret = ethnl_parse_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT, tb[ETHTOOL_A_FEATURES_WANTED], netdev_features_strings, info->extack); @@ -255,13 +255,14 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) bitmap_andnot(new_wanted, old_wanted, req_mask, NETDEV_FEATURE_COUNT); bitmap_or(req_wanted, new_wanted, req_wanted, NETDEV_FEATURE_COUNT); if (!bitmap_equal(req_wanted, old_wanted, NETDEV_FEATURE_COUNT)) { - netdev_wanted_features_direct_andnot(dev, dev->hw_features); + netdev_wanted_features_direct_andnot(dev, + netdev_hw_features(dev)); tmp = netdev_hw_features_and(dev, ethnl_bitmap_to_features(req_wanted)); netdev_wanted_features_direct_or(dev, tmp); __netdev_update_features(dev); } - ethnl_features_to_bitmap(new_active, dev->active_features); + ethnl_features_to_bitmap(new_active, netdev_active_features(dev)); mod = !bitmap_equal(old_active, new_active, NETDEV_FEATURE_COUNT);
ret = 0; diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 578b8be4f03f..90fb4c2a313d 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -96,9 +96,9 @@ static int ethtool_get_features(struct net_device *dev, void __user *useraddr) BUILD_BUG_ON(ETHTOOL_DEV_FEATURE_WORDS * sizeof(u32) > sizeof(netdev_features_t));
for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) { - features[i].available = (u32)(dev->hw_features >> (32 * i)); - features[i].requested = (u32)(dev->wanted_features >> (32 * i)); - features[i].active = (u32)(dev->active_features >> (32 * i)); + features[i].available = (u32)(netdev_hw_features(dev) >> (32 * i)); + features[i].requested = (u32)(netdev_wanted_features(dev) >> (32 * i)); + features[i].active = (u32)(netdev_active_features(dev) >> (32 * i)); features[i].never_changed = (u32)(NETIF_F_NEVER_CHANGE >> (32 * i)); } @@ -154,7 +154,8 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
tmp = netdev_hw_features_andnot_r(dev, valid); if (tmp) { - netdev_features_direct_and(&valid, dev->hw_enc_features); + netdev_features_direct_and(&valid, + netdev_hw_enc_features(dev)); ret |= ETHTOOL_F_UNSUPPORTED; }
@@ -163,7 +164,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) netdev_wanted_features_direct_or(dev, tmp); __netdev_update_features(dev);
- tmp = netdev_wanted_features_xor(dev, dev->active_features); + tmp = netdev_wanted_features_xor(dev, netdev_active_features(dev)); if (netdev_features_intersects(tmp, valid)) ret |= ETHTOOL_F_WISH;
@@ -293,7 +294,7 @@ static int ethtool_set_one_feature(struct net_device *dev, return -EFAULT;
mask = ethtool_get_feature_mask(ethcmd); - netdev_features_direct_and(&mask, dev->hw_enc_features); + netdev_features_direct_and(&mask, netdev_hw_enc_features(dev)); if (!mask) return -EOPNOTSUPP;
@@ -2840,7 +2841,7 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr, if (rc < 0) goto out; } - old_features = dev->active_features; + old_features = netdev_active_features(dev);
switch (ethcmd) { case ETHTOOL_GSET: @@ -3055,7 +3056,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->active_features) + if (old_features != netdev_active_features(dev)) netdev_features_change(dev); out: if (dev->dev.parent)
For the prototype of netdev_features_t is u64, and the number of netdevice feature bits is 64 now. So there is no space to introduce new feature bit. Change the prototype of netdev_features_t from u64 to structure below: typedef struct { DECLARE_BITMAP(bits, NETDEV_FEATURE_COUNT); } netdev_features_t;
Rewrite the netdev_features helpers to adapt with new prototype.
To avoid mistake using NETIF_F_XXX as NETIF_F_XXX_BIT as input macroes for above helpers, remove all the macroes of NETIF_F_XXX for single feature bit.
With the prototype is no longer u64, the implementation of print interface for netdev features(%pNF) is changed to bitmap. So does the implementation of net/ethtool/.
Signed-off-by: Jian Shen shenjian15@huawei.com --- include/linux/netdev_features.h | 89 +--------------- include/linux/netdevice.h | 173 ++++++++++++++++++++------------ lib/vsprintf.c | 11 +- net/core/dev.c | 30 +++--- net/ethtool/features.c | 67 ++++++------- net/ethtool/ioctl.c | 31 +++--- 6 files changed, 176 insertions(+), 225 deletions(-)
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index b25f2bb31f94..4126016c8d1d 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -9,8 +9,6 @@ #include <linux/bitops.h> #include <asm/byteorder.h>
-typedef u64 netdev_features_t; - enum { NETIF_F_SG_BIT, /* Scatter/gather IO. */ NETIF_F_IP_CSUM_BIT, /* Can checksum TCP/UDP over IPv4. */ @@ -101,94 +99,15 @@ enum { /**/NETDEV_FEATURE_COUNT };
-/* copy'n'paste compression ;) */ -#define __NETIF_F_BIT(bit) ((netdev_features_t)1 << (bit)) -#define __NETIF_F(name) __NETIF_F_BIT(NETIF_F_##name##_BIT) - -#define NETIF_F_FCOE_CRC __NETIF_F(FCOE_CRC) -#define NETIF_F_FCOE_MTU __NETIF_F(FCOE_MTU) -#define NETIF_F_FRAGLIST __NETIF_F(FRAGLIST) -#define NETIF_F_FSO __NETIF_F(FSO) -#define NETIF_F_GRO __NETIF_F(GRO) -#define NETIF_F_GRO_HW __NETIF_F(GRO_HW) -#define NETIF_F_GSO __NETIF_F(GSO) -#define NETIF_F_GSO_ROBUST __NETIF_F(GSO_ROBUST) -#define NETIF_F_HIGHDMA __NETIF_F(HIGHDMA) -#define NETIF_F_HW_CSUM __NETIF_F(HW_CSUM) -#define NETIF_F_HW_VLAN_CTAG_FILTER __NETIF_F(HW_VLAN_CTAG_FILTER) -#define NETIF_F_HW_VLAN_CTAG_RX __NETIF_F(HW_VLAN_CTAG_RX) -#define NETIF_F_HW_VLAN_CTAG_TX __NETIF_F(HW_VLAN_CTAG_TX) -#define NETIF_F_IP_CSUM __NETIF_F(IP_CSUM) -#define NETIF_F_IPV6_CSUM __NETIF_F(IPV6_CSUM) -#define NETIF_F_LLTX __NETIF_F(LLTX) -#define NETIF_F_LOOPBACK __NETIF_F(LOOPBACK) -#define NETIF_F_LRO __NETIF_F(LRO) -#define NETIF_F_NETNS_LOCAL __NETIF_F(NETNS_LOCAL) -#define NETIF_F_NOCACHE_COPY __NETIF_F(NOCACHE_COPY) -#define NETIF_F_NTUPLE __NETIF_F(NTUPLE) -#define NETIF_F_RXCSUM __NETIF_F(RXCSUM) -#define NETIF_F_RXHASH __NETIF_F(RXHASH) -#define NETIF_F_SCTP_CRC __NETIF_F(SCTP_CRC) -#define NETIF_F_SG __NETIF_F(SG) -#define NETIF_F_TSO6 __NETIF_F(TSO6) -#define NETIF_F_TSO_ECN __NETIF_F(TSO_ECN) -#define NETIF_F_TSO __NETIF_F(TSO) -#define NETIF_F_VLAN_CHALLENGED __NETIF_F(VLAN_CHALLENGED) -#define NETIF_F_RXFCS __NETIF_F(RXFCS) -#define NETIF_F_RXALL __NETIF_F(RXALL) -#define NETIF_F_GSO_GRE __NETIF_F(GSO_GRE) -#define NETIF_F_GSO_GRE_CSUM __NETIF_F(GSO_GRE_CSUM) -#define NETIF_F_GSO_IPXIP4 __NETIF_F(GSO_IPXIP4) -#define NETIF_F_GSO_IPXIP6 __NETIF_F(GSO_IPXIP6) -#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) -#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM) -#define NETIF_F_TSO_MANGLEID __NETIF_F(TSO_MANGLEID) -#define NETIF_F_GSO_PARTIAL __NETIF_F(GSO_PARTIAL) -#define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM) -#define NETIF_F_GSO_SCTP __NETIF_F(GSO_SCTP) -#define NETIF_F_GSO_ESP __NETIF_F(GSO_ESP) -#define NETIF_F_GSO_UDP __NETIF_F(GSO_UDP) -#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) -#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX) -#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX) -#define NETIF_F_HW_L2FW_DOFFLOAD __NETIF_F(HW_L2FW_DOFFLOAD) -#define NETIF_F_HW_TC __NETIF_F(HW_TC) -#define NETIF_F_HW_ESP __NETIF_F(HW_ESP) -#define NETIF_F_HW_ESP_TX_CSUM __NETIF_F(HW_ESP_TX_CSUM) -#define NETIF_F_RX_UDP_TUNNEL_PORT __NETIF_F(RX_UDP_TUNNEL_PORT) -#define NETIF_F_HW_TLS_RECORD __NETIF_F(HW_TLS_RECORD) -#define NETIF_F_GSO_UDP_L4 __NETIF_F(GSO_UDP_L4) -#define NETIF_F_HW_TLS_TX __NETIF_F(HW_TLS_TX) -#define NETIF_F_HW_TLS_RX __NETIF_F(HW_TLS_RX) -#define NETIF_F_GRO_FRAGLIST __NETIF_F(GRO_FRAGLIST) -#define NETIF_F_GSO_FRAGLIST __NETIF_F(GSO_FRAGLIST) -#define NETIF_F_HW_MACSEC __NETIF_F(HW_MACSEC) -#define NETIF_F_GRO_UDP_FWD __NETIF_F(GRO_UDP_FWD) -#define NETIF_F_HW_HSR_TAG_INS __NETIF_F(HW_HSR_TAG_INS) -#define NETIF_F_HW_HSR_TAG_RM __NETIF_F(HW_HSR_TAG_RM) -#define NETIF_F_HW_HSR_FWD __NETIF_F(HW_HSR_FWD) -#define NETIF_F_HW_HSR_DUP __NETIF_F(HW_HSR_DUP) - -/* Finds the next feature with the highest number of the range of start till 0. - */ -static inline int find_next_netdev_feature(u64 feature, unsigned long start) -{ - /* like BITMAP_LAST_WORD_MASK() for u64 - * this sets the most significant 64 - start to 0. - */ - feature &= ~0ULL >> (-start & ((sizeof(feature) * 8) - 1)); - - return fls64(feature) - 1; -} +typedef struct { + DECLARE_BITMAP(bits, NETDEV_FEATURE_COUNT); +} netdev_features_t;
/* This goes for the MSB to the LSB through the set feature bits, * mask_addr should be a u64 and bit an int */ #define for_each_netdev_feature(mask_addr, bit) \ - for ((bit) = find_next_netdev_feature((mask_addr), \ - NETDEV_FEATURE_COUNT); \ - (bit) >= 0; \ - (bit) = find_next_netdev_feature((mask_addr), (bit) - 1)) + for_each_set_bit(bit, (unsigned long *)(mask_addr.bits), NETDEV_FEATURE_COUNT)
extern netdev_features_t netdev_ethtool_features __ro_after_init; extern netdev_features_t netdev_never_change_features __ro_after_init; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 13f397c5960c..77d78a4bae9d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2297,24 +2297,24 @@ struct net_device {
static inline void netdev_features_zero(netdev_features_t *dst) { - *dst = 0; + bitmap_zero(dst->bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_features_fill(netdev_features_t *dst) { - *dst = ~0ULL; + bitmap_fill(dst->bits, NETDEV_FEATURE_COUNT); }
static inline bool netdev_features_empty(const netdev_features_t src) { - return src == 0; + return bitmap_empty(src.bits, NETDEV_FEATURE_COUNT); }
/* helpers for netdev features '==' operation */ static inline bool netdev_features_equal(const netdev_features_t src1, const netdev_features_t src2) { - return src1 == src2; + return bitmap_equal(src1.bits, src2.bits, NETDEV_FEATURE_COUNT); }
#define netdev_active_features_equal(ndev, features) \ @@ -2342,7 +2342,10 @@ static inline bool netdev_features_equal(const netdev_features_t src1, static inline netdev_features_t netdev_features_and(const netdev_features_t a, const netdev_features_t b) { - return a & b; + netdev_features_t dst; + + bitmap_and(dst.bits, a.bits, b.bits, NETDEV_FEATURE_COUNT); + return dst; }
#define netdev_active_features_and(ndev, features) \ @@ -2371,63 +2374,73 @@ static inline void netdev_features_direct_and(netdev_features_t *dst, const netdev_features_t features) { - *dst = netdev_features_and(*dst, features); + bitmap_and(dst->bits, dst->bits, features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_active_features_direct_and(struct net_device *ndev, const netdev_features_t features) { - ndev->active_features = netdev_active_features_and(ndev, features); + bitmap_and(ndev->active_features.bits, ndev->active_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_features_direct_and(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_features = netdev_hw_features_and(ndev, features); + bitmap_and(ndev->hw_features.bits, ndev->hw_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_wanted_features_direct_and(struct net_device *ndev, const netdev_features_t features) { - ndev->wanted_features = netdev_wanted_features_and(ndev, features); + bitmap_and(ndev->wanted_features.bits, ndev->wanted_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_vlan_features_direct_and(struct net_device *ndev, const netdev_features_t features) { - ndev->vlan_features = netdev_vlan_features_and(ndev, features); + bitmap_and(ndev->vlan_features.bits, ndev->vlan_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_enc_features_direct_and(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_enc_features = netdev_hw_enc_features_and(ndev, features); + bitmap_and(ndev->hw_enc_features.bits, ndev->hw_enc_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_mpls_features_direct_and(struct net_device *ndev, const netdev_features_t features) { - ndev->mpls_features = netdev_mpls_features_and(ndev, features); + bitmap_and(ndev->mpls_features.bits, ndev->mpls_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_gso_partial_features_direct_and(struct net_device *ndev, const netdev_features_t features) { - ndev->gso_partial_features = netdev_mpls_features_and(ndev, features); + bitmap_and(ndev->gso_partial_features.bits, ndev->gso_partial_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
/* helpers for netdev features '|' operation */ static inline netdev_features_t netdev_features_or(const netdev_features_t a, const netdev_features_t b) { - return a | b; + netdev_features_t dst; + + bitmap_or(dst.bits, a.bits, b.bits, NETDEV_FEATURE_COUNT); + return dst; }
#define netdev_active_features_or(ndev, features) \ @@ -2456,63 +2469,73 @@ static inline void netdev_features_direct_or(netdev_features_t *dst, const netdev_features_t features) { - *dst = netdev_features_or(*dst, features); + bitmap_or(dst->bits, dst->bits, features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_active_features_direct_or(struct net_device *ndev, const netdev_features_t features) { - ndev->active_features = netdev_active_features_or(ndev, features); + bitmap_or(ndev->active_features.bits, ndev->active_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_features_direct_or(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_features = netdev_hw_features_or(ndev, features); + bitmap_or(ndev->hw_features.bits, ndev->hw_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_wanted_features_direct_or(struct net_device *ndev, const netdev_features_t features) { - ndev->wanted_features = netdev_wanted_features_or(ndev, features); + bitmap_or(ndev->wanted_features.bits, ndev->wanted_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_vlan_features_direct_or(struct net_device *ndev, const netdev_features_t features) { - ndev->vlan_features = netdev_vlan_features_or(ndev, features); + bitmap_or(ndev->vlan_features.bits, ndev->vlan_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_enc_features_direct_or(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_enc_features = netdev_hw_enc_features_or(ndev, features); + bitmap_or(ndev->hw_enc_features.bits, ndev->hw_enc_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_mpls_features_direct_or(struct net_device *ndev, const netdev_features_t features) { - ndev->mpls_features = netdev_mpls_features_or(ndev, features); + bitmap_or(ndev->mpls_features.bits, ndev->mpls_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_gso_partial_features_direct_or(struct net_device *ndev, const netdev_features_t features) { - ndev->gso_partial_features = netdev_mpls_features_or(ndev, features); + bitmap_or(ndev->gso_partial_features.bits, ndev->gso_partial_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
/* helpers for netdev features '^' operation */ static inline netdev_features_t netdev_features_xor(const netdev_features_t a, const netdev_features_t b) { - return a ^ b; + netdev_features_t dst; + + bitmap_xor(dst.bits, a.bits, b.bits, NETDEV_FEATURE_COUNT); + return dst; }
#define netdev_active_features_xor(ndev, features) \ @@ -2541,57 +2564,66 @@ static inline void netdev_active_features_direct_xor(struct net_device *ndev, const netdev_features_t features) { - ndev->active_features = netdev_active_features_xor(ndev, features); + bitmap_xor(ndev->active_features.bits, ndev->active_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_features_direct_xor(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_features = netdev_hw_features_xor(ndev, features); + bitmap_xor(ndev->hw_features.bits, ndev->hw_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_wanted_features_direct_xor(struct net_device *ndev, const netdev_features_t features) { - ndev->wanted_features = netdev_wanted_features_xor(ndev, features); + bitmap_xor(ndev->wanted_features.bits, ndev->wanted_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_vlan_features_direct_xor(struct net_device *ndev, const netdev_features_t features) { - ndev->vlan_features = netdev_vlan_features_xor(ndev, features); + bitmap_xor(ndev->vlan_features.bits, ndev->vlan_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_enc_features_direct_xor(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_enc_features = netdev_hw_enc_features_xor(ndev, features); + bitmap_xor(ndev->hw_enc_features.bits, ndev->hw_enc_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_mpls_features_direct_xor(struct net_device *ndev, const netdev_features_t features) { - ndev->mpls_features = netdev_mpls_features_xor(ndev, features); + bitmap_xor(ndev->mpls_features.bits, ndev->mpls_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_gso_partial_features_direct_xor(struct net_device *ndev, const netdev_features_t features) { - ndev->gso_partial_features = - netdev_gso_partial_features_xor(ndev, features); + bitmap_xor(ndev->gso_partial_features.bits, ndev->gso_partial_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
/* helpers for netdev features '& ~' operation */ static inline netdev_features_t netdev_features_andnot(const netdev_features_t a, const netdev_features_t b) { - return a & ~b; + netdev_features_t dst; + + bitmap_andnot(dst.bits, a.bits, b.bits, NETDEV_FEATURE_COUNT); + return dst; }
#define netdev_active_features_andnot(ndev, features) \ @@ -2640,63 +2672,69 @@ static inline void netdev_features_direct_andnot(netdev_features_t *dst, const netdev_features_t features) { - *dst = netdev_features_andnot(*dst, features); + bitmap_andnot(dst->bits, dst->bits, features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_active_features_direct_andnot(struct net_device *ndev, const netdev_features_t features) { - ndev->active_features = netdev_active_features_andnot(ndev, features); + bitmap_andnot(ndev->active_features.bits, ndev->active_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_features_direct_andnot(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_features = netdev_hw_features_andnot(ndev, features); + bitmap_andnot(ndev->hw_features.bits, ndev->hw_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_wanted_features_direct_andnot(struct net_device *ndev, const netdev_features_t features) { - ndev->wanted_features = netdev_wanted_features_andnot(ndev, features); + bitmap_andnot(ndev->wanted_features.bits, ndev->wanted_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_vlan_features_direct_andnot(struct net_device *ndev, const netdev_features_t features) { - ndev->vlan_features = netdev_vlan_features_andnot(ndev, features); + bitmap_andnot(ndev->vlan_features.bits, ndev->vlan_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_hw_enc_features_direct_andnot(struct net_device *ndev, const netdev_features_t features) { - ndev->hw_enc_features = netdev_hw_enc_features_andnot(ndev, features); + bitmap_andnot(ndev->hw_enc_features.bits, ndev->hw_enc_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_mpls_features_direct_andnot(struct net_device *ndev, const netdev_features_t features) { - ndev->mpls_features = netdev_mpls_features_andnot(ndev, features); + bitmap_andnot(ndev->mpls_features.bits, ndev->mpls_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
static inline void netdev_gso_partial_features_direct_andnot(struct net_device *ndev, const netdev_features_t features) { - ndev->gso_partial_features = - netdev_gso_partial_features_andnot(ndev, features); + bitmap_andnot(ndev->gso_partial_features.bits, ndev->gso_partial_features.bits, + features.bits, NETDEV_FEATURE_COUNT); }
/* helpers for netdev features 'set bit' operation */ static inline void netdev_features_set_bit(int nr, netdev_features_t *src) { - *src |= __NETIF_F_BIT(nr); + __set_bit(nr, src->bits); }
#define netdev_active_features_set_bit(ndev, nr) \ @@ -2754,7 +2792,7 @@ static inline void netdev_features_set_array(const int *array, int array_size, /* helpers for netdev features 'clear bit' operation */ static inline void netdev_features_clear_bit(int nr, netdev_features_t *src) { - *src &= ~__NETIF_F_BIT(nr); + __clear_bit(nr, src->bits); }
#define netdev_active_features_clear_bit(ndev, nr) \ @@ -2781,7 +2819,7 @@ static inline void netdev_features_clear_bit(int nr, netdev_features_t *src) /* helpers for netdev features 'test bit' operation */ static inline bool netdev_features_test_bit(int nr, const netdev_features_t src) { - return (src & __NETIF_F_BIT(nr)) > 0; + return test_bit(nr, src.bits); }
#define netdev_active_features_test_bit(ndev, nr) \ @@ -2808,7 +2846,7 @@ static inline bool netdev_features_test_bit(int nr, const netdev_features_t src) static inline bool netdev_features_intersects(const netdev_features_t src1, const netdev_features_t src2) { - return (src1 & src2) > 0; + return bitmap_intersects(src1.bits, src2.bits, NETDEV_FEATURE_COUNT); }
#define netdev_active_features_intersects(ndev, features) \ @@ -2889,7 +2927,7 @@ static inline void netdev_set_gso_partial_features(struct net_device *ndev, static inline bool netdev_features_subset(const netdev_features_t src1, const netdev_features_t src2) { - return (src1 & src2) == src2; + return bitmap_subset(src1.bits, src2.bits, NETDEV_FEATURE_COUNT); }
static inline bool netif_elide_gro(const struct net_device *dev) @@ -5464,28 +5502,31 @@ netdev_features_t netif_skb_features(struct sk_buff *skb);
static inline bool net_gso_ok(netdev_features_t features, int gso_type) { - netdev_features_t feature = (netdev_features_t)gso_type << NETIF_F_GSO_SHIFT; +#define GSO_INDEX(x) ((1ULL << (x)) >> NETIF_F_GSO_SHIFT) + netdev_features_t feature; + + bitmap_from_u64(feature.bits, (u64)gso_type << NETIF_F_GSO_SHIFT));
/* check flags correspondence */ - BUILD_BUG_ON(SKB_GSO_TCPV4 != (NETIF_F_TSO >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_DODGY != (NETIF_F_GSO_ROBUST >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_TCP_FIXEDID != (NETIF_F_TSO_MANGLEID >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_TCPV6 != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_GRE != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_IPXIP4 != (NETIF_F_GSO_IPXIP4 >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_IPXIP6 != (NETIF_F_GSO_IPXIP6 >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_SCTP != (NETIF_F_GSO_SCTP >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_ESP != (NETIF_F_GSO_ESP >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_UDP != (NETIF_F_GSO_UDP >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_UDP_L4 != (NETIF_F_GSO_UDP_L4 >> NETIF_F_GSO_SHIFT)); - BUILD_BUG_ON(SKB_GSO_FRAGLIST != (NETIF_F_GSO_FRAGLIST >> NETIF_F_GSO_SHIFT)); + BUILD_BUG_ON(SKB_GSO_TCPV4 != GSO_INDEX(NETIF_F_TSO_BIT)); + BUILD_BUG_ON(SKB_GSO_DODGY != GSO_INDEX(NETIF_F_GSO_ROBUST_BIT)); + BUILD_BUG_ON(SKB_GSO_TCP_ECN != GSO_INDEX(NETIF_F_TSO_ECN_BIT)); + BUILD_BUG_ON(SKB_GSO_TCP_FIXEDID != GSO_INDEX(NETIF_F_TSO_MANGLEID_BIT)); + BUILD_BUG_ON(SKB_GSO_TCPV6 != GSO_INDEX(NETIF_F_TSO6_BIT)); + BUILD_BUG_ON(SKB_GSO_FCOE != GSO_INDEX(NETIF_F_FSO_BIT)); + BUILD_BUG_ON(SKB_GSO_GRE != GSO_INDEX(NETIF_F_GSO_GRE_BIT)); + BUILD_BUG_ON(SKB_GSO_GRE_CSUM != GSO_INDEX(NETIF_F_GSO_GRE_CSUM_BIT)); + BUILD_BUG_ON(SKB_GSO_IPXIP4 != GSO_INDEX(NETIF_F_GSO_IPXIP4_BIT)); + BUILD_BUG_ON(SKB_GSO_IPXIP6 != GSO_INDEX(NETIF_F_GSO_IPXIP6_BIT)); + BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != GSO_INDEX(NETIF_F_GSO_UDP_TUNNEL_BIT)); + BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != GSO_INDEX(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT)); + BUILD_BUG_ON(SKB_GSO_PARTIAL != GSO_INDEX(NETIF_F_GSO_PARTIAL_BIT)); + BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != GSO_INDEX(NETIF_F_GSO_TUNNEL_REMCSUM_BIT)); + BUILD_BUG_ON(SKB_GSO_SCTP != GSO_INDEX(NETIF_F_GSO_SCTP_BIT)); + BUILD_BUG_ON(SKB_GSO_ESP != GSO_INDEX(NETIF_F_GSO_ESP_BIT)); + BUILD_BUG_ON(SKB_GSO_UDP != GSO_INDEX(NETIF_F_GSO_UDP_BIT)); + BUILD_BUG_ON(SKB_GSO_UDP_L4 != GSO_INDEX(NETIF_F_GSO_UDP_L4_BIT)); + BUILD_BUG_ON(SKB_GSO_FRAGLIST != GSO_INDEX(NETIF_F_GSO_FRAGLIST_BIT));
return netdev_features_subset(features, features); } diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 3b8129dd374c..be018453fae5 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1733,25 +1733,24 @@ char *uuid_string(char *buf, char *end, const u8 *addr, }
static noinline_for_stack -char *netdev_bits(char *buf, char *end, const void *addr, +char *netdev_bits(char *buf, char *end, void *addr, struct printf_spec spec, const char *fmt) { - unsigned long long num; - int size; + unsigned long *bitmap;
if (check_pointer(&buf, end, addr, spec)) return buf;
switch (fmt[1]) { case 'F': - num = *(const netdev_features_t *)addr; - size = sizeof(netdev_features_t); + bitmap = *(netdev_features_t *)addr->bits; + spec->field_width = NETDEV_FEATURE_COUNT; break; default: return error_string(buf, end, "(%pN?)", spec); }
- return special_hex_number(buf, end, num, size); + return bitmap_string(buf, end, add->bits, spec, fmt); }
static noinline_for_stack diff --git a/net/core/dev.c b/net/core/dev.c index c7f95ff8cf10..c98464c11d75 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9433,17 +9433,15 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower, struct net_device *upper, netdev_features_t features) { netdev_features_t upper_disables; - netdev_features_t feature; int feature_bit;
upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { - feature = __NETIF_F_BIT(feature_bit); - if (!netdev_wanted_features_intersects(upper, feature) && - netdev_features_intersects(features, feature)) { - netdev_dbg(lower, "Dropping feature %pNF, upper dev %s has it off.\n", - &feature, upper->name); - netdev_features_direct_andnot(&features, feature); + if (!netdev_wanted_features_test_bit(upper, feature_bit) && + netdev_features_test_bit(features)) { + netdev_dbg(lower, "Dropping feature bit %d, upper dev %s has it off.\n", + feature_bit, upper->name); + netdev_features_clear_bit(feature_bit, &features); } }
@@ -9454,22 +9452,20 @@ static void netdev_sync_lower_features(struct net_device *upper, struct net_device *lower, netdev_features_t features) { netdev_features_t upper_disables; - netdev_features_t feature; int feature_bit;
upper_disables = NETIF_F_UPPER_DISABLES; for_each_netdev_feature(upper_disables, feature_bit) { - feature = __NETIF_F_BIT(feature_bit); - if (!netdev_features_intersects(features, feature) && - netdev_active_features_intersects(lower, feature)) { - netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", - &feature, lower->name); - netdev_wanted_features_direct_andnot(lower, feature); + if (!netdev_features_test_bit(feature_bit, features) && + netdev_active_features_test_bit(lower, feature_bit)) { + netdev_dbg(upper, "Disabling feature bit %d on lower dev %s.\n", + feature_bit, lower->name); + netdev_wanted_features_clear_bit(lower, feature_bit); __netdev_update_features(lower);
- if (unlikely(netdev_active_features_intersects(lower, feature))) - netdev_WARN(upper, "failed to disable %pNF on %s!\n", - &feature, lower->name); + if (unlikely(netdev_active_features_test_bit(lower, feature_bit))) + netdev_WARN(upper, "failed to disable feature bit %d on %s!\n", + feature_bit, lower->name); else netdev_features_change(lower); } diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 01dd727299ed..d4ee659b1420 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -27,10 +27,7 @@ const struct nla_policy ethnl_features_get_policy[] = {
static void ethnl_features_to_bitmap32(u32 *dest, netdev_features_t src) { - unsigned int i; - - for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; i++) - dest[i] = src >> (32 * i); + bitmap_to_arr32(dest, src.bits, ETHTOOL_DEV_FEATURE_WORDS); }
static int features_prepare_data(const struct ethnl_req_info *req_base, @@ -45,7 +42,7 @@ static int features_prepare_data(const struct ethnl_req_info *req_base, ethnl_features_to_bitmap32(data->wanted, netdev_wanted_features(dev)); ethnl_features_to_bitmap32(data->active, netdev_active_features(dev)); ethnl_features_to_bitmap32(data->nochange, NETIF_F_NEVER_CHANGE); - all_features = GENMASK_ULL(NETDEV_FEATURE_COUNT - 1, 0); + netdev_features_fill(&all_features); ethnl_features_to_bitmap32(data->all, all_features);
return 0; @@ -137,21 +134,18 @@ static void ethnl_features_to_bitmap(unsigned long *dest, netdev_features_t val) unsigned int i;
for (i = 0; i < words; i++) - dest[i] = (unsigned long)(val >> (i * BITS_PER_LONG)); + dest[i] = val.bits[i]; }
static netdev_features_t ethnl_bitmap_to_features(unsigned long *src) { - const unsigned int nft_bits = sizeof(netdev_features_t) * BITS_PER_BYTE; const unsigned int words = BITS_TO_LONGS(NETDEV_FEATURE_COUNT); netdev_features_t ret; unsigned int i;
- netdev_features_zero(&ret); for (i = 0; i < words; i++) - netdev_features_direct_or(&ret, - (netdev_features_t)(src[i]) << (i * BITS_PER_LONG)); - ret &= ~(netdev_features_t)0 >> (nft_bits - NETDEV_FEATURE_COUNT); + ret.bits[i] = dest[i]; + return ret; }
@@ -211,18 +205,17 @@ static int features_send_reply(struct net_device *dev, struct genl_info *info,
int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) { - DECLARE_BITMAP(wanted_diff_mask, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(active_diff_mask, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(old_active, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(old_wanted, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(new_active, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(new_wanted, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(req_wanted, NETDEV_FEATURE_COUNT); - DECLARE_BITMAP(req_mask, NETDEV_FEATURE_COUNT); struct ethnl_req_info req_info = {}; struct nlattr **tb = info->attrs; + netdev_features_t wanted_diff_mask; + netdev_features_t active_diff_mask; + netdev_features_t old_active; + netdev_features_t old_wanted; + netdev_features_t new_active; + netdev_features_t new_wanted; + netdev_features_t req_wanted; + netdev_features_t req_mask; struct net_device *dev; - netdev_features_t tmp; bool mod; int ret;
@@ -237,28 +230,29 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) dev = req_info.dev;
rtnl_lock(); - ethnl_features_to_bitmap(old_active, netdev_active_features(dev)); - ethnl_features_to_bitmap(old_wanted, netdev_wanted_features(dev)); + old_active = netdev_active_features(dev); + old_wanted = netdev_wanted_features(dev); ret = ethnl_parse_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT, tb[ETHTOOL_A_FEATURES_WANTED], netdev_features_strings, info->extack); if (ret < 0) goto out_rtnl; - if (ethnl_bitmap_to_features(req_mask) & ~NETIF_F_ETHTOOL_BITS) { + if (!netdev_features_subset(NETIF_F_ETHTOOL_BITS, req_mask)) { GENL_SET_ERR_MSG(info, "attempt to change non-ethtool features"); ret = -EINVAL; goto out_rtnl; }
/* set req_wanted bits not in req_mask from old_wanted */ - bitmap_and(req_wanted, req_wanted, req_mask, NETDEV_FEATURE_COUNT); - bitmap_andnot(new_wanted, old_wanted, req_mask, NETDEV_FEATURE_COUNT); - bitmap_or(req_wanted, new_wanted, req_wanted, NETDEV_FEATURE_COUNT); - if (!bitmap_equal(req_wanted, old_wanted, NETDEV_FEATURE_COUNT)) { + netdev_features_direct_and(&req_wanted, req_mask); + new_wanted = netdev_features_andnot(old_wanted, req_mask); + netdev_features_direct_or(&req_wanted, new_wanted); + if (!netdev_features_equal(req_wanted, old_wanted)) { + netdev_features_t tmp; + netdev_wanted_features_direct_andnot(dev, netdev_hw_features(dev)); - tmp = netdev_hw_features_and(dev, - ethnl_bitmap_to_features(req_wanted)); + tmp = netdev_hw_features_and(dev, ethnl_bitmap_to_features(req_wanted));); netdev_wanted_features_direct_or(dev, tmp); __netdev_update_features(dev); } @@ -269,16 +263,11 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) if (!(req_info.flags & ETHTOOL_FLAG_OMIT_REPLY)) { bool compact = req_info.flags & ETHTOOL_FLAG_COMPACT_BITSETS;
- bitmap_xor(wanted_diff_mask, req_wanted, new_active, - NETDEV_FEATURE_COUNT); - bitmap_xor(active_diff_mask, old_active, new_active, - NETDEV_FEATURE_COUNT); - bitmap_and(wanted_diff_mask, wanted_diff_mask, req_mask, - NETDEV_FEATURE_COUNT); - bitmap_and(req_wanted, req_wanted, wanted_diff_mask, - NETDEV_FEATURE_COUNT); - bitmap_and(new_active, new_active, active_diff_mask, - NETDEV_FEATURE_COUNT); + wanted_diff_mask = netdev_features_xor(req_wanted, new_active); + active_diff_mask = netdev_features_xor(old_active, new_active); + netdev_features_direct_and(&wanted_diff_mask, req_mask); + netdev_features_direct_and(&req_wanted, wanted_diff_mask); + netdev_features_direct_and(&new_active, active_diff_mask);
ret = features_send_reply(dev, info, req_wanted, wanted_diff_mask, new_active, diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 90fb4c2a313d..460a5c12a13e 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -88,6 +88,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; @@ -95,12 +99,15 @@ static int ethtool_get_features(struct net_device *dev, void __user *useraddr) /* in case feature bits run out again */ BUILD_BUG_ON(ETHTOOL_DEV_FEATURE_WORDS * sizeof(u32) > sizeof(netdev_features_t));
+ bitmap_to_arr32(hw_arr, netdev_hw_features(dev), NETDEV_FEATURE_COUNT); + bitmap_to_arr32(wanted_arr, netdev_wanted_features(dev), NETDEV_FEATURE_COUNT); + bitmap_to_arr32(active_arr, netdev_active_features(dev), NETDEV_FEATURE_COUNT); + bitmap_to_arr32(never_changed_arr, NETIF_F_NEVER_CHANGE, NETDEV_FEATURE_COUNT); for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) { - features[i].available = (u32)(netdev_hw_features(dev) >> (32 * i)); - features[i].requested = (u32)(netdev_wanted_features(dev) >> (32 * i)); - features[i].active = (u32)(netdev_active_features(dev) >> (32 * i)); - features[i].never_changed = - (u32)(NETIF_F_NEVER_CHANGE >> (32 * i)); + features[i].available = hw_arr[i]; + features[i].requested = wanted_arr[i]; + features[i].active = active_arr[i]; + features[i].never_changed = never_changed_arr[i]; }
sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size); @@ -124,6 +131,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; @@ -139,14 +148,12 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) if (copy_from_user(features, useraddr, sizeof(features))) return -EFAULT;
- netdev_features_zero(&wanted); - netdev_features_zero(&valid); for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) { - netdev_features_direct_or(&valid, - (netdev_features_t)features[i].valid << (32 * i)); - netdev_features_direct_or(&wanted, - (netdev_features_t)features[i].requested << (32 * i)); + valid_arr[i] = features[i].valid; + wanted_arr[i] = features[i].requested; } + bitmap_from_arr32(valid.bits, valid_arr, NETDEV_FEATURE_COUNT); + bitmap_from_arr32(wanted.bits, wanted_arr, NETDEV_FEATURE_COUNT);
tmp = netdev_features_andnot(valid, NETIF_F_ETHTOOL_BITS); if (tmp) @@ -370,7 +377,7 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) changed = netdev_active_features_xor(dev, features); netdev_features_direct_and(&changed, eth_all_features); tmp = netdev_hw_features_andnot_r(dev, changed); - if (tmp) + if (!netdev_features_empty(tmp)) return netdev_hw_features_intersects(dev, changed) ? -EINVAL : -EOPNOTSUPP;
netdev_wanted_features_direct_andnot(dev, changed);