diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2016-07-25 04:43:13 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2016-07-25 12:55:32 -0400 |
commit | fbb0e4da96f4503e65bc4fb627cf4e1d7c8c64e6 (patch) | |
tree | 7c17fa1f6f451a838974067ef63372818404c495 /arch/ia64/kernel | |
parent | 70f4f9352317ed8bc70cd7fe2bf34a3f9f7f21e3 (diff) |
ia64: salinfo: use a waitqueue instead a sema down/up combo
The only purpose of down_try_lock() followed by up() seems to be to wake
up a possible reader. This patch replaces it with a wake-queue. There is
no locking around cpumask_empty() and the test is re-done in case there
was no hit.
With wait_event_interruptible_lock_irq(,&data_saved_lock) we would probably
be able to get rid of the `retry` label. However we still can return CPU
X which is valid now but later (after the lock dropped) the event may
have been removed because the CPU went offline.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r-- | arch/ia64/kernel/salinfo.c | 38 |
1 files changed, 10 insertions, 28 deletions
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index 1eeffb7fbb16..5313007d5423 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c | |||
@@ -141,7 +141,7 @@ enum salinfo_state { | |||
141 | 141 | ||
142 | struct salinfo_data { | 142 | struct salinfo_data { |
143 | cpumask_t cpu_event; /* which cpus have outstanding events */ | 143 | cpumask_t cpu_event; /* which cpus have outstanding events */ |
144 | struct semaphore mutex; | 144 | wait_queue_head_t read_wait; |
145 | u8 *log_buffer; | 145 | u8 *log_buffer; |
146 | u64 log_size; | 146 | u64 log_size; |
147 | u8 *oemdata; /* decoded oem data */ | 147 | u8 *oemdata; /* decoded oem data */ |
@@ -182,21 +182,6 @@ struct salinfo_platform_oemdata_parms { | |||
182 | int ret; | 182 | int ret; |
183 | }; | 183 | }; |
184 | 184 | ||
185 | /* Kick the mutex that tells user space that there is work to do. Instead of | ||
186 | * trying to track the state of the mutex across multiple cpus, in user | ||
187 | * context, interrupt context, non-maskable interrupt context and hotplug cpu, | ||
188 | * it is far easier just to grab the mutex if it is free then release it. | ||
189 | * | ||
190 | * This routine must be called with data_saved_lock held, to make the down/up | ||
191 | * operation atomic. | ||
192 | */ | ||
193 | static void | ||
194 | salinfo_work_to_do(struct salinfo_data *data) | ||
195 | { | ||
196 | (void)(down_trylock(&data->mutex) ?: 0); | ||
197 | up(&data->mutex); | ||
198 | } | ||
199 | |||
200 | static void | 185 | static void |
201 | salinfo_platform_oemdata_cpu(void *context) | 186 | salinfo_platform_oemdata_cpu(void *context) |
202 | { | 187 | { |
@@ -258,7 +243,7 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe) | |||
258 | } | 243 | } |
259 | cpumask_set_cpu(smp_processor_id(), &data->cpu_event); | 244 | cpumask_set_cpu(smp_processor_id(), &data->cpu_event); |
260 | if (irqsafe) { | 245 | if (irqsafe) { |
261 | salinfo_work_to_do(data); | 246 | wake_up_interruptible(&data->read_wait); |
262 | spin_unlock_irqrestore(&data_saved_lock, flags); | 247 | spin_unlock_irqrestore(&data_saved_lock, flags); |
263 | } | 248 | } |
264 | } | 249 | } |
@@ -271,14 +256,10 @@ extern void ia64_mlogbuf_dump(void); | |||
271 | static void | 256 | static void |
272 | salinfo_timeout_check(struct salinfo_data *data) | 257 | salinfo_timeout_check(struct salinfo_data *data) |
273 | { | 258 | { |
274 | unsigned long flags; | ||
275 | if (!data->open) | 259 | if (!data->open) |
276 | return; | 260 | return; |
277 | if (!cpumask_empty(&data->cpu_event)) { | 261 | if (!cpumask_empty(&data->cpu_event)) |
278 | spin_lock_irqsave(&data_saved_lock, flags); | 262 | wake_up_interruptible(&data->read_wait); |
279 | salinfo_work_to_do(data); | ||
280 | spin_unlock_irqrestore(&data_saved_lock, flags); | ||
281 | } | ||
282 | } | 263 | } |
283 | 264 | ||
284 | static void | 265 | static void |
@@ -308,10 +289,11 @@ salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t | |||
308 | int i, n, cpu = -1; | 289 | int i, n, cpu = -1; |
309 | 290 | ||
310 | retry: | 291 | retry: |
311 | if (cpumask_empty(&data->cpu_event) && down_trylock(&data->mutex)) { | 292 | if (cpumask_empty(&data->cpu_event)) { |
312 | if (file->f_flags & O_NONBLOCK) | 293 | if (file->f_flags & O_NONBLOCK) |
313 | return -EAGAIN; | 294 | return -EAGAIN; |
314 | if (down_interruptible(&data->mutex)) | 295 | if (wait_event_interruptible(data->read_wait, |
296 | !cpumask_empty(&data->cpu_event))) | ||
315 | return -EINTR; | 297 | return -EINTR; |
316 | } | 298 | } |
317 | 299 | ||
@@ -510,7 +492,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu) | |||
510 | if (data->state == STATE_LOG_RECORD) { | 492 | if (data->state == STATE_LOG_RECORD) { |
511 | spin_lock_irqsave(&data_saved_lock, flags); | 493 | spin_lock_irqsave(&data_saved_lock, flags); |
512 | cpumask_set_cpu(cpu, &data->cpu_event); | 494 | cpumask_set_cpu(cpu, &data->cpu_event); |
513 | salinfo_work_to_do(data); | 495 | wake_up_interruptible(&data->read_wait); |
514 | spin_unlock_irqrestore(&data_saved_lock, flags); | 496 | spin_unlock_irqrestore(&data_saved_lock, flags); |
515 | } | 497 | } |
516 | return 0; | 498 | return 0; |
@@ -582,7 +564,7 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu | |||
582 | i < ARRAY_SIZE(salinfo_data); | 564 | i < ARRAY_SIZE(salinfo_data); |
583 | ++i, ++data) { | 565 | ++i, ++data) { |
584 | cpumask_set_cpu(cpu, &data->cpu_event); | 566 | cpumask_set_cpu(cpu, &data->cpu_event); |
585 | salinfo_work_to_do(data); | 567 | wake_up_interruptible(&data->read_wait); |
586 | } | 568 | } |
587 | spin_unlock_irqrestore(&data_saved_lock, flags); | 569 | spin_unlock_irqrestore(&data_saved_lock, flags); |
588 | break; | 570 | break; |
@@ -640,7 +622,7 @@ salinfo_init(void) | |||
640 | for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) { | 622 | for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) { |
641 | data = salinfo_data + i; | 623 | data = salinfo_data + i; |
642 | data->type = i; | 624 | data->type = i; |
643 | sema_init(&data->mutex, 1); | 625 | init_waitqueue_head(&data->read_wait); |
644 | dir = proc_mkdir(salinfo_log_name[i], salinfo_dir); | 626 | dir = proc_mkdir(salinfo_log_name[i], salinfo_dir); |
645 | if (!dir) | 627 | if (!dir) |
646 | continue; | 628 | continue; |