blob: 52980cdd34417709a1aa479674c264ad11b2c516 [file] [log] [blame]
From 6021f45632642d281a50b16a33c4a4563367b49c Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Fri, 3 Jul 2009 08:29:30 -0500
Subject: [PATCH] drivers/net: Make loopback_xmit -rt safe
commit cc78f78d74928e7752e70fdfc16e30b8e97a91b7 in tip.
commit 58f539740b ([NET]: Can use __get_cpu_var() instead of per_cpu()
in loopback driver.) breaks on preempt-rt.
Use get_cpu() if -rt is enabled.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 72b7949..377144f 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -65,6 +65,14 @@ struct pcpu_lstats {
unsigned long drops;
};
+#ifdef CONFIG_PREEMPT_RT
+# define xmit_get_cpu() get_cpu()
+# define xmit_put_cpu() put_cpu()
+#else
+# define xmit_get_cpu() smp_processor_id()
+# define xmit_put_cpu() do { } while (0)
+#endif
+
/*
* The higher levels take care of making this non-reentrant (it's
* called with bh's disabled).
@@ -74,23 +82,24 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
{
struct pcpu_lstats __percpu *pcpu_lstats;
struct pcpu_lstats *lb_stats;
- int len;
+ int len, res;
skb_orphan(skb);
skb->protocol = eth_type_trans(skb, dev);
+ len = skb->len;
+ res = netif_rx(skb);
- /* it's OK to use per_cpu_ptr() because BHs are off */
pcpu_lstats = (void __percpu __force *)dev->ml_priv;
- lb_stats = this_cpu_ptr(pcpu_lstats);
+ lb_stats = per_cpu_ptr(pcpu_lstats, xmit_get_cpu());
- len = skb->len;
- if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
+ if (likely(res == NET_RX_SUCCESS)) {
lb_stats->bytes += len;
lb_stats->packets++;
} else
lb_stats->drops++;
+ xmit_put_cpu();
return NETDEV_TX_OK;
}
--
1.7.1.1