spi:do spin_unlock before msg callback function, fix xpt_2046 bug as follow:
authorlyx <lyx@rock-chips.com>
Wed, 13 Oct 2010 01:22:17 +0000 (18:22 -0700)
committerlyx <lyx@rock-chips.com>
Wed, 13 Oct 2010 01:27:52 +0000 (18:27 -0700)
 [ 344.540000] BUG: spinlock lockup on CPU#0, swapper/0, cd417880
[ 344.540000] [<c044e0bc>] (unwind_backtrace+0x0/0xdc) from [<c06f2a4c>] (dump_stack+0x18/0x1c)
[ 344.540000] [<c06f2a4c>] (dump_stack+0x18/0x1c) from [<c055a1a4>] (_raw_spin_lock+0x128/0x168)
[ 344.540000] [<c055a1a4>] (_raw_spin_lock+0x128/0x168) from [<c06f5fec>] (_spin_lock_irqsave+0x5c/0x68)
[ 344.540000] [<c06f5fec>] (_spin_lock_irqsave+0x5c/0x68) from [<c05b4b50>] (rk2818_spi_quick_transfer+0x30/0xb0)
[ 344.540000] [<c05b4b50>] (rk2818_spi_quick_transfer+0x30/0xb0) from [<c05b21d8>] (spi_async+0xa4/0xb0)
[ 344.540000] [<c05b21d8>] (spi_async+0xa4/0xb0) from [<c05fa42c>] (xpt2046_rx_val+0xd4/0x110)
[ 344.540000] [<c05fa42c>] (xpt2046_rx_val+0xd4/0x110) from [<c05b3470>] (msg_giveback+0x6c/0x70)
[ 344.540000] [<c05b3470>] (msg_giveback+0x6c/0x70) from [<c05b46a0>] (rk2818_pump_messages+0x568/0x598)
[ 344.540000] [<c05b46a0>] (rk2818_pump_messages+0x568/0x598) from [<c05b4bbc>] (rk2818_spi_quick_transfer+0x9c/0xb0)
[ 344.540000] [<c05b4bbc>] (rk2818_spi_quick_transfer+0x9c/0xb0) from [<c05b21d8>] (spi_async+0xa4/0xb0)
[ 344.540000] [<c05b21d8>] (spi_async+0xa4/0xb0) from [<c05fa548>] (xpt2046_timer+0xe0/0x120)
[ 344.540000] [<c05fa548>] (xpt2046_timer+0xe0/0x120) from [<c047cc24>] (__run_hrtimer+0x90/0xec)
[ 344.540000] [<c047cc24>] (__run_hrtimer+0x90/0xec) from [<c047cf64>] (hrtimer_interrupt+0x198/0x218)
[ 344.540000] [<c047cf64>] (hrtimer_interrupt+0x198/0x218) from [<c04527c4>] (rk2818_timer_clockevent_interrupt+0x28/0x34)
[ 344.540000] [<c04527c4>] (rk2818_timer_clockevent_interrupt+0x28/0x34) from [<c049ba0c>] (handle_IRQ_event+0x2c/0xfc)
[ 344.540000] [<c049ba0c>] (handle_IRQ_event+0x2c/0xfc) from [<c049d908>] (handle_level_irq+0xbc/0x130)
[ 344.540000] [<c049d908>] (handle_level_irq+0xbc/0x130) from [<c0448070>] (asm_do_IRQ+0x70/0x8c)
[ 344.540000] [<c0448070>] (asm_do_IRQ+0x70/0x8c) from [<c0448ac8>] (__irq_svc+0x48/0xc0)

drivers/spi/rk2818_spim.c

index 543262ae0098e7b4b1d36023d07f8c5fe95dcdbd..ef72157a0bd247d6aef37dd4f255439c05db230a 100755 (executable)
@@ -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