xen-netback: make sure that hashes are not send to unaware frontends
[cascardo/linux.git] / drivers / net / xen-netback / interface.c
index 83deeeb..74dc2bf 100644 (file)
@@ -128,15 +128,6 @@ irqreturn_t xenvif_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-irqreturn_t xenvif_ctrl_interrupt(int irq, void *dev_id)
-{
-       struct xenvif *vif = dev_id;
-
-       wake_up(&vif->ctrl_wq);
-
-       return IRQ_HANDLED;
-}
-
 int xenvif_queue_stopped(struct xenvif_queue *queue)
 {
        struct net_device *dev = queue->vif->dev;
@@ -158,17 +149,8 @@ static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb,
        struct xenvif *vif = netdev_priv(dev);
        unsigned int size = vif->hash.size;
 
-       if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE) {
-               u16 index = fallback(dev, skb) % dev->real_num_tx_queues;
-
-               /* Make sure there is no hash information in the socket
-                * buffer otherwise it would be incorrectly forwarded
-                * to the frontend.
-                */
-               skb_clear_hash(skb);
-
-               return index;
-       }
+       if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
+               return fallback(dev, skb) % dev->real_num_tx_queues;
 
        xenvif_set_skb_hash(vif, skb);
 
@@ -217,6 +199,13 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
        cb = XENVIF_RX_CB(skb);
        cb->expires = jiffies + vif->drain_timeout;
 
+       /* If there is no hash algorithm configured then make sure there
+        * is no hash information in the socket buffer otherwise it
+        * would be incorrectly forwarded to the frontend.
+        */
+       if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
+               skb_clear_hash(skb);
+
        xenvif_rx_queue_tail(queue, skb);
        xenvif_kick_thread(queue);
 
@@ -328,9 +317,9 @@ static netdev_features_t xenvif_fix_features(struct net_device *dev,
 
        if (!vif->can_sg)
                features &= ~NETIF_F_SG;
-       if (~(vif->gso_mask | vif->gso_prefix_mask) & GSO_BIT(TCPV4))
+       if (~(vif->gso_mask) & GSO_BIT(TCPV4))
                features &= ~NETIF_F_TSO;
-       if (~(vif->gso_mask | vif->gso_prefix_mask) & GSO_BIT(TCPV6))
+       if (~(vif->gso_mask) & GSO_BIT(TCPV6))
                features &= ~NETIF_F_TSO6;
        if (!vif->ip_csum)
                features &= ~NETIF_F_IP_CSUM;
@@ -476,7 +465,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
        dev->netdev_ops = &xenvif_netdev_ops;
        dev->hw_features = NETIF_F_SG |
                NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-               NETIF_F_TSO | NETIF_F_TSO6;
+               NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_FRAGLIST;
        dev->features = dev->hw_features | NETIF_F_RXCSUM;
        dev->ethtool_ops = &xenvif_ethtool_ops;
 
@@ -570,8 +559,7 @@ int xenvif_connect_ctrl(struct xenvif *vif, grant_ref_t ring_ref,
        struct net_device *dev = vif->dev;
        void *addr;
        struct xen_netif_ctrl_sring *shared;
-       struct task_struct *task;
-       int err = -ENOMEM;
+       int err;
 
        err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif),
                                     &ring_ref, 1, &addr);
@@ -581,11 +569,7 @@ int xenvif_connect_ctrl(struct xenvif *vif, grant_ref_t ring_ref,
        shared = (struct xen_netif_ctrl_sring *)addr;
        BACK_RING_INIT(&vif->ctrl, shared, XEN_PAGE_SIZE);
 
-       init_waitqueue_head(&vif->ctrl_wq);
-
-       err = bind_interdomain_evtchn_to_irqhandler(vif->domid, evtchn,
-                                                   xenvif_ctrl_interrupt,
-                                                   0, dev->name, vif);
+       err = bind_interdomain_evtchn_to_irq(vif->domid, evtchn);
        if (err < 0)
                goto err_unmap;
 
@@ -593,19 +577,13 @@ int xenvif_connect_ctrl(struct xenvif *vif, grant_ref_t ring_ref,
 
        xenvif_init_hash(vif);
 
-       task = kthread_create(xenvif_ctrl_kthread, (void *)vif,
-                             "%s-control", dev->name);
-       if (IS_ERR(task)) {
-               pr_warn("Could not allocate kthread for %s\n", dev->name);
-               err = PTR_ERR(task);
+       err = request_threaded_irq(vif->ctrl_irq, NULL, xenvif_ctrl_irq_fn,
+                                  IRQF_ONESHOT, "xen-netback-ctrl", vif);
+       if (err) {
+               pr_warn("Could not setup irq handler for %s\n", dev->name);
                goto err_deinit;
        }
 
-       get_task_struct(task);
-       vif->ctrl_task = task;
-
-       wake_up_process(vif->ctrl_task);
-
        return 0;
 
 err_deinit:
@@ -774,12 +752,6 @@ void xenvif_disconnect_data(struct xenvif *vif)
 
 void xenvif_disconnect_ctrl(struct xenvif *vif)
 {
-       if (vif->ctrl_task) {
-               kthread_stop(vif->ctrl_task);
-               put_task_struct(vif->ctrl_task);
-               vif->ctrl_task = NULL;
-       }
-
        if (vif->ctrl_irq) {
                xenvif_deinit_hash(vif);
                unbind_from_irqhandler(vif->ctrl_irq, vif);