ANDROID: tty: hvc_dcc: Save irq flags when locking

Disable interrupts when using DCC fifo to prevent deadlock if interrupt
occurs that causes a console write.

Bug: 175415911
Fixes: 61d87acb93 ("FROMLIST: hvc_dcc: bind driver to core0 for reads
and writes")
Change-Id: I645bafef1d8bc58ee93b086b46d822c046aece2d
Signed-off-by: Elliot Berman <eberman@codeaurora.org>
This commit is contained in:
Elliot Berman 2020-11-05 10:39:15 -08:00 committed by Todd Kjos
parent 0edac9cb95
commit 37f671817b

View File

@ -128,8 +128,9 @@ static DEFINE_KFIFO(outbuf, unsigned char, 1024);
static void dcc_put_work_fn(struct work_struct *work)
{
unsigned char ch;
unsigned long irqflags;
spin_lock(&dcc_lock);
spin_lock_irqsave(&dcc_lock, irqflags);
/* While there's data in the output FIFO, write it to the DCC */
while (kfifo_get(&outbuf, &ch))
@ -142,7 +143,7 @@ static void dcc_put_work_fn(struct work_struct *work)
kfifo_put(&inbuf, ch);
}
spin_unlock(&dcc_lock);
spin_unlock_irqrestore(&dcc_lock, irqflags);
}
/*
@ -152,19 +153,20 @@ static void dcc_put_work_fn(struct work_struct *work)
static void dcc_get_work_fn(struct work_struct *work)
{
unsigned char ch;
unsigned long irqflags;
/*
* Read characters from DCC and put them into the input FIFO, as
* long as there is room and we have characters to read.
*/
spin_lock(&dcc_lock);
spin_lock_irqsave(&dcc_lock, irqflags);
while (!kfifo_is_full(&inbuf)) {
if (!hvc_dcc_get_chars(0, &ch, 1))
break;
kfifo_put(&inbuf, ch);
}
spin_unlock(&dcc_lock);
spin_unlock_irqrestore(&dcc_lock, irqflags);
}
/*
@ -175,11 +177,12 @@ static int hvc_dcc0_put_chars(uint32_t vt, const char *buf,
int count)
{
int len;
unsigned long irqflags;
spin_lock(&dcc_lock);
spin_lock_irqsave(&dcc_lock, irqflags);
if (smp_processor_id() || (!kfifo_is_empty(&outbuf))) {
len = kfifo_in(&outbuf, buf, count);
spin_unlock(&dcc_lock);
spin_unlock_irqrestore(&dcc_lock, irqflags);
/*
* We just push data to the output FIFO, so schedule the
* workqueue that will actually write that data to DCC.
@ -193,7 +196,7 @@ static int hvc_dcc0_put_chars(uint32_t vt, const char *buf,
* write the data to DCC.
*/
len = hvc_dcc_put_chars(vt, buf, count);
spin_unlock(&dcc_lock);
spin_unlock_irqrestore(&dcc_lock, irqflags);
return len;
}
@ -205,12 +208,13 @@ static int hvc_dcc0_put_chars(uint32_t vt, const char *buf,
static int hvc_dcc0_get_chars(uint32_t vt, char *buf, int count)
{
int len;
unsigned long irqflags;
spin_lock(&dcc_lock);
spin_lock_irqsave(&dcc_lock, irqflags);
if (smp_processor_id() || (!kfifo_is_empty(&inbuf))) {
len = kfifo_out(&inbuf, buf, count);
spin_unlock(&dcc_lock);
spin_unlock_irqrestore(&dcc_lock, irqflags);
/*
* If the FIFO was empty, there may be characters in the DCC
@ -229,7 +233,7 @@ static int hvc_dcc0_get_chars(uint32_t vt, char *buf, int count)
* read the data from DCC.
*/
len = hvc_dcc_get_chars(vt, buf, count);
spin_unlock(&dcc_lock);
spin_unlock_irqrestore(&dcc_lock, irqflags);
return len;
}