Merge branch 'master' of git://1984.lsi.us.es/net-2.6
[pandora-kernel.git] / net / core / dev.c
index 4cd3e84..a3ef808 100644 (file)
@@ -1732,33 +1732,6 @@ 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_V4_CSUM) &&
-                protocol == htons(ETH_P_IP)) ||
-               ((features & NETIF_F_V6_CSUM) &&
-                protocol == htons(ETH_P_IPV6)) ||
-               ((features & NETIF_F_FCOE_CRC) &&
-                protocol == htons(ETH_P_FCOE)));
-}
-
-static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
-{
-       __be16 protocol = skb->protocol;
-       int features = dev->features;
-
-       if (vlan_tx_tag_present(skb)) {
-               features &= dev->vlan_features;
-       } else if (protocol == htons(ETH_P_8021Q)) {
-               struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
-               protocol = veh->h_vlan_encapsulated_proto;
-               features &= dev->vlan_features;
-       }
-
-       return can_checksum_protocol(features, protocol);
-}
-
 /**
  * skb_dev_set -- assign a new device to a buffer
  * @skb: buffer for the new device
@@ -2015,6 +1988,17 @@ static inline void skb_orphan_try(struct sk_buff *skb)
        }
 }
 
+static bool can_checksum_protocol(unsigned long features, __be16 protocol)
+{
+       return ((features & NETIF_F_GEN_CSUM) ||
+               ((features & NETIF_F_V4_CSUM) &&
+                protocol == htons(ETH_P_IP)) ||
+               ((features & NETIF_F_V6_CSUM) &&
+                protocol == htons(ETH_P_IPV6)) ||
+               ((features & NETIF_F_FCOE_CRC) &&
+                protocol == htons(ETH_P_FCOE)));
+}
+
 static int harmonize_features(struct sk_buff *skb, __be16 protocol, int features)
 {
        if (!can_checksum_protocol(protocol, features)) {
@@ -2059,22 +2043,13 @@ EXPORT_SYMBOL(netif_skb_features);
  *        support DMA from it.
  */
 static inline int skb_needs_linearize(struct sk_buff *skb,
-                                     struct net_device *dev)
+                                     int features)
 {
-       if (skb_is_nonlinear(skb)) {
-               int features = dev->features;
-
-               if (vlan_tx_tag_present(skb))
-                       features &= dev->vlan_features;
-
-               return (skb_has_frag_list(skb) &&
-                       !(features & NETIF_F_FRAGLIST)) ||
+       return skb_is_nonlinear(skb) &&
+                       ((skb_has_frag_list(skb) &&
+                               !(features & NETIF_F_FRAGLIST)) ||
                        (skb_shinfo(skb)->nr_frags &&
-                       (!(features & NETIF_F_SG) ||
-                       illegal_highdma(dev, skb)));
-       }
-
-       return 0;
+                               !(features & NETIF_F_SG)));
 }
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
@@ -2115,7 +2090,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        if (skb->next)
                                goto gso;
                } else {
-                       if (skb_needs_linearize(skb, dev) &&
+                       if (skb_needs_linearize(skb, features) &&
                            __skb_linearize(skb))
                                goto out_kfree_skb;
 
@@ -2126,7 +2101,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                                skb_set_transport_header(skb,
                                        skb_checksum_start_offset(skb));
-                               if (!dev_can_checksum(dev, skb) &&
+                               if (!(features & NETIF_F_ALL_CSUM) &&
                                     skb_checksum_help(skb))
                                        goto out_kfree_skb;
                        }
@@ -2322,7 +2297,10 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
                 */
                if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE))
                        skb_dst_force(skb);
-               __qdisc_update_bstats(q, skb->len);
+
+               qdisc_skb_cb(skb)->pkt_len = skb->len;
+               qdisc_bstats_update(q, skb);
+
                if (sch_direct_xmit(skb, q, dev, txq, root_lock)) {
                        if (unlikely(contended)) {
                                spin_unlock(&q->busylock);
@@ -5642,18 +5620,20 @@ struct netdev_queue *dev_ingress_queue_create(struct net_device *dev)
 }
 
 /**
- *     alloc_netdev_mq - allocate network device
+ *     alloc_netdev_mqs - allocate network device
  *     @sizeof_priv:   size of private data to allocate space for
  *     @name:          device name format string
  *     @setup:         callback to initialize device
- *     @queue_count:   the number of subqueues to allocate
+ *     @txqs:          the number of TX subqueues to allocate
+ *     @rxqs:          the number of RX subqueues to allocate
  *
  *     Allocates a struct net_device with private data area for driver use
  *     and performs basic initialization.  Also allocates subquue structs
- *     for each queue on the device at the end of the netdevice.
+ *     for each queue on the device.
  */
-struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
-               void (*setup)(struct net_device *), unsigned int queue_count)
+struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
+               void (*setup)(struct net_device *),
+               unsigned int txqs, unsigned int rxqs)
 {
        struct net_device *dev;
        size_t alloc_size;
@@ -5661,12 +5641,20 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
 
        BUG_ON(strlen(name) >= sizeof(dev->name));
 
-       if (queue_count < 1) {
+       if (txqs < 1) {
                pr_err("alloc_netdev: Unable to allocate device "
                       "with zero queues.\n");
                return NULL;
        }
 
+#ifdef CONFIG_RPS
+       if (rxqs < 1) {
+               pr_err("alloc_netdev: Unable to allocate device "
+                      "with zero RX queues.\n");
+               return NULL;
+       }
+#endif
+
        alloc_size = sizeof(struct net_device);
        if (sizeof_priv) {
                /* ensure 32-byte alignment of private area */
@@ -5697,14 +5685,14 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
 
        dev_net_set(dev, &init_net);
 
-       dev->num_tx_queues = queue_count;
-       dev->real_num_tx_queues = queue_count;
+       dev->num_tx_queues = txqs;
+       dev->real_num_tx_queues = txqs;
        if (netif_alloc_netdev_queues(dev))
                goto free_pcpu;
 
 #ifdef CONFIG_RPS
-       dev->num_rx_queues = queue_count;
-       dev->real_num_rx_queues = queue_count;
+       dev->num_rx_queues = rxqs;
+       dev->real_num_rx_queues = rxqs;
        if (netif_alloc_rx_queues(dev))
                goto free_pcpu;
 #endif
@@ -5732,7 +5720,7 @@ free_p:
        kfree(p);
        return NULL;
 }
-EXPORT_SYMBOL(alloc_netdev_mq);
+EXPORT_SYMBOL(alloc_netdev_mqs);
 
 /**
  *     free_netdev - free network device