diff options
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index f1df942072bb..5bd90a7eb763 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -156,9 +156,9 @@ static inline void lpar_qirr_info(int n_cpu , u8 value) | |||
156 | 156 | ||
157 | 157 | ||
158 | #ifdef CONFIG_SMP | 158 | #ifdef CONFIG_SMP |
159 | static int get_irq_server(unsigned int virq) | 159 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
160 | { | 160 | { |
161 | unsigned int server; | 161 | int server; |
162 | /* For the moment only implement delivery to all cpus or one cpu */ | 162 | /* For the moment only implement delivery to all cpus or one cpu */ |
163 | cpumask_t cpumask = irq_desc[virq].affinity; | 163 | cpumask_t cpumask = irq_desc[virq].affinity; |
164 | cpumask_t tmp = CPU_MASK_NONE; | 164 | cpumask_t tmp = CPU_MASK_NONE; |
@@ -166,22 +166,25 @@ static int get_irq_server(unsigned int virq) | |||
166 | if (!distribute_irqs) | 166 | if (!distribute_irqs) |
167 | return default_server; | 167 | return default_server; |
168 | 168 | ||
169 | if (cpus_equal(cpumask, CPU_MASK_ALL)) { | 169 | if (!cpus_equal(cpumask, CPU_MASK_ALL)) { |
170 | server = default_distrib_server; | ||
171 | } else { | ||
172 | cpus_and(tmp, cpu_online_map, cpumask); | 170 | cpus_and(tmp, cpu_online_map, cpumask); |
173 | 171 | ||
174 | if (cpus_empty(tmp)) | 172 | server = first_cpu(tmp); |
175 | server = default_distrib_server; | 173 | |
176 | else | 174 | if (server < NR_CPUS) |
177 | server = get_hard_smp_processor_id(first_cpu(tmp)); | 175 | return get_hard_smp_processor_id(server); |
176 | |||
177 | if (strict_check) | ||
178 | return -1; | ||
178 | } | 179 | } |
179 | 180 | ||
180 | return server; | 181 | if (cpus_equal(cpu_online_map, cpu_present_map)) |
182 | return default_distrib_server; | ||
181 | 183 | ||
184 | return default_server; | ||
182 | } | 185 | } |
183 | #else | 186 | #else |
184 | static int get_irq_server(unsigned int virq) | 187 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
185 | { | 188 | { |
186 | return default_server; | 189 | return default_server; |
187 | } | 190 | } |
@@ -192,7 +195,7 @@ static void xics_unmask_irq(unsigned int virq) | |||
192 | { | 195 | { |
193 | unsigned int irq; | 196 | unsigned int irq; |
194 | int call_status; | 197 | int call_status; |
195 | unsigned int server; | 198 | int server; |
196 | 199 | ||
197 | pr_debug("xics: unmask virq %d\n", virq); | 200 | pr_debug("xics: unmask virq %d\n", virq); |
198 | 201 | ||
@@ -201,7 +204,7 @@ static void xics_unmask_irq(unsigned int virq) | |||
201 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 204 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
202 | return; | 205 | return; |
203 | 206 | ||
204 | server = get_irq_server(virq); | 207 | server = get_irq_server(virq, 0); |
205 | 208 | ||
206 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, | 209 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, |
207 | DEFAULT_PRIORITY); | 210 | DEFAULT_PRIORITY); |
@@ -398,8 +401,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
398 | unsigned int irq; | 401 | unsigned int irq; |
399 | int status; | 402 | int status; |
400 | int xics_status[2]; | 403 | int xics_status[2]; |
401 | unsigned long newmask; | 404 | int irq_server; |
402 | cpumask_t tmp = CPU_MASK_NONE; | ||
403 | 405 | ||
404 | irq = (unsigned int)irq_map[virq].hwirq; | 406 | irq = (unsigned int)irq_map[virq].hwirq; |
405 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 407 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
@@ -413,18 +415,21 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
413 | return; | 415 | return; |
414 | } | 416 | } |
415 | 417 | ||
416 | /* For the moment only implement delivery to all cpus or one cpu */ | 418 | /* |
417 | if (cpus_equal(cpumask, CPU_MASK_ALL)) { | 419 | * For the moment only implement delivery to all cpus or one cpu. |
418 | newmask = default_distrib_server; | 420 | * Get current irq_server for the given irq |
419 | } else { | 421 | */ |
420 | cpus_and(tmp, cpu_online_map, cpumask); | 422 | irq_server = get_irq_server(irq, 1); |
421 | if (cpus_empty(tmp)) | 423 | if (irq_server == -1) { |
422 | return; | 424 | char cpulist[128]; |
423 | newmask = get_hard_smp_processor_id(first_cpu(tmp)); | 425 | cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); |
426 | printk(KERN_WARNING "xics_set_affinity: No online cpus in " | ||
427 | "the mask %s for irq %d\n", cpulist, virq); | ||
428 | return; | ||
424 | } | 429 | } |
425 | 430 | ||
426 | status = rtas_call(ibm_set_xive, 3, 1, NULL, | 431 | status = rtas_call(ibm_set_xive, 3, 1, NULL, |
427 | irq, newmask, xics_status[1]); | 432 | irq, irq_server, xics_status[1]); |
428 | 433 | ||
429 | if (status) { | 434 | if (status) { |
430 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " | 435 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " |