Commit 6438a694 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Samuel Ortiz

mfd: pcf50633-adc: Fix potential race in pcf50633_adc_sync_read

Currently it's not guaranteed that request struct is not already freed when
reading from it. Fix this by moving synced request related fields from the
pcf50633_adc_request struct to its own struct and store it on the functions
stack.
Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 0aeee5d4
...@@ -30,13 +30,13 @@ ...@@ -30,13 +30,13 @@
struct pcf50633_adc_request { struct pcf50633_adc_request {
int mux; int mux;
int avg; int avg;
int result;
void (*callback)(struct pcf50633 *, void *, int); void (*callback)(struct pcf50633 *, void *, int);
void *callback_param; void *callback_param;
};
/* Used in case of sync requests */ struct pcf50633_adc_sync_request {
int result;
struct completion completion; struct completion completion;
}; };
#define PCF50633_MAX_ADC_FIFO_DEPTH 8 #define PCF50633_MAX_ADC_FIFO_DEPTH 8
...@@ -109,10 +109,10 @@ adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req) ...@@ -109,10 +109,10 @@ adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req)
return 0; return 0;
} }
static void static void pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param,
pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result) int result)
{ {
struct pcf50633_adc_request *req = param; struct pcf50633_adc_sync_request *req = param;
req->result = result; req->result = result;
complete(&req->completion); complete(&req->completion);
...@@ -120,28 +120,19 @@ pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result) ...@@ -120,28 +120,19 @@ pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result)
int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg) int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg)
{ {
struct pcf50633_adc_request *req; struct pcf50633_adc_sync_request req;
int err; int ret;
/* req is freed when the result is ready, in interrupt handler */ init_completion(&req.completion);
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
req->mux = mux;
req->avg = avg;
req->callback = pcf50633_adc_sync_read_callback;
req->callback_param = req;
init_completion(&req->completion); ret = pcf50633_adc_async_read(pcf, mux, avg,
err = adc_enqueue_request(pcf, req); pcf50633_adc_sync_read_callback, &req);
if (err) if (ret)
return err; return ret;
wait_for_completion(&req->completion); wait_for_completion(&req.completion);
/* FIXME by this time req might be already freed */ return req.result;
return req->result;
} }
EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read); EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment