Messages in this thread Patch in this message | | | Date | Fri, 11 Mar 2011 15:27:44 -0800 | From | Andrew Morton <> | Subject | Re: [PATCH 3/4] calibrate: retry with wider bounds when converge seems to fail |
| |
On Thu, 10 Mar 2011 16:48:06 +0200 Phil Carmody <ext-phil.2.carmody@nokia.com> wrote:
> Systems with unmaskable interrupts such as SMIs may massively underestimate > loops_per_jiffy, and fail to converge anywhere near the real value. A case > seen on x86_64 was an initial estimate of 256<<12, which converged to 511<<12 > where the real value should have been over 630<<12. This admitedly requires > bypassing the TSC calibration (lpj_fine), and a failure to settle in the > direct calibration too, but is physically possible. This failure does not > depend on my previous calibration optimisation, but by luck is easy to fix > with the optimisation in place with a trivial retry loop. > > In the context of the optimised converging method, as we can no longer trust > the starting estimate, enlarge the search bounds exponentially so that the > number of retries is logarithmically bounded. > > ... > > @@ -165,6 +169,16 @@ static unsigned long __cpuinit calibrate_delay_converge(void) > lpj -= loopadd; > loopadd >>= 1; > } > + /* > + * If we incremented every single time possible, presume we've > + * massively underestimated initially, and retry with a higher > + * start, and larger range. (Only seen on x86_64.) > + */ > + if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) { > + lpj_base = lpj; > + loopadd_base <<= 2; > + goto recalibrate; > + }
This is more informative, no?
--- a/init/calibrate.c~calibrate-retry-with-wider-bounds-when-converge-seems-to-fail-fix +++ a/init/calibrate.c @@ -172,7 +172,7 @@ recalibrate: /* * If we incremented every single time possible, presume we've * massively underestimated initially, and retry with a higher - * start, and larger range. (Only seen on x86_64.) + * start, and larger range. (Only seen on x86_64, due to SMIs) */ if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) { lpj_base = lpj; _
| |