diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 00:19:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 00:19:54 -0400 |
commit | d4429f608abde89e8bc1e24b43cd503feb95c496 (patch) | |
tree | 4c11afa193593a5e3949391bf35022b4f87ba375 /arch/powerpc/kernel/paca.c | |
parent | e10117d36ef758da0690c95ecffc09d5dd7da479 (diff) | |
parent | 6a1c9dfe4186f18fed38421b35b40fb9260cbfe1 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (71 commits)
powerpc/44x: Update ppc44x_defconfig
powerpc/watchdog: Make default timeout for Book-E watchdog a Kconfig option
fsl_rio: Add comments for sRIO registers.
powerpc/fsl-booke: Add e55xx (64-bit) smp defconfig
powerpc/fsl-booke: Add p5020 DS board support
powerpc/fsl-booke64: Use TLB CAMs to cover linear mapping on FSL 64-bit chips
powerpc/fsl-booke: Add support for FSL Arch v1.0 MMU in setup_page_sizes
powerpc/fsl-booke: Add support for FSL 64-bit e5500 core
powerpc/85xx: add cache-sram support
powerpc/85xx: add ngPIXIS FPGA device tree node to the P1022DS board
powerpc: Fix compile error with paca code on ppc64e
powerpc/fsl-booke: Add p3041 DS board support
oprofile/fsl emb: Don't set MSR[PMM] until after clearing the interrupt.
powerpc/fsl-booke: Add PCI device ids for P2040/P3041/P5010/P5020 QoirQ chips
powerpc/mpc8xxx_gpio: Add support for 'qoriq-gpio' controllers
powerpc/fsl_booke: Add support to boot from core other than 0
powerpc/p1022: Add probing for individual DMA channels
powerpc/fsl_soc: Search all global-utilities nodes for rstccr
powerpc: Fix invalid page flags in create TLB CAM path for PTE_64BIT
powerpc/mpc83xx: Support for MPC8308 P1M board
...
Fix up conflict with the generic irq_work changes in arch/powerpc/kernel/time.c
Diffstat (limited to 'arch/powerpc/kernel/paca.c')
-rw-r--r-- | arch/powerpc/kernel/paca.c | 70 |
1 files changed, 68 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index a4e72159234..ebf9846f3c3 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -27,6 +27,20 @@ extern unsigned long __toc_start; | |||
27 | #ifdef CONFIG_PPC_BOOK3S | 27 | #ifdef CONFIG_PPC_BOOK3S |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * We only have to have statically allocated lppaca structs on | ||
31 | * legacy iSeries, which supports at most 64 cpus. | ||
32 | */ | ||
33 | #ifdef CONFIG_PPC_ISERIES | ||
34 | #if NR_CPUS < 64 | ||
35 | #define NR_LPPACAS NR_CPUS | ||
36 | #else | ||
37 | #define NR_LPPACAS 64 | ||
38 | #endif | ||
39 | #else /* not iSeries */ | ||
40 | #define NR_LPPACAS 1 | ||
41 | #endif | ||
42 | |||
43 | /* | ||
30 | * The structure which the hypervisor knows about - this structure | 44 | * The structure which the hypervisor knows about - this structure |
31 | * should not cross a page boundary. The vpa_init/register_vpa call | 45 | * should not cross a page boundary. The vpa_init/register_vpa call |
32 | * is now known to fail if the lppaca structure crosses a page | 46 | * is now known to fail if the lppaca structure crosses a page |
@@ -36,7 +50,7 @@ extern unsigned long __toc_start; | |||
36 | * will suffice to ensure that it doesn't cross a page boundary. | 50 | * will suffice to ensure that it doesn't cross a page boundary. |
37 | */ | 51 | */ |
38 | struct lppaca lppaca[] = { | 52 | struct lppaca lppaca[] = { |
39 | [0 ... (NR_CPUS-1)] = { | 53 | [0 ... (NR_LPPACAS-1)] = { |
40 | .desc = 0xd397d781, /* "LpPa" */ | 54 | .desc = 0xd397d781, /* "LpPa" */ |
41 | .size = sizeof(struct lppaca), | 55 | .size = sizeof(struct lppaca), |
42 | .dyn_proc_status = 2, | 56 | .dyn_proc_status = 2, |
@@ -49,6 +63,54 @@ struct lppaca lppaca[] = { | |||
49 | }, | 63 | }, |
50 | }; | 64 | }; |
51 | 65 | ||
66 | static struct lppaca *extra_lppacas; | ||
67 | static long __initdata lppaca_size; | ||
68 | |||
69 | static void allocate_lppacas(int nr_cpus, unsigned long limit) | ||
70 | { | ||
71 | if (nr_cpus <= NR_LPPACAS) | ||
72 | return; | ||
73 | |||
74 | lppaca_size = PAGE_ALIGN(sizeof(struct lppaca) * | ||
75 | (nr_cpus - NR_LPPACAS)); | ||
76 | extra_lppacas = __va(memblock_alloc_base(lppaca_size, | ||
77 | PAGE_SIZE, limit)); | ||
78 | } | ||
79 | |||
80 | static struct lppaca *new_lppaca(int cpu) | ||
81 | { | ||
82 | struct lppaca *lp; | ||
83 | |||
84 | if (cpu < NR_LPPACAS) | ||
85 | return &lppaca[cpu]; | ||
86 | |||
87 | lp = extra_lppacas + (cpu - NR_LPPACAS); | ||
88 | *lp = lppaca[0]; | ||
89 | |||
90 | return lp; | ||
91 | } | ||
92 | |||
93 | static void free_lppacas(void) | ||
94 | { | ||
95 | long new_size = 0, nr; | ||
96 | |||
97 | if (!lppaca_size) | ||
98 | return; | ||
99 | nr = num_possible_cpus() - NR_LPPACAS; | ||
100 | if (nr > 0) | ||
101 | new_size = PAGE_ALIGN(nr * sizeof(struct lppaca)); | ||
102 | if (new_size >= lppaca_size) | ||
103 | return; | ||
104 | |||
105 | memblock_free(__pa(extra_lppacas) + new_size, lppaca_size - new_size); | ||
106 | lppaca_size = new_size; | ||
107 | } | ||
108 | |||
109 | #else | ||
110 | |||
111 | static inline void allocate_lppacas(int nr_cpus, unsigned long limit) { } | ||
112 | static inline void free_lppacas(void) { } | ||
113 | |||
52 | #endif /* CONFIG_PPC_BOOK3S */ | 114 | #endif /* CONFIG_PPC_BOOK3S */ |
53 | 115 | ||
54 | #ifdef CONFIG_PPC_STD_MMU_64 | 116 | #ifdef CONFIG_PPC_STD_MMU_64 |
@@ -88,7 +150,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu) | |||
88 | unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; | 150 | unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; |
89 | 151 | ||
90 | #ifdef CONFIG_PPC_BOOK3S | 152 | #ifdef CONFIG_PPC_BOOK3S |
91 | new_paca->lppaca_ptr = &lppaca[cpu]; | 153 | new_paca->lppaca_ptr = new_lppaca(cpu); |
92 | #else | 154 | #else |
93 | new_paca->kernel_pgd = swapper_pg_dir; | 155 | new_paca->kernel_pgd = swapper_pg_dir; |
94 | #endif | 156 | #endif |
@@ -144,6 +206,8 @@ void __init allocate_pacas(void) | |||
144 | printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n", | 206 | printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n", |
145 | paca_size, nr_cpus, paca); | 207 | paca_size, nr_cpus, paca); |
146 | 208 | ||
209 | allocate_lppacas(nr_cpus, limit); | ||
210 | |||
147 | /* Can't use for_each_*_cpu, as they aren't functional yet */ | 211 | /* Can't use for_each_*_cpu, as they aren't functional yet */ |
148 | for (cpu = 0; cpu < nr_cpus; cpu++) | 212 | for (cpu = 0; cpu < nr_cpus; cpu++) |
149 | initialise_paca(&paca[cpu], cpu); | 213 | initialise_paca(&paca[cpu], cpu); |
@@ -164,4 +228,6 @@ void __init free_unused_pacas(void) | |||
164 | paca_size - new_size); | 228 | paca_size - new_size); |
165 | 229 | ||
166 | paca_size = new_size; | 230 | paca_size = new_size; |
231 | |||
232 | free_lppacas(); | ||
167 | } | 233 | } |