| @@ -6,8 +6,6 @@ · 5 unmodified lines |
| 6 | 6 | #include <linux/list.h> |
| 7 | 7 | #include <asm/system.h> |
| 8 | 8 | |
| 9 | | −#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP) |
| 10 | | − |
| 11 | 9 | /* |
| 12 | 10 | * stop_cpu[s]() is simplistic per-cpu maximum priority cpu |
| 13 | 11 | * monopolization mechanism. The caller can specify a non-sleeping |
| @@ -18,9 +16,10 @@ · 4 unmodified lines |
| 18 | 16 | * up and requests are guaranteed to be served as long as the target |
| 19 | 17 | * cpus are online. |
| 20 | 18 | */ |
| 21 | | − |
| 22 | 19 | typedef int (*cpu_stop_fn_t)(void *arg); |
| 23 | 20 | |
| 21 | +#ifdef CONFIG_SMP |
| 22 | + |
| 24 | 23 | struct cpu_stop_work { |
| 25 | 24 | struct list_head list; /* cpu_stopper->works */ |
| 26 | 25 | cpu_stop_fn_t fn; |
| @@ -34,12 +33,70 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, · 7 unmodified lines |
| 34 | 33 | int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); |
| 35 | 34 | int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); |
| 36 | 35 | |
| 36 | +#else /* CONFIG_SMP */ |
| 37 | + |
| 38 | +#include <linux/workqueue.h> |
| 39 | + |
| 40 | +struct cpu_stop_work { |
| 41 | + struct work_struct work; |
| 42 | + cpu_stop_fn_t fn; |
| 43 | + void *arg; |
| 44 | +}; |
| 45 | + |
| 46 | +static inline int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg) |
| 47 | +{ |
| 48 | + int ret = -ENOENT; |
| 49 | + preempt_disable(); |
| 50 | + if (cpu == smp_processor_id()) |
| 51 | + ret = fn(arg); |
| 52 | + preempt_enable(); |
| 53 | + return ret; |
| 54 | +} |
| 55 | + |
| 56 | +static void stop_one_cpu_nowait_workfn(struct work_struct *work) |
| 57 | +{ |
| 58 | + struct cpu_stop_work *stwork = |
| 59 | + container_of(work, struct cpu_stop_work, work); |
| 60 | + preempt_disable(); |
| 61 | + stwork->fn(stwork->arg); |
| 62 | + preempt_enable(); |
| 63 | +} |
| 64 | + |
| 65 | +static inline void stop_one_cpu_nowait(unsigned int cpu, |
| 66 | + cpu_stop_fn_t fn, void *arg, |
| 67 | + struct cpu_stop_work *work_buf) |
| 68 | +{ |
| 69 | + if (cpu == smp_processor_id()) { |
| 70 | + INIT_WORK(&work_buf->work, stop_one_cpu_nowait_workfn); |
| 71 | + work_buf->fn = fn; |
| 72 | + work_buf->arg = arg; |
| 73 | + schedule_work(&work_buf->work); |
| 74 | + } |
| 75 | +} |
| 76 | + |
| 77 | +static inline int stop_cpus(const struct cpumask *cpumask, |
| 78 | + cpu_stop_fn_t fn, void *arg) |
| 79 | +{ |
| 80 | + if (cpumask_test_cpu(raw_smp_processor_id(), cpumask)) |
| 81 | + return stop_one_cpu(raw_smp_processor_id(), fn, arg); |
| 82 | + return -ENOENT; |
| 83 | +} |
| 84 | + |
| 85 | +static inline int try_stop_cpus(const struct cpumask *cpumask, |
| 86 | + cpu_stop_fn_t fn, void *arg) |
| 87 | +{ |
| 88 | + return stop_cpus(cpumask, fn, arg); |
| 89 | +} |
| 90 | + |
| 91 | +#endif /* CONFIG_SMP */ |
| 92 | + |
| 37 | 93 | /* |
| 38 | 94 | * stop_machine "Bogolock": stop the entire machine, disable |
| 39 | 95 | * interrupts. This is a very heavy lock, which is equivalent to |
| 40 | 96 | * grabbing every spinlock (and more). So the "read" side to such a |
| 41 | 97 | * lock is anything which disables preeempt. |
| 42 | 98 | */ |
| 99 | +#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP) |
| 43 | 100 | |
| 44 | 101 | /** |
| 45 | 102 | * stop_machine: freeze the machine on all CPUs and run this function |
| @@ -67,7 +124,7 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus); · 21 unmodified lines |
| 67 | 124 | */ |
| 68 | 125 | int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus); |
| 69 | 126 | |
| 70 | | −#else |
| 127 | +#else /* CONFIG_STOP_MACHINE && CONFIG_SMP */ |
| 71 | 128 | |
| 72 | 129 | static inline int stop_machine(int (*fn)(void *), void *data, |
| 73 | 130 | const struct cpumask *cpus) |
| @@ -79,5 +136,5 @@ static inline int stop_machine(int (*fn)(void *), void *data, · 5 unmodified lines |
| 79 | 136 | return ret; |
| 80 | 137 | } |
| 81 | 138 | |
| 82 | | −#endif /* CONFIG_SMP */ |
| 83 | | −#endif /* _LINUX_STOP_MACHINE */ |
| 139 | +#endif /* CONFIG_STOP_MACHINE && CONFIG_SMP */ |
| 140 | +#endif /* _LINUX_STOP_MACHINE */ |