aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/ds.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c
index 0cb96dc399b7..d412cf876ab4 100644
--- a/arch/sparc64/kernel/ds.c
+++ b/arch/sparc64/kernel/ds.c
@@ -12,7 +12,7 @@
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/mutex.h> 14#include <linux/mutex.h>
15#include <linux/workqueue.h> 15#include <linux/kthread.h>
16#include <linux/cpu.h> 16#include <linux/cpu.h>
17 17
18#include <asm/ldc.h> 18#include <asm/ldc.h>
@@ -395,6 +395,7 @@ struct dr_cpu_resp_entry {
395 * ds_lock, and processed by dr_cpu_process() in order. 395 * ds_lock, and processed by dr_cpu_process() in order.
396 */ 396 */
397static LIST_HEAD(dr_cpu_work_list); 397static LIST_HEAD(dr_cpu_work_list);
398static DECLARE_WAIT_QUEUE_HEAD(dr_cpu_wait);
398 399
399struct dr_cpu_queue_entry { 400struct dr_cpu_queue_entry {
400 struct list_head list; 401 struct list_head list;
@@ -533,10 +534,13 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num,
533 534
534 printk(KERN_INFO PFX "Starting cpu %d...\n", cpu); 535 printk(KERN_INFO PFX "Starting cpu %d...\n", cpu);
535 err = cpu_up(cpu); 536 err = cpu_up(cpu);
536 if (err) 537 if (err) {
538 printk(KERN_INFO PFX "CPU startup failed err=%d\n",
539 err);
537 dr_cpu_mark(resp, cpu, ncpus, 540 dr_cpu_mark(resp, cpu, ncpus,
538 DR_CPU_RES_FAILURE, 541 DR_CPU_RES_FAILURE,
539 DR_CPU_STAT_UNCONFIGURED); 542 DR_CPU_STAT_UNCONFIGURED);
543 }
540 } 544 }
541 545
542 spin_lock_irqsave(&ds_lock, flags); 546 spin_lock_irqsave(&ds_lock, flags);
@@ -569,18 +573,16 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num,
569 return -EOPNOTSUPP; 573 return -EOPNOTSUPP;
570} 574}
571 575
572static void dr_cpu_process(struct work_struct *work) 576static void process_dr_cpu_list(struct ds_cap_state *cp)
573{ 577{
574 struct dr_cpu_queue_entry *qp, *tmp; 578 struct dr_cpu_queue_entry *qp, *tmp;
575 struct ds_cap_state *cp;
576 unsigned long flags; 579 unsigned long flags;
577 LIST_HEAD(todo); 580 LIST_HEAD(todo);
578 cpumask_t mask; 581 cpumask_t mask;
579 582
580 cp = find_cap_by_string("dr-cpu");
581
582 spin_lock_irqsave(&ds_lock, flags); 583 spin_lock_irqsave(&ds_lock, flags);
583 list_splice(&dr_cpu_work_list, &todo); 584 list_splice(&dr_cpu_work_list, &todo);
585 INIT_LIST_HEAD(&dr_cpu_work_list);
584 spin_unlock_irqrestore(&ds_lock, flags); 586 spin_unlock_irqrestore(&ds_lock, flags);
585 587
586 list_for_each_entry_safe(qp, tmp, &todo, list) { 588 list_for_each_entry_safe(qp, tmp, &todo, list) {
@@ -627,7 +629,27 @@ next:
627 } 629 }
628} 630}
629 631
630static DECLARE_WORK(dr_cpu_work, dr_cpu_process); 632static int dr_cpu_thread(void *__unused)
633{
634 struct ds_cap_state *cp;
635 DEFINE_WAIT(wait);
636
637 cp = find_cap_by_string("dr-cpu");
638
639 while (1) {
640 prepare_to_wait(&dr_cpu_wait, &wait, TASK_INTERRUPTIBLE);
641 if (list_empty(&dr_cpu_work_list))
642 schedule();
643 finish_wait(&dr_cpu_wait, &wait);
644
645 if (kthread_should_stop())
646 break;
647
648 process_dr_cpu_list(cp);
649 }
650
651 return 0;
652}
631 653
632static void dr_cpu_data(struct ldc_channel *lp, 654static void dr_cpu_data(struct ldc_channel *lp,
633 struct ds_cap_state *dp, 655 struct ds_cap_state *dp,
@@ -648,7 +670,7 @@ static void dr_cpu_data(struct ldc_channel *lp,
648 } else { 670 } else {
649 memcpy(&qp->req, buf, len); 671 memcpy(&qp->req, buf, len);
650 list_add_tail(&qp->list, &dr_cpu_work_list); 672 list_add_tail(&qp->list, &dr_cpu_work_list);
651 schedule_work(&dr_cpu_work); 673 wake_up(&dr_cpu_wait);
652 } 674 }
653} 675}
654#endif 676#endif
@@ -1095,6 +1117,10 @@ static int __init ds_init(void)
1095 for (i = 0; i < ARRAY_SIZE(ds_states); i++) 1117 for (i = 0; i < ARRAY_SIZE(ds_states); i++)
1096 ds_states[i].handle = ((u64)i << 32); 1118 ds_states[i].handle = ((u64)i << 32);
1097 1119
1120#ifdef CONFIG_HOTPLUG_CPU
1121 kthread_run(dr_cpu_thread, NULL, "kdrcpud");
1122#endif
1123
1098 return vio_register_driver(&ds_driver); 1124 return vio_register_driver(&ds_driver);
1099} 1125}
1100 1126