mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-25 21:54:06 +08:00
powerpc/kernel: Block interrupts when updating TIDR
clear_thread_tidr() is called in interrupt context as a part of delayed
put of the task structure (i.e as a part of timer interrupt). To prevent
a deadlock, block interrupts when holding vas_thread_id_lock to set/
clear TIDR for a task.
Fixes: ec233ede4c
("powerpc: Add support for setting SPRN_TIDR")
Cc: stable@vger.kernel.org # v4.15+
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
902bdc5745
commit
384dfd627f
@ -1515,14 +1515,15 @@ static int assign_thread_tidr(void)
|
||||
{
|
||||
int index;
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
again:
|
||||
if (!ida_pre_get(&vas_thread_ida, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock(&vas_thread_id_lock);
|
||||
spin_lock_irqsave(&vas_thread_id_lock, flags);
|
||||
err = ida_get_new_above(&vas_thread_ida, 1, &index);
|
||||
spin_unlock(&vas_thread_id_lock);
|
||||
spin_unlock_irqrestore(&vas_thread_id_lock, flags);
|
||||
|
||||
if (err == -EAGAIN)
|
||||
goto again;
|
||||
@ -1530,9 +1531,9 @@ again:
|
||||
return err;
|
||||
|
||||
if (index > MAX_THREAD_CONTEXT) {
|
||||
spin_lock(&vas_thread_id_lock);
|
||||
spin_lock_irqsave(&vas_thread_id_lock, flags);
|
||||
ida_remove(&vas_thread_ida, index);
|
||||
spin_unlock(&vas_thread_id_lock);
|
||||
spin_unlock_irqrestore(&vas_thread_id_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -1541,9 +1542,11 @@ again:
|
||||
|
||||
static void free_thread_tidr(int id)
|
||||
{
|
||||
spin_lock(&vas_thread_id_lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&vas_thread_id_lock, flags);
|
||||
ida_remove(&vas_thread_ida, id);
|
||||
spin_unlock(&vas_thread_id_lock);
|
||||
spin_unlock_irqrestore(&vas_thread_id_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user