diff options
| -rw-r--r-- | arch/powerpc/include/asm/smp.h | 7 | ||||
| -rw-r--r-- | arch/powerpc/kernel/smp.c | 59 |
2 files changed, 66 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 1866cec4f967..c25f73d1d842 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h | |||
| @@ -81,6 +81,13 @@ extern int cpu_to_core_id(int cpu); | |||
| 81 | #define PPC_MSG_CALL_FUNC_SINGLE 2 | 81 | #define PPC_MSG_CALL_FUNC_SINGLE 2 |
| 82 | #define PPC_MSG_DEBUGGER_BREAK 3 | 82 | #define PPC_MSG_DEBUGGER_BREAK 3 |
| 83 | 83 | ||
| 84 | /* | ||
| 85 | * irq controllers that have dedicated ipis per message and don't | ||
| 86 | * need additional code in the action handler may use this | ||
| 87 | */ | ||
| 88 | extern int smp_request_message_ipi(int virq, int message); | ||
| 89 | extern const char *smp_ipi_name[]; | ||
| 90 | |||
| 84 | void smp_init_iSeries(void); | 91 | void smp_init_iSeries(void); |
| 85 | void smp_init_pSeries(void); | 92 | void smp_init_pSeries(void); |
| 86 | void smp_init_cell(void); | 93 | void smp_init_cell(void); |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index ff9f7010097d..a59d8d72bb97 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
| @@ -123,6 +123,65 @@ void smp_message_recv(int msg) | |||
| 123 | } | 123 | } |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | static irqreturn_t call_function_action(int irq, void *data) | ||
| 127 | { | ||
| 128 | generic_smp_call_function_interrupt(); | ||
| 129 | return IRQ_HANDLED; | ||
| 130 | } | ||
| 131 | |||
| 132 | static irqreturn_t reschedule_action(int irq, void *data) | ||
| 133 | { | ||
| 134 | /* we just need the return path side effect of checking need_resched */ | ||
| 135 | return IRQ_HANDLED; | ||
| 136 | } | ||
| 137 | |||
| 138 | static irqreturn_t call_function_single_action(int irq, void *data) | ||
| 139 | { | ||
| 140 | generic_smp_call_function_single_interrupt(); | ||
| 141 | return IRQ_HANDLED; | ||
| 142 | } | ||
| 143 | |||
| 144 | static irqreturn_t debug_ipi_action(int irq, void *data) | ||
| 145 | { | ||
| 146 | smp_message_recv(PPC_MSG_DEBUGGER_BREAK); | ||
| 147 | return IRQ_HANDLED; | ||
| 148 | } | ||
| 149 | |||
| 150 | static irq_handler_t smp_ipi_action[] = { | ||
| 151 | [PPC_MSG_CALL_FUNCTION] = call_function_action, | ||
| 152 | [PPC_MSG_RESCHEDULE] = reschedule_action, | ||
| 153 | [PPC_MSG_CALL_FUNC_SINGLE] = call_function_single_action, | ||
| 154 | [PPC_MSG_DEBUGGER_BREAK] = debug_ipi_action, | ||
| 155 | }; | ||
| 156 | |||
| 157 | const char *smp_ipi_name[] = { | ||
| 158 | [PPC_MSG_CALL_FUNCTION] = "ipi call function", | ||
| 159 | [PPC_MSG_RESCHEDULE] = "ipi reschedule", | ||
| 160 | [PPC_MSG_CALL_FUNC_SINGLE] = "ipi call function single", | ||
| 161 | [PPC_MSG_DEBUGGER_BREAK] = "ipi debugger", | ||
| 162 | }; | ||
| 163 | |||
| 164 | /* optional function to request ipi, for controllers with >= 4 ipis */ | ||
| 165 | int smp_request_message_ipi(int virq, int msg) | ||
| 166 | { | ||
| 167 | int err; | ||
| 168 | |||
| 169 | if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) { | ||
| 170 | return -EINVAL; | ||
| 171 | } | ||
| 172 | #if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC) | ||
| 173 | if (msg == PPC_MSG_DEBUGGER_BREAK) { | ||
| 174 | return 1; | ||
| 175 | } | ||
| 176 | #endif | ||
| 177 | err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU, | ||
| 178 | smp_ipi_name[msg], 0); | ||
| 179 | WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n", | ||
| 180 | virq, smp_ipi_name[msg], err); | ||
| 181 | |||
| 182 | return err; | ||
| 183 | } | ||
| 184 | |||
| 126 | void smp_send_reschedule(int cpu) | 185 | void smp_send_reschedule(int cpu) |
| 127 | { | 186 | { |
| 128 | if (likely(smp_ops)) | 187 | if (likely(smp_ops)) |
