[PATCH 2/2] spi/pxa2xx: use a flag to check if the device is runtime suspended

From: Mika Westerberg
Date: Tue Jun 18 2013 - 10:27:44 EST


Current code calls pm_runtime_suspended() in the interrupt handler to check
if the device is suspended or not. However, runtime PM status of the device
is only set to suspended once all PM runtime suspend hooks have executed.

In our case we have the device bound to the ACPI power domain and its
runtime suspend hook will put the device to D3hot (or D3cold if possible).
This effectively means that the device is powered off before its state is
set to runtime suspended. During this time, it might get an interrupt that
is meant for another device (as the interrupt line is shared), and because
the device is powered off accessing its registers will return 0xffffffff
that the driver misinterprets as an invalid state. When this happens user
will see messages like below on the console:

pxa2xx-spi INT33C0:00: bad message state in interrupt handler

Fix this by adding flag to the driver private data that indicates whether
the device is runtime suspended, and in that case return IRQ_NONE from the
interrupt handler.

Signed-off-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx>
---
drivers/spi/spi-pxa2xx.c | 4 +++-
drivers/spi/spi-pxa2xx.h | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index b92a5d0..a105c03 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -536,7 +536,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
* the IRQ was not for us (we shouldn't be RPM suspended when the
* interrupt is enabled).
*/
- if (pm_runtime_suspended(&drv_data->pdev->dev))
+ if (drv_data->suspended)
return IRQ_NONE;

sccr1_reg = read_SSCR1(reg);
@@ -1309,6 +1309,7 @@ static int pxa2xx_spi_runtime_suspend(struct device *dev)
struct driver_data *drv_data = dev_get_drvdata(dev);

clk_disable_unprepare(drv_data->ssp->clk);
+ drv_data->suspended = true;
return 0;
}

@@ -1317,6 +1318,7 @@ static int pxa2xx_spi_runtime_resume(struct device *dev)
struct driver_data *drv_data = dev_get_drvdata(dev);

clk_prepare_enable(drv_data->ssp->clk);
+ drv_data->suspended = false;
return 0;
}
#endif
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 5adc2a1..a5f8bb5 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -86,6 +86,7 @@ struct driver_data {
int (*read)(struct driver_data *drv_data);
irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
void (*cs_control)(u32 command);
+ bool suspended;

void __iomem *lpss_base;
};
--
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/