@@ -313,9 +313,11 @@ static inline bool eth_type_vlan(__be16 ethertype)
static inline bool vlan_hw_offload_capable(netdev_features_t features,
__be16 proto)
{
- if (proto == htons(ETH_P_8021Q) && features & NETIF_F_HW_VLAN_CTAG_TX)
+ if (proto == htons(ETH_P_8021Q) &&
+ netdev_feature_test_bit(NETIF_F_HW_VLAN_CTAG_TX_BIT, features))
return true;
- if (proto == htons(ETH_P_8021AD) && features & NETIF_F_HW_VLAN_STAG_TX)
+ if (proto == htons(ETH_P_8021AD) &&
+ netdev_feature_test_bit(NETIF_F_HW_VLAN_STAG_TX_BIT, features))
return true;
return false;
}
@@ -563,7 +565,8 @@ static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb,
*/
static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
{
- if (skb->dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
+ if (netdev_feature_test_bit(NETIF_F_HW_VLAN_CTAG_TX_BIT,
+ skb->dev->features)) {
return __vlan_hwaccel_get_tag(skb, vlan_tci);
} else {
return __vlan_get_tag(skb, vlan_tci);
@@ -736,9 +739,10 @@ static inline void vlan_features_check(struct sk_buff *skb,
* sure that only devices supporting NETIF_F_HW_CSUM will
* have checksum offloading support.
*/
- *features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
- NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX |
- NETIF_F_HW_VLAN_STAG_TX;
+ netdev_feature_and_bits(NETIF_F_SG | NETIF_F_HIGHDMA |
+ NETIF_F_HW_CSUM | NETIF_F_FRAGLIST |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_STAG_TX, features);
}
}
@@ -134,7 +134,8 @@ int vlan_check_real_dev(struct net_device *real_dev,
{
const char *name = real_dev->name;
- if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
+ if (netdev_feature_test_bit(NETIF_F_VLAN_CHALLENGED_BIT,
+ real_dev->features)) {
pr_info("VLANs not supported on %s\n", name);
NL_SET_ERR_MSG_MOD(extack, "VLANs not supported on device");
return -EOPNOTSUPP;
@@ -339,7 +340,7 @@ static void vlan_transfer_features(struct net_device *dev,
vlandev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
vlandev->priv_flags |= (vlan->real_dev->priv_flags & IFF_XMIT_DST_RELEASE);
- vlandev->hw_enc_features = vlan_tnl_features(vlan->real_dev);
+ vlan_tnl_features(vlan->real_dev, &vlandev->hw_enc_features);
netdev_update_features(vlandev);
}
@@ -386,13 +387,15 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
}
if ((event == NETDEV_UP) &&
- (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
+ netdev_feature_test_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+ dev->features)) {
pr_info("adding VLAN 0 to HW filter on device %s\n",
dev->name);
vlan_vid_add(dev, htons(ETH_P_8021Q), 0);
}
if (event == NETDEV_DOWN &&
- (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+ netdev_feature_test_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+ dev->features))
vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
vlan_info = rtnl_dereference(dev->vlan_info);
@@ -103,17 +103,21 @@ static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
return NULL;
}
-static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)
+static inline void vlan_tnl_features(struct net_device *real_dev,
+ netdev_features_t *tnl)
{
- netdev_features_t ret;
-
- ret = real_dev->hw_enc_features &
- (NETIF_F_CSUM_MASK | NETIF_F_GSO_SOFTWARE |
- NETIF_F_GSO_ENCAP_ALL);
-
- if ((ret & NETIF_F_GSO_ENCAP_ALL) && (ret & NETIF_F_CSUM_MASK))
- return (ret & ~NETIF_F_CSUM_MASK) | NETIF_F_HW_CSUM;
- return 0;
+ netdev_feature_zero(tnl);
+ netdev_feature_set_bits(NETIF_F_CSUM_MASK | NETIF_F_GSO_SOFTWARE |
+ NETIF_F_GSO_ENCAP_ALL, tnl);
+ netdev_feature_and(tnl, *tnl, real_dev->hw_enc_features);
+
+ if (netdev_feature_test_bits(NETIF_F_GSO_ENCAP_ALL, *tnl) &&
+ netdev_feature_test_bits(NETIF_F_CSUM_MASK, *tnl)) {
+ netdev_feature_clear_bits(NETIF_F_CSUM_MASK, tnl);
+ netdev_feature_set_bit(NETIF_F_HW_CSUM_BIT, tnl);
+ return;
+ }
+ netdev_feature_zero(tnl);
}
#define vlan_group_for_each_dev(grp, i, dev) \
@@ -169,10 +169,12 @@ struct vlan_vid_info {
static bool vlan_hw_filter_capable(const struct net_device *dev, __be16 proto)
{
if (proto == htons(ETH_P_8021Q) &&
- dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+ netdev_feature_test_bit(NETIF_F_HW_VLAN_CTAG_FILTER_BIT,
+ dev->features))
return true;
if (proto == htons(ETH_P_8021AD) &&
- dev->features & NETIF_F_HW_VLAN_STAG_FILTER)
+ netdev_feature_test_bit(NETIF_F_HW_VLAN_STAG_FILTER_BIT,
+ dev->features))
return true;
return false;
}
@@ -566,21 +566,24 @@ static int vlan_dev_init(struct net_device *dev)
if (vlan->flags & VLAN_FLAG_BRIDGE_BINDING)
dev->state |= (1 << __LINK_STATE_NOCARRIER);
- dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG |
- NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE |
- NETIF_F_GSO_ENCAP_ALL |
- NETIF_F_HIGHDMA | NETIF_F_SCTP_CRC |
- NETIF_F_ALL_FCOE;
-
- dev->features |= dev->hw_features | NETIF_F_LLTX;
+ netdev_feature_zero(&dev->hw_features);
+ netdev_feature_set_bits(NETIF_F_HW_CSUM | NETIF_F_SG |
+ NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE |
+ NETIF_F_GSO_ENCAP_ALL |
+ NETIF_F_HIGHDMA | NETIF_F_SCTP_CRC |
+ NETIF_F_ALL_FCOE, &dev->hw_features);
+
+ netdev_feature_or(&dev->features, dev->features, dev->hw_features);
+ netdev_feature_set_bit(NETIF_F_LLTX_BIT, &dev->features);
dev->gso_max_size = real_dev->gso_max_size;
dev->gso_max_segs = real_dev->gso_max_segs;
- if (dev->features & NETIF_F_VLAN_FEATURES)
+ if (netdev_feature_test_bits(NETIF_F_VLAN_FEATURES, dev->features))
netdev_warn(real_dev, "VLAN features are set incorrectly. Q-in-Q configurations may not work correctly.\n");
- dev->vlan_features = real_dev->vlan_features & ~NETIF_F_ALL_FCOE;
- dev->hw_enc_features = vlan_tnl_features(real_dev);
- dev->mpls_features = real_dev->mpls_features;
+ netdev_feature_copy(&dev->vlan_features, real_dev->vlan_features);
+ netdev_feature_clear_bits(NETIF_F_ALL_FCOE, &dev->vlan_features);
+ vlan_tnl_features(real_dev, &dev->hw_enc_features);
+ netdev_feature_copy(&dev->mpls_features, real_dev->mpls_features);
/* ipv6 shared card related stuff */
dev->dev_id = real_dev->dev_id;
@@ -637,21 +640,27 @@ static void vlan_dev_fix_features(struct net_device *dev,
netdev_features_t *features)
{
struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
- netdev_features_t old_features = *features;
netdev_features_t lower_features;
+ netdev_features_t old_features;
+ netdev_features_t tmp;
- netdev_intersect_features(&lower_features,
- (real_dev->vlan_features | NETIF_F_RXCSUM),
- real_dev->features);
+ netdev_feature_copy(&tmp, real_dev->vlan_features);
+ netdev_feature_set_bit(NETIF_F_RXCSUM_BIT, &tmp);
+ netdev_feature_copy(&old_features, *features);
+ netdev_intersect_features(&lower_features, tmp, real_dev->features);
/* Add HW_CSUM setting to preserve user ability to control
* checksum offload on the vlan device.
*/
- if (lower_features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
- lower_features |= NETIF_F_HW_CSUM;
+ if (netdev_feature_test_bits(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM,
+ lower_features))
+ netdev_feature_set_bit(NETIF_F_HW_CSUM_BIT, &lower_features);
netdev_intersect_features(features, *features, lower_features);
- *features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE);
- *features |= NETIF_F_LLTX;
+
+ netdev_feature_and_bits(NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE,
+ &old_features);
+ netdev_feature_or(features, *features, old_features);
+ netdev_feature_set_bit(NETIF_F_LLTX_BIT, features);
}
static int vlan_ethtool_get_link_ksettings(struct net_device *dev,
Use netdev_feature_xxx helpers to replace the logical operation for netdev features. Signed-off-by: Jian Shen <shenjian15@huawei.com> --- include/linux/if_vlan.h | 16 ++++++++------ net/8021q/vlan.c | 11 ++++++---- net/8021q/vlan.h | 24 ++++++++++++--------- net/8021q/vlan_core.c | 6 ++++-- net/8021q/vlan_dev.c | 47 ++++++++++++++++++++++++----------------- 5 files changed, 63 insertions(+), 41 deletions(-)