]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/core/dev.c
Merge branch 'timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mv-sheeva.git] / net / core / dev.c
index ae0b66936abe70b30f5462e255baac4fcc12d6e7..052dd478d3e112b769b66ab83db5b82996d88061 100644 (file)
 /* This should be increased if a protocol with a bigger head is added. */
 #define GRO_MAX_HEAD (MAX_HEADER + 128)
 
-enum {
-       GRO_MERGED,
-       GRO_MERGED_FREE,
-       GRO_HELD,
-       GRO_NORMAL,
-       GRO_DROP,
-};
-
 /*
  *     The list of packet types we will receive (as opposed to discard)
  *     and the routines to invoke.
@@ -215,13 +207,6 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
        return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)];
 }
 
-static inline void *skb_gro_mac_header(struct sk_buff *skb)
-{
-       return skb_mac_header(skb) < skb->data ? skb_mac_header(skb) :
-              page_address(skb_shinfo(skb)->frags[0].page) +
-              skb_shinfo(skb)->frags[0].page_offset;
-}
-
 /* Device list insertion */
 static int list_netdevice(struct net_device *dev)
 {
@@ -1683,8 +1668,8 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        struct netdev_queue *txq)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
+       int rc;
 
-       prefetch(&dev->netdev_ops->ndo_start_xmit);
        if (likely(!skb->next)) {
                if (!list_empty(&ptype_all))
                        dev_queue_xmit_nit(skb, dev);
@@ -1696,13 +1681,27 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                                goto gso;
                }
 
-               return ops->ndo_start_xmit(skb, dev);
+               rc = ops->ndo_start_xmit(skb, dev);
+               /*
+                * TODO: if skb_orphan() was called by
+                * dev->hard_start_xmit() (for example, the unmodified
+                * igb driver does that; bnx2 doesn't), then
+                * skb_tx_software_timestamp() will be unable to send
+                * back the time stamp.
+                *
+                * How can this be prevented? Always create another
+                * reference to the socket before calling
+                * dev->hard_start_xmit()? Prevent that skb_orphan()
+                * does anything in dev->hard_start_xmit() by clearing
+                * the skb destructor before the call and restoring it
+                * afterwards, then doing the skb_orphan() ourselves?
+                */
+               return rc;
        }
 
 gso:
        do {
                struct sk_buff *nskb = skb->next;
-               int rc;
 
                skb->next = nskb->next;
                nskb->next = NULL;
@@ -1724,17 +1723,11 @@ out_kfree_skb:
 }
 
 static u32 skb_tx_hashrnd;
-static int skb_tx_hashrnd_initialized = 0;
 
-static u16 skb_tx_hash(struct net_device *dev, struct sk_buff *skb)
+u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
 {
        u32 hash;
 
-       if (unlikely(!skb_tx_hashrnd_initialized)) {
-               get_random_bytes(&skb_tx_hashrnd, 4);
-               skb_tx_hashrnd_initialized = 1;
-       }
-
        if (skb_rx_queue_recorded(skb)) {
                hash = skb_get_rx_queue(skb);
        } else if (skb->sk && skb->sk->sk_hash) {
@@ -1746,6 +1739,7 @@ static u16 skb_tx_hash(struct net_device *dev, struct sk_buff *skb)
 
        return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
 }
+EXPORT_SYMBOL(skb_tx_hash);
 
 static struct netdev_queue *dev_pick_tx(struct net_device *dev,
                                        struct sk_buff *skb)
@@ -2252,12 +2246,6 @@ int netif_receive_skb(struct sk_buff *skb)
 
        rcu_read_lock();
 
-       /* Don't receive packets in an exiting network namespace */
-       if (!net_alive(dev_net(skb->dev))) {
-               kfree_skb(skb);
-               goto out;
-       }
-
 #ifdef CONFIG_NET_CLS_ACT
        if (skb->tc_verd & TC_NCLS) {
                skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
@@ -2415,29 +2403,16 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 
        rcu_read_lock();
        list_for_each_entry_rcu(ptype, head, list) {
-               struct sk_buff *p;
-               void *mac;
-
                if (ptype->type != type || ptype->dev || !ptype->gro_receive)
                        continue;
 
                skb_set_network_header(skb, skb_gro_offset(skb));
-               mac = skb_gro_mac_header(skb);
                mac_len = skb->network_header - skb->mac_header;
                skb->mac_len = mac_len;
                NAPI_GRO_CB(skb)->same_flow = 0;
                NAPI_GRO_CB(skb)->flush = 0;
                NAPI_GRO_CB(skb)->free = 0;
 
-               for (p = napi->gro_list; p; p = p->next) {
-                       if (!NAPI_GRO_CB(p)->same_flow)
-                               continue;
-
-                       if (p->mac_len != mac_len ||
-                           memcmp(skb_mac_header(p), mac, mac_len))
-                               NAPI_GRO_CB(p)->same_flow = 0;
-               }
-
                pp = ptype->gro_receive(&napi->gro_list, skb);
                break;
        }
@@ -2491,8 +2466,12 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        struct sk_buff *p;
 
+       if (netpoll_rx_on(skb))
+               return GRO_NORMAL;
+
        for (p = napi->gro_list; p; p = p->next) {
-               NAPI_GRO_CB(p)->same_flow = 1;
+               NAPI_GRO_CB(p)->same_flow = !compare_ether_header(
+                       skb_mac_header(p), skb_gro_mac_header(skb));
                NAPI_GRO_CB(p)->flush = 0;
        }
 
@@ -2648,9 +2627,9 @@ static int process_backlog(struct napi_struct *napi, int quota)
                local_irq_disable();
                skb = __skb_dequeue(&queue->input_pkt_queue);
                if (!skb) {
-                       __napi_complete(napi);
                        local_irq_enable();
-                       break;
+                       napi_complete(napi);
+                       goto out;
                }
                local_irq_enable();
 
@@ -2659,6 +2638,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
 
        napi_gro_flush(napi);
 
+out:
        return work;
 }
 
@@ -2732,7 +2712,7 @@ void netif_napi_del(struct napi_struct *napi)
        struct sk_buff *skb, *next;
 
        list_del_init(&napi->dev_list);
-       kfree(napi->skb);
+       kfree_skb(napi->skb);
 
        for (skb = napi->gro_list; skb; skb = next) {
                next = skb->next;
@@ -4010,6 +3990,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
                            cmd == SIOCSMIIREG ||
                            cmd == SIOCBRADDIF ||
                            cmd == SIOCBRDELIF ||
+                           cmd == SIOCSHWTSTAMP ||
                            cmd == SIOCWANDEV) {
                                err = -EOPNOTSUPP;
                                if (ops->ndo_do_ioctl) {
@@ -4164,6 +4145,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                case SIOCBONDCHANGEACTIVE:
                case SIOCBRADDIF:
                case SIOCBRDELIF:
+               case SIOCSHWTSTAMP:
                        if (!capable(CAP_NET_ADMIN))
                                return -EPERM;
                        /* fall through */
@@ -4344,6 +4326,39 @@ unsigned long netdev_fix_features(unsigned long features, const char *name)
 }
 EXPORT_SYMBOL(netdev_fix_features);
 
+/* Some devices need to (re-)set their netdev_ops inside
+ * ->init() or similar.  If that happens, we have to setup
+ * the compat pointers again.
+ */
+void netdev_resync_ops(struct net_device *dev)
+{
+#ifdef CONFIG_COMPAT_NET_DEV_OPS
+       const struct net_device_ops *ops = dev->netdev_ops;
+
+       dev->init = ops->ndo_init;
+       dev->uninit = ops->ndo_uninit;
+       dev->open = ops->ndo_open;
+       dev->change_rx_flags = ops->ndo_change_rx_flags;
+       dev->set_rx_mode = ops->ndo_set_rx_mode;
+       dev->set_multicast_list = ops->ndo_set_multicast_list;
+       dev->set_mac_address = ops->ndo_set_mac_address;
+       dev->validate_addr = ops->ndo_validate_addr;
+       dev->do_ioctl = ops->ndo_do_ioctl;
+       dev->set_config = ops->ndo_set_config;
+       dev->change_mtu = ops->ndo_change_mtu;
+       dev->neigh_setup = ops->ndo_neigh_setup;
+       dev->tx_timeout = ops->ndo_tx_timeout;
+       dev->get_stats = ops->ndo_get_stats;
+       dev->vlan_rx_register = ops->ndo_vlan_rx_register;
+       dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
+       dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller = ops->ndo_poll_controller;
+#endif
+#endif
+}
+EXPORT_SYMBOL(netdev_resync_ops);
+
 /**
  *     register_netdevice      - register a network device
  *     @dev: device to register
@@ -4388,27 +4403,7 @@ int register_netdevice(struct net_device *dev)
         * This is temporary until all network devices are converted.
         */
        if (dev->netdev_ops) {
-               const struct net_device_ops *ops = dev->netdev_ops;
-
-               dev->init = ops->ndo_init;
-               dev->uninit = ops->ndo_uninit;
-               dev->open = ops->ndo_open;
-               dev->change_rx_flags = ops->ndo_change_rx_flags;
-               dev->set_rx_mode = ops->ndo_set_rx_mode;
-               dev->set_multicast_list = ops->ndo_set_multicast_list;
-               dev->set_mac_address = ops->ndo_set_mac_address;
-               dev->validate_addr = ops->ndo_validate_addr;
-               dev->do_ioctl = ops->ndo_do_ioctl;
-               dev->set_config = ops->ndo_set_config;
-               dev->change_mtu = ops->ndo_change_mtu;
-               dev->tx_timeout = ops->ndo_tx_timeout;
-               dev->get_stats = ops->ndo_get_stats;
-               dev->vlan_rx_register = ops->ndo_vlan_rx_register;
-               dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
-               dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-               dev->poll_controller = ops->ndo_poll_controller;
-#endif
+               netdev_resync_ops(dev);
        } else {
                char drivername[64];
                pr_info("%s (%s): not using net_device_ops yet\n",
@@ -5280,6 +5275,14 @@ out:
 
 subsys_initcall(net_dev_init);
 
+static int __init initialize_hashrnd(void)
+{
+       get_random_bytes(&skb_tx_hashrnd, sizeof(skb_tx_hashrnd));
+       return 0;
+}
+
+late_initcall_sync(initialize_hashrnd);
+
 EXPORT_SYMBOL(__dev_get_by_index);
 EXPORT_SYMBOL(__dev_get_by_name);
 EXPORT_SYMBOL(__dev_remove_pack);