From 81eec36e0200a149f7e239b717cdf93378f6107a Mon Sep 17 00:00:00 2001
From: Ben Pfaff <blp@nicira.com>
Date: Wed, 13 Jan 2010 10:43:31 -0800
Subject: [PATCH] datapath: Disable preemption updating per-CPU data in
 dp_dev_recv().

dp_dev_recv() is called from do_output(), which can be called from
execute_actions(), which can be called from process context with
preemption enabled, so it needs to disabled preemption before it can
access per-CPU data.

Build tested on a few different kernels.

Bug #2316.

Reported-by: John Galgay <john@galgay.net>
CC: Dan Wendlandt <dan@nicira.com>
---
 datapath/dp_dev.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/datapath/dp_dev.c b/datapath/dp_dev.c
index 284a6b52..5b434c1f 100644
--- a/datapath/dp_dev.c
+++ b/datapath/dp_dev.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  * Distributed under the terms of the GNU GPL version 2.
  *
  * Significant portions of this file may be copied from parts of the Linux
@@ -10,6 +10,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
+#include <linux/preempt.h>
 #include <linux/rcupdate.h>
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
@@ -62,9 +63,13 @@ int dp_dev_recv(struct net_device *netdev, struct sk_buff *skb)
 	else
 		netif_rx_ni(skb);
 	netdev->last_rx = jiffies;
+
+	preempt_disable();
 	lb_stats = per_cpu_ptr(dp_dev->lstats, smp_processor_id());
 	lb_stats->rx_packets++;
 	lb_stats->rx_bytes += len;
+	preempt_enable();
+
 	return len;
 }
 
-- 
2.30.2