diff options
| -rw-r--r-- | kernel/irq_work.c | 22 | 
1 files changed, 7 insertions, 15 deletions
diff --git a/kernel/irq_work.c b/kernel/irq_work.c index df0dbf4d859b..255454a48346 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c @@ -29,24 +29,16 @@ static DEFINE_PER_CPU(struct llist_head, lazy_list);   */  static bool irq_work_claim(struct irq_work *work)  { -	int flags, oflags, nflags; +	int oflags; +	oflags = atomic_fetch_or(IRQ_WORK_CLAIMED, &work->flags);  	/* -	 * Start with our best wish as a premise but only trust any -	 * flag value after cmpxchg() result. +	 * If the work is already pending, no need to raise the IPI. +	 * The pairing atomic_xchg() in irq_work_run() makes sure +	 * everything we did before is visible.  	 */ -	flags = atomic_read(&work->flags) & ~IRQ_WORK_PENDING; -	for (;;) { -		nflags = flags | IRQ_WORK_CLAIMED; -		oflags = atomic_cmpxchg(&work->flags, flags, nflags); -		if (oflags == flags) -			break; -		if (oflags & IRQ_WORK_PENDING) -			return false; -		flags = oflags; -		cpu_relax(); -	} - +	if (oflags & IRQ_WORK_PENDING) +		return false;  	return true;  }  | 

