diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S index cafe454703b8..0cfa76fe6dfd 100644 --- a/arch/s390/boot/head.S +++ b/arch/s390/boot/head.S @@ -27,6 +27,7 @@ #include #include #include +#include #define ARCH_OFFSET 4 @@ -410,6 +411,6 @@ SYM_DATA_START(parmarea) SYM_DATA_END(parmarea) .org EARLY_SCCB_OFFSET - .fill 4096 + .fill EXT_SCCB_READ_SCP .org HEAD_END diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 5763769a39b6..3adbb417f740 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -8,8 +8,6 @@ #define _ASM_S390_SCLP_H #include -#include -#include #define SCLP_CHP_INFO_MASK_SIZE 32 #define EARLY_SCCB_SIZE PAGE_SIZE @@ -19,6 +17,10 @@ /* 24 + 16 * SCLP_MAX_CORES */ #define EXT_SCCB_READ_CPU (3 * PAGE_SIZE) +#ifndef __ASSEMBLY__ +#include +#include + struct sclp_chp_info { u8 recognized[SCLP_CHP_INFO_MASK_SIZE]; u8 standby[SCLP_CHP_INFO_MASK_SIZE]; @@ -147,4 +149,5 @@ static inline int sclp_get_core_info(struct sclp_core_info *info, int early) return _sclp_get_core_info(info); } +#endif /* __ASSEMBLY__ */ #endif /* _ASM_S390_SCLP_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 3a77aa96d092..cf285f57579f 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -7,6 +7,7 @@ #define _ASM_S390_SETUP_H #include +#include #include #include @@ -14,7 +15,7 @@ #define EP_STRING "S390EP" #define PARMAREA 0x10400 #define EARLY_SCCB_OFFSET 0x11000 -#define HEAD_END 0x12000 +#define HEAD_END (EARLY_SCCB_OFFSET + EXT_SCCB_READ_SCP) /* * Machine features detected in early.c diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index b7329af076a0..80ba6523e76e 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -235,11 +235,20 @@ void sclp_early_printk(const char *str) __sclp_early_printk(str, strlen(str)); } +/* + * We can't pass sclp_info_sccb to sclp_early_cmd() here directly, + * because it might not fulfil the requiremets for a SCLP communication buffer: + * - lie below 2G in memory + * - be page-aligned + * Therefore, we use the buffer sclp_early_sccb (which fulfils all those + * requirements) temporarily for communication and copy a received response + * back into the buffer sclp_info_sccb upon successful completion. + */ int __init sclp_early_read_info(void) { int i; int length = test_facility(140) ? EXT_SCCB_READ_SCP : PAGE_SIZE; - struct read_info_sccb *sccb = &sclp_info_sccb; + struct read_info_sccb *sccb = (struct read_info_sccb *)sclp_early_sccb; sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, SCLP_CMDW_READ_SCP_INFO}; @@ -251,6 +260,7 @@ int __init sclp_early_read_info(void) if (sclp_early_cmd(commands[i], sccb)) break; if (sccb->header.response_code == 0x10) { + memcpy(&sclp_info_sccb, sccb, length); sclp_info_sccb_valid = 1; return 0; }