@@ -3947,6 +3947,46 @@ static void netdev_init_queue_locks(struct net_device *dev)
3947
3947
__netdev_init_queue_locks_one (dev , & dev -> rx_queue , NULL );
3948
3948
}
3949
3949
3950
+ unsigned long netdev_fix_features (unsigned long features , const char * name )
3951
+ {
3952
+ /* Fix illegal SG+CSUM combinations. */
3953
+ if ((features & NETIF_F_SG ) &&
3954
+ !(features & NETIF_F_ALL_CSUM )) {
3955
+ if (name )
3956
+ printk (KERN_NOTICE "%s: Dropping NETIF_F_SG since no "
3957
+ "checksum feature.\n" , name );
3958
+ features &= ~NETIF_F_SG ;
3959
+ }
3960
+
3961
+ /* TSO requires that SG is present as well. */
3962
+ if ((features & NETIF_F_TSO ) && !(features & NETIF_F_SG )) {
3963
+ if (name )
3964
+ printk (KERN_NOTICE "%s: Dropping NETIF_F_TSO since no "
3965
+ "SG feature.\n" , name );
3966
+ features &= ~NETIF_F_TSO ;
3967
+ }
3968
+
3969
+ if (features & NETIF_F_UFO ) {
3970
+ if (!(features & NETIF_F_GEN_CSUM )) {
3971
+ if (name )
3972
+ printk (KERN_ERR "%s: Dropping NETIF_F_UFO "
3973
+ "since no NETIF_F_HW_CSUM feature.\n" ,
3974
+ name );
3975
+ features &= ~NETIF_F_UFO ;
3976
+ }
3977
+
3978
+ if (!(features & NETIF_F_SG )) {
3979
+ if (name )
3980
+ printk (KERN_ERR "%s: Dropping NETIF_F_UFO "
3981
+ "since no NETIF_F_SG feature.\n" , name );
3982
+ features &= ~NETIF_F_UFO ;
3983
+ }
3984
+ }
3985
+
3986
+ return features ;
3987
+ }
3988
+ EXPORT_SYMBOL (netdev_fix_features );
3989
+
3950
3990
/**
3951
3991
* register_netdevice - register a network device
3952
3992
* @dev: device to register
@@ -4032,36 +4072,7 @@ int register_netdevice(struct net_device *dev)
4032
4072
dev -> features &= ~(NETIF_F_IP_CSUM |NETIF_F_IPV6_CSUM |NETIF_F_HW_CSUM );
4033
4073
}
4034
4074
4035
-
4036
- /* Fix illegal SG+CSUM combinations. */
4037
- if ((dev -> features & NETIF_F_SG ) &&
4038
- !(dev -> features & NETIF_F_ALL_CSUM )) {
4039
- printk (KERN_NOTICE "%s: Dropping NETIF_F_SG since no checksum feature.\n" ,
4040
- dev -> name );
4041
- dev -> features &= ~NETIF_F_SG ;
4042
- }
4043
-
4044
- /* TSO requires that SG is present as well. */
4045
- if ((dev -> features & NETIF_F_TSO ) &&
4046
- !(dev -> features & NETIF_F_SG )) {
4047
- printk (KERN_NOTICE "%s: Dropping NETIF_F_TSO since no SG feature.\n" ,
4048
- dev -> name );
4049
- dev -> features &= ~NETIF_F_TSO ;
4050
- }
4051
- if (dev -> features & NETIF_F_UFO ) {
4052
- if (!(dev -> features & NETIF_F_HW_CSUM )) {
4053
- printk (KERN_ERR "%s: Dropping NETIF_F_UFO since no "
4054
- "NETIF_F_HW_CSUM feature.\n" ,
4055
- dev -> name );
4056
- dev -> features &= ~NETIF_F_UFO ;
4057
- }
4058
- if (!(dev -> features & NETIF_F_SG )) {
4059
- printk (KERN_ERR "%s: Dropping NETIF_F_UFO since no "
4060
- "NETIF_F_SG feature.\n" ,
4061
- dev -> name );
4062
- dev -> features &= ~NETIF_F_UFO ;
4063
- }
4064
- }
4075
+ dev -> features = netdev_fix_features (dev -> features , dev -> name );
4065
4076
4066
4077
/* Enable software GSO if SG is supported. */
4067
4078
if (dev -> features & NETIF_F_SG )
@@ -4700,49 +4711,45 @@ static int __init netdev_dma_register(void) { return -ENODEV; }
4700
4711
#endif /* CONFIG_NET_DMA */
4701
4712
4702
4713
/**
4703
- * netdev_compute_feature - compute conjunction of two feature sets
4704
- * @all: first feature set
4705
- * @one: second feature set
4714
+ * netdev_increment_features - increment feature set by one
4715
+ * @all: current feature set
4716
+ * @one: new feature set
4717
+ * @mask: mask feature set
4706
4718
*
4707
4719
* Computes a new feature set after adding a device with feature set
4708
- * @one to the master device with current feature set @all. Returns
4709
- * the new feature set.
4720
+ * @one to the master device with current feature set @all. Will not
4721
+ * enable anything that is off in @mask. Returns the new feature set.
4710
4722
*/
4711
- int netdev_compute_features (unsigned long all , unsigned long one )
4712
- {
4713
- /* if device needs checksumming, downgrade to hw checksumming */
4714
- if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM ))
4715
- all ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM ;
4716
-
4717
- /* if device can't do all checksum, downgrade to ipv4/ipv6 */
4718
- if (all & NETIF_F_HW_CSUM && !(one & NETIF_F_HW_CSUM ))
4719
- all ^= NETIF_F_HW_CSUM
4720
- | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM ;
4721
-
4722
- if (one & NETIF_F_GSO )
4723
- one |= NETIF_F_GSO_SOFTWARE ;
4724
- one |= NETIF_F_GSO ;
4725
-
4726
- /*
4727
- * If even one device supports a GSO protocol with software fallback,
4728
- * enable it for all.
4729
- */
4730
- all |= one & NETIF_F_GSO_SOFTWARE ;
4723
+ unsigned long netdev_increment_features (unsigned long all , unsigned long one ,
4724
+ unsigned long mask )
4725
+ {
4726
+ /* If device needs checksumming, downgrade to it. */
4727
+ if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM ))
4728
+ all ^= NETIF_F_NO_CSUM | (one & NETIF_F_ALL_CSUM );
4729
+ else if (mask & NETIF_F_ALL_CSUM ) {
4730
+ /* If one device supports v4/v6 checksumming, set for all. */
4731
+ if (one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM ) &&
4732
+ !(all & NETIF_F_GEN_CSUM )) {
4733
+ all &= ~NETIF_F_ALL_CSUM ;
4734
+ all |= one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM );
4735
+ }
4731
4736
4732
- /* If even one device supports robust GSO, enable it for all. */
4733
- if (one & NETIF_F_GSO_ROBUST )
4734
- all |= NETIF_F_GSO_ROBUST ;
4737
+ /* If one device supports hw checksumming, set for all. */
4738
+ if (one & NETIF_F_GEN_CSUM && !(all & NETIF_F_GEN_CSUM )) {
4739
+ all &= ~NETIF_F_ALL_CSUM ;
4740
+ all |= NETIF_F_HW_CSUM ;
4741
+ }
4742
+ }
4735
4743
4736
- all &= one | NETIF_F_LLTX ;
4744
+ one |= NETIF_F_ALL_CSUM ;
4737
4745
4738
- if (!(all & NETIF_F_ALL_CSUM ))
4739
- all &= ~NETIF_F_SG ;
4740
- if (!(all & NETIF_F_SG ))
4741
- all &= ~NETIF_F_GSO_MASK ;
4746
+ one |= all & NETIF_F_ONE_FOR_ALL ;
4747
+ all &= one | NETIF_F_LLTX | NETIF_F_GSO ;
4748
+ all |= one & mask & NETIF_F_ONE_FOR_ALL ;
4742
4749
4743
4750
return all ;
4744
4751
}
4745
- EXPORT_SYMBOL (netdev_compute_features );
4752
+ EXPORT_SYMBOL (netdev_increment_features );
4746
4753
4747
4754
static struct hlist_head * netdev_create_hash (void )
4748
4755
{
0 commit comments