fpga: spi_gpio: fix memory leak and corruption, more static
author黄涛 <huangtao@rock-chips.com>
Mon, 27 Sep 2010 06:08:15 +0000 (14:08 +0800)
committer黄涛 <huangtao@rock-chips.com>
Mon, 27 Sep 2010 06:08:35 +0000 (14:08 +0800)
drivers/fpga/spi_gpio.c

index a1af5b11c5718f00704ec9179c8e69823a57bbb5..8d4de9e36b25b878e211398a0a353ff5193a2a69 100755 (executable)
@@ -39,9 +39,8 @@
 #define SPI_GPIO_TEST 0\r
 #define HIGH_SPI_TEST 1\r
 \r
-spinlock_t             gpio_lock;\r
-spinlock_t             gpio_state_lock;\r
-spinlock_t             gpio_irq_lock;\r
+static DEFINE_SPINLOCK(gpio_state_lock);\r
+//static DEFINE_SPINLOCK(gpio_irq_lock);\r
 static unsigned short int gGpio0State = 0;             \r
 #define SPI_GPIO_IRQ_NUM 16\r
 static SPI_GPIO_PDATA g_spiGpioVectorTable[SPI_GPIO_IRQ_NUM] = \\r
@@ -480,10 +479,10 @@ int spi_request_gpio_irq(eSpiGpioPinNum_t PinNum, pSpiFunc Routine, eSpiGpioIntT
 int spi_free_gpio_irq(eSpiGpioPinNum_t PinNum)\r
 {      \r
        spi_gpio_disable_int(PinNum);\r
-       spin_lock(&gpio_irq_lock);\r
+//     spin_lock(&gpio_irq_lock);\r
        g_spiGpioVectorTable[PinNum].gpio_vector = NULL;\r
        g_spiGpioVectorTable[PinNum].gpio_devid= NULL;\r
-       spin_unlock(&gpio_irq_lock);\r
+//     spin_unlock(&gpio_irq_lock);\r
 \r
        return 0;\r
 }\r
@@ -547,7 +546,7 @@ static irqreturn_t spi_gpio_int_test_3(int irq, void *dev)
 }\r
 \r
 \r
-volatile int TestGpioPinLevel = 0;\r
+static volatile int TestGpioPinLevel = 0;\r
 void spi_gpio_work_handler(struct work_struct *work)\r
 {\r
        //struct spi_fpga_port *port =\r
@@ -722,7 +721,7 @@ int spi_gpio_init_first(void)
 \r
 }\r
 \r
-void spi_gpio_irq_work_handler(struct work_struct *work);\r
+static void spi_gpio_irq_work_handler(struct work_struct *work);\r
 \r
 int spi_gpio_register(struct spi_fpga_port *port)\r
 {\r
@@ -741,17 +740,13 @@ int spi_gpio_register(struct spi_fpga_port *port)
 \r
 #endif \r
 \r
-       spin_lock_init(&gpio_lock);\r
-       spin_lock_init(&gpio_state_lock);\r
-       spin_lock_init(&gpio_irq_lock);\r
-\r
+       INIT_LIST_HEAD(&port->gpio.msg_queue);\r
        port->gpio.spi_gpio_irq_workqueue = create_freezeable_workqueue("spi_gpio_irq_workqueue");\r
        if (!port->gpio.spi_gpio_irq_workqueue) {\r
                printk("cannot create spi_gpio_irq workqueue\n");\r
                return -EBUSY;\r
        }\r
        INIT_WORK(&port->gpio.spi_gpio_irq_work, spi_gpio_irq_work_handler);\r
-       INIT_LIST_HEAD(&port->gpio.msg_queue);\r
 \r
        DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
        return 0;\r
@@ -946,48 +941,54 @@ static int _spi_gpio_irq_set_wake(unsigned irq, unsigned state)
        return 0;\r
 }\r
 \r
-void spi_gpio_irq_work_handler(struct work_struct *work)\r
+static void spi_gpio_irq_work_handler(struct work_struct *work)\r
 {\r
-       unsigned int irq;\r
-       unsigned int type;\r
-       unsigned int state;\r
-       unsigned int id;\r
        struct spi_fpga_port *port =\r
                container_of(work, struct spi_fpga_port, gpio.spi_gpio_irq_work);\r
 \r
-       while (!list_empty(&port->gpio.msg_queue)) \r
-       {\r
-               struct spi_gpio_irq_transfer    *t = NULL;\r
-               list_for_each_entry(t, &port->gpio.msg_queue, queue)\r
-               {\r
-                       irq = t->irq;\r
-                       type = t->type;\r
-                       state = t->state;\r
-                       id = t->id;\r
-                       if ((irq == 0) || (id == 0)) \r
-                               break;  \r
-                       printk("%s:irq=%d,type=%d,state=%d,id=%d\n",__FUNCTION__,irq,type,state,id);\r
-                       switch(id)\r
-                       {\r
-                               case ID_SPI_GPIO_IRQ_ENABLE:\r
-                                       _spi_gpio_irq_enable(irq);\r
-                                       break;\r
-                               case ID_SPI_GPIO_IRQ_DISABLE:\r
-                                       _spi_gpio_irq_disable(irq);\r
-                                       break;\r
-                               case ID_SPI_GPIO_IRQ_SET_TYPE:\r
-                                       _spi_gpio_irq_set_type(irq,type);\r
-                                       break;\r
-                               case ID_SPI_GPIO_IRQ_SET_WAKE:\r
-                                       _spi_gpio_irq_set_wake(irq,state);\r
-                                       break;\r
-                               default:\r
-                                       break;\r
-                                       \r
-                       }\r
-                       kfree(t);\r
+       while (1) {\r
+               struct spi_gpio_irq_transfer *t = NULL;\r
+               unsigned long flags;\r
+               unsigned int irq;\r
+               unsigned int type;\r
+               unsigned int state;\r
+               unsigned int id;\r
+\r
+               spin_lock_irqsave(&port->work_lock, flags);\r
+               if (!list_empty(&port->gpio.msg_queue)) {\r
+                       t = list_first_entry(&port->gpio.msg_queue, struct spi_gpio_irq_transfer, queue);\r
+                       list_del(&t->queue);\r
+               }\r
+               spin_unlock_irqrestore(&port->work_lock, flags);\r
+\r
+               if (!t) // msg_queue empty\r
+                       break;\r
+\r
+               irq = t->irq;\r
+               type = t->type;\r
+               state = t->state;\r
+               id = t->id;\r
+               kfree(t);\r
+\r
+               if ((irq == 0) || (id == 0))\r
+                       continue;\r
+               printk("%s:irq=%d,type=%d,state=%d,id=%d\n",__FUNCTION__,irq,type,state,id);\r
+               switch (id) {\r
+                       case ID_SPI_GPIO_IRQ_ENABLE:\r
+                               _spi_gpio_irq_enable(irq);\r
+                               break;\r
+                       case ID_SPI_GPIO_IRQ_DISABLE:\r
+                               _spi_gpio_irq_disable(irq);\r
+                               break;\r
+                       case ID_SPI_GPIO_IRQ_SET_TYPE:\r
+                               _spi_gpio_irq_set_type(irq, type);\r
+                               break;\r
+                       case ID_SPI_GPIO_IRQ_SET_WAKE:\r
+                               _spi_gpio_irq_set_wake(irq, state);\r
+                               break;\r
+                       default:\r
+                               break;\r
                }\r
-               list_del_init(&port->gpio.msg_queue);\r
        }\r
 }\r
 \r
@@ -997,7 +998,7 @@ static void spi_gpio_irq_enable(unsigned irq)
        struct spi_fpga_port *port = pFpgaPort;\r
        struct spi_gpio_irq_transfer *t;\r
        unsigned long flags;\r
-       t = kzalloc(sizeof(struct spi_gpio_irq_transfer), GFP_KERNEL);\r
+       t = kzalloc(sizeof(struct spi_gpio_irq_transfer), GFP_ATOMIC);\r
        if (!t)\r
        {\r
                printk("err:%s:ENOMEM\n",__FUNCTION__);\r
@@ -1008,8 +1009,9 @@ static void spi_gpio_irq_enable(unsigned irq)
        \r
        spin_lock_irqsave(&port->work_lock, flags);\r
        list_add_tail(&t->queue, &port->gpio.msg_queue);\r
-       queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work);\r
        spin_unlock_irqrestore(&port->work_lock, flags);\r
+\r
+       queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work);\r
 }\r
 \r
 static void spi_gpio_irq_disable(unsigned irq)\r
@@ -1017,7 +1019,7 @@ static void spi_gpio_irq_disable(unsigned irq)
        struct spi_fpga_port *port = pFpgaPort;\r
        struct spi_gpio_irq_transfer *t;\r
        unsigned long flags;\r
-       t = kzalloc(sizeof(struct spi_gpio_irq_transfer), GFP_KERNEL);\r
+       t = kzalloc(sizeof(struct spi_gpio_irq_transfer), GFP_ATOMIC);\r
        if (!t)\r
        {\r
                printk("err:%s:ENOMEM\n",__FUNCTION__);\r
@@ -1028,10 +1030,9 @@ static void spi_gpio_irq_disable(unsigned irq)
        \r
        spin_lock_irqsave(&port->work_lock, flags);\r
        list_add_tail(&t->queue, &port->gpio.msg_queue);\r
-       queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work);\r
        spin_unlock_irqrestore(&port->work_lock, flags);\r
 \r
-\r
+       queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work);\r
 }\r
 \r
 static void spi_gpio_irq_mask(unsigned int irq)\r
@@ -1061,8 +1062,10 @@ static int spi_gpio_irq_set_type(unsigned int irq, unsigned int type)
        \r
        spin_lock_irqsave(&port->work_lock, flags);\r
        list_add_tail(&t->queue, &port->gpio.msg_queue);\r
-       queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work);\r
        spin_unlock_irqrestore(&port->work_lock, flags);\r
+\r
+       queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work);\r
+\r
        return 0;\r
 }\r
 \r
@@ -1083,8 +1086,10 @@ static int spi_gpio_irq_set_wake(unsigned irq, unsigned state)
        \r
        spin_lock_irqsave(&port->work_lock, flags);\r
        list_add_tail(&t->queue, &port->gpio.msg_queue);\r
-       queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work);\r
        spin_unlock_irqrestore(&port->work_lock, flags);\r
+\r
+       queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work);\r
+\r
        return 0;\r
 }\r
 \r
@@ -1167,7 +1172,7 @@ void spi_gpio_test_gpio_irq_init(void)
 \r
 }\r
 \r
-int spi_gpio_banks;\r
+static int spi_gpio_banks;\r
 static struct lock_class_key gpio_lock_class;\r
 \r
 /*\r