~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to kernel/smp.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
74
74
        .notifier_call          = hotplug_cfd,
75
75
};
76
76
 
77
 
static int __cpuinit init_call_single_data(void)
 
77
void __init call_function_init(void)
78
78
{
79
79
        void *cpu = (void *)(long)smp_processor_id();
80
80
        int i;
88
88
 
89
89
        hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
90
90
        register_cpu_notifier(&hotplug_cfd_notifier);
91
 
 
92
 
        return 0;
93
91
}
94
 
early_initcall(init_call_single_data);
95
92
 
96
93
/*
97
94
 * csd_lock/csd_unlock used to serialize access to per-cpu csd resources
194
191
         */
195
192
        list_for_each_entry_rcu(data, &call_function.queue, csd.list) {
196
193
                int refs;
197
 
                void (*func) (void *info);
 
194
                smp_call_func_t func;
198
195
 
199
196
                /*
200
197
                 * Since we walk the list without any locks, we might
214
211
                if (atomic_read(&data->refs) == 0)
215
212
                        continue;
216
213
 
217
 
                func = data->csd.func;                  /* for later warn */
218
 
                data->csd.func(data->csd.info);
 
214
                func = data->csd.func;          /* save for later warn */
 
215
                func(data->csd.info);
219
216
 
220
217
                /*
221
 
                 * If the cpu mask is not still set then it enabled interrupts,
222
 
                 * we took another smp interrupt, and executed the function
223
 
                 * twice on this cpu.  In theory that copy decremented refs.
 
218
                 * If the cpu mask is not still set then func enabled
 
219
                 * interrupts (BUG), and this cpu took another smp call
 
220
                 * function interrupt and executed func(info) twice
 
221
                 * on this cpu.  That nested execution decremented refs.
224
222
                 */
225
223
                if (!cpumask_test_and_clear_cpu(cpu, data->cpumask)) {
226
 
                        WARN(1, "%pS enabled interrupts and double executed\n",
227
 
                             func);
 
224
                        WARN(1, "%pf enabled interrupts and double executed\n", func);
228
225
                        continue;
229
226
                }
230
227
 
604
601
}
605
602
#endif /* USE_GENERIC_SMP_HELPERS */
606
603
 
 
604
/* Setup configured maximum number of CPUs to activate */
 
605
unsigned int setup_max_cpus = NR_CPUS;
 
606
EXPORT_SYMBOL(setup_max_cpus);
 
607
 
 
608
 
 
609
/*
 
610
 * Setup routine for controlling SMP activation
 
611
 *
 
612
 * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
 
613
 * activation entirely (the MPS table probe still happens, though).
 
614
 *
 
615
 * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
 
616
 * greater than 0, limits the maximum number of CPUs activated in
 
617
 * SMP mode to <NUM>.
 
618
 */
 
619
 
 
620
void __weak arch_disable_smp_support(void) { }
 
621
 
 
622
static int __init nosmp(char *str)
 
623
{
 
624
        setup_max_cpus = 0;
 
625
        arch_disable_smp_support();
 
626
 
 
627
        return 0;
 
628
}
 
629
 
 
630
early_param("nosmp", nosmp);
 
631
 
 
632
/* this is hard limit */
 
633
static int __init nrcpus(char *str)
 
634
{
 
635
        int nr_cpus;
 
636
 
 
637
        get_option(&str, &nr_cpus);
 
638
        if (nr_cpus > 0 && nr_cpus < nr_cpu_ids)
 
639
                nr_cpu_ids = nr_cpus;
 
640
 
 
641
        return 0;
 
642
}
 
643
 
 
644
early_param("nr_cpus", nrcpus);
 
645
 
 
646
static int __init maxcpus(char *str)
 
647
{
 
648
        get_option(&str, &setup_max_cpus);
 
649
        if (setup_max_cpus == 0)
 
650
                arch_disable_smp_support();
 
651
 
 
652
        return 0;
 
653
}
 
654
 
 
655
early_param("maxcpus", maxcpus);
 
656
 
 
657
/* Setup number of possible processor ids */
 
658
int nr_cpu_ids __read_mostly = NR_CPUS;
 
659
EXPORT_SYMBOL(nr_cpu_ids);
 
660
 
 
661
/* An arch may set nr_cpu_ids earlier if needed, so this would be redundant */
 
662
void __init setup_nr_cpu_ids(void)
 
663
{
 
664
        nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
 
665
}
 
666
 
 
667
/* Called by boot processor to activate the rest. */
 
668
void __init smp_init(void)
 
669
{
 
670
        unsigned int cpu;
 
671
 
 
672
        /* FIXME: This should be done in userspace --RR */
 
673
        for_each_present_cpu(cpu) {
 
674
                if (num_online_cpus() >= setup_max_cpus)
 
675
                        break;
 
676
                if (!cpu_online(cpu))
 
677
                        cpu_up(cpu);
 
678
        }
 
679
 
 
680
        /* Any cleanup work */
 
681
        printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus());
 
682
        smp_cpus_done(setup_max_cpus);
 
683
}
 
684
 
607
685
/*
608
686
 * Call a function on all processors.  May be used during early boot while
609
687
 * early_boot_irqs_disabled is set.  Use local_irq_save/restore() instead