From 58a46b553c83380bf25104817890e16f55373b83 Mon Sep 17 00:00:00 2001 From: lyx Date: Tue, 12 Oct 2010 18:22:17 -0700 Subject: [PATCH] spi:do spin_unlock before msg callback function, fix xpt_2046 bug as follow: [ 344.540000] BUG: spinlock lockup on CPU#0, swapper/0, cd417880 [ 344.540000] [] (unwind_backtrace+0x0/0xdc) from [] (dump_stack+0x18/0x1c) [ 344.540000] [] (dump_stack+0x18/0x1c) from [] (_raw_spin_lock+0x128/0x168) [ 344.540000] [] (_raw_spin_lock+0x128/0x168) from [] (_spin_lock_irqsave+0x5c/0x68) [ 344.540000] [] (_spin_lock_irqsave+0x5c/0x68) from [] (rk2818_spi_quick_transfer+0x30/0xb0) [ 344.540000] [] (rk2818_spi_quick_transfer+0x30/0xb0) from [] (spi_async+0xa4/0xb0) [ 344.540000] [] (spi_async+0xa4/0xb0) from [] (xpt2046_rx_val+0xd4/0x110) [ 344.540000] [] (xpt2046_rx_val+0xd4/0x110) from [] (msg_giveback+0x6c/0x70) [ 344.540000] [] (msg_giveback+0x6c/0x70) from [] (rk2818_pump_messages+0x568/0x598) [ 344.540000] [] (rk2818_pump_messages+0x568/0x598) from [] (rk2818_spi_quick_transfer+0x9c/0xb0) [ 344.540000] [] (rk2818_spi_quick_transfer+0x9c/0xb0) from [] (spi_async+0xa4/0xb0) [ 344.540000] [] (spi_async+0xa4/0xb0) from [] (xpt2046_timer+0xe0/0x120) [ 344.540000] [] (xpt2046_timer+0xe0/0x120) from [] (__run_hrtimer+0x90/0xec) [ 344.540000] [] (__run_hrtimer+0x90/0xec) from [] (hrtimer_interrupt+0x198/0x218) [ 344.540000] [] (hrtimer_interrupt+0x198/0x218) from [] (rk2818_timer_clockevent_interrupt+0x28/0x34) [ 344.540000] [] (rk2818_timer_clockevent_interrupt+0x28/0x34) from [] (handle_IRQ_event+0x2c/0xfc) [ 344.540000] [] (handle_IRQ_event+0x2c/0xfc) from [] (handle_level_irq+0xbc/0x130) [ 344.540000] [] (handle_level_irq+0xbc/0x130) from [] (asm_do_IRQ+0x70/0x8c) [ 344.540000] [] (asm_do_IRQ+0x70/0x8c) from [] (__irq_svc+0x48/0xc0) --- drivers/spi/rk2818_spim.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/spi/rk2818_spim.c b/drivers/spi/rk2818_spim.c index 543262ae0098..ef72157a0bd2 100755 --- a/drivers/spi/rk2818_spim.c +++ b/drivers/spi/rk2818_spim.c @@ -768,7 +768,9 @@ static void msg_giveback(struct rk2818_spi *dws) { struct spi_transfer *last_transfer; struct spi_message *msg; + DBG("+++++++++++++++enter %s++++++++++++++++++\n", __func__); + msg = dws->cur_msg; dws->cur_msg = NULL; dws->cur_transfer = NULL; @@ -784,9 +786,7 @@ static void msg_giveback(struct rk2818_spi *dws) if (!last_transfer->cs_change) dws->cs_control(dws,msg->spi->chip_select,MRST_SPI_DEASSERT); - msg->state = NULL; - if (msg->complete) - msg->complete(msg->context); + msg->state = NULL; } /* Must be called inside pump_transfers() */ @@ -814,7 +814,7 @@ comple: if (dws->cur_msg->state == DONE_STATE) { dws->cur_msg->status = 0; - msg_giveback(dws); + //msg_giveback(dws); return 0; } else { @@ -848,7 +848,7 @@ static int do_half_transfer(struct rk2818_spi *dws) if (dws->cur_msg->state == DONE_STATE) { dws->cur_msg->status = 0; - msg_giveback(dws); + //msg_giveback(dws); return 0; } else { @@ -1021,7 +1021,7 @@ static int rk2818_pump_transfers(struct rk2818_spi *dws, int mode) return do_half_transfer(dws); early_exit: - msg_giveback(dws); + //msg_giveback(dws); return 0; } @@ -1064,6 +1064,7 @@ static int rk2818_spi_quick_transfer(struct spi_device *spi, struct spi_message struct rk2818_spi *dws = spi_master_get_devdata(spi->master); unsigned long flags; struct rk2818_spi_chip *chip_info = spi->controller_data; + struct spi_message *mmsg; DBG("+++++++++++++++enter %s++++++++++++++++++\n", __func__); @@ -1089,7 +1090,14 @@ static int rk2818_spi_quick_transfer(struct spi_device *spi, struct spi_message //printk("+++++++++++++half transfer++++++++++++++\n"); } + mmsg = dws->cur_msg; + msg_giveback(dws); + spin_unlock_irqrestore(&dws->lock, flags); + + if (mmsg->complete) + mmsg->complete(mmsg->context); + return 0; } #endif -- 2.34.1