[PATCH] ARM: SAMSUNG: Clean up timed-out adc transaction
From: Huisung Kang <hidden>
Date: 2012-02-11 02:52:40
Also in:
linux-samsung-soc
From: Sung-Taek Lim <redacted> This patch tries to clean up timed-out adc transaction. Otherwise, time-out adc transaction remains as adc->cur permanently and may block other incoming adc transactions. Signed-off-by: Sung-Taek Lim <redacted> Signed-off-by: KeyYoung Park <redacted> Signed-off-by: Huisung Kang <redacted> --- arch/arm/plat-samsung/adc.c | 54 +++++++++++++++++++++++------------------- 1 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index e4e965c..fccc644 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c@@ -185,6 +185,34 @@ int s3c_adc_start(struct s3c_adc_client *client, } EXPORT_SYMBOL_GPL(s3c_adc_start); +static void s3c_adc_stop(struct s3c_adc_client *client) { + unsigned long flags; + + spin_lock_irqsave(&adc_dev->lock, flags); + + /* We should really check that nothing is in progress. */ + if (adc_dev->cur == client) + adc_dev->cur = NULL; + if (adc_dev->ts_pend == client) + adc_dev->ts_pend = NULL; + else { + struct list_head *p, *n; + struct s3c_adc_client *tmp; + + list_for_each_safe(p, n, &adc_pending) { + tmp = list_entry(p, struct s3c_adc_client, pend); + if (tmp == client) + list_del(&tmp->pend); + } + } + + if (adc_dev->cur == NULL) + s3c_adc_try(adc_dev); + + spin_unlock_irqrestore(&adc_dev->lock, flags); } + static void s3c_convert_done(struct s3c_adc_client *client, unsigned v, unsigned u, unsigned *left) { @@ -207,6 +235,7 @@ int s3c_adc_read(struct s3c_adc_client
*client, unsigned int ch)
ret = wait_event_timeout(wake, client->result >= 0, HZ / 2);
if (client->result < 0) {
+ s3c_adc_stop(client);
ret = -ETIMEDOUT;
goto err;
}@@ -259,30 +288,7 @@ EXPORT_SYMBOL_GPL(s3c_adc_register); void s3c_adc_release(struct s3c_adc_client *client) { - unsigned long flags; - - spin_lock_irqsave(&adc_dev->lock, flags); - - /* We should really check that nothing is in progress. */ - if (adc_dev->cur == client) - adc_dev->cur = NULL; - if (adc_dev->ts_pend == client) - adc_dev->ts_pend = NULL; - else { - struct list_head *p, *n; - struct s3c_adc_client *tmp; - - list_for_each_safe(p, n, &adc_pending) { - tmp = list_entry(p, struct s3c_adc_client, pend); - if (tmp == client) - list_del(&tmp->pend); - } - } - - if (adc_dev->cur == NULL) - s3c_adc_try(adc_dev); - - spin_unlock_irqrestore(&adc_dev->lock, flags); + s3c_adc_stop(client); kfree(client); } EXPORT_SYMBOL_GPL(s3c_adc_release); --
1.7.1