diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-11-26 04:53:44 -0500 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-12-23 01:35:04 -0500 |
commit | f2a4aa5646687f9a51616581221b1d348590d47e (patch) | |
tree | 19845c1811e71f6b2ee3d4837b3b1a8caeb47be3 | |
parent | 53dc110c97436dcf2a758091c98093657116e91c (diff) |
ARC: [SMP] simplify IPI code
* ipi_data is just a word, no need to keep it as struct
* find_next_bit() not needed to loop thru a 32bit word, ffs suffices
-rw-r--r-- | arch/arc/kernel/smp.c | 56 |
1 files changed, 28 insertions, 28 deletions
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index 467dd9cca18f..c00c612e8dd3 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c | |||
@@ -197,37 +197,31 @@ int __init setup_profiling_timer(unsigned int multiplier) | |||
197 | /* Inter Processor Interrupt Handling */ | 197 | /* Inter Processor Interrupt Handling */ |
198 | /*****************************************************************************/ | 198 | /*****************************************************************************/ |
199 | 199 | ||
200 | /* | ||
201 | * structures for inter-processor calls | ||
202 | * A Collection of single bit ipi messages | ||
203 | * | ||
204 | */ | ||
205 | |||
206 | /* | ||
207 | * TODO_rajesh investigate tlb message types. | ||
208 | * IPI Timer not needed because each ARC has an individual Interrupting Timer | ||
209 | */ | ||
210 | enum ipi_msg_type { | 200 | enum ipi_msg_type { |
211 | IPI_NOP = 0, | 201 | IPI_EMPTY = 0, |
212 | IPI_RESCHEDULE = 1, | 202 | IPI_RESCHEDULE = 1, |
213 | IPI_CALL_FUNC, | 203 | IPI_CALL_FUNC, |
214 | IPI_CPU_STOP | 204 | IPI_CPU_STOP, |
215 | }; | 205 | }; |
216 | 206 | ||
217 | struct ipi_data { | 207 | /* |
218 | unsigned long bits; | 208 | * In arches with IRQ for each msg type (above), receiver can use IRQ-id to |
219 | }; | 209 | * figure out what msg was sent. For those which don't (ARC has dedicated IPI |
210 | * IRQ), the msg-type needs to be conveyed via per-cpu data | ||
211 | */ | ||
220 | 212 | ||
221 | static DEFINE_PER_CPU(struct ipi_data, ipi_data); | 213 | static DEFINE_PER_CPU(unsigned long, ipi_data); |
222 | 214 | ||
223 | static void ipi_send_msg_one(int cpu, enum ipi_msg_type msg) | 215 | static void ipi_send_msg_one(int cpu, enum ipi_msg_type msg) |
224 | { | 216 | { |
225 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | 217 | unsigned long __percpu *ipi_data_ptr = per_cpu_ptr(&ipi_data, cpu); |
226 | unsigned long flags; | 218 | unsigned long flags; |
227 | 219 | ||
220 | pr_debug("%d Sending msg [%d] to %d\n", smp_processor_id(), msg, cpu); | ||
221 | |||
228 | local_irq_save(flags); | 222 | local_irq_save(flags); |
229 | 223 | ||
230 | set_bit(msg, &ipi->bits); | 224 | set_bit(msg, ipi_data_ptr); |
231 | 225 | ||
232 | /* Call the platform specific cross-CPU call function */ | 226 | /* Call the platform specific cross-CPU call function */ |
233 | if (plat_smp_ops.ipi_send) | 227 | if (plat_smp_ops.ipi_send) |
@@ -275,12 +269,11 @@ static void ipi_cpu_stop(void) | |||
275 | machine_halt(); | 269 | machine_halt(); |
276 | } | 270 | } |
277 | 271 | ||
278 | static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi) | 272 | static inline void __do_IPI(unsigned long pending) |
279 | { | 273 | { |
280 | unsigned long msg = 0; | 274 | while (pending) { |
281 | 275 | ||
282 | do { | 276 | unsigned long msg = __ffs(pending); |
283 | msg = find_next_bit(ops, BITS_PER_LONG, msg+1); | ||
284 | 277 | ||
285 | switch (msg) { | 278 | switch (msg) { |
286 | case IPI_RESCHEDULE: | 279 | case IPI_RESCHEDULE: |
@@ -294,8 +287,14 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi) | |||
294 | case IPI_CPU_STOP: | 287 | case IPI_CPU_STOP: |
295 | ipi_cpu_stop(); | 288 | ipi_cpu_stop(); |
296 | break; | 289 | break; |
290 | |||
291 | default: | ||
292 | pr_warn("IPI missing msg\n"); | ||
293 | |||
297 | } | 294 | } |
298 | } while (msg < BITS_PER_LONG); | 295 | |
296 | pending &= ~(1U << msg); | ||
297 | } | ||
299 | } | 298 | } |
300 | 299 | ||
301 | /* | 300 | /* |
@@ -304,9 +303,10 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi) | |||
304 | */ | 303 | */ |
305 | irqreturn_t do_IPI(int irq, void *dev_id) | 304 | irqreturn_t do_IPI(int irq, void *dev_id) |
306 | { | 305 | { |
307 | int cpu = smp_processor_id(); | 306 | unsigned long pending; |
308 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | 307 | |
309 | unsigned long ops; | 308 | pr_debug("IPI [%ld] received on cpu %d\n", |
309 | *this_cpu_ptr(&ipi_data), smp_processor_id()); | ||
310 | 310 | ||
311 | if (plat_smp_ops.ipi_clear) | 311 | if (plat_smp_ops.ipi_clear) |
312 | plat_smp_ops.ipi_clear(irq); | 312 | plat_smp_ops.ipi_clear(irq); |
@@ -315,8 +315,8 @@ irqreturn_t do_IPI(int irq, void *dev_id) | |||
315 | * XXX: is this loop really needed | 315 | * XXX: is this loop really needed |
316 | * And do we need to move ipi_clean inside | 316 | * And do we need to move ipi_clean inside |
317 | */ | 317 | */ |
318 | while ((ops = xchg(&ipi->bits, 0)) != 0) | 318 | while ((pending = xchg(this_cpu_ptr(&ipi_data), 0)) != 0) |
319 | __do_IPI(&ops, ipi); | 319 | __do_IPI(pending); |
320 | 320 | ||
321 | return IRQ_HANDLED; | 321 | return IRQ_HANDLED; |
322 | } | 322 | } |