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
This commit is contained in:
parent
53dc110c97
commit
f2a4aa5646
1 changed files with 28 additions and 28 deletions
|
@ -197,37 +197,31 @@ int __init setup_profiling_timer(unsigned int multiplier)
|
||||||
/* Inter Processor Interrupt Handling */
|
/* Inter Processor Interrupt Handling */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
/*
|
|
||||||
* structures for inter-processor calls
|
|
||||||
* A Collection of single bit ipi messages
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO_rajesh investigate tlb message types.
|
|
||||||
* IPI Timer not needed because each ARC has an individual Interrupting Timer
|
|
||||||
*/
|
|
||||||
enum ipi_msg_type {
|
enum ipi_msg_type {
|
||||||
IPI_NOP = 0,
|
IPI_EMPTY = 0,
|
||||||
IPI_RESCHEDULE = 1,
|
IPI_RESCHEDULE = 1,
|
||||||
IPI_CALL_FUNC,
|
IPI_CALL_FUNC,
|
||||||
IPI_CPU_STOP
|
IPI_CPU_STOP,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipi_data {
|
/*
|
||||||
unsigned long bits;
|
* In arches with IRQ for each msg type (above), receiver can use IRQ-id to
|
||||||
};
|
* figure out what msg was sent. For those which don't (ARC has dedicated IPI
|
||||||
|
* IRQ), the msg-type needs to be conveyed via per-cpu data
|
||||||
|
*/
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct ipi_data, ipi_data);
|
static DEFINE_PER_CPU(unsigned long, ipi_data);
|
||||||
|
|
||||||
static void ipi_send_msg_one(int cpu, enum ipi_msg_type msg)
|
static void ipi_send_msg_one(int cpu, enum ipi_msg_type msg)
|
||||||
{
|
{
|
||||||
struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
|
unsigned long __percpu *ipi_data_ptr = per_cpu_ptr(&ipi_data, cpu);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
pr_debug("%d Sending msg [%d] to %d\n", smp_processor_id(), msg, cpu);
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
set_bit(msg, &ipi->bits);
|
set_bit(msg, ipi_data_ptr);
|
||||||
|
|
||||||
/* Call the platform specific cross-CPU call function */
|
/* Call the platform specific cross-CPU call function */
|
||||||
if (plat_smp_ops.ipi_send)
|
if (plat_smp_ops.ipi_send)
|
||||||
|
@ -275,12 +269,11 @@ static void ipi_cpu_stop(void)
|
||||||
machine_halt();
|
machine_halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi)
|
static inline void __do_IPI(unsigned long pending)
|
||||||
{
|
{
|
||||||
unsigned long msg = 0;
|
while (pending) {
|
||||||
|
|
||||||
do {
|
unsigned long msg = __ffs(pending);
|
||||||
msg = find_next_bit(ops, BITS_PER_LONG, msg+1);
|
|
||||||
|
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case IPI_RESCHEDULE:
|
case IPI_RESCHEDULE:
|
||||||
|
@ -294,8 +287,14 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi)
|
||||||
case IPI_CPU_STOP:
|
case IPI_CPU_STOP:
|
||||||
ipi_cpu_stop();
|
ipi_cpu_stop();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pr_warn("IPI missing msg\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
} while (msg < BITS_PER_LONG);
|
|
||||||
|
pending &= ~(1U << msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -304,9 +303,10 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi)
|
||||||
*/
|
*/
|
||||||
irqreturn_t do_IPI(int irq, void *dev_id)
|
irqreturn_t do_IPI(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
int cpu = smp_processor_id();
|
unsigned long pending;
|
||||||
struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
|
|
||||||
unsigned long ops;
|
pr_debug("IPI [%ld] received on cpu %d\n",
|
||||||
|
*this_cpu_ptr(&ipi_data), smp_processor_id());
|
||||||
|
|
||||||
if (plat_smp_ops.ipi_clear)
|
if (plat_smp_ops.ipi_clear)
|
||||||
plat_smp_ops.ipi_clear(irq);
|
plat_smp_ops.ipi_clear(irq);
|
||||||
|
@ -315,8 +315,8 @@ irqreturn_t do_IPI(int irq, void *dev_id)
|
||||||
* XXX: is this loop really needed
|
* XXX: is this loop really needed
|
||||||
* And do we need to move ipi_clean inside
|
* And do we need to move ipi_clean inside
|
||||||
*/
|
*/
|
||||||
while ((ops = xchg(&ipi->bits, 0)) != 0)
|
while ((pending = xchg(this_cpu_ptr(&ipi_data), 0)) != 0)
|
||||||
__do_IPI(&ops, ipi);
|
__do_IPI(pending);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue