From 272df502bcd1fbb1b95facc92bd861d604be8871 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 31 Mar 2011 07:18:46 +0900 Subject: [PATCH 1/5] gpio/pca953x: fix error handling path in probe() call If the device fails to respond, then the error path tries to remove an interrupt that never got registered, which causes an backtrace from the interrupt handling code. Fix this by ensuring that the cleanup path has two labels and use the correct path as needed. fixes the following error: WARNING: at kernel/irq/manage.c:908 __free_irq+0x80/0x160() Trying to free already-free IRQ 0 Signed-off-by: Ben Dooks Signed-off-by: Mark Brown Signed-off-by: Grant Likely --- drivers/gpio/pca953x.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 583e92592073..7630ab7b9bec 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -558,7 +558,7 @@ static int __devinit pca953x_probe(struct i2c_client *client, ret = gpiochip_add(&chip->gpio_chip); if (ret) - goto out_failed; + goto out_failed_irq; if (pdata->setup) { ret = pdata->setup(client, chip->gpio_chip.base, @@ -570,8 +570,9 @@ static int __devinit pca953x_probe(struct i2c_client *client, i2c_set_clientdata(client, chip); return 0; -out_failed: +out_failed_irq: pca953x_irq_teardown(chip); +out_failed: kfree(chip->dyn_pdata); kfree(chip); return ret; From ba43861277f1858472de4adfc0b28a047484da83 Mon Sep 17 00:00:00 2001 From: Peter Tyser Date: Thu, 24 Mar 2011 18:17:14 -0500 Subject: [PATCH 2/5] gpio/ml_ioh_gpio: Fix output value of ioh_gpio_direction_output() The ioh_gpio_direction_output() function was missing a write to set the desired output value. The function would properly set the GPIO direction, but not the output value. The value would have to manually be set with a follow up call to ioh_gpio_set(). Add the missing write so that ioh_gpio_direction_output() sets both the GPIO direction and value. Signed-off-by: Peter Tyser Tested-by: Tomoya MORINAGA Signed-off-by: Grant Likely --- drivers/gpio/ml_ioh_gpio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/ml_ioh_gpio.c b/drivers/gpio/ml_ioh_gpio.c index 7f6f01a4b145..0a775f7987c2 100644 --- a/drivers/gpio/ml_ioh_gpio.c +++ b/drivers/gpio/ml_ioh_gpio.c @@ -116,6 +116,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, reg_val |= (1 << nr); else reg_val &= ~(1 << nr); + iowrite32(reg_val, &chip->reg->regs[chip->ch].po); mutex_unlock(&chip->lock); From 88aab9341a315d81118be6b41c45e4fe32b94bc1 Mon Sep 17 00:00:00 2001 From: Peter Tyser Date: Fri, 25 Mar 2011 10:04:00 -0500 Subject: [PATCH 3/5] gpio/pch_gpio: Fix output value of pch_gpio_direction_output() The pch_gpio_direction_output() function was missing a write to set the desired output value. The function would properly set the GPIO direction, but not the output value. The value would have to manually be set with a follow up call to pch_gpio_set(). Add the missing write so that pch_gpio_direction_output() sets both the GPIO direction and value. Signed-off-by: Peter Tyser Tested-by: Tomoya MORINAGA Signed-off-by: Grant Likely --- drivers/gpio/pch_gpio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c index 2c6af8705103..f970a5f3585e 100644 --- a/drivers/gpio/pch_gpio.c +++ b/drivers/gpio/pch_gpio.c @@ -105,6 +105,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, reg_val |= (1 << nr); else reg_val &= ~(1 << nr); + iowrite32(reg_val, &chip->reg->po); mutex_unlock(&chip->lock); From 850a28ecd8044ef36b2c7699d2e3736a410b4d0a Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Wed, 6 Apr 2011 17:49:15 +0300 Subject: [PATCH 4/5] spi: Fix race condition in stop_queue() There's a race condition in stop_queue() in some drivers - if drv_data->queue is empty, but drv_data->busy is still set (or opposite situation) stop_queue will return -EBUSY. So fix loop condition to check that both drv_data->queue is empty and drv_data->busy is not set. This patch affects following drivers: pxa2xx_spi spi_bfin5xx amba-pl022 dw_spi Signed-off-by: Vasily Khoruzhick Acked-by: Eric Miao Acked-by: Mike Frysinger Signed-off-by: Grant Likely --- drivers/spi/amba-pl022.c | 2 +- drivers/spi/dw_spi.c | 2 +- drivers/spi/pxa2xx_spi.c | 2 +- drivers/spi/spi_bfin5xx.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 5a4e0afb9ad6..4b8357b728cb 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -1555,7 +1555,7 @@ static int stop_queue(struct pl022 *pl022) * A wait_queue on the pl022->busy could be used, but then the common * execution path (pump_messages) would be required to call wake_up or * friends on every SPI message. Do this instead */ - while (!list_empty(&pl022->queue) && pl022->busy && limit--) { + while ((!list_empty(&pl022->queue) || pl022->busy) && limit--) { spin_unlock_irqrestore(&pl022->queue_lock, flags); msleep(10); spin_lock_irqsave(&pl022->queue_lock, flags); diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index 9a6196461b27..d040debc07c2 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c @@ -821,7 +821,7 @@ static int stop_queue(struct dw_spi *dws) spin_lock_irqsave(&dws->lock, flags); dws->run = QUEUE_STOPPED; - while (!list_empty(&dws->queue) && dws->busy && limit--) { + while ((!list_empty(&dws->queue) || dws->busy) && limit--) { spin_unlock_irqrestore(&dws->lock, flags); msleep(10); spin_lock_irqsave(&dws->lock, flags); diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index a429b01d0285..3aa782067b68 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1493,7 +1493,7 @@ static int stop_queue(struct driver_data *drv_data) * execution path (pump_messages) would be required to call wake_up or * friends on every SPI message. Do this instead */ drv_data->run = QUEUE_STOPPED; - while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) { + while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) { spin_unlock_irqrestore(&drv_data->lock, flags); msleep(10); spin_lock_irqsave(&drv_data->lock, flags); diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index a28462486df8..f3a1c52c0fb0 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -1284,7 +1284,7 @@ static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data) * friends on every SPI message. Do this instead */ drv_data->running = false; - while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) { + while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) { spin_unlock_irqrestore(&drv_data->lock, flags); msleep(10); spin_lock_irqsave(&drv_data->lock, flags); From 8faa7cf828bca1745a4ed599876567f5afc47544 Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Thu, 7 Apr 2011 10:33:03 -0700 Subject: [PATCH 5/5] dt/fsldma: fix build warning caused by of_platform_device changes Commit 000061245a6797d542854106463b6b20fbdcb12e, "dt/powerpc: Eliminate users of of_platform_{,un}register_driver" forgot to convert the type of structure passed into platform_device_register() when it was converted from of_platform_device_register. Fix it. Signed-off-by: Ira W. Snyder Signed-off-by: Grant Likely --- drivers/dma/fsldma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 6b396759e7f5..8a781540590c 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1448,7 +1448,7 @@ static const struct of_device_id fsldma_of_ids[] = { {} }; -static struct of_platform_driver fsldma_of_driver = { +static struct platform_driver fsldma_of_driver = { .driver = { .name = "fsl-elo-dma", .owner = THIS_MODULE,