summaryrefslogtreecommitdiffstats
path: root/drivers/net/irda/ali-ircc.c
diff options
context:
space:
mode:
authorAlexey Khoroshilov <khoroshilov@ispras.ru>2015-09-11 23:34:48 +0200
committerDavid S. Miller <davem@davemloft.net>2015-09-12 01:18:33 +0200
commite8684c88774c0ddfeefdbed0aa469b25b9962f3e (patch)
treee88c7b91bd30df72be335b9577d30126a4851523 /drivers/net/irda/ali-ircc.c
parentopenvswitch: Fix dependency on IPv6 defrag. (diff)
downloadlinux-e8684c88774c0ddfeefdbed0aa469b25b9962f3e.tar.xz
linux-e8684c88774c0ddfeefdbed0aa469b25b9962f3e.zip
irda: ali-ircc: Fix deadlock in ali_ircc_sir_change_speed()
ali_ircc_sir_change_speed() is always called with self->lock held, so acquiring the lock inside it leads to unavoidable deadlock. Call graph: ali_ircc_sir_change_speed() is called from ali_ircc_change_speed() ali_ircc_fir_hard_xmit() under spin_lock_irqsave(&self->lock, flags); ali_ircc_sir_hard_xmit() under spin_lock_irqsave(&self->lock, flags); ali_ircc_net_ioctl() under spin_lock_irqsave(&self->lock, flags); ali_ircc_dma_xmit_complete() ali_ircc_fir_interrupt() ali_ircc_interrupt() under spin_lock(&self->lock); ali_ircc_sir_write_wakeup() ali_ircc_sir_interrupt() ali_ircc_interrupt() under spin_lock(&self->lock); The patch removes spin_lock/unlock from ali_ircc_sir_change_speed(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/irda/ali-ircc.c')
-rw-r--r--drivers/net/irda/ali-ircc.c6
1 files changed, 0 insertions, 6 deletions
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index 58ae11a14bb6..64bb44d5d867 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -1031,7 +1031,6 @@ static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 baud)
static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed)
{
struct ali_ircc_cb *self = priv;
- unsigned long flags;
int iobase;
int fcr; /* FIFO control reg */
int lcr; /* Line control reg */
@@ -1061,8 +1060,6 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed)
/* Update accounting for new speed */
self->io.speed = speed;
- spin_lock_irqsave(&self->lock, flags);
-
divisor = 115200/speed;
fcr = UART_FCR_ENABLE_FIFO;
@@ -1089,9 +1086,6 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed)
/* without this, the connection will be broken after come back from FIR speed,
but with this, the SIR connection is harder to established */
outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
-
- spin_unlock_irqrestore(&self->lock, flags);
-
}
static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed)