From 837e9594fc3cb9a06bddd7ecf66151334a2e13d2 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 14 Jan 2006 16:18:45 +0100 Subject: [PATCH 01/24] [PATCH] sem2mutex: drivers/macintosh/windfarm_core.c semaphore to mutex conversion. the conversion was generated via scripts, and the result was validated automatically via a script as well. build and boot tested. Signed-off-by: Ingo Molnar Signed-off-by: Paul Mackerras --- drivers/macintosh/windfarm_core.c | 53 ++++++++++++++++--------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 6c2a471ea6c0..32d466441ac2 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "windfarm.h" @@ -48,7 +49,7 @@ static LIST_HEAD(wf_controls); static LIST_HEAD(wf_sensors); -static DECLARE_MUTEX(wf_lock); +static DEFINE_MUTEX(wf_lock); static struct notifier_block *wf_client_list; static int wf_client_count; static unsigned int wf_overtemp; @@ -160,12 +161,12 @@ int wf_register_control(struct wf_control *new_ct) { struct wf_control *ct; - down(&wf_lock); + mutex_lock(&wf_lock); list_for_each_entry(ct, &wf_controls, link) { if (!strcmp(ct->name, new_ct->name)) { printk(KERN_WARNING "windfarm: trying to register" " duplicate control %s\n", ct->name); - up(&wf_lock); + mutex_unlock(&wf_lock); return -EEXIST; } } @@ -175,7 +176,7 @@ int wf_register_control(struct wf_control *new_ct) DBG("wf: Registered control %s\n", new_ct->name); wf_notify(WF_EVENT_NEW_CONTROL, new_ct); - up(&wf_lock); + mutex_unlock(&wf_lock); return 0; } @@ -183,9 +184,9 @@ EXPORT_SYMBOL_GPL(wf_register_control); void wf_unregister_control(struct wf_control *ct) { - down(&wf_lock); + mutex_lock(&wf_lock); list_del(&ct->link); - up(&wf_lock); + mutex_unlock(&wf_lock); DBG("wf: Unregistered control %s\n", ct->name); @@ -197,16 +198,16 @@ struct wf_control * wf_find_control(const char *name) { struct wf_control *ct; - down(&wf_lock); + mutex_lock(&wf_lock); list_for_each_entry(ct, &wf_controls, link) { if (!strcmp(ct->name, name)) { if (wf_get_control(ct)) ct = NULL; - up(&wf_lock); + mutex_unlock(&wf_lock); return ct; } } - up(&wf_lock); + mutex_unlock(&wf_lock); return NULL; } EXPORT_SYMBOL_GPL(wf_find_control); @@ -250,12 +251,12 @@ int wf_register_sensor(struct wf_sensor *new_sr) { struct wf_sensor *sr; - down(&wf_lock); + mutex_lock(&wf_lock); list_for_each_entry(sr, &wf_sensors, link) { if (!strcmp(sr->name, new_sr->name)) { printk(KERN_WARNING "windfarm: trying to register" " duplicate sensor %s\n", sr->name); - up(&wf_lock); + mutex_unlock(&wf_lock); return -EEXIST; } } @@ -265,7 +266,7 @@ int wf_register_sensor(struct wf_sensor *new_sr) DBG("wf: Registered sensor %s\n", new_sr->name); wf_notify(WF_EVENT_NEW_SENSOR, new_sr); - up(&wf_lock); + mutex_unlock(&wf_lock); return 0; } @@ -273,9 +274,9 @@ EXPORT_SYMBOL_GPL(wf_register_sensor); void wf_unregister_sensor(struct wf_sensor *sr) { - down(&wf_lock); + mutex_lock(&wf_lock); list_del(&sr->link); - up(&wf_lock); + mutex_unlock(&wf_lock); DBG("wf: Unregistered sensor %s\n", sr->name); @@ -287,16 +288,16 @@ struct wf_sensor * wf_find_sensor(const char *name) { struct wf_sensor *sr; - down(&wf_lock); + mutex_lock(&wf_lock); list_for_each_entry(sr, &wf_sensors, link) { if (!strcmp(sr->name, name)) { if (wf_get_sensor(sr)) sr = NULL; - up(&wf_lock); + mutex_unlock(&wf_lock); return sr; } } - up(&wf_lock); + mutex_unlock(&wf_lock); return NULL; } EXPORT_SYMBOL_GPL(wf_find_sensor); @@ -329,7 +330,7 @@ int wf_register_client(struct notifier_block *nb) struct wf_control *ct; struct wf_sensor *sr; - down(&wf_lock); + mutex_lock(&wf_lock); rc = notifier_chain_register(&wf_client_list, nb); if (rc != 0) goto bail; @@ -341,19 +342,19 @@ int wf_register_client(struct notifier_block *nb) if (wf_client_count == 1) wf_start_thread(); bail: - up(&wf_lock); + mutex_unlock(&wf_lock); return rc; } EXPORT_SYMBOL_GPL(wf_register_client); int wf_unregister_client(struct notifier_block *nb) { - down(&wf_lock); + mutex_lock(&wf_lock); notifier_chain_unregister(&wf_client_list, nb); wf_client_count++; if (wf_client_count == 0) wf_stop_thread(); - up(&wf_lock); + mutex_unlock(&wf_lock); return 0; } @@ -361,23 +362,23 @@ EXPORT_SYMBOL_GPL(wf_unregister_client); void wf_set_overtemp(void) { - down(&wf_lock); + mutex_lock(&wf_lock); wf_overtemp++; if (wf_overtemp == 1) { printk(KERN_WARNING "windfarm: Overtemp condition detected !\n"); wf_overtemp_counter = 0; wf_notify(WF_EVENT_OVERTEMP, NULL); } - up(&wf_lock); + mutex_unlock(&wf_lock); } EXPORT_SYMBOL_GPL(wf_set_overtemp); void wf_clear_overtemp(void) { - down(&wf_lock); + mutex_lock(&wf_lock); WARN_ON(wf_overtemp == 0); if (wf_overtemp == 0) { - up(&wf_lock); + mutex_unlock(&wf_lock); return; } wf_overtemp--; @@ -385,7 +386,7 @@ void wf_clear_overtemp(void) printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n"); wf_notify(WF_EVENT_NORMALTEMP, NULL); } - up(&wf_lock); + mutex_unlock(&wf_lock); } EXPORT_SYMBOL_GPL(wf_clear_overtemp); From e2f5a3c1bec1cf3e7c76c080fd7f21476f05008a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 7 Feb 2006 13:55:30 +1100 Subject: [PATCH 02/24] powerpc/64: Fix bug in setting floating-point exception mode When loading up the FPU, we were using a 'ld' (load doubleword) instruction to get the FP exception mode from the thread_struct, but it's only an int field. This changes the ld to lwz (load word and zero-extend). Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/fpu.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index e4362dfa37fb..340730fb8c91 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S @@ -66,7 +66,7 @@ _GLOBAL(load_up_fpu) #else ld r4,PACACURRENT(r13) addi r5,r4,THREAD /* Get THREAD */ - ld r4,THREAD_FPEXC_MODE(r5) + lwz r4,THREAD_FPEXC_MODE(r5) ori r12,r12,MSR_FP or r12,r12,r4 std r12,_MSR(r1) From aee9f26542cc27a37d593f1790b84cd57801a7c7 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Mon, 23 Jan 2006 17:37:11 -0800 Subject: [PATCH 03/24] [PATCH] powerpc: Fix spufs initialization sequence. This is a small fix to get the spufs init sequence right. init_spu_base() in spu_base.c should be called (via module_init(init_spu_base)) before spufs_init() (via module_init(spufs_init)) in spufs/inode.c gets called. Signed-off-by: Masato Noguchi Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 16031b565be4..3b998a393e3f 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -2,7 +2,7 @@ obj-y += interrupt.o iommu.o setup.o spider-pic.o obj-y += pervasive.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SPU_FS) += spufs/ spu-base.o +obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ spu-base-y += spu_base.o spu_priv1.o From 3ea4807de7b2c5c903380ba2c2e7150bee942f42 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 23 Jan 2006 13:57:06 -0200 Subject: [PATCH 04/24] [PATCH] powerpc/8xx: last two 8MB D-TLB entries are incorrectly set The last two 8MB TLB entries are being incorrectly set by initial_mmu on 8xx. The first entry is written with the same virtual/physical address, which renders it invalid: BDI>rms 792 0x00001e00 BDI>rms 824 1 BDI>rds 824 SPR 824 : 0xc08000c0 -1065353024 BDI>rds 825 SPR 825 : 0xc0800de0 -1065349664 BDI>rds 826 SPR 826 : 0x00000000 0 And the second entry, in addition, does not have its TLB index set correctly. Signed-off-by: Marcelo Tosatti Signed-off-by: Paul Mackerras --- arch/ppc/kernel/head_8xx.S | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index 3e6ca7f5843f..c1e89ad0684d 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -810,13 +810,16 @@ initial_mmu: mtspr SPRN_MD_TWC, r9 li r11, MI_BOOTINIT /* Create RPN for address 0 */ addis r11, r11, 0x0080 /* Add 8M */ - mtspr SPRN_MD_RPN, r8 + mtspr SPRN_MD_RPN, r11 + + addi r10, r10, 0x0100 + mtspr SPRN_MD_CTR, r10 addis r8, r8, 0x0080 /* Add 8M */ mtspr SPRN_MD_EPN, r8 mtspr SPRN_MD_TWC, r9 addis r11, r11, 0x0080 /* Add 8M */ - mtspr SPRN_MD_RPN, r8 + mtspr SPRN_MD_RPN, r11 #endif /* Since the cache is enabled according to the information we From fa93895329b87112cb1fd784db969e60b5b46af6 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 Jan 2006 21:31:25 +1300 Subject: [PATCH 05/24] [PATCH] powerpc: Don't allocate zero bytes in finish_device_tree() In prom.c we run finish_node() on allnodes twice. The first time we just calculate how much memory we'll need, the second time we do the actual work. If the calculation stage determines that we need 0 bytes, then we should skip the lmb allocation. Although an alloc of zero will work, it has been seen to lead to a BUG_ON() in reserve_bootmem() on at least one machine. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index d50c8df0183e..535a33e4aa37 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -491,7 +491,12 @@ void __init finish_device_tree(void) size = 16; finish_node(allnodes, &size, 1); size -= 16; - end = start = (unsigned long) __va(lmb_alloc(size, 128)); + + if (0 == size) + end = start = 0; + else + end = start = (unsigned long)__va(lmb_alloc(size, 128)); + finish_node(allnodes, &end, 0); BUG_ON(end != start + size); From 8c20fafa8548917fdbbd95588494498dd901b375 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 Jan 2006 21:31:26 +1300 Subject: [PATCH 06/24] [PATCH] powerpc: Make sure we don't create empty lmb regions To prevent problems later in boot, make sure we don't create zero-size lmb regions. I've checked all the callers, and at the moment no one should ever hit this. All callers use a constant size, or they check the computed size before they call us. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/mm/lmb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index 9584608fd768..bbe3eac918e8 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -197,6 +197,8 @@ long __init lmb_reserve(unsigned long base, unsigned long size) { struct lmb_region *_rgn = &(lmb.reserved); + BUG_ON(0 == size); + return lmb_add_region(_rgn, base, size); } @@ -227,6 +229,8 @@ unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, long i, j; unsigned long base = 0; + BUG_ON(0 == size); + #ifdef CONFIG_PPC32 /* On 32-bit, make sure we allocate lowmem */ if (max_addr == LMB_ALLOC_ANYWHERE) From cdc3ee8f2061bafe7593bab0096a0e711408b0f9 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 Jan 2006 21:48:48 +1300 Subject: [PATCH 07/24] [PATCH] powerpc: Refuse to boot a kdump kernel via OF You can't boot a kdump kernel via OF, not reliably anyway, the kernel being at 32 MB conflicts with the zImage wrapper etc. and it blows up. It's trivial to check in prom_init though, and this is early enough that we can actually drop back to OF where a reset-all will get you going again, which is kinda nice. I think this should go in for 2.6.16. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 7881ec96ef11..ec7153f4d47c 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -2098,6 +2098,10 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, */ prom_init_stdout(); + /* Bail if this is a kdump kernel. */ + if (PHYSICAL_START > 0) + prom_panic("Error: You can't boot a kdump kernel from OF!\n"); + /* * Check for an initrd */ From a958a2648602aaa8f98aeb3c1c914f1b8096bfdc Mon Sep 17 00:00:00 2001 From: Jake Moilanen Date: Mon, 30 Jan 2006 21:51:54 -0600 Subject: [PATCH 08/24] [PATCH] powerpc: IOMMU SG paranoia This addresses two items, which are unlikely to be hit if we trust drivers. The first is moving a memory barrier below where the vmerged SG count is passed back, but before the list is set to end. If those instructions were reordered, there could be an issue in iommu_unmap_sg(). The second is making sure we terminate the list on the failure case of iommu_map_sg(). If a driver does not look at the failure return code, it could pass a ill-formed SG list to iommu_unmap_sg(). Signed-off-by: Jake Moilanen Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/iommu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 4d9b4388918b..946f3219fd29 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -334,9 +334,6 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, spin_unlock_irqrestore(&(tbl->it_lock), flags); - /* Make sure updates are seen by hardware */ - mb(); - DBG("mapped %d elements:\n", outcount); /* For the sake of iommu_unmap_sg, we clear out the length in the @@ -347,6 +344,10 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, outs->dma_address = DMA_ERROR_CODE; outs->dma_length = 0; } + + /* Make sure updates are seen by hardware */ + mb(); + return outcount; failure: @@ -358,6 +359,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, npages = (PAGE_ALIGN(s->dma_address + s->dma_length) - vaddr) >> PAGE_SHIFT; __iommu_free(tbl, vaddr, npages); + s->dma_address = DMA_ERROR_CODE; + s->dma_length = 0; } } spin_unlock_irqrestore(&(tbl->it_lock), flags); From 31a7f67e587aa0745a132ae68efa7f15dac677f9 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 31 Jan 2006 17:17:47 +1100 Subject: [PATCH 09/24] [PATCH] powerpc: Fix !SMP build of rtas.c arch/powerpc/kernel/rtas.c is getting hvcall.h via spinlock.h, but when we're building for UP we don't include spinlock.h. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 7fe4a5c944c9..b7092a47064b 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include From c4cb8ecca66e3f136f66b5b30ec189530290a9b9 Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Fri, 3 Feb 2006 01:18:46 -0600 Subject: [PATCH 10/24] [PATCH] powerpc: return correct rtas status from ibm,suspend-me Correctly return the status from the RTAS call. rtas_call expects to return the status as a return value. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index b7092a47064b..f9b34e3ccf5a 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -588,8 +588,8 @@ static void rtas_percpu_suspend_me(void *info) if (rc == H_Continue) { data->waiting = 0; - rtas_call(ibm_suspend_me_token, 0, 1, - data->args->args); + data->args->args[data->args->nargs] = + rtas_call(ibm_suspend_me_token, 0, 1, NULL); } else { data->waiting = -EBUSY; printk(KERN_ERR "Error on H_Join hypervisor call\n"); From 82a4df74628a3bf0ac762be198b45e02a7c5879f Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Fri, 3 Feb 2006 01:18:39 -0600 Subject: [PATCH 11/24] [PATCH] powerpc: prod all processors after ibm,suspend-me We need to prod everyone here since this is the only CPU that is guaranteed to be running after the ibm,suspend-me RTAS call returns. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index f9b34e3ccf5a..0c6ed6d75b17 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -566,6 +566,7 @@ static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; #ifdef CONFIG_PPC_PSERIES static void rtas_percpu_suspend_me(void *info) { + int i; long rc; long flags; struct rtas_suspend_me_data *data = @@ -590,6 +591,8 @@ static void rtas_percpu_suspend_me(void *info) data->waiting = 0; data->args->args[data->args->nargs] = rtas_call(ibm_suspend_me_token, 0, 1, NULL); + for_each_cpu(i) + plpar_hcall_norets(H_PROD,i); } else { data->waiting = -EBUSY; printk(KERN_ERR "Error on H_Join hypervisor call\n"); From b4fd884a037c791a39f2f03da719e251af176a97 Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Fri, 3 Feb 2006 01:18:36 -0600 Subject: [PATCH 12/24] [PATCH] powerpc: remove useless call to touch_softlockup_watchdog It turns out that we can't stop the watchdog from triggering here. If we touch the timer (which just uses the current jiffie value) before we enable interrupts, it does nothing because jiffies are not mass-updated until after we enable interrupts. If we touch the timer after we enable interrupts, its too late because the softlockup watchdog will already have triggered. The touch_softlockup_watchdog call removed below does nothing. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 0c6ed6d75b17..b5b2add7ad1e 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -599,10 +599,6 @@ static void rtas_percpu_suspend_me(void *info) } out: - /* before we restore interrupts, make sure we don't - * generate a spurious soft lockup errors - */ - touch_softlockup_watchdog(); local_irq_restore(flags); return; } From b68239ee746760bd99a68692f4c97a28f08a5d01 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 3 Feb 2006 19:05:47 +1100 Subject: [PATCH 13/24] [PATCH] powerpc: Don't overwrite flat device tree with kdump kernel It's possible for prom_init to allocate the flat device tree inside the kdump crash kernel region. If this happens, when we load the kdump kernel we overwrite the flattened device tree, which is bad. We could make prom_init try and avoid allocating inside the crash kernel region, but then we run into issues if the crash kernel region uses all the space inside the RMO. The easiest solution is to move the flat device tree once we're running in the kernel. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 27 +++++++++++++++++++++++++++ arch/powerpc/kernel/setup_64.c | 3 +++ include/asm-powerpc/prom.h | 2 ++ 3 files changed, 32 insertions(+) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 535a33e4aa37..2b062853bcc7 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1922,3 +1922,30 @@ int prom_update_property(struct device_node *np, return 0; } + +#ifdef CONFIG_KEXEC +/* We may have allocated the flat device tree inside the crash kernel region + * in prom_init. If so we need to move it out into regular memory. */ +void kdump_move_device_tree(void) +{ + unsigned long start, end; + struct boot_param_header *new; + + start = __pa((unsigned long)initial_boot_params); + end = start + initial_boot_params->totalsize; + + if (end < crashk_res.start || start > crashk_res.end) + return; + + new = (struct boot_param_header*) + __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE)); + + memcpy(new, initial_boot_params, initial_boot_params->totalsize); + + initial_boot_params = new; + + DBG("Flat device tree blob moved to %p\n", initial_boot_params); + + /* XXX should we unreserve the old DT? */ +} +#endif /* CONFIG_KEXEC */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index e29b275e09e0..a717dff695ef 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -398,6 +398,9 @@ void __init setup_system(void) { DBG(" -> setup_system()\n"); +#ifdef CONFIG_KEXEC + kdump_move_device_tree(); +#endif /* * Unflatten the device-tree passed by prom_init or kexec */ diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 5b2bd4eefb01..cbd297f44cce 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -222,5 +222,7 @@ extern int of_address_to_resource(struct device_node *dev, int index, extern int of_pci_address_to_resource(struct device_node *dev, int bar, struct resource *r); +extern void kdump_move_device_tree(void); + #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ From d8a8188ded1251afc6a2ec8a668b0bdf038b64a1 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sat, 4 Feb 2006 10:34:56 +0100 Subject: [PATCH 14/24] [PATCH] powerpc: remove pointer/integer confusion in generic_calibrate_decr remove pointer/integer confusion Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/time.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index c4a294d657b9..1886045a2fd8 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -612,10 +612,10 @@ void __init generic_calibrate_decr(void) ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ node_found = 0; - if (cpu != 0) { + if (cpu) { fp = (unsigned int *)get_property(cpu, "timebase-frequency", NULL); - if (fp != 0) { + if (fp) { node_found = 1; ppc_tb_freq = *fp; } @@ -626,10 +626,10 @@ void __init generic_calibrate_decr(void) ppc_proc_freq = DEFAULT_PROC_FREQ; node_found = 0; - if (cpu != 0) { + if (cpu) { fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL); - if (fp != 0) { + if (fp) { node_found = 1; ppc_proc_freq = *fp; } From 03478804920a53405dfff73a0b23e9dcbbbee1c1 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sat, 4 Feb 2006 11:05:33 +0100 Subject: [PATCH 15/24] [PATCH] powerpc: restore clock speed in /proc/cpuinfo Use generic_calibrate_decr to restore missing clock: speed in /proc/cpuinfo Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/chrp/chrp.h | 1 - arch/powerpc/platforms/chrp/setup.c | 2 +- arch/powerpc/platforms/chrp/time.c | 21 --------------------- 3 files changed, 1 insertion(+), 23 deletions(-) diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h index 3a2057fa314a..814f54742e0f 100644 --- a/arch/powerpc/platforms/chrp/chrp.h +++ b/arch/powerpc/platforms/chrp/chrp.h @@ -5,7 +5,6 @@ extern void chrp_nvram_init(void); extern void chrp_get_rtc_time(struct rtc_time *); extern int chrp_set_rtc_time(struct rtc_time *); -extern void chrp_calibrate_decr(void); extern long chrp_time_init(void); extern void chrp_find_bridges(void); diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 2dc87aa5962f..e1fadbf49150 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -506,7 +506,7 @@ void __init chrp_init(void) ppc_md.halt = rtas_halt; ppc_md.time_init = chrp_time_init; - ppc_md.calibrate_decr = chrp_calibrate_decr; + ppc_md.calibrate_decr = generic_calibrate_decr; /* this may get overridden with rtas routines later... */ ppc_md.set_rtc_time = chrp_set_rtc_time; diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 36a0f97bb7b1..78df2e7ca88a 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -167,24 +167,3 @@ void chrp_get_rtc_time(struct rtc_time *tm) tm->tm_mon = mon; tm->tm_year = year; } - - -void __init chrp_calibrate_decr(void) -{ - struct device_node *cpu; - unsigned int freq, *fp; - - /* - * The cpu node should have a timebase-frequency property - * to tell us the rate at which the decrementer counts. - */ - freq = 16666000; /* hardcoded default */ - cpu = find_type_devices("cpu"); - if (cpu != 0) { - fp = (unsigned int *) - get_property(cpu, "timebase-frequency", NULL); - if (fp != 0) - freq = *fp; - } - ppc_tb_freq = freq; -} From 090db7c86d5df0161135793063e75bc1abddaa6f Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sat, 4 Feb 2006 12:44:56 +0100 Subject: [PATCH 16/24] [PATCH] powerpc: remove pointer/integer confusion in of_find_node_by_name remove pointer/integer confusion Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 2b062853bcc7..294832a7e0a6 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1403,8 +1403,8 @@ struct device_node *of_find_node_by_name(struct device_node *from, read_lock(&devtree_lock); np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) - if (np->name != 0 && strcasecmp(np->name, name) == 0 + for (; np != NULL; np = np->allnext) + if (np->name != NULL && strcasecmp(np->name, name) == 0 && of_node_get(np)) break; if (from) From d60dcd9450cf1c4d6482f7cd9c73366c07931bf6 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sat, 4 Feb 2006 12:55:41 +0100 Subject: [PATCH 17/24] [PATCH] powerpc: add refcounting to setup_peg2 and of_get_pci_address setup_peg2 must do some refcounting. of_get_pci_address may need to drop the node Pegasos l2cr : L2 cache was not active, activating PCI bus 0 controlled by pci at 80000000 Badness in kref_get at /home/olaf/kernel/olh/ppc64/linux-2.6.16-rc2-olh/lib/kref.c:32 Call Trace: [C037BD00] [C0007934] show_stack+0x5c/0x184 (unreliable) [C037BD30] [C000E068] program_check_exception+0x184/0x584 [C037BD90] [C000F5F0] ret_from_except_full+0x0/0x4c --- Exception: 700 at kref_get+0xc/0x24 LR = of_node_get+0x24/0x3c [C037BE50] [C004FD94] __pte_alloc_kernel+0x64/0x80 (unreliable) [C037BE70] [C000CA18] of_get_parent+0x34/0x58 [C037BE90] [C0009B18] of_get_address+0x24/0x174 [C037BED0] [C000A108] of_address_to_resource+0x24/0x68 [C037BF00] [C038B128] chrp_find_bridges+0x114/0x470 [C037BF90] [C038AE48] chrp_setup_arch+0x1fc/0x32c [C037BFB0] [C03849B0] setup_arch+0x144/0x188 [C037BFD0] [C037C45C] start_kernel+0x34/0x1a8 [C037BFF0] [000037A0] 0x37a0 Badness in kref_get at /home/olaf/kernel/olh/ppc64/linux-2.6.16-rc2-olh/lib/kref.c:32 Call Trace: [C037BC90] [C0007934] show_stack+0x5c/0x184 (unreliable) [C037BCC0] [C000E068] program_check_exception+0x184/0x584 [C037BD20] [C000F5F0] ret_from_except_full+0x0/0x4c --- Exception: 700 at kref_get+0xc/0x24 LR = of_node_get+0x24/0x3c [C037BDE0] [00000000] 0x0 (unreliable) [C037BE00] [C000CA18] of_get_parent+0x34/0x58 [C037BE20] [C0009CE8] of_translate_address+0x2c/0x2fc [C037BEA0] [C0009FE8] __of_address_to_resource+0x30/0xc4 [C037BED0] [C000A130] of_address_to_resource+0x4c/0x68 [C037BF00] [C038B128] chrp_find_bridges+0x114/0x470 [C037BF90] [C038AE48] chrp_setup_arch+0x1fc/0x32c [C037BFB0] [C03849B0] setup_arch+0x144/0x188 [C037BFD0] [C037C45C] start_kernel+0x34/0x1a8 [C037BFF0] [000037A0] 0x37a0 PCI bus 0 controlled by pci at c0000000 Top of RAM: 0x10000000, Total RAM: 0x10000000 Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_parse.c | 4 +++- arch/powerpc/platforms/chrp/pci.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index a8099c806150..3934c227549b 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -465,8 +465,10 @@ u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, if (parent == NULL) return NULL; bus = of_match_bus(parent); - if (strcmp(bus->name, "pci")) + if (strcmp(bus->name, "pci")) { + of_node_put(parent); return NULL; + } bus->count_cells(dev, &na, &ns); of_node_put(parent); if (!OF_CHECK_COUNTS(na, ns)) diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 00c52f27ef4f..8ef279ad36ad 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -204,9 +204,11 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d struct device_node *root = find_path_device("/"); struct device_node *rtas; + of_node_get(root); rtas = of_find_node_by_name (root, "rtas"); if (rtas) { hose->ops = &rtas_pci_ops; + of_node_put(rtas); } else { printk ("RTAS supporting Pegasos OF not found, please upgrade" " your firmware\n"); From 4009d980224389c33dce1565e0ac9f673354c43f Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sat, 4 Feb 2006 13:33:46 +0100 Subject: [PATCH 18/24] [PATCH] powerpc: fix compile warning in udbg_init_maple_realmode arch/powerpc/kernel/udbg_16550.c: In function `udbg_init_maple_realmode': arch/powerpc/kernel/udbg_16550.c:162: warning: assignment from incompatible pointer type Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/udbg_16550.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 2da65a9c93f6..5d29dcca523c 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c @@ -144,7 +144,7 @@ unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock) } #ifdef CONFIG_PPC_MAPLE -void udbg_maple_real_putc(unsigned char c) +void udbg_maple_real_putc(char c) { if (udbg_comport) { while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) From 95eff20feb679a2223a6da1e7f272fe9aa99591e Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 4 Feb 2006 20:35:59 +0100 Subject: [PATCH 19/24] [PATCH] Don't check pointer for NULL before passing it to kfree [arch/powerpc/kernel/rtas_flash.c] Checking a pointer for NULL before passing it to kfree is pointless, kfree does its own NULL checking of input. Signed-off-by: Jesper Juhl Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas_flash.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 50500093c97f..aaf384c3f04a 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -672,8 +672,7 @@ static void rtas_flash_firmware(int reboot_type) static void remove_flash_pde(struct proc_dir_entry *dp) { if (dp) { - if (dp->data != NULL) - kfree(dp->data); + kfree(dp->data); dp->owner = NULL; remove_proc_entry(dp->name, dp->parent); } From 09f5dc44aeff9f792a807a7dca64c1791d98d8c8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 6 Feb 2006 13:24:53 +1100 Subject: [PATCH 20/24] [PATCH] powerpc: Cleanup, consolidating icache dirtying logic The code to mark a page as icache dirty (so that it will later be icache-dcache flushed when we try to execute from it) is duplicated in three places: flush_dcache_page() does this marking and nothing else, but clear_user_page() and copy_user_page() duplicate it, since those functions make the page icache dirty themselves. This patch makes those other functions call flush_dcache_page() instead, so the logic's all in one place. This will make life less confusing if we ever need to tweak the details of the the lazy icache flush mechanism. arch/powerpc/mm/mem.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/mm/mem.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 15aac0d78dfa..550517c2dd42 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -435,17 +435,12 @@ void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { clear_page(page); - if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) - return; /* * We shouldnt have to do this, but some versions of glibc * require it (ld.so assumes zero filled pages are icache clean) * - Anton */ - - /* avoid an atomic op if possible */ - if (test_bit(PG_arch_1, &pg->flags)) - clear_bit(PG_arch_1, &pg->flags); + flush_dcache_page(pg); } EXPORT_SYMBOL(clear_user_page); @@ -469,12 +464,7 @@ void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, return; #endif - if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) - return; - - /* avoid an atomic op if possible */ - if (test_bit(PG_arch_1, &pg->flags)) - clear_bit(PG_arch_1, &pg->flags); + flush_dcache_page(pg); } void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, From f9b4045d6bbb109d066d127549b2beb38fd9bfc4 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 7 Feb 2006 13:26:14 +1100 Subject: [PATCH 21/24] [PATCH] powerpc: Don't use toc in decrementer_iSeries_masked Since 404849bbd2bfd62e05b36f4753f6e1af6050a824 we've been using LOAD_REG_ADDRBASE, which uses the toc pointer, in decrementer_iSeries_masked. This can explode if we take the decrementer interrupt while we're in a module, because the toc pointer in r2 will be the module's toc pointer. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/head_64.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 308268466342..415659629394 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -749,11 +749,12 @@ iSeries_secondary_smp_loop: .globl decrementer_iSeries_masked decrementer_iSeries_masked: + /* We may not have a valid TOC pointer in here. */ li r11,1 ld r12,PACALPPACAPTR(r13) stb r11,LPPACADECRINT(r12) - LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy) - lwz r12,ADDROFF(tb_ticks_per_jiffy)(r12) + LOAD_REG_IMMEDIATE(r12, tb_ticks_per_jiffy) + lwz r12,0(r12) mtspr SPRN_DEC,r12 /* fall through */ From 7d4b95ae8e946e5754122220644c865ec3735428 Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Mon, 6 Feb 2006 14:26:31 -0600 Subject: [PATCH 22/24] [PATCH] documentation/powerpc: add bus-frequency property to SOC node Updated SOC node definition in documentation to include bus-frequency property. Also extended mdio example to match specification. Signed-off-by: Becky Bruce Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- Documentation/powerpc/booting-without-of.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 1284498e847c..54e5f9b1536d 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -880,6 +880,10 @@ address which can extend beyond that limit. - device_type : Should be "soc" - ranges : Should be defined as specified in 1) to describe the translation of SOC addresses for memory mapped SOC registers. + - bus-frequency: Contains the bus frequency for the SOC node. + Typically, the value of this field is filled in by the boot + loader. + Recommended properties: @@ -919,6 +923,7 @@ SOC. device_type = "soc"; ranges = <00000000 e0000000 00100000> reg = ; + bus-frequency = <0>; } @@ -1170,6 +1175,8 @@ platforms are moved over to use the flattened-device-tree model. mdio@24520 { reg = <24520 20>; + device_type = "mdio"; + compatible = "gianfar"; ethernet-phy@0 { ...... @@ -1317,6 +1324,7 @@ not necessary as they are usually the same as the root node. device_type = "soc"; ranges = <00000000 e0000000 00100000> reg = ; + bus-frequency = <0>; mdio@24520 { reg = <24520 20>; From 4dc43256931db60d02d76bacf3cf03b5d79aa33a Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Tue, 7 Feb 2006 10:58:21 +1100 Subject: [PATCH 23/24] [PATCH] powerpc: hypervisor check in pseries_kexec_cpu_down We call unregister_vpa but we don't check to see if the hypervisor supports this. Signed-off-by: Michael Neuling Acked-by: Anton Blanchard -- arch/powerpc/platforms/pseries/setup.c | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index da6cebaf72cd..9edeca83f434 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -585,7 +585,7 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) { /* Don't risk a hypervisor call if we're crashing */ - if (!crash_shutdown) { + if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { unsigned long vpa = __pa(get_lppaca()); if (unregister_vpa(hard_smp_processor_id(), vpa)) { From 7d4d61544a12333600bdb9b018a149868418692e Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 6 Feb 2006 22:44:23 -0600 Subject: [PATCH 24/24] [PATCH] powerpc: avoid timer interrupt replay effect when onlining cpu When a cpu is hotplug-onlined, if we don't set per_cpu(last_jiffy) to something sane, timer_interrupt will execute its while loop for every tick missed since the cpu was last online (or since the system was booted, if we're adding a new cpu). This can cause weird hangs, ssh sessions dropping, and we can even go xmon if we take a global IPI at the wrong time. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/smp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index c8458c531b25..13595a64f013 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -540,6 +540,9 @@ int __devinit start_secondary(void *unused) if (smp_ops->take_timebase) smp_ops->take_timebase(); + if (system_state > SYSTEM_BOOTING) + per_cpu(last_jiffy, cpu) = get_tb(); + spin_lock(&call_lock); cpu_set(cpu, cpu_online_map); spin_unlock(&call_lock);