/* Use IRQ_SUPPLE_0 to request reschedule. * When returning from interrupt to user space, * there is chance to reschedule */ static irqreturn_t ipi_handler_int0(int irq, void *dev_instance) { unsigned int cpu = smp_processor_id(); platform_clear_ipi(cpu, IRQ_SUPPLE_0); return IRQ_HANDLED; }
static irqreturn_t ipi_handler(int irq, void *dev_instance) { struct ipi_message *msg; struct ipi_message_queue *msg_queue; unsigned int cpu = smp_processor_id(); platform_clear_ipi(cpu); msg_queue = &__get_cpu_var(ipi_msg_queue); msg_queue->count++; spin_lock(&msg_queue->lock); while (!list_empty(&msg_queue->head)) { msg = list_entry(msg_queue->head.next, typeof(*msg), list); list_del(&msg->list); switch (msg->type) { case BFIN_IPI_RESCHEDULE: /* That's the easiest one; leave it to * return_from_int. */ kfree(msg); break; case BFIN_IPI_CALL_FUNC: spin_unlock(&msg_queue->lock); ipi_call_function(cpu, msg); spin_lock(&msg_queue->lock); break; case BFIN_IPI_CPU_STOP: spin_unlock(&msg_queue->lock); ipi_cpu_stop(cpu); spin_lock(&msg_queue->lock); kfree(msg); break; default: printk(KERN_CRIT "CPU%u: Unknown IPI message \ 0x%lx\n", cpu, msg->type); kfree(msg); break; } } spin_unlock(&msg_queue->lock); return IRQ_HANDLED; }
static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) { struct ipi_data *bfin_ipi_data; unsigned int cpu = smp_processor_id(); unsigned long pending; unsigned long msg; platform_clear_ipi(cpu, IRQ_SUPPLE_1); bfin_ipi_data = &__get_cpu_var(bfin_ipi); smp_mb(); while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) { msg = 0; do { msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1); switch (msg) { case BFIN_IPI_TIMER: ipi_timer(); break; case BFIN_IPI_RESCHEDULE: scheduler_ipi(); break; case BFIN_IPI_CALL_FUNC: generic_smp_call_function_interrupt(); break; case BFIN_IPI_CALL_FUNC_SINGLE: generic_smp_call_function_single_interrupt(); break; case BFIN_IPI_CPU_STOP: ipi_cpu_stop(cpu); break; } } while (msg < BITS_PER_LONG); smp_mb(); } return IRQ_HANDLED; }
static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) { struct ipi_message *msg; struct ipi_message_queue *msg_queue; unsigned int cpu = smp_processor_id(); unsigned long flags; platform_clear_ipi(cpu, IRQ_SUPPLE_1); msg_queue = &__get_cpu_var(ipi_msg_queue); spin_lock_irqsave(&msg_queue->lock, flags); while (msg_queue->count) { msg = &msg_queue->ipi_message[msg_queue->head]; switch (msg->type) { case BFIN_IPI_CALL_FUNC: spin_unlock_irqrestore(&msg_queue->lock, flags); ipi_call_function(cpu, msg); spin_lock_irqsave(&msg_queue->lock, flags); break; case BFIN_IPI_CPU_STOP: spin_unlock_irqrestore(&msg_queue->lock, flags); ipi_cpu_stop(cpu); spin_lock_irqsave(&msg_queue->lock, flags); break; default: printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n", cpu, msg->type); break; } msg_queue->head++; msg_queue->head %= BFIN_IPI_MSGQ_LEN; msg_queue->count--; } spin_unlock_irqrestore(&msg_queue->lock, flags); return IRQ_HANDLED; }
static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) { struct ipi_data *bfin_ipi_data; unsigned int cpu = smp_processor_id(); unsigned long pending; unsigned long msg; platform_clear_ipi(cpu, IRQ_SUPPLE_1); smp_rmb(); bfin_ipi_data = this_cpu_ptr(&bfin_ipi); while ((pending = atomic_xchg(&bfin_ipi_data->bits, 0)) != 0) { msg = 0; do { msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1); switch (msg) { case BFIN_IPI_TIMER: ipi_timer(); break; case BFIN_IPI_RESCHEDULE: scheduler_ipi(); break; case BFIN_IPI_CALL_FUNC: generic_smp_call_function_interrupt(); break; case BFIN_IPI_CPU_STOP: ipi_cpu_stop(cpu); break; default: goto out; } atomic_dec(&bfin_ipi_data->count); } while (msg < BITS_PER_LONG); } out: return IRQ_HANDLED; }