]> err.no Git - linux-2.6/blobdiff - arch/s390/kernel/early.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[linux-2.6] / arch / s390 / kernel / early.c
index e518dd53eff52408f0b7427d181efd4715145e75..540a67f979b64820e4b45319451b1e3897ebb0e0 100644 (file)
 #include <linux/module.h>
 #include <linux/pfn.h>
 #include <linux/uaccess.h>
+#include <asm/ipl.h>
 #include <asm/lowcore.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/cpcmd.h>
 #include <asm/sclp.h>
+#include "entry.h"
 
 /*
  * Create a Kernel NSS if the SAVESYS= parameter is defined
@@ -87,13 +89,17 @@ static noinline __init void create_kernel_nss(void)
 
        __cpcmd(defsys_cmd, NULL, 0, &response);
 
-       if (response != 0)
+       if (response != 0) {
+               kernel_nss_name[0] = '\0';
                return;
+       }
 
        __cpcmd(savesys_cmd, NULL, 0, &response);
 
-       if (response != strlen(savesys_cmd))
+       if (response != strlen(savesys_cmd)) {
+               kernel_nss_name[0] = '\0';
                return;
+       }
 
        ipl_flags = IPL_NSS_VALID;
 }
@@ -109,7 +115,7 @@ static inline void create_kernel_nss(void) { }
  */
 static noinline __init void clear_bss_section(void)
 {
-       memset(__bss_start, 0, _end - __bss_start);
+       memset(__bss_start, 0, __bss_stop - __bss_start);
 }
 
 /*
@@ -129,7 +135,7 @@ static noinline __init void detect_machine_type(void)
 {
        struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
 
-       asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
+       get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
 
        /* Running under z/VM ? */
        if (cpuinfo->cpu_id.version == 0xff)
@@ -140,9 +146,9 @@ static noinline __init void detect_machine_type(void)
                machine_flags |= 4;
 }
 
+#ifdef CONFIG_64BIT
 static noinline __init int memory_fast_detect(void)
 {
-
        unsigned long val0 = 0;
        unsigned long val1 = 0xc;
        int ret = -ENOSYS;
@@ -160,40 +166,15 @@ static noinline __init int memory_fast_detect(void)
        if (ret || val0 != val1)
                return -ENOSYS;
 
-       memory_chunk[0].size = val0;
+       memory_chunk[0].size = val0 + 1;
        return 0;
 }
-
-#define ADDR2G (1UL << 31)
-
-static noinline __init unsigned long sclp_memory_detect(void)
+#else
+static inline int memory_fast_detect(void)
 {
-       struct sclp_readinfo_sccb *sccb;
-       unsigned long long memsize;
-
-       sccb = &s390_readinfo_sccb;
-
-       if (sccb->header.response_code != 0x10)
-               return 0;
-
-       if (sccb->rnsize)
-               memsize = sccb->rnsize << 20;
-       else
-               memsize = sccb->rnsize2 << 20;
-       if (sccb->rnmax)
-               memsize *= sccb->rnmax;
-       else
-               memsize *= sccb->rnmax2;
-#ifndef CONFIG_64BIT
-       /*
-        * Can't deal with more than 2G in 31 bit addressing mode, so
-        * limit the value in order to avoid strange side effects.
-        */
-       if (memsize > ADDR2G)
-               memsize = ADDR2G;
-#endif
-       return (unsigned long) memsize;
+       return -ENOSYS;
 }
+#endif
 
 static inline __init unsigned long __tprot(unsigned long addr)
 {
@@ -211,6 +192,7 @@ static inline __init unsigned long __tprot(unsigned long addr)
 
 /* Checking memory in 128KB increments. */
 #define CHUNK_INCR     (1UL << 17)
+#define ADDR2G         (1UL << 31)
 
 static noinline __init void find_memory_chunks(unsigned long memsize)
 {
@@ -223,11 +205,13 @@ static noinline __init void find_memory_chunks(unsigned long memsize)
                cc = __tprot(addr);
                while (cc == old_cc) {
                        addr += CHUNK_INCR;
-                       cc = __tprot(addr);
+                       if (memsize && addr >= memsize)
+                               break;
 #ifndef CONFIG_64BIT
                        if (addr == ADDR2G)
                                break;
 #endif
+                       cc = __tprot(addr);
                }
 
                if (old_addr != addr &&
@@ -246,11 +230,10 @@ static noinline __init void find_memory_chunks(unsigned long memsize)
                        break;
 #endif
                /*
-                * Finish memory detection at the first hole, unless
-                * - we reached the hsa -> skip it.
-                * - we know there must be more.
+                * Finish memory detection at the first hole
+                * if storage size is unknown.
                 */
-               if (cc == -1UL && !memsize && old_addr != ADDR2G)
+               if (cc == -1UL && !memsize)
                        break;
                if (memsize && addr >= memsize)
                        break;
@@ -287,7 +270,7 @@ static noinline __init void setup_lowcore_early(void)
  */
 void __init startup_init(void)
 {
-       unsigned long memsize;
+       unsigned long long memsize;
 
        ipl_save_parameters();
        clear_bss_section();
@@ -298,9 +281,18 @@ void __init startup_init(void)
        create_kernel_nss();
        sort_main_extable();
        setup_lowcore_early();
-       sclp_readinfo_early();
+       sclp_read_info_early();
+       sclp_facilities_detect();
        memsize = sclp_memory_detect();
+#ifndef CONFIG_64BIT
+       /*
+        * Can't deal with more than 2G in 31 bit addressing mode, so
+        * limit the value in order to avoid strange side effects.
+        */
+       if (memsize > ADDR2G)
+               memsize = ADDR2G;
+#endif
        if (memory_fast_detect() < 0)
-               find_memory_chunks(memsize);
+               find_memory_chunks((unsigned long) memsize);
        lockdep_on();
 }