Commit 05dd2530 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

[S390] sclp: introduce some new interfaces.

Introduce some new interfaces so that random subsystems don't have to
mess around with sclp internal structures.
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent bccdbdc9
...@@ -171,37 +171,6 @@ static inline int memory_fast_detect(void) ...@@ -171,37 +171,6 @@ static inline int memory_fast_detect(void)
} }
#endif #endif
#define ADDR2G (1UL << 31)
static noinline __init unsigned long sclp_memory_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;
}
static inline __init unsigned long __tprot(unsigned long addr) static inline __init unsigned long __tprot(unsigned long addr)
{ {
int cc = -1; int cc = -1;
...@@ -218,6 +187,7 @@ static inline __init unsigned long __tprot(unsigned long addr) ...@@ -218,6 +187,7 @@ static inline __init unsigned long __tprot(unsigned long addr)
/* Checking memory in 128KB increments. */ /* Checking memory in 128KB increments. */
#define CHUNK_INCR (1UL << 17) #define CHUNK_INCR (1UL << 17)
#define ADDR2G (1UL << 31)
static noinline __init void find_memory_chunks(unsigned long memsize) static noinline __init void find_memory_chunks(unsigned long memsize)
{ {
...@@ -293,7 +263,7 @@ static noinline __init void setup_lowcore_early(void) ...@@ -293,7 +263,7 @@ static noinline __init void setup_lowcore_early(void)
*/ */
void __init startup_init(void) void __init startup_init(void)
{ {
unsigned long memsize; unsigned long long memsize;
ipl_save_parameters(); ipl_save_parameters();
clear_bss_section(); clear_bss_section();
...@@ -306,7 +276,15 @@ void __init startup_init(void) ...@@ -306,7 +276,15 @@ void __init startup_init(void)
setup_lowcore_early(); setup_lowcore_early();
sclp_readinfo_early(); sclp_readinfo_early();
memsize = sclp_memory_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) if (memory_fast_detect() < 0)
find_memory_chunks(memsize); find_memory_chunks((unsigned long) memsize);
lockdep_on(); lockdep_on();
} }
...@@ -25,10 +25,6 @@ ...@@ -25,10 +25,6 @@
#define IPL_PARM_BLOCK_VERSION 0 #define IPL_PARM_BLOCK_VERSION 0
#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
#define SCCB_FLAG (s390_readinfo_sccb.flags)
#define IPL_UNKNOWN_STR "unknown" #define IPL_UNKNOWN_STR "unknown"
#define IPL_CCW_STR "ccw" #define IPL_CCW_STR "ccw"
#define IPL_FCP_STR "fcp" #define IPL_FCP_STR "fcp"
...@@ -146,6 +142,8 @@ static struct ipl_parameter_block *dump_block_ccw; ...@@ -146,6 +142,8 @@ static struct ipl_parameter_block *dump_block_ccw;
static enum shutdown_action on_panic_action = SHUTDOWN_STOP; static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
static struct sclp_ipl_info sclp_ipl_info;
int diag308(unsigned long subcode, void *addr) int diag308(unsigned long subcode, void *addr)
{ {
register unsigned long _addr asm("0") = (unsigned long) addr; register unsigned long _addr asm("0") = (unsigned long) addr;
...@@ -375,9 +373,9 @@ static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page) ...@@ -375,9 +373,9 @@ static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page)
{ {
char loadparm[LOADPARM_LEN + 1] = {}; char loadparm[LOADPARM_LEN + 1] = {};
if (!SCCB_VALID) if (!sclp_ipl_info.is_valid)
return sprintf(page, "#unknown#\n"); return sprintf(page, "#unknown#\n");
memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN); memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
EBCASC(loadparm, LOADPARM_LEN); EBCASC(loadparm, LOADPARM_LEN);
strstrip(loadparm); strstrip(loadparm);
return sprintf(page, "%s\n", loadparm); return sprintf(page, "%s\n", loadparm);
...@@ -910,9 +908,9 @@ static int __init reipl_ccw_init(void) ...@@ -910,9 +908,9 @@ static int __init reipl_ccw_init(void)
reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
/* check if read scp info worked and set loadparm */ /* check if read scp info worked and set loadparm */
if (SCCB_VALID) if (sclp_ipl_info.is_valid)
memcpy(reipl_block_ccw->ipl_info.ccw.load_param, memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
SCCB_LOADPARM, LOADPARM_LEN); &sclp_ipl_info.loadparm, LOADPARM_LEN);
else else
/* read scp info failed: set empty loadparm (EBCDIC blanks) */ /* read scp info failed: set empty loadparm (EBCDIC blanks) */
memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
...@@ -1007,7 +1005,7 @@ static int __init dump_fcp_init(void) ...@@ -1007,7 +1005,7 @@ static int __init dump_fcp_init(void)
{ {
int rc; int rc;
if(!(SCCB_FLAG & 0x2) || !SCCB_VALID) if (!sclp_ipl_info.has_dump)
return 0; /* LDIPL DUMP is not installed */ return 0; /* LDIPL DUMP is not installed */
if (!diag308_set_works) if (!diag308_set_works)
return 0; return 0;
...@@ -1088,6 +1086,7 @@ static int __init s390_ipl_init(void) ...@@ -1088,6 +1086,7 @@ static int __init s390_ipl_init(void)
{ {
int rc; int rc;
sclp_get_ipl_info(&sclp_ipl_info);
reipl_probe(); reipl_probe();
rc = ipl_init(); rc = ipl_init();
if (rc) if (rc)
......
...@@ -72,6 +72,13 @@ typedef unsigned int sclp_cmdw_t; ...@@ -72,6 +72,13 @@ typedef unsigned int sclp_cmdw_t;
typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
struct sccb_header {
u16 length;
u8 function_code;
u8 control_mask[3];
u16 response_code;
} __attribute__((packed));
struct gds_subvector { struct gds_subvector {
u8 length; u8 length;
u8 key; u8 key;
......
...@@ -11,47 +11,97 @@ ...@@ -11,47 +11,97 @@
#include <asm/sclp.h> #include <asm/sclp.h>
#include "sclp.h" #include "sclp.h"
struct sclp_readinfo_sccb s390_readinfo_sccb; struct sclp_readinfo_sccb {
struct sccb_header header; /* 0-7 */
u16 rnmax; /* 8-9 */
u8 rnsize; /* 10 */
u8 _reserved0[24 - 11]; /* 11-23 */
u8 loadparm[8]; /* 24-31 */
u8 _reserved1[48 - 32]; /* 32-47 */
u64 facilities; /* 48-55 */
u8 _reserved2[91 - 56]; /* 56-90 */
u8 flags; /* 91 */
u8 _reserved3[100 - 92]; /* 92-99 */
u32 rnsize2; /* 100-103 */
u64 rnmax2; /* 104-111 */
u8 _reserved4[4096 - 112]; /* 112-4095 */
} __attribute__((packed, aligned(4096)));
static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
static int __initdata early_readinfo_sccb_valid;
void __init sclp_readinfo_early(void) void __init sclp_readinfo_early(void)
{ {
sclp_cmdw_t command;
struct sccb_header *sccb;
int ret; int ret;
int i;
struct sclp_readinfo_sccb *sccb;
sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
SCLP_CMDW_READ_SCP_INFO};
__ctl_set_bit(0, 9); /* enable service signal subclass mask */ /* Enable service signal subclass mask. */
__ctl_set_bit(0, 9);
sccb = &s390_readinfo_sccb.header; sccb = &early_readinfo_sccb;
command = SCLP_CMDW_READ_SCP_INFO_FORCED; for (i = 0; i < ARRAY_SIZE(commands); i++) {
while (1) { do {
u16 response; memset(sccb, 0, sizeof(*sccb));
sccb->header.length = sizeof(*sccb);
memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb)); sccb->header.control_mask[2] = 0x80;
sccb->length = sizeof(s390_readinfo_sccb); ret = sclp_service_call(commands[i], sccb);
sccb->control_mask[2] = 0x80; } while (ret == -EBUSY);
ret = sclp_service_call(command, &s390_readinfo_sccb);
if (ret == -EIO)
goto out;
if (ret == -EBUSY)
continue;
if (ret)
break;
__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
PSW_MASK_WAIT | PSW_DEFAULT_KEY); PSW_MASK_WAIT | PSW_DEFAULT_KEY);
local_irq_disable(); local_irq_disable();
/*
* Contents of the sccb might have changed
* therefore a barrier is needed.
*/
barrier(); barrier();
if (sccb->header.response_code == 0x10) {
early_readinfo_sccb_valid = 1;
break;
}
if (sccb->header.response_code != 0x1f0)
break;
}
/* Disable service signal subclass mask again. */
__ctl_clear_bit(0, 9);
}
response = sccb->response_code; unsigned long long __init sclp_memory_detect(void)
{
unsigned long long memsize;
struct sclp_readinfo_sccb *sccb;
if (response == 0x10) if (!early_readinfo_sccb_valid)
break; return 0;
sccb = &early_readinfo_sccb;
if (sccb->rnsize)
memsize = sccb->rnsize << 20;
else
memsize = sccb->rnsize2 << 20;
if (sccb->rnmax)
memsize *= sccb->rnmax;
else
memsize *= sccb->rnmax2;
return memsize;
}
if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO) /*
break; * This function will be called after sclp_memory_detect(), which gets called
* early from early.c code. Therefore the sccb should have valid contents.
*/
void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
{
struct sclp_readinfo_sccb *sccb;
command = SCLP_CMDW_READ_SCP_INFO; if (!early_readinfo_sccb_valid)
} return;
out: sccb = &early_readinfo_sccb;
__ctl_clear_bit(0, 9); /* disable service signal subclass mask */ info->is_valid = 1;
if (sccb->flags & 0x2)
info->has_dump = 1;
memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
} }
...@@ -11,29 +11,6 @@ ...@@ -11,29 +11,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <asm/chpid.h> #include <asm/chpid.h>
struct sccb_header {
u16 length;
u8 function_code;
u8 control_mask[3];
u16 response_code;
} __attribute__((packed));
#define LOADPARM_LEN 8
struct sclp_readinfo_sccb {
struct sccb_header header; /* 0-7 */
u16 rnmax; /* 8-9 */
u8 rnsize; /* 10 */
u8 _reserved0[24 - 11]; /* 11-23 */
u8 loadparm[LOADPARM_LEN]; /* 24-31 */
u8 _reserved1[91 - 32]; /* 32-90 */
u8 flags; /* 91 */
u8 _reserved2[100 - 92]; /* 92-99 */
u32 rnsize2; /* 100-103 */
u64 rnmax2; /* 104-111 */
u8 _reserved3[4096 - 112]; /* 112-4095 */
} __attribute__((packed, aligned(4096)));
#define SCLP_CHP_INFO_MASK_SIZE 32 #define SCLP_CHP_INFO_MASK_SIZE 32
struct sclp_chp_info { struct sclp_chp_info {
...@@ -42,12 +19,21 @@ struct sclp_chp_info { ...@@ -42,12 +19,21 @@ struct sclp_chp_info {
u8 configured[SCLP_CHP_INFO_MASK_SIZE]; u8 configured[SCLP_CHP_INFO_MASK_SIZE];
}; };
extern struct sclp_readinfo_sccb s390_readinfo_sccb; #define LOADPARM_LEN 8
extern void sclp_readinfo_early(void);
extern int sclp_sdias_blk_count(void); struct sclp_ipl_info {
extern int sclp_sdias_copy(void *dest, int blk_num, int nr_blks); int is_valid;
extern int sclp_chp_configure(struct chp_id chpid); int has_dump;
extern int sclp_chp_deconfigure(struct chp_id chpid); char loadparm[LOADPARM_LEN];
extern int sclp_chp_read_info(struct sclp_chp_info *info); };
void sclp_readinfo_early(void);
unsigned long long sclp_memory_detect(void);
int sclp_sdias_blk_count(void);
int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
int sclp_chp_configure(struct chp_id chpid);
int sclp_chp_deconfigure(struct chp_id chpid);
int sclp_chp_read_info(struct sclp_chp_info *info);
void sclp_get_ipl_info(struct sclp_ipl_info *info);
#endif /* _ASM_S390_SCLP_H */ #endif /* _ASM_S390_SCLP_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment