summaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/kernel/apus_setup.c3
-rw-r--r--arch/ppc/kernel/chrp_pci.c1
-rw-r--r--arch/ppc/kernel/chrp_setup.c102
-rw-r--r--arch/ppc/kernel/gemini_setup.c2
-rw-r--r--arch/ppc/kernel/idle.c5
-rw-r--r--arch/ppc/kernel/irq.c14
-rw-r--r--arch/ppc/kernel/m8xx_setup.c10
-rw-r--r--arch/ppc/kernel/mbx_setup.c11
-rw-r--r--arch/ppc/kernel/misc.S4
-rw-r--r--arch/ppc/kernel/pci.c22
-rw-r--r--arch/ppc/kernel/pmac_pci.c22
-rw-r--r--arch/ppc/kernel/pmac_pic.c9
-rw-r--r--arch/ppc/kernel/pmac_setup.c8
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c1
-rw-r--r--arch/ppc/kernel/prep_setup.c3
-rw-r--r--arch/ppc/kernel/setup.c19
-rw-r--r--arch/ppc/mbx_defconfig2
-rw-r--r--arch/ppc/mm/init.c297
18 files changed, 232 insertions, 303 deletions
diff --git a/arch/ppc/kernel/apus_setup.c b/arch/ppc/kernel/apus_setup.c
index 80377490a..353482a18 100644
--- a/arch/ppc/kernel/apus_setup.c
+++ b/arch/ppc/kernel/apus_setup.c
@@ -255,8 +255,7 @@ struct pci_bus * __init pci_scan_peer_bridge(int bus)
/*********************************************************** SETUP */
/* From arch/m68k/kernel/setup.c. */
-void __init apus_setup_arch(unsigned long * memory_start_p,
- unsigned long * memory_end_p)
+void __init apus_setup_arch(void)
{
#ifdef CONFIG_APUS
extern char cmd_line[];
diff --git a/arch/ppc/kernel/chrp_pci.c b/arch/ppc/kernel/chrp_pci.c
index da752ccb6..983a9f2eb 100644
--- a/arch/ppc/kernel/chrp_pci.c
+++ b/arch/ppc/kernel/chrp_pci.c
@@ -16,7 +16,6 @@
#include <asm/hydra.h>
#include <asm/prom.h>
#include <asm/gg2.h>
-#include <asm/ide.h>
#include <asm/machdep.h>
#include "pci.h"
diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c
index 4f71def9a..58d2003c4 100644
--- a/arch/ppc/kernel/chrp_setup.c
+++ b/arch/ppc/kernel/chrp_setup.c
@@ -28,6 +28,7 @@
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/blk.h>
+#include <linux/ide.h>
#include <linux/ioport.h>
#include <linux/console.h>
#include <linux/pci.h>
@@ -35,13 +36,12 @@
#include <linux/version.h>
#include <linux/adb.h>
#include <linux/module.h>
+#include <linux/delay.h>
#include <asm/mmu.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/pgtable.h>
-#include <linux/ide.h>
-#include <asm/ide.h>
#include <asm/prom.h>
#include <asm/gg2.h>
#include <asm/pci-bridge.h>
@@ -227,7 +227,7 @@ static void __init sio_init(void)
void __init
-chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
+chrp_setup_arch(void)
{
extern char cmd_line[];
struct device_node *device;
@@ -278,7 +278,7 @@ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
- *memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+ pmac_find_bridges();
/* Get the event scan rate for the rtas so we know how
* often it expects a heartbeat. -- Cort
@@ -363,10 +363,7 @@ int chrp_get_irq( struct pt_regs *regs )
irq = *chrp_int_ack_special;
else
irq = i8259_irq( smp_processor_id() );
- /*
- * Acknowledge as soon as possible to allow i8259
- * interrupt nesting */
- openpic_eoi( smp_processor_id() );
+ openpic_eoi( smp_processor_id() );
}
if (irq == OPENPIC_VEC_SPURIOUS)
/*
@@ -374,6 +371,11 @@ int chrp_get_irq( struct pt_regs *regs )
* acknowledged
*/
irq = -1;
+ /*
+ * I would like to openpic_eoi here but there seem to be timing problems
+ * between the openpic ack and the openpic eoi.
+ * -- Cort
+ */
return irq;
}
@@ -382,89 +384,15 @@ void chrp_post_irq(int irq)
/*
* If it's an i8259 irq then we've already done the
* openpic irq. So we just check to make sure the controller
- * is an openpic and if it is then eoi -- Cort
+ * is an openpic and if it is then eoi
+ *
+ * We do it this way since our irq_desc[irq].ctl can change
+ * with RTL and no longer be open_pic -- Cort
*/
- if ( irq_desc[irq].ctl == &open_pic )
+ if ( irq >= open_pic.irq_offset)
openpic_eoi( smp_processor_id() );
}
-#if 0
-void
-chrp_do_IRQ(struct pt_regs *regs,
- int cpu,
- int isfake)
-{
- int irq;
- unsigned long bits = 0;
- int openpic_eoi_done = 0;
-
-#ifdef __SMP__
- {
- unsigned int loops = 1000000;
- while (test_bit(0, &global_irq_lock)) {
- if (smp_processor_id() == global_irq_holder) {
- printk("uh oh, interrupt while we hold global irq lock!\n");
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- break;
- }
- if (loops-- == 0) {
- printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- }
- }
- }
-#endif /* __SMP__ */
-
- irq = openpic_irq(0);
- if (irq == IRQ_8259_CASCADE)
- {
- /*
- * This magic address generates a PCI IACK cycle.
- *
- * This should go in the above mask/ack code soon. -- Cort
- */
- if ( chrp_int_ack_special )
- irq = *chrp_int_ack_special;
- else
- irq = i8259_irq(0);
- /*
- * Acknowledge as soon as possible to allow i8259
- * interrupt nesting */
- openpic_eoi(0);
- openpic_eoi_done = 1;
- }
- if (irq == OPENPIC_VEC_SPURIOUS)
- {
- /*
- * Spurious interrupts should never be
- * acknowledged
- */
- ppc_spurious_interrupts++;
- openpic_eoi_done = 1;
- goto out;
- }
- bits = 1UL << irq;
-
- if (irq < 0)
- {
- printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
- irq, regs->nip);
- ppc_spurious_interrupts++;
- }
- else
- {
- ppc_irq_dispatch_handler( regs, irq );
- }
-out:
- if (!openpic_eoi_done)
- openpic_eoi(0);
-}
-#endif
-
void __init chrp_init_IRQ(void)
{
struct device_node *np;
diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c
index 6e599cff2..23060ba26 100644
--- a/arch/ppc/kernel/gemini_setup.c
+++ b/arch/ppc/kernel/gemini_setup.c
@@ -134,7 +134,7 @@ extern int root_mountflags;
extern char cmd_line[];
-void __init gemini_setup_arch(unsigned long *memstart, unsigned long *memend)
+void __init gemini_setup_arch(void)
{
unsigned int cpu;
extern char cmd_line[];
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index 09066a848..8f03ac79a 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -293,11 +293,8 @@ void power_save(void)
/* set the POW bit in the MSR, and enable interrupts
* so we wake up sometime! */
+ __sti(); /* this keeps rtl from getting confused -- Cort */
_nmask_and_or_msr(0, MSR_POW | MSR_EE);
-
- /* Disable interrupts again so restore_flags will
- * work. */
- _nmask_and_or_msr(MSR_EE, 0);
}
restore_flags(msr);
default:
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index 9c157d41b..9ab3589f6 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -296,15 +296,19 @@ asmlinkage void do_IRQ(struct pt_regs *regs, int isfake)
irq = ppc_md.get_irq( regs );
if ( irq < 0 )
{
- printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
- irq, regs->nip);
- ppc_spurious_interrupts++;
- return;
+ /* -2 means ignore, already handled */
+ if (irq != -2) {
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ ppc_spurious_interrupts++;
+ }
+ goto out;
}
ppc_irq_dispatch_handler( regs, irq );
if ( ppc_md.post_irq )
ppc_md.post_irq( irq );
-
+
+ out:
hardirq_exit( cpu );
}
diff --git a/arch/ppc/kernel/m8xx_setup.c b/arch/ppc/kernel/m8xx_setup.c
index f99f5b335..4d510612b 100644
--- a/arch/ppc/kernel/m8xx_setup.c
+++ b/arch/ppc/kernel/m8xx_setup.c
@@ -33,6 +33,7 @@
#include <linux/blk.h>
#include <linux/ioport.h>
#include <linux/ide.h>
+#include <linux/bootmem.h>
#include <asm/mmu.h>
#include <asm/processor.h>
@@ -83,13 +84,12 @@ void __init adbdev_init(void)
}
void __init
-m8xx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
+m8xx_setup_arch(void)
{
int cpm_page;
extern char cmd_line[];
- cpm_page = *memory_start_p;
- *memory_start_p += PAGE_SIZE;
+ cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE);
printk("Boot arguments: %s\n", cmd_line);
@@ -108,6 +108,9 @@ m8xx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
rd_doload = 1;
rd_image_start = 0;
#endif
+#if 0 /* XXX this may need to be updated for the new bootmem stuff,
+ or possibly just deleted (see set_phys_avail() in init.c).
+ - paulus. */
/* initrd_start and size are setup by boot/head.S and kernel/head.S */
if ( initrd_start )
{
@@ -120,6 +123,7 @@ m8xx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
}
}
#endif
+#endif
}
void
diff --git a/arch/ppc/kernel/mbx_setup.c b/arch/ppc/kernel/mbx_setup.c
index 67cab4503..f6487783b 100644
--- a/arch/ppc/kernel/mbx_setup.c
+++ b/arch/ppc/kernel/mbx_setup.c
@@ -30,6 +30,7 @@
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/blk.h>
+#include <linux/ide.h>
#include <linux/ioport.h>
#include <asm/mmu.h>
@@ -37,7 +38,6 @@
#include <asm/residual.h>
#include <asm/io.h>
#include <asm/pgtable.h>
-#include <asm/ide.h>
#include <asm/mbx.h>
#include <asm/machdep.h>
@@ -76,13 +76,12 @@ void __init adbdev_init(void)
}
void __init
-mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
+mbx_setup_arch(void)
{
int cpm_page;
extern char cmd_line[];
- cpm_page = *memory_start_p;
- *memory_start_p += PAGE_SIZE;
+ cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE);
sprintf(cmd_line,
"%s root=/dev/nfs nfsroot=/sys/mbxroot",
@@ -104,6 +103,9 @@ mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
rd_doload = 1;
rd_image_start = 0;
#endif
+#if 0 /* XXX this may need to be updated for the new bootmem stuff,
+ or possibly just deleted (see set_phys_avail() in init.c).
+ - paulus. */
/* initrd_start and size are setup by boot/head.S and kernel/head.S */
if ( initrd_start )
{
@@ -116,6 +118,7 @@ mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
}
}
#endif
+#endif
#ifdef notdef
request_region(0x20,0x20,"pic1");
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 4d041cc98..89994881b 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -235,9 +235,9 @@ _GLOBAL(flush_dcache_range)
* snoop from the data cache.
* This is a no-op on the 601 which has a unified cache.
*
- * void flush_page_to_ram(void *page)
+ * void __flush_page_to_ram(void *page)
*/
-_GLOBAL(flush_page_to_ram)
+_GLOBAL(__flush_page_to_ram)
mfspr r5,PVR
rlwinm r5,r5,16,16,31
cmpi 0,r5,1
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index de0a0a36d..0d07c289d 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -146,3 +146,25 @@ int pcibios_assign_resource(struct pci_dev *pdev, int resource)
{
return 0;
}
+
+/* the next two are stolen from the alpha port... */
+void __init
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+ struct resource *res, int resource)
+{
+ unsigned long where, size;
+ u32 reg;
+
+ where = PCI_BASE_ADDRESS_0 + (resource * 4);
+ size = res->end - res->start;
+ pci_read_config_dword(dev, where, &reg);
+ reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+ pci_write_config_dword(dev, where, reg);
+}
+
+void __init
+pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+ /* XXX FIXME - update OF device tree node interrupt property */
+}
diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c
index 932e7dbb6..62161f68a 100644
--- a/arch/ppc/kernel/pmac_pci.c
+++ b/arch/ppc/kernel/pmac_pci.c
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/bootmem.h>
#include <asm/init.h>
#include <asm/io.h>
@@ -30,7 +31,7 @@
struct bridge_data **bridges, *bridge_list;
static int max_bus;
-static void add_bridges(struct device_node *dev, unsigned long *mem_ptr);
+static void add_bridges(struct device_node *dev);
/*
* Magic constants for enabling cache coherency in the bandit/PSX bridge.
@@ -362,24 +363,22 @@ static void __init init_bandit(struct bridge_data *bp)
bp->io_base);
}
-unsigned long __init pmac_find_bridges(unsigned long mem_start, unsigned long mem_end)
+void __init pmac_find_bridges(void)
{
int bus;
struct bridge_data *bridge;
bridge_list = 0;
max_bus = 0;
- add_bridges(find_devices("bandit"), &mem_start);
- add_bridges(find_devices("chaos"), &mem_start);
- add_bridges(find_devices("pci"), &mem_start);
- bridges = (struct bridge_data **) mem_start;
- mem_start += (max_bus + 1) * sizeof(struct bridge_data *);
+ add_bridges(find_devices("bandit"));
+ add_bridges(find_devices("chaos"));
+ add_bridges(find_devices("pci"));
+ bridges = (struct bridge_data **)
+ alloc_bootmem((max_bus + 1) * sizeof(struct bridge_data *));
memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *));
for (bridge = bridge_list; bridge != NULL; bridge = bridge->next)
for (bus = bridge->bus_number; bus <= bridge->max_bus; ++bus)
bridges[bus] = bridge;
-
- return mem_start;
}
/*
@@ -387,7 +386,7 @@ unsigned long __init pmac_find_bridges(unsigned long mem_start, unsigned long me
* "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
* if we have one or more bandit or chaos bridges, we don't have a MPC106.
*/
-static void __init add_bridges(struct device_node *dev, unsigned long *mem_ptr)
+static void __init add_bridges(struct device_node *dev)
{
int *bus_range;
int len;
@@ -413,8 +412,7 @@ static void __init add_bridges(struct device_node *dev, unsigned long *mem_ptr)
printk(KERN_INFO "PCI buses %d..%d", bus_range[0],
bus_range[1]);
printk(" controlled by %s at %x\n", dev->name, addr->address);
- bp = (struct bridge_data *) *mem_ptr;
- *mem_ptr += sizeof(struct bridge_data);
+ bp = (struct bridge_data *) alloc_bootmem(sizeof(*bp));
if (strcmp(dev->name, "pci") != 0) {
bp->cfg_addr = (volatile unsigned int *)
ioremap(addr->address + 0x800000, 0x1000);
diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c
index 683aac568..f7224f5dd 100644
--- a/arch/ppc/kernel/pmac_pic.c
+++ b/arch/ppc/kernel/pmac_pic.c
@@ -225,7 +225,7 @@ pmac_get_irq(struct pt_regs *regs)
xmon(regs);
#endif
smp_message_recv();
- return -1;
+ return -2; /* ignore, already handled */
}
{
@@ -374,7 +374,7 @@ pmac_pic_init(void)
}
/* get addresses of second controller */
- irqctrler = (irqctrler->next) ? irqctrler->next : NULL;
+ irqctrler = irqctrler->next;
if (irqctrler && irqctrler->n_addrs > 0) {
addr = (unsigned long)
ioremap(irqctrler->addrs[0].address, 0x40);
@@ -382,6 +382,11 @@ pmac_pic_init(void)
pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
(addr + (4 - i) * 0x10);
}
+ } else {
+ /* older powermacs have a GC (grand central) or ohare at
+ f3000000, with interrupt control registers at f3000020. */
+ addr = (unsigned long) ioremap(0xf3000000, 0x40);
+ pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
}
/* disable all interrupts in all controllers */
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
index 3418a7e8b..0a23c4473 100644
--- a/arch/ppc/kernel/pmac_setup.c
+++ b/arch/ppc/kernel/pmac_setup.c
@@ -39,6 +39,7 @@
#include <linux/ioport.h>
#include <linux/major.h>
#include <linux/blk.h>
+#include <linux/ide.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
#include <linux/ide.h>
@@ -57,7 +58,6 @@
#include <asm/ohare.h>
#include <asm/mediabay.h>
#include <asm/feature.h>
-#include <asm/ide.h>
#include <asm/machdep.h>
#include <asm/keyboard.h>
#include <asm/dma.h>
@@ -238,7 +238,7 @@ pmac_mksound(unsigned int hz, unsigned int ticks)
static volatile u32 *sysctrl_regs;
void __init
-pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p)
+pmac_setup_arch(void)
{
struct device_node *cpu;
int *fp;
@@ -269,7 +269,7 @@ pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p)
__ioremap(0xffc00000, 0x400000, pgprot_val(PAGE_READONLY));
ohare_init();
- *memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+ pmac_find_bridges();
init_p2pbridge();
/* Checks "l2cr-value" property in the registry */
@@ -421,7 +421,7 @@ note_scsi_host(struct device_node *node, void *host)
#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
extern int pmac_ide_count;
extern struct device_node *pmac_ide_node[];
-static int ide_majors[] = { 3, 22, 33, 34, 56, 57, 88, 89 };
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 };
kdev_t __init find_ide_boot(void)
{
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index cabce054c..399b99052 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -60,7 +60,6 @@ EXPORT_SYMBOL(do_signal);
EXPORT_SYMBOL(syscall_trace);
EXPORT_SYMBOL(transfer_to_handler);
EXPORT_SYMBOL(do_IRQ);
-EXPORT_SYMBOL(init_task_union);
EXPORT_SYMBOL(MachineCheckException);
EXPORT_SYMBOL(AlignmentException);
EXPORT_SYMBOL(ProgramCheckException);
diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c
index 53c859a16..fe7043206 100644
--- a/arch/ppc/kernel/prep_setup.c
+++ b/arch/ppc/kernel/prep_setup.c
@@ -41,7 +41,6 @@
#include <asm/residual.h>
#include <asm/io.h>
#include <asm/pgtable.h>
-#include <asm/ide.h>
#include <asm/cache.h>
#include <asm/dma.h>
#include <asm/machdep.h>
@@ -211,7 +210,7 @@ no_l2:
}
void __init
-prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
+prep_setup_arch()
{
extern char cmd_line[];
unsigned char reg;
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 57955efca..518446bf9 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -11,12 +11,11 @@
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/blk.h>
+#include <linux/ide.h>
#include <asm/init.h>
#include <asm/residual.h>
#include <asm/io.h>
-#include <linux/ide.h>
-#include <asm/ide.h>
#include <asm/prom.h>
#include <asm/processor.h>
#include <asm/pgtable.h>
@@ -540,14 +539,12 @@ void __init ppc_init(void)
}
}
-void __init setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p)
+void __init setup_arch(char **cmdline_p)
{
extern int panic_timeout;
extern char _etext[], _edata[];
extern char *klimit;
- extern unsigned long find_available_memory(void);
- extern unsigned long *end_of_DRAM;
+ extern void do_init_bootmem(void);
#ifdef CONFIG_XMON
extern void xmon_map_scc(void);
@@ -556,22 +553,22 @@ void __init setup_arch(char **cmdline_p,
xmon(0);
#endif /* CONFIG_XMON */
- /* reboot on panic */
+ /* reboot on panic */
panic_timeout = 180;
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata;
- init_mm.brk = (unsigned long) klimit;
+ init_mm.brk = (unsigned long) klimit;
/* Save unparsed command line copy for /proc/cmdline */
strcpy(saved_command_line, cmd_line);
*cmdline_p = cmd_line;
- *memory_start_p = find_available_memory();
- *memory_end_p = (unsigned long) end_of_DRAM;
+ /* set up the bootmem stuff with available memory */
+ do_init_bootmem();
- ppc_md.setup_arch(memory_start_p, memory_end_p);
+ ppc_md.setup_arch();
/* clear the progress line */
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
}
diff --git a/arch/ppc/mbx_defconfig b/arch/ppc/mbx_defconfig
index 494717c54..7080efb3e 100644
--- a/arch/ppc/mbx_defconfig
+++ b/arch/ppc/mbx_defconfig
@@ -74,7 +74,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_VIA82C586 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_BLK_DEV_CMD646 is not set
CONFIG_BLK_DEV_SL82C105=y
# CONFIG_IDE_CHIPSETS is not set
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index eb158fb1e..240344314 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/openpic.h>
+#include <linux/bootmem.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h> /* for initrd_* */
#endif
@@ -59,6 +60,9 @@ int prom_trashed;
atomic_t next_mmu_context;
unsigned long *end_of_DRAM;
int mem_init_done;
+int init_bootmem_done;
+int boot_mapsize;
+unsigned long totalram_pages = 0;
extern pgd_t swapper_pg_dir[];
extern char _start[], _end[];
extern char etext[], _stext[];
@@ -108,9 +112,9 @@ struct mem_pieces {
};
struct mem_pieces phys_mem;
struct mem_pieces phys_avail;
-struct mem_pieces prom_mem;
static void remove_mem_piece(struct mem_pieces *, unsigned, unsigned, int);
+static void set_phys_avail(void);
void *find_mem_piece(unsigned, unsigned);
static void print_mem_pieces(struct mem_pieces *);
#if defined(CONFIG_PREP) || defined(CONFIG_APUS) || defined(CONFIG_ALL_PPC)
@@ -202,7 +206,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
pte = (pte_t *) MMU_get_page();
else if ((pte = (pte_t *) get_zero_page_fast()) == NULL)
if ((pte = (pte_t *) __get_free_page(GFP_KERNEL)))
- clear_page((unsigned long)pte);
+ clear_page(pte);
if (pte) {
pmd_val(*pmd) = (unsigned long)pte;
return pte + offset;
@@ -246,20 +250,20 @@ int do_check_pgt_cache(int low, int high)
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
-unsigned long empty_bad_page_table;
+pte_t *empty_bad_page_table;
pte_t * __bad_pagetable(void)
{
- __clear_user((void *)empty_bad_page_table, PAGE_SIZE);
- return (pte_t *) empty_bad_page_table;
+ clear_page(empty_bad_page_table);
+ return empty_bad_page_table;
}
-unsigned long empty_bad_page;
+void *empty_bad_page;
pte_t __bad_page(void)
{
- __clear_user((void *)empty_bad_page, PAGE_SIZE);
- return pte_mkdirty(mk_pte(empty_bad_page, PAGE_SHARED));
+ clear_page(empty_bad_page);
+ return pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED));
}
void show_mem(void)
@@ -289,6 +293,7 @@ void show_mem(void)
printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached);
printk("%d pages in page table cache\n",(int)pgtable_cache_size);
+ show_buffers();
#ifdef CONFIG_NET
show_net_buffers();
#endif
@@ -345,7 +350,7 @@ void si_meminfo(struct sysinfo *val)
val->totalram = 0;
val->sharedram = 0;
val->freeram = nr_free_pages << PAGE_SHIFT;
- val->bufferram = atomic_read(&buffermem);
+ val->bufferram = atomic_read(&buffermem_pages);
while (i-- > 0) {
if (PageReserved(mem_map+i))
continue;
@@ -590,6 +595,37 @@ mmu_context_overflow(void)
#endif /* CONFIG_8xx */
/*
+ * Set phys_avail to phys_mem less the kernel text/data/bss.
+ */
+static void __init set_phys_avail(void)
+{
+ unsigned long kstart, ksize;
+
+ /* we can't call the prom any more at this stage, so
+ all of memory is available (after klimit) */
+ phys_avail = phys_mem;
+
+ /*
+ * phys_avail records memory we can use.
+ * Make sure the kernel text/data/bss is not in it.
+ */
+ kstart = __pa(_stext); /* should be 0 */
+ ksize = PAGE_ALIGN(klimit - _stext);
+ remove_mem_piece(&phys_avail, kstart, ksize, 0);
+ remove_mem_piece(&phys_avail, 0, 0x4000, 0);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start) {
+ /*
+ * Remove the initialized ramdisk from the available memory.
+ */
+ remove_mem_piece(&phys_avail, __pa(initrd_start),
+ initrd_end - initrd_start, 1);
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+}
+
+/*
* Scan a region for a piece of a given size with the required alignment.
*/
void __init *find_mem_piece(unsigned size, unsigned align)
@@ -681,7 +717,7 @@ static void __init print_mem_pieces(struct mem_pieces *mp)
printk("\n");
}
-#if defined(CONFIG_PREP) || defined(CONFIG_APUS) || defined(CONFIG_PPC_ALL)
+#if defined(CONFIG_PREP) || defined(CONFIG_APUS) || defined(CONFIG_ALL_PPC)
/*
* Add some memory to an array of pieces
*/
@@ -833,8 +869,8 @@ static void __init mapin_ram(void)
{
int i;
unsigned long v, p, s, f;
-#ifndef CONFIG_8xx
+#ifndef CONFIG_8xx
if (!__map_without_bats) {
unsigned long tot, mem_base, bl, done;
unsigned long max_size = (256<<20);
@@ -869,24 +905,7 @@ static void __init mapin_ram(void)
RAM_PAGE);
}
}
- v = KERNELBASE;
- for (i = 0; i < phys_mem.n_regions; ++i) {
- p = phys_mem.regions[i].address;
- for (s = 0; s < phys_mem.regions[i].size; s += PAGE_SIZE) {
- f = _PAGE_PRESENT | _PAGE_ACCESSED;
- if ((char *) v < _stext || (char *) v >= etext)
- f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
- else
- /* On the powerpc, no user access
- forces R/W kernel access */
- f |= _PAGE_USER;
- map_page(v, p, f);
- v += PAGE_SIZE;
- p += PAGE_SIZE;
- }
- }
-
-#else /* CONFIG_8xx */
+#endif /* CONFIG_8xx */
for (i = 0; i < phys_mem.n_regions; ++i) {
v = (ulong)__va(phys_mem.regions[i].address);
@@ -896,37 +915,35 @@ static void __init mapin_ram(void)
* don't get ASID compares on kernel space.
*/
f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
-
- /* I don't really need the rest of this code, but
- * I grabbed it because I think the line:
- * f |= _PAGE_USER
- * is incorrect. It needs to be set to bits we
- * don't define to cause a kernel read-only. On
- * the MPC8xx, the PAGE_DIRTY takes care of that
- * for us (along with the RW software state).
- */
if ((char *) v < _stext || (char *) v >= etext)
f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
+#ifndef CONFIG_8xx
+ else
+ /* On the powerpc (not 8xx), no user access
+ forces R/W kernel access */
+ f |= _PAGE_USER;
+#endif /* CONFIG_8xx */
map_page(v, p, f);
v += PAGE_SIZE;
p += PAGE_SIZE;
}
- }
-#endif /* CONFIG_8xx */
+ }
}
-/* This can get called from ioremap, so don't make it an __init, OK? */
+/* In fact this is only called until mem_init is done. */
static void __init *MMU_get_page(void)
{
void *p;
if (mem_init_done) {
p = (void *) __get_free_page(GFP_KERNEL);
- if (p == 0)
- panic("couldn't get a page in MMU_get_page");
+ } else if (init_bootmem_done) {
+ p = alloc_bootmem_pages(PAGE_SIZE);
} else {
p = find_mem_piece(PAGE_SIZE, PAGE_SIZE);
}
+ if (p == 0)
+ panic("couldn't get a page in MMU_get_page");
__clear_user(p, PAGE_SIZE);
return p;
}
@@ -1106,6 +1123,51 @@ void __init MMU_init(void)
}
/*
+ * Initialize the bootmem system and give it all the memory we
+ * have available.
+ */
+void __init do_init_bootmem(void)
+{
+ unsigned long start, size;
+ int i;
+
+ /*
+ * Find an area to use for the bootmem bitmap.
+ * We look for the first area which is at least
+ * 128kB in length (128kB is enough for a bitmap
+ * for 4GB of memory, using 4kB pages), plus 1 page
+ * (in case the address isn't page-aligned).
+ */
+ start = 0;
+ size = 0;
+ for (i = 0; i < phys_avail.n_regions; ++i) {
+ unsigned long a = phys_avail.regions[i].address;
+ unsigned long s = phys_avail.regions[i].size;
+ if (s <= size)
+ continue;
+ start = a;
+ size = s;
+ if (s >= 33 * PAGE_SIZE)
+ break;
+ }
+ start = PAGE_ALIGN(start);
+
+ boot_mapsize = init_bootmem(start >> PAGE_SHIFT,
+ __pa(end_of_DRAM) >> PAGE_SHIFT);
+
+ /* remove the bootmem bitmap from the available memory */
+ remove_mem_piece(&phys_avail, start, start + boot_mapsize, 1);
+
+ /* add everything in phys_avail into the bootmem map */
+ for (i = 0; i < phys_avail.n_regions; ++i)
+ free_bootmem(phys_avail.regions[i].address,
+ phys_avail.regions[i].size);
+
+ init_bootmem_done = 1;
+}
+
+#if 0
+/*
* Find some memory for setup_arch to return.
* We use the largest chunk of available memory as the area
* that setup_arch returns, making sure that there are at
@@ -1143,97 +1205,56 @@ unsigned long __init find_available_memory(void)
avail_start = (unsigned long) __va(a);
return avail_start;
}
+#endif /* 0 */
/*
* paging_init() sets up the page tables - in fact we've already done this.
*/
-unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
+void __init paging_init(void)
{
- extern unsigned long free_area_init(unsigned long, unsigned long);
/*
* Grab some memory for bad_page and bad_pagetable to use.
*/
- empty_bad_page = PAGE_ALIGN(start_mem);
- empty_bad_page_table = empty_bad_page + PAGE_SIZE;
- start_mem = empty_bad_page + 2 * PAGE_SIZE;
-
- /* note: free_area_init uses its second argument
- to size the mem_map array. */
- start_mem = free_area_init(start_mem, end_mem);
- return start_mem;
+ empty_bad_page = alloc_bootmem_pages(PAGE_SIZE);
+ empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE);
+
+ free_area_init(max_low_pfn);
}
-void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+void __init mem_init(void)
{
unsigned long addr;
- int i;
- unsigned long a, lim;
int codepages = 0;
int datapages = 0;
int initpages = 0;
extern unsigned int rtas_data, rtas_size;
- end_mem &= PAGE_MASK;
- high_memory = (void *) end_mem;
- max_mapnr = MAP_NR(high_memory);
-
- /* mark usable pages in the mem_map[] */
- start_mem = PAGE_ALIGN(start_mem);
-
+ max_mapnr = max_low_pfn;
+ high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
num_physpages = max_mapnr; /* RAM is assumed contiguous */
- remove_mem_piece(&phys_avail, __pa(avail_start),
- start_mem - avail_start, 1);
- for (i = 0; i < phys_avail.n_regions; ++i) {
- a = (unsigned long) __va(phys_avail.regions[i].address);
- lim = (a + phys_avail.regions[i].size) & PAGE_MASK;
- a = PAGE_ALIGN(a);
- for (; a < lim; a += PAGE_SIZE)
- clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
- }
+ totalram_pages += free_all_bootmem();
#ifdef CONFIG_BLK_DEV_INITRD
/* if we are booted from BootX with an initial ramdisk,
make sure the ramdisk pages aren't reserved. */
if (initrd_start) {
- for (a = initrd_start; a < initrd_end; a += PAGE_SIZE)
- clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
+ for (addr = initrd_start; addr < initrd_end; addr += PAGE_SIZE)
+ clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags);
}
#endif /* CONFIG_BLK_DEV_INITRD */
- /* free the prom's memory - no-op on prep */
- for (i = 0; i < prom_mem.n_regions; ++i) {
- a = (unsigned long) __va(prom_mem.regions[i].address);
- lim = (a + prom_mem.regions[i].size) & PAGE_MASK;
- a = PAGE_ALIGN(a);
- for (; a < lim; a += PAGE_SIZE)
- clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
- }
-
- prom_trashed = 1;
-
- for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) {
- if (PageReserved(mem_map + MAP_NR(addr))) {
- if (addr < (ulong) etext)
- codepages++;
- else if (addr >= (unsigned long)&__init_begin
- && addr < (unsigned long)&__init_end)
- initpages++;
- else if (addr < (ulong) start_mem)
- datapages++;
+ for (addr = PAGE_OFFSET; addr < (unsigned long)end_of_DRAM;
+ addr += PAGE_SIZE) {
+ if (!PageReserved(mem_map + MAP_NR(addr)))
continue;
- }
- set_page_count(mem_map + MAP_NR(addr), 1);
-#ifdef CONFIG_BLK_DEV_INITRD
- if (!initrd_start ||
- addr < (initrd_start & PAGE_MASK) || addr >= initrd_end)
-#endif /* CONFIG_BLK_DEV_INITRD */
-#ifndef CONFIG_8xx
- if ( !rtas_data ||
- addr < (rtas_data & PAGE_MASK) ||
- addr >= (rtas_data+rtas_size))
-#endif /* CONFIG_8xx */
- free_page(addr);
+ if (addr < (ulong) etext)
+ codepages++;
+ else if (addr >= (unsigned long)&__init_begin
+ && addr < (unsigned long)&__init_end)
+ initpages++;
+ else if (addr < (ulong) klimit)
+ datapages++;
}
printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08x,%08lx]\n",
@@ -1241,7 +1262,7 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem)
codepages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10),
- PAGE_OFFSET, end_mem);
+ PAGE_OFFSET, (unsigned long) end_of_DRAM);
mem_init_done = 1;
}
@@ -1257,11 +1278,9 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem)
unsigned long __init *pmac_find_end_of_memory(void)
{
unsigned long a, total;
- unsigned long kstart, ksize;
- int i;
/* max amount of RAM we allow -- Cort */
-#define RAM_LIMIT (256<<20)
+#define RAM_LIMIT (768<<20)
memory_node = find_devices("memory");
if (memory_node == NULL) {
@@ -1309,32 +1328,8 @@ unsigned long __init *pmac_find_end_of_memory(void)
phys_mem.n_regions = 1;
}
- if (boot_infos == 0) {
- /* record which bits the prom is using */
- get_mem_prop("available", &phys_avail);
- prom_mem = phys_mem;
- for (i = 0; i < phys_avail.n_regions; ++i)
- remove_mem_piece(&prom_mem,
- phys_avail.regions[i].address,
- phys_avail.regions[i].size, 0);
- } else {
- /* booted from BootX - it's all available (after klimit) */
- phys_avail = phys_mem;
- prom_mem.n_regions = 0;
- }
+ set_phys_avail();
- /*
- * phys_avail records memory we can use now.
- * prom_mem records memory allocated by the prom that we
- * don't want to use now, but we'll reclaim later.
- * Make sure the kernel text/data/bss is in neither.
- */
- kstart = __pa(_stext); /* should be 0 */
- ksize = PAGE_ALIGN(klimit - _stext);
- remove_mem_piece(&phys_avail, kstart, ksize, 0);
- remove_mem_piece(&prom_mem, kstart, ksize, 0);
- remove_mem_piece(&phys_avail, 0, 0x4000, 0);
- remove_mem_piece(&prom_mem, 0, 0x4000, 0);
#undef RAM_LIMIT
return __va(total);
}
@@ -1349,7 +1344,6 @@ unsigned long __init *pmac_find_end_of_memory(void)
*/
unsigned long __init *prep_find_end_of_memory(void)
{
- unsigned long kstart, ksize;
unsigned long total;
total = res->TotalMemory;
@@ -1364,11 +1358,7 @@ unsigned long __init *prep_find_end_of_memory(void)
printk("Ramsize default to be %ldM\n", total>>20);
}
append_mem_piece(&phys_mem, 0, total);
- phys_avail = phys_mem;
- kstart = __pa(_stext); /* should be 0 */
- ksize = PAGE_ALIGN(klimit - _stext);
- remove_mem_piece(&phys_avail, kstart, ksize, 0);
- remove_mem_piece(&phys_avail, 0, 0x4000, 0);
+ set_phys_avail();
return (__va(total));
}
@@ -1378,7 +1368,7 @@ unsigned long __init *prep_find_end_of_memory(void)
#if defined(CONFIG_GEMINI)
unsigned long __init *gemini_find_end_of_memory(void)
{
- unsigned long total, kstart, ksize, *ret;
+ unsigned long total, *ret;
unsigned char reg;
reg = readb(GEMINI_MEMCFG);
@@ -1390,10 +1380,7 @@ unsigned long __init *gemini_find_end_of_memory(void)
phys_mem.n_regions = 1;
ret = __va(phys_mem.regions[0].size);
- phys_avail = phys_mem;
- kstart = __pa(_stext);
- ksize = PAGE_ALIGN( _end - _stext );
- remove_mem_piece( &phys_avail, kstart, ksize, 0 );
+ set_phys_avail();
return ret;
}
#endif /* defined(CONFIG_GEMINI) || defined(CONFIG_ALL_PPC) */
@@ -1429,15 +1416,8 @@ unsigned long __init *apus_find_end_of_memory(void)
}
/* Now register the memory block. */
- {
- unsigned long kstart, ksize;
-
- append_mem_piece(&phys_mem, memory[0].addr, memory[0].size);
- phys_avail = phys_mem;
- kstart = __pa(_stext);
- ksize = PAGE_ALIGN(klimit - _stext);
- remove_mem_piece(&phys_avail, kstart, ksize, 0);
- }
+ append_mem_piece(&phys_mem, memory[0].addr, memory[0].size);
+ set_phys_avail();
/* Remove the memory chunks that are controlled by special
Phase5 hardware. */
@@ -1586,7 +1566,6 @@ static void __init hash_init(void)
*/
unsigned long __init *m8xx_find_end_of_memory(void)
{
- unsigned long kstart, ksize;
bd_t *binfo;
unsigned long *ret;
extern unsigned char __res[];
@@ -1600,11 +1579,7 @@ unsigned long __init *m8xx_find_end_of_memory(void)
ret = __va(phys_mem.regions[0].address+
phys_mem.regions[0].size);
- phys_avail = phys_mem;
-
- kstart = __pa(_stext); /* should be 0 */
- ksize = PAGE_ALIGN(_end - _stext);
- remove_mem_piece(&phys_avail, kstart, ksize, 0);
+ set_phys_avail();
return ret;
}
#endif /* ndef CONFIG_8xx */