X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Floopback.c;h=b33111e2131310e1d6b891772bcca697b2be2435;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=1885bfe3c9592fd10310f8b98b1d78492804a797;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 1885bfe3c..b33111e21 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -7,7 +7,7 @@ * * Version: @(#)loopback.c 1.0.4b 08/16/93 * - * Authors: Ross Biro, + * Authors: Ross Biro * Fred N. van Kempen, * Donald Becker, * @@ -49,13 +49,16 @@ #include #include #include +#include #include #include #include /* For the statistics structure. */ #include /* For ARPHRD_ETHER */ #include #include +#include +static DEFINE_PER_CPU(struct net_device_stats, loopback_stats); #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) @@ -123,7 +126,7 @@ static void emulate_large_send_offload(struct sk_buff *skb) */ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = dev->priv; + struct net_device_stats *lb_stats; skb_orphan(skb); @@ -142,12 +145,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) } dev->last_rx = jiffies; - if (likely(stats)) { - stats->rx_bytes+=skb->len; - stats->tx_bytes+=skb->len; - stats->rx_packets++; - stats->tx_packets++; - } + + lb_stats = &per_cpu(loopback_stats, get_cpu()); + lb_stats->rx_bytes += skb->len; + lb_stats->tx_bytes += skb->len; + lb_stats->rx_packets++; + lb_stats->tx_packets++; + put_cpu(); netif_rx(skb); @@ -156,9 +160,41 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) static struct net_device_stats *get_stats(struct net_device *dev) { - return (struct net_device_stats *)dev->priv; + struct net_device_stats *stats = dev->priv; + int i; + + if (!stats) { + return NULL; + } + + memset(stats, 0, sizeof(struct net_device_stats)); + + for (i=0; i < NR_CPUS; i++) { + struct net_device_stats *lb_stats; + + if (!cpu_possible(i)) + continue; + lb_stats = &per_cpu(loopback_stats, i); + stats->rx_bytes += lb_stats->rx_bytes; + stats->tx_bytes += lb_stats->tx_bytes; + stats->rx_packets += lb_stats->rx_packets; + stats->tx_packets += lb_stats->tx_packets; + } + + return stats; } +static u32 loopback_get_link(struct net_device *dev) +{ + return 1; +} + +static struct ethtool_ops loopback_ethtool_ops = { + .get_link = loopback_get_link, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, +}; + struct net_device loopback_dev = { .name = "lo", .mtu = (16 * 1024) + 20 + 20 + 12, @@ -173,7 +209,9 @@ struct net_device loopback_dev = { .rebuild_header = eth_rebuild_header, .flags = IFF_LOOPBACK, .features = NETIF_F_SG|NETIF_F_FRAGLIST - |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA, + |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA + |NETIF_F_LLTX, + .ethtool_ops = &loopback_ethtool_ops, }; /* Setup and register the of the LOOPBACK device. */