spi_fpga_init: fix slab corruption bug
author黄涛 <huangtao@rock-chips.com>
Tue, 12 Oct 2010 09:52:55 +0000 (17:52 +0800)
committer黄涛 <huangtao@rock-chips.com>
Tue, 12 Oct 2010 09:52:55 +0000 (17:52 +0800)
fix this bug:
[   74.920000] bt turn on power
bcm4329
patch_plus -d /etc/bluez/bcm4325/BCM4329B1_TestOnly_0237_26MHz_SEMCO_B23.hcd /dev/ttySPI0 bcm4325 1500000
speed of uart to :1500000
[   75.330000] uart->index=0
[   75.330000] baud=115200,quot=0x34
[   75.340000] baud=115200,quot=0x34
[   75.340000] Slab corruption: size-32 start=cc3b3660, len=32
[   75.340000] 010: 6b 6b 6b 6b b4 36 3b cc 6b 6b 6b 6b 6b 6b 6b a5
[   75.370000] Prev obj: start=cc3b3640, len=32
[   75.370000] 000: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b
[   75.370000] 010: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5
[   75.370000] Next obj: start=cc3b3680, len=32
[   75.370000] 000: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b
[   75.370000] 010: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5

drivers/fpga/spi_fpga_init.c

index e26a131c111c03a1004602141028ca9b290f4497..a6ca4c1cbc4efdded2e0ef3331636d8d228582e6 100755 (executable)
@@ -71,36 +71,32 @@ static void spi_fpga_trans_work_handler(struct work_struct *work)
 {\r
        struct spi_fpga_port *port =\r
                container_of(work, struct spi_fpga_port, fpga_trans_work);\r
-       unsigned long flags;\r
-       spin_lock_irqsave(&port->work_lock, flags);\r
-       while (!list_empty(&port->trans_queue)) \r
-       {\r
-               spin_unlock_irqrestore(&port->work_lock, flags);\r
-               struct spi_fpga_transfer        *t = NULL, *tmp;\r
-               list_for_each_entry_safe(t, tmp, &port->trans_queue, queue)\r
-               {\r
 \r
-                       if (t->id == 0) \r
-                               break;  \r
-                       DBG("%s:id=%d,txbuf=0x%x\n",__FUNCTION__,t->id,(int)t->txbuf);\r
-                       switch(t->id)\r
-                       {\r
-                               case ID_SPI_FPGA_WRITE:\r
-                                       spi_write(port->spi, t->txbuf, t->n_tx);\r
-                                       break;\r
-                               default:\r
-                                       break;\r
-                                       \r
-                       }\r
-                       kfree(t->txbuf);\r
-                       kfree(t);\r
-               }\r
+       while (1) {\r
+               unsigned long flags;\r
+               struct spi_fpga_transfer *t = NULL;\r
+\r
                spin_lock_irqsave(&port->work_lock, flags);\r
-               list_del_init(&port->trans_queue);\r
+               if (!list_empty(&port->trans_queue)) {\r
+                       t = list_first_entry(&port->trans_queue, struct spi_fpga_transfer, queue);\r
+                       list_del(&t->queue);\r
+               }\r
+               spin_unlock_irqrestore(&port->work_lock, flags);\r
 \r
-       }\r
-       spin_unlock_irqrestore(&port->work_lock, flags);\r
+               if (!t) // trans_queue empty\r
+                       break;\r
 \r
+               DBG("%s:id=%d,txbuf=0x%x\n",__FUNCTION__,t->id,(int)t->txbuf);\r
+               switch (t->id) {\r
+                       case ID_SPI_FPGA_WRITE:\r
+                               spi_write(port->spi, t->txbuf, t->n_tx);\r
+                               break;\r
+                       default:\r
+                               break;\r
+               }\r
+               kfree(t->txbuf);\r
+               kfree(t);\r
+       }\r
 }\r
 \r
 int spi_write_work(struct spi_device *spi, u8 *buf, size_t len)\r
@@ -129,8 +125,8 @@ int spi_write_work(struct spi_device *spi, u8 *buf, size_t len)
 \r
        spin_lock_irqsave(&port->work_lock, flags);\r
        list_add_tail(&t->queue, &port->trans_queue);\r
-       queue_work(port->fpga_trans_workqueue, &port->fpga_trans_work);\r
        spin_unlock_irqrestore(&port->work_lock, flags);\r
+       queue_work(port->fpga_trans_workqueue, &port->fpga_trans_work);\r
 \r
        return 0;\r
 \r
@@ -685,43 +681,43 @@ static int spi_fpga_wait_suspend(struct spi_fpga_port *port)
        }\r
        \r
        return -1;\r
-}
-
-static void fpga_close_power_support(void)
-{
-       //cmmb power down
-       gpio_request(FPGA_PIO4_03, NULL); 
-       gpio_direction_output(FPGA_PIO4_03,GPIO_LOW); 
-       gpio_free(FPGA_PIO4_03);
-       gpio_request(FPGA_PIO2_09, NULL); 
-       gpio_direction_output(FPGA_PIO2_09,GPIO_LOW); 
-       gpio_free(FPGA_PIO2_09);
-       gpio_request(FPGA_PIO2_06, NULL); 
-       gpio_direction_output(FPGA_PIO2_06,GPIO_LOW);
-       gpio_free(FPGA_PIO2_06);
-
-       //KEY LED control
-       gpio_request(FPGA_PIO1_13, NULL);       
-       gpio_direction_output(FPGA_PIO1_13,GPIO_LOW); 
-       gpio_free(FPGA_PIO1_13);
-}
-
-static void fpga_open_power_support(void)
-{
-       //cmmb do not control here
-
-       //KEY LED resume
-       gpio_request(FPGA_PIO1_13, NULL);       
-       gpio_direction_output(FPGA_PIO1_13,GPIO_HIGH); 
-       gpio_free(FPGA_PIO1_13);                
+}\r
+\r
+static void fpga_close_power_support(void)\r
+{\r
+       //cmmb power down\r
+       gpio_request(FPGA_PIO4_03, NULL); \r
+       gpio_direction_output(FPGA_PIO4_03,GPIO_LOW); \r
+       gpio_free(FPGA_PIO4_03);\r
+       gpio_request(FPGA_PIO2_09, NULL); \r
+       gpio_direction_output(FPGA_PIO2_09,GPIO_LOW); \r
+       gpio_free(FPGA_PIO2_09);\r
+       gpio_request(FPGA_PIO2_06, NULL); \r
+       gpio_direction_output(FPGA_PIO2_06,GPIO_LOW);\r
+       gpio_free(FPGA_PIO2_06);\r
+\r
+       //KEY LED control\r
+       gpio_request(FPGA_PIO1_13, NULL);       \r
+       gpio_direction_output(FPGA_PIO1_13,GPIO_LOW); \r
+       gpio_free(FPGA_PIO1_13);\r
+}\r
+\r
+static void fpga_open_power_support(void)\r
+{\r
+       //cmmb do not control here\r
+\r
+       //KEY LED resume\r
+       gpio_request(FPGA_PIO1_13, NULL);       \r
+       gpio_direction_output(FPGA_PIO1_13,GPIO_HIGH); \r
+       gpio_free(FPGA_PIO1_13);                \r
 }\r
 \r
 static int spi_fpga_suspend(struct spi_device *spi, pm_message_t state)\r
 {\r
 \r
-       struct spi_fpga_port *port = dev_get_drvdata(&spi->dev);
-       fpga_close_power_support( );\r
+       struct spi_fpga_port *port = dev_get_drvdata(&spi->dev);\r
        int ret;\r
+       fpga_close_power_support( );\r
        ret = spi_fpga_wait_suspend(port);\r
        if(!ret)\r
        {\r