aboutsummaryrefslogtreecommitdiff
path: root/drivers/mfd/pcf50633-adc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-18 09:22:36 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-18 09:22:36 -0700
commit6f130478e24d810078c3f0ee292bcc4ec034dcce (patch)
tree1c782ccceaf998e9e23862094588c125ee6f38af /drivers/mfd/pcf50633-adc.c
parent6f128fa344833bf8bf076a51d14401661c146470 (diff)
parent75f2ba8f0006440e720e47ae14c917e07c452d72 (diff)
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (55 commits) regulator: Voltage count for AB3100 mfd: Convert WM8350 to use request_threaded_irq() mfd: Update MAINTAINERS patterns for WM831x mfd: Fix twl4030-power warnings regulator: AB3100 support rtc: AB3100 RTC support mfd: Fix ab3100-otp build failure mfd: OMAP: Board-specifc twl4030 DPS scripts for RX51 board mfd: Print warning for twl4030 out-of-order script loading mfd: Add support for TWL4030/5030 dynamic power switching mfd: AB3100 OTP readout regulator: Add Freescale MC13783 driver mfd: Add Freescale MC13783 driver mfd: AB3100 disable irq nosync mfd: AB3100 alter default setting mfd: AB3100 propagate error mfd: AB3100 accessor function cleanups rtc: Add support for RTCs on Wolfson WM831x devices regulator: get pcap data from the parent device input: PCAP2 misc input driver ...
Diffstat (limited to 'drivers/mfd/pcf50633-adc.c')
-rw-r--r--drivers/mfd/pcf50633-adc.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
index c2d05becfa9..3d31e97d6a4 100644
--- a/drivers/mfd/pcf50633-adc.c
+++ b/drivers/mfd/pcf50633-adc.c
@@ -73,15 +73,10 @@ static void trigger_next_adc_job_if_any(struct pcf50633 *pcf)
struct pcf50633_adc *adc = __to_adc(pcf);
int head;
- mutex_lock(&adc->queue_mutex);
-
head = adc->queue_head;
- if (!adc->queue[head]) {
- mutex_unlock(&adc->queue_mutex);
+ if (!adc->queue[head])
return;
- }
- mutex_unlock(&adc->queue_mutex);
adc_setup(pcf, adc->queue[head]->mux, adc->queue[head]->avg);
}
@@ -99,16 +94,17 @@ adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req)
if (adc->queue[tail]) {
mutex_unlock(&adc->queue_mutex);
+ dev_err(pcf->dev, "ADC queue is full, dropping request\n");
return -EBUSY;
}
adc->queue[tail] = req;
+ if (head == tail)
+ trigger_next_adc_job_if_any(pcf);
adc->queue_tail = (tail + 1) & (PCF50633_MAX_ADC_FIFO_DEPTH - 1);
mutex_unlock(&adc->queue_mutex);
- trigger_next_adc_job_if_any(pcf);
-
return 0;
}
@@ -124,6 +120,7 @@ pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result)
int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg)
{
struct pcf50633_adc_request *req;
+ int err;
/* req is freed when the result is ready, in interrupt handler */
req = kzalloc(sizeof(*req), GFP_KERNEL);
@@ -136,9 +133,13 @@ int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg)
req->callback_param = req;
init_completion(&req->completion);
- adc_enqueue_request(pcf, req);
+ err = adc_enqueue_request(pcf, req);
+ if (err)
+ return err;
+
wait_for_completion(&req->completion);
+ /* FIXME by this time req might be already freed */
return req->result;
}
EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read);
@@ -159,9 +160,7 @@ int pcf50633_adc_async_read(struct pcf50633 *pcf, int mux, int avg,
req->callback = callback;
req->callback_param = callback_param;
- adc_enqueue_request(pcf, req);
-
- return 0;
+ return adc_enqueue_request(pcf, req);
}
EXPORT_SYMBOL_GPL(pcf50633_adc_async_read);
@@ -184,7 +183,7 @@ static void pcf50633_adc_irq(int irq, void *data)
struct pcf50633_adc *adc = data;
struct pcf50633 *pcf = adc->pcf;
struct pcf50633_adc_request *req;
- int head;
+ int head, res;
mutex_lock(&adc->queue_mutex);
head = adc->queue_head;
@@ -199,12 +198,13 @@ static void pcf50633_adc_irq(int irq, void *data)
adc->queue_head = (head + 1) &
(PCF50633_MAX_ADC_FIFO_DEPTH - 1);
+ res = adc_result(pcf);
+ trigger_next_adc_job_if_any(pcf);
+
mutex_unlock(&adc->queue_mutex);
- req->callback(pcf, req->callback_param, adc_result(pcf));
+ req->callback(pcf, req->callback_param, res);
kfree(req);
-
- trigger_next_adc_job_if_any(pcf);
}
static int __devinit pcf50633_adc_probe(struct platform_device *pdev)