Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/cell: Use common smp ipi actions

The cell iic interrupt controller has enough software caused interrupts
to use a unique interrupt for each of the 4 messages powerpc uses.
This means each interrupt gets its own irq action/data combination.

Use the seperate, optimized, arch common ipi action functions
registered via the helper smp_request_message_ipi instead passing the
message as action data to a single action that then demultipexes to
the required acton via a switch statement.

smp_request_message_ipi will register the action as IRQF_PER_CPU
and IRQF_DISABLED, and WARN if the allocation fails for some reason,
so no need to print on that failure. It will return positive if
the message will not be used by the kernel, in which case we can
free the virq.

In addition to elimiating inefficient code, this also corrects the
error that a kernel built with kexec but without a debugger would
not register the ipi for kdump to notify the other cpus of a crash.

This also restores the debugger action to be static to kernel/smp.c.

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Milton Miller and committed by
Benjamin Herrenschmidt
7ef71d75 ce2a4045

+14 -35
-2
arch/powerpc/include/asm/smp.h
··· 191 191 extern unsigned long __secondary_hold_acknowledge; 192 192 extern char __secondary_hold; 193 193 194 - extern irqreturn_t debug_ipi_action(int irq, void *data); 195 - 196 194 #endif /* __ASSEMBLY__ */ 197 195 198 196 #endif /* __KERNEL__ */
+1 -1
arch/powerpc/kernel/smp.c
··· 129 129 return IRQ_HANDLED; 130 130 } 131 131 132 - irqreturn_t debug_ipi_action(int irq, void *data) 132 + static irqreturn_t debug_ipi_action(int irq, void *data) 133 133 { 134 134 if (crash_ipi_function_ptr) { 135 135 crash_ipi_function_ptr(get_irq_regs());
+13 -32
arch/powerpc/platforms/cell/interrupt.c
··· 192 192 } 193 193 EXPORT_SYMBOL_GPL(iic_get_irq_host); 194 194 195 - static irqreturn_t iic_ipi_action(int irq, void *dev_id) 196 - { 197 - int ipi = (int)(long)dev_id; 198 - 199 - switch(ipi) { 200 - case PPC_MSG_CALL_FUNCTION: 201 - generic_smp_call_function_interrupt(); 202 - break; 203 - case PPC_MSG_RESCHEDULE: 204 - scheduler_ipi(); 205 - break; 206 - case PPC_MSG_CALL_FUNC_SINGLE: 207 - generic_smp_call_function_single_interrupt(); 208 - break; 209 - case PPC_MSG_DEBUGGER_BREAK: 210 - debug_ipi_action(0, NULL); 211 - break; 212 - } 213 - return IRQ_HANDLED; 214 - } 215 - static void iic_request_ipi(int ipi, const char *name) 195 + static void iic_request_ipi(int ipi) 216 196 { 217 197 int virq; 218 198 219 199 virq = irq_create_mapping(iic_host, iic_ipi_to_irq(ipi)); 220 200 if (virq == NO_IRQ) { 221 201 printk(KERN_ERR 222 - "iic: failed to map IPI %s\n", name); 202 + "iic: failed to map IPI %s\n", smp_ipi_name[ipi]); 223 203 return; 224 204 } 225 - if (request_irq(virq, iic_ipi_action, IRQF_DISABLED, name, 226 - (void *)(long)ipi)) 227 - printk(KERN_ERR 228 - "iic: failed to request IPI %s\n", name); 205 + 206 + /* 207 + * If smp_request_message_ipi encounters an error it will notify 208 + * the error. If a message is not needed it will return non-zero. 209 + */ 210 + if (smp_request_message_ipi(virq, ipi)) 211 + irq_dispose_mapping(virq); 229 212 } 230 213 231 214 void iic_request_IPIs(void) 232 215 { 233 - iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call"); 234 - iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched"); 235 - iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE, "IPI-call-single"); 236 - #ifdef CONFIG_DEBUGGER 237 - iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); 238 - #endif /* CONFIG_DEBUGGER */ 216 + iic_request_ipi(PPC_MSG_CALL_FUNCTION); 217 + iic_request_ipi(PPC_MSG_RESCHEDULE); 218 + iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE); 219 + iic_request_ipi(PPC_MSG_DEBUGGER_BREAK); 239 220 } 240 221 241 222 #endif /* CONFIG_SMP */