diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/ecard.c | 13 | ||||
-rw-r--r-- | arch/arm/kernel/ecard.h | 13 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/stacktrace.c | 34 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 120 |
5 files changed, 50 insertions, 134 deletions
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index a53c0aba5c14..8bfd299bfe77 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c | |||
@@ -680,7 +680,7 @@ static int __init ecard_probeirqhw(void) | |||
680 | #define IO_EC_MEMC8_BASE 0 | 680 | #define IO_EC_MEMC8_BASE 0 |
681 | #endif | 681 | #endif |
682 | 682 | ||
683 | unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) | 683 | static unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) |
684 | { | 684 | { |
685 | unsigned long address = 0; | 685 | unsigned long address = 0; |
686 | int slot = ec->slot_no; | 686 | int slot = ec->slot_no; |
@@ -1002,7 +1002,7 @@ ecard_probe(int slot, card_type_t type) | |||
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | rc = -ENODEV; | 1004 | rc = -ENODEV; |
1005 | if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0) | 1005 | if ((ec->podaddr = __ecard_address(ec, type, ECARD_SYNC)) == 0) |
1006 | goto nodev; | 1006 | goto nodev; |
1007 | 1007 | ||
1008 | cid.r_zero = 1; | 1008 | cid.r_zero = 1; |
@@ -1141,10 +1141,10 @@ static int ecard_drv_probe(struct device *dev) | |||
1141 | 1141 | ||
1142 | id = ecard_match_device(drv->id_table, ec); | 1142 | id = ecard_match_device(drv->id_table, ec); |
1143 | 1143 | ||
1144 | ecard_claim(ec); | 1144 | ec->claimed = 1; |
1145 | ret = drv->probe(ec, id); | 1145 | ret = drv->probe(ec, id); |
1146 | if (ret) | 1146 | if (ret) |
1147 | ecard_release(ec); | 1147 | ec->claimed = 0; |
1148 | return ret; | 1148 | return ret; |
1149 | } | 1149 | } |
1150 | 1150 | ||
@@ -1154,7 +1154,7 @@ static int ecard_drv_remove(struct device *dev) | |||
1154 | struct ecard_driver *drv = ECARD_DRV(dev->driver); | 1154 | struct ecard_driver *drv = ECARD_DRV(dev->driver); |
1155 | 1155 | ||
1156 | drv->remove(ec); | 1156 | drv->remove(ec); |
1157 | ecard_release(ec); | 1157 | ec->claimed = 0; |
1158 | 1158 | ||
1159 | /* | 1159 | /* |
1160 | * Restore the default operations. We ensure that the | 1160 | * Restore the default operations. We ensure that the |
@@ -1182,7 +1182,7 @@ static void ecard_drv_shutdown(struct device *dev) | |||
1182 | if (dev->driver) { | 1182 | if (dev->driver) { |
1183 | if (drv->shutdown) | 1183 | if (drv->shutdown) |
1184 | drv->shutdown(ec); | 1184 | drv->shutdown(ec); |
1185 | ecard_release(ec); | 1185 | ec->claimed = 0; |
1186 | } | 1186 | } |
1187 | 1187 | ||
1188 | /* | 1188 | /* |
@@ -1239,7 +1239,6 @@ static int ecard_bus_init(void) | |||
1239 | postcore_initcall(ecard_bus_init); | 1239 | postcore_initcall(ecard_bus_init); |
1240 | 1240 | ||
1241 | EXPORT_SYMBOL(ecard_readchunk); | 1241 | EXPORT_SYMBOL(ecard_readchunk); |
1242 | EXPORT_SYMBOL(__ecard_address); | ||
1243 | EXPORT_SYMBOL(ecard_register_driver); | 1242 | EXPORT_SYMBOL(ecard_register_driver); |
1244 | EXPORT_SYMBOL(ecard_remove_driver); | 1243 | EXPORT_SYMBOL(ecard_remove_driver); |
1245 | EXPORT_SYMBOL(ecard_bus_type); | 1244 | EXPORT_SYMBOL(ecard_bus_type); |
diff --git a/arch/arm/kernel/ecard.h b/arch/arm/kernel/ecard.h index d7c2dacf935d..4642d436be2a 100644 --- a/arch/arm/kernel/ecard.h +++ b/arch/arm/kernel/ecard.h | |||
@@ -54,3 +54,16 @@ struct ex_chunk_dir { | |||
54 | #define c_len(x) ((x)->r_len[0]|((x)->r_len[1]<<8)|((x)->r_len[2]<<16)) | 54 | #define c_len(x) ((x)->r_len[0]|((x)->r_len[1]<<8)|((x)->r_len[2]<<16)) |
55 | #define c_start(x) ((x)->r_start) | 55 | #define c_start(x) ((x)->r_start) |
56 | }; | 56 | }; |
57 | |||
58 | typedef enum ecard_type { /* Cards address space */ | ||
59 | ECARD_IOC, | ||
60 | ECARD_MEMC, | ||
61 | ECARD_EASI | ||
62 | } card_type_t; | ||
63 | |||
64 | typedef enum { /* Speed for ECARD_IOC space */ | ||
65 | ECARD_SLOW = 0, | ||
66 | ECARD_MEDIUM = 1, | ||
67 | ECARD_FAST = 2, | ||
68 | ECARD_SYNC = 3 | ||
69 | } card_speed_t; | ||
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 46bf2ede6128..199b3680118b 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -133,10 +133,8 @@ static void default_idle(void) | |||
133 | cpu_relax(); | 133 | cpu_relax(); |
134 | else { | 134 | else { |
135 | local_irq_disable(); | 135 | local_irq_disable(); |
136 | if (!need_resched()) { | 136 | if (!need_resched()) |
137 | timer_dyn_reprogram(); | ||
138 | arch_idle(); | 137 | arch_idle(); |
139 | } | ||
140 | local_irq_enable(); | 138 | local_irq_enable(); |
141 | } | 139 | } |
142 | } | 140 | } |
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index ae31deb2d065..90e0c35ae60d 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c | |||
@@ -36,6 +36,7 @@ EXPORT_SYMBOL(walk_stackframe); | |||
36 | #ifdef CONFIG_STACKTRACE | 36 | #ifdef CONFIG_STACKTRACE |
37 | struct stack_trace_data { | 37 | struct stack_trace_data { |
38 | struct stack_trace *trace; | 38 | struct stack_trace *trace; |
39 | unsigned int no_sched_functions; | ||
39 | unsigned int skip; | 40 | unsigned int skip; |
40 | }; | 41 | }; |
41 | 42 | ||
@@ -43,27 +44,52 @@ static int save_trace(struct stackframe *frame, void *d) | |||
43 | { | 44 | { |
44 | struct stack_trace_data *data = d; | 45 | struct stack_trace_data *data = d; |
45 | struct stack_trace *trace = data->trace; | 46 | struct stack_trace *trace = data->trace; |
47 | unsigned long addr = frame->lr; | ||
46 | 48 | ||
49 | if (data->no_sched_functions && in_sched_functions(addr)) | ||
50 | return 0; | ||
47 | if (data->skip) { | 51 | if (data->skip) { |
48 | data->skip--; | 52 | data->skip--; |
49 | return 0; | 53 | return 0; |
50 | } | 54 | } |
51 | 55 | ||
52 | trace->entries[trace->nr_entries++] = frame->lr; | 56 | trace->entries[trace->nr_entries++] = addr; |
53 | 57 | ||
54 | return trace->nr_entries >= trace->max_entries; | 58 | return trace->nr_entries >= trace->max_entries; |
55 | } | 59 | } |
56 | 60 | ||
57 | void save_stack_trace(struct stack_trace *trace) | 61 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) |
58 | { | 62 | { |
59 | struct stack_trace_data data; | 63 | struct stack_trace_data data; |
60 | unsigned long fp, base; | 64 | unsigned long fp, base; |
61 | 65 | ||
62 | data.trace = trace; | 66 | data.trace = trace; |
63 | data.skip = trace->skip; | 67 | data.skip = trace->skip; |
64 | base = (unsigned long)task_stack_page(current); | 68 | base = (unsigned long)task_stack_page(tsk); |
65 | asm("mov %0, fp" : "=r" (fp)); | 69 | |
70 | if (tsk != current) { | ||
71 | #ifdef CONFIG_SMP | ||
72 | /* | ||
73 | * What guarantees do we have here that 'tsk' | ||
74 | * is not running on another CPU? | ||
75 | */ | ||
76 | BUG(); | ||
77 | #else | ||
78 | data.no_sched_functions = 1; | ||
79 | fp = thread_saved_fp(tsk); | ||
80 | #endif | ||
81 | } else { | ||
82 | data.no_sched_functions = 0; | ||
83 | asm("mov %0, fp" : "=r" (fp)); | ||
84 | } | ||
66 | 85 | ||
67 | walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data); | 86 | walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data); |
87 | if (trace->nr_entries < trace->max_entries) | ||
88 | trace->entries[trace->nr_entries++] = ULONG_MAX; | ||
89 | } | ||
90 | |||
91 | void save_stack_trace(struct stack_trace *trace) | ||
92 | { | ||
93 | save_stack_trace_tsk(current, trace); | ||
68 | } | 94 | } |
69 | #endif | 95 | #endif |
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index b5867eca1d0b..cc5145b28e7f 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c | |||
@@ -365,108 +365,6 @@ static struct sysdev_class timer_sysclass = { | |||
365 | .resume = timer_resume, | 365 | .resume = timer_resume, |
366 | }; | 366 | }; |
367 | 367 | ||
368 | #ifdef CONFIG_NO_IDLE_HZ | ||
369 | static int timer_dyn_tick_enable(void) | ||
370 | { | ||
371 | struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; | ||
372 | unsigned long flags; | ||
373 | int ret = -ENODEV; | ||
374 | |||
375 | if (dyn_tick) { | ||
376 | spin_lock_irqsave(&dyn_tick->lock, flags); | ||
377 | ret = 0; | ||
378 | if (!(dyn_tick->state & DYN_TICK_ENABLED)) { | ||
379 | ret = dyn_tick->enable(); | ||
380 | |||
381 | if (ret == 0) | ||
382 | dyn_tick->state |= DYN_TICK_ENABLED; | ||
383 | } | ||
384 | spin_unlock_irqrestore(&dyn_tick->lock, flags); | ||
385 | } | ||
386 | |||
387 | return ret; | ||
388 | } | ||
389 | |||
390 | static int timer_dyn_tick_disable(void) | ||
391 | { | ||
392 | struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; | ||
393 | unsigned long flags; | ||
394 | int ret = -ENODEV; | ||
395 | |||
396 | if (dyn_tick) { | ||
397 | spin_lock_irqsave(&dyn_tick->lock, flags); | ||
398 | ret = 0; | ||
399 | if (dyn_tick->state & DYN_TICK_ENABLED) { | ||
400 | ret = dyn_tick->disable(); | ||
401 | |||
402 | if (ret == 0) | ||
403 | dyn_tick->state &= ~DYN_TICK_ENABLED; | ||
404 | } | ||
405 | spin_unlock_irqrestore(&dyn_tick->lock, flags); | ||
406 | } | ||
407 | |||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * Reprogram the system timer for at least the calculated time interval. | ||
413 | * This function should be called from the idle thread with IRQs disabled, | ||
414 | * immediately before sleeping. | ||
415 | */ | ||
416 | void timer_dyn_reprogram(void) | ||
417 | { | ||
418 | struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; | ||
419 | unsigned long next, seq, flags; | ||
420 | |||
421 | if (!dyn_tick) | ||
422 | return; | ||
423 | |||
424 | spin_lock_irqsave(&dyn_tick->lock, flags); | ||
425 | if (dyn_tick->state & DYN_TICK_ENABLED) { | ||
426 | next = next_timer_interrupt(); | ||
427 | do { | ||
428 | seq = read_seqbegin(&xtime_lock); | ||
429 | dyn_tick->reprogram(next - jiffies); | ||
430 | } while (read_seqretry(&xtime_lock, seq)); | ||
431 | } | ||
432 | spin_unlock_irqrestore(&dyn_tick->lock, flags); | ||
433 | } | ||
434 | |||
435 | static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) | ||
436 | { | ||
437 | return sprintf(buf, "%i\n", | ||
438 | (system_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1); | ||
439 | } | ||
440 | |||
441 | static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf, | ||
442 | size_t count) | ||
443 | { | ||
444 | unsigned int enable = simple_strtoul(buf, NULL, 2); | ||
445 | |||
446 | if (enable) | ||
447 | timer_dyn_tick_enable(); | ||
448 | else | ||
449 | timer_dyn_tick_disable(); | ||
450 | |||
451 | return count; | ||
452 | } | ||
453 | static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick); | ||
454 | |||
455 | /* | ||
456 | * dyntick=enable|disable | ||
457 | */ | ||
458 | static char dyntick_str[4] __initdata = ""; | ||
459 | |||
460 | static int __init dyntick_setup(char *str) | ||
461 | { | ||
462 | if (str) | ||
463 | strlcpy(dyntick_str, str, sizeof(dyntick_str)); | ||
464 | return 1; | ||
465 | } | ||
466 | |||
467 | __setup("dyntick=", dyntick_setup); | ||
468 | #endif | ||
469 | |||
470 | static int __init timer_init_sysfs(void) | 368 | static int __init timer_init_sysfs(void) |
471 | { | 369 | { |
472 | int ret = sysdev_class_register(&timer_sysclass); | 370 | int ret = sysdev_class_register(&timer_sysclass); |
@@ -475,19 +373,6 @@ static int __init timer_init_sysfs(void) | |||
475 | ret = sysdev_register(&system_timer->dev); | 373 | ret = sysdev_register(&system_timer->dev); |
476 | } | 374 | } |
477 | 375 | ||
478 | #ifdef CONFIG_NO_IDLE_HZ | ||
479 | if (ret == 0 && system_timer->dyn_tick) { | ||
480 | ret = sysdev_create_file(&system_timer->dev, &attr_dyn_tick); | ||
481 | |||
482 | /* | ||
483 | * Turn on dynamic tick after calibrate delay | ||
484 | * for correct bogomips | ||
485 | */ | ||
486 | if (ret == 0 && dyntick_str[0] == 'e') | ||
487 | ret = timer_dyn_tick_enable(); | ||
488 | } | ||
489 | #endif | ||
490 | |||
491 | return ret; | 376 | return ret; |
492 | } | 377 | } |
493 | 378 | ||
@@ -500,10 +385,5 @@ void __init time_init(void) | |||
500 | system_timer->offset = dummy_gettimeoffset; | 385 | system_timer->offset = dummy_gettimeoffset; |
501 | #endif | 386 | #endif |
502 | system_timer->init(); | 387 | system_timer->init(); |
503 | |||
504 | #ifdef CONFIG_NO_IDLE_HZ | ||
505 | if (system_timer->dyn_tick) | ||
506 | spin_lock_init(&system_timer->dyn_tick->lock); | ||
507 | #endif | ||
508 | } | 388 | } |
509 | 389 | ||