summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm63xx/patches-3.9/322-MIPS-BCM63XX-allow-setting-affinity-for-IPIC.patch
blob: c89a344ff9040d0b3830ac66ff1d91625b90ce59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
From 9e341df1f67c3c64dc5ac668a30bbb6b5ab5f2b4 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Fri, 26 Apr 2013 12:06:03 +0200
Subject: [PATCH 14/14] MIPS: BCM63XX: allow setting affinity for IPIC

Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
 arch/mips/bcm63xx/irq.c |   49 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 41 insertions(+), 8 deletions(-)

--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -24,8 +24,10 @@ static void __dispatch_internal_32(int c
 static void __dispatch_internal_64(int cpu) __maybe_unused;
 static void __internal_irq_mask_32(struct irq_data *d) __maybe_unused;
 static void __internal_irq_mask_64(struct irq_data *d) __maybe_unused;
-static void __internal_irq_unmask_32(struct irq_data *d) __maybe_unused;
-static void __internal_irq_unmask_64(struct irq_data *d) __maybe_unused;
+static void __internal_irq_unmask_32(struct irq_data *d,
+				     const struct cpumask *mask) __maybe_unused;
+static void __internal_irq_unmask_64(struct irq_data *d,
+				     const struct cpumask *mask) __maybe_unused;
 
 static DEFINE_SPINLOCK(ipic_lock);
 static DEFINE_SPINLOCK(epic_lock);
@@ -168,7 +170,7 @@ static unsigned int ext_irq_count;
 static unsigned int ext_irq_start, ext_irq_end;
 static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
 static void (*internal_irq_mask)(struct irq_data *d);
-static void (*internal_irq_unmask)(struct irq_data *d);
+static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
 
 static void bcm63xx_init_irq(void)
 {
@@ -311,6 +313,20 @@ static inline void handle_internal(int i
 		do_IRQ(intbit + IRQ_INTERNAL_BASE);
 }
 
+static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
+				     const struct cpumask *m)
+{
+	bool enable = cpu_online(cpu);
+#ifdef CONFIG_SMP
+
+	if (m)
+		enable &= cpu_isset(cpu, *m);
+	else if (irqd_affinity_was_set(d))
+		enable &= cpu_isset(cpu, *d->affinity);
+#endif
+	return enable;
+}
+
 /*
  * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
  * prioritize any interrupt relatively to another. the static counter
@@ -381,7 +397,8 @@ static void __internal_irq_mask_##width(
 	spin_unlock_irqrestore(&ipic_lock, flags);			\
 }									\
 									\
-static void __internal_irq_unmask_##width(struct irq_data *d)		\
+static void __internal_irq_unmask_##width(struct irq_data *d,		\
+					  const struct cpumask *m)	\
 { 									\
 	u32 val;							\
 	unsigned irq = d->irq - IRQ_INTERNAL_BASE;			\
@@ -398,7 +415,7 @@ static void __internal_irq_unmask_##widt
 			break;						\
 									\
 		val = bcm_readl(irq_mask_addr + reg * sizeof(u32));	\
-		if (cpu_online(cpu))					\
+		if (enable_irq_for_cpu(cpu, d, m))			\
 			val |= (1 << bit); 				\
 		else							\
 			val &= ~(1 << bit);				\
@@ -455,7 +472,7 @@ static void bcm63xx_internal_irq_mask(st
 
 static void bcm63xx_internal_irq_unmask(struct irq_data *d)
 {
-	internal_irq_unmask(d);
+	internal_irq_unmask(d, NULL);
 }
 
 /*
@@ -503,7 +520,8 @@ static void bcm63xx_external_irq_unmask(
 	spin_unlock_irqrestore(&epic_lock, flags);
 
 	if (is_ext_irq_cascaded)
-		internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start));
+		internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
+				    NULL);
 }
 
 static void bcm63xx_external_irq_clear(struct irq_data *d)
@@ -622,6 +640,18 @@ static int bcm63xx_external_irq_set_type
 	return IRQ_SET_MASK_OK_NOCOPY;
 }
 
+#ifdef CONFIG_SMP
+static int bcm63xx_internal_set_affinity(struct irq_data *data,
+					 const struct cpumask *dest,
+					 bool force)
+{
+	if (!irqd_irq_disabled(data))
+		internal_irq_unmask(data, dest);
+
+	return 0;
+}
+#endif
+
 static struct irq_chip bcm63xx_internal_irq_chip = {
 	.name		= "bcm63xx_ipic",
 	.irq_mask	= bcm63xx_internal_irq_mask,
@@ -679,7 +709,10 @@ void __init arch_init_irq(void)
 
 	setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
 #ifdef CONFIG_SMP
-	if (is_ext_irq_cascaded)
+	if (is_ext_irq_cascaded) {
 		setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
+		bcm63xx_internal_irq_chip.irq_set_affinity =
+			bcm63xx_internal_set_affinity;
+	}
 #endif
 }