it8xxx2: intc: protect interrupt enable registers of soc Because these two functions are called from threads and ISR. And they run a bit-wise OR operation on the interrupt registers. So protect them to prevent race condition between thread and ISR context where causing an interrupt won't enable as expected. eg. - Pseudo code of thread enable IER1's bit1: 1. load word from IER1 (0x40) and write into CPU register S1 => S1=0x40 2. Or S1's bit1 => S1=0x42 (But if an interrupt is triggered here) 3. Store word to IER1 from S1 => IER1=0x42 (IER1 will be 0x42 not 0x43, IER1's bit0 is disable again due to the race condition above) -Pseudo code of ISR enable IER1's bit0 1. load word from IER1 (0x40) write into CPU register S2 => S2=0x40 2. Or S2's bit0 => S2=0x41 3. Store word to IER1 from S2 => IER1=0x41 4. Go back to thread. Signed-off-by: Dino Li <Dino.Li@ite.com.tw>
diff --git a/drivers/interrupt_controller/intc_ite_it8xxx2.c b/drivers/interrupt_controller/intc_ite_it8xxx2.c index a630489..b25111c 100644 --- a/drivers/interrupt_controller/intc_ite_it8xxx2.c +++ b/drivers/interrupt_controller/intc_ite_it8xxx2.c
@@ -125,7 +125,11 @@ g = irq / MAX_REGISR_IRQ_NUM; i = irq % MAX_REGISR_IRQ_NUM; en = reg_enable[g]; + + /* critical section due to run a bit-wise OR operation */ + unsigned int key = irq_lock(); SET_MASK(*en, BIT(i)); + irq_unlock(key); } void ite_intc_irq_disable(unsigned int irq) @@ -139,7 +143,11 @@ g = irq / MAX_REGISR_IRQ_NUM; i = irq % MAX_REGISR_IRQ_NUM; en = reg_enable[g]; + + /* critical section due to run a bit-wise OR operation */ + unsigned int key = irq_lock(); CLEAR_MASK(*en, BIT(i)); + irq_unlock(key); } void ite_intc_irq_priority_set(unsigned int irq,