diff options
Diffstat (limited to 'arch')
53 files changed, 911 insertions, 302 deletions
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 134aec1c6d19..b5f83e9f04db 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c | |||
@@ -54,7 +54,7 @@ asmlinkage void ret_from_fork(void); | |||
54 | void default_idle(void) | 54 | void default_idle(void) |
55 | { | 55 | { |
56 | while(1) { | 56 | while(1) { |
57 | if (need_resched()) { | 57 | if (!need_resched()) { |
58 | local_irq_enable(); | 58 | local_irq_enable(); |
59 | __asm__("sleep"); | 59 | __asm__("sleep"); |
60 | local_irq_disable(); | 60 | local_irq_disable(); |
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig index f25ffd74235c..0f1eb507233b 100644 --- a/arch/i386/kernel/cpu/cpufreq/Kconfig +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig | |||
@@ -23,7 +23,7 @@ config X86_ACPI_CPUFREQ | |||
23 | If in doubt, say N. | 23 | If in doubt, say N. |
24 | 24 | ||
25 | config ELAN_CPUFREQ | 25 | config ELAN_CPUFREQ |
26 | tristate "AMD Elan" | 26 | tristate "AMD Elan SC400 and SC410" |
27 | select CPU_FREQ_TABLE | 27 | select CPU_FREQ_TABLE |
28 | depends on X86_ELAN | 28 | depends on X86_ELAN |
29 | ---help--- | 29 | ---help--- |
@@ -38,6 +38,18 @@ config ELAN_CPUFREQ | |||
38 | 38 | ||
39 | If in doubt, say N. | 39 | If in doubt, say N. |
40 | 40 | ||
41 | config SC520_CPUFREQ | ||
42 | tristate "AMD Elan SC520" | ||
43 | select CPU_FREQ_TABLE | ||
44 | depends on X86_ELAN | ||
45 | ---help--- | ||
46 | This adds the CPUFreq driver for AMD Elan SC520 processor. | ||
47 | |||
48 | For details, take a look at <file:Documentation/cpu-freq/>. | ||
49 | |||
50 | If in doubt, say N. | ||
51 | |||
52 | |||
41 | config X86_POWERNOW_K6 | 53 | config X86_POWERNOW_K6 |
42 | tristate "AMD Mobile K6-2/K6-3 PowerNow!" | 54 | tristate "AMD Mobile K6-2/K6-3 PowerNow!" |
43 | select CPU_FREQ_TABLE | 55 | select CPU_FREQ_TABLE |
diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile index a922e97aeedd..2e894f1c8910 100644 --- a/arch/i386/kernel/cpu/cpufreq/Makefile +++ b/arch/i386/kernel/cpu/cpufreq/Makefile | |||
@@ -3,6 +3,7 @@ obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o | |||
3 | obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o | 3 | obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o |
4 | obj-$(CONFIG_X86_LONGHAUL) += longhaul.o | 4 | obj-$(CONFIG_X86_LONGHAUL) += longhaul.o |
5 | obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o | 5 | obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o |
6 | obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o | ||
6 | obj-$(CONFIG_X86_LONGRUN) += longrun.o | 7 | obj-$(CONFIG_X86_LONGRUN) += longrun.o |
7 | obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o | 8 | obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o |
8 | obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o | 9 | obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o |
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index ab0f9f5aac11..04e3563da4fe 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/cpufreq.h> | 29 | #include <linux/cpufreq.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
32 | #include <linux/pci.h> | ||
32 | 33 | ||
33 | #include <asm/msr.h> | 34 | #include <asm/msr.h> |
34 | #include <asm/timex.h> | 35 | #include <asm/timex.h> |
@@ -119,7 +120,13 @@ static int longhaul_get_cpu_mult(void) | |||
119 | static void do_powersaver(union msr_longhaul *longhaul, | 120 | static void do_powersaver(union msr_longhaul *longhaul, |
120 | unsigned int clock_ratio_index) | 121 | unsigned int clock_ratio_index) |
121 | { | 122 | { |
123 | struct pci_dev *dev; | ||
124 | unsigned long flags; | ||
125 | unsigned int tmp_mask; | ||
122 | int version; | 126 | int version; |
127 | int i; | ||
128 | u16 pci_cmd; | ||
129 | u16 cmd_state[64]; | ||
123 | 130 | ||
124 | switch (cpu_model) { | 131 | switch (cpu_model) { |
125 | case CPU_EZRA_T: | 132 | case CPU_EZRA_T: |
@@ -137,17 +144,58 @@ static void do_powersaver(union msr_longhaul *longhaul, | |||
137 | longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; | 144 | longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; |
138 | longhaul->bits.EnableSoftBusRatio = 1; | 145 | longhaul->bits.EnableSoftBusRatio = 1; |
139 | longhaul->bits.RevisionKey = 0; | 146 | longhaul->bits.RevisionKey = 0; |
140 | local_irq_disable(); | 147 | |
141 | wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); | 148 | preempt_disable(); |
149 | local_irq_save(flags); | ||
150 | |||
151 | /* | ||
152 | * get current pci bus master state for all devices | ||
153 | * and clear bus master bit | ||
154 | */ | ||
155 | dev = NULL; | ||
156 | i = 0; | ||
157 | do { | ||
158 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); | ||
159 | if (dev != NULL) { | ||
160 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | ||
161 | cmd_state[i++] = pci_cmd; | ||
162 | pci_cmd &= ~PCI_COMMAND_MASTER; | ||
163 | pci_write_config_word(dev, PCI_COMMAND, pci_cmd); | ||
164 | } | ||
165 | } while (dev != NULL); | ||
166 | |||
167 | tmp_mask=inb(0x21); /* works on C3. save mask. */ | ||
168 | outb(0xFE,0x21); /* TMR0 only */ | ||
169 | outb(0xFF,0x80); /* delay */ | ||
170 | |||
142 | local_irq_enable(); | 171 | local_irq_enable(); |
172 | |||
173 | __hlt(); | ||
174 | wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); | ||
143 | __hlt(); | 175 | __hlt(); |
144 | 176 | ||
177 | local_irq_disable(); | ||
178 | |||
179 | outb(tmp_mask,0x21); /* restore mask */ | ||
180 | |||
181 | /* restore pci bus master state for all devices */ | ||
182 | dev = NULL; | ||
183 | i = 0; | ||
184 | do { | ||
185 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); | ||
186 | if (dev != NULL) { | ||
187 | pci_cmd = cmd_state[i++]; | ||
188 | pci_write_config_byte(dev, PCI_COMMAND, pci_cmd); | ||
189 | } | ||
190 | } while (dev != NULL); | ||
191 | local_irq_restore(flags); | ||
192 | preempt_enable(); | ||
193 | |||
194 | /* disable bus ratio bit */ | ||
145 | rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); | 195 | rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); |
146 | longhaul->bits.EnableSoftBusRatio = 0; | 196 | longhaul->bits.EnableSoftBusRatio = 0; |
147 | longhaul->bits.RevisionKey = version; | 197 | longhaul->bits.RevisionKey = version; |
148 | local_irq_disable(); | ||
149 | wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); | 198 | wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); |
150 | local_irq_enable(); | ||
151 | } | 199 | } |
152 | 200 | ||
153 | /** | 201 | /** |
@@ -578,7 +626,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
578 | longhaul_setup_voltagescaling(); | 626 | longhaul_setup_voltagescaling(); |
579 | 627 | ||
580 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | 628 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; |
581 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 629 | policy->cpuinfo.transition_latency = 200000; /* nsec */ |
582 | policy->cur = calc_speed(longhaul_get_cpu_mult()); | 630 | policy->cur = calc_speed(longhaul_get_cpu_mult()); |
583 | 631 | ||
584 | ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); | 632 | ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); |
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 913f652623d9..5c530064eb74 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/dmi.h> | 23 | #include <linux/dmi.h> |
24 | 24 | ||
25 | #include <asm/msr.h> | 25 | #include <asm/msr.h> |
26 | #include <asm/timer.h> | ||
26 | #include <asm/timex.h> | 27 | #include <asm/timex.h> |
27 | #include <asm/io.h> | 28 | #include <asm/io.h> |
28 | #include <asm/system.h> | 29 | #include <asm/system.h> |
@@ -586,13 +587,17 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) | |||
586 | 587 | ||
587 | rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val); | 588 | rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val); |
588 | 589 | ||
589 | /* A K7 with powernow technology is set to max frequency by BIOS */ | 590 | /* recalibrate cpu_khz */ |
590 | fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID]; | 591 | result = recalibrate_cpu_khz(); |
592 | if (result) | ||
593 | return result; | ||
594 | |||
595 | fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID]; | ||
591 | if (!fsb) { | 596 | if (!fsb) { |
592 | printk(KERN_WARNING PFX "can not determine bus frequency\n"); | 597 | printk(KERN_WARNING PFX "can not determine bus frequency\n"); |
593 | return -EINVAL; | 598 | return -EINVAL; |
594 | } | 599 | } |
595 | dprintk("FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000); | 600 | dprintk("FSB: %3dMHz\n", fsb/1000); |
596 | 601 | ||
597 | if (dmi_check_system(powernow_dmi_table) || acpi_force) { | 602 | if (dmi_check_system(powernow_dmi_table) || acpi_force) { |
598 | printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n"); | 603 | printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n"); |
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index a65ff7e32e5d..10cc096c0ade 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * GNU general public license version 2. See "COPYING" or | 4 | * GNU general public license version 2. See "COPYING" or |
5 | * http://www.gnu.org/licenses/gpl.html | 5 | * http://www.gnu.org/licenses/gpl.html |
6 | * | 6 | * |
7 | * Support : paul.devriendt@amd.com | 7 | * Support : mark.langsdorf@amd.com |
8 | * | 8 | * |
9 | * Based on the powernow-k7.c module written by Dave Jones. | 9 | * Based on the powernow-k7.c module written by Dave Jones. |
10 | * (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs | 10 | * (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs |
@@ -15,12 +15,13 @@ | |||
15 | * | 15 | * |
16 | * Valuable input gratefully received from Dave Jones, Pavel Machek, | 16 | * Valuable input gratefully received from Dave Jones, Pavel Machek, |
17 | * Dominik Brodowski, and others. | 17 | * Dominik Brodowski, and others. |
18 | * Originally developed by Paul Devriendt. | ||
18 | * Processor information obtained from Chapter 9 (Power and Thermal Management) | 19 | * Processor information obtained from Chapter 9 (Power and Thermal Management) |
19 | * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD | 20 | * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD |
20 | * Opteron Processors" available for download from www.amd.com | 21 | * Opteron Processors" available for download from www.amd.com |
21 | * | 22 | * |
22 | * Tables for specific CPUs can be infrerred from | 23 | * Tables for specific CPUs can be infrerred from |
23 | * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf | 24 | * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf |
24 | */ | 25 | */ |
25 | 26 | ||
26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
@@ -30,6 +31,7 @@ | |||
30 | #include <linux/cpufreq.h> | 31 | #include <linux/cpufreq.h> |
31 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
32 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/cpumask.h> | ||
33 | 35 | ||
34 | #include <asm/msr.h> | 36 | #include <asm/msr.h> |
35 | #include <asm/io.h> | 37 | #include <asm/io.h> |
@@ -42,7 +44,7 @@ | |||
42 | 44 | ||
43 | #define PFX "powernow-k8: " | 45 | #define PFX "powernow-k8: " |
44 | #define BFX PFX "BIOS error: " | 46 | #define BFX PFX "BIOS error: " |
45 | #define VERSION "version 1.00.09e" | 47 | #define VERSION "version 1.40.2" |
46 | #include "powernow-k8.h" | 48 | #include "powernow-k8.h" |
47 | 49 | ||
48 | /* serialize freq changes */ | 50 | /* serialize freq changes */ |
@@ -50,6 +52,10 @@ static DECLARE_MUTEX(fidvid_sem); | |||
50 | 52 | ||
51 | static struct powernow_k8_data *powernow_data[NR_CPUS]; | 53 | static struct powernow_k8_data *powernow_data[NR_CPUS]; |
52 | 54 | ||
55 | #ifndef CONFIG_SMP | ||
56 | static cpumask_t cpu_core_map[1]; | ||
57 | #endif | ||
58 | |||
53 | /* Return a frequency in MHz, given an input fid */ | 59 | /* Return a frequency in MHz, given an input fid */ |
54 | static u32 find_freq_from_fid(u32 fid) | 60 | static u32 find_freq_from_fid(u32 fid) |
55 | { | 61 | { |
@@ -274,11 +280,18 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid | |||
274 | { | 280 | { |
275 | u32 rvosteps = data->rvo; | 281 | u32 rvosteps = data->rvo; |
276 | u32 savefid = data->currfid; | 282 | u32 savefid = data->currfid; |
283 | u32 maxvid, lo; | ||
277 | 284 | ||
278 | dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n", | 285 | dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n", |
279 | smp_processor_id(), | 286 | smp_processor_id(), |
280 | data->currfid, data->currvid, reqvid, data->rvo); | 287 | data->currfid, data->currvid, reqvid, data->rvo); |
281 | 288 | ||
289 | rdmsr(MSR_FIDVID_STATUS, lo, maxvid); | ||
290 | maxvid = 0x1f & (maxvid >> 16); | ||
291 | dprintk("ph1 maxvid=0x%x\n", maxvid); | ||
292 | if (reqvid < maxvid) /* lower numbers are higher voltages */ | ||
293 | reqvid = maxvid; | ||
294 | |||
282 | while (data->currvid > reqvid) { | 295 | while (data->currvid > reqvid) { |
283 | dprintk("ph1: curr 0x%x, req vid 0x%x\n", | 296 | dprintk("ph1: curr 0x%x, req vid 0x%x\n", |
284 | data->currvid, reqvid); | 297 | data->currvid, reqvid); |
@@ -286,8 +299,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid | |||
286 | return 1; | 299 | return 1; |
287 | } | 300 | } |
288 | 301 | ||
289 | while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) { | 302 | while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) { |
290 | if (data->currvid == 0) { | 303 | if (data->currvid == maxvid) { |
291 | rvosteps = 0; | 304 | rvosteps = 0; |
292 | } else { | 305 | } else { |
293 | dprintk("ph1: changing vid for rvo, req 0x%x\n", | 306 | dprintk("ph1: changing vid for rvo, req 0x%x\n", |
@@ -671,7 +684,7 @@ static int find_psb_table(struct powernow_k8_data *data) | |||
671 | * BIOS and Kernel Developer's Guide, which is available on | 684 | * BIOS and Kernel Developer's Guide, which is available on |
672 | * www.amd.com | 685 | * www.amd.com |
673 | */ | 686 | */ |
674 | printk(KERN_ERR PFX "BIOS error - no PSB\n"); | 687 | printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n"); |
675 | return -ENODEV; | 688 | return -ENODEV; |
676 | } | 689 | } |
677 | 690 | ||
@@ -695,7 +708,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) | |||
695 | struct cpufreq_frequency_table *powernow_table; | 708 | struct cpufreq_frequency_table *powernow_table; |
696 | 709 | ||
697 | if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { | 710 | if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { |
698 | dprintk("register performance failed\n"); | 711 | dprintk("register performance failed: bad ACPI data\n"); |
699 | return -EIO; | 712 | return -EIO; |
700 | } | 713 | } |
701 | 714 | ||
@@ -746,22 +759,23 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) | |||
746 | continue; | 759 | continue; |
747 | } | 760 | } |
748 | 761 | ||
749 | if (fid < HI_FID_TABLE_BOTTOM) { | 762 | /* verify only 1 entry from the lo frequency table */ |
750 | if (cntlofreq) { | 763 | if (fid < HI_FID_TABLE_BOTTOM) { |
751 | /* if both entries are the same, ignore this | 764 | if (cntlofreq) { |
752 | * one... | 765 | /* if both entries are the same, ignore this |
753 | */ | 766 | * one... |
754 | if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) || | 767 | */ |
755 | (powernow_table[i].index != powernow_table[cntlofreq].index)) { | 768 | if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) || |
756 | printk(KERN_ERR PFX "Too many lo freq table entries\n"); | 769 | (powernow_table[i].index != powernow_table[cntlofreq].index)) { |
757 | goto err_out_mem; | 770 | printk(KERN_ERR PFX "Too many lo freq table entries\n"); |
758 | } | 771 | goto err_out_mem; |
759 | 772 | } | |
760 | dprintk("double low frequency table entry, ignoring it.\n"); | 773 | |
761 | powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; | 774 | dprintk("double low frequency table entry, ignoring it.\n"); |
762 | continue; | 775 | powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; |
763 | } else | 776 | continue; |
764 | cntlofreq = i; | 777 | } else |
778 | cntlofreq = i; | ||
765 | } | 779 | } |
766 | 780 | ||
767 | if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { | 781 | if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { |
@@ -816,7 +830,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde | |||
816 | { | 830 | { |
817 | u32 fid; | 831 | u32 fid; |
818 | u32 vid; | 832 | u32 vid; |
819 | int res; | 833 | int res, i; |
820 | struct cpufreq_freqs freqs; | 834 | struct cpufreq_freqs freqs; |
821 | 835 | ||
822 | dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); | 836 | dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); |
@@ -841,7 +855,8 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde | |||
841 | } | 855 | } |
842 | 856 | ||
843 | if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) { | 857 | if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) { |
844 | printk("ignoring illegal change in lo freq table-%x to 0x%x\n", | 858 | printk(KERN_ERR PFX |
859 | "ignoring illegal change in lo freq table-%x to 0x%x\n", | ||
845 | data->currfid, fid); | 860 | data->currfid, fid); |
846 | return 1; | 861 | return 1; |
847 | } | 862 | } |
@@ -850,18 +865,20 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde | |||
850 | smp_processor_id(), fid, vid); | 865 | smp_processor_id(), fid, vid); |
851 | 866 | ||
852 | freqs.cpu = data->cpu; | 867 | freqs.cpu = data->cpu; |
853 | |||
854 | freqs.old = find_khz_freq_from_fid(data->currfid); | 868 | freqs.old = find_khz_freq_from_fid(data->currfid); |
855 | freqs.new = find_khz_freq_from_fid(fid); | 869 | freqs.new = find_khz_freq_from_fid(fid); |
856 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 870 | for_each_cpu_mask(i, cpu_core_map[data->cpu]) { |
871 | freqs.cpu = i; | ||
872 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
873 | } | ||
857 | 874 | ||
858 | down(&fidvid_sem); | ||
859 | res = transition_fid_vid(data, fid, vid); | 875 | res = transition_fid_vid(data, fid, vid); |
860 | up(&fidvid_sem); | ||
861 | 876 | ||
862 | freqs.new = find_khz_freq_from_fid(data->currfid); | 877 | freqs.new = find_khz_freq_from_fid(data->currfid); |
863 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 878 | for_each_cpu_mask(i, cpu_core_map[data->cpu]) { |
864 | 879 | freqs.cpu = i; | |
880 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
881 | } | ||
865 | return res; | 882 | return res; |
866 | } | 883 | } |
867 | 884 | ||
@@ -874,6 +891,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi | |||
874 | u32 checkvid = data->currvid; | 891 | u32 checkvid = data->currvid; |
875 | unsigned int newstate; | 892 | unsigned int newstate; |
876 | int ret = -EIO; | 893 | int ret = -EIO; |
894 | int i; | ||
877 | 895 | ||
878 | /* only run on specific CPU from here on */ | 896 | /* only run on specific CPU from here on */ |
879 | oldmask = current->cpus_allowed; | 897 | oldmask = current->cpus_allowed; |
@@ -902,22 +920,41 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi | |||
902 | data->currfid, data->currvid); | 920 | data->currfid, data->currvid); |
903 | 921 | ||
904 | if ((checkvid != data->currvid) || (checkfid != data->currfid)) { | 922 | if ((checkvid != data->currvid) || (checkfid != data->currfid)) { |
905 | printk(KERN_ERR PFX | 923 | printk(KERN_INFO PFX |
906 | "error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n", | 924 | "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n", |
907 | checkfid, data->currfid, checkvid, data->currvid); | 925 | checkfid, data->currfid, checkvid, data->currvid); |
908 | } | 926 | } |
909 | 927 | ||
910 | if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) | 928 | if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) |
911 | goto err_out; | 929 | goto err_out; |
912 | 930 | ||
931 | down(&fidvid_sem); | ||
932 | |||
933 | for_each_cpu_mask(i, cpu_core_map[pol->cpu]) { | ||
934 | /* make sure the sibling is initialized */ | ||
935 | if (!powernow_data[i]) { | ||
936 | ret = 0; | ||
937 | up(&fidvid_sem); | ||
938 | goto err_out; | ||
939 | } | ||
940 | } | ||
941 | |||
913 | powernow_k8_acpi_pst_values(data, newstate); | 942 | powernow_k8_acpi_pst_values(data, newstate); |
914 | 943 | ||
915 | if (transition_frequency(data, newstate)) { | 944 | if (transition_frequency(data, newstate)) { |
916 | printk(KERN_ERR PFX "transition frequency failed\n"); | 945 | printk(KERN_ERR PFX "transition frequency failed\n"); |
917 | ret = 1; | 946 | ret = 1; |
947 | up(&fidvid_sem); | ||
918 | goto err_out; | 948 | goto err_out; |
919 | } | 949 | } |
920 | 950 | ||
951 | /* Update all the fid/vids of our siblings */ | ||
952 | for_each_cpu_mask(i, cpu_core_map[pol->cpu]) { | ||
953 | powernow_data[i]->currvid = data->currvid; | ||
954 | powernow_data[i]->currfid = data->currfid; | ||
955 | } | ||
956 | up(&fidvid_sem); | ||
957 | |||
921 | pol->cur = find_khz_freq_from_fid(data->currfid); | 958 | pol->cur = find_khz_freq_from_fid(data->currfid); |
922 | ret = 0; | 959 | ret = 0; |
923 | 960 | ||
@@ -962,7 +999,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
962 | */ | 999 | */ |
963 | 1000 | ||
964 | if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { | 1001 | if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { |
965 | printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n"); | 1002 | printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n"); |
966 | kfree(data); | 1003 | kfree(data); |
967 | return -ENODEV; | 1004 | return -ENODEV; |
968 | } | 1005 | } |
@@ -1003,6 +1040,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
1003 | schedule(); | 1040 | schedule(); |
1004 | 1041 | ||
1005 | pol->governor = CPUFREQ_DEFAULT_GOVERNOR; | 1042 | pol->governor = CPUFREQ_DEFAULT_GOVERNOR; |
1043 | pol->cpus = cpu_core_map[pol->cpu]; | ||
1006 | 1044 | ||
1007 | /* Take a crude guess here. | 1045 | /* Take a crude guess here. |
1008 | * That guess was in microseconds, so multiply with 1000 */ | 1046 | * That guess was in microseconds, so multiply with 1000 */ |
@@ -1069,7 +1107,7 @@ static unsigned int powernowk8_get (unsigned int cpu) | |||
1069 | return 0; | 1107 | return 0; |
1070 | } | 1108 | } |
1071 | preempt_disable(); | 1109 | preempt_disable(); |
1072 | 1110 | ||
1073 | if (query_current_values_with_pending_wait(data)) | 1111 | if (query_current_values_with_pending_wait(data)) |
1074 | goto out; | 1112 | goto out; |
1075 | 1113 | ||
@@ -1127,9 +1165,10 @@ static void __exit powernowk8_exit(void) | |||
1127 | cpufreq_unregister_driver(&cpufreq_amd64_driver); | 1165 | cpufreq_unregister_driver(&cpufreq_amd64_driver); |
1128 | } | 1166 | } |
1129 | 1167 | ||
1130 | MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>"); | 1168 | MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com."); |
1131 | MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver."); | 1169 | MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver."); |
1132 | MODULE_LICENSE("GPL"); | 1170 | MODULE_LICENSE("GPL"); |
1133 | 1171 | ||
1134 | late_initcall(powernowk8_init); | 1172 | late_initcall(powernowk8_init); |
1135 | module_exit(powernowk8_exit); | 1173 | module_exit(powernowk8_exit); |
1174 | |||
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index 63ebc8470f52..9ed5bf221cb7 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h | |||
@@ -174,3 +174,18 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi | |||
174 | static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid); | 174 | static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid); |
175 | 175 | ||
176 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index); | 176 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index); |
177 | |||
178 | #ifndef for_each_cpu_mask | ||
179 | #define for_each_cpu_mask(i,mask) for (i=0;i<1;i++) | ||
180 | #endif | ||
181 | |||
182 | #ifdef CONFIG_SMP | ||
183 | static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[]) | ||
184 | { | ||
185 | } | ||
186 | #else | ||
187 | static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[]) | ||
188 | { | ||
189 | cpu_set(0, cpu_sharedcore_mask[0]); | ||
190 | } | ||
191 | #endif | ||
diff --git a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c new file mode 100644 index 000000000000..ef457d50f4ac --- /dev/null +++ b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * sc520_freq.c: cpufreq driver for the AMD Elan sc520 | ||
3 | * | ||
4 | * Copyright (C) 2005 Sean Young <sean@mess.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * Based on elanfreq.c | ||
12 | * | ||
13 | * 2005-03-30: - initial revision | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | #include <linux/cpufreq.h> | ||
22 | |||
23 | #include <asm/msr.h> | ||
24 | #include <asm/timex.h> | ||
25 | #include <asm/io.h> | ||
26 | |||
27 | #define MMCR_BASE 0xfffef000 /* The default base address */ | ||
28 | #define OFFS_CPUCTL 0x2 /* CPU Control Register */ | ||
29 | |||
30 | static __u8 __iomem *cpuctl; | ||
31 | |||
32 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "sc520_freq", msg) | ||
33 | |||
34 | static struct cpufreq_frequency_table sc520_freq_table[] = { | ||
35 | {0x01, 100000}, | ||
36 | {0x02, 133000}, | ||
37 | {0, CPUFREQ_TABLE_END}, | ||
38 | }; | ||
39 | |||
40 | static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu) | ||
41 | { | ||
42 | u8 clockspeed_reg = *cpuctl; | ||
43 | |||
44 | switch (clockspeed_reg & 0x03) { | ||
45 | default: | ||
46 | printk(KERN_ERR "sc520_freq: error: cpuctl register has unexpected value %02x\n", clockspeed_reg); | ||
47 | case 0x01: | ||
48 | return 100000; | ||
49 | case 0x02: | ||
50 | return 133000; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | static void sc520_freq_set_cpu_state (unsigned int state) | ||
55 | { | ||
56 | |||
57 | struct cpufreq_freqs freqs; | ||
58 | u8 clockspeed_reg; | ||
59 | |||
60 | freqs.old = sc520_freq_get_cpu_frequency(0); | ||
61 | freqs.new = sc520_freq_table[state].frequency; | ||
62 | freqs.cpu = 0; /* AMD Elan is UP */ | ||
63 | |||
64 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
65 | |||
66 | dprintk("attempting to set frequency to %i kHz\n", | ||
67 | sc520_freq_table[state].frequency); | ||
68 | |||
69 | local_irq_disable(); | ||
70 | |||
71 | clockspeed_reg = *cpuctl & ~0x03; | ||
72 | *cpuctl = clockspeed_reg | sc520_freq_table[state].index; | ||
73 | |||
74 | local_irq_enable(); | ||
75 | |||
76 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
77 | }; | ||
78 | |||
79 | static int sc520_freq_verify (struct cpufreq_policy *policy) | ||
80 | { | ||
81 | return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]); | ||
82 | } | ||
83 | |||
84 | static int sc520_freq_target (struct cpufreq_policy *policy, | ||
85 | unsigned int target_freq, | ||
86 | unsigned int relation) | ||
87 | { | ||
88 | unsigned int newstate = 0; | ||
89 | |||
90 | if (cpufreq_frequency_table_target(policy, sc520_freq_table, target_freq, relation, &newstate)) | ||
91 | return -EINVAL; | ||
92 | |||
93 | sc520_freq_set_cpu_state(newstate); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | |||
99 | /* | ||
100 | * Module init and exit code | ||
101 | */ | ||
102 | |||
103 | static int sc520_freq_cpu_init(struct cpufreq_policy *policy) | ||
104 | { | ||
105 | struct cpuinfo_x86 *c = cpu_data; | ||
106 | int result; | ||
107 | |||
108 | /* capability check */ | ||
109 | if (c->x86_vendor != X86_VENDOR_AMD || | ||
110 | c->x86 != 4 || c->x86_model != 9) | ||
111 | return -ENODEV; | ||
112 | |||
113 | /* cpuinfo and default policy values */ | ||
114 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
115 | policy->cpuinfo.transition_latency = 1000000; /* 1ms */ | ||
116 | policy->cur = sc520_freq_get_cpu_frequency(0); | ||
117 | |||
118 | result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table); | ||
119 | if (result) | ||
120 | return (result); | ||
121 | |||
122 | cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | |||
128 | static int sc520_freq_cpu_exit(struct cpufreq_policy *policy) | ||
129 | { | ||
130 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | |||
135 | static struct freq_attr* sc520_freq_attr[] = { | ||
136 | &cpufreq_freq_attr_scaling_available_freqs, | ||
137 | NULL, | ||
138 | }; | ||
139 | |||
140 | |||
141 | static struct cpufreq_driver sc520_freq_driver = { | ||
142 | .get = sc520_freq_get_cpu_frequency, | ||
143 | .verify = sc520_freq_verify, | ||
144 | .target = sc520_freq_target, | ||
145 | .init = sc520_freq_cpu_init, | ||
146 | .exit = sc520_freq_cpu_exit, | ||
147 | .name = "sc520_freq", | ||
148 | .owner = THIS_MODULE, | ||
149 | .attr = sc520_freq_attr, | ||
150 | }; | ||
151 | |||
152 | |||
153 | static int __init sc520_freq_init(void) | ||
154 | { | ||
155 | struct cpuinfo_x86 *c = cpu_data; | ||
156 | |||
157 | /* Test if we have the right hardware */ | ||
158 | if(c->x86_vendor != X86_VENDOR_AMD || | ||
159 | c->x86 != 4 || c->x86_model != 9) { | ||
160 | dprintk("no Elan SC520 processor found!\n"); | ||
161 | return -ENODEV; | ||
162 | } | ||
163 | cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1); | ||
164 | if(!cpuctl) { | ||
165 | printk(KERN_ERR "sc520_freq: error: failed to remap memory\n"); | ||
166 | return -ENOMEM; | ||
167 | } | ||
168 | |||
169 | return cpufreq_register_driver(&sc520_freq_driver); | ||
170 | } | ||
171 | |||
172 | |||
173 | static void __exit sc520_freq_exit(void) | ||
174 | { | ||
175 | cpufreq_unregister_driver(&sc520_freq_driver); | ||
176 | iounmap(cpuctl); | ||
177 | } | ||
178 | |||
179 | |||
180 | MODULE_LICENSE("GPL"); | ||
181 | MODULE_AUTHOR("Sean Young <sean@mess.org>"); | ||
182 | MODULE_DESCRIPTION("cpufreq driver for AMD's Elan sc520 CPU"); | ||
183 | |||
184 | module_init(sc520_freq_init); | ||
185 | module_exit(sc520_freq_exit); | ||
186 | |||
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 07d5612dc00f..7dcbf70fc16f 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | |||
@@ -54,6 +54,8 @@ enum { | |||
54 | CPU_DOTHAN_A1, | 54 | CPU_DOTHAN_A1, |
55 | CPU_DOTHAN_A2, | 55 | CPU_DOTHAN_A2, |
56 | CPU_DOTHAN_B0, | 56 | CPU_DOTHAN_B0, |
57 | CPU_MP4HT_D0, | ||
58 | CPU_MP4HT_E0, | ||
57 | }; | 59 | }; |
58 | 60 | ||
59 | static const struct cpu_id cpu_ids[] = { | 61 | static const struct cpu_id cpu_ids[] = { |
@@ -61,6 +63,8 @@ static const struct cpu_id cpu_ids[] = { | |||
61 | [CPU_DOTHAN_A1] = { 6, 13, 1 }, | 63 | [CPU_DOTHAN_A1] = { 6, 13, 1 }, |
62 | [CPU_DOTHAN_A2] = { 6, 13, 2 }, | 64 | [CPU_DOTHAN_A2] = { 6, 13, 2 }, |
63 | [CPU_DOTHAN_B0] = { 6, 13, 6 }, | 65 | [CPU_DOTHAN_B0] = { 6, 13, 6 }, |
66 | [CPU_MP4HT_D0] = {15, 3, 4 }, | ||
67 | [CPU_MP4HT_E0] = {15, 4, 1 }, | ||
64 | }; | 68 | }; |
65 | #define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0])) | 69 | #define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0])) |
66 | 70 | ||
@@ -226,6 +230,8 @@ static struct cpu_model models[] = | |||
226 | { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL }, | 230 | { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL }, |
227 | { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL }, | 231 | { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL }, |
228 | { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL }, | 232 | { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL }, |
233 | { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL }, | ||
234 | { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL }, | ||
229 | 235 | ||
230 | { NULL, } | 236 | { NULL, } |
231 | }; | 237 | }; |
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c index 8ba430a9c3a2..d368b3f5fce8 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c | |||
@@ -336,7 +336,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, | |||
336 | if (!prev_speed) | 336 | if (!prev_speed) |
337 | return -EIO; | 337 | return -EIO; |
338 | 338 | ||
339 | dprintk("previous seped is %u\n", prev_speed); | 339 | dprintk("previous speed is %u\n", prev_speed); |
340 | 340 | ||
341 | local_irq_save(flags); | 341 | local_irq_save(flags); |
342 | 342 | ||
@@ -348,7 +348,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, | |||
348 | goto out; | 348 | goto out; |
349 | } | 349 | } |
350 | 350 | ||
351 | dprintk("low seped is %u\n", *low_speed); | 351 | dprintk("low speed is %u\n", *low_speed); |
352 | 352 | ||
353 | /* switch to high state */ | 353 | /* switch to high state */ |
354 | set_state(SPEEDSTEP_HIGH); | 354 | set_state(SPEEDSTEP_HIGH); |
@@ -358,7 +358,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, | |||
358 | goto out; | 358 | goto out; |
359 | } | 359 | } |
360 | 360 | ||
361 | dprintk("high seped is %u\n", *high_speed); | 361 | dprintk("high speed is %u\n", *high_speed); |
362 | 362 | ||
363 | if (*low_speed == *high_speed) { | 363 | if (*low_speed == *high_speed) { |
364 | ret = -ENODEV; | 364 | ret = -ENODEV; |
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index 79440b3f087e..b25fb6b635ae 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c | |||
@@ -357,6 +357,9 @@ static int __init speedstep_init(void) | |||
357 | case SPEEDSTEP_PROCESSOR_PIII_C: | 357 | case SPEEDSTEP_PROCESSOR_PIII_C: |
358 | case SPEEDSTEP_PROCESSOR_PIII_C_EARLY: | 358 | case SPEEDSTEP_PROCESSOR_PIII_C_EARLY: |
359 | break; | 359 | break; |
360 | case SPEEDSTEP_PROCESSOR_P4M: | ||
361 | printk(KERN_INFO "speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.\n"); | ||
362 | break; | ||
360 | default: | 363 | default: |
361 | speedstep_processor = 0; | 364 | speedstep_processor = 0; |
362 | } | 365 | } |
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 945ec73163c8..2bfbddebdbf8 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -1502,11 +1502,13 @@ void __init setup_arch(char **cmdline_p) | |||
1502 | if (efi_enabled) | 1502 | if (efi_enabled) |
1503 | efi_map_memmap(); | 1503 | efi_map_memmap(); |
1504 | 1504 | ||
1505 | #ifdef CONFIG_ACPI_BOOT | ||
1505 | /* | 1506 | /* |
1506 | * Parse the ACPI tables for possible boot-time SMP configuration. | 1507 | * Parse the ACPI tables for possible boot-time SMP configuration. |
1507 | */ | 1508 | */ |
1508 | acpi_boot_table_init(); | 1509 | acpi_boot_table_init(); |
1509 | acpi_boot_init(); | 1510 | acpi_boot_init(); |
1511 | #endif | ||
1510 | 1512 | ||
1511 | #ifdef CONFIG_X86_LOCAL_APIC | 1513 | #ifdef CONFIG_X86_LOCAL_APIC |
1512 | if (smp_found_config) | 1514 | if (smp_found_config) |
diff --git a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c index f7f90005e22e..8e201219f525 100644 --- a/arch/i386/kernel/timers/common.c +++ b/arch/i386/kernel/timers/common.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/timex.h> | 6 | #include <linux/timex.h> |
7 | #include <linux/errno.h> | 7 | #include <linux/errno.h> |
8 | #include <linux/jiffies.h> | 8 | #include <linux/jiffies.h> |
9 | #include <linux/module.h> | ||
9 | 10 | ||
10 | #include <asm/io.h> | 11 | #include <asm/io.h> |
11 | #include <asm/timer.h> | 12 | #include <asm/timer.h> |
@@ -24,7 +25,7 @@ | |||
24 | 25 | ||
25 | #define CALIBRATE_TIME (5 * 1000020/HZ) | 26 | #define CALIBRATE_TIME (5 * 1000020/HZ) |
26 | 27 | ||
27 | unsigned long __init calibrate_tsc(void) | 28 | unsigned long calibrate_tsc(void) |
28 | { | 29 | { |
29 | mach_prepare_counter(); | 30 | mach_prepare_counter(); |
30 | 31 | ||
@@ -139,7 +140,7 @@ bad_calibration: | |||
139 | #endif | 140 | #endif |
140 | 141 | ||
141 | /* calculate cpu_khz */ | 142 | /* calculate cpu_khz */ |
142 | void __init init_cpu_khz(void) | 143 | void init_cpu_khz(void) |
143 | { | 144 | { |
144 | if (cpu_has_tsc) { | 145 | if (cpu_has_tsc) { |
145 | unsigned long tsc_quotient = calibrate_tsc(); | 146 | unsigned long tsc_quotient = calibrate_tsc(); |
@@ -158,3 +159,4 @@ void __init init_cpu_khz(void) | |||
158 | } | 159 | } |
159 | } | 160 | } |
160 | } | 161 | } |
162 | |||
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index 7926d967be00..180444d87824 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c | |||
@@ -320,6 +320,26 @@ core_initcall(cpufreq_tsc); | |||
320 | static inline void cpufreq_delayed_get(void) { return; } | 320 | static inline void cpufreq_delayed_get(void) { return; } |
321 | #endif | 321 | #endif |
322 | 322 | ||
323 | int recalibrate_cpu_khz(void) | ||
324 | { | ||
325 | #ifndef CONFIG_SMP | ||
326 | unsigned long cpu_khz_old = cpu_khz; | ||
327 | |||
328 | if (cpu_has_tsc) { | ||
329 | init_cpu_khz(); | ||
330 | cpu_data[0].loops_per_jiffy = | ||
331 | cpufreq_scale(cpu_data[0].loops_per_jiffy, | ||
332 | cpu_khz_old, | ||
333 | cpu_khz); | ||
334 | return 0; | ||
335 | } else | ||
336 | return -ENODEV; | ||
337 | #else | ||
338 | return -ENODEV; | ||
339 | #endif | ||
340 | } | ||
341 | EXPORT_SYMBOL(recalibrate_cpu_khz); | ||
342 | |||
323 | static void mark_offset_tsc(void) | 343 | static void mark_offset_tsc(void) |
324 | { | 344 | { |
325 | unsigned long lost,delay; | 345 | unsigned long lost,delay; |
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 247a21c64aea..c1e20d65dd6c 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c | |||
@@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents, | |||
2427 | { | 2427 | { |
2428 | struct epoll_event *events64 = NULL; | 2428 | struct epoll_event *events64 = NULL; |
2429 | mm_segment_t old_fs = get_fs(); | 2429 | mm_segment_t old_fs = get_fs(); |
2430 | int error, numevents, size; | 2430 | int numevents, size; |
2431 | int evt_idx; | 2431 | int evt_idx; |
2432 | int do_free_pages = 0; | 2432 | int do_free_pages = 0; |
2433 | 2433 | ||
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 81c45d447394..d99316c9be28 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -1182,7 +1182,7 @@ ENTRY(notify_resume_user) | |||
1182 | ;; | 1182 | ;; |
1183 | (pNonSys) mov out2=0 // out2==0 => not a syscall | 1183 | (pNonSys) mov out2=0 // out2==0 => not a syscall |
1184 | .fframe 16 | 1184 | .fframe 16 |
1185 | .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) | 1185 | .spillsp ar.unat, 16 |
1186 | st8 [sp]=r9,-16 // allocate space for ar.unat and save it | 1186 | st8 [sp]=r9,-16 // allocate space for ar.unat and save it |
1187 | st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch | 1187 | st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch |
1188 | .body | 1188 | .body |
@@ -1208,7 +1208,7 @@ GLOBAL_ENTRY(sys_rt_sigsuspend) | |||
1208 | adds out2=8,sp // out2=&sigscratch->ar_pfs | 1208 | adds out2=8,sp // out2=&sigscratch->ar_pfs |
1209 | ;; | 1209 | ;; |
1210 | .fframe 16 | 1210 | .fframe 16 |
1211 | .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) | 1211 | .spillsp ar.unat, 16 |
1212 | st8 [sp]=r9,-16 // allocate space for ar.unat and save it | 1212 | st8 [sp]=r9,-16 // allocate space for ar.unat and save it |
1213 | st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch | 1213 | st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch |
1214 | .body | 1214 | .body |
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 4d6c7b8f667b..736e328b5e61 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c | |||
@@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) | |||
1103 | return IRQ_HANDLED; | 1103 | return IRQ_HANDLED; |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | #endif /* CONFIG_ACPI */ | ||
1107 | |||
1108 | /* | 1106 | /* |
1109 | * ia64_mca_cpe_poll | 1107 | * ia64_mca_cpe_poll |
1110 | * | 1108 | * |
@@ -1122,6 +1120,8 @@ ia64_mca_cpe_poll (unsigned long dummy) | |||
1122 | platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0); | 1120 | platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0); |
1123 | } | 1121 | } |
1124 | 1122 | ||
1123 | #endif /* CONFIG_ACPI */ | ||
1124 | |||
1125 | /* | 1125 | /* |
1126 | * C portion of the OS INIT handler | 1126 | * C portion of the OS INIT handler |
1127 | * | 1127 | * |
@@ -1390,8 +1390,7 @@ ia64_mca_init(void) | |||
1390 | register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); | 1390 | register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); |
1391 | 1391 | ||
1392 | #ifdef CONFIG_ACPI | 1392 | #ifdef CONFIG_ACPI |
1393 | /* Setup the CPEI/P vector and handler */ | 1393 | /* Setup the CPEI/P handler */ |
1394 | cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI); | ||
1395 | register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); | 1394 | register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); |
1396 | #endif | 1395 | #endif |
1397 | 1396 | ||
@@ -1436,6 +1435,7 @@ ia64_mca_late_init(void) | |||
1436 | 1435 | ||
1437 | #ifdef CONFIG_ACPI | 1436 | #ifdef CONFIG_ACPI |
1438 | /* Setup the CPEI/P vector and handler */ | 1437 | /* Setup the CPEI/P vector and handler */ |
1438 | cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI); | ||
1439 | init_timer(&cpe_poll_timer); | 1439 | init_timer(&cpe_poll_timer); |
1440 | cpe_poll_timer.function = ia64_mca_cpe_poll; | 1440 | cpe_poll_timer.function = ia64_mca_cpe_poll; |
1441 | 1441 | ||
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h index 1dbc7b2497c9..f6d8a010d99b 100644 --- a/arch/ia64/kernel/minstate.h +++ b/arch/ia64/kernel/minstate.h | |||
@@ -41,7 +41,7 @@ | |||
41 | (pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \ | 41 | (pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \ |
42 | (pKStk) ld8 r3 = [r3];; \ | 42 | (pKStk) ld8 r3 = [r3];; \ |
43 | (pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \ | 43 | (pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \ |
44 | (pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \ | 44 | (pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \ |
45 | (pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ | 45 | (pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ |
46 | (pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ | 46 | (pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ |
47 | ;; \ | 47 | ;; \ |
@@ -50,7 +50,6 @@ | |||
50 | (pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ | 50 | (pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ |
51 | (pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \ | 51 | (pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \ |
52 | ;; \ | 52 | ;; \ |
53 | (pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ | ||
54 | (pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ | 53 | (pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ |
55 | ;; \ | 54 | ;; \ |
56 | (pUStk) mov r18=ar.bsp; \ | 55 | (pUStk) mov r18=ar.bsp; \ |
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 71c101601e3e..6407bff6bfd7 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
@@ -11,7 +11,7 @@ | |||
11 | * Version Perfmon-2.x is a rewrite of perfmon-1.x | 11 | * Version Perfmon-2.x is a rewrite of perfmon-1.x |
12 | * by Stephane Eranian, Hewlett Packard Co. | 12 | * by Stephane Eranian, Hewlett Packard Co. |
13 | * | 13 | * |
14 | * Copyright (C) 1999-2003, 2005 Hewlett Packard Co | 14 | * Copyright (C) 1999-2005 Hewlett Packard Co |
15 | * Stephane Eranian <eranian@hpl.hp.com> | 15 | * Stephane Eranian <eranian@hpl.hp.com> |
16 | * David Mosberger-Tang <davidm@hpl.hp.com> | 16 | * David Mosberger-Tang <davidm@hpl.hp.com> |
17 | * | 17 | * |
@@ -497,6 +497,9 @@ typedef struct { | |||
497 | static pfm_stats_t pfm_stats[NR_CPUS]; | 497 | static pfm_stats_t pfm_stats[NR_CPUS]; |
498 | static pfm_session_t pfm_sessions; /* global sessions information */ | 498 | static pfm_session_t pfm_sessions; /* global sessions information */ |
499 | 499 | ||
500 | static spinlock_t pfm_alt_install_check = SPIN_LOCK_UNLOCKED; | ||
501 | static pfm_intr_handler_desc_t *pfm_alt_intr_handler; | ||
502 | |||
500 | static struct proc_dir_entry *perfmon_dir; | 503 | static struct proc_dir_entry *perfmon_dir; |
501 | static pfm_uuid_t pfm_null_uuid = {0,}; | 504 | static pfm_uuid_t pfm_null_uuid = {0,}; |
502 | 505 | ||
@@ -606,6 +609,7 @@ DEFINE_PER_CPU(unsigned long, pfm_syst_info); | |||
606 | DEFINE_PER_CPU(struct task_struct *, pmu_owner); | 609 | DEFINE_PER_CPU(struct task_struct *, pmu_owner); |
607 | DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); | 610 | DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); |
608 | DEFINE_PER_CPU(unsigned long, pmu_activation_number); | 611 | DEFINE_PER_CPU(unsigned long, pmu_activation_number); |
612 | EXPORT_PER_CPU_SYMBOL_GPL(pfm_syst_info); | ||
609 | 613 | ||
610 | 614 | ||
611 | /* forward declaration */ | 615 | /* forward declaration */ |
@@ -1325,7 +1329,7 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu) | |||
1325 | error_conflict: | 1329 | error_conflict: |
1326 | DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n", | 1330 | DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n", |
1327 | pfm_sessions.pfs_sys_session[cpu]->pid, | 1331 | pfm_sessions.pfs_sys_session[cpu]->pid, |
1328 | smp_processor_id())); | 1332 | cpu)); |
1329 | abort: | 1333 | abort: |
1330 | UNLOCK_PFS(flags); | 1334 | UNLOCK_PFS(flags); |
1331 | 1335 | ||
@@ -5555,26 +5559,32 @@ pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs) | |||
5555 | int ret; | 5559 | int ret; |
5556 | 5560 | ||
5557 | this_cpu = get_cpu(); | 5561 | this_cpu = get_cpu(); |
5558 | min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min; | 5562 | if (likely(!pfm_alt_intr_handler)) { |
5559 | max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max; | 5563 | min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min; |
5564 | max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max; | ||
5560 | 5565 | ||
5561 | start_cycles = ia64_get_itc(); | 5566 | start_cycles = ia64_get_itc(); |
5562 | 5567 | ||
5563 | ret = pfm_do_interrupt_handler(irq, arg, regs); | 5568 | ret = pfm_do_interrupt_handler(irq, arg, regs); |
5564 | 5569 | ||
5565 | total_cycles = ia64_get_itc(); | 5570 | total_cycles = ia64_get_itc(); |
5566 | 5571 | ||
5567 | /* | 5572 | /* |
5568 | * don't measure spurious interrupts | 5573 | * don't measure spurious interrupts |
5569 | */ | 5574 | */ |
5570 | if (likely(ret == 0)) { | 5575 | if (likely(ret == 0)) { |
5571 | total_cycles -= start_cycles; | 5576 | total_cycles -= start_cycles; |
5572 | 5577 | ||
5573 | if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles; | 5578 | if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles; |
5574 | if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles; | 5579 | if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles; |
5575 | 5580 | ||
5576 | pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles; | 5581 | pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles; |
5582 | } | ||
5583 | } | ||
5584 | else { | ||
5585 | (*pfm_alt_intr_handler->handler)(irq, arg, regs); | ||
5577 | } | 5586 | } |
5587 | |||
5578 | put_cpu_no_resched(); | 5588 | put_cpu_no_resched(); |
5579 | return IRQ_HANDLED; | 5589 | return IRQ_HANDLED; |
5580 | } | 5590 | } |
@@ -6425,6 +6435,141 @@ static struct irqaction perfmon_irqaction = { | |||
6425 | .name = "perfmon" | 6435 | .name = "perfmon" |
6426 | }; | 6436 | }; |
6427 | 6437 | ||
6438 | static void | ||
6439 | pfm_alt_save_pmu_state(void *data) | ||
6440 | { | ||
6441 | struct pt_regs *regs; | ||
6442 | |||
6443 | regs = ia64_task_regs(current); | ||
6444 | |||
6445 | DPRINT(("called\n")); | ||
6446 | |||
6447 | /* | ||
6448 | * should not be necessary but | ||
6449 | * let's take not risk | ||
6450 | */ | ||
6451 | pfm_clear_psr_up(); | ||
6452 | pfm_clear_psr_pp(); | ||
6453 | ia64_psr(regs)->pp = 0; | ||
6454 | |||
6455 | /* | ||
6456 | * This call is required | ||
6457 | * May cause a spurious interrupt on some processors | ||
6458 | */ | ||
6459 | pfm_freeze_pmu(); | ||
6460 | |||
6461 | ia64_srlz_d(); | ||
6462 | } | ||
6463 | |||
6464 | void | ||
6465 | pfm_alt_restore_pmu_state(void *data) | ||
6466 | { | ||
6467 | struct pt_regs *regs; | ||
6468 | |||
6469 | regs = ia64_task_regs(current); | ||
6470 | |||
6471 | DPRINT(("called\n")); | ||
6472 | |||
6473 | /* | ||
6474 | * put PMU back in state expected | ||
6475 | * by perfmon | ||
6476 | */ | ||
6477 | pfm_clear_psr_up(); | ||
6478 | pfm_clear_psr_pp(); | ||
6479 | ia64_psr(regs)->pp = 0; | ||
6480 | |||
6481 | /* | ||
6482 | * perfmon runs with PMU unfrozen at all times | ||
6483 | */ | ||
6484 | pfm_unfreeze_pmu(); | ||
6485 | |||
6486 | ia64_srlz_d(); | ||
6487 | } | ||
6488 | |||
6489 | int | ||
6490 | pfm_install_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl) | ||
6491 | { | ||
6492 | int ret, i; | ||
6493 | int reserve_cpu; | ||
6494 | |||
6495 | /* some sanity checks */ | ||
6496 | if (hdl == NULL || hdl->handler == NULL) return -EINVAL; | ||
6497 | |||
6498 | /* do the easy test first */ | ||
6499 | if (pfm_alt_intr_handler) return -EBUSY; | ||
6500 | |||
6501 | /* one at a time in the install or remove, just fail the others */ | ||
6502 | if (!spin_trylock(&pfm_alt_install_check)) { | ||
6503 | return -EBUSY; | ||
6504 | } | ||
6505 | |||
6506 | /* reserve our session */ | ||
6507 | for_each_online_cpu(reserve_cpu) { | ||
6508 | ret = pfm_reserve_session(NULL, 1, reserve_cpu); | ||
6509 | if (ret) goto cleanup_reserve; | ||
6510 | } | ||
6511 | |||
6512 | /* save the current system wide pmu states */ | ||
6513 | ret = on_each_cpu(pfm_alt_save_pmu_state, NULL, 0, 1); | ||
6514 | if (ret) { | ||
6515 | DPRINT(("on_each_cpu() failed: %d\n", ret)); | ||
6516 | goto cleanup_reserve; | ||
6517 | } | ||
6518 | |||
6519 | /* officially change to the alternate interrupt handler */ | ||
6520 | pfm_alt_intr_handler = hdl; | ||
6521 | |||
6522 | spin_unlock(&pfm_alt_install_check); | ||
6523 | |||
6524 | return 0; | ||
6525 | |||
6526 | cleanup_reserve: | ||
6527 | for_each_online_cpu(i) { | ||
6528 | /* don't unreserve more than we reserved */ | ||
6529 | if (i >= reserve_cpu) break; | ||
6530 | |||
6531 | pfm_unreserve_session(NULL, 1, i); | ||
6532 | } | ||
6533 | |||
6534 | spin_unlock(&pfm_alt_install_check); | ||
6535 | |||
6536 | return ret; | ||
6537 | } | ||
6538 | EXPORT_SYMBOL_GPL(pfm_install_alt_pmu_interrupt); | ||
6539 | |||
6540 | int | ||
6541 | pfm_remove_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl) | ||
6542 | { | ||
6543 | int i; | ||
6544 | int ret; | ||
6545 | |||
6546 | if (hdl == NULL) return -EINVAL; | ||
6547 | |||
6548 | /* cannot remove someone else's handler! */ | ||
6549 | if (pfm_alt_intr_handler != hdl) return -EINVAL; | ||
6550 | |||
6551 | /* one at a time in the install or remove, just fail the others */ | ||
6552 | if (!spin_trylock(&pfm_alt_install_check)) { | ||
6553 | return -EBUSY; | ||
6554 | } | ||
6555 | |||
6556 | pfm_alt_intr_handler = NULL; | ||
6557 | |||
6558 | ret = on_each_cpu(pfm_alt_restore_pmu_state, NULL, 0, 1); | ||
6559 | if (ret) { | ||
6560 | DPRINT(("on_each_cpu() failed: %d\n", ret)); | ||
6561 | } | ||
6562 | |||
6563 | for_each_online_cpu(i) { | ||
6564 | pfm_unreserve_session(NULL, 1, i); | ||
6565 | } | ||
6566 | |||
6567 | spin_unlock(&pfm_alt_install_check); | ||
6568 | |||
6569 | return 0; | ||
6570 | } | ||
6571 | EXPORT_SYMBOL_GPL(pfm_remove_alt_pmu_interrupt); | ||
6572 | |||
6428 | /* | 6573 | /* |
6429 | * perfmon initialization routine, called from the initcall() table | 6574 | * perfmon initialization routine, called from the initcall() table |
6430 | */ | 6575 | */ |
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 907464ee7273..08c8a5eb25ab 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c | |||
@@ -692,16 +692,30 @@ convert_to_non_syscall (struct task_struct *child, struct pt_regs *pt, | |||
692 | unsigned long cfm) | 692 | unsigned long cfm) |
693 | { | 693 | { |
694 | struct unw_frame_info info, prev_info; | 694 | struct unw_frame_info info, prev_info; |
695 | unsigned long ip, pr; | 695 | unsigned long ip, sp, pr; |
696 | 696 | ||
697 | unw_init_from_blocked_task(&info, child); | 697 | unw_init_from_blocked_task(&info, child); |
698 | while (1) { | 698 | while (1) { |
699 | prev_info = info; | 699 | prev_info = info; |
700 | if (unw_unwind(&info) < 0) | 700 | if (unw_unwind(&info) < 0) |
701 | return; | 701 | return; |
702 | if (unw_get_rp(&info, &ip) < 0) | 702 | |
703 | unw_get_sp(&info, &sp); | ||
704 | if ((long)((unsigned long)child + IA64_STK_OFFSET - sp) | ||
705 | < IA64_PT_REGS_SIZE) { | ||
706 | dprintk("ptrace.%s: ran off the top of the kernel " | ||
707 | "stack\n", __FUNCTION__); | ||
708 | return; | ||
709 | } | ||
710 | if (unw_get_pr (&prev_info, &pr) < 0) { | ||
711 | unw_get_rp(&prev_info, &ip); | ||
712 | dprintk("ptrace.%s: failed to read " | ||
713 | "predicate register (ip=0x%lx)\n", | ||
714 | __FUNCTION__, ip); | ||
703 | return; | 715 | return; |
704 | if (ip < FIXADDR_USER_END) | 716 | } |
717 | if (unw_is_intr_frame(&info) | ||
718 | && (pr & (1UL << PRED_USER_STACK))) | ||
705 | break; | 719 | break; |
706 | } | 720 | } |
707 | 721 | ||
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 0d5ee57c9865..3865f088ffa2 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c | |||
@@ -624,7 +624,7 @@ static struct { | |||
624 | __u16 thread_id; | 624 | __u16 thread_id; |
625 | __u16 proc_fixed_addr; | 625 | __u16 proc_fixed_addr; |
626 | __u8 valid; | 626 | __u8 valid; |
627 | }mt_info[NR_CPUS] __devinit; | 627 | } mt_info[NR_CPUS] __devinitdata; |
628 | 628 | ||
629 | #ifdef CONFIG_HOTPLUG_CPU | 629 | #ifdef CONFIG_HOTPLUG_CPU |
630 | static inline void | 630 | static inline void |
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index a8cf6d8a509c..770fab37928e 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c | |||
@@ -182,13 +182,6 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un | |||
182 | } | 182 | } |
183 | } | 183 | } |
184 | 184 | ||
185 | /* | ||
186 | * A zero mmap always succeeds in Linux, independent of whether or not the | ||
187 | * remaining arguments are valid. | ||
188 | */ | ||
189 | if (len == 0) | ||
190 | goto out; | ||
191 | |||
192 | /* Careful about overflows.. */ | 185 | /* Careful about overflows.. */ |
193 | len = PAGE_ALIGN(len); | 186 | len = PAGE_ALIGN(len); |
194 | if (!len || len > TASK_SIZE) { | 187 | if (!len || len > TASK_SIZE) { |
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 4fb44984afe6..e64cb8175f7a 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c | |||
@@ -271,6 +271,8 @@ void __init sn_setup(char **cmdline_p) | |||
271 | int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); | 271 | int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); |
272 | extern void sn_cpu_init(void); | 272 | extern void sn_cpu_init(void); |
273 | 273 | ||
274 | ia64_sn_plat_set_error_handling_features(); | ||
275 | |||
274 | /* | 276 | /* |
275 | * If the generic code has enabled vga console support - lets | 277 | * If the generic code has enabled vga console support - lets |
276 | * get rid of it again. This is a kludge for the fact that ACPI | 278 | * get rid of it again. This is a kludge for the fact that ACPI |
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 2b6c9d32b7a6..c4a33f265dc0 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c | |||
@@ -45,11 +45,13 @@ asmlinkage void ret_from_fork(void); | |||
45 | */ | 45 | */ |
46 | void default_idle(void) | 46 | void default_idle(void) |
47 | { | 47 | { |
48 | while(1) { | 48 | local_irq_disable(); |
49 | if (need_resched()) | 49 | while (!need_resched()) { |
50 | __asm__("stop #0x2000" : : : "cc"); | 50 | /* This stop will re-enable interrupts */ |
51 | schedule(); | 51 | __asm__("stop #0x2000" : : : "cc"); |
52 | local_irq_disable(); | ||
52 | } | 53 | } |
54 | local_irq_enable(); | ||
53 | } | 55 | } |
54 | 56 | ||
55 | void (*idle)(void) = default_idle; | 57 | void (*idle)(void) = default_idle; |
@@ -63,7 +65,12 @@ void (*idle)(void) = default_idle; | |||
63 | void cpu_idle(void) | 65 | void cpu_idle(void) |
64 | { | 66 | { |
65 | /* endless idle loop with no priority at all */ | 67 | /* endless idle loop with no priority at all */ |
66 | idle(); | 68 | while (1) { |
69 | idle(); | ||
70 | preempt_enable_no_resched(); | ||
71 | schedule(); | ||
72 | preempt_disable(); | ||
73 | } | ||
67 | } | 74 | } |
68 | 75 | ||
69 | void machine_restart(char * __unused) | 76 | void machine_restart(char * __unused) |
diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c index 8aa5e8c69009..d44b7dc5390a 100644 --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c | |||
@@ -838,6 +838,17 @@ struct cpu_spec cpu_specs[] = { | |||
838 | .icache_bsize = 32, | 838 | .icache_bsize = 32, |
839 | .dcache_bsize = 32, | 839 | .dcache_bsize = 32, |
840 | }, | 840 | }, |
841 | { /* 405EP */ | ||
842 | .pvr_mask = 0xffff0000, | ||
843 | .pvr_value = 0x51210000, | ||
844 | .cpu_name = "405EP", | ||
845 | .cpu_features = CPU_FTR_SPLIT_ID_CACHE | | ||
846 | CPU_FTR_USE_TB, | ||
847 | .cpu_user_features = PPC_FEATURE_32 | | ||
848 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
849 | .icache_bsize = 32, | ||
850 | .dcache_bsize = 32, | ||
851 | }, | ||
841 | 852 | ||
842 | #endif /* CONFIG_40x */ | 853 | #endif /* CONFIG_40x */ |
843 | #ifdef CONFIG_44x | 854 | #ifdef CONFIG_44x |
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index e4f1615ec13f..7329ef177a18 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S | |||
@@ -619,7 +619,7 @@ _GLOBAL(flush_instruction_cache) | |||
619 | _GLOBAL(flush_icache_range) | 619 | _GLOBAL(flush_icache_range) |
620 | BEGIN_FTR_SECTION | 620 | BEGIN_FTR_SECTION |
621 | blr /* for 601, do nothing */ | 621 | blr /* for 601, do nothing */ |
622 | END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) | 622 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) |
623 | li r5,L1_CACHE_LINE_SIZE-1 | 623 | li r5,L1_CACHE_LINE_SIZE-1 |
624 | andc r3,r3,r5 | 624 | andc r3,r3,r5 |
625 | subf r4,r3,r4 | 625 | subf r4,r3,r4 |
@@ -736,7 +736,7 @@ _GLOBAL(flush_dcache_all) | |||
736 | _GLOBAL(__flush_dcache_icache) | 736 | _GLOBAL(__flush_dcache_icache) |
737 | BEGIN_FTR_SECTION | 737 | BEGIN_FTR_SECTION |
738 | blr /* for 601, do nothing */ | 738 | blr /* for 601, do nothing */ |
739 | END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) | 739 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) |
740 | rlwinm r3,r3,0,0,19 /* Get page base address */ | 740 | rlwinm r3,r3,0,0,19 /* Get page base address */ |
741 | li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */ | 741 | li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */ |
742 | mtctr r4 | 742 | mtctr r4 |
@@ -764,7 +764,7 @@ END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) | |||
764 | _GLOBAL(__flush_dcache_icache_phys) | 764 | _GLOBAL(__flush_dcache_icache_phys) |
765 | BEGIN_FTR_SECTION | 765 | BEGIN_FTR_SECTION |
766 | blr /* for 601, do nothing */ | 766 | blr /* for 601, do nothing */ |
767 | END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) | 767 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) |
768 | mfmsr r10 | 768 | mfmsr r10 |
769 | rlwinm r0,r10,0,28,26 /* clear DR */ | 769 | rlwinm r0,r10,0,28,26 /* clear DR */ |
770 | mtmsr r0 | 770 | mtmsr r0 |
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c index 2cee87137f2e..7f15136830f4 100644 --- a/arch/ppc/syslib/prom_init.c +++ b/arch/ppc/syslib/prom_init.c | |||
@@ -626,8 +626,18 @@ inspect_node(phandle node, struct device_node *dad, | |||
626 | l = call_prom("package-to-path", 3, 1, node, | 626 | l = call_prom("package-to-path", 3, 1, node, |
627 | mem_start, mem_end - mem_start); | 627 | mem_start, mem_end - mem_start); |
628 | if (l >= 0) { | 628 | if (l >= 0) { |
629 | char *p, *ep; | ||
630 | |||
629 | np->full_name = PTRUNRELOC((char *) mem_start); | 631 | np->full_name = PTRUNRELOC((char *) mem_start); |
630 | *(char *)(mem_start + l) = 0; | 632 | *(char *)(mem_start + l) = 0; |
633 | /* Fixup an Apple bug where they have bogus \0 chars in the | ||
634 | * middle of the path in some properties | ||
635 | */ | ||
636 | for (p = (char *)mem_start, ep = p + l; p < ep; p++) | ||
637 | if ((*p) == '\0') { | ||
638 | memmove(p, p+1, ep - p); | ||
639 | ep--; | ||
640 | } | ||
631 | mem_start = ALIGNUL(mem_start + l + 1); | 641 | mem_start = ALIGNUL(mem_start + l + 1); |
632 | } | 642 | } |
633 | 643 | ||
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S index d3604056e1a9..b61572eb2a71 100644 --- a/arch/ppc64/kernel/entry.S +++ b/arch/ppc64/kernel/entry.S | |||
@@ -436,15 +436,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
436 | REST_8GPRS(14, r1) | 436 | REST_8GPRS(14, r1) |
437 | REST_10GPRS(22, r1) | 437 | REST_10GPRS(22, r1) |
438 | 438 | ||
439 | #ifdef CONFIG_PPC_ISERIES | ||
440 | clrrdi r7,r1,THREAD_SHIFT /* get current_thread_info() */ | ||
441 | ld r7,TI_FLAGS(r7) /* Get run light flag */ | ||
442 | mfspr r9,CTRLF | ||
443 | srdi r7,r7,TIF_RUN_LIGHT | ||
444 | insrdi r9,r7,1,63 /* Insert run light into CTRL */ | ||
445 | mtspr CTRLT,r9 | ||
446 | #endif | ||
447 | |||
448 | /* convert old thread to its task_struct for return value */ | 439 | /* convert old thread to its task_struct for return value */ |
449 | addi r3,r3,-THREAD | 440 | addi r3,r3,-THREAD |
450 | ld r7,_NIP(r1) /* Return to _switch caller in new task */ | 441 | ld r7,_NIP(r1) /* Return to _switch caller in new task */ |
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 92a744c31ab1..346dbf606b5d 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S | |||
@@ -626,10 +626,10 @@ system_reset_iSeries: | |||
626 | lhz r24,PACAPACAINDEX(r13) /* Get processor # */ | 626 | lhz r24,PACAPACAINDEX(r13) /* Get processor # */ |
627 | cmpwi 0,r24,0 /* Are we processor 0? */ | 627 | cmpwi 0,r24,0 /* Are we processor 0? */ |
628 | beq .__start_initialization_iSeries /* Start up the first processor */ | 628 | beq .__start_initialization_iSeries /* Start up the first processor */ |
629 | mfspr r4,CTRLF | 629 | mfspr r4,SPRN_CTRLF |
630 | li r5,RUNLATCH /* Turn off the run light */ | 630 | li r5,CTRL_RUNLATCH /* Turn off the run light */ |
631 | andc r4,r4,r5 | 631 | andc r4,r4,r5 |
632 | mtspr CTRLT,r4 | 632 | mtspr SPRN_CTRLT,r4 |
633 | 633 | ||
634 | 1: | 634 | 1: |
635 | HMT_LOW | 635 | HMT_LOW |
@@ -2082,9 +2082,9 @@ _GLOBAL(hmt_start_secondary) | |||
2082 | mfspr r4, HID0 | 2082 | mfspr r4, HID0 |
2083 | ori r4, r4, 0x1 | 2083 | ori r4, r4, 0x1 |
2084 | mtspr HID0, r4 | 2084 | mtspr HID0, r4 |
2085 | mfspr r4, CTRLF | 2085 | mfspr r4, SPRN_CTRLF |
2086 | oris r4, r4, 0x40 | 2086 | oris r4, r4, 0x40 |
2087 | mtspr CTRLT, r4 | 2087 | mtspr SPRN_CTRLT, r4 |
2088 | blr | 2088 | blr |
2089 | #endif | 2089 | #endif |
2090 | 2090 | ||
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c index da20120f2261..6d06eb550a3f 100644 --- a/arch/ppc64/kernel/iSeries_setup.c +++ b/arch/ppc64/kernel/iSeries_setup.c | |||
@@ -852,6 +852,28 @@ static int __init iSeries_src_init(void) | |||
852 | 852 | ||
853 | late_initcall(iSeries_src_init); | 853 | late_initcall(iSeries_src_init); |
854 | 854 | ||
855 | static int set_spread_lpevents(char *str) | ||
856 | { | ||
857 | unsigned long i; | ||
858 | unsigned long val = simple_strtoul(str, NULL, 0); | ||
859 | |||
860 | /* | ||
861 | * The parameter is the number of processors to share in processing | ||
862 | * lp events. | ||
863 | */ | ||
864 | if (( val > 0) && (val <= NR_CPUS)) { | ||
865 | for (i = 1; i < val; ++i) | ||
866 | paca[i].lpqueue_ptr = paca[0].lpqueue_ptr; | ||
867 | |||
868 | printk("lpevent processing spread over %ld processors\n", val); | ||
869 | } else { | ||
870 | printk("invalid spread_lpevents %ld\n", val); | ||
871 | } | ||
872 | |||
873 | return 1; | ||
874 | } | ||
875 | __setup("spread_lpevents=", set_spread_lpevents); | ||
876 | |||
855 | void __init iSeries_early_setup(void) | 877 | void __init iSeries_early_setup(void) |
856 | { | 878 | { |
857 | iSeries_fixup_klimit(); | 879 | iSeries_fixup_klimit(); |
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index 6abc621d3ba0..f24ce2b87200 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c | |||
@@ -75,13 +75,9 @@ static int iSeries_idle(void) | |||
75 | { | 75 | { |
76 | struct paca_struct *lpaca; | 76 | struct paca_struct *lpaca; |
77 | long oldval; | 77 | long oldval; |
78 | unsigned long CTRL; | ||
79 | 78 | ||
80 | /* ensure iSeries run light will be out when idle */ | 79 | /* ensure iSeries run light will be out when idle */ |
81 | clear_thread_flag(TIF_RUN_LIGHT); | 80 | ppc64_runlatch_off(); |
82 | CTRL = mfspr(CTRLF); | ||
83 | CTRL &= ~RUNLATCH; | ||
84 | mtspr(CTRLT, CTRL); | ||
85 | 81 | ||
86 | lpaca = get_paca(); | 82 | lpaca = get_paca(); |
87 | 83 | ||
@@ -111,7 +107,9 @@ static int iSeries_idle(void) | |||
111 | } | 107 | } |
112 | } | 108 | } |
113 | 109 | ||
110 | ppc64_runlatch_on(); | ||
114 | schedule(); | 111 | schedule(); |
112 | ppc64_runlatch_off(); | ||
115 | } | 113 | } |
116 | 114 | ||
117 | return 0; | 115 | return 0; |
diff --git a/arch/ppc64/kernel/pSeries_reconfig.c b/arch/ppc64/kernel/pSeries_reconfig.c index cb5443f2e49b..dc2a69d412a2 100644 --- a/arch/ppc64/kernel/pSeries_reconfig.c +++ b/arch/ppc64/kernel/pSeries_reconfig.c | |||
@@ -47,14 +47,6 @@ static void remove_node_proc_entries(struct device_node *np) | |||
47 | remove_proc_entry(pp->name, np->pde); | 47 | remove_proc_entry(pp->name, np->pde); |
48 | pp = pp->next; | 48 | pp = pp->next; |
49 | } | 49 | } |
50 | |||
51 | /* Assuming that symlinks have the same parent directory as | ||
52 | * np->pde. | ||
53 | */ | ||
54 | if (np->name_link) | ||
55 | remove_proc_entry(np->name_link->name, parent->pde); | ||
56 | if (np->addr_link) | ||
57 | remove_proc_entry(np->addr_link->name, parent->pde); | ||
58 | if (np->pde) | 50 | if (np->pde) |
59 | remove_proc_entry(np->pde->name, parent->pde); | 51 | remove_proc_entry(np->pde->name, parent->pde); |
60 | } | 52 | } |
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c index 8b0686122738..cdfecbeb331f 100644 --- a/arch/ppc64/kernel/process.c +++ b/arch/ppc64/kernel/process.c | |||
@@ -378,9 +378,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | |||
378 | childregs->gpr[1] = sp + sizeof(struct pt_regs); | 378 | childregs->gpr[1] = sp + sizeof(struct pt_regs); |
379 | p->thread.regs = NULL; /* no user register state */ | 379 | p->thread.regs = NULL; /* no user register state */ |
380 | clear_ti_thread_flag(p->thread_info, TIF_32BIT); | 380 | clear_ti_thread_flag(p->thread_info, TIF_32BIT); |
381 | #ifdef CONFIG_PPC_ISERIES | ||
382 | set_ti_thread_flag(p->thread_info, TIF_RUN_LIGHT); | ||
383 | #endif | ||
384 | } else { | 381 | } else { |
385 | childregs->gpr[1] = usp; | 382 | childregs->gpr[1] = usp; |
386 | p->thread.regs = childregs; | 383 | p->thread.regs = childregs; |
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 6f79b7b9b445..b7683abfbe6a 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c | |||
@@ -211,13 +211,23 @@ struct { | |||
211 | */ | 211 | */ |
212 | #define ADDR(x) (u32) ((unsigned long)(x) - offset) | 212 | #define ADDR(x) (u32) ((unsigned long)(x) - offset) |
213 | 213 | ||
214 | /* | ||
215 | * Error results ... some OF calls will return "-1" on error, some | ||
216 | * will return 0, some will return either. To simplify, here are | ||
217 | * macros to use with any ihandle or phandle return value to check if | ||
218 | * it is valid | ||
219 | */ | ||
220 | |||
221 | #define PROM_ERROR (-1u) | ||
222 | #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) | ||
223 | #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) | ||
224 | |||
225 | |||
214 | /* This is the one and *ONLY* place where we actually call open | 226 | /* This is the one and *ONLY* place where we actually call open |
215 | * firmware from, since we need to make sure we're running in 32b | 227 | * firmware from, since we need to make sure we're running in 32b |
216 | * mode when we do. We switch back to 64b mode upon return. | 228 | * mode when we do. We switch back to 64b mode upon return. |
217 | */ | 229 | */ |
218 | 230 | ||
219 | #define PROM_ERROR (-1) | ||
220 | |||
221 | static int __init call_prom(const char *service, int nargs, int nret, ...) | 231 | static int __init call_prom(const char *service, int nargs, int nret, ...) |
222 | { | 232 | { |
223 | int i; | 233 | int i; |
@@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void) | |||
587 | { | 597 | { |
588 | unsigned long offset = reloc_offset(); | 598 | unsigned long offset = reloc_offset(); |
589 | ihandle elfloader; | 599 | ihandle elfloader; |
590 | int ret; | ||
591 | 600 | ||
592 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); | 601 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); |
593 | if (elfloader == 0) { | 602 | if (elfloader == 0) { |
594 | prom_printf("couldn't open /packages/elf-loader\n"); | 603 | prom_printf("couldn't open /packages/elf-loader\n"); |
595 | return; | 604 | return; |
596 | } | 605 | } |
597 | ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"), | 606 | call_prom("call-method", 3, 1, ADDR("process-elf-header"), |
598 | elfloader, ADDR(&fake_elf)); | 607 | elfloader, ADDR(&fake_elf)); |
599 | call_prom("close", 1, 0, elfloader); | 608 | call_prom("close", 1, 0, elfloader); |
600 | } | 609 | } |
@@ -646,7 +655,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align) | |||
646 | base = _ALIGN_UP(base + 0x100000, align)) { | 655 | base = _ALIGN_UP(base + 0x100000, align)) { |
647 | prom_debug(" trying: 0x%x\n\r", base); | 656 | prom_debug(" trying: 0x%x\n\r", base); |
648 | addr = (unsigned long)prom_claim(base, size, 0); | 657 | addr = (unsigned long)prom_claim(base, size, 0); |
649 | if ((int)addr != PROM_ERROR) | 658 | if (addr != PROM_ERROR) |
650 | break; | 659 | break; |
651 | addr = 0; | 660 | addr = 0; |
652 | if (align == 0) | 661 | if (align == 0) |
@@ -708,7 +717,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align, | |||
708 | for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { | 717 | for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { |
709 | prom_debug(" trying: 0x%x\n\r", base); | 718 | prom_debug(" trying: 0x%x\n\r", base); |
710 | addr = (unsigned long)prom_claim(base, size, 0); | 719 | addr = (unsigned long)prom_claim(base, size, 0); |
711 | if ((int)addr != PROM_ERROR) | 720 | if (addr != PROM_ERROR) |
712 | break; | 721 | break; |
713 | addr = 0; | 722 | addr = 0; |
714 | } | 723 | } |
@@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void) | |||
902 | { | 911 | { |
903 | unsigned long offset = reloc_offset(); | 912 | unsigned long offset = reloc_offset(); |
904 | struct prom_t *_prom = PTRRELOC(&prom); | 913 | struct prom_t *_prom = PTRRELOC(&prom); |
905 | phandle prom_rtas, rtas_node; | 914 | phandle rtas_node; |
915 | ihandle rtas_inst; | ||
906 | u32 base, entry = 0; | 916 | u32 base, entry = 0; |
907 | u32 size = 0; | 917 | u32 size = 0; |
908 | 918 | ||
909 | prom_debug("prom_instantiate_rtas: start...\n"); | 919 | prom_debug("prom_instantiate_rtas: start...\n"); |
910 | 920 | ||
911 | prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | 921 | rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); |
912 | prom_debug("prom_rtas: %x\n", prom_rtas); | 922 | prom_debug("rtas_node: %x\n", rtas_node); |
913 | if (prom_rtas == (phandle) -1) | 923 | if (!PHANDLE_VALID(rtas_node)) |
914 | return; | 924 | return; |
915 | 925 | ||
916 | prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size)); | 926 | prom_getprop(rtas_node, "rtas-size", &size, sizeof(size)); |
917 | if (size == 0) | 927 | if (size == 0) |
918 | return; | 928 | return; |
919 | 929 | ||
@@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void) | |||
922 | prom_printf("RTAS allocation failed !\n"); | 932 | prom_printf("RTAS allocation failed !\n"); |
923 | return; | 933 | return; |
924 | } | 934 | } |
925 | prom_printf("instantiating rtas at 0x%x", base); | ||
926 | 935 | ||
927 | rtas_node = call_prom("open", 1, 1, ADDR("/rtas")); | 936 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); |
928 | prom_printf("..."); | 937 | if (!IHANDLE_VALID(rtas_inst)) { |
938 | prom_printf("opening rtas package failed"); | ||
939 | return; | ||
940 | } | ||
941 | |||
942 | prom_printf("instantiating rtas at 0x%x ...", base); | ||
929 | 943 | ||
930 | if (call_prom("call-method", 3, 2, | 944 | if (call_prom("call-method", 3, 2, |
931 | ADDR("instantiate-rtas"), | 945 | ADDR("instantiate-rtas"), |
932 | rtas_node, base) != PROM_ERROR) { | 946 | rtas_inst, base) != PROM_ERROR) { |
933 | entry = (long)_prom->args.rets[1]; | 947 | entry = (long)_prom->args.rets[1]; |
934 | } | 948 | } |
935 | if (entry == 0) { | 949 | if (entry == 0) { |
@@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void) | |||
940 | 954 | ||
941 | reserve_mem(base, size); | 955 | reserve_mem(base, size); |
942 | 956 | ||
943 | prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base)); | 957 | prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); |
944 | prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry)); | 958 | prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); |
945 | 959 | ||
946 | prom_debug("rtas base = 0x%x\n", base); | 960 | prom_debug("rtas base = 0x%x\n", base); |
947 | prom_debug("rtas entry = 0x%x\n", entry); | 961 | prom_debug("rtas entry = 0x%x\n", entry); |
@@ -1062,7 +1076,7 @@ static void __init prom_initialize_tce_table(void) | |||
1062 | 1076 | ||
1063 | prom_printf("opening PHB %s", path); | 1077 | prom_printf("opening PHB %s", path); |
1064 | phb_node = call_prom("open", 1, 1, path); | 1078 | phb_node = call_prom("open", 1, 1, path); |
1065 | if ( (long)phb_node <= 0) | 1079 | if (phb_node == 0) |
1066 | prom_printf("... failed\n"); | 1080 | prom_printf("... failed\n"); |
1067 | else | 1081 | else |
1068 | prom_printf("... done\n"); | 1082 | prom_printf("... done\n"); |
@@ -1279,12 +1293,12 @@ static void __init prom_init_client_services(unsigned long pp) | |||
1279 | 1293 | ||
1280 | /* get a handle for the stdout device */ | 1294 | /* get a handle for the stdout device */ |
1281 | _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); | 1295 | _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); |
1282 | if ((long)_prom->chosen <= 0) | 1296 | if (!PHANDLE_VALID(_prom->chosen)) |
1283 | prom_panic("cannot find chosen"); /* msg won't be printed :( */ | 1297 | prom_panic("cannot find chosen"); /* msg won't be printed :( */ |
1284 | 1298 | ||
1285 | /* get device tree root */ | 1299 | /* get device tree root */ |
1286 | _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); | 1300 | _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); |
1287 | if ((long)_prom->root <= 0) | 1301 | if (!PHANDLE_VALID(_prom->root)) |
1288 | prom_panic("cannot find device tree root"); /* msg won't be printed :( */ | 1302 | prom_panic("cannot find device tree root"); /* msg won't be printed :( */ |
1289 | } | 1303 | } |
1290 | 1304 | ||
@@ -1356,9 +1370,8 @@ static int __init prom_find_machine_type(void) | |||
1356 | } | 1370 | } |
1357 | /* Default to pSeries. We need to know if we are running LPAR */ | 1371 | /* Default to pSeries. We need to know if we are running LPAR */ |
1358 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | 1372 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); |
1359 | if (rtas != (phandle) -1) { | 1373 | if (PHANDLE_VALID(rtas)) { |
1360 | unsigned long x; | 1374 | int x = prom_getproplen(rtas, "ibm,hypertas-functions"); |
1361 | x = prom_getproplen(rtas, "ibm,hypertas-functions"); | ||
1362 | if (x != PROM_ERROR) { | 1375 | if (x != PROM_ERROR) { |
1363 | prom_printf("Hypertas detected, assuming LPAR !\n"); | 1376 | prom_printf("Hypertas detected, assuming LPAR !\n"); |
1364 | return PLATFORM_PSERIES_LPAR; | 1377 | return PLATFORM_PSERIES_LPAR; |
@@ -1426,12 +1439,13 @@ static void __init prom_check_displays(void) | |||
1426 | * leave some room at the end of the path for appending extra | 1439 | * leave some room at the end of the path for appending extra |
1427 | * arguments | 1440 | * arguments |
1428 | */ | 1441 | */ |
1429 | if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0) | 1442 | if (call_prom("package-to-path", 3, 1, node, path, |
1443 | PROM_SCRATCH_SIZE-10) == PROM_ERROR) | ||
1430 | continue; | 1444 | continue; |
1431 | prom_printf("found display : %s, opening ... ", path); | 1445 | prom_printf("found display : %s, opening ... ", path); |
1432 | 1446 | ||
1433 | ih = call_prom("open", 1, 1, path); | 1447 | ih = call_prom("open", 1, 1, path); |
1434 | if (ih == (ihandle)0 || ih == (ihandle)-1) { | 1448 | if (ih == 0) { |
1435 | prom_printf("failed\n"); | 1449 | prom_printf("failed\n"); |
1436 | continue; | 1450 | continue; |
1437 | } | 1451 | } |
@@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str) | |||
1514 | return 0; | 1528 | return 0; |
1515 | } | 1529 | } |
1516 | 1530 | ||
1531 | /* | ||
1532 | * The Open Firmware 1275 specification states properties must be 31 bytes or | ||
1533 | * less, however not all firmwares obey this. Make it 64 bytes to be safe. | ||
1534 | */ | ||
1535 | #define MAX_PROPERTY_NAME 64 | ||
1536 | |||
1517 | static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | 1537 | static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, |
1518 | unsigned long *mem_end) | 1538 | unsigned long *mem_end) |
1519 | { | 1539 | { |
@@ -1527,10 +1547,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | |||
1527 | /* get and store all property names */ | 1547 | /* get and store all property names */ |
1528 | prev_name = RELOC(""); | 1548 | prev_name = RELOC(""); |
1529 | for (;;) { | 1549 | for (;;) { |
1530 | 1550 | int rc; | |
1531 | /* 32 is max len of name including nul. */ | 1551 | |
1532 | namep = make_room(mem_start, mem_end, 32, 1); | 1552 | /* 64 is max len of name including nul. */ |
1533 | if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) { | 1553 | namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); |
1554 | rc = call_prom("nextprop", 3, 1, node, prev_name, namep); | ||
1555 | if (rc != 1) { | ||
1534 | /* No more nodes: unwind alloc */ | 1556 | /* No more nodes: unwind alloc */ |
1535 | *mem_start = (unsigned long)namep; | 1557 | *mem_start = (unsigned long)namep; |
1536 | break; | 1558 | break; |
@@ -1555,18 +1577,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | |||
1555 | } | 1577 | } |
1556 | } | 1578 | } |
1557 | 1579 | ||
1558 | /* | ||
1559 | * The Open Firmware 1275 specification states properties must be 31 bytes or | ||
1560 | * less, however not all firmwares obey this. Make it 64 bytes to be safe. | ||
1561 | */ | ||
1562 | #define MAX_PROPERTY_NAME 64 | ||
1563 | |||
1564 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | 1580 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, |
1565 | unsigned long *mem_end) | 1581 | unsigned long *mem_end) |
1566 | { | 1582 | { |
1567 | int l, align; | 1583 | int l, align; |
1568 | phandle child; | 1584 | phandle child; |
1569 | char *namep, *prev_name, *sstart; | 1585 | char *namep, *prev_name, *sstart, *p, *ep; |
1570 | unsigned long soff; | 1586 | unsigned long soff; |
1571 | unsigned char *valp; | 1587 | unsigned char *valp; |
1572 | unsigned long offset = reloc_offset(); | 1588 | unsigned long offset = reloc_offset(); |
@@ -1588,6 +1604,14 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
1588 | call_prom("package-to-path", 3, 1, node, namep, l); | 1604 | call_prom("package-to-path", 3, 1, node, namep, l); |
1589 | } | 1605 | } |
1590 | namep[l] = '\0'; | 1606 | namep[l] = '\0'; |
1607 | /* Fixup an Apple bug where they have bogus \0 chars in the | ||
1608 | * middle of the path in some properties | ||
1609 | */ | ||
1610 | for (p = namep, ep = namep + l; p < ep; p++) | ||
1611 | if (*p == '\0') { | ||
1612 | memmove(p, p+1, ep - p); | ||
1613 | ep--; l--; | ||
1614 | } | ||
1591 | *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); | 1615 | *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); |
1592 | } | 1616 | } |
1593 | 1617 | ||
@@ -1599,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
1599 | prev_name = RELOC(""); | 1623 | prev_name = RELOC(""); |
1600 | sstart = (char *)RELOC(dt_string_start); | 1624 | sstart = (char *)RELOC(dt_string_start); |
1601 | for (;;) { | 1625 | for (;;) { |
1602 | if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0) | 1626 | int rc; |
1627 | |||
1628 | rc = call_prom("nextprop", 3, 1, node, prev_name, pname); | ||
1629 | if (rc != 1) | ||
1603 | break; | 1630 | break; |
1604 | 1631 | ||
1605 | /* find string offset */ | 1632 | /* find string offset */ |
@@ -1615,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
1615 | l = call_prom("getproplen", 2, 1, node, pname); | 1642 | l = call_prom("getproplen", 2, 1, node, pname); |
1616 | 1643 | ||
1617 | /* sanity checks */ | 1644 | /* sanity checks */ |
1618 | if (l < 0) | 1645 | if (l == PROM_ERROR) |
1619 | continue; | 1646 | continue; |
1620 | if (l > MAX_PROPERTY_LENGTH) { | 1647 | if (l > MAX_PROPERTY_LENGTH) { |
1621 | prom_printf("WARNING: ignoring large property "); | 1648 | prom_printf("WARNING: ignoring large property "); |
@@ -1763,17 +1790,18 @@ static void __init fixup_device_tree(void) | |||
1763 | 1790 | ||
1764 | /* Some G5s have a missing interrupt definition, fix it up here */ | 1791 | /* Some G5s have a missing interrupt definition, fix it up here */ |
1765 | u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); | 1792 | u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); |
1766 | if ((long)u3 <= 0) | 1793 | if (!PHANDLE_VALID(u3)) |
1767 | return; | 1794 | return; |
1768 | i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); | 1795 | i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); |
1769 | if ((long)i2c <= 0) | 1796 | if (!PHANDLE_VALID(i2c)) |
1770 | return; | 1797 | return; |
1771 | mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); | 1798 | mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); |
1772 | if ((long)mpic <= 0) | 1799 | if (!PHANDLE_VALID(mpic)) |
1773 | return; | 1800 | return; |
1774 | 1801 | ||
1775 | /* check if proper rev of u3 */ | 1802 | /* check if proper rev of u3 */ |
1776 | if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0) | 1803 | if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) |
1804 | == PROM_ERROR) | ||
1777 | return; | 1805 | return; |
1778 | if (u3_rev != 0x35) | 1806 | if (u3_rev != 0x35) |
1779 | return; | 1807 | return; |
@@ -1881,6 +1909,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long | |||
1881 | &getprop_rval, sizeof(getprop_rval)); | 1909 | &getprop_rval, sizeof(getprop_rval)); |
1882 | 1910 | ||
1883 | /* | 1911 | /* |
1912 | * On pSeries, inform the firmware about our capabilities | ||
1913 | */ | ||
1914 | if (RELOC(of_platform) & PLATFORM_PSERIES) | ||
1915 | prom_send_capabilities(); | ||
1916 | |||
1917 | /* | ||
1884 | * On pSeries, copy the CPU hold code | 1918 | * On pSeries, copy the CPU hold code |
1885 | */ | 1919 | */ |
1886 | if (RELOC(of_platform) & PLATFORM_PSERIES) | 1920 | if (RELOC(of_platform) & PLATFORM_PSERIES) |
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index 21c57f539c29..dce198d39328 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c | |||
@@ -103,11 +103,6 @@ extern void unflatten_device_tree(void); | |||
103 | 103 | ||
104 | extern void smp_release_cpus(void); | 104 | extern void smp_release_cpus(void); |
105 | 105 | ||
106 | unsigned long decr_overclock = 1; | ||
107 | unsigned long decr_overclock_proc0 = 1; | ||
108 | unsigned long decr_overclock_set = 0; | ||
109 | unsigned long decr_overclock_proc0_set = 0; | ||
110 | |||
111 | int have_of = 1; | 106 | int have_of = 1; |
112 | int boot_cpuid = 0; | 107 | int boot_cpuid = 0; |
113 | int boot_cpuid_phys = 0; | 108 | int boot_cpuid_phys = 0; |
@@ -1120,64 +1115,15 @@ void ppc64_dump_msg(unsigned int src, const char *msg) | |||
1120 | printk("[dump]%04x %s\n", src, msg); | 1115 | printk("[dump]%04x %s\n", src, msg); |
1121 | } | 1116 | } |
1122 | 1117 | ||
1123 | int set_spread_lpevents( char * str ) | ||
1124 | { | ||
1125 | /* The parameter is the number of processors to share in processing lp events */ | ||
1126 | unsigned long i; | ||
1127 | unsigned long val = simple_strtoul( str, NULL, 0 ); | ||
1128 | if ( ( val > 0 ) && ( val <= NR_CPUS ) ) { | ||
1129 | for ( i=1; i<val; ++i ) | ||
1130 | paca[i].lpqueue_ptr = paca[0].lpqueue_ptr; | ||
1131 | printk("lpevent processing spread over %ld processors\n", val); | ||
1132 | } | ||
1133 | else | ||
1134 | printk("invalid spreaqd_lpevents %ld\n", val); | ||
1135 | return 1; | ||
1136 | } | ||
1137 | |||
1138 | /* This should only be called on processor 0 during calibrate decr */ | 1118 | /* This should only be called on processor 0 during calibrate decr */ |
1139 | void setup_default_decr(void) | 1119 | void setup_default_decr(void) |
1140 | { | 1120 | { |
1141 | struct paca_struct *lpaca = get_paca(); | 1121 | struct paca_struct *lpaca = get_paca(); |
1142 | 1122 | ||
1143 | if ( decr_overclock_set && !decr_overclock_proc0_set ) | 1123 | lpaca->default_decr = tb_ticks_per_jiffy; |
1144 | decr_overclock_proc0 = decr_overclock; | ||
1145 | |||
1146 | lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0; | ||
1147 | lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy; | 1124 | lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy; |
1148 | } | 1125 | } |
1149 | 1126 | ||
1150 | int set_decr_overclock_proc0( char * str ) | ||
1151 | { | ||
1152 | unsigned long val = simple_strtoul( str, NULL, 0 ); | ||
1153 | if ( ( val >= 1 ) && ( val <= 48 ) ) { | ||
1154 | decr_overclock_proc0_set = 1; | ||
1155 | decr_overclock_proc0 = val; | ||
1156 | printk("proc 0 decrementer overclock factor of %ld\n", val); | ||
1157 | } | ||
1158 | else | ||
1159 | printk("invalid proc 0 decrementer overclock factor of %ld\n", val); | ||
1160 | return 1; | ||
1161 | } | ||
1162 | |||
1163 | int set_decr_overclock( char * str ) | ||
1164 | { | ||
1165 | unsigned long val = simple_strtoul( str, NULL, 0 ); | ||
1166 | if ( ( val >= 1 ) && ( val <= 48 ) ) { | ||
1167 | decr_overclock_set = 1; | ||
1168 | decr_overclock = val; | ||
1169 | printk("decrementer overclock factor of %ld\n", val); | ||
1170 | } | ||
1171 | else | ||
1172 | printk("invalid decrementer overclock factor of %ld\n", val); | ||
1173 | return 1; | ||
1174 | |||
1175 | } | ||
1176 | |||
1177 | __setup("spread_lpevents=", set_spread_lpevents ); | ||
1178 | __setup("decr_overclock_proc0=", set_decr_overclock_proc0 ); | ||
1179 | __setup("decr_overclock=", set_decr_overclock ); | ||
1180 | |||
1181 | #ifndef CONFIG_PPC_ISERIES | 1127 | #ifndef CONFIG_PPC_ISERIES |
1182 | /* | 1128 | /* |
1183 | * This function can be used by platforms to "find" legacy serial ports. | 1129 | * This function can be used by platforms to "find" legacy serial ports. |
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c index 3b906cd94037..9ef5d36d6b25 100644 --- a/arch/ppc64/kernel/smp.c +++ b/arch/ppc64/kernel/smp.c | |||
@@ -334,7 +334,6 @@ void smp_call_function_interrupt(void) | |||
334 | } | 334 | } |
335 | } | 335 | } |
336 | 336 | ||
337 | extern unsigned long decr_overclock; | ||
338 | extern struct gettimeofday_struct do_gtod; | 337 | extern struct gettimeofday_struct do_gtod; |
339 | 338 | ||
340 | struct thread_info *current_set[NR_CPUS]; | 339 | struct thread_info *current_set[NR_CPUS]; |
@@ -491,7 +490,7 @@ int __devinit __cpu_up(unsigned int cpu) | |||
491 | if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)) | 490 | if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)) |
492 | return -EINVAL; | 491 | return -EINVAL; |
493 | 492 | ||
494 | paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock; | 493 | paca[cpu].default_decr = tb_ticks_per_jiffy; |
495 | 494 | ||
496 | if (!cpu_has_feature(CPU_FTR_SLB)) { | 495 | if (!cpu_has_feature(CPU_FTR_SLB)) { |
497 | void *tmp; | 496 | void *tmp; |
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c index 0925694c3ce5..c8fa6569b2fd 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/ppc64/kernel/sysfs.c | |||
@@ -113,7 +113,6 @@ void ppc64_enable_pmcs(void) | |||
113 | #ifdef CONFIG_PPC_PSERIES | 113 | #ifdef CONFIG_PPC_PSERIES |
114 | unsigned long set, reset; | 114 | unsigned long set, reset; |
115 | int ret; | 115 | int ret; |
116 | unsigned int ctrl; | ||
117 | #endif /* CONFIG_PPC_PSERIES */ | 116 | #endif /* CONFIG_PPC_PSERIES */ |
118 | 117 | ||
119 | /* Only need to enable them once */ | 118 | /* Only need to enable them once */ |
@@ -167,11 +166,8 @@ void ppc64_enable_pmcs(void) | |||
167 | * On SMT machines we have to set the run latch in the ctrl register | 166 | * On SMT machines we have to set the run latch in the ctrl register |
168 | * in order to make PMC6 spin. | 167 | * in order to make PMC6 spin. |
169 | */ | 168 | */ |
170 | if (cpu_has_feature(CPU_FTR_SMT)) { | 169 | if (cpu_has_feature(CPU_FTR_SMT)) |
171 | ctrl = mfspr(CTRLF); | 170 | ppc64_runlatch_on(); |
172 | ctrl |= RUNLATCH; | ||
173 | mtspr(CTRLT, ctrl); | ||
174 | } | ||
175 | #endif /* CONFIG_PPC_PSERIES */ | 171 | #endif /* CONFIG_PPC_PSERIES */ |
176 | } | 172 | } |
177 | 173 | ||
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 3d54745108c7..33364a7d2cd2 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c | |||
@@ -325,9 +325,7 @@ int timer_interrupt(struct pt_regs * regs) | |||
325 | 325 | ||
326 | irq_enter(); | 326 | irq_enter(); |
327 | 327 | ||
328 | #ifndef CONFIG_PPC_ISERIES | ||
329 | profile_tick(CPU_PROFILING, regs); | 328 | profile_tick(CPU_PROFILING, regs); |
330 | #endif | ||
331 | 329 | ||
332 | lpaca->lppaca.int_dword.fields.decr_int = 0; | 330 | lpaca->lppaca.int_dword.fields.decr_int = 0; |
333 | 331 | ||
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 01ae1964c938..c067435bae45 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c | |||
@@ -28,6 +28,7 @@ | |||
28 | //#include <linux/kernel_stat.h> | 28 | //#include <linux/kernel_stat.h> |
29 | #include <linux/notifier.h> | 29 | #include <linux/notifier.h> |
30 | #include <linux/cpu.h> | 30 | #include <linux/cpu.h> |
31 | #include <linux/workqueue.h> | ||
31 | 32 | ||
32 | #include "appldata.h" | 33 | #include "appldata.h" |
33 | 34 | ||
@@ -133,9 +134,12 @@ static int appldata_interval = APPLDATA_CPU_INTERVAL; | |||
133 | static int appldata_timer_active; | 134 | static int appldata_timer_active; |
134 | 135 | ||
135 | /* | 136 | /* |
136 | * Tasklet | 137 | * Work queue |
137 | */ | 138 | */ |
138 | static struct tasklet_struct appldata_tasklet_struct; | 139 | static struct workqueue_struct *appldata_wq; |
140 | static void appldata_work_fn(void *data); | ||
141 | static DECLARE_WORK(appldata_work, appldata_work_fn, NULL); | ||
142 | |||
139 | 143 | ||
140 | /* | 144 | /* |
141 | * Ops list | 145 | * Ops list |
@@ -144,11 +148,11 @@ static DEFINE_SPINLOCK(appldata_ops_lock); | |||
144 | static LIST_HEAD(appldata_ops_list); | 148 | static LIST_HEAD(appldata_ops_list); |
145 | 149 | ||
146 | 150 | ||
147 | /************************* timer, tasklet, DIAG ******************************/ | 151 | /*************************** timer, work, DIAG *******************************/ |
148 | /* | 152 | /* |
149 | * appldata_timer_function() | 153 | * appldata_timer_function() |
150 | * | 154 | * |
151 | * schedule tasklet and reschedule timer | 155 | * schedule work and reschedule timer |
152 | */ | 156 | */ |
153 | static void appldata_timer_function(unsigned long data, struct pt_regs *regs) | 157 | static void appldata_timer_function(unsigned long data, struct pt_regs *regs) |
154 | { | 158 | { |
@@ -157,22 +161,22 @@ static void appldata_timer_function(unsigned long data, struct pt_regs *regs) | |||
157 | atomic_read(&appldata_expire_count)); | 161 | atomic_read(&appldata_expire_count)); |
158 | if (atomic_dec_and_test(&appldata_expire_count)) { | 162 | if (atomic_dec_and_test(&appldata_expire_count)) { |
159 | atomic_set(&appldata_expire_count, num_online_cpus()); | 163 | atomic_set(&appldata_expire_count, num_online_cpus()); |
160 | tasklet_schedule((struct tasklet_struct *) data); | 164 | queue_work(appldata_wq, (struct work_struct *) data); |
161 | } | 165 | } |
162 | } | 166 | } |
163 | 167 | ||
164 | /* | 168 | /* |
165 | * appldata_tasklet_function() | 169 | * appldata_work_fn() |
166 | * | 170 | * |
167 | * call data gathering function for each (active) module | 171 | * call data gathering function for each (active) module |
168 | */ | 172 | */ |
169 | static void appldata_tasklet_function(unsigned long data) | 173 | static void appldata_work_fn(void *data) |
170 | { | 174 | { |
171 | struct list_head *lh; | 175 | struct list_head *lh; |
172 | struct appldata_ops *ops; | 176 | struct appldata_ops *ops; |
173 | int i; | 177 | int i; |
174 | 178 | ||
175 | P_DEBUG(" -= Tasklet =-\n"); | 179 | P_DEBUG(" -= Work Queue =-\n"); |
176 | i = 0; | 180 | i = 0; |
177 | spin_lock(&appldata_ops_lock); | 181 | spin_lock(&appldata_ops_lock); |
178 | list_for_each(lh, &appldata_ops_list) { | 182 | list_for_each(lh, &appldata_ops_list) { |
@@ -231,7 +235,7 @@ static int appldata_diag(char record_nr, u16 function, unsigned long buffer, | |||
231 | : "=d" (ry) : "d" (&(appldata_parameter_list)) : "cc"); | 235 | : "=d" (ry) : "d" (&(appldata_parameter_list)) : "cc"); |
232 | return (int) ry; | 236 | return (int) ry; |
233 | } | 237 | } |
234 | /********************** timer, tasklet, DIAG <END> ***************************/ | 238 | /************************ timer, work, DIAG <END> ****************************/ |
235 | 239 | ||
236 | 240 | ||
237 | /****************************** /proc stuff **********************************/ | 241 | /****************************** /proc stuff **********************************/ |
@@ -411,7 +415,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, | |||
411 | struct list_head *lh; | 415 | struct list_head *lh; |
412 | 416 | ||
413 | found = 0; | 417 | found = 0; |
414 | spin_lock_bh(&appldata_ops_lock); | 418 | spin_lock(&appldata_ops_lock); |
415 | list_for_each(lh, &appldata_ops_list) { | 419 | list_for_each(lh, &appldata_ops_list) { |
416 | tmp_ops = list_entry(lh, struct appldata_ops, list); | 420 | tmp_ops = list_entry(lh, struct appldata_ops, list); |
417 | if (&tmp_ops->ctl_table[2] == ctl) { | 421 | if (&tmp_ops->ctl_table[2] == ctl) { |
@@ -419,15 +423,15 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, | |||
419 | } | 423 | } |
420 | } | 424 | } |
421 | if (!found) { | 425 | if (!found) { |
422 | spin_unlock_bh(&appldata_ops_lock); | 426 | spin_unlock(&appldata_ops_lock); |
423 | return -ENODEV; | 427 | return -ENODEV; |
424 | } | 428 | } |
425 | ops = ctl->data; | 429 | ops = ctl->data; |
426 | if (!try_module_get(ops->owner)) { // protect this function | 430 | if (!try_module_get(ops->owner)) { // protect this function |
427 | spin_unlock_bh(&appldata_ops_lock); | 431 | spin_unlock(&appldata_ops_lock); |
428 | return -ENODEV; | 432 | return -ENODEV; |
429 | } | 433 | } |
430 | spin_unlock_bh(&appldata_ops_lock); | 434 | spin_unlock(&appldata_ops_lock); |
431 | 435 | ||
432 | if (!*lenp || *ppos) { | 436 | if (!*lenp || *ppos) { |
433 | *lenp = 0; | 437 | *lenp = 0; |
@@ -451,10 +455,11 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, | |||
451 | return -EFAULT; | 455 | return -EFAULT; |
452 | } | 456 | } |
453 | 457 | ||
454 | spin_lock_bh(&appldata_ops_lock); | 458 | spin_lock(&appldata_ops_lock); |
455 | if ((buf[0] == '1') && (ops->active == 0)) { | 459 | if ((buf[0] == '1') && (ops->active == 0)) { |
456 | if (!try_module_get(ops->owner)) { // protect tasklet | 460 | // protect work queue callback |
457 | spin_unlock_bh(&appldata_ops_lock); | 461 | if (!try_module_get(ops->owner)) { |
462 | spin_unlock(&appldata_ops_lock); | ||
458 | module_put(ops->owner); | 463 | module_put(ops->owner); |
459 | return -ENODEV; | 464 | return -ENODEV; |
460 | } | 465 | } |
@@ -485,7 +490,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, | |||
485 | } | 490 | } |
486 | module_put(ops->owner); | 491 | module_put(ops->owner); |
487 | } | 492 | } |
488 | spin_unlock_bh(&appldata_ops_lock); | 493 | spin_unlock(&appldata_ops_lock); |
489 | out: | 494 | out: |
490 | *lenp = len; | 495 | *lenp = len; |
491 | *ppos += len; | 496 | *ppos += len; |
@@ -529,7 +534,7 @@ int appldata_register_ops(struct appldata_ops *ops) | |||
529 | } | 534 | } |
530 | memset(ops->ctl_table, 0, 4*sizeof(struct ctl_table)); | 535 | memset(ops->ctl_table, 0, 4*sizeof(struct ctl_table)); |
531 | 536 | ||
532 | spin_lock_bh(&appldata_ops_lock); | 537 | spin_lock(&appldata_ops_lock); |
533 | list_for_each(lh, &appldata_ops_list) { | 538 | list_for_each(lh, &appldata_ops_list) { |
534 | tmp_ops = list_entry(lh, struct appldata_ops, list); | 539 | tmp_ops = list_entry(lh, struct appldata_ops, list); |
535 | P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n", | 540 | P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n", |
@@ -541,18 +546,18 @@ int appldata_register_ops(struct appldata_ops *ops) | |||
541 | APPLDATA_PROC_NAME_LENGTH) == 0) { | 546 | APPLDATA_PROC_NAME_LENGTH) == 0) { |
542 | P_ERROR("Name \"%s\" already registered!\n", ops->name); | 547 | P_ERROR("Name \"%s\" already registered!\n", ops->name); |
543 | kfree(ops->ctl_table); | 548 | kfree(ops->ctl_table); |
544 | spin_unlock_bh(&appldata_ops_lock); | 549 | spin_unlock(&appldata_ops_lock); |
545 | return -EBUSY; | 550 | return -EBUSY; |
546 | } | 551 | } |
547 | if (tmp_ops->ctl_nr == ops->ctl_nr) { | 552 | if (tmp_ops->ctl_nr == ops->ctl_nr) { |
548 | P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr); | 553 | P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr); |
549 | kfree(ops->ctl_table); | 554 | kfree(ops->ctl_table); |
550 | spin_unlock_bh(&appldata_ops_lock); | 555 | spin_unlock(&appldata_ops_lock); |
551 | return -EBUSY; | 556 | return -EBUSY; |
552 | } | 557 | } |
553 | } | 558 | } |
554 | list_add(&ops->list, &appldata_ops_list); | 559 | list_add(&ops->list, &appldata_ops_list); |
555 | spin_unlock_bh(&appldata_ops_lock); | 560 | spin_unlock(&appldata_ops_lock); |
556 | 561 | ||
557 | ops->ctl_table[0].ctl_name = CTL_APPLDATA; | 562 | ops->ctl_table[0].ctl_name = CTL_APPLDATA; |
558 | ops->ctl_table[0].procname = appldata_proc_name; | 563 | ops->ctl_table[0].procname = appldata_proc_name; |
@@ -583,12 +588,12 @@ int appldata_register_ops(struct appldata_ops *ops) | |||
583 | */ | 588 | */ |
584 | void appldata_unregister_ops(struct appldata_ops *ops) | 589 | void appldata_unregister_ops(struct appldata_ops *ops) |
585 | { | 590 | { |
586 | spin_lock_bh(&appldata_ops_lock); | 591 | spin_lock(&appldata_ops_lock); |
587 | unregister_sysctl_table(ops->sysctl_header); | 592 | unregister_sysctl_table(ops->sysctl_header); |
588 | list_del(&ops->list); | 593 | list_del(&ops->list); |
589 | kfree(ops->ctl_table); | 594 | kfree(ops->ctl_table); |
590 | ops->ctl_table = NULL; | 595 | ops->ctl_table = NULL; |
591 | spin_unlock_bh(&appldata_ops_lock); | 596 | spin_unlock(&appldata_ops_lock); |
592 | P_INFO("%s-ops unregistered!\n", ops->name); | 597 | P_INFO("%s-ops unregistered!\n", ops->name); |
593 | } | 598 | } |
594 | /********************** module-ops management <END> **************************/ | 599 | /********************** module-ops management <END> **************************/ |
@@ -602,7 +607,7 @@ appldata_online_cpu(int cpu) | |||
602 | init_virt_timer(&per_cpu(appldata_timer, cpu)); | 607 | init_virt_timer(&per_cpu(appldata_timer, cpu)); |
603 | per_cpu(appldata_timer, cpu).function = appldata_timer_function; | 608 | per_cpu(appldata_timer, cpu).function = appldata_timer_function; |
604 | per_cpu(appldata_timer, cpu).data = (unsigned long) | 609 | per_cpu(appldata_timer, cpu).data = (unsigned long) |
605 | &appldata_tasklet_struct; | 610 | &appldata_work; |
606 | atomic_inc(&appldata_expire_count); | 611 | atomic_inc(&appldata_expire_count); |
607 | spin_lock(&appldata_timer_lock); | 612 | spin_lock(&appldata_timer_lock); |
608 | __appldata_vtimer_setup(APPLDATA_MOD_TIMER); | 613 | __appldata_vtimer_setup(APPLDATA_MOD_TIMER); |
@@ -615,7 +620,7 @@ appldata_offline_cpu(int cpu) | |||
615 | del_virt_timer(&per_cpu(appldata_timer, cpu)); | 620 | del_virt_timer(&per_cpu(appldata_timer, cpu)); |
616 | if (atomic_dec_and_test(&appldata_expire_count)) { | 621 | if (atomic_dec_and_test(&appldata_expire_count)) { |
617 | atomic_set(&appldata_expire_count, num_online_cpus()); | 622 | atomic_set(&appldata_expire_count, num_online_cpus()); |
618 | tasklet_schedule(&appldata_tasklet_struct); | 623 | queue_work(appldata_wq, &appldata_work); |
619 | } | 624 | } |
620 | spin_lock(&appldata_timer_lock); | 625 | spin_lock(&appldata_timer_lock); |
621 | __appldata_vtimer_setup(APPLDATA_MOD_TIMER); | 626 | __appldata_vtimer_setup(APPLDATA_MOD_TIMER); |
@@ -648,7 +653,7 @@ static struct notifier_block __devinitdata appldata_nb = { | |||
648 | /* | 653 | /* |
649 | * appldata_init() | 654 | * appldata_init() |
650 | * | 655 | * |
651 | * init timer and tasklet, register /proc entries | 656 | * init timer, register /proc entries |
652 | */ | 657 | */ |
653 | static int __init appldata_init(void) | 658 | static int __init appldata_init(void) |
654 | { | 659 | { |
@@ -657,6 +662,12 @@ static int __init appldata_init(void) | |||
657 | P_DEBUG("sizeof(parameter_list) = %lu\n", | 662 | P_DEBUG("sizeof(parameter_list) = %lu\n", |
658 | sizeof(struct appldata_parameter_list)); | 663 | sizeof(struct appldata_parameter_list)); |
659 | 664 | ||
665 | appldata_wq = create_singlethread_workqueue("appldata"); | ||
666 | if (!appldata_wq) { | ||
667 | P_ERROR("Could not create work queue\n"); | ||
668 | return -ENOMEM; | ||
669 | } | ||
670 | |||
660 | for_each_online_cpu(i) | 671 | for_each_online_cpu(i) |
661 | appldata_online_cpu(i); | 672 | appldata_online_cpu(i); |
662 | 673 | ||
@@ -670,7 +681,6 @@ static int __init appldata_init(void) | |||
670 | appldata_table[1].de->owner = THIS_MODULE; | 681 | appldata_table[1].de->owner = THIS_MODULE; |
671 | #endif | 682 | #endif |
672 | 683 | ||
673 | tasklet_init(&appldata_tasklet_struct, appldata_tasklet_function, 0); | ||
674 | P_DEBUG("Base interface initialized.\n"); | 684 | P_DEBUG("Base interface initialized.\n"); |
675 | return 0; | 685 | return 0; |
676 | } | 686 | } |
@@ -678,7 +688,7 @@ static int __init appldata_init(void) | |||
678 | /* | 688 | /* |
679 | * appldata_exit() | 689 | * appldata_exit() |
680 | * | 690 | * |
681 | * stop timer and tasklet, unregister /proc entries | 691 | * stop timer, unregister /proc entries |
682 | */ | 692 | */ |
683 | static void __exit appldata_exit(void) | 693 | static void __exit appldata_exit(void) |
684 | { | 694 | { |
@@ -690,7 +700,7 @@ static void __exit appldata_exit(void) | |||
690 | /* | 700 | /* |
691 | * ops list should be empty, but just in case something went wrong... | 701 | * ops list should be empty, but just in case something went wrong... |
692 | */ | 702 | */ |
693 | spin_lock_bh(&appldata_ops_lock); | 703 | spin_lock(&appldata_ops_lock); |
694 | list_for_each(lh, &appldata_ops_list) { | 704 | list_for_each(lh, &appldata_ops_list) { |
695 | ops = list_entry(lh, struct appldata_ops, list); | 705 | ops = list_entry(lh, struct appldata_ops, list); |
696 | rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, | 706 | rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, |
@@ -700,7 +710,7 @@ static void __exit appldata_exit(void) | |||
700 | "return code: %d\n", ops->name, rc); | 710 | "return code: %d\n", ops->name, rc); |
701 | } | 711 | } |
702 | } | 712 | } |
703 | spin_unlock_bh(&appldata_ops_lock); | 713 | spin_unlock(&appldata_ops_lock); |
704 | 714 | ||
705 | for_each_online_cpu(i) | 715 | for_each_online_cpu(i) |
706 | appldata_offline_cpu(i); | 716 | appldata_offline_cpu(i); |
@@ -709,7 +719,7 @@ static void __exit appldata_exit(void) | |||
709 | 719 | ||
710 | unregister_sysctl_table(appldata_sysctl_header); | 720 | unregister_sysctl_table(appldata_sysctl_header); |
711 | 721 | ||
712 | tasklet_kill(&appldata_tasklet_struct); | 722 | destroy_workqueue(appldata_wq); |
713 | P_DEBUG("... module unloaded!\n"); | 723 | P_DEBUG("... module unloaded!\n"); |
714 | } | 724 | } |
715 | /**************************** init / exit <END> ******************************/ | 725 | /**************************** init / exit <END> ******************************/ |
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c index 462ee9a84e76..f0e2fbed3d4c 100644 --- a/arch/s390/appldata/appldata_mem.c +++ b/arch/s390/appldata/appldata_mem.c | |||
@@ -68,7 +68,7 @@ struct appldata_mem_data { | |||
68 | u64 pgmajfault; /* page faults (major only) */ | 68 | u64 pgmajfault; /* page faults (major only) */ |
69 | // <-- New in 2.6 | 69 | // <-- New in 2.6 |
70 | 70 | ||
71 | } appldata_mem_data; | 71 | } __attribute__((packed)) appldata_mem_data; |
72 | 72 | ||
73 | 73 | ||
74 | static inline void appldata_debug_print(struct appldata_mem_data *mem_data) | 74 | static inline void appldata_debug_print(struct appldata_mem_data *mem_data) |
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c index dd61638d3027..2a4c7432db4a 100644 --- a/arch/s390/appldata/appldata_net_sum.c +++ b/arch/s390/appldata/appldata_net_sum.c | |||
@@ -57,7 +57,7 @@ struct appldata_net_sum_data { | |||
57 | u64 rx_dropped; /* no space in linux buffers */ | 57 | u64 rx_dropped; /* no space in linux buffers */ |
58 | u64 tx_dropped; /* no space available in linux */ | 58 | u64 tx_dropped; /* no space available in linux */ |
59 | u64 collisions; /* collisions while transmitting */ | 59 | u64 collisions; /* collisions while transmitting */ |
60 | } appldata_net_sum_data; | 60 | } __attribute__((packed)) appldata_net_sum_data; |
61 | 61 | ||
62 | 62 | ||
63 | static inline void appldata_print_debug(struct appldata_net_sum_data *net_data) | 63 | static inline void appldata_print_debug(struct appldata_net_sum_data *net_data) |
diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index b83f07484551..e0a476bf4fd6 100644 --- a/arch/s390/appldata/appldata_os.c +++ b/arch/s390/appldata/appldata_os.c | |||
@@ -49,7 +49,7 @@ struct appldata_os_per_cpu { | |||
49 | u32 per_cpu_softirq; /* ... spent in softirqs */ | 49 | u32 per_cpu_softirq; /* ... spent in softirqs */ |
50 | u32 per_cpu_iowait; /* ... spent while waiting for I/O */ | 50 | u32 per_cpu_iowait; /* ... spent while waiting for I/O */ |
51 | // <-- New in 2.6 | 51 | // <-- New in 2.6 |
52 | }; | 52 | } __attribute__((packed)); |
53 | 53 | ||
54 | struct appldata_os_data { | 54 | struct appldata_os_data { |
55 | u64 timestamp; | 55 | u64 timestamp; |
@@ -75,7 +75,7 @@ struct appldata_os_data { | |||
75 | 75 | ||
76 | /* per cpu data */ | 76 | /* per cpu data */ |
77 | struct appldata_os_per_cpu os_cpu[0]; | 77 | struct appldata_os_per_cpu os_cpu[0]; |
78 | }; | 78 | } __attribute__((packed)); |
79 | 79 | ||
80 | static struct appldata_os_data *appldata_os_data; | 80 | static struct appldata_os_data *appldata_os_data; |
81 | 81 | ||
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 26889366929a..06afa3103ace 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/pgalloc.h> | 40 | #include <asm/pgalloc.h> |
41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
43 | #include <asm/unistd.h> | ||
43 | 44 | ||
44 | #ifdef CONFIG_S390_SUPPORT | 45 | #ifdef CONFIG_S390_SUPPORT |
45 | #include "compat_ptrace.h" | 46 | #include "compat_ptrace.h" |
@@ -130,13 +131,19 @@ static int | |||
130 | peek_user(struct task_struct *child, addr_t addr, addr_t data) | 131 | peek_user(struct task_struct *child, addr_t addr, addr_t data) |
131 | { | 132 | { |
132 | struct user *dummy = NULL; | 133 | struct user *dummy = NULL; |
133 | addr_t offset, tmp; | 134 | addr_t offset, tmp, mask; |
134 | 135 | ||
135 | /* | 136 | /* |
136 | * Stupid gdb peeks/pokes the access registers in 64 bit with | 137 | * Stupid gdb peeks/pokes the access registers in 64 bit with |
137 | * an alignment of 4. Programmers from hell... | 138 | * an alignment of 4. Programmers from hell... |
138 | */ | 139 | */ |
139 | if ((addr & 3) || addr > sizeof(struct user) - __ADDR_MASK) | 140 | mask = __ADDR_MASK; |
141 | #ifdef CONFIG_ARCH_S390X | ||
142 | if (addr >= (addr_t) &dummy->regs.acrs && | ||
143 | addr < (addr_t) &dummy->regs.orig_gpr2) | ||
144 | mask = 3; | ||
145 | #endif | ||
146 | if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK) | ||
140 | return -EIO; | 147 | return -EIO; |
141 | 148 | ||
142 | if (addr < (addr_t) &dummy->regs.acrs) { | 149 | if (addr < (addr_t) &dummy->regs.acrs) { |
@@ -153,6 +160,16 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) | |||
153 | * access registers are stored in the thread structure | 160 | * access registers are stored in the thread structure |
154 | */ | 161 | */ |
155 | offset = addr - (addr_t) &dummy->regs.acrs; | 162 | offset = addr - (addr_t) &dummy->regs.acrs; |
163 | #ifdef CONFIG_ARCH_S390X | ||
164 | /* | ||
165 | * Very special case: old & broken 64 bit gdb reading | ||
166 | * from acrs[15]. Result is a 64 bit value. Read the | ||
167 | * 32 bit acrs[15] value and shift it by 32. Sick... | ||
168 | */ | ||
169 | if (addr == (addr_t) &dummy->regs.acrs[15]) | ||
170 | tmp = ((unsigned long) child->thread.acrs[15]) << 32; | ||
171 | else | ||
172 | #endif | ||
156 | tmp = *(addr_t *)((addr_t) &child->thread.acrs + offset); | 173 | tmp = *(addr_t *)((addr_t) &child->thread.acrs + offset); |
157 | 174 | ||
158 | } else if (addr == (addr_t) &dummy->regs.orig_gpr2) { | 175 | } else if (addr == (addr_t) &dummy->regs.orig_gpr2) { |
@@ -167,6 +184,9 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) | |||
167 | */ | 184 | */ |
168 | offset = addr - (addr_t) &dummy->regs.fp_regs; | 185 | offset = addr - (addr_t) &dummy->regs.fp_regs; |
169 | tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset); | 186 | tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset); |
187 | if (addr == (addr_t) &dummy->regs.fp_regs.fpc) | ||
188 | tmp &= (unsigned long) FPC_VALID_MASK | ||
189 | << (BITS_PER_LONG - 32); | ||
170 | 190 | ||
171 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { | 191 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { |
172 | /* | 192 | /* |
@@ -191,13 +211,19 @@ static int | |||
191 | poke_user(struct task_struct *child, addr_t addr, addr_t data) | 211 | poke_user(struct task_struct *child, addr_t addr, addr_t data) |
192 | { | 212 | { |
193 | struct user *dummy = NULL; | 213 | struct user *dummy = NULL; |
194 | addr_t offset; | 214 | addr_t offset, mask; |
195 | 215 | ||
196 | /* | 216 | /* |
197 | * Stupid gdb peeks/pokes the access registers in 64 bit with | 217 | * Stupid gdb peeks/pokes the access registers in 64 bit with |
198 | * an alignment of 4. Programmers from hell indeed... | 218 | * an alignment of 4. Programmers from hell indeed... |
199 | */ | 219 | */ |
200 | if ((addr & 3) || addr > sizeof(struct user) - __ADDR_MASK) | 220 | mask = __ADDR_MASK; |
221 | #ifdef CONFIG_ARCH_S390X | ||
222 | if (addr >= (addr_t) &dummy->regs.acrs && | ||
223 | addr < (addr_t) &dummy->regs.orig_gpr2) | ||
224 | mask = 3; | ||
225 | #endif | ||
226 | if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK) | ||
201 | return -EIO; | 227 | return -EIO; |
202 | 228 | ||
203 | if (addr < (addr_t) &dummy->regs.acrs) { | 229 | if (addr < (addr_t) &dummy->regs.acrs) { |
@@ -224,6 +250,17 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) | |||
224 | * access registers are stored in the thread structure | 250 | * access registers are stored in the thread structure |
225 | */ | 251 | */ |
226 | offset = addr - (addr_t) &dummy->regs.acrs; | 252 | offset = addr - (addr_t) &dummy->regs.acrs; |
253 | #ifdef CONFIG_ARCH_S390X | ||
254 | /* | ||
255 | * Very special case: old & broken 64 bit gdb writing | ||
256 | * to acrs[15] with a 64 bit value. Ignore the lower | ||
257 | * half of the value and write the upper 32 bit to | ||
258 | * acrs[15]. Sick... | ||
259 | */ | ||
260 | if (addr == (addr_t) &dummy->regs.acrs[15]) | ||
261 | child->thread.acrs[15] = (unsigned int) (data >> 32); | ||
262 | else | ||
263 | #endif | ||
227 | *(addr_t *)((addr_t) &child->thread.acrs + offset) = data; | 264 | *(addr_t *)((addr_t) &child->thread.acrs + offset) = data; |
228 | 265 | ||
229 | } else if (addr == (addr_t) &dummy->regs.orig_gpr2) { | 266 | } else if (addr == (addr_t) &dummy->regs.orig_gpr2) { |
@@ -237,7 +274,8 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) | |||
237 | * floating point regs. are stored in the thread structure | 274 | * floating point regs. are stored in the thread structure |
238 | */ | 275 | */ |
239 | if (addr == (addr_t) &dummy->regs.fp_regs.fpc && | 276 | if (addr == (addr_t) &dummy->regs.fp_regs.fpc && |
240 | (data & ~FPC_VALID_MASK) != 0) | 277 | (data & ~((unsigned long) FPC_VALID_MASK |
278 | << (BITS_PER_LONG - 32))) != 0) | ||
241 | return -EINVAL; | 279 | return -EINVAL; |
242 | offset = addr - (addr_t) &dummy->regs.fp_regs; | 280 | offset = addr - (addr_t) &dummy->regs.fp_regs; |
243 | *(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data; | 281 | *(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data; |
@@ -723,6 +761,13 @@ syscall_trace(struct pt_regs *regs, int entryexit) | |||
723 | ? 0x80 : 0)); | 761 | ? 0x80 : 0)); |
724 | 762 | ||
725 | /* | 763 | /* |
764 | * If the debuffer has set an invalid system call number, | ||
765 | * we prepare to skip the system call restart handling. | ||
766 | */ | ||
767 | if (!entryexit && regs->gprs[2] >= NR_syscalls) | ||
768 | regs->trap = -1; | ||
769 | |||
770 | /* | ||
726 | * this isn't the same as continuing with a signal, but it will do | 771 | * this isn't the same as continuing with a signal, but it will do |
727 | * for normal use. strace only continues with a signal if the | 772 | * for normal use. strace only continues with a signal if the |
728 | * stopping signal is not SIGTRAP. -brl | 773 | * stopping signal is not SIGTRAP. -brl |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 80306bc8c799..75fde949d125 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -207,7 +207,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) | |||
207 | * we are not in an interrupt and that there is a | 207 | * we are not in an interrupt and that there is a |
208 | * user context. | 208 | * user context. |
209 | */ | 209 | */ |
210 | if (user_address == 0 || in_interrupt() || !mm) | 210 | if (user_address == 0 || in_atomic() || !mm) |
211 | goto no_context; | 211 | goto no_context; |
212 | 212 | ||
213 | /* | 213 | /* |
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 33ca56c90da2..2803bc7c2c79 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c | |||
@@ -196,6 +196,34 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long | |||
196 | return NULL; | 196 | return NULL; |
197 | } | 197 | } |
198 | 198 | ||
199 | static int iommu_alloc_ctx(struct pci_iommu *iommu) | ||
200 | { | ||
201 | int lowest = iommu->ctx_lowest_free; | ||
202 | int sz = IOMMU_NUM_CTXS - lowest; | ||
203 | int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest); | ||
204 | |||
205 | if (unlikely(n == sz)) { | ||
206 | n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1); | ||
207 | if (unlikely(n == lowest)) { | ||
208 | printk(KERN_WARNING "IOMMU: Ran out of contexts.\n"); | ||
209 | n = 0; | ||
210 | } | ||
211 | } | ||
212 | if (n) | ||
213 | __set_bit(n, iommu->ctx_bitmap); | ||
214 | |||
215 | return n; | ||
216 | } | ||
217 | |||
218 | static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) | ||
219 | { | ||
220 | if (likely(ctx)) { | ||
221 | __clear_bit(ctx, iommu->ctx_bitmap); | ||
222 | if (ctx < iommu->ctx_lowest_free) | ||
223 | iommu->ctx_lowest_free = ctx; | ||
224 | } | ||
225 | } | ||
226 | |||
199 | /* Allocate and map kernel buffer of size SIZE using consistent mode | 227 | /* Allocate and map kernel buffer of size SIZE using consistent mode |
200 | * DMA for PCI device PDEV. Return non-NULL cpu-side address if | 228 | * DMA for PCI device PDEV. Return non-NULL cpu-side address if |
201 | * successful and set *DMA_ADDRP to the PCI side dma address. | 229 | * successful and set *DMA_ADDRP to the PCI side dma address. |
@@ -236,7 +264,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad | |||
236 | npages = size >> IO_PAGE_SHIFT; | 264 | npages = size >> IO_PAGE_SHIFT; |
237 | ctx = 0; | 265 | ctx = 0; |
238 | if (iommu->iommu_ctxflush) | 266 | if (iommu->iommu_ctxflush) |
239 | ctx = iommu->iommu_cur_ctx++; | 267 | ctx = iommu_alloc_ctx(iommu); |
240 | first_page = __pa(first_page); | 268 | first_page = __pa(first_page); |
241 | while (npages--) { | 269 | while (npages--) { |
242 | iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) | | 270 | iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) | |
@@ -317,6 +345,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ | |||
317 | } | 345 | } |
318 | } | 346 | } |
319 | 347 | ||
348 | iommu_free_ctx(iommu, ctx); | ||
349 | |||
320 | spin_unlock_irqrestore(&iommu->lock, flags); | 350 | spin_unlock_irqrestore(&iommu->lock, flags); |
321 | 351 | ||
322 | order = get_order(size); | 352 | order = get_order(size); |
@@ -360,7 +390,7 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct | |||
360 | base_paddr = __pa(oaddr & IO_PAGE_MASK); | 390 | base_paddr = __pa(oaddr & IO_PAGE_MASK); |
361 | ctx = 0; | 391 | ctx = 0; |
362 | if (iommu->iommu_ctxflush) | 392 | if (iommu->iommu_ctxflush) |
363 | ctx = iommu->iommu_cur_ctx++; | 393 | ctx = iommu_alloc_ctx(iommu); |
364 | if (strbuf->strbuf_enabled) | 394 | if (strbuf->strbuf_enabled) |
365 | iopte_protection = IOPTE_STREAMING(ctx); | 395 | iopte_protection = IOPTE_STREAMING(ctx); |
366 | else | 396 | else |
@@ -380,39 +410,53 @@ bad: | |||
380 | return PCI_DMA_ERROR_CODE; | 410 | return PCI_DMA_ERROR_CODE; |
381 | } | 411 | } |
382 | 412 | ||
383 | static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages) | 413 | static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction) |
384 | { | 414 | { |
385 | int limit; | 415 | int limit; |
386 | 416 | ||
387 | PCI_STC_FLUSHFLAG_INIT(strbuf); | ||
388 | if (strbuf->strbuf_ctxflush && | 417 | if (strbuf->strbuf_ctxflush && |
389 | iommu->iommu_ctxflush) { | 418 | iommu->iommu_ctxflush) { |
390 | unsigned long matchreg, flushreg; | 419 | unsigned long matchreg, flushreg; |
420 | u64 val; | ||
391 | 421 | ||
392 | flushreg = strbuf->strbuf_ctxflush; | 422 | flushreg = strbuf->strbuf_ctxflush; |
393 | matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); | 423 | matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); |
394 | 424 | ||
395 | limit = 100000; | ||
396 | pci_iommu_write(flushreg, ctx); | 425 | pci_iommu_write(flushreg, ctx); |
397 | for(;;) { | 426 | val = pci_iommu_read(matchreg); |
398 | if (((long)pci_iommu_read(matchreg)) >= 0L) | 427 | val &= 0xffff; |
399 | break; | 428 | if (!val) |
400 | limit--; | 429 | goto do_flush_sync; |
401 | if (!limit) | 430 | |
402 | break; | 431 | while (val) { |
403 | udelay(1); | 432 | if (val & 0x1) |
433 | pci_iommu_write(flushreg, ctx); | ||
434 | val >>= 1; | ||
404 | } | 435 | } |
405 | if (!limit) | 436 | val = pci_iommu_read(matchreg); |
437 | if (unlikely(val)) { | ||
406 | printk(KERN_WARNING "pci_strbuf_flush: ctx flush " | 438 | printk(KERN_WARNING "pci_strbuf_flush: ctx flush " |
407 | "timeout vaddr[%08x] ctx[%lx]\n", | 439 | "timeout matchreg[%lx] ctx[%lx]\n", |
408 | vaddr, ctx); | 440 | val, ctx); |
441 | goto do_page_flush; | ||
442 | } | ||
409 | } else { | 443 | } else { |
410 | unsigned long i; | 444 | unsigned long i; |
411 | 445 | ||
446 | do_page_flush: | ||
412 | for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) | 447 | for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) |
413 | pci_iommu_write(strbuf->strbuf_pflush, vaddr); | 448 | pci_iommu_write(strbuf->strbuf_pflush, vaddr); |
414 | } | 449 | } |
415 | 450 | ||
451 | do_flush_sync: | ||
452 | /* If the device could not have possibly put dirty data into | ||
453 | * the streaming cache, no flush-flag synchronization needs | ||
454 | * to be performed. | ||
455 | */ | ||
456 | if (direction == PCI_DMA_TODEVICE) | ||
457 | return; | ||
458 | |||
459 | PCI_STC_FLUSHFLAG_INIT(strbuf); | ||
416 | pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); | 460 | pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); |
417 | (void) pci_iommu_read(iommu->write_complete_reg); | 461 | (void) pci_iommu_read(iommu->write_complete_reg); |
418 | 462 | ||
@@ -466,7 +510,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int | |||
466 | 510 | ||
467 | /* Step 1: Kick data out of streaming buffers if necessary. */ | 511 | /* Step 1: Kick data out of streaming buffers if necessary. */ |
468 | if (strbuf->strbuf_enabled) | 512 | if (strbuf->strbuf_enabled) |
469 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); | 513 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); |
470 | 514 | ||
471 | /* Step 2: Clear out first TSB entry. */ | 515 | /* Step 2: Clear out first TSB entry. */ |
472 | iopte_make_dummy(iommu, base); | 516 | iopte_make_dummy(iommu, base); |
@@ -474,6 +518,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int | |||
474 | free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, | 518 | free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, |
475 | npages, ctx); | 519 | npages, ctx); |
476 | 520 | ||
521 | iommu_free_ctx(iommu, ctx); | ||
522 | |||
477 | spin_unlock_irqrestore(&iommu->lock, flags); | 523 | spin_unlock_irqrestore(&iommu->lock, flags); |
478 | } | 524 | } |
479 | 525 | ||
@@ -613,7 +659,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int | |||
613 | /* Step 4: Choose a context if necessary. */ | 659 | /* Step 4: Choose a context if necessary. */ |
614 | ctx = 0; | 660 | ctx = 0; |
615 | if (iommu->iommu_ctxflush) | 661 | if (iommu->iommu_ctxflush) |
616 | ctx = iommu->iommu_cur_ctx++; | 662 | ctx = iommu_alloc_ctx(iommu); |
617 | 663 | ||
618 | /* Step 5: Create the mappings. */ | 664 | /* Step 5: Create the mappings. */ |
619 | if (strbuf->strbuf_enabled) | 665 | if (strbuf->strbuf_enabled) |
@@ -678,7 +724,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, | |||
678 | 724 | ||
679 | /* Step 1: Kick data out of streaming buffers if necessary. */ | 725 | /* Step 1: Kick data out of streaming buffers if necessary. */ |
680 | if (strbuf->strbuf_enabled) | 726 | if (strbuf->strbuf_enabled) |
681 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); | 727 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); |
682 | 728 | ||
683 | /* Step 2: Clear out first TSB entry. */ | 729 | /* Step 2: Clear out first TSB entry. */ |
684 | iopte_make_dummy(iommu, base); | 730 | iopte_make_dummy(iommu, base); |
@@ -686,6 +732,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, | |||
686 | free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, | 732 | free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, |
687 | npages, ctx); | 733 | npages, ctx); |
688 | 734 | ||
735 | iommu_free_ctx(iommu, ctx); | ||
736 | |||
689 | spin_unlock_irqrestore(&iommu->lock, flags); | 737 | spin_unlock_irqrestore(&iommu->lock, flags); |
690 | } | 738 | } |
691 | 739 | ||
@@ -724,7 +772,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size | |||
724 | } | 772 | } |
725 | 773 | ||
726 | /* Step 2: Kick data out of streaming buffers. */ | 774 | /* Step 2: Kick data out of streaming buffers. */ |
727 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); | 775 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); |
728 | 776 | ||
729 | spin_unlock_irqrestore(&iommu->lock, flags); | 777 | spin_unlock_irqrestore(&iommu->lock, flags); |
730 | } | 778 | } |
@@ -768,7 +816,7 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i | |||
768 | i--; | 816 | i--; |
769 | npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) | 817 | npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) |
770 | - bus_addr) >> IO_PAGE_SHIFT; | 818 | - bus_addr) >> IO_PAGE_SHIFT; |
771 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); | 819 | pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); |
772 | 820 | ||
773 | spin_unlock_irqrestore(&iommu->lock, flags); | 821 | spin_unlock_irqrestore(&iommu->lock, flags); |
774 | } | 822 | } |
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 3567fa879e1f..534320ef0db2 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
@@ -1212,7 +1212,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) | |||
1212 | 1212 | ||
1213 | /* Setup initial software IOMMU state. */ | 1213 | /* Setup initial software IOMMU state. */ |
1214 | spin_lock_init(&iommu->lock); | 1214 | spin_lock_init(&iommu->lock); |
1215 | iommu->iommu_cur_ctx = 0; | 1215 | iommu->ctx_lowest_free = 1; |
1216 | 1216 | ||
1217 | /* Register addresses. */ | 1217 | /* Register addresses. */ |
1218 | iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; | 1218 | iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; |
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 5525d1ec4af8..53d333b4a4e8 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c | |||
@@ -1265,7 +1265,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, | |||
1265 | 1265 | ||
1266 | /* Setup initial software IOMMU state. */ | 1266 | /* Setup initial software IOMMU state. */ |
1267 | spin_lock_init(&iommu->lock); | 1267 | spin_lock_init(&iommu->lock); |
1268 | iommu->iommu_cur_ctx = 0; | 1268 | iommu->ctx_lowest_free = 1; |
1269 | 1269 | ||
1270 | /* Register addresses. */ | 1270 | /* Register addresses. */ |
1271 | iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; | 1271 | iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; |
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index e93fcadc3722..5753175b94e6 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
@@ -1753,7 +1753,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
1753 | 1753 | ||
1754 | /* Setup initial software IOMMU state. */ | 1754 | /* Setup initial software IOMMU state. */ |
1755 | spin_lock_init(&iommu->lock); | 1755 | spin_lock_init(&iommu->lock); |
1756 | iommu->iommu_cur_ctx = 0; | 1756 | iommu->ctx_lowest_free = 1; |
1757 | 1757 | ||
1758 | /* Register addresses, SCHIZO has iommu ctx flushing. */ | 1758 | /* Register addresses, SCHIZO has iommu ctx flushing. */ |
1759 | iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; | 1759 | iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; |
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 76ea6455433f..89f5e019f24c 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c | |||
@@ -117,17 +117,25 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages | |||
117 | 117 | ||
118 | #define STRBUF_TAG_VALID 0x02UL | 118 | #define STRBUF_TAG_VALID 0x02UL |
119 | 119 | ||
120 | static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) | 120 | static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction) |
121 | { | 121 | { |
122 | unsigned long n; | 122 | unsigned long n; |
123 | int limit; | 123 | int limit; |
124 | 124 | ||
125 | iommu->strbuf_flushflag = 0UL; | ||
126 | n = npages; | 125 | n = npages; |
127 | while (n--) | 126 | while (n--) |
128 | upa_writeq(base + (n << IO_PAGE_SHIFT), | 127 | upa_writeq(base + (n << IO_PAGE_SHIFT), |
129 | iommu->strbuf_regs + STRBUF_PFLUSH); | 128 | iommu->strbuf_regs + STRBUF_PFLUSH); |
130 | 129 | ||
130 | /* If the device could not have possibly put dirty data into | ||
131 | * the streaming cache, no flush-flag synchronization needs | ||
132 | * to be performed. | ||
133 | */ | ||
134 | if (direction == SBUS_DMA_TODEVICE) | ||
135 | return; | ||
136 | |||
137 | iommu->strbuf_flushflag = 0UL; | ||
138 | |||
131 | /* Whoopee cushion! */ | 139 | /* Whoopee cushion! */ |
132 | upa_writeq(__pa(&iommu->strbuf_flushflag), | 140 | upa_writeq(__pa(&iommu->strbuf_flushflag), |
133 | iommu->strbuf_regs + STRBUF_FSYNC); | 141 | iommu->strbuf_regs + STRBUF_FSYNC); |
@@ -421,7 +429,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, | |||
421 | 429 | ||
422 | spin_lock_irqsave(&iommu->lock, flags); | 430 | spin_lock_irqsave(&iommu->lock, flags); |
423 | free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); | 431 | free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); |
424 | sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); | 432 | sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT, direction); |
425 | spin_unlock_irqrestore(&iommu->lock, flags); | 433 | spin_unlock_irqrestore(&iommu->lock, flags); |
426 | } | 434 | } |
427 | 435 | ||
@@ -584,7 +592,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int | |||
584 | iommu = sdev->bus->iommu; | 592 | iommu = sdev->bus->iommu; |
585 | spin_lock_irqsave(&iommu->lock, flags); | 593 | spin_lock_irqsave(&iommu->lock, flags); |
586 | free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); | 594 | free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); |
587 | sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); | 595 | sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT, direction); |
588 | spin_unlock_irqrestore(&iommu->lock, flags); | 596 | spin_unlock_irqrestore(&iommu->lock, flags); |
589 | } | 597 | } |
590 | 598 | ||
@@ -596,7 +604,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t | |||
596 | size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); | 604 | size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); |
597 | 605 | ||
598 | spin_lock_irqsave(&iommu->lock, flags); | 606 | spin_lock_irqsave(&iommu->lock, flags); |
599 | sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); | 607 | sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT, direction); |
600 | spin_unlock_irqrestore(&iommu->lock, flags); | 608 | spin_unlock_irqrestore(&iommu->lock, flags); |
601 | } | 609 | } |
602 | 610 | ||
@@ -620,7 +628,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int | |||
620 | size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; | 628 | size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; |
621 | 629 | ||
622 | spin_lock_irqsave(&iommu->lock, flags); | 630 | spin_lock_irqsave(&iommu->lock, flags); |
623 | sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); | 631 | sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT, direction); |
624 | spin_unlock_irqrestore(&iommu->lock, flags); | 632 | spin_unlock_irqrestore(&iommu->lock, flags); |
625 | } | 633 | } |
626 | 634 | ||
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 0f430d9d3632..289f448ac89c 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -305,6 +305,7 @@ config HPET_TIMER | |||
305 | 305 | ||
306 | config X86_PM_TIMER | 306 | config X86_PM_TIMER |
307 | bool "PM timer" | 307 | bool "PM timer" |
308 | depends on ACPI | ||
308 | default y | 309 | default y |
309 | help | 310 | help |
310 | Support the ACPI PM timer for time keeping. This is slow, | 311 | Support the ACPI PM timer for time keeping. This is slow, |
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 80e9b498c443..afd87e64d0a8 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/desc.h> | 37 | #include <asm/desc.h> |
38 | #include <asm/proto.h> | 38 | #include <asm/proto.h> |
39 | #include <asm/mach_apic.h> | 39 | #include <asm/mach_apic.h> |
40 | #include <asm/acpi.h> | ||
40 | 41 | ||
41 | #define __apicdebuginit __init | 42 | #define __apicdebuginit __init |
42 | 43 | ||
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index f86d9db94bfc..61a63be6b294 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/pgalloc.h> | 30 | #include <asm/pgalloc.h> |
31 | #include <asm/io_apic.h> | 31 | #include <asm/io_apic.h> |
32 | #include <asm/proto.h> | 32 | #include <asm/proto.h> |
33 | #include <asm/acpi.h> | ||
33 | 34 | ||
34 | /* Have we found an MP table */ | 35 | /* Have we found an MP table */ |
35 | int smp_found_config; | 36 | int smp_found_config; |
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 735b6767c8ed..fb8c809b4cd9 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c | |||
@@ -27,7 +27,9 @@ | |||
27 | #include <linux/bcd.h> | 27 | #include <linux/bcd.h> |
28 | #include <linux/kallsyms.h> | 28 | #include <linux/kallsyms.h> |
29 | #include <linux/acpi.h> | 29 | #include <linux/acpi.h> |
30 | #ifdef CONFIG_ACPI | ||
30 | #include <acpi/achware.h> /* for PM timer frequency */ | 31 | #include <acpi/achware.h> /* for PM timer frequency */ |
32 | #endif | ||
31 | #include <asm/8253pit.h> | 33 | #include <asm/8253pit.h> |
32 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
33 | #include <asm/vsyscall.h> | 35 | #include <asm/vsyscall.h> |