diff options
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/dev.c | 22 | ||||
| -rw-r--r-- | net/core/flow_dissector.c | 20 | ||||
| -rw-r--r-- | net/core/rtnetlink.c | 19 | 
3 files changed, 28 insertions, 33 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 4ad1b78c9c7..b1b0c8d4d7d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2420,7 +2420,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault);   * 2. No high memory really exists on this machine.   */ -static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) +static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb)  {  #ifdef CONFIG_HIGHMEM  	int i; @@ -2495,34 +2495,36 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features)  }  static netdev_features_t harmonize_features(struct sk_buff *skb, -	netdev_features_t features) +					    const struct net_device *dev, +					    netdev_features_t features)  {  	if (skb->ip_summed != CHECKSUM_NONE &&  	    !can_checksum_protocol(features, skb_network_protocol(skb))) {  		features &= ~NETIF_F_ALL_CSUM; -	} else if (illegal_highdma(skb->dev, skb)) { +	} else if (illegal_highdma(dev, skb)) {  		features &= ~NETIF_F_SG;  	}  	return features;  } -netdev_features_t netif_skb_features(struct sk_buff *skb) +netdev_features_t netif_skb_dev_features(struct sk_buff *skb, +					 const struct net_device *dev)  {  	__be16 protocol = skb->protocol; -	netdev_features_t features = skb->dev->features; +	netdev_features_t features = dev->features; -	if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) +	if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs)  		features &= ~NETIF_F_GSO_MASK;  	if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) {  		struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;  		protocol = veh->h_vlan_encapsulated_proto;  	} else if (!vlan_tx_tag_present(skb)) { -		return harmonize_features(skb, features); +		return harmonize_features(skb, dev, features);  	} -	features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | +	features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |  					       NETIF_F_HW_VLAN_STAG_TX);  	if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) @@ -2530,9 +2532,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)  				NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX |  				NETIF_F_HW_VLAN_STAG_TX; -	return harmonize_features(skb, features); +	return harmonize_features(skb, dev, features);  } -EXPORT_SYMBOL(netif_skb_features); +EXPORT_SYMBOL(netif_skb_dev_features);  int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,  			struct netdev_queue *txq) diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 87577d44755..e29e810663d 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -323,17 +323,6 @@ u32 __skb_get_poff(const struct sk_buff *skb)  	return poff;  } -static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index) -{ -	if (unlikely(queue_index >= dev->real_num_tx_queues)) { -		net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n", -				     dev->name, queue_index, -				     dev->real_num_tx_queues); -		return 0; -	} -	return queue_index; -} -  static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)  {  #ifdef CONFIG_XPS @@ -372,7 +361,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)  #endif  } -u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) +static u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)  {  	struct sock *sk = skb->sk;  	int queue_index = sk_tx_queue_get(sk); @@ -392,7 +381,6 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)  	return queue_index;  } -EXPORT_SYMBOL(__netdev_pick_tx);  struct netdev_queue *netdev_pick_tx(struct net_device *dev,  				    struct sk_buff *skb, @@ -403,13 +391,13 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev,  	if (dev->real_num_tx_queues != 1) {  		const struct net_device_ops *ops = dev->netdev_ops;  		if (ops->ndo_select_queue) -			queue_index = ops->ndo_select_queue(dev, skb, -							    accel_priv); +			queue_index = ops->ndo_select_queue(dev, skb, accel_priv, +							    __netdev_pick_tx);  		else  			queue_index = __netdev_pick_tx(dev, skb);  		if (!accel_priv) -			queue_index = dev_cap_txqueue(dev, queue_index); +			queue_index = netdev_cap_txqueue(dev, queue_index);  	}  	skb_set_queue_mapping(skb, queue_index); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 048dc8d183a..1a0dac2ef9a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1963,16 +1963,21 @@ replay:  		dev->ifindex = ifm->ifi_index; -		if (ops->newlink) +		if (ops->newlink) {  			err = ops->newlink(net, dev, tb, data); -		else +			/* Drivers should call free_netdev() in ->destructor +			 * and unregister it on failure so that device could be +			 * finally freed in rtnl_unlock. +			 */ +			if (err < 0) +				goto out; +		} else {  			err = register_netdevice(dev); - -		if (err < 0) { -			free_netdev(dev); -			goto out; +			if (err < 0) { +				free_netdev(dev); +				goto out; +			}  		} -  		err = rtnl_configure_link(dev, ifm);  		if (err < 0)  			unregister_netdevice(dev);  | 
