]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/platforms/iseries/setup.c
powerpc: iSeries build fixes
[karo-tx-linux.git] / arch / powerpc / platforms / iseries / setup.c
index ad78c8581a5ab512a11c9f2247bf69558b54447d..da26639190dbf5807333d184b8ae0a7051d449f1 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/kdev_t.h>
 #include <linux/major.h>
 #include <linux/root_dev.h>
+#include <linux/kernel.h>
 
 #include <asm/processor.h>
 #include <asm/machdep.h>
 #include <asm/sections.h>
 #include <asm/iommu.h>
 #include <asm/firmware.h>
-
+#include <asm/system.h>
 #include <asm/time.h>
-#include <asm/naca.h>
 #include <asm/paca.h>
 #include <asm/cache.h>
 #include <asm/sections.h>
 #include <asm/abs_addr.h>
-#include <asm/iSeries/HvCallHpt.h>
-#include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/HvCallEvent.h>
-#include <asm/iSeries/HvCallSm.h>
-#include <asm/iSeries/HvCallXm.h>
-#include <asm/iSeries/ItLpQueue.h>
-#include <asm/iSeries/IoHriMainStore.h>
-#include <asm/iSeries/mf.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/iSeries_irq.h>
-#include <asm/iSeries/IoHriProcessorVpd.h>
-#include <asm/iSeries/ItVpdAreas.h>
-#include <asm/iSeries/LparMap.h>
-
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call_event.h>
+#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/it_lp_queue.h>
+#include <asm/iseries/mf.h>
+#include <asm/iseries/hv_lp_event.h>
+#include <asm/iseries/lpar_map.h>
+
+#include "naca.h"
 #include "setup.h"
+#include "irq.h"
+#include "vpd_areas.h"
+#include "processor_vpd.h"
+#include "main_store.h"
+#include "call_sm.h"
+#include "call_hpt.h"
 
 extern void hvlog(char *fmt, ...);
 
@@ -70,11 +71,9 @@ extern void hvlog(char *fmt, ...);
 #endif
 
 /* Function Prototypes */
-extern void ppcdbg_initialize(void);
-
-static void build_iSeries_Memory_Map(void);
-static int iseries_shared_idle(void);
-static int iseries_dedicated_idle(void);
+static unsigned long build_iSeries_Memory_Map(void);
+static void iseries_shared_idle(void);
+static void iseries_dedicated_idle(void);
 #ifdef CONFIG_PCI
 extern void iSeries_pci_final_fixup(void);
 #else
@@ -85,7 +84,6 @@ static void iSeries_pci_final_fixup(void) { }
 int piranha_simulator;
 
 extern int rd_size;            /* Defined in drivers/block/rd.c */
-extern unsigned long klimit;
 extern unsigned long embedded_sysmap_start;
 extern unsigned long embedded_sysmap_end;
 
@@ -94,6 +92,8 @@ extern unsigned long iSeries_recal_titan;
 
 static int mf_initialized;
 
+static unsigned long cmd_mem_limit;
+
 struct MemoryBlock {
        unsigned long absStart;
        unsigned long absEnd;
@@ -302,14 +302,10 @@ static void __init iSeries_get_cmdline(void)
 
 static void __init iSeries_init_early(void)
 {
-       extern unsigned long memory_limit;
-
        DBG(" -> iSeries_init_early()\n");
 
        ppc64_firmware_features = FW_FEATURE_ISERIES;
 
-       ppcdbg_initialize();
-
        ppc64_interrupt_controller = IC_ISERIES;
 
 #if defined(CONFIG_BLK_DEV_INITRD)
@@ -319,11 +315,11 @@ static void __init iSeries_init_early(void)
         */
        if (naca.xRamDisk) {
                initrd_start = (unsigned long)__va(naca.xRamDisk);
-               initrd_end = initrd_start + naca.xRamDiskSize * PAGE_SIZE;
+               initrd_end = initrd_start + naca.xRamDiskSize * HW_PAGE_SIZE;
                initrd_below_start_ok = 1;      // ramdisk in kernel space
                ROOT_DEV = Root_RAM0;
-               if (((rd_size * 1024) / PAGE_SIZE) < naca.xRamDiskSize)
-                       rd_size = (naca.xRamDiskSize * PAGE_SIZE) / 1024;
+               if (((rd_size * 1024) / HW_PAGE_SIZE) < naca.xRamDiskSize)
+                       rd_size = (naca.xRamDiskSize * HW_PAGE_SIZE) / 1024;
        } else
 #endif /* CONFIG_BLK_DEV_INITRD */
        {
@@ -343,23 +339,6 @@ static void __init iSeries_init_early(void)
         */
        iommu_init_early_iSeries();
 
-       iSeries_get_cmdline();
-
-       /* Save unparsed command line copy for /proc/cmdline */
-       strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-
-       /* Parse early parameters, in particular mem=x */
-       parse_early_param();
-
-       if (memory_limit) {
-               if (memory_limit < systemcfg->physicalMemorySize)
-                       systemcfg->physicalMemorySize = memory_limit;
-               else {
-                       printk("Ignoring mem=%lu >= ram_top.\n", memory_limit);
-                       memory_limit = 0;
-               }
-       }
-
        /* Initialize machine-dependency vectors */
 #ifdef CONFIG_SMP
        smp_init_iSeries();
@@ -423,14 +402,15 @@ void mschunks_alloc(unsigned long num_chunks)
  * a table used to translate Linux's physical addresses to these
  * absolute addresses.  Absolute addresses are needed when
  * communicating with the hypervisor (e.g. to build HPT entries)
+ *
+ * Returns the physical memory size
  */
 
-static void __init build_iSeries_Memory_Map(void)
+static unsigned long __init build_iSeries_Memory_Map(void)
 {
        u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize;
        u32 nextPhysChunk;
        u32 hptFirstChunk, hptLastChunk, hptSizeChunks, hptSizePages;
-       u32 num_ptegs;
        u32 totalChunks,moreChunks;
        u32 currChunk, thisChunk, absChunk;
        u32 currDword;
@@ -487,16 +467,14 @@ static void __init build_iSeries_Memory_Map(void)
         */
        hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress());
        hptSizePages = (u32)HvCallHpt_getHptPages();
-       hptSizeChunks = hptSizePages >> (MSCHUNKS_CHUNK_SHIFT - PAGE_SHIFT);
+       hptSizeChunks = hptSizePages >>
+               (MSCHUNKS_CHUNK_SHIFT - HW_PAGE_SHIFT);
        hptLastChunk = hptFirstChunk + hptSizeChunks - 1;
 
        printk("HPT absolute addr = %016lx, size = %dK\n",
                        chunk_to_addr(hptFirstChunk), hptSizeChunks * 256);
 
-       /* Fill in the hashed page table hash mask */
-       num_ptegs = hptSizePages *
-               (PAGE_SIZE / (sizeof(hpte_t) * HPTES_PER_GROUP));
-       htab_hash_mask = num_ptegs - 1;
+       ppc64_pft_size = __ilog2(hptSizePages * HW_PAGE_SIZE);
 
        /*
         * The actual hashed page table is in the hypervisor,
@@ -561,7 +539,7 @@ static void __init build_iSeries_Memory_Map(void)
         * which should be equal to
         *   nextPhysChunk
         */
-       systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
+       return chunk_to_addr(nextPhysChunk);
 }
 
 /*
@@ -569,8 +547,6 @@ static void __init build_iSeries_Memory_Map(void)
  */
 static void __init iSeries_setup_arch(void)
 {
-       unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
-
        if (get_paca()->lppaca.shared_proc) {
                ppc_md.idle_loop = iseries_shared_idle;
                printk(KERN_INFO "Using shared processor idle loop\n");
@@ -586,12 +562,9 @@ static void __init iSeries_setup_arch(void)
                        itVpdAreas.xSlicMaxLogicalProcs);
        printk("Max physical processors = %d\n",
                        itVpdAreas.xSlicMaxPhysicalProcs);
-
-       systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR;
-       printk("Processor version = %x\n", systemcfg->processor);
 }
 
-static void iSeries_get_cpuinfo(struct seq_file *m)
+static void iSeries_show_cpuinfo(struct seq_file *m)
 {
        seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
 }
@@ -649,7 +622,7 @@ static void __init iSeries_fixup_klimit(void)
         */
        if (naca.xRamDisk)
                klimit = KERNELBASE + (u64)naca.xRamDisk +
-                       (naca.xRamDiskSize * PAGE_SIZE);
+                       (naca.xRamDiskSize * HW_PAGE_SIZE);
        else {
                /*
                 * No ram disk was included - check and see if there
@@ -697,7 +670,7 @@ static void yield_shared_processor(void)
        process_iSeries_events();
 }
 
-static int iseries_shared_idle(void)
+static void iseries_shared_idle(void)
 {
        while (1) {
                while (!need_resched() && !hvlpevent_is_pending()) {
@@ -717,22 +690,18 @@ static int iseries_shared_idle(void)
                if (hvlpevent_is_pending())
                        process_iSeries_events();
 
+               preempt_enable_no_resched();
                schedule();
+               preempt_disable();
        }
-
-       return 0;
 }
 
-static int iseries_dedicated_idle(void)
+static void iseries_dedicated_idle(void)
 {
-       long oldval;
+       set_thread_flag(TIF_POLLING_NRFLAG);
 
        while (1) {
-               oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
-
-               if (!oldval) {
-                       set_thread_flag(TIF_POLLING_NRFLAG);
-
+               if (!need_resched()) {
                        while (!need_resched()) {
                                ppc64_runlatch_off();
                                HMT_low();
@@ -745,16 +714,13 @@ static int iseries_dedicated_idle(void)
                        }
 
                        HMT_medium();
-                       clear_thread_flag(TIF_POLLING_NRFLAG);
-               } else {
-                       set_need_resched();
                }
 
                ppc64_runlatch_on();
+               preempt_enable_no_resched();
                schedule();
+               preempt_disable();
        }
-
-       return 0;
 }
 
 #ifndef CONFIG_PCI
@@ -768,7 +734,7 @@ static int __init iseries_probe(int platform)
 
 struct machdep_calls __initdata iseries_md = {
        .setup_arch     = iSeries_setup_arch,
-       .get_cpuinfo    = iSeries_get_cpuinfo,
+       .show_cpuinfo   = iSeries_show_cpuinfo,
        .init_IRQ       = iSeries_init_IRQ,
        .get_irq        = iSeries_get_irq,
        .init_early     = iSeries_init_early,
@@ -958,7 +924,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
        dt_end_node(dt);
 }
 
-void build_flat_dt(struct iseries_flat_dt *dt)
+void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
 {
        u64 tmp[2];
 
@@ -974,13 +940,15 @@ void build_flat_dt(struct iseries_flat_dt *dt)
        dt_prop_str(dt, "name", "memory");
        dt_prop_str(dt, "device_type", "memory");
        tmp[0] = 0;
-       tmp[1] = systemcfg->physicalMemorySize;
+       tmp[1] = phys_mem_size;
        dt_prop_u64_list(dt, "reg", tmp, 2);
        dt_end_node(dt);
 
        /* /chosen */
        dt_start_node(dt, "chosen");
        dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
+       if (cmd_mem_limit)
+               dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
        dt_end_node(dt);
 
        dt_cpus(dt);
@@ -992,15 +960,37 @@ void build_flat_dt(struct iseries_flat_dt *dt)
 
 void * __init iSeries_early_setup(void)
 {
+       unsigned long phys_mem_size;
+
        iSeries_fixup_klimit();
 
        /*
         * Initialize the table which translate Linux physical addresses to
         * AS/400 absolute addresses
         */
-       build_iSeries_Memory_Map();
+       phys_mem_size = build_iSeries_Memory_Map();
+
+       iSeries_get_cmdline();
+
+       /* Save unparsed command line copy for /proc/cmdline */
+       strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
 
-       build_flat_dt(&iseries_dt);
+       /* Parse early parameters, in particular mem=x */
+       parse_early_param();
+
+       build_flat_dt(&iseries_dt, phys_mem_size);
 
        return (void *) __pa(&iseries_dt);
 }
+
+/*
+ * On iSeries we just parse the mem=X option from the command line.
+ * On pSeries it's a bit more complicated, see prom_init_mem()
+ */
+static int __init early_parsemem(char *p)
+{
+       if (p)
+               cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
+       return 0;
+}
+early_param("mem", early_parsemem);