diff options
Diffstat (limited to 'drivers/net/loopback.c')
| -rw-r--r-- | drivers/net/loopback.c | 36 | 
1 files changed, 22 insertions, 14 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 2d9663a1c54..bb96409f8c0 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -39,9 +39,7 @@  #include <linux/errno.h>  #include <linux/fcntl.h>  #include <linux/in.h> -#include <linux/init.h> -#include <asm/system.h>  #include <asm/uaccess.h>  #include <asm/io.h> @@ -78,6 +76,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,  	skb_orphan(skb); +	/* Before queueing this packet to netif_rx(), +	 * make sure dst is refcounted. +	 */ +	skb_dst_force(skb); +  	skb->protocol = eth_type_trans(skb, dev);  	/* it's OK to use per_cpu_ptr() because BHs are off */ @@ -108,10 +111,10 @@ static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev,  		lb_stats = per_cpu_ptr(dev->lstats, i);  		do { -			start = u64_stats_fetch_begin(&lb_stats->syncp); +			start = u64_stats_fetch_begin_irq(&lb_stats->syncp);  			tbytes = lb_stats->bytes;  			tpackets = lb_stats->packets; -		} while (u64_stats_fetch_retry(&lb_stats->syncp, start)); +		} while (u64_stats_fetch_retry_irq(&lb_stats->syncp, start));  		bytes   += tbytes;  		packets += tpackets;  	} @@ -129,23 +132,19 @@ static u32 always_on(struct net_device *dev)  static const struct ethtool_ops loopback_ethtool_ops = {  	.get_link		= always_on, -	.set_tso		= ethtool_op_set_tso, -	.get_tx_csum		= always_on, -	.get_sg			= always_on, -	.get_rx_csum		= always_on,  };  static int loopback_dev_init(struct net_device *dev)  { -	dev->lstats = alloc_percpu(struct pcpu_lstats); +	dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);  	if (!dev->lstats)  		return -ENOMEM; -  	return 0;  }  static void loopback_dev_free(struct net_device *dev)  { +	dev_net(dev)->loopback_dev = NULL;  	free_percpu(dev->lstats);  	free_netdev(dev);  } @@ -154,6 +153,7 @@ static const struct net_device_ops loopback_ops = {  	.ndo_init      = loopback_dev_init,  	.ndo_start_xmit= loopback_xmit,  	.ndo_get_stats64 = loopback_get_stats64, +	.ndo_set_mac_address = eth_mac_addr,  };  /* @@ -162,19 +162,26 @@ static const struct net_device_ops loopback_ops = {   */  static void loopback_setup(struct net_device *dev)  { -	dev->mtu		= (16 * 1024) + 20 + 20 + 12; +	dev->mtu		= 64 * 1024;  	dev->hard_header_len	= ETH_HLEN;	/* 14	*/  	dev->addr_len		= ETH_ALEN;	/* 6	*/  	dev->tx_queue_len	= 0;  	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001*/  	dev->flags		= IFF_LOOPBACK; +	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;  	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE; +	dev->hw_features	= NETIF_F_ALL_TSO | NETIF_F_UFO;  	dev->features 		= NETIF_F_SG | NETIF_F_FRAGLIST -		| NETIF_F_TSO -		| NETIF_F_NO_CSUM +		| NETIF_F_ALL_TSO +		| NETIF_F_UFO +		| NETIF_F_HW_CSUM +		| NETIF_F_RXCSUM +		| NETIF_F_SCTP_CSUM  		| NETIF_F_HIGHDMA  		| NETIF_F_LLTX -		| NETIF_F_NETNS_LOCAL; +		| NETIF_F_NETNS_LOCAL +		| NETIF_F_VLAN_CHALLENGED +		| NETIF_F_LOOPBACK;  	dev->ethtool_ops	= &loopback_ethtool_ops;  	dev->header_ops		= ð_header_ops;  	dev->netdev_ops		= &loopback_ops; @@ -197,6 +204,7 @@ static __net_init int loopback_net_init(struct net *net)  	if (err)  		goto out_free_netdev; +	BUG_ON(dev->ifindex != LOOPBACK_IFINDEX);  	net->loopback_dev = dev;  	return 0;  | 
