gpadc: fix sample result error
authorBin Yang <bin.yang@intel.com>
Thu, 6 Oct 2011 15:18:30 +0000 (16:18 +0100)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 21:17:20 +0000 (13:17 -0800)
During stress test, ADC results have some bad valules.
Driver has a race condition issue. It initializes the output data to 0 first
without any lock. And the caller may access the output pointer before function
return.

This patch moves the output data initializing code inside mutex protected period.
And it also adds a limitation which forbid caller to access output pointer
before function return.

Change-Id: I7a108abf4fc5c0bb7a2e9c135add4f977d29c919
Signed-off-by: Bin Yang <bin.yang@intel.com>
drivers/hwmon/intel_mid_gpadc.c

index 5f429c9..64b15db 100644 (file)
@@ -268,8 +268,8 @@ static void free_channel_addr(struct gpadc_info *mgi, int addr)
 
 /**
  * intel_mid_gpadc_gsmpulse_sample - do gpadc sample during gsm pulse.
- * @val: return the voltage value.
- * @cur: return the current value.
+ * @val: return the voltage value. caller should not access it before return.
+ * @cur: return the current value. caller should not access it before return.
  *
  * Returns 0 on success or an error code.
  *
@@ -336,6 +336,7 @@ EXPORT_SYMBOL(intel_mid_gpadc_gsmpulse_sample);
  * @handle: the gpadc handle
  * @sample_count: do sample serveral times and get the average value.
  * @...: sampling resulting arguments of all channels. refer to sscanf.
+ *       caller should not access it before return.
  *
  * Returns 0 on success or an error code.
  *
@@ -357,6 +358,7 @@ int intel_mid_gpadc_sample(void *handle, int sample_count, ...)
        if (!mgi->initialized)
                return -ENODEV;
 
+       mutex_lock(&mgi->lock);
        va_start(args, sample_count);
        for (i = 0; i < rq->count; i++) {
                val[i] = va_arg(args, int*);
@@ -364,7 +366,6 @@ int intel_mid_gpadc_sample(void *handle, int sample_count, ...)
        }
        va_end(args);
 
-       mutex_lock(&mgi->lock);
        pm_qos_add_request(&mgi->pm_qos_request,
                           PM_QOS_CPU_DMA_LATENCY, PM_QOS_ADC_DRV_VALUE);
        gpadc_poweron(mgi, rq->vref);