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 a4e72159234f..ebf9846f3c3b 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 | } |
