]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/core/dev.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / net / core / dev.c
index 1aa07047826e275110743a5a5b4d7feb09692416..be6cedab5aa83cc3d5551e89ef66d5597dfccbf0 100644 (file)
 #include <linux/ctype.h>
 #include <linux/if_arp.h>
 
+#include "net-sysfs.h"
+
 /*
  *     The list of packet types we will receive (as opposed to discard)
  *     and the routines to invoke.
@@ -249,10 +251,6 @@ static RAW_NOTIFIER_HEAD(netdev_chain);
 
 DEFINE_PER_CPU(struct softnet_data, softnet_data);
 
-extern int netdev_kobject_init(void);
-extern int netdev_register_kobject(struct net_device *);
-extern void netdev_unregister_kobject(struct net_device *);
-
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 /*
  * register_netdevice() inits dev->_xmit_lock and sets lockdep class
@@ -557,6 +555,7 @@ __setup("netdev=", netdev_boot_setup);
 
 /**
  *     __dev_get_by_name       - find a device by its name
+ *     @net: the applicable net namespace
  *     @name: name to find
  *
  *     Find an interface by name. Must be called under RTNL semaphore
@@ -581,6 +580,7 @@ struct net_device *__dev_get_by_name(struct net *net, const char *name)
 
 /**
  *     dev_get_by_name         - find a device by its name
+ *     @net: the applicable net namespace
  *     @name: name to find
  *
  *     Find an interface by name. This can be called from any
@@ -604,6 +604,7 @@ struct net_device *dev_get_by_name(struct net *net, const char *name)
 
 /**
  *     __dev_get_by_index - find a device by its ifindex
+ *     @net: the applicable net namespace
  *     @ifindex: index of device
  *
  *     Search for an interface by index. Returns %NULL if the device
@@ -629,6 +630,7 @@ struct net_device *__dev_get_by_index(struct net *net, int ifindex)
 
 /**
  *     dev_get_by_index - find a device by its ifindex
+ *     @net: the applicable net namespace
  *     @ifindex: index of device
  *
  *     Search for an interface by index. Returns NULL if the device
@@ -651,6 +653,7 @@ struct net_device *dev_get_by_index(struct net *net, int ifindex)
 
 /**
  *     dev_getbyhwaddr - find a device by its hardware address
+ *     @net: the applicable net namespace
  *     @type: media type of device
  *     @ha: hardware address
  *
@@ -709,6 +712,7 @@ EXPORT_SYMBOL(dev_getfirstbyhwtype);
 
 /**
  *     dev_get_by_flags - find any device with given flags
+ *     @net: the applicable net namespace
  *     @if_flags: IFF_* values
  *     @mask: bitmask of bits in if_flags to check
  *
@@ -879,6 +883,9 @@ int dev_change_name(struct net_device *dev, char *newname)
        if (!dev_valid_name(newname))
                return -EINVAL;
 
+       if (strncmp(newname, dev->name, IFNAMSIZ) == 0)
+               return 0;
+
        memcpy(oldname, dev->name, IFNAMSIZ);
 
        if (strchr(newname, '%')) {
@@ -948,6 +955,7 @@ void netdev_state_change(struct net_device *dev)
 
 /**
  *     dev_load        - load a network module
+ *     @net: the applicable net namespace
  *     @name: name of interface
  *
  *     If a network interface is not present and the process has suitable
@@ -1000,17 +1008,20 @@ int dev_open(struct net_device *dev)
         *      Call device private open method
         */
        set_bit(__LINK_STATE_START, &dev->state);
-       if (dev->open) {
+
+       if (dev->validate_addr)
+               ret = dev->validate_addr(dev);
+
+       if (!ret && dev->open)
                ret = dev->open(dev);
-               if (ret)
-                       clear_bit(__LINK_STATE_START, &dev->state);
-       }
 
        /*
         *      If it went open OK then:
         */
 
-       if (!ret) {
+       if (ret)
+               clear_bit(__LINK_STATE_START, &dev->state);
+       else {
                /*
                 *      Set the flags.
                 */
@@ -1031,6 +1042,7 @@ int dev_open(struct net_device *dev)
                 */
                call_netdevice_notifiers(NETDEV_UP, dev);
        }
+
        return ret;
 }
 
@@ -1185,7 +1197,7 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
 /**
  *     call_netdevice_notifiers - call all network notifier blocks
  *      @val: value passed unmodified to notifier function
- *      @v:   pointer passed unmodified to notifier function
+ *      @dev: net_device pointer passed unmodified to notifier function
  *
  *     Call all network notifier blocks.  Parameters and return value
  *     are as for raw_notifier_call_chain().
@@ -1355,22 +1367,21 @@ int skb_checksum_help(struct sk_buff *skb)
                goto out_set_summed;
        }
 
-       if (skb_cloned(skb)) {
+       offset = skb->csum_start - skb_headroom(skb);
+       BUG_ON(offset >= skb_headlen(skb));
+       csum = skb_checksum(skb, offset, skb->len - offset, 0);
+
+       offset += skb->csum_offset;
+       BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb));
+
+       if (skb_cloned(skb) &&
+           !skb_clone_writable(skb, offset + sizeof(__sum16))) {
                ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
                if (ret)
                        goto out;
        }
 
-       offset = skb->csum_start - skb_headroom(skb);
-       BUG_ON(offset > (int)skb->len);
-       csum = skb_checksum(skb, offset, skb->len-offset, 0);
-
-       offset = skb_headlen(skb) - offset;
-       BUG_ON(offset <= 0);
-       BUG_ON(skb->csum_offset + 2 > offset);
-
-       *(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) =
-               csum_fold(csum);
+       *(__sum16 *)(skb->data + offset) = csum_fold(csum);
 out_set_summed:
        skb->ip_summed = CHECKSUM_NONE;
 out:
@@ -1547,7 +1558,7 @@ gso:
                        return rc;
                }
                if (unlikely((netif_queue_stopped(dev) ||
-                            netif_subqueue_stopped(dev, skb->queue_mapping)) &&
+                            netif_subqueue_stopped(dev, skb)) &&
                             skb->next))
                        return NETDEV_TX_BUSY;
        } while (skb->next);
@@ -1655,7 +1666,7 @@ gso:
                q = dev->qdisc;
                if (q->enqueue) {
                        /* reset queue_mapping to zero */
-                       skb->queue_mapping = 0;
+                       skb_set_queue_mapping(skb, 0);
                        rc = q->enqueue(skb, q);
                        qdisc_run(dev);
                        spin_unlock(&dev->queue_lock);
@@ -1686,7 +1697,7 @@ gso:
                        HARD_TX_LOCK(dev, cpu);
 
                        if (!netif_queue_stopped(dev) &&
-                           !netif_subqueue_stopped(dev, skb->queue_mapping)) {
+                           !netif_subqueue_stopped(dev, skb)) {
                                rc = 0;
                                if (!dev_hard_start_xmit(skb, dev)) {
                                        HARD_TX_UNLOCK(dev);
@@ -1740,9 +1751,6 @@ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
  *
  *     return values:
  *     NET_RX_SUCCESS  (no congestion)
- *     NET_RX_CN_LOW   (low congestion)
- *     NET_RX_CN_MOD   (moderate congestion)
- *     NET_RX_CN_HIGH  (high congestion)
  *     NET_RX_DROP     (packet was dropped)
  *
  */
@@ -1942,30 +1950,69 @@ static int ing_filter(struct sk_buff *skb)
        struct Qdisc *q;
        struct net_device *dev = skb->dev;
        int result = TC_ACT_OK;
+       u32 ttl = G_TC_RTTL(skb->tc_verd);
 
-       if (dev->qdisc_ingress) {
-               __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
-               if (MAX_RED_LOOP < ttl++) {
-                       printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n",
-                               skb->iif, skb->dev->ifindex);
-                       return TC_ACT_SHOT;
-               }
+       if (MAX_RED_LOOP < ttl++) {
+               printk(KERN_WARNING
+                      "Redir loop detected Dropping packet (%d->%d)\n",
+                      skb->iif, dev->ifindex);
+               return TC_ACT_SHOT;
+       }
 
-               skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl);
+       skb->tc_verd = SET_TC_RTTL(skb->tc_verd, ttl);
+       skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS);
 
-               skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
+       spin_lock(&dev->ingress_lock);
+       if ((q = dev->qdisc_ingress) != NULL)
+               result = q->enqueue(skb, q);
+       spin_unlock(&dev->ingress_lock);
 
-               spin_lock(&dev->ingress_lock);
-               if ((q = dev->qdisc_ingress) != NULL)
-                       result = q->enqueue(skb, q);
-               spin_unlock(&dev->ingress_lock);
+       return result;
+}
 
+static inline struct sk_buff *handle_ing(struct sk_buff *skb,
+                                        struct packet_type **pt_prev,
+                                        int *ret, struct net_device *orig_dev)
+{
+       if (!skb->dev->qdisc_ingress)
+               goto out;
+
+       if (*pt_prev) {
+               *ret = deliver_skb(skb, *pt_prev, orig_dev);
+               *pt_prev = NULL;
+       } else {
+               /* Huh? Why does turning on AF_PACKET affect this? */
+               skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
        }
 
-       return result;
+       switch (ing_filter(skb)) {
+       case TC_ACT_SHOT:
+       case TC_ACT_STOLEN:
+               kfree_skb(skb);
+               return NULL;
+       }
+
+out:
+       skb->tc_verd = 0;
+       return skb;
 }
 #endif
 
+/**
+ *     netif_receive_skb - process receive buffer from network
+ *     @skb: buffer to process
+ *
+ *     netif_receive_skb() is the main receive data processing function.
+ *     It always succeeds. The buffer may be dropped during processing
+ *     for congestion control or by the protocol layers.
+ *
+ *     This function may only be called from softirq context and interrupts
+ *     should be enabled.
+ *
+ *     Return values (usually ignored):
+ *     NET_RX_SUCCESS: no congestion
+ *     NET_RX_DROP: packet was dropped
+ */
 int netif_receive_skb(struct sk_buff *skb)
 {
        struct packet_type *ptype, *pt_prev;
@@ -2014,21 +2061,9 @@ int netif_receive_skb(struct sk_buff *skb)
        }
 
 #ifdef CONFIG_NET_CLS_ACT
-       if (pt_prev) {
-               ret = deliver_skb(skb, pt_prev, orig_dev);
-               pt_prev = NULL; /* noone else should process this after*/
-       } else {
-               skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
-       }
-
-       ret = ing_filter(skb);
-
-       if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) {
-               kfree_skb(skb);
+       skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
+       if (!skb)
                goto out;
-       }
-
-       skb->tc_verd = 0;
 ncls:
 #endif
 
@@ -2097,7 +2132,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
 
 /**
  * __napi_schedule - schedule for receive
- * @napi: entry to schedule
+ * @n: entry to schedule
  *
  * The entry's receive function will be scheduled to run
  */
@@ -2149,7 +2184,15 @@ static void net_rx_action(struct softirq_action *h)
 
                weight = n->weight;
 
-               work = n->poll(n, weight);
+               /* This NAPI_STATE_SCHED test is for avoiding a race
+                * with netpoll's poll_napi().  Only the entity which
+                * obtains the lock and sees NAPI_STATE_SCHED set will
+                * actually make the ->poll() call.  Therefore we avoid
+                * accidently calling ->poll() when NAPI is not scheduled.
+                */
+               work = 0;
+               if (test_bit(NAPI_STATE_SCHED, &n->state))
+                       work = n->poll(n, weight);
 
                WARN_ON_ONCE(work > weight);
 
@@ -2611,7 +2654,7 @@ static const struct file_operations ptype_seq_fops = {
 };
 
 
-static int dev_proc_net_init(struct net *net)
+static int __net_init dev_proc_net_init(struct net *net)
 {
        int rc = -ENOMEM;
 
@@ -2636,7 +2679,7 @@ out_dev:
        goto out;
 }
 
-static void dev_proc_net_exit(struct net *net)
+static void __net_exit dev_proc_net_exit(struct net *net)
 {
        wext_proc_exit(net);
 
@@ -3259,6 +3302,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
 
 /**
  *     dev_ioctl       -       network device ioctl
+ *     @net: the applicable net namespace
  *     @cmd: command to issue
  *     @arg: pointer to a struct ifreq in user space
  *
@@ -3436,6 +3480,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 
 /**
  *     dev_new_index   -       allocate an ifindex
+ *     @net: the applicable net namespace
  *
  *     Returns a suitable unique value for a new device interface
  *     number.  The caller must hold the rtnl semaphore or the
@@ -3463,6 +3508,60 @@ static void net_set_todo(struct net_device *dev)
        spin_unlock(&net_todo_list_lock);
 }
 
+static void rollback_registered(struct net_device *dev)
+{
+       BUG_ON(dev_boot_phase);
+       ASSERT_RTNL();
+
+       /* Some devices call without registering for initialization unwind. */
+       if (dev->reg_state == NETREG_UNINITIALIZED) {
+               printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
+                                 "was registered\n", dev->name, dev);
+
+               WARN_ON(1);
+               return;
+       }
+
+       BUG_ON(dev->reg_state != NETREG_REGISTERED);
+
+       /* If device is running, close it first. */
+       dev_close(dev);
+
+       /* And unlink it from device chain. */
+       unlist_netdevice(dev);
+
+       dev->reg_state = NETREG_UNREGISTERING;
+
+       synchronize_net();
+
+       /* Shutdown queueing discipline. */
+       dev_shutdown(dev);
+
+
+       /* Notify protocols, that we are about to destroy
+          this device. They should clean all the things.
+       */
+       call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
+
+       /*
+        *      Flush the unicast and multicast chains
+        */
+       dev_addr_discard(dev);
+
+       if (dev->uninit)
+               dev->uninit(dev);
+
+       /* Notifier chain MUST detach us from master device. */
+       BUG_TRAP(!dev->master);
+
+       /* Remove entries from kobject tree */
+       netdev_unregister_kobject(dev);
+
+       synchronize_net();
+
+       dev_put(dev);
+}
+
 /**
  *     register_netdevice      - register a network device
  *     @dev: device to register
@@ -3600,8 +3699,10 @@ int register_netdevice(struct net_device *dev)
        /* Notify protocols, that a new device appeared. */
        ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
        ret = notifier_to_errno(ret);
-       if (ret)
-               unregister_netdevice(dev);
+       if (ret) {
+               rollback_registered(dev);
+               dev->reg_state = NETREG_UNREGISTERED;
+       }
 
 out:
        return ret;
@@ -3878,60 +3979,9 @@ void synchronize_net(void)
 
 void unregister_netdevice(struct net_device *dev)
 {
-       BUG_ON(dev_boot_phase);
-       ASSERT_RTNL();
-
-       /* Some devices call without registering for initialization unwind. */
-       if (dev->reg_state == NETREG_UNINITIALIZED) {
-               printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
-                                 "was registered\n", dev->name, dev);
-
-               WARN_ON(1);
-               return;
-       }
-
-       BUG_ON(dev->reg_state != NETREG_REGISTERED);
-
-       /* If device is running, close it first. */
-       if (dev->flags & IFF_UP)
-               dev_close(dev);
-
-       /* And unlink it from device chain. */
-       unlist_netdevice(dev);
-
-       dev->reg_state = NETREG_UNREGISTERING;
-
-       synchronize_net();
-
-       /* Shutdown queueing discipline. */
-       dev_shutdown(dev);
-
-
-       /* Notify protocols, that we are about to destroy
-          this device. They should clean all the things.
-       */
-       call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
-
-       /*
-        *      Flush the unicast and multicast chains
-        */
-       dev_addr_discard(dev);
-
-       if (dev->uninit)
-               dev->uninit(dev);
-
-       /* Notifier chain MUST detach us from master device. */
-       BUG_TRAP(!dev->master);
-
-       /* Remove entries from kobject tree */
-       netdev_unregister_kobject(dev);
-
+       rollback_registered(dev);
        /* Finish processing unregister after unlock */
        net_set_todo(dev);
-
-       synchronize_net();
-
-       dev_put(dev);
 }
 
 /**
@@ -4018,8 +4068,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
         */
 
        /* If device is running close it first. */
-       if (dev->flags & IFF_UP)
-               dev_close(dev);
+       dev_close(dev);
 
        /* And unlink it from device chain */
        err = -ENODEV;
@@ -4278,7 +4327,7 @@ static struct hlist_head *netdev_create_hash(void)
 }
 
 /* Initialize per network namespace state */
-static int netdev_init(struct net *net)
+static int __net_init netdev_init(struct net *net)
 {
        INIT_LIST_HEAD(&net->dev_base_head);
        rwlock_init(&dev_base_lock);
@@ -4299,18 +4348,18 @@ err_name:
        return -ENOMEM;
 }
 
-static void netdev_exit(struct net *net)
+static void __net_exit netdev_exit(struct net *net)
 {
        kfree(net->dev_name_head);
        kfree(net->dev_index_head);
 }
 
-static struct pernet_operations netdev_net_ops = {
+static struct pernet_operations  netdev_net_ops = {
        .init = netdev_init,
        .exit = netdev_exit,
 };
 
-static void default_device_exit(struct net *net)
+static void __net_exit default_device_exit(struct net *net)
 {
        struct net_device *dev, *next;
        /*
@@ -4336,7 +4385,7 @@ static void default_device_exit(struct net *net)
        rtnl_unlock();
 }
 
-static struct pernet_operations default_device_ops = {
+static struct pernet_operations  default_device_ops = {
        .exit = default_device_exit,
 };