diff options
-rw-r--r-- | arch/powerpc/kernel/time.c | 63 |
1 files changed, 16 insertions, 47 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 5b59bc18dfe7..a1b5e4b16151 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -220,11 +220,8 @@ static void account_process_time(struct pt_regs *regs) | |||
220 | */ | 220 | */ |
221 | struct cpu_purr_data { | 221 | struct cpu_purr_data { |
222 | int initialized; /* thread is running */ | 222 | int initialized; /* thread is running */ |
223 | u64 tb0; /* timebase at origin time */ | ||
224 | u64 purr0; /* PURR at origin time */ | ||
225 | u64 tb; /* last TB value read */ | 223 | u64 tb; /* last TB value read */ |
226 | u64 purr; /* last PURR value read */ | 224 | u64 purr; /* last PURR value read */ |
227 | u64 stolen; /* stolen time so far */ | ||
228 | spinlock_t lock; | 225 | spinlock_t lock; |
229 | }; | 226 | }; |
230 | 227 | ||
@@ -234,10 +231,8 @@ static void snapshot_tb_and_purr(void *data) | |||
234 | { | 231 | { |
235 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); | 232 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); |
236 | 233 | ||
237 | p->tb0 = mftb(); | 234 | p->tb = mftb(); |
238 | p->purr0 = mfspr(SPRN_PURR); | 235 | p->purr = mfspr(SPRN_PURR); |
239 | p->tb = p->tb0; | ||
240 | p->purr = 0; | ||
241 | wmb(); | 236 | wmb(); |
242 | p->initialized = 1; | 237 | p->initialized = 1; |
243 | } | 238 | } |
@@ -258,37 +253,24 @@ void snapshot_timebases(void) | |||
258 | 253 | ||
259 | void calculate_steal_time(void) | 254 | void calculate_steal_time(void) |
260 | { | 255 | { |
261 | u64 tb, purr, t0; | 256 | u64 tb, purr; |
262 | s64 stolen; | 257 | s64 stolen; |
263 | struct cpu_purr_data *p0, *pme, *phim; | 258 | struct cpu_purr_data *pme; |
264 | int cpu; | ||
265 | 259 | ||
266 | if (!cpu_has_feature(CPU_FTR_PURR)) | 260 | if (!cpu_has_feature(CPU_FTR_PURR)) |
267 | return; | 261 | return; |
268 | cpu = smp_processor_id(); | 262 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
269 | pme = &per_cpu(cpu_purr_data, cpu); | ||
270 | if (!pme->initialized) | 263 | if (!pme->initialized) |
271 | return; /* this can happen in early boot */ | 264 | return; /* this can happen in early boot */ |
272 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | 265 | spin_lock(&pme->lock); |
273 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | ||
274 | spin_lock(&p0->lock); | ||
275 | tb = mftb(); | 266 | tb = mftb(); |
276 | purr = mfspr(SPRN_PURR) - pme->purr0; | 267 | purr = mfspr(SPRN_PURR); |
277 | if (!phim->initialized || !cpu_online(cpu ^ 1)) { | 268 | stolen = (tb - pme->tb) - (purr - pme->purr); |
278 | stolen = (tb - pme->tb) - (purr - pme->purr); | 269 | if (stolen > 0) |
279 | } else { | ||
280 | t0 = pme->tb0; | ||
281 | if (phim->tb0 < t0) | ||
282 | t0 = phim->tb0; | ||
283 | stolen = phim->tb - t0 - phim->purr - purr - p0->stolen; | ||
284 | } | ||
285 | if (stolen > 0) { | ||
286 | account_steal_time(current, stolen); | 270 | account_steal_time(current, stolen); |
287 | p0->stolen += stolen; | ||
288 | } | ||
289 | pme->tb = tb; | 271 | pme->tb = tb; |
290 | pme->purr = purr; | 272 | pme->purr = purr; |
291 | spin_unlock(&p0->lock); | 273 | spin_unlock(&pme->lock); |
292 | } | 274 | } |
293 | 275 | ||
294 | /* | 276 | /* |
@@ -297,30 +279,17 @@ void calculate_steal_time(void) | |||
297 | */ | 279 | */ |
298 | static void snapshot_purr(void) | 280 | static void snapshot_purr(void) |
299 | { | 281 | { |
300 | int cpu; | 282 | struct cpu_purr_data *pme; |
301 | u64 purr; | ||
302 | struct cpu_purr_data *p0, *pme, *phim; | ||
303 | unsigned long flags; | 283 | unsigned long flags; |
304 | 284 | ||
305 | if (!cpu_has_feature(CPU_FTR_PURR)) | 285 | if (!cpu_has_feature(CPU_FTR_PURR)) |
306 | return; | 286 | return; |
307 | cpu = smp_processor_id(); | 287 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
308 | pme = &per_cpu(cpu_purr_data, cpu); | 288 | spin_lock_irqsave(&pme->lock, flags); |
309 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | 289 | pme->tb = mftb(); |
310 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | 290 | pme->purr = mfspr(SPRN_PURR); |
311 | spin_lock_irqsave(&p0->lock, flags); | ||
312 | pme->tb = pme->tb0 = mftb(); | ||
313 | purr = mfspr(SPRN_PURR); | ||
314 | if (!phim->initialized) { | ||
315 | pme->purr = 0; | ||
316 | pme->purr0 = purr; | ||
317 | } else { | ||
318 | /* set p->purr and p->purr0 for no change in p0->stolen */ | ||
319 | pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen; | ||
320 | pme->purr0 = purr - pme->purr; | ||
321 | } | ||
322 | pme->initialized = 1; | 291 | pme->initialized = 1; |
323 | spin_unlock_irqrestore(&p0->lock, flags); | 292 | spin_unlock_irqrestore(&pme->lock, flags); |
324 | } | 293 | } |
325 | 294 | ||
326 | #endif /* CONFIG_PPC_SPLPAR */ | 295 | #endif /* CONFIG_PPC_SPLPAR */ |