diff options
author | Sumanth Korikkar <sumanthk@linux.ibm.com> | 2020-11-07 22:55:51 -0600 |
---|---|---|
committer | Heiko Carstens <hca@linux.ibm.com> | 2020-11-18 12:16:02 +0100 |
commit | 08ab919d0dccc4ed6fb12231b20758cef112bd26 (patch) | |
tree | 3f987b8902bb7f210f847bb3b4d95e8c62a4b1c4 /drivers/s390/char | |
parent | da78693e6e496ccd5cb6b0e9025007803e8f93c2 (diff) |
s390/sclp: use memblock for early read cpu info
sclp early read cpu info is used to detect the number of configured
cpus, which is utilized by smp_detect_cpus() in early startup.
* For read cpu info, the sccb block should be below 2gb.
* smp_detect_cpus() utilizes read cpu info early, but after memblock
initialization. Thus use memblock_allow_low() instead.
* Avoid copy of sclp_core_info structure.
* sclp_early_init_core_info(), sclp_early_core_info and
sclp_early_core_info_valid initdata are no longer required.
* smp_get_core_info() is called only once during early stage. Hence for
early sclp_get_core_info(), directly call read cpu command. No need to
maintain sclp_early_core_info_valid.
Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Reviewed-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'drivers/s390/char')
-rw-r--r-- | drivers/s390/char/sclp_early.c | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index cc5e84b80c69..62e0d35ea1a7 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -9,9 +9,11 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/errno.h> +#include <linux/memblock.h> #include <asm/ctl_reg.h> #include <asm/sclp.h> #include <asm/ipl.h> +#include <asm/setup.h> #include "sclp_sdias.h" #include "sclp.h" @@ -107,29 +109,34 @@ void __init sclp_early_get_ipl_info(struct sclp_ipl_info *info) *info = sclp_ipl_info; } -static struct sclp_core_info sclp_early_core_info __initdata; -static int sclp_early_core_info_valid __initdata; - -static void __init sclp_early_init_core_info(struct read_cpu_info_sccb *sccb) -{ - if (!SCLP_HAS_CPU_INFO) - return; - memset(sccb, 0, sizeof(*sccb)); - sccb->header.length = sizeof(*sccb); - if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO, sccb)) - return; - if (sccb->header.response_code != 0x0010) - return; - sclp_fill_core_info(&sclp_early_core_info, sccb); - sclp_early_core_info_valid = 1; -} - int __init sclp_early_get_core_info(struct sclp_core_info *info) { - if (!sclp_early_core_info_valid) - return -EIO; - *info = sclp_early_core_info; - return 0; + struct read_cpu_info_sccb *sccb; + int length = PAGE_SIZE; + int rc = 0; + + if (!SCLP_HAS_CPU_INFO) + return -EOPNOTSUPP; + + sccb = memblock_alloc_low(length, PAGE_SIZE); + if (!sccb) + return -ENOMEM; + + memset(sccb, 0, length); + sccb->header.length = length; + sccb->header.control_mask[2] = 0x80; + if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO, sccb)) { + rc = -EIO; + goto out; + } + if (sccb->header.response_code != 0x0010) { + rc = -EIO; + goto out; + } + sclp_fill_core_info(info, sccb); +out: + memblock_free_early((unsigned long)sccb, length); + return rc; } static void __init sclp_early_console_detect(struct init_sccb *sccb) @@ -149,7 +156,6 @@ void __init sclp_early_detect(void) void *sccb = sclp_early_sccb; sclp_early_facilities_detect(sccb); - sclp_early_init_core_info(sccb); /* * Turn off SCLP event notifications. Also save remote masks in the |