mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
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: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
0aeee5d4f6
commit
6438a694b6
1 changed files with 15 additions and 24 deletions
|
@ -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)
|
||||||
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)
|
||||||
|
|
||||||
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;
|
ret = pcf50633_adc_async_read(pcf, mux, avg,
|
||||||
req->avg = avg;
|
pcf50633_adc_sync_read_callback, &req);
|
||||||
req->callback = pcf50633_adc_sync_read_callback;
|
if (ret)
|
||||||
req->callback_param = req;
|
return ret;
|
||||||
|
|
||||||
init_completion(&req->completion);
|
wait_for_completion(&req.completion);
|
||||||
err = adc_enqueue_request(pcf, req);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
wait_for_completion(&req->completion);
|
return req.result;
|
||||||
|
|
||||||
/* FIXME by this time req might be already freed */
|
|
||||||
return req->result;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read);
|
EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue