From: 黄涛 Date: Tue, 12 Oct 2010 09:52:55 +0000 (+0800) Subject: spi_fpga_init: fix slab corruption bug X-Git-Tag: firefly_0821_release~11068 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=cf60841e0249936ff12189f27d368d5e447e46eb;p=firefly-linux-kernel-4.4.55.git spi_fpga_init: fix slab corruption bug 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 --- diff --git a/drivers/fpga/spi_fpga_init.c b/drivers/fpga/spi_fpga_init.c index e26a131c111c..a6ca4c1cbc4e 100755 --- a/drivers/fpga/spi_fpga_init.c +++ b/drivers/fpga/spi_fpga_init.c @@ -71,36 +71,32 @@ static void spi_fpga_trans_work_handler(struct work_struct *work) { struct spi_fpga_port *port = container_of(work, struct spi_fpga_port, fpga_trans_work); - unsigned long flags; - spin_lock_irqsave(&port->work_lock, flags); - while (!list_empty(&port->trans_queue)) - { - spin_unlock_irqrestore(&port->work_lock, flags); - struct spi_fpga_transfer *t = NULL, *tmp; - list_for_each_entry_safe(t, tmp, &port->trans_queue, queue) - { - if (t->id == 0) - break; - DBG("%s:id=%d,txbuf=0x%x\n",__FUNCTION__,t->id,(int)t->txbuf); - switch(t->id) - { - case ID_SPI_FPGA_WRITE: - spi_write(port->spi, t->txbuf, t->n_tx); - break; - default: - break; - - } - kfree(t->txbuf); - kfree(t); - } + while (1) { + unsigned long flags; + struct spi_fpga_transfer *t = NULL; + spin_lock_irqsave(&port->work_lock, flags); - list_del_init(&port->trans_queue); + if (!list_empty(&port->trans_queue)) { + t = list_first_entry(&port->trans_queue, struct spi_fpga_transfer, queue); + list_del(&t->queue); + } + spin_unlock_irqrestore(&port->work_lock, flags); - } - spin_unlock_irqrestore(&port->work_lock, flags); + if (!t) // trans_queue empty + break; + DBG("%s:id=%d,txbuf=0x%x\n",__FUNCTION__,t->id,(int)t->txbuf); + switch (t->id) { + case ID_SPI_FPGA_WRITE: + spi_write(port->spi, t->txbuf, t->n_tx); + break; + default: + break; + } + kfree(t->txbuf); + kfree(t); + } } int spi_write_work(struct spi_device *spi, u8 *buf, size_t len) @@ -129,8 +125,8 @@ int spi_write_work(struct spi_device *spi, u8 *buf, size_t len) spin_lock_irqsave(&port->work_lock, flags); list_add_tail(&t->queue, &port->trans_queue); - queue_work(port->fpga_trans_workqueue, &port->fpga_trans_work); spin_unlock_irqrestore(&port->work_lock, flags); + queue_work(port->fpga_trans_workqueue, &port->fpga_trans_work); return 0; @@ -685,43 +681,43 @@ static int spi_fpga_wait_suspend(struct spi_fpga_port *port) } return -1; -} - -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); +} + +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); } static int spi_fpga_suspend(struct spi_device *spi, pm_message_t state) { - struct spi_fpga_port *port = dev_get_drvdata(&spi->dev); - fpga_close_power_support( ); + struct spi_fpga_port *port = dev_get_drvdata(&spi->dev); int ret; + fpga_close_power_support( ); ret = spi_fpga_wait_suspend(port); if(!ret) {