]> xenbits.xensource.com Git - people/ssmith/nc2-2.6.27.bak/.git/commitdiff
patch netback-watch-csum-offload
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Thu, 28 May 2009 10:54:20 +0000 (11:54 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Thu, 28 May 2009 10:54:20 +0000 (11:54 +0100)
drivers/xen/netback/common.h
drivers/xen/netback/interface.c
drivers/xen/netback/xenbus.c

index c9ff79113c0a8c1b3207148d74b58bb4982589e4..faa527fab8f887fcbd52b6a15867d40ad547530d 100644 (file)
@@ -55,6 +55,8 @@
 #define WPRINTK(fmt, args...)                          \
        printk(KERN_WARNING "xen_net: " fmt, ##args)
 
+struct backend_info;
+
 typedef struct netif_st {
        /* Unique identifier for this interface. */
        domid_t          domid;
@@ -103,6 +105,7 @@ typedef struct netif_st {
        atomic_t         refcnt;
        struct net_device *dev;
        struct net_device_stats stats;
+       struct backend_info *be;
 
        unsigned int carrier;
 
@@ -147,6 +150,9 @@ struct backend_info {
        struct xenbus_device *dev;
        netif_t *netif;
        enum xenbus_state frontend_state;
+       struct xenbus_watch csum_offload_watch;
+       int have_csum_offload:1;
+       int have_csum_offload_watch:1;
 
        /* State relating to the netback accelerator */
        void *netback_accel_priv;
@@ -206,6 +212,8 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev);
 struct net_device_stats *netif_be_get_stats(struct net_device *dev);
 irqreturn_t netif_be_int(int irq, void *dev_id);
 
+void netif_set_tx_csum(struct backend_info *, u32);
+
 static inline int netbk_can_queue(struct net_device *dev)
 {
        netif_t *netif = netdev_priv(dev);
index 215eb28ccb45f5fbc467cb8e2c7d563b463fc290..f206e0b4be372786f8c85d25aabcf74413314fa8 100644 (file)
@@ -116,6 +116,13 @@ static int netbk_set_tso(struct net_device *dev, u32 data)
        return ethtool_op_set_tso(dev, data);
 }
 
+static int netbk_set_tx_csum(struct net_device *dev, u32 data)
+{
+       netif_t *netif = netdev_priv(dev);
+       netif_set_tx_csum(netif->be, data);
+       return ethtool_op_set_tx_csum(dev, data);
+}
+
 static void netbk_get_drvinfo(struct net_device *dev,
                              struct ethtool_drvinfo *info)
 {
@@ -163,7 +170,7 @@ static struct ethtool_ops network_ethtool_ops =
        .get_drvinfo = netbk_get_drvinfo,
 
        .get_tx_csum = ethtool_op_get_tx_csum,
-       .set_tx_csum = ethtool_op_set_tx_csum,
+       .set_tx_csum = netbk_set_tx_csum,
        .get_sg = ethtool_op_get_sg,
        .set_sg = netbk_set_sg,
        .get_tso = ethtool_op_get_tso,
index 05af01bb5bac0d190cfb22430998da3194ead53c..1bb9140b64721648502b70334ff0390d2ff0a91d 100644 (file)
@@ -32,6 +32,8 @@
 static int connect_rings(struct backend_info *);
 static void connect(struct backend_info *);
 static void backend_create_netif(struct backend_info *be);
+static int register_csum_offload_watch(struct backend_info *be);
+static void unregister_csum_offload_watch(struct backend_info *be);
 
 static int netback_remove(struct xenbus_device *dev)
 {
@@ -39,6 +41,7 @@ static int netback_remove(struct xenbus_device *dev)
 
        netback_remove_accelerators(be, dev);
 
+       unregister_csum_offload_watch(be);
        if (be->netif) {
                kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
                netif_disconnect(be->netif);
@@ -72,6 +75,8 @@ static int netback_probe(struct xenbus_device *dev,
        be->dev = dev;
        dev->dev.driver_data = be;
 
+       be->have_csum_offload = 1;
+
        sg = 1;
        if (netbk_copy_skb_mode == NETBK_ALWAYS_COPY_SKB)
                sg = 0;
@@ -214,6 +219,7 @@ static void backend_create_netif(struct backend_info *be)
                xenbus_dev_fatal(dev, err, "creating interface");
                return;
        }
+       be->netif->be = be;
        SET_NETDEV_DEV(be->netif->dev, &dev->dev);
 
        kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
@@ -225,6 +231,7 @@ static void disconnect_backend(struct xenbus_device *dev)
        struct backend_info *be = dev->dev.driver_data;
 
        if (be->netif) {
+               unregister_csum_offload_watch(be);
                netif_disconnect(be->netif);
                be->netif = NULL;
        }
@@ -369,6 +376,66 @@ static void connect(struct backend_info *be)
        netif_wake_queue(be->netif->dev);
 }
 
+static void feature_csum_offload_changed(struct xenbus_watch *watch,
+                                        const char **vec,
+                                        unsigned int vec_size)
+{
+       int val;
+       struct backend_info *be = container_of(watch,
+                                              struct backend_info,
+                                              csum_offload_watch);
+
+       if (xenbus_scanf(XBT_NIL, be->dev->otherend, "feature-no-csum-offload",
+                        "%d", &val) < 0)
+               val = 0;
+
+       if (val) {
+               be->netif->features &= ~NETIF_F_IP_CSUM;
+               be->netif->dev->features &= ~NETIF_F_IP_CSUM;
+       } else {
+               be->netif->features |= NETIF_F_IP_CSUM;
+               be->netif->dev->features |= NETIF_F_IP_CSUM;
+       }
+}
+static int register_csum_offload_watch(struct backend_info *be)
+{
+       struct xenbus_device *dev = be->dev;
+       int err;
+
+       if (!be->have_csum_offload || be->have_csum_offload_watch)
+               return 0;
+
+       err = xenbus_watch_path2(dev, dev->otherend, "feature-no-csum-offload",
+                                &be->csum_offload_watch,
+                                feature_csum_offload_changed);
+       if (err) {
+               xenbus_dev_fatal(dev, err,
+                                "watching %s/feature-no-csum-offload",
+                                dev->otherend);
+               return err;
+       }
+       be->have_csum_offload_watch = 1;
+       return 0;
+
+}
+
+static void unregister_csum_offload_watch(struct backend_info *be)
+{
+       if (be->have_csum_offload_watch) {
+               unregister_xenbus_watch(&be->csum_offload_watch);
+               kfree(be->csum_offload_watch.node);
+       }
+       be->have_csum_offload_watch = 0;
+}
+
+void netif_set_tx_csum(struct backend_info *be, u32 data)
+{
+       be->have_csum_offload = data;
+       if (data)
+               register_csum_offload_watch(be);
+       else
+               unregister_csum_offload_watch(be);
+}
 
 static int connect_rings(struct backend_info *be)
 {
@@ -443,13 +510,10 @@ static int connect_rings(struct backend_info *be)
                be->netif->dev->features |= NETIF_F_TSO;
        }
 
-       if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
-                        "%d", &val) < 0)
-               val = 0;
-       if (val) {
-               be->netif->features &= ~NETIF_F_IP_CSUM;
-               be->netif->dev->features &= ~NETIF_F_IP_CSUM;
-       }
+       unregister_csum_offload_watch(be);
+       err = register_csum_offload_watch(be);
+       if (err)
+               return err;
 
        /* Map the shared frame, irq etc. */
        err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn);