aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-09-19 19:48:39 +0530
committerGary S. Robertson <gary.robertson@linaro.org>2013-10-24 09:37:02 -0500
commit5946d4b5ea5a009c712036a6ebcd540f40dd2cc4 (patch)
treec3addf79843084704692ca86ad7ed765e911460b
parent04cf4fc0d4a70bf75ac646f18c654cf019e96ef4 (diff)
datapath: Enable RT Kernel supportHEADmaster
I found these files where there can be some issues on RT kernel: - datapath/datapath.c - datapath/vport.c - datapath/linux/compat/workqueue.c Important calls here are (that doesn't fit well with RT are): - spin_lock_irq{save}() - spin_lock_bh() - local_bh_disable() 1- spin_lock_irq{save}() These are simply converted to spin_lock() in RT and so access to critical sections is guaranteed to be serialized.. And so nothing is required to be fixed for it.. 2- spin_lock_bh() It guarantees code to be serialized and hence shouldn't be a problem.. 2- local_bh_disable() This is how it is implemented: +void local_bh_disable(void) +{ + migrate_disable(); + current->softirq_nestcnt++; +} +EXPORT_SYMBOL(local_bh_disable); And here is the problem: Code currently using local_bh_disable() isn't guaranteed to be serialized and so that is required to be fixed. A simple solution would be to add a spin_lock_bh() for this case which will make it work (efficiently) for both RT and non-RT cases. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--datapath/actions.c5
-rw-r--r--datapath/datapath.c2
2 files changed, 5 insertions, 2 deletions
diff --git a/datapath/actions.c b/datapath/actions.c
index 30ea1d23..3550a00a 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -28,6 +28,7 @@
#include <linux/in6.h>
#include <linux/if_arp.h>
#include <linux/if_vlan.h>
+#include <linux/spinlock.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/checksum.h>
@@ -38,6 +39,8 @@
#include "vlan.h"
#include "vport.h"
+static DEFINE_SPINLOCK(action_lock);
+
static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
const struct nlattr *attr, int len, bool keep_skb);
@@ -600,6 +603,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb)
int error;
/* Check whether we've looped too much. */
+ spin_lock_bh(&action_lock);
loop = &__get_cpu_var(loop_counters);
if (unlikely(++loop->count > MAX_LOOPS))
loop->looping = true;
@@ -622,5 +626,6 @@ out_loop:
if (!--loop->count)
loop->looping = false;
+ spin_unlock_bh(&action_lock);
return error;
}
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 50ee6cd3..6b7298a6 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -528,9 +528,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
if (!dp)
goto err_unlock;
- local_bh_disable();
err = ovs_execute_actions(dp, packet);
- local_bh_enable();
rcu_read_unlock();
ovs_flow_free(flow, false);