X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fcore%2Fdev.c;h=034b57e3155592fff3f10008e47c1c4d9d4ce526;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=50eff37718d6f2200598f361734206653c479550;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/net/core/dev.c b/net/core/dev.c index 50eff3771..034b57e31 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -81,7 +81,6 @@ #include #include #include -#include #include #include #include @@ -111,18 +110,12 @@ #include #include #include -#include +#ifdef CONFIG_NET_RADIO +#include /* Note : will define WIRELESS_EXT */ #include -#include -#include -#include +#endif /* CONFIG_NET_RADIO */ #include - -#ifdef CONFIG_XEN -#include -#include -#include -#endif +#include /* * The list of packet types we will receive (as opposed to discard) @@ -135,7 +128,7 @@ * sure which should go first, but I bet it won't make much * difference if we are running VLANs. The good news is that * this protocol won't be in the list unless compiled in, so - * the average user (w/out VLANs) will not be adversely affected. + * the average user (w/out VLANs) will not be adversly affected. * --BLG * * 0800 IP @@ -157,7 +150,7 @@ static struct list_head ptype_base[16]; /* 16 way hashed list */ static struct list_head ptype_all; /* Taps */ /* - * The @dev_base list is protected by @dev_base_lock and the rtnl + * The @dev_base list is protected by @dev_base_lock and the rtln * semaphore. * * Pure readers hold dev_base_lock for reading. @@ -201,7 +194,7 @@ static inline struct hlist_head *dev_index_hash(int ifindex) * Our notifier list */ -static RAW_NOTIFIER_HEAD(netdev_chain); +static struct notifier_block *netdev_chain; /* * Device drivers call our routines to queue packets here. We empty the @@ -649,12 +642,10 @@ int dev_valid_name(const char *name) * @name: name format string * * Passed a format string - eg "lt%d" it will try and find a suitable - * id. It scans list of devices to build up a free map, then chooses - * the first empty slot. The caller must hold the dev_base or rtnl lock - * while allocating the name and adding the device in order to avoid - * duplicates. - * Limited to bits_per_byte * page size devices (ie 32K on most platforms). - * Returns the number of the unit assigned or a negative errno code. + * id. Not efficient for many devices, not called a lot. The caller + * must hold the dev_base or rtnl lock while allocating the name and + * adding the device in order to avoid duplicates. Returns the number + * of the unit assigned or a negative errno code. */ int dev_alloc_name(struct net_device *dev, const char *name) @@ -746,22 +737,21 @@ int dev_change_name(struct net_device *dev, char *newname) if (!err) { hlist_del(&dev->name_hlist); hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); - raw_notifier_call_chain(&netdev_chain, - NETDEV_CHANGENAME, dev); + notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); } return err; } /** - * netdev_features_change - device changes features + * netdev_features_change - device changes fatures * @dev: device to cause notification * * Called to indicate a device has changed features. */ void netdev_features_change(struct net_device *dev) { - raw_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev); + notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev); } EXPORT_SYMBOL(netdev_features_change); @@ -776,8 +766,7 @@ EXPORT_SYMBOL(netdev_features_change); void netdev_state_change(struct net_device *dev) { if (dev->flags & IFF_UP) { - raw_notifier_call_chain(&netdev_chain, - NETDEV_CHANGE, dev); + notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); rtmsg_ifinfo(RTM_NEWLINK, dev, 0); } } @@ -874,7 +863,7 @@ int dev_open(struct net_device *dev) /* * ... and announce new interface. */ - raw_notifier_call_chain(&netdev_chain, NETDEV_UP, dev); + notifier_call_chain(&netdev_chain, NETDEV_UP, dev); } return ret; } @@ -897,7 +886,7 @@ int dev_close(struct net_device *dev) * Tell people we are going down, so that they can * prepare to death, when device is still operating. */ - raw_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev); + notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev); dev_deactivate(dev); @@ -934,7 +923,7 @@ int dev_close(struct net_device *dev) /* * Tell people we are down */ - raw_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev); + notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev); return 0; } @@ -965,7 +954,7 @@ int register_netdevice_notifier(struct notifier_block *nb) int err; rtnl_lock(); - err = raw_notifier_chain_register(&netdev_chain, nb); + err = notifier_chain_register(&netdev_chain, nb); if (!err) { for (dev = dev_base; dev; dev = dev->next) { nb->notifier_call(nb, NETDEV_REGISTER, dev); @@ -990,12 +979,7 @@ int register_netdevice_notifier(struct notifier_block *nb) int unregister_netdevice_notifier(struct notifier_block *nb) { - int err; - - rtnl_lock(); - err = raw_notifier_chain_unregister(&netdev_chain, nb); - rtnl_unlock(); - return err; + return notifier_chain_unregister(&netdev_chain, nb); } /** @@ -1004,12 +988,12 @@ int unregister_netdevice_notifier(struct notifier_block *nb) * @v: pointer passed unmodified to notifier function * * Call all network notifier blocks. Parameters and return value - * are as for raw_notifier_call_chain(). + * are as for notifier_call_chain(). */ int call_netdevice_notifiers(unsigned long val, void *v) { - return raw_notifier_call_chain(&netdev_chain, val, v); + return notifier_call_chain(&netdev_chain, val, v); } /* When > 0 there are consumers of rx skb time stamps */ @@ -1050,8 +1034,10 @@ static inline void net_timestamp(struct sk_buff *skb) */ #if !((defined(CONFIG_VNET) || defined(CONFIG_VNET_MODULE))) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12) static #endif +#endif void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) { struct packet_type *ptype; @@ -1093,70 +1079,6 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) rcu_read_unlock(); } - -void __netif_schedule(struct net_device *dev) -{ - if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) { - unsigned long flags; - struct softnet_data *sd; - - local_irq_save(flags); - sd = &__get_cpu_var(softnet_data); - dev->next_sched = sd->output_queue; - sd->output_queue = dev; - raise_softirq_irqoff(NET_TX_SOFTIRQ); - local_irq_restore(flags); - } -} -EXPORT_SYMBOL(__netif_schedule); - -void __netif_rx_schedule(struct net_device *dev) -{ - unsigned long flags; - - local_irq_save(flags); - dev_hold(dev); - list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list); - if (dev->quota < 0) - dev->quota += dev->weight; - else - dev->quota = dev->weight; - __raise_softirq_irqoff(NET_RX_SOFTIRQ); - local_irq_restore(flags); -} -EXPORT_SYMBOL(__netif_rx_schedule); - -void dev_kfree_skb_any(struct sk_buff *skb) -{ - if (in_irq() || irqs_disabled()) - dev_kfree_skb_irq(skb); - else - dev_kfree_skb(skb); -} -EXPORT_SYMBOL(dev_kfree_skb_any); - - -/* Hot-plugging. */ -void netif_device_detach(struct net_device *dev) -{ - if (test_and_clear_bit(__LINK_STATE_PRESENT, &dev->state) && - netif_running(dev)) { - netif_stop_queue(dev); - } -} -EXPORT_SYMBOL(netif_device_detach); - -void netif_device_attach(struct net_device *dev) -{ - if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) && - netif_running(dev)) { - netif_wake_queue(dev); - __netdev_watchdog_up(dev); - } -} -EXPORT_SYMBOL(netif_device_attach); - - /* * Invalidate hardware checksum when packet is to be mangled, and * complete checksum manually on outgoing path. @@ -1190,45 +1112,6 @@ out: return ret; } -/** - * skb_gso_segment - Perform segmentation on skb. - * @skb: buffer to segment - * @features: features for the output path (see dev->features) - * - * This function segments the given skb and returns a list of segments. - * - * It may return NULL if the skb requires no segmentation. This is - * only possible when GSO is used for verifying header integrity. - */ -struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) -{ - struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); - struct packet_type *ptype; - int type = skb->protocol; - - BUG_ON(skb_shinfo(skb)->frag_list); - BUG_ON(skb->ip_summed != CHECKSUM_HW); - - skb->mac.raw = skb->data; - skb->mac_len = skb->nh.raw - skb->data; - __skb_pull(skb, skb->mac_len); - - rcu_read_lock(); - list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { - if (ptype->type == type && !ptype->dev && ptype->gso_segment) { - segs = ptype->gso_segment(skb, features); - break; - } - } - rcu_read_unlock(); - - __skb_push(skb, skb->data - skb->mac.raw); - - return segs; -} - -EXPORT_SYMBOL(skb_gso_segment); - /* Take action when hardware reception checksum errors are detected. */ #ifdef CONFIG_BUG void netdev_rx_csum_fault(struct net_device *dev) @@ -1265,148 +1148,79 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb) #define illegal_highdma(dev, skb) (0) #endif -struct dev_gso_cb { - void (*destructor)(struct sk_buff *skb); -}; - -#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb) - -static void dev_gso_skb_destructor(struct sk_buff *skb) -{ - struct dev_gso_cb *cb; - - do { - struct sk_buff *nskb = skb->next; - - skb->next = nskb->next; - nskb->next = NULL; - kfree_skb(nskb); - } while (skb->next); - - cb = DEV_GSO_CB(skb); - if (cb->destructor) - cb->destructor(skb); -} - -/** - * dev_gso_segment - Perform emulated hardware segmentation on skb. - * @skb: buffer to segment - * - * This function segments the given skb and stores the list of segments - * in skb->next. - */ -static int dev_gso_segment(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - struct sk_buff *segs; - int features = dev->features & ~(illegal_highdma(dev, skb) ? - NETIF_F_SG : 0); - - segs = skb_gso_segment(skb, features); - - /* Verifying header integrity only. */ - if (!segs) - return 0; - - if (unlikely(IS_ERR(segs))) - return PTR_ERR(segs); - - skb->next = segs; - DEV_GSO_CB(skb)->destructor = skb->destructor; - skb->destructor = dev_gso_skb_destructor; - - return 0; -} - -int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - if (likely(!skb->next)) { - if (netdev_nit) - dev_queue_xmit_nit(skb, dev); - - if (netif_needs_gso(dev, skb)) { - if (unlikely(dev_gso_segment(skb))) - goto out_kfree_skb; - if (skb->next) - goto gso; - } - - return dev->hard_start_xmit(skb, dev); - } - -gso: - do { - struct sk_buff *nskb = skb->next; - int rc; - - skb->next = nskb->next; - nskb->next = NULL; - rc = dev->hard_start_xmit(nskb, dev); - if (unlikely(rc)) { - nskb->next = skb->next; - skb->next = nskb; - return rc; - } - if (unlikely(netif_queue_stopped(dev) && skb->next)) - return NETDEV_TX_BUSY; - } while (skb->next); - - skb->destructor = DEV_GSO_CB(skb)->destructor; - -out_kfree_skb: - kfree_skb(skb); +/* Keep head the same: replace data */ +int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask) +{ + unsigned int size; + u8 *data; + long offset; + struct skb_shared_info *ninfo; + int headerlen = skb->data - skb->head; + int expand = (skb->tail + skb->data_len) - skb->end; + + if (skb_shared(skb)) + BUG(); + + if (expand <= 0) + expand = 0; + + size = skb->end - skb->head + expand; + size = SKB_DATA_ALIGN(size); + data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask); + if (!data) + return -ENOMEM; + + /* Copy entire thing */ + if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len)) + BUG(); + + /* Set up shinfo */ + ninfo = (struct skb_shared_info*)(data + size); + atomic_set(&ninfo->dataref, 1); + ninfo->tso_size = skb_shinfo(skb)->tso_size; + ninfo->tso_segs = skb_shinfo(skb)->tso_segs; + ninfo->ufo_size = skb_shinfo(skb)->ufo_size; + ninfo->nr_frags = 0; + ninfo->frag_list = NULL; + + /* Offset between the two in bytes */ + offset = data - skb->head; + + /* Free old data. */ + skb_release_data(skb); + + skb->head = data; + skb->end = data + size; + + /* Set up new pointers */ + skb->h.raw += offset; + skb->nh.raw += offset; + skb->mac.raw += offset; + skb->tail += offset; + skb->data += offset; + + /* We are no longer a clone, even if we were. */ + skb->cloned = 0; + + skb->tail += skb->data_len; + skb->data_len = 0; return 0; } #define HARD_TX_LOCK(dev, cpu) { \ if ((dev->features & NETIF_F_LLTX) == 0) { \ - netif_tx_lock(dev); \ + spin_lock(&dev->xmit_lock); \ + dev->xmit_lock_owner = cpu; \ } \ } #define HARD_TX_UNLOCK(dev) { \ if ((dev->features & NETIF_F_LLTX) == 0) { \ - netif_tx_unlock(dev); \ + dev->xmit_lock_owner = -1; \ + spin_unlock(&dev->xmit_lock); \ } \ } -#ifdef CONFIG_XEN -inline int skb_checksum_setup(struct sk_buff *skb) -{ - if (skb->proto_csum_blank) { - if (skb->protocol != htons(ETH_P_IP)) - goto out; - skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl; - if (skb->h.raw >= skb->tail) - goto out; - switch (skb->nh.iph->protocol) { - case IPPROTO_TCP: - skb->csum = offsetof(struct tcphdr, check); - break; - case IPPROTO_UDP: - skb->csum = offsetof(struct udphdr, check); - break; - default: - if (net_ratelimit()) - printk(KERN_ERR "Attempting to checksum a non-" - "TCP/UDP packet, dropping a protocol" - " %d packet", skb->nh.iph->protocol); - goto out; - } - if ((skb->h.raw + skb->csum + 2) > skb->tail) - goto out; - skb->ip_summed = CHECKSUM_HW; - skb->proto_csum_blank = 0; - } - return 0; -out: - return -EPROTO; -} -#else -inline int skb_checksum_setup(struct sk_buff *skb) { return 0; } -#endif - - /** * dev_queue_xmit - transmit a buffer * @skb: buffer to transmit @@ -1439,19 +1253,9 @@ int dev_queue_xmit(struct sk_buff *skb) struct Qdisc *q; int rc = -ENOMEM; - /* If a checksum-deferred packet is forwarded to a device that needs a - * checksum, correct the pointers and force checksumming. - */ - if (skb_checksum_setup(skb)) - goto out_kfree_skb; - - /* GSO will handle the following emulations directly. */ - if (netif_needs_gso(dev, skb)) - goto gso; - if (skb_shinfo(skb)->frag_list && !(dev->features & NETIF_F_FRAGLIST) && - __skb_linearize(skb)) + __skb_linearize(skb, GFP_ATOMIC)) goto out_kfree_skb; /* Fragmented skb is linearized if device does not support SG, @@ -1460,26 +1264,25 @@ int dev_queue_xmit(struct sk_buff *skb) */ if (skb_shinfo(skb)->nr_frags && (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && - __skb_linearize(skb)) + __skb_linearize(skb, GFP_ATOMIC)) goto out_kfree_skb; /* If packet is not checksummed and device does not support * checksumming for this protocol, complete checksumming here. */ if (skb->ip_summed == CHECKSUM_HW && - (!(dev->features & NETIF_F_GEN_CSUM) && + (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) && (!(dev->features & NETIF_F_IP_CSUM) || skb->protocol != htons(ETH_P_IP)))) if (skb_checksum_help(skb, 0)) goto out_kfree_skb; -gso: spin_lock_prefetch(&dev->queue_lock); /* Disable soft irqs for various locks below. Also * stops preemption for RCU. */ - rcu_read_lock_bh(); + local_bh_disable(); /* Updates of qdisc are serialized by queue_lock. * The struct Qdisc which is pointed to by qdisc is now a @@ -1500,21 +1303,23 @@ gso: if (q->enqueue) { /* Grab device queue */ spin_lock(&dev->queue_lock); + q = dev->qdisc; + if (q->enqueue) { + rc = q->enqueue(skb, q); + qdisc_run(dev); + spin_unlock(&dev->queue_lock); - rc = q->enqueue(skb, q); - - qdisc_run(dev); - + rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc; + goto out; + } spin_unlock(&dev->queue_lock); - rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc; - goto out; } /* The device has no queue. Common case for software devices: loopback, all the sorts of tunnels... - Really, it is unlikely that netif_tx_lock protection is necessary - here. (f.e. loopback and IP tunnels are clean ignoring statistics + Really, it is unlikely that xmit_lock protection is necessary here. + (f.e. loopback and IP tunnels are clean ignoring statistics counters.) However, it is possible, that they rely on protection made by us here. @@ -1530,8 +1335,11 @@ gso: HARD_TX_LOCK(dev, cpu); if (!netif_queue_stopped(dev)) { + if (netdev_nit) + dev_queue_xmit_nit(skb, dev); + rc = 0; - if (!dev_hard_start_xmit(skb, dev)) { + if (!dev->hard_start_xmit(skb, dev)) { HARD_TX_UNLOCK(dev); goto out; } @@ -1550,13 +1358,13 @@ gso: } rc = -ENETDOWN; - rcu_read_unlock_bh(); + local_bh_enable(); out_kfree_skb: kfree_skb(skb); return rc; out: - rcu_read_unlock_bh(); + local_bh_enable(); return rc; } @@ -1649,29 +1457,8 @@ static inline struct net_device *skb_bond(struct sk_buff *skb) { struct net_device *dev = skb->dev; - if (dev->master) { - /* - * On bonding slaves other than the currently active - * slave, suppress duplicates except for 802.3ad - * ETH_P_SLOW and alb non-mcast/bcast. - */ - if (dev->priv_flags & IFF_SLAVE_INACTIVE) { - if (dev->master->priv_flags & IFF_MASTER_ALB) { - if (skb->pkt_type != PACKET_BROADCAST && - skb->pkt_type != PACKET_MULTICAST) - goto keep; - } - - if (dev->master->priv_flags & IFF_MASTER_8023AD && - skb->protocol == __constant_htons(ETH_P_SLOW)) - goto keep; - - kfree_skb(skb); - return NULL; - } -keep: + if (dev->master) skb->dev = dev->master; - } return dev; } @@ -1815,9 +1602,6 @@ int netif_receive_skb(struct sk_buff *skb) orig_dev = skb_bond(skb); - if (!orig_dev) - return NET_RX_DROP; - __get_cpu_var(netdev_rx_stat).total++; skb->h.raw = skb->nh.raw = skb->data; @@ -1834,19 +1618,6 @@ int netif_receive_skb(struct sk_buff *skb) } #endif -#ifdef CONFIG_XEN - switch (skb->ip_summed) { - case CHECKSUM_UNNECESSARY: - skb->proto_data_valid = 1; - break; - case CHECKSUM_HW: - /* XXX Implement me. */ - default: - skb->proto_data_valid = 0; - break; - } -#endif - list_for_each_entry_rcu(ptype, &ptype_all, list) { if (!ptype->dev || ptype->dev == skb->dev) { if (pt_prev) @@ -1975,7 +1746,8 @@ static void net_rx_action(struct softirq_action *h) if (dev->quota <= 0 || dev->poll(dev, &budget)) { netpoll_poll_unlock(have); local_irq_disable(); - list_move_tail(&dev->poll_list, &queue->poll_list); + list_del(&dev->poll_list); + list_add_tail(&dev->poll_list, &queue->poll_list); if (dev->quota < 0) dev->quota += dev->weight; else @@ -2272,7 +2044,7 @@ static struct file_operations softnet_seq_fops = { .release = seq_release, }; -#ifdef CONFIG_WIRELESS_EXT +#ifdef WIRELESS_EXT extern int wireless_proc_init(void); #else #define wireless_proc_init() 0 @@ -2346,7 +2118,7 @@ int netdev_set_master(struct net_device *slave, struct net_device *master) * @dev: device * @inc: modifier * - * Add or remove promiscuity from a device. While the count in the device + * Add or remove promsicuity from a device. While the count in the device * remains above zero the interface remains promiscuous. Once it hits zero * the device reverts back to normal filtering operation. A negative inc * value is used to drop promiscuity on the device. @@ -2364,12 +2136,6 @@ void dev_set_promiscuity(struct net_device *dev, int inc) printk(KERN_INFO "device %s %s promiscuous mode\n", dev->name, (dev->flags & IFF_PROMISC) ? "entered" : "left"); - audit_log(current->audit_context, GFP_ATOMIC, - AUDIT_ANOM_PROMISCUOUS, - "dev=%s prom=%d old_prom=%d auid=%u", - dev->name, (dev->flags & IFF_PROMISC), - (old_flags & IFF_PROMISC), - audit_get_loginuid(current->audit_context)); } } @@ -2402,20 +2168,12 @@ unsigned dev_get_flags(const struct net_device *dev) flags = (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI | - IFF_RUNNING | - IFF_LOWER_UP | - IFF_DORMANT)) | + IFF_RUNNING)) | (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI)); - if (netif_running(dev)) { - if (netif_oper_up(dev)) - flags |= IFF_RUNNING; - if (netif_carrier_ok(dev)) - flags |= IFF_LOWER_UP; - if (netif_dormant(dev)) - flags |= IFF_DORMANT; - } + if (netif_running(dev) && netif_carrier_ok(dev)) + flags |= IFF_RUNNING; return flags; } @@ -2458,8 +2216,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags) if (dev->flags & IFF_UP && ((old_flags ^ dev->flags) &~ (IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE))) - raw_notifier_call_chain(&netdev_chain, - NETDEV_CHANGE, dev); + notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); if ((flags ^ dev->gflags) & IFF_PROMISC) { int inc = (flags & IFF_PROMISC) ? +1 : -1; @@ -2503,8 +2260,8 @@ int dev_set_mtu(struct net_device *dev, int new_mtu) else dev->mtu = new_mtu; if (!err && dev->flags & IFF_UP) - raw_notifier_call_chain(&netdev_chain, - NETDEV_CHANGEMTU, dev); + notifier_call_chain(&netdev_chain, + NETDEV_CHANGEMTU, dev); return err; } @@ -2520,8 +2277,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) return -ENODEV; err = dev->set_mac_address(dev, sa); if (!err) - raw_notifier_call_chain(&netdev_chain, - NETDEV_CHANGEADDR, dev); + notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev); return err; } @@ -2577,7 +2333,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd) return -EINVAL; memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len)); - raw_notifier_call_chain(&netdev_chain, + notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev); return 0; @@ -2696,9 +2452,9 @@ int dev_ioctl(unsigned int cmd, void __user *arg) */ if (cmd == SIOCGIFCONF) { - rtnl_lock(); + rtnl_shlock(); ret = dev_ifconf((char __user *) arg); - rtnl_unlock(); + rtnl_shunlock(); return ret; } if (cmd == SIOCGIFNAME) @@ -2842,14 +2598,13 @@ int dev_ioctl(unsigned int cmd, void __user *arg) ret = -EFAULT; return ret; } -#ifdef CONFIG_WIRELESS_EXT +#ifdef WIRELESS_EXT /* Take care of Wireless Extensions */ if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { /* If command is `set a parameter', or * `get the encoding parameters', check if * the user has the right to do it */ - if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE - || cmd == SIOCGIWENCODEEXT) { + if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE) { if (!capable(CAP_NET_ADMIN)) return -EPERM; } @@ -2864,7 +2619,7 @@ int dev_ioctl(unsigned int cmd, void __user *arg) ret = -EFAULT; return ret; } -#endif /* CONFIG_WIRELESS_EXT */ +#endif /* WIRELESS_EXT */ return -EINVAL; } } @@ -2927,13 +2682,11 @@ int register_netdevice(struct net_device *dev) BUG_ON(dev_boot_phase); ASSERT_RTNL(); - might_sleep(); - /* When net_device's are persistent, this will be fatal. */ BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); spin_lock_init(&dev->queue_lock); - spin_lock_init(&dev->_xmit_lock); + spin_lock_init(&dev->xmit_lock); dev->xmit_lock_owner = -1; #ifdef CONFIG_NET_CLS_ACT spin_lock_init(&dev->ingress_lock); @@ -2977,7 +2730,9 @@ int register_netdevice(struct net_device *dev) /* Fix illegal SG+CSUM combinations. */ if ((dev->features & NETIF_F_SG) && - !(dev->features & NETIF_F_ALL_CSUM)) { + !(dev->features & (NETIF_F_IP_CSUM | + NETIF_F_NO_CSUM | + NETIF_F_HW_CSUM))) { printk("%s: Dropping NETIF_F_SG since no checksum feature.\n", dev->name); dev->features &= ~NETIF_F_SG; @@ -3013,11 +2768,6 @@ int register_netdevice(struct net_device *dev) if (!dev->rebuild_header) dev->rebuild_header = default_rebuild_header; - ret = netdev_register_sysfs(dev); - if (ret) - goto out_err; - dev->reg_state = NETREG_REGISTERED; - /* * Default initial state at registry is that the * device is present. @@ -3033,11 +2783,14 @@ int register_netdevice(struct net_device *dev) hlist_add_head(&dev->name_hlist, head); hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex)); dev_hold(dev); + dev->reg_state = NETREG_REGISTERING; write_unlock_bh(&dev_base_lock); /* Notify protocols, that a new device appeared. */ - raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); + notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); + /* Finish registration after unlock */ + net_set_todo(dev); ret = 0; out: @@ -3110,10 +2863,10 @@ static void netdev_wait_allrefs(struct net_device *dev) rebroadcast_time = warning_time = jiffies; while (atomic_read(&dev->refcnt) != 0) { if (time_after(jiffies, rebroadcast_time + 1 * HZ)) { - rtnl_lock(); + rtnl_shlock(); /* Rebroadcast unregister notification */ - raw_notifier_call_chain(&netdev_chain, + notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); if (test_bit(__LINK_STATE_LINKWATCH_PENDING, @@ -3127,7 +2880,7 @@ static void netdev_wait_allrefs(struct net_device *dev) linkwatch_run_queue(); } - __rtnl_unlock(); + rtnl_shunlock(); rebroadcast_time = jiffies; } @@ -3160,18 +2913,20 @@ static void netdev_wait_allrefs(struct net_device *dev) * * We are invoked by rtnl_unlock() after it drops the semaphore. * This allows us to deal with problems: - * 1) We can delete sysfs objects which invoke hotplug + * 1) We can create/delete sysfs objects which invoke hotplug * without deadlocking with linkwatch via keventd. * 2) Since we run with the RTNL semaphore not held, we can sleep * safely in order to wait for the netdev refcnt to drop to zero. */ -static DEFINE_MUTEX(net_todo_run_mutex); +static DECLARE_MUTEX(net_todo_run_mutex); void netdev_run_todo(void) { struct list_head list = LIST_HEAD_INIT(list); + int err; + /* Need to guard against multiple cpu's getting out of order. */ - mutex_lock(&net_todo_run_mutex); + down(&net_todo_run_mutex); /* Not safe to do outside the semaphore. We must not return * until all unregister events invoked by the local processor @@ -3191,33 +2946,44 @@ void netdev_run_todo(void) = list_entry(list.next, struct net_device, todo_list); list_del(&dev->todo_list); - if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) { - printk(KERN_ERR "network todo '%s' but state %d\n", - dev->name, dev->reg_state); - dump_stack(); - continue; - } + switch(dev->reg_state) { + case NETREG_REGISTERING: + dev->reg_state = NETREG_REGISTERED; + err = netdev_register_sysfs(dev); + if (err) + printk(KERN_ERR "%s: failed sysfs registration (%d)\n", + dev->name, err); + break; - netdev_unregister_sysfs(dev); - dev->reg_state = NETREG_UNREGISTERED; + case NETREG_UNREGISTERING: + netdev_unregister_sysfs(dev); + dev->reg_state = NETREG_UNREGISTERED; - netdev_wait_allrefs(dev); + netdev_wait_allrefs(dev); - /* paranoia */ - BUG_ON(atomic_read(&dev->refcnt)); - BUG_TRAP(!dev->ip_ptr); - BUG_TRAP(!dev->ip6_ptr); - BUG_TRAP(!dev->dn_ptr); + /* paranoia */ + BUG_ON(atomic_read(&dev->refcnt)); + BUG_TRAP(!dev->ip_ptr); + BUG_TRAP(!dev->ip6_ptr); + BUG_TRAP(!dev->dn_ptr); - /* It must be the very last action, - * after this 'dev' may point to freed up memory. - */ - if (dev->destructor) - dev->destructor(dev); + + /* It must be the very last action, + * after this 'dev' may point to freed up memory. + */ + if (dev->destructor) + dev->destructor(dev); + break; + + default: + printk(KERN_ERR "network todo '%s' but state %d\n", + dev->name, dev->reg_state); + break; + } } out: - mutex_unlock(&net_todo_run_mutex); + up(&net_todo_run_mutex); } /** @@ -3240,11 +3006,12 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; - p = kzalloc(alloc_size, GFP_KERNEL); + p = kmalloc(alloc_size, GFP_KERNEL); if (!p) { printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); return NULL; } + memset(p, 0, alloc_size); dev = (struct net_device *) (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); @@ -3270,7 +3037,7 @@ EXPORT_SYMBOL(alloc_netdev); void free_netdev(struct net_device *dev) { #ifdef CONFIG_SYSFS - /* Compatibility with error handling in drivers */ + /* Compatiablity with error handling in drivers */ if (dev->reg_state == NETREG_UNINITIALIZED) { kfree((char *)dev - dev->padded); return; @@ -3355,7 +3122,7 @@ int unregister_netdevice(struct net_device *dev) /* Notify protocols, that we are about to destroy this device. They should clean all the things. */ - raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); + notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); /* * Flush the multicast chain @@ -3486,7 +3253,7 @@ static int __init net_dev_init(void) * Initialise the packet receive queues. */ - for_each_possible_cpu(i) { + for_each_cpu(i) { struct softnet_data *queue; queue = &per_cpu(softnet_data, i); @@ -3517,6 +3284,7 @@ subsys_initcall(net_dev_init); EXPORT_SYMBOL(__dev_get_by_index); EXPORT_SYMBOL(__dev_get_by_name); EXPORT_SYMBOL(__dev_remove_pack); +EXPORT_SYMBOL(__skb_linearize); EXPORT_SYMBOL(dev_valid_name); EXPORT_SYMBOL(dev_add_pack); EXPORT_SYMBOL(dev_alloc_name); @@ -3551,7 +3319,6 @@ EXPORT_SYMBOL(unregister_netdevice_notifier); EXPORT_SYMBOL(net_enable_timestamp); EXPORT_SYMBOL(net_disable_timestamp); EXPORT_SYMBOL(dev_get_flags); -EXPORT_SYMBOL(skb_checksum_setup); #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) EXPORT_SYMBOL(br_handle_frame_hook);