udelay.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. * This file is part of the flashrom project.
  3. *
  4. * Copyright (C) 2000 Silicon Integrated System Corporation
  5. * Copyright (C) 2009,2010 Carl-Daniel Hailfinger
  6. * Copyright (C) 2011 Google Inc.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #ifndef __LIBPAYLOAD__
  23. #include <unistd.h>
  24. #include <sys/time.h>
  25. #include <time.h>
  26. #include <stdlib.h>
  27. #include <limits.h>
  28. #include <errno.h>
  29. #include "flash.h"
  30. /* 100ms is currently the highest delay period for operations that are expected
  31. * to be called repeatedly (such as block erases). Delays beyond that are used
  32. * in rare circumstances, so a few extra milliseconds delay shouldn't have much
  33. * impact on overall runtime.
  34. */
  35. #define IMPRECISE_MIN_DELAY_THRESHOLD_US (100 * 1000)
  36. /* Are OS timers broken? */
  37. int broken_timer = 0;
  38. /* loops per microsecond */
  39. static unsigned long micro = 1;
  40. __attribute__ ((noinline)) void myusec_delay(int usecs)
  41. {
  42. unsigned long i;
  43. for (i = 0; i < usecs * micro; i++) {
  44. /* Make sure the compiler doesn't optimize the loop away. */
  45. asm volatile ("" : : "rm" (i) );
  46. }
  47. }
  48. static unsigned long measure_os_delay_resolution(void)
  49. {
  50. unsigned long timeusec;
  51. struct timeval start, end;
  52. unsigned long counter = 0;
  53. gettimeofday(&start, NULL);
  54. timeusec = 0;
  55. while (!timeusec && (++counter < 1000000000)) {
  56. gettimeofday(&end, NULL);
  57. timeusec = 1000000 * (end.tv_sec - start.tv_sec) +
  58. (end.tv_usec - start.tv_usec);
  59. /* Protect against time going forward too much. */
  60. if ((end.tv_sec > start.tv_sec) &&
  61. ((end.tv_sec - start.tv_sec) >= LONG_MAX / 1000000 - 1))
  62. timeusec = 0;
  63. /* Protect against time going backwards during leap seconds. */
  64. if ((end.tv_sec < start.tv_sec) || (timeusec > LONG_MAX))
  65. timeusec = 0;
  66. }
  67. return timeusec;
  68. }
  69. static unsigned long measure_delay(int usecs)
  70. {
  71. unsigned long timeusec;
  72. struct timeval start, end;
  73. gettimeofday(&start, NULL);
  74. myusec_delay(usecs);
  75. gettimeofday(&end, NULL);
  76. timeusec = 1000000 * (end.tv_sec - start.tv_sec) +
  77. (end.tv_usec - start.tv_usec);
  78. /* Protect against time going forward too much. */
  79. if ((end.tv_sec > start.tv_sec) &&
  80. ((end.tv_sec - start.tv_sec) >= LONG_MAX / 1000000 - 1))
  81. timeusec = LONG_MAX;
  82. /* Protect against time going backwards during leap seconds. */
  83. if ((end.tv_sec < start.tv_sec) || (timeusec > LONG_MAX))
  84. timeusec = 1;
  85. return timeusec;
  86. }
  87. void myusec_calibrate_delay(void)
  88. {
  89. unsigned long count = 1000;
  90. unsigned long timeusec, resolution;
  91. int i, tries = 0;
  92. if (!broken_timer)
  93. return;
  94. msg_pdbg("Calibrating delay loop... ");
  95. resolution = measure_os_delay_resolution();
  96. if (resolution) {
  97. msg_pdbg("OS timer resolution is %lu usecs, ", resolution);
  98. } else {
  99. msg_pinfo("OS timer resolution is unusable. ");
  100. }
  101. recalibrate:
  102. count = 1000;
  103. while (1) {
  104. timeusec = measure_delay(count);
  105. if (timeusec > 1000000 / 4)
  106. break;
  107. if (count >= ULONG_MAX / 2) {
  108. msg_pinfo("timer loop overflow, reduced precision. ");
  109. break;
  110. }
  111. count *= 2;
  112. }
  113. tries ++;
  114. /* Avoid division by zero, but in that case the loop is shot anyway. */
  115. if (!timeusec)
  116. timeusec = 1;
  117. /* Compute rounded up number of loops per microsecond. */
  118. micro = (count * micro) / timeusec + 1;
  119. msg_pdbg("%luM loops per second, ", micro);
  120. /* Did we try to recalibrate less than 5 times? */
  121. if (tries < 5) {
  122. /* Recheck our timing to make sure we weren't just hitting
  123. * a scheduler delay or something similar.
  124. */
  125. for (i = 0; i < 4; i++) {
  126. if (resolution && (resolution < 10)) {
  127. timeusec = measure_delay(100);
  128. } else if (resolution &&
  129. (resolution < ULONG_MAX / 200)) {
  130. timeusec = measure_delay(resolution * 10) *
  131. 100 / (resolution * 10);
  132. } else {
  133. /* This workaround should be active for broken
  134. * OS and maybe libpayload. The criterion
  135. * here is horrible or non-measurable OS timer
  136. * resolution which will result in
  137. * measure_delay(100)=0 whereas a longer delay
  138. * (1000 ms) may be sufficient
  139. * to get a nonzero time measurement.
  140. */
  141. timeusec = measure_delay(1000000) / 10000;
  142. }
  143. if (timeusec < 90) {
  144. msg_pdbg("delay more than 10%% too short (got "
  145. "%lu%% of expected delay), "
  146. "recalculating... ", timeusec);
  147. goto recalibrate;
  148. }
  149. }
  150. } else {
  151. msg_perr("delay loop is unreliable, trying to continue ");
  152. }
  153. /* We're interested in the actual precision. */
  154. timeusec = measure_delay(10);
  155. msg_pdbg("10 myus = %ld us, ", timeusec);
  156. timeusec = measure_delay(100);
  157. msg_pdbg("100 myus = %ld us, ", timeusec);
  158. timeusec = measure_delay(1000);
  159. msg_pdbg("1000 myus = %ld us, ", timeusec);
  160. timeusec = measure_delay(10000);
  161. msg_pdbg("10000 myus = %ld us, ", timeusec);
  162. timeusec = measure_delay(resolution * 4);
  163. msg_pdbg("%ld myus = %ld us, ", resolution * 4, timeusec);
  164. msg_pdbg("OK.\n");
  165. }
  166. static void imprecise_delay(int usecs)
  167. {
  168. int ret, done_waiting = 0;
  169. unsigned long long nsecs;
  170. struct timespec req = { 0, 0 };
  171. /* flashrom delays work with a microsecond granularity. However
  172. * usleep has been obsoleted in POSIX.1-2001 and removed from
  173. * POSIX.1-2008 with the suggestion to use nanosleep(2) instead.
  174. */
  175. nsecs = 1000ULL * usecs;
  176. req.tv_sec = nsecs / 1000000000ULL;
  177. req.tv_nsec = nsecs % 1000000000ULL;
  178. while (!done_waiting) {
  179. struct timespec rem;
  180. ret = nanosleep(&req, &rem);
  181. if (ret && (errno == EINTR)) {
  182. req = rem;
  183. continue;
  184. }
  185. done_waiting = 1;
  186. }
  187. /* If nanosleep reports problems with copying information from user
  188. * space we fall back to the "broken timer" code.
  189. */
  190. if (ret && (errno == EFAULT)) {
  191. broken_timer = 1;
  192. /* Since we use delays quite early (i.e. during probing)
  193. * we can recalibrate our delay loop interjacently without
  194. * risking data integrity. This will only happen once.
  195. */
  196. myusec_calibrate_delay();
  197. /* Now, for the sake of it, delay. */
  198. myusec_delay(usecs);
  199. }
  200. }
  201. void internal_delay(int usecs)
  202. {
  203. if (broken_timer) {
  204. /* Very long delays don't need much precision, so use nanosleep
  205. * instead of busy waiting to avoid excessive overhead.
  206. */
  207. if (usecs > IMPRECISE_MIN_DELAY_THRESHOLD_US)
  208. imprecise_delay(usecs);
  209. else
  210. myusec_delay(usecs);
  211. } else {
  212. imprecise_delay(usecs);
  213. }
  214. }
  215. #else
  216. #include <libpayload.h>
  217. void myusec_calibrate_delay(void)
  218. {
  219. get_cpu_speed();
  220. }
  221. void internal_delay(int usecs)
  222. {
  223. udelay(usecs);
  224. }
  225. #endif