vhost-net: switch to smp barriers
[safe/jmp/linux-2.6] / drivers / net / xen-netfront.c
index b4de126..a869b45 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/mm.h>
 #include <net/ip.h>
 
+#include <xen/xen.h>
 #include <xen/xenbus.h>
 #include <xen/events.h>
 #include <xen/page.h>
@@ -51,7 +52,7 @@
 #include <xen/interface/memory.h>
 #include <xen/interface/grant_table.h>
 
-static struct ethtool_ops xennet_ethtool_ops;
+static const struct ethtool_ops xennet_ethtool_ops;
 
 struct netfront_cb {
        struct page *page;
@@ -73,24 +74,13 @@ struct netfront_info {
        struct net_device *netdev;
 
        struct napi_struct napi;
-       struct net_device_stats stats;
-
-       struct xen_netif_tx_front_ring tx;
-       struct xen_netif_rx_front_ring rx;
-
-       spinlock_t   tx_lock;
-       spinlock_t   rx_lock;
 
        unsigned int evtchn;
+       struct xenbus_device *xbdev;
 
-       /* Receive-ring batched refills. */
-#define RX_MIN_TARGET 8
-#define RX_DFL_MIN_TARGET 64
-#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
-       unsigned rx_min_target, rx_max_target, rx_target;
-       struct sk_buff_head rx_batch;
-
-       struct timer_list rx_refill_timer;
+       spinlock_t   tx_lock;
+       struct xen_netif_tx_front_ring tx;
+       int tx_ring_ref;
 
        /*
         * {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries
@@ -103,20 +93,29 @@ struct netfront_info {
         */
        union skb_entry {
                struct sk_buff *skb;
-               unsigned link;
+               unsigned long link;
        } tx_skbs[NET_TX_RING_SIZE];
        grant_ref_t gref_tx_head;
        grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
        unsigned tx_skb_freelist;
 
+       spinlock_t   rx_lock ____cacheline_aligned_in_smp;
+       struct xen_netif_rx_front_ring rx;
+       int rx_ring_ref;
+
+       /* Receive-ring batched refills. */
+#define RX_MIN_TARGET 8
+#define RX_DFL_MIN_TARGET 64
+#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+       unsigned rx_min_target, rx_max_target, rx_target;
+       struct sk_buff_head rx_batch;
+
+       struct timer_list rx_refill_timer;
+
        struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
        grant_ref_t gref_rx_head;
        grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
 
-       struct xenbus_device *xbdev;
-       int tx_ring_ref;
-       int rx_ring_ref;
-
        unsigned long rx_pfn_array[NET_RX_RING_SIZE];
        struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
        struct mmu_update rx_mmu[NET_RX_RING_SIZE];
@@ -127,6 +126,17 @@ struct netfront_rx_info {
        struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
 };
 
+static void skb_entry_set_link(union skb_entry *list, unsigned short id)
+{
+       list->link = id;
+}
+
+static int skb_entry_is_link(const union skb_entry *list)
+{
+       BUILD_BUG_ON(sizeof(list->skb) != sizeof(list->link));
+       return ((unsigned long)list->skb < PAGE_OFFSET);
+}
+
 /*
  * Access macros for acquiring freeing slots in tx_skbs[].
  */
@@ -134,7 +144,7 @@ struct netfront_rx_info {
 static void add_id_to_freelist(unsigned *head, union skb_entry *list,
                               unsigned short id)
 {
-       list[id].link = *head;
+       skb_entry_set_link(&list[id], *head);
        *head = id;
 }
 
@@ -187,7 +197,7 @@ static void rx_refill_timeout(unsigned long data)
 {
        struct net_device *dev = (struct net_device *)data;
        struct netfront_info *np = netdev_priv(dev);
-       netif_rx_schedule(dev, &np->napi);
+       napi_schedule(&np->napi);
 }
 
 static int netfront_tx_slot_available(struct netfront_info *np)
@@ -230,11 +240,14 @@ static void xennet_alloc_rx_buffers(struct net_device *dev)
         */
        batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
        for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
-               skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD,
+               skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD + NET_IP_ALIGN,
                                         GFP_ATOMIC | __GFP_NOWARN);
                if (unlikely(!skb))
                        goto no_skb;
 
+               /* Align ip header to a 16 bytes boundary */
+               skb_reserve(skb, NET_IP_ALIGN);
+
                page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
                if (!page) {
                        kfree_skb(skb);
@@ -309,8 +322,6 @@ static int xennet_open(struct net_device *dev)
 {
        struct netfront_info *np = netdev_priv(dev);
 
-       memset(&np->stats, 0, sizeof(np->stats));
-
        napi_enable(&np->napi);
 
        spin_lock_bh(&np->rx_lock);
@@ -318,11 +329,11 @@ static int xennet_open(struct net_device *dev)
                xennet_alloc_rx_buffers(dev);
                np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
                if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
-                       netif_rx_schedule(dev, &np->napi);
+                       napi_schedule(&np->napi);
        }
        spin_unlock_bh(&np->rx_lock);
 
-       xennet_maybe_wake_tx(dev);
+       netif_start_queue(dev);
 
        return 0;
 }
@@ -464,7 +475,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        unsigned int offset = offset_in_page(data);
        unsigned int len = skb_headlen(skb);
 
-       frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
+       frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
        if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
                printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
                       frags);
@@ -537,8 +548,8 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (notify)
                notify_remote_via_irq(np->netdev->irq);
 
-       np->stats.tx_bytes += skb->len;
-       np->stats.tx_packets++;
+       dev->stats.tx_bytes += skb->len;
+       dev->stats.tx_packets++;
 
        /* Note: It is not safe to access skb after xennet_tx_buf_gc()! */
        xennet_tx_buf_gc(dev);
@@ -548,12 +559,12 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        spin_unlock_irq(&np->tx_lock);
 
-       return 0;
+       return NETDEV_TX_OK;
 
  drop:
-       np->stats.tx_dropped++;
+       dev->stats.tx_dropped++;
        dev_kfree_skb(skb);
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static int xennet_close(struct net_device *dev)
@@ -564,12 +575,6 @@ static int xennet_close(struct net_device *dev)
        return 0;
 }
 
-static struct net_device_stats *xennet_get_stats(struct net_device *dev)
-{
-       struct netfront_info *np = netdev_priv(dev);
-       return &np->stats;
-}
-
 static void xennet_move_rx_slot(struct netfront_info *np, struct sk_buff *skb,
                                grant_ref_t ref)
 {
@@ -804,9 +809,8 @@ out:
 }
 
 static int handle_incoming_queue(struct net_device *dev,
-                                 struct sk_buff_head *rxq)
+                                struct sk_buff_head *rxq)
 {
-       struct netfront_info *np = netdev_priv(dev);
        int packets_dropped = 0;
        struct sk_buff *skb;
 
@@ -828,17 +832,16 @@ static int handle_incoming_queue(struct net_device *dev,
                        if (skb_checksum_setup(skb)) {
                                kfree_skb(skb);
                                packets_dropped++;
-                               np->stats.rx_errors++;
+                               dev->stats.rx_errors++;
                                continue;
                        }
                }
 
-               np->stats.rx_packets++;
-               np->stats.rx_bytes += skb->len;
+               dev->stats.rx_packets++;
+               dev->stats.rx_bytes += skb->len;
 
                /* Pass it up. */
                netif_receive_skb(skb);
-               dev->last_rx = jiffies;
        }
 
        return packets_dropped;
@@ -863,11 +866,6 @@ static int xennet_poll(struct napi_struct *napi, int budget)
 
        spin_lock(&np->rx_lock);
 
-       if (unlikely(!netif_carrier_ok(dev))) {
-               spin_unlock(&np->rx_lock);
-               return 0;
-       }
-
        skb_queue_head_init(&rxq);
        skb_queue_head_init(&errq);
        skb_queue_head_init(&tmpq);
@@ -887,7 +885,7 @@ static int xennet_poll(struct napi_struct *napi, int budget)
 err:
                        while ((skb = __skb_dequeue(&tmpq)))
                                __skb_queue_tail(&errq, skb);
-                       np->stats.rx_errors++;
+                       dev->stats.rx_errors++;
                        i = np->rx.rsp_cons;
                        continue;
                }
@@ -962,8 +960,7 @@ err:
                work_done++;
        }
 
-       while ((skb = __skb_dequeue(&errq)))
-               kfree_skb(skb);
+       __skb_queue_purge(&errq);
 
        work_done -= handle_incoming_queue(dev, &rxq);
 
@@ -983,7 +980,7 @@ err:
 
                RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do);
                if (!more_to_do)
-                       __netif_rx_complete(dev, napi);
+                       __napi_complete(napi);
 
                local_irq_restore(flags);
        }
@@ -1010,7 +1007,7 @@ static void xennet_release_tx_bufs(struct netfront_info *np)
 
        for (i = 0; i < NET_TX_RING_SIZE; i++) {
                /* Skip over entries which are actually freelist references */
-               if ((unsigned long)np->tx_skbs[i].skb < PAGE_OFFSET)
+               if (skb_entry_is_link(&np->tx_skbs[i]))
                        continue;
 
                skb = np->tx_skbs[i].skb;
@@ -1089,14 +1086,13 @@ static void xennet_release_rx_bufs(struct netfront_info *np)
                if (!xen_feature(XENFEAT_auto_translated_physmap)) {
                        /* Do all the remapping work and M2P updates. */
                        MULTI_mmu_update(mcl, np->rx_mmu, mmu - np->rx_mmu,
-                                        0, DOMID_SELF);
+                                        NULL, DOMID_SELF);
                        mcl++;
                        HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl);
                }
        }
 
-       while ((skb = __skb_dequeue(&free_list)) != NULL)
-               dev_kfree_skb(skb);
+       __skb_queue_purge(&free_list);
 
        spin_unlock_bh(&np->rx_lock);
 }
@@ -1110,6 +1106,16 @@ static void xennet_uninit(struct net_device *dev)
        gnttab_free_grant_references(np->gref_rx_head);
 }
 
+static const struct net_device_ops xennet_netdev_ops = {
+       .ndo_open            = xennet_open,
+       .ndo_uninit          = xennet_uninit,
+       .ndo_stop            = xennet_close,
+       .ndo_start_xmit      = xennet_start_xmit,
+       .ndo_change_mtu      = xennet_change_mtu,
+       .ndo_set_mac_address = eth_mac_addr,
+       .ndo_validate_addr   = eth_validate_addr,
+};
+
 static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev)
 {
        int i, err;
@@ -1141,7 +1147,7 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
        /* Initialise tx_skbs as a free chain containing every entry. */
        np->tx_skb_freelist = 0;
        for (i = 0; i < NET_TX_RING_SIZE; i++) {
-               np->tx_skbs[i].link = i+1;
+               skb_entry_set_link(&np->tx_skbs[i], i+1);
                np->grant_tx_ref[i] = GRANT_INVALID_REF;
        }
 
@@ -1166,17 +1172,12 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
                goto exit_free_tx;
        }
 
-       netdev->open            = xennet_open;
-       netdev->hard_start_xmit = xennet_start_xmit;
-       netdev->stop            = xennet_close;
-       netdev->get_stats       = xennet_get_stats;
+       netdev->netdev_ops      = &xennet_netdev_ops;
+
        netif_napi_add(netdev, &np->napi, xennet_poll, 64);
-       netdev->uninit          = xennet_uninit;
-       netdev->change_mtu      = xennet_change_mtu;
        netdev->features        = NETIF_F_IP_CSUM;
 
        SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops);
-       SET_MODULE_OWNER(netdev);
        SET_NETDEV_DEV(netdev, &dev->dev);
 
        np->netdev = netdev;
@@ -1212,7 +1213,7 @@ static int __devinit netfront_probe(struct xenbus_device *dev,
        }
 
        info = netdev_priv(netdev);
-       dev->dev.driver_data = info;
+       dev_set_drvdata(&dev->dev, info);
 
        err = register_netdev(info->netdev);
        if (err) {
@@ -1233,7 +1234,7 @@ static int __devinit netfront_probe(struct xenbus_device *dev,
 
  fail:
        free_netdev(netdev);
-       dev->dev.driver_data = NULL;
+       dev_set_drvdata(&dev->dev, NULL);
        return err;
 }
 
@@ -1275,7 +1276,7 @@ static void xennet_disconnect_backend(struct netfront_info *info)
  */
 static int netfront_resume(struct xenbus_device *dev)
 {
-       struct netfront_info *info = dev->dev.driver_data;
+       struct netfront_info *info = dev_get_drvdata(&dev->dev);
 
        dev_dbg(&dev->dev, "%s\n", dev->nodename);
 
@@ -1317,7 +1318,7 @@ static irqreturn_t xennet_interrupt(int irq, void *dev_id)
                xennet_tx_buf_gc(dev);
                /* Under tx_lock: protects access to rx shared-ring indexes. */
                if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
-                       netif_rx_schedule(dev, &np->napi);
+                       napi_schedule(&np->napi);
        }
 
        spin_unlock_irqrestore(&np->tx_lock, flags);
@@ -1344,7 +1345,7 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
                goto fail;
        }
 
-       txs = (struct xen_netif_tx_sring *)get_zeroed_page(GFP_KERNEL);
+       txs = (struct xen_netif_tx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
        if (!txs) {
                err = -ENOMEM;
                xenbus_dev_fatal(dev, err, "allocating tx ring page");
@@ -1360,7 +1361,7 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
        }
 
        info->tx_ring_ref = err;
-       rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_KERNEL);
+       rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
        if (!rxs) {
                err = -ENOMEM;
                xenbus_dev_fatal(dev, err, "allocating rx ring page");
@@ -1511,7 +1512,7 @@ static int xennet_set_tso(struct net_device *dev, u32 data)
 static void xennet_set_features(struct net_device *dev)
 {
        /* Turn off all GSO bits except ROBUST. */
-       dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1;
+       dev->features &= ~NETIF_F_GSO_MASK;
        dev->features |= NETIF_F_GSO_ROBUST;
        xennet_set_sg(dev, 0);
 
@@ -1539,7 +1540,7 @@ static int xennet_connect(struct net_device *dev)
 
        if (!feature_rx_copy) {
                dev_info(&dev->dev,
-                        "backend does not support copying recieve path");
+                        "backend does not support copying receive path\n");
                return -ENODEV;
        }
 
@@ -1600,7 +1601,7 @@ static int xennet_connect(struct net_device *dev)
 static void backend_changed(struct xenbus_device *dev,
                            enum xenbus_state backend_state)
 {
-       struct netfront_info *np = dev->dev.driver_data;
+       struct netfront_info *np = dev_get_drvdata(&dev->dev);
        struct net_device *netdev = np->netdev;
 
        dev_dbg(&dev->dev, "%s\n", xenbus_strstate(backend_state));
@@ -1627,13 +1628,10 @@ static void backend_changed(struct xenbus_device *dev,
        }
 }
 
-static struct ethtool_ops xennet_ethtool_ops =
+static const struct ethtool_ops xennet_ethtool_ops =
 {
-       .get_tx_csum = ethtool_op_get_tx_csum,
        .set_tx_csum = ethtool_op_set_tx_csum,
-       .get_sg = ethtool_op_get_sg,
        .set_sg = xennet_set_sg,
-       .get_tso = ethtool_op_get_tso,
        .set_tso = xennet_set_tso,
        .get_link = ethtool_op_get_link,
 };
@@ -1777,7 +1775,7 @@ static struct xenbus_device_id netfront_ids[] = {
 
 static int __devexit xennet_remove(struct xenbus_device *dev)
 {
-       struct netfront_info *info = dev->dev.driver_data;
+       struct netfront_info *info = dev_get_drvdata(&dev->dev);
 
        dev_dbg(&dev->dev, "%s\n", dev->nodename);
 
@@ -1794,7 +1792,7 @@ static int __devexit xennet_remove(struct xenbus_device *dev)
        return 0;
 }
 
-static struct xenbus_driver netfront = {
+static struct xenbus_driver netfront_driver = {
        .name = "vif",
        .owner = THIS_MODULE,
        .ids = netfront_ids,
@@ -1806,27 +1804,29 @@ static struct xenbus_driver netfront = {
 
 static int __init netif_init(void)
 {
-       if (!is_running_on_xen())
+       if (!xen_domain())
                return -ENODEV;
 
-       if (is_initial_xendomain())
+       if (xen_initial_domain())
                return 0;
 
        printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n");
 
-       return xenbus_register_frontend(&netfront);
+       return xenbus_register_frontend(&netfront_driver);
 }
 module_init(netif_init);
 
 
 static void __exit netif_exit(void)
 {
-       if (is_initial_xendomain())
+       if (xen_initial_domain())
                return;
 
-       return xenbus_unregister_driver(&netfront);
+       xenbus_unregister_driver(&netfront_driver);
 }
 module_exit(netif_exit);
 
 MODULE_DESCRIPTION("Xen virtual network device frontend");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("xen:vif");
+MODULE_ALIAS("xennet");