diff options
| author | Michael Holzheu <holzheu@linux.vnet.ibm.com> | 2013-11-13 04:38:27 -0500 |
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-11-15 08:08:41 -0500 |
| commit | acf6a004e6a35dad17032e3b7c5a046c29957e65 (patch) | |
| tree | 377fb42d62773abbb2bbddecdfff8b8e3eb8f3f8 /drivers | |
| parent | e657d8fe2faf49ed5d35e2325bd0f1712b8058cd (diff) | |
s390/sclp: Move early code from sclp_cmd.c to sclp_early.c
The early SCLP driver code in sclp_cmd.c belongs to sclp_early.c
because it is independent from the 'normal' SCLP driver. So move
it to sclp_early.c
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/s390/char/sclp.h | 6 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_cmd.c | 180 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_early.c | 162 |
3 files changed, 176 insertions, 172 deletions
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 9cb8076f66c4..6fbe09686d18 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
| @@ -99,6 +99,7 @@ struct init_sccb { | |||
| 99 | } __attribute__((packed)); | 99 | } __attribute__((packed)); |
| 100 | 100 | ||
| 101 | extern u64 sclp_facilities; | 101 | extern u64 sclp_facilities; |
| 102 | |||
| 102 | #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) | 103 | #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) |
| 103 | #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) | 104 | #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) |
| 104 | #define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL) | 105 | #define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL) |
| @@ -172,7 +173,6 @@ int sclp_deactivate(void); | |||
| 172 | int sclp_reactivate(void); | 173 | int sclp_reactivate(void); |
| 173 | int sclp_service_call(sclp_cmdw_t command, void *sccb); | 174 | int sclp_service_call(sclp_cmdw_t command, void *sccb); |
| 174 | int sclp_sync_request(sclp_cmdw_t command, void *sccb); | 175 | int sclp_sync_request(sclp_cmdw_t command, void *sccb); |
| 175 | int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb); | ||
| 176 | 176 | ||
| 177 | int sclp_sdias_init(void); | 177 | int sclp_sdias_init(void); |
| 178 | void sclp_sdias_exit(void); | 178 | void sclp_sdias_exit(void); |
| @@ -180,6 +180,10 @@ void sclp_sdias_exit(void); | |||
| 180 | extern int sclp_console_pages; | 180 | extern int sclp_console_pages; |
| 181 | extern int sclp_console_drop; | 181 | extern int sclp_console_drop; |
| 182 | extern unsigned long sclp_console_full; | 182 | extern unsigned long sclp_console_full; |
| 183 | extern u8 sclp_fac84; | ||
| 184 | extern unsigned long long sclp_rzm; | ||
| 185 | extern unsigned long long sclp_rnmax; | ||
| 186 | extern __initdata int sclp_early_read_info_sccb_valid; | ||
| 183 | 187 | ||
| 184 | /* useful inlines */ | 188 | /* useful inlines */ |
| 185 | 189 | ||
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 5bbe6db988b9..eaa21d542c5c 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
| @@ -28,168 +28,6 @@ | |||
| 28 | 28 | ||
| 29 | #include "sclp.h" | 29 | #include "sclp.h" |
| 30 | 30 | ||
| 31 | #define SCLP_CMDW_READ_SCP_INFO 0x00020001 | ||
| 32 | #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 | ||
| 33 | |||
| 34 | struct read_info_sccb { | ||
| 35 | struct sccb_header header; /* 0-7 */ | ||
| 36 | u16 rnmax; /* 8-9 */ | ||
| 37 | u8 rnsize; /* 10 */ | ||
| 38 | u8 _reserved0[24 - 11]; /* 11-15 */ | ||
| 39 | u8 loadparm[8]; /* 24-31 */ | ||
| 40 | u8 _reserved1[48 - 32]; /* 32-47 */ | ||
| 41 | u64 facilities; /* 48-55 */ | ||
| 42 | u8 _reserved2[84 - 56]; /* 56-83 */ | ||
| 43 | u8 fac84; /* 84 */ | ||
| 44 | u8 fac85; /* 85 */ | ||
| 45 | u8 _reserved3[91 - 86]; /* 86-90 */ | ||
| 46 | u8 flags; /* 91 */ | ||
| 47 | u8 _reserved4[100 - 92]; /* 92-99 */ | ||
| 48 | u32 rnsize2; /* 100-103 */ | ||
| 49 | u64 rnmax2; /* 104-111 */ | ||
| 50 | u8 _reserved5[4096 - 112]; /* 112-4095 */ | ||
| 51 | } __attribute__((packed, aligned(PAGE_SIZE))); | ||
| 52 | |||
| 53 | static struct init_sccb __initdata early_event_mask_sccb __aligned(PAGE_SIZE); | ||
| 54 | static struct read_info_sccb __initdata early_read_info_sccb; | ||
| 55 | static int __initdata early_read_info_sccb_valid; | ||
| 56 | |||
| 57 | u64 sclp_facilities; | ||
| 58 | static u8 sclp_fac84; | ||
| 59 | static unsigned long long rzm; | ||
| 60 | static unsigned long long rnmax; | ||
| 61 | |||
| 62 | int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) | ||
| 63 | { | ||
| 64 | int rc; | ||
| 65 | |||
| 66 | __ctl_set_bit(0, 9); | ||
| 67 | rc = sclp_service_call(cmd, sccb); | ||
| 68 | if (rc) | ||
| 69 | goto out; | ||
| 70 | __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | | ||
| 71 | PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT); | ||
| 72 | local_irq_disable(); | ||
| 73 | out: | ||
| 74 | /* Contents of the sccb might have changed. */ | ||
| 75 | barrier(); | ||
| 76 | __ctl_clear_bit(0, 9); | ||
| 77 | return rc; | ||
| 78 | } | ||
| 79 | |||
| 80 | static void __init sclp_read_info_early(void) | ||
| 81 | { | ||
| 82 | int rc; | ||
| 83 | int i; | ||
| 84 | struct read_info_sccb *sccb; | ||
| 85 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, | ||
| 86 | SCLP_CMDW_READ_SCP_INFO}; | ||
| 87 | |||
| 88 | sccb = &early_read_info_sccb; | ||
| 89 | for (i = 0; i < ARRAY_SIZE(commands); i++) { | ||
| 90 | do { | ||
| 91 | memset(sccb, 0, sizeof(*sccb)); | ||
| 92 | sccb->header.length = sizeof(*sccb); | ||
| 93 | sccb->header.function_code = 0x80; | ||
| 94 | sccb->header.control_mask[2] = 0x80; | ||
| 95 | rc = sclp_cmd_sync_early(commands[i], sccb); | ||
| 96 | } while (rc == -EBUSY); | ||
| 97 | |||
| 98 | if (rc) | ||
| 99 | break; | ||
| 100 | if (sccb->header.response_code == 0x10) { | ||
| 101 | early_read_info_sccb_valid = 1; | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | if (sccb->header.response_code != 0x1f0) | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | static void __init sclp_event_mask_early(void) | ||
| 110 | { | ||
| 111 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
| 112 | int rc; | ||
| 113 | |||
| 114 | do { | ||
| 115 | memset(sccb, 0, sizeof(*sccb)); | ||
| 116 | sccb->header.length = sizeof(*sccb); | ||
| 117 | sccb->mask_length = sizeof(sccb_mask_t); | ||
| 118 | rc = sclp_cmd_sync_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); | ||
| 119 | } while (rc == -EBUSY); | ||
| 120 | } | ||
| 121 | |||
| 122 | void __init sclp_facilities_detect(void) | ||
| 123 | { | ||
| 124 | struct read_info_sccb *sccb; | ||
| 125 | |||
| 126 | sclp_read_info_early(); | ||
| 127 | if (!early_read_info_sccb_valid) | ||
| 128 | return; | ||
| 129 | |||
| 130 | sccb = &early_read_info_sccb; | ||
| 131 | sclp_facilities = sccb->facilities; | ||
| 132 | sclp_fac84 = sccb->fac84; | ||
| 133 | if (sccb->fac85 & 0x02) | ||
| 134 | S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; | ||
| 135 | rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; | ||
| 136 | rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; | ||
| 137 | rzm <<= 20; | ||
| 138 | |||
| 139 | sclp_event_mask_early(); | ||
| 140 | } | ||
| 141 | |||
| 142 | bool __init sclp_has_linemode(void) | ||
| 143 | { | ||
| 144 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
| 145 | |||
| 146 | if (sccb->header.response_code != 0x20) | ||
| 147 | return 0; | ||
| 148 | if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) | ||
| 149 | return 0; | ||
| 150 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
| 151 | return 0; | ||
| 152 | return 1; | ||
| 153 | } | ||
| 154 | |||
| 155 | bool __init sclp_has_vt220(void) | ||
| 156 | { | ||
| 157 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
| 158 | |||
| 159 | if (sccb->header.response_code != 0x20) | ||
| 160 | return 0; | ||
| 161 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) | ||
| 162 | return 1; | ||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | unsigned long long sclp_get_rnmax(void) | ||
| 167 | { | ||
| 168 | return rnmax; | ||
| 169 | } | ||
| 170 | |||
| 171 | unsigned long long sclp_get_rzm(void) | ||
| 172 | { | ||
| 173 | return rzm; | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * This function will be called after sclp_facilities_detect(), which gets | ||
| 178 | * called from early.c code. Therefore the sccb should have valid contents. | ||
| 179 | */ | ||
| 180 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) | ||
| 181 | { | ||
| 182 | struct read_info_sccb *sccb; | ||
| 183 | |||
| 184 | if (!early_read_info_sccb_valid) | ||
| 185 | return; | ||
| 186 | sccb = &early_read_info_sccb; | ||
| 187 | info->is_valid = 1; | ||
| 188 | if (sccb->flags & 0x2) | ||
| 189 | info->has_dump = 1; | ||
| 190 | memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); | ||
| 191 | } | ||
| 192 | |||
| 193 | static void sclp_sync_callback(struct sclp_req *req, void *data) | 31 | static void sclp_sync_callback(struct sclp_req *req, void *data) |
| 194 | { | 32 | { |
| 195 | struct completion *completion = data; | 33 | struct completion *completion = data; |
| @@ -356,14 +194,14 @@ struct assign_storage_sccb { | |||
| 356 | 194 | ||
| 357 | int arch_get_memory_phys_device(unsigned long start_pfn) | 195 | int arch_get_memory_phys_device(unsigned long start_pfn) |
| 358 | { | 196 | { |
| 359 | if (!rzm) | 197 | if (!sclp_rzm) |
| 360 | return 0; | 198 | return 0; |
| 361 | return PFN_PHYS(start_pfn) >> ilog2(rzm); | 199 | return PFN_PHYS(start_pfn) >> ilog2(sclp_rzm); |
| 362 | } | 200 | } |
| 363 | 201 | ||
| 364 | static unsigned long long rn2addr(u16 rn) | 202 | static unsigned long long rn2addr(u16 rn) |
| 365 | { | 203 | { |
| 366 | return (unsigned long long) (rn - 1) * rzm; | 204 | return (unsigned long long) (rn - 1) * sclp_rzm; |
| 367 | } | 205 | } |
| 368 | 206 | ||
| 369 | static int do_assign_storage(sclp_cmdw_t cmd, u16 rn) | 207 | static int do_assign_storage(sclp_cmdw_t cmd, u16 rn) |
| @@ -404,7 +242,7 @@ static int sclp_assign_storage(u16 rn) | |||
| 404 | if (rc) | 242 | if (rc) |
| 405 | return rc; | 243 | return rc; |
| 406 | start = rn2addr(rn); | 244 | start = rn2addr(rn); |
| 407 | storage_key_init_range(start, start + rzm); | 245 | storage_key_init_range(start, start + sclp_rzm); |
| 408 | return 0; | 246 | return 0; |
| 409 | } | 247 | } |
| 410 | 248 | ||
| @@ -462,7 +300,7 @@ static int sclp_mem_change_state(unsigned long start, unsigned long size, | |||
| 462 | istart = rn2addr(incr->rn); | 300 | istart = rn2addr(incr->rn); |
| 463 | if (start + size - 1 < istart) | 301 | if (start + size - 1 < istart) |
| 464 | break; | 302 | break; |
| 465 | if (start > istart + rzm - 1) | 303 | if (start > istart + sclp_rzm - 1) |
| 466 | continue; | 304 | continue; |
| 467 | if (online) | 305 | if (online) |
| 468 | rc |= sclp_assign_storage(incr->rn); | 306 | rc |= sclp_assign_storage(incr->rn); |
| @@ -526,7 +364,7 @@ static void __init add_memory_merged(u16 rn) | |||
| 526 | if (!first_rn) | 364 | if (!first_rn) |
| 527 | goto skip_add; | 365 | goto skip_add; |
| 528 | start = rn2addr(first_rn); | 366 | start = rn2addr(first_rn); |
| 529 | size = (unsigned long long ) num * rzm; | 367 | size = (unsigned long long) num * sclp_rzm; |
| 530 | if (start >= VMEM_MAX_PHYS) | 368 | if (start >= VMEM_MAX_PHYS) |
| 531 | goto skip_add; | 369 | goto skip_add; |
| 532 | if (start + size > VMEM_MAX_PHYS) | 370 | if (start + size > VMEM_MAX_PHYS) |
| @@ -574,7 +412,7 @@ static void __init insert_increment(u16 rn, int standby, int assigned) | |||
| 574 | } | 412 | } |
| 575 | if (!assigned) | 413 | if (!assigned) |
| 576 | new_incr->rn = last_rn + 1; | 414 | new_incr->rn = last_rn + 1; |
| 577 | if (new_incr->rn > rnmax) { | 415 | if (new_incr->rn > sclp_rnmax) { |
| 578 | kfree(new_incr); | 416 | kfree(new_incr); |
| 579 | return; | 417 | return; |
| 580 | } | 418 | } |
| @@ -617,7 +455,7 @@ static int __init sclp_detect_standby_memory(void) | |||
| 617 | 455 | ||
| 618 | if (OLDMEM_BASE) /* No standby memory in kdump mode */ | 456 | if (OLDMEM_BASE) /* No standby memory in kdump mode */ |
| 619 | return 0; | 457 | return 0; |
| 620 | if (!early_read_info_sccb_valid) | 458 | if (!sclp_early_read_info_sccb_valid) |
| 621 | return 0; | 459 | return 0; |
| 622 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) | 460 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) |
| 623 | return 0; | 461 | return 0; |
| @@ -661,7 +499,7 @@ static int __init sclp_detect_standby_memory(void) | |||
| 661 | } | 499 | } |
| 662 | if (rc || list_empty(&sclp_mem_list)) | 500 | if (rc || list_empty(&sclp_mem_list)) |
| 663 | goto out; | 501 | goto out; |
| 664 | for (i = 1; i <= rnmax - assigned; i++) | 502 | for (i = 1; i <= sclp_rnmax - assigned; i++) |
| 665 | insert_increment(0, 1, 0); | 503 | insert_increment(0, 1, 0); |
| 666 | rc = register_memory_notifier(&sclp_mem_nb); | 504 | rc = register_memory_notifier(&sclp_mem_nb); |
| 667 | if (rc) | 505 | if (rc) |
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index 775112964eef..cbec45fdcc59 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c | |||
| @@ -7,14 +7,176 @@ | |||
| 7 | #define KMSG_COMPONENT "sclp_early" | 7 | #define KMSG_COMPONENT "sclp_early" |
| 8 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 8 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
| 9 | 9 | ||
| 10 | #include <asm/ctl_reg.h> | ||
| 10 | #include <asm/sclp.h> | 11 | #include <asm/sclp.h> |
| 11 | #include <asm/ipl.h> | 12 | #include <asm/ipl.h> |
| 12 | #include "sclp_sdias.h" | 13 | #include "sclp_sdias.h" |
| 13 | #include "sclp.h" | 14 | #include "sclp.h" |
| 14 | 15 | ||
| 16 | #define SCLP_CMDW_READ_SCP_INFO 0x00020001 | ||
| 17 | #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 | ||
| 18 | |||
| 19 | struct read_info_sccb { | ||
| 20 | struct sccb_header header; /* 0-7 */ | ||
| 21 | u16 rnmax; /* 8-9 */ | ||
| 22 | u8 rnsize; /* 10 */ | ||
| 23 | u8 _reserved0[24 - 11]; /* 11-15 */ | ||
| 24 | u8 loadparm[8]; /* 24-31 */ | ||
| 25 | u8 _reserved1[48 - 32]; /* 32-47 */ | ||
| 26 | u64 facilities; /* 48-55 */ | ||
| 27 | u8 _reserved2[84 - 56]; /* 56-83 */ | ||
| 28 | u8 fac84; /* 84 */ | ||
| 29 | u8 fac85; /* 85 */ | ||
| 30 | u8 _reserved3[91 - 86]; /* 86-90 */ | ||
| 31 | u8 flags; /* 91 */ | ||
| 32 | u8 _reserved4[100 - 92]; /* 92-99 */ | ||
| 33 | u32 rnsize2; /* 100-103 */ | ||
| 34 | u64 rnmax2; /* 104-111 */ | ||
| 35 | u8 _reserved5[4096 - 112]; /* 112-4095 */ | ||
| 36 | } __packed __aligned(PAGE_SIZE); | ||
| 37 | |||
| 38 | static __initdata struct init_sccb early_event_mask_sccb __aligned(PAGE_SIZE); | ||
| 39 | static __initdata struct read_info_sccb early_read_info_sccb; | ||
| 15 | static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); | 40 | static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); |
| 16 | static unsigned long sclp_hsa_size; | 41 | static unsigned long sclp_hsa_size; |
| 17 | 42 | ||
| 43 | __initdata int sclp_early_read_info_sccb_valid; | ||
| 44 | u64 sclp_facilities; | ||
| 45 | u8 sclp_fac84; | ||
| 46 | unsigned long long sclp_rzm; | ||
| 47 | unsigned long long sclp_rnmax; | ||
| 48 | |||
| 49 | static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) | ||
| 50 | { | ||
| 51 | int rc; | ||
| 52 | |||
| 53 | __ctl_set_bit(0, 9); | ||
| 54 | rc = sclp_service_call(cmd, sccb); | ||
| 55 | if (rc) | ||
| 56 | goto out; | ||
| 57 | __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | | ||
| 58 | PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT); | ||
| 59 | local_irq_disable(); | ||
| 60 | out: | ||
| 61 | /* Contents of the sccb might have changed. */ | ||
| 62 | barrier(); | ||
| 63 | __ctl_clear_bit(0, 9); | ||
| 64 | return rc; | ||
| 65 | } | ||
| 66 | |||
| 67 | static void __init sclp_read_info_early(void) | ||
| 68 | { | ||
| 69 | int rc; | ||
| 70 | int i; | ||
| 71 | struct read_info_sccb *sccb; | ||
| 72 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, | ||
| 73 | SCLP_CMDW_READ_SCP_INFO}; | ||
| 74 | |||
| 75 | sccb = &early_read_info_sccb; | ||
| 76 | for (i = 0; i < ARRAY_SIZE(commands); i++) { | ||
| 77 | do { | ||
| 78 | memset(sccb, 0, sizeof(*sccb)); | ||
| 79 | sccb->header.length = sizeof(*sccb); | ||
| 80 | sccb->header.function_code = 0x80; | ||
| 81 | sccb->header.control_mask[2] = 0x80; | ||
| 82 | rc = sclp_cmd_sync_early(commands[i], sccb); | ||
| 83 | } while (rc == -EBUSY); | ||
| 84 | |||
| 85 | if (rc) | ||
| 86 | break; | ||
| 87 | if (sccb->header.response_code == 0x10) { | ||
| 88 | sclp_early_read_info_sccb_valid = 1; | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | if (sccb->header.response_code != 0x1f0) | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | static void __init sclp_event_mask_early(void) | ||
| 97 | { | ||
| 98 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
| 99 | int rc; | ||
| 100 | |||
| 101 | do { | ||
| 102 | memset(sccb, 0, sizeof(*sccb)); | ||
| 103 | sccb->header.length = sizeof(*sccb); | ||
| 104 | sccb->mask_length = sizeof(sccb_mask_t); | ||
| 105 | rc = sclp_cmd_sync_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); | ||
| 106 | } while (rc == -EBUSY); | ||
| 107 | } | ||
| 108 | |||
| 109 | void __init sclp_facilities_detect(void) | ||
| 110 | { | ||
| 111 | struct read_info_sccb *sccb; | ||
| 112 | |||
| 113 | sclp_read_info_early(); | ||
| 114 | if (!sclp_early_read_info_sccb_valid) | ||
| 115 | return; | ||
| 116 | |||
| 117 | sccb = &early_read_info_sccb; | ||
| 118 | sclp_facilities = sccb->facilities; | ||
| 119 | sclp_fac84 = sccb->fac84; | ||
| 120 | if (sccb->fac85 & 0x02) | ||
| 121 | S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; | ||
| 122 | sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; | ||
| 123 | sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; | ||
| 124 | sclp_rzm <<= 20; | ||
| 125 | |||
| 126 | sclp_event_mask_early(); | ||
| 127 | } | ||
| 128 | |||
| 129 | bool __init sclp_has_linemode(void) | ||
| 130 | { | ||
| 131 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
| 132 | |||
| 133 | if (sccb->header.response_code != 0x20) | ||
| 134 | return 0; | ||
| 135 | if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) | ||
| 136 | return 0; | ||
| 137 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
| 138 | return 0; | ||
| 139 | return 1; | ||
| 140 | } | ||
| 141 | |||
| 142 | bool __init sclp_has_vt220(void) | ||
| 143 | { | ||
| 144 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
| 145 | |||
| 146 | if (sccb->header.response_code != 0x20) | ||
| 147 | return 0; | ||
| 148 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) | ||
| 149 | return 1; | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | unsigned long long sclp_get_rnmax(void) | ||
| 154 | { | ||
| 155 | return sclp_rnmax; | ||
| 156 | } | ||
| 157 | |||
| 158 | unsigned long long sclp_get_rzm(void) | ||
| 159 | { | ||
| 160 | return sclp_rzm; | ||
| 161 | } | ||
| 162 | |||
| 163 | /* | ||
| 164 | * This function will be called after sclp_facilities_detect(), which gets | ||
| 165 | * called from early.c code. Therefore the sccb should have valid contents. | ||
| 166 | */ | ||
| 167 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) | ||
| 168 | { | ||
| 169 | struct read_info_sccb *sccb; | ||
| 170 | |||
| 171 | if (!sclp_early_read_info_sccb_valid) | ||
| 172 | return; | ||
| 173 | sccb = &early_read_info_sccb; | ||
| 174 | info->is_valid = 1; | ||
| 175 | if (sccb->flags & 0x2) | ||
| 176 | info->has_dump = 1; | ||
| 177 | memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); | ||
| 178 | } | ||
| 179 | |||
| 18 | static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) | 180 | static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) |
| 19 | { | 181 | { |
| 20 | int rc; | 182 | int rc; |
