aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2007-07-10 05:24:09 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-07-10 05:24:42 -0400
commit05dd25307ca67cbfa0207bbba2e6c79fa97d125b (patch)
tree4601c5732e71883bffab31a4a786f838e8473f58
parentbccdbdc9bd7db3a32c14d8a47f1fb66e3de3c92f (diff)
[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: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/kernel/early.c44
-rw-r--r--arch/s390/kernel/ipl.c17
-rw-r--r--drivers/s390/char/sclp.h7
-rw-r--r--drivers/s390/char/sclp_info.c108
-rw-r--r--include/asm-s390/sclp.h46
5 files changed, 121 insertions, 101 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 50538e545618..9fcf3f1f47b6 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -171,37 +171,6 @@ static inline int memory_fast_detect(void)
171} 171}
172#endif 172#endif
173 173
174#define ADDR2G (1UL << 31)
175
176static noinline __init unsigned long sclp_memory_detect(void)
177{
178 struct sclp_readinfo_sccb *sccb;
179 unsigned long long memsize;
180
181 sccb = &s390_readinfo_sccb;
182
183 if (sccb->header.response_code != 0x10)
184 return 0;
185
186 if (sccb->rnsize)
187 memsize = sccb->rnsize << 20;
188 else
189 memsize = sccb->rnsize2 << 20;
190 if (sccb->rnmax)
191 memsize *= sccb->rnmax;
192 else
193 memsize *= sccb->rnmax2;
194#ifndef CONFIG_64BIT
195 /*
196 * Can't deal with more than 2G in 31 bit addressing mode, so
197 * limit the value in order to avoid strange side effects.
198 */
199 if (memsize > ADDR2G)
200 memsize = ADDR2G;
201#endif
202 return (unsigned long) memsize;
203}
204
205static inline __init unsigned long __tprot(unsigned long addr) 174static inline __init unsigned long __tprot(unsigned long addr)
206{ 175{
207 int cc = -1; 176 int cc = -1;
@@ -218,6 +187,7 @@ static inline __init unsigned long __tprot(unsigned long addr)
218 187
219/* Checking memory in 128KB increments. */ 188/* Checking memory in 128KB increments. */
220#define CHUNK_INCR (1UL << 17) 189#define CHUNK_INCR (1UL << 17)
190#define ADDR2G (1UL << 31)
221 191
222static noinline __init void find_memory_chunks(unsigned long memsize) 192static noinline __init void find_memory_chunks(unsigned long memsize)
223{ 193{
@@ -293,7 +263,7 @@ static noinline __init void setup_lowcore_early(void)
293 */ 263 */
294void __init startup_init(void) 264void __init startup_init(void)
295{ 265{
296 unsigned long memsize; 266 unsigned long long memsize;
297 267
298 ipl_save_parameters(); 268 ipl_save_parameters();
299 clear_bss_section(); 269 clear_bss_section();
@@ -306,7 +276,15 @@ void __init startup_init(void)
306 setup_lowcore_early(); 276 setup_lowcore_early();
307 sclp_readinfo_early(); 277 sclp_readinfo_early();
308 memsize = sclp_memory_detect(); 278 memsize = sclp_memory_detect();
279#ifndef CONFIG_64BIT
280 /*
281 * Can't deal with more than 2G in 31 bit addressing mode, so
282 * limit the value in order to avoid strange side effects.
283 */
284 if (memsize > ADDR2G)
285 memsize = ADDR2G;
286#endif
309 if (memory_fast_detect() < 0) 287 if (memory_fast_detect() < 0)
310 find_memory_chunks(memsize); 288 find_memory_chunks((unsigned long) memsize);
311 lockdep_on(); 289 lockdep_on();
312} 290}
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 367caf92ea78..82b131ddd7ff 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -25,10 +25,6 @@
25 25
26#define IPL_PARM_BLOCK_VERSION 0 26#define IPL_PARM_BLOCK_VERSION 0
27 27
28#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
29#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
30#define SCCB_FLAG (s390_readinfo_sccb.flags)
31
32#define IPL_UNKNOWN_STR "unknown" 28#define IPL_UNKNOWN_STR "unknown"
33#define IPL_CCW_STR "ccw" 29#define IPL_CCW_STR "ccw"
34#define IPL_FCP_STR "fcp" 30#define IPL_FCP_STR "fcp"
@@ -146,6 +142,8 @@ static struct ipl_parameter_block *dump_block_ccw;
146 142
147static enum shutdown_action on_panic_action = SHUTDOWN_STOP; 143static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
148 144
145static struct sclp_ipl_info sclp_ipl_info;
146
149int diag308(unsigned long subcode, void *addr) 147int diag308(unsigned long subcode, void *addr)
150{ 148{
151 register unsigned long _addr asm("0") = (unsigned long) addr; 149 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{ 373{
376 char loadparm[LOADPARM_LEN + 1] = {}; 374 char loadparm[LOADPARM_LEN + 1] = {};
377 375
378 if (!SCCB_VALID) 376 if (!sclp_ipl_info.is_valid)
379 return sprintf(page, "#unknown#\n"); 377 return sprintf(page, "#unknown#\n");
380 memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN); 378 memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
381 EBCASC(loadparm, LOADPARM_LEN); 379 EBCASC(loadparm, LOADPARM_LEN);
382 strstrip(loadparm); 380 strstrip(loadparm);
383 return sprintf(page, "%s\n", loadparm); 381 return sprintf(page, "%s\n", loadparm);
@@ -910,9 +908,9 @@ static int __init reipl_ccw_init(void)
910 reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; 908 reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
911 reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; 909 reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
912 /* check if read scp info worked and set loadparm */ 910 /* check if read scp info worked and set loadparm */
913 if (SCCB_VALID) 911 if (sclp_ipl_info.is_valid)
914 memcpy(reipl_block_ccw->ipl_info.ccw.load_param, 912 memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
915 SCCB_LOADPARM, LOADPARM_LEN); 913 &sclp_ipl_info.loadparm, LOADPARM_LEN);
916 else 914 else
917 /* read scp info failed: set empty loadparm (EBCDIC blanks) */ 915 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
918 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, 916 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
@@ -1007,7 +1005,7 @@ static int __init dump_fcp_init(void)
1007{ 1005{
1008 int rc; 1006 int rc;
1009 1007
1010 if(!(SCCB_FLAG & 0x2) || !SCCB_VALID) 1008 if (!sclp_ipl_info.has_dump)
1011 return 0; /* LDIPL DUMP is not installed */ 1009 return 0; /* LDIPL DUMP is not installed */
1012 if (!diag308_set_works) 1010 if (!diag308_set_works)
1013 return 0; 1011 return 0;
@@ -1088,6 +1086,7 @@ static int __init s390_ipl_init(void)
1088{ 1086{
1089 int rc; 1087 int rc;
1090 1088
1089 sclp_get_ipl_info(&sclp_ipl_info);
1091 reipl_probe(); 1090 reipl_probe();
1092 rc = ipl_init(); 1091 rc = ipl_init();
1093 if (rc) 1092 if (rc)
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index dbb99d1b6f57..cb5888f79007 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -72,6 +72,13 @@ typedef unsigned int sclp_cmdw_t;
72 72
73typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ 73typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
74 74
75struct sccb_header {
76 u16 length;
77 u8 function_code;
78 u8 control_mask[3];
79 u16 response_code;
80} __attribute__((packed));
81
75struct gds_subvector { 82struct gds_subvector {
76 u8 length; 83 u8 length;
77 u8 key; 84 u8 key;
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
index 7bcbe643b087..7d21dbb12fcd 100644
--- a/drivers/s390/char/sclp_info.c
+++ b/drivers/s390/char/sclp_info.c
@@ -11,47 +11,97 @@
11#include <asm/sclp.h> 11#include <asm/sclp.h>
12#include "sclp.h" 12#include "sclp.h"
13 13
14struct sclp_readinfo_sccb s390_readinfo_sccb; 14struct sclp_readinfo_sccb {
15 struct sccb_header header; /* 0-7 */
16 u16 rnmax; /* 8-9 */
17 u8 rnsize; /* 10 */
18 u8 _reserved0[24 - 11]; /* 11-23 */
19 u8 loadparm[8]; /* 24-31 */
20 u8 _reserved1[48 - 32]; /* 32-47 */
21 u64 facilities; /* 48-55 */
22 u8 _reserved2[91 - 56]; /* 56-90 */
23 u8 flags; /* 91 */
24 u8 _reserved3[100 - 92]; /* 92-99 */
25 u32 rnsize2; /* 100-103 */
26 u64 rnmax2; /* 104-111 */
27 u8 _reserved4[4096 - 112]; /* 112-4095 */
28} __attribute__((packed, aligned(4096)));
29
30static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
31static int __initdata early_readinfo_sccb_valid;
15 32
16void __init sclp_readinfo_early(void) 33void __init sclp_readinfo_early(void)
17{ 34{
18 sclp_cmdw_t command;
19 struct sccb_header *sccb;
20 int ret; 35 int ret;
36 int i;
37 struct sclp_readinfo_sccb *sccb;
38 sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
39 SCLP_CMDW_READ_SCP_INFO};
21 40
22 __ctl_set_bit(0, 9); /* enable service signal subclass mask */ 41 /* Enable service signal subclass mask. */
23 42 __ctl_set_bit(0, 9);
24 sccb = &s390_readinfo_sccb.header; 43 sccb = &early_readinfo_sccb;
25 command = SCLP_CMDW_READ_SCP_INFO_FORCED; 44 for (i = 0; i < ARRAY_SIZE(commands); i++) {
26 while (1) { 45 do {
27 u16 response; 46 memset(sccb, 0, sizeof(*sccb));
28 47 sccb->header.length = sizeof(*sccb);
29 memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb)); 48 sccb->header.control_mask[2] = 0x80;
30 sccb->length = sizeof(s390_readinfo_sccb); 49 ret = sclp_service_call(commands[i], sccb);
31 sccb->control_mask[2] = 0x80; 50 } while (ret == -EBUSY);
32
33 ret = sclp_service_call(command, &s390_readinfo_sccb);
34
35 if (ret == -EIO)
36 goto out;
37 if (ret == -EBUSY)
38 continue;
39 51
52 if (ret)
53 break;
40 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | 54 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
41 PSW_MASK_WAIT | PSW_DEFAULT_KEY); 55 PSW_MASK_WAIT | PSW_DEFAULT_KEY);
42 local_irq_disable(); 56 local_irq_disable();
57 /*
58 * Contents of the sccb might have changed
59 * therefore a barrier is needed.
60 */
43 barrier(); 61 barrier();
62 if (sccb->header.response_code == 0x10) {
63 early_readinfo_sccb_valid = 1;
64 break;
65 }
66 if (sccb->header.response_code != 0x1f0)
67 break;
68 }
69 /* Disable service signal subclass mask again. */
70 __ctl_clear_bit(0, 9);
71}
44 72
45 response = sccb->response_code; 73unsigned long long __init sclp_memory_detect(void)
74{
75 unsigned long long memsize;
76 struct sclp_readinfo_sccb *sccb;
46 77
47 if (response == 0x10) 78 if (!early_readinfo_sccb_valid)
48 break; 79 return 0;
80 sccb = &early_readinfo_sccb;
81 if (sccb->rnsize)
82 memsize = sccb->rnsize << 20;
83 else
84 memsize = sccb->rnsize2 << 20;
85 if (sccb->rnmax)
86 memsize *= sccb->rnmax;
87 else
88 memsize *= sccb->rnmax2;
89 return memsize;
90}
49 91
50 if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO) 92/*
51 break; 93 * This function will be called after sclp_memory_detect(), which gets called
94 * early from early.c code. Therefore the sccb should have valid contents.
95 */
96void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
97{
98 struct sclp_readinfo_sccb *sccb;
52 99
53 command = SCLP_CMDW_READ_SCP_INFO; 100 if (!early_readinfo_sccb_valid)
54 } 101 return;
55out: 102 sccb = &early_readinfo_sccb;
56 __ctl_clear_bit(0, 9); /* disable service signal subclass mask */ 103 info->is_valid = 1;
104 if (sccb->flags & 0x2)
105 info->has_dump = 1;
106 memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
57} 107}
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h
index 21ed64773210..ddfaa8db47be 100644
--- a/include/asm-s390/sclp.h
+++ b/include/asm-s390/sclp.h
@@ -11,29 +11,6 @@
11#include <linux/types.h> 11#include <linux/types.h>
12#include <asm/chpid.h> 12#include <asm/chpid.h>
13 13
14struct sccb_header {
15 u16 length;
16 u8 function_code;
17 u8 control_mask[3];
18 u16 response_code;
19} __attribute__((packed));
20
21#define LOADPARM_LEN 8
22
23struct sclp_readinfo_sccb {
24 struct sccb_header header; /* 0-7 */
25 u16 rnmax; /* 8-9 */
26 u8 rnsize; /* 10 */
27 u8 _reserved0[24 - 11]; /* 11-23 */
28 u8 loadparm[LOADPARM_LEN]; /* 24-31 */
29 u8 _reserved1[91 - 32]; /* 32-90 */
30 u8 flags; /* 91 */
31 u8 _reserved2[100 - 92]; /* 92-99 */
32 u32 rnsize2; /* 100-103 */
33 u64 rnmax2; /* 104-111 */
34 u8 _reserved3[4096 - 112]; /* 112-4095 */
35} __attribute__((packed, aligned(4096)));
36
37#define SCLP_CHP_INFO_MASK_SIZE 32 14#define SCLP_CHP_INFO_MASK_SIZE 32
38 15
39struct sclp_chp_info { 16struct sclp_chp_info {
@@ -42,12 +19,21 @@ struct sclp_chp_info {
42 u8 configured[SCLP_CHP_INFO_MASK_SIZE]; 19 u8 configured[SCLP_CHP_INFO_MASK_SIZE];
43}; 20};
44 21
45extern struct sclp_readinfo_sccb s390_readinfo_sccb; 22#define LOADPARM_LEN 8
46extern void sclp_readinfo_early(void); 23
47extern int sclp_sdias_blk_count(void); 24struct sclp_ipl_info {
48extern int sclp_sdias_copy(void *dest, int blk_num, int nr_blks); 25 int is_valid;
49extern int sclp_chp_configure(struct chp_id chpid); 26 int has_dump;
50extern int sclp_chp_deconfigure(struct chp_id chpid); 27 char loadparm[LOADPARM_LEN];
51extern int sclp_chp_read_info(struct sclp_chp_info *info); 28};
29
30void sclp_readinfo_early(void);
31unsigned long long sclp_memory_detect(void);
32int sclp_sdias_blk_count(void);
33int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
34int sclp_chp_configure(struct chp_id chpid);
35int sclp_chp_deconfigure(struct chp_id chpid);
36int sclp_chp_read_info(struct sclp_chp_info *info);
37void sclp_get_ipl_info(struct sclp_ipl_info *info);
52 38
53#endif /* _ASM_S390_SCLP_H */ 39#endif /* _ASM_S390_SCLP_H */