]> err.no Git - linux-2.6/blobdiff - net/core/dev.c
Merge branch 'agp-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[linux-2.6] / net / core / dev.c
index ed49da592051f368cf32b3bafd59bd05494c3c67..68d8df0992abfd425c517fc8b9df3d6a40fe71ff 100644 (file)
 #include <linux/err.h>
 #include <linux/ctype.h>
 #include <linux/if_arp.h>
+#include <linux/if_vlan.h>
 
 #include "net-sysfs.h"
 
@@ -162,7 +163,7 @@ struct net_dma {
        struct dma_client client;
        spinlock_t lock;
        cpumask_t channel_mask;
-       struct dma_chan *channels[NR_CPUS];
+       struct dma_chan **channels;
 };
 
 static enum dma_state_client
@@ -903,7 +904,11 @@ int dev_change_name(struct net_device *dev, char *newname)
                strlcpy(dev->name, newname, IFNAMSIZ);
 
 rollback:
-       device_rename(&dev->dev, dev->name);
+       err = device_rename(&dev->dev, dev->name);
+       if (err) {
+               memcpy(dev->name, oldname, IFNAMSIZ);
+               return err;
+       }
 
        write_lock_bh(&dev_base_lock);
        hlist_del(&dev->name_hlist);
@@ -994,6 +999,8 @@ int dev_open(struct net_device *dev)
 {
        int ret = 0;
 
+       ASSERT_RTNL();
+
        /*
         *      Is it already up?
         */
@@ -1060,6 +1067,8 @@ int dev_open(struct net_device *dev)
  */
 int dev_close(struct net_device *dev)
 {
+       ASSERT_RTNL();
+
        might_sleep();
 
        if (!(dev->flags & IFF_UP))
@@ -1354,6 +1363,29 @@ void netif_device_attach(struct net_device *dev)
 }
 EXPORT_SYMBOL(netif_device_attach);
 
+static bool can_checksum_protocol(unsigned long features, __be16 protocol)
+{
+       return ((features & NETIF_F_GEN_CSUM) ||
+               ((features & NETIF_F_IP_CSUM) &&
+                protocol == htons(ETH_P_IP)) ||
+               ((features & NETIF_F_IPV6_CSUM) &&
+                protocol == htons(ETH_P_IPV6)));
+}
+
+static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
+{
+       if (can_checksum_protocol(dev->features, skb->protocol))
+               return true;
+
+       if (skb->protocol == htons(ETH_P_8021Q)) {
+               struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
+               if (can_checksum_protocol(dev->features & dev->vlan_features,
+                                         veh->h_vlan_encapsulated_proto))
+                       return true;
+       }
+
+       return false;
+}
 
 /*
  * Invalidate hardware checksum when packet is to be mangled, and
@@ -1632,14 +1664,8 @@ int dev_queue_xmit(struct sk_buff *skb)
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                skb_set_transport_header(skb, skb->csum_start -
                                              skb_headroom(skb));
-
-               if (!(dev->features & NETIF_F_GEN_CSUM) &&
-                   !((dev->features & NETIF_F_IP_CSUM) &&
-                     skb->protocol == htons(ETH_P_IP)) &&
-                   !((dev->features & NETIF_F_IPV6_CSUM) &&
-                     skb->protocol == htons(ETH_P_IPV6)))
-                       if (skb_checksum_help(skb))
-                               goto out_kfree_skb;
+               if (!dev_can_checksum(dev, skb) && skb_checksum_help(skb))
+                       goto out_kfree_skb;
        }
 
 gso:
@@ -2444,7 +2470,7 @@ static struct netif_rx_stats *softnet_get_online(loff_t *pos)
 {
        struct netif_rx_stats *rc = NULL;
 
-       while (*pos < NR_CPUS)
+       while (*pos < nr_cpu_ids)
                if (cpu_online(*pos)) {
                        rc = &per_cpu(netdev_rx_stat, *pos);
                        break;
@@ -3133,7 +3159,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
         *      Load in the correct multicast list now the flags have changed.
         */
 
-       if (dev->change_rx_flags && (dev->flags ^ flags) & IFF_MULTICAST)
+       if (dev->change_rx_flags && (old_flags ^ flags) & IFF_MULTICAST)
                dev->change_rx_flags(dev, IFF_MULTICAST);
 
        dev_set_rx_mode(dev);
@@ -3776,6 +3802,7 @@ int register_netdevice(struct net_device *dev)
                }
        }
 
+       netdev_initialize_kobject(dev);
        ret = netdev_register_kobject(dev);
        if (ret)
                goto err_uninit;
@@ -4208,7 +4235,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
        }
 
        /* Fixup kobjects */
-       err = device_rename(&dev->dev, dev->name);
+       netdev_unregister_kobject(dev);
+       err = netdev_register_kobject(dev);
        WARN_ON(err);
 
        /* Add the device back in the hashes */
@@ -4324,7 +4352,7 @@ netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
        spin_lock(&net_dma->lock);
        switch (state) {
        case DMA_RESOURCE_AVAILABLE:
-               for (i = 0; i < NR_CPUS; i++)
+               for (i = 0; i < nr_cpu_ids; i++)
                        if (net_dma->channels[i] == chan) {
                                found = 1;
                                break;
@@ -4339,7 +4367,7 @@ netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
                }
                break;
        case DMA_RESOURCE_REMOVED:
-               for (i = 0; i < NR_CPUS; i++)
+               for (i = 0; i < nr_cpu_ids; i++)
                        if (net_dma->channels[i] == chan) {
                                found = 1;
                                pos = i;
@@ -4366,6 +4394,13 @@ netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
  */
 static int __init netdev_dma_register(void)
 {
+       net_dma.channels = kzalloc(nr_cpu_ids * sizeof(struct net_dma),
+                                                               GFP_KERNEL);
+       if (unlikely(!net_dma.channels)) {
+               printk(KERN_NOTICE
+                               "netdev_dma: no memory for net_dma.channels\n");
+               return -ENOMEM;
+       }
        spin_lock_init(&net_dma.lock);
        dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask);
        dma_async_client_register(&net_dma.client);
@@ -4471,17 +4506,19 @@ static void __net_exit default_device_exit(struct net *net)
        rtnl_lock();
        for_each_netdev_safe(net, dev, next) {
                int err;
+               char fb_name[IFNAMSIZ];
 
                /* Ignore unmoveable devices (i.e. loopback) */
                if (dev->features & NETIF_F_NETNS_LOCAL)
                        continue;
 
                /* Push remaing network devices to init_net */
-               err = dev_change_net_namespace(dev, &init_net, "dev%d");
+               snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex);
+               err = dev_change_net_namespace(dev, &init_net, fb_name);
                if (err) {
-                       printk(KERN_WARNING "%s: failed to move %s to init_net: %d\n",
+                       printk(KERN_EMERG "%s: failed to move %s to init_net: %d\n",
                                __func__, dev->name, err);
-                       unregister_netdevice(dev);
+                       BUG();
                }
        }
        rtnl_unlock();