ASoC: Intel: Common: Update dsp register poll implementation
authorJeeja KP <jeeja.kp@intel.com>
Mon, 2 Jan 2017 04:20:02 +0000 (09:50 +0530)
committerMark Brown <broonie@kernel.org>
Fri, 6 Jan 2017 18:14:45 +0000 (18:14 +0000)
Poll implementation is not quite accurate, especially for smaller
values of timeout or timeout values close to the actual timeout needed

Use jiffies to set the timeout value and time_before() to get the
accurate time. So update the dsp register poll implementation to
provide accurate timeout using jiffies.

Signed-off-by: Jayachandran B <jayachandran.b@intel.com>
Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/common/sst-dsp.c

index c00ede4ea4d7040c255556802ea8ebddd12bd1ad..11c0805393ff96c50b03b2b29fb70a32b53fa3dc 100644 (file)
@@ -252,44 +252,44 @@ void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset,
 EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced);
 
 int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
-                        u32 target, u32 timeout, char *operation)
+                        u32 target, u32 time, char *operation)
 {
-       int time, ret;
        u32 reg;
-       bool done = false;
+       unsigned long timeout;
+       int k = 0, s = 500;
 
        /*
-        * we will poll for couple of ms using mdelay, if not successful
-        * then go to longer sleep using usleep_range
+        * split the loop into sleeps of varying resolution. more accurately,
+        * the range of wakeups are:
+        * Phase 1(first 5ms): min sleep 0.5ms; max sleep 1ms.
+        * Phase 2:( 5ms to 10ms) : min sleep 0.5ms; max sleep 10ms
+        * (usleep_range (500, 1000) and usleep_range(5000, 10000) are
+        * both possible in this phase depending on whether k > 10 or not).
+        * Phase 3: (beyond 10 ms) min sleep 5ms; max sleep 10ms.
         */
 
-       /* check if set state successful */
-       for (time = 0; time < 5; time++) {
-               if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) {
-                       done = true;
-                       break;
-               }
-               mdelay(1);
+       timeout = jiffies + msecs_to_jiffies(time);
+       while (((sst_dsp_shim_read_unlocked(ctx, offset) & mask) != target)
+               && time_before(jiffies, timeout)) {
+               k++;
+               if (k > 10)
+                       s = 5000;
+
+               usleep_range(s, 2*s);
        }
 
-       if (done ==  false) {
-               /* sleeping in 10ms steps so adjust timeout value */
-               timeout /= 10;
+       reg = sst_dsp_shim_read_unlocked(ctx, offset);
 
-               for (time = 0; time < timeout; time++) {
-                       if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target)
-                               break;
+       if ((reg & mask) == target) {
+               dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s successful\n",
+                                       reg, operation);
 
-                       usleep_range(5000, 10000);
-               }
+               return 0;
        }
 
-       reg = sst_dsp_shim_read_unlocked(ctx, offset);
-       dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s %s\n", reg, operation,
-                       (time < timeout) ? "successful" : "timedout");
-       ret = time < timeout ? 0 : -ETIME;
-
-       return ret;
+       dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s timedout\n",
+                                       reg, operation);
+       return -ETIME;
 }
 EXPORT_SYMBOL_GPL(sst_dsp_register_poll);