| @@ -74,6 +74,8 @@ static struct clocksource *watchdog; · 73 unmodified lines |
| 74 | 74 | static struct timer_list watchdog_timer; |
| 75 | 75 | static DEFINE_SPINLOCK(watchdog_lock); |
| 76 | 76 | static cycle_t watchdog_last; |
| 77 | +static int watchdog_resumed; |
| 78 | + |
| 77 | 79 | /* |
| 78 | 80 | * Interval: 0.5sec Threshold: 0.0625s |
| 79 | 81 | */ |
| @@ -98,15 +100,26 @@ static void clocksource_watchdog(unsigned long data) · 18 unmodified lines |
| 98 | 100 | struct clocksource *cs, *tmp; |
| 99 | 101 | cycle_t csnow, wdnow; |
| 100 | 102 | int64_t wd_nsec, cs_nsec; |
| 103 | + int resumed; |
| 101 | 104 | |
| 102 | 105 | spin_lock(&watchdog_lock); |
| 103 | 106 | |
| 107 | + resumed = watchdog_resumed; |
| 108 | + if (unlikely(resumed)) |
| 109 | + watchdog_resumed = 0; |
| 110 | + |
| 104 | 111 | wdnow = watchdog->read(); |
| 105 | 112 | wd_nsec = cyc2ns(watchdog, (wdnow - watchdog_last) & watchdog->mask); |
| 106 | 113 | watchdog_last = wdnow; |
| 107 | 114 | |
| 108 | 115 | list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) { |
| 109 | 116 | csnow = cs->read(); |
| 117 | + |
| 118 | + if (unlikely(resumed)) { |
| 119 | + cs->wd_last = csnow; |
| 120 | + continue; |
| 121 | + } |
| 122 | + |
| 110 | 123 | /* Initialized ? */ |
| 111 | 124 | if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) { |
| 112 | 125 | if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) && |
| @@ -136,6 +149,13 @@ static void clocksource_watchdog(unsigned long data) · 23 unmodified lines |
| 136 | 149 | } |
| 137 | 150 | spin_unlock(&watchdog_lock); |
| 138 | 151 | } |
| 152 | +static void clocksource_resume_watchdog(void) |
| 153 | +{ |
| 154 | + spin_lock(&watchdog_lock); |
| 155 | + watchdog_resumed = 1; |
| 156 | + spin_unlock(&watchdog_lock); |
| 157 | +} |
| 158 | + |
| 139 | 159 | static void clocksource_check_watchdog(struct clocksource *cs) |
| 140 | 160 | { |
| 141 | 161 | struct clocksource *cse; |
| @@ -182,8 +202,33 @@ static void clocksource_check_watchdog(struct clocksource *cs) · 40 unmodified lines |
| 182 | 202 | if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) |
| 183 | 203 | cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; |
| 184 | 204 | } |
| 205 | + |
| 206 | +static inline void clocksource_resume_watchdog(void) { } |
| 185 | 207 | #endif |
| 186 | 208 | |
| 209 | +/** |
| 210 | + * clocksource_resume - resume the clocksource(s) |
| 211 | + */ |
| 212 | +void clocksource_resume(void) |
| 213 | +{ |
| 214 | + struct list_head *tmp; |
| 215 | + unsigned long flags; |
| 216 | + |
| 217 | + spin_lock_irqsave(&clocksource_lock, flags); |
| 218 | + |
| 219 | + list_for_each(tmp, &clocksource_list) { |
| 220 | + struct clocksource *cs; |
| 221 | + |
| 222 | + cs = list_entry(tmp, struct clocksource, list); |
| 223 | + if (cs->resume) |
| 224 | + cs->resume(); |
| 225 | + } |
| 226 | + |
| 227 | + clocksource_resume_watchdog(); |
| 228 | + |
| 229 | + spin_unlock_irqrestore(&clocksource_lock, flags); |
| 230 | +} |
| 231 | + |
| 187 | 232 | /** |
| 188 | 233 | * clocksource_get_next - Returns the selected clocksource |
| 189 | 234 | * |