diff options
-rw-r--r-- | arch/s390/include/asm/sclp.h | 2 | ||||
-rw-r--r-- | arch/s390/include/asm/setup.h | 3 | ||||
-rw-r--r-- | arch/s390/kernel/crash_dump.c | 22 | ||||
-rw-r--r-- | arch/s390/kernel/early.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 7 | ||||
-rw-r--r-- | drivers/s390/char/Makefile | 3 | ||||
-rw-r--r-- | drivers/s390/char/sclp.h | 1 | ||||
-rw-r--r-- | drivers/s390/char/sclp_cmd.c | 2 | ||||
-rw-r--r-- | drivers/s390/char/sclp_early.c | 111 | ||||
-rw-r--r-- | drivers/s390/char/zcore.c | 22 |
10 files changed, 142 insertions, 32 deletions
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 7dc7f9c63b65..593069201bb9 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h | |||
@@ -57,5 +57,7 @@ bool sclp_has_vt220(void); | |||
57 | int sclp_pci_configure(u32 fid); | 57 | int sclp_pci_configure(u32 fid); |
58 | int sclp_pci_deconfigure(u32 fid); | 58 | int sclp_pci_deconfigure(u32 fid); |
59 | int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); | 59 | int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); |
60 | void sclp_hsa_size_detect(void); | ||
61 | unsigned long sclp_get_hsa_size(void); | ||
60 | 62 | ||
61 | #endif /* _ASM_S390_SCLP_H */ | 63 | #endif /* _ASM_S390_SCLP_H */ |
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index df802ee14af6..94cfbe442f12 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h | |||
@@ -107,9 +107,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr, | |||
107 | #define MACHINE_HAS_RRBM (S390_lowcore.machine_flags & MACHINE_FLAG_RRBM) | 107 | #define MACHINE_HAS_RRBM (S390_lowcore.machine_flags & MACHINE_FLAG_RRBM) |
108 | #endif /* CONFIG_64BIT */ | 108 | #endif /* CONFIG_64BIT */ |
109 | 109 | ||
110 | #define ZFCPDUMP_HSA_SIZE (32UL<<20) | ||
111 | #define ZFCPDUMP_HSA_SIZE_MAX (64UL<<20) | ||
112 | |||
113 | /* | 110 | /* |
114 | * Console mode. Override with conmode= | 111 | * Console mode. Override with conmode= |
115 | */ | 112 | */ |
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index f45b2ab0cb81..d7658c4b2ed5 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c | |||
@@ -95,7 +95,7 @@ static void *elfcorehdr_newmem; | |||
95 | /* | 95 | /* |
96 | * Copy one page from zfcpdump "oldmem" | 96 | * Copy one page from zfcpdump "oldmem" |
97 | * | 97 | * |
98 | * For pages below ZFCPDUMP_HSA_SIZE memory from the HSA is copied. Otherwise | 98 | * For pages below HSA size memory from the HSA is copied. Otherwise |
99 | * real memory copy is used. | 99 | * real memory copy is used. |
100 | */ | 100 | */ |
101 | static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, | 101 | static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, |
@@ -103,7 +103,7 @@ static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, | |||
103 | { | 103 | { |
104 | int rc; | 104 | int rc; |
105 | 105 | ||
106 | if (src < ZFCPDUMP_HSA_SIZE) { | 106 | if (src < sclp_get_hsa_size()) { |
107 | rc = memcpy_hsa(buf, src, csize, userbuf); | 107 | rc = memcpy_hsa(buf, src, csize, userbuf); |
108 | } else { | 108 | } else { |
109 | if (userbuf) | 109 | if (userbuf) |
@@ -188,18 +188,19 @@ static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma, | |||
188 | /* | 188 | /* |
189 | * Remap "oldmem" for zfcpdump | 189 | * Remap "oldmem" for zfcpdump |
190 | * | 190 | * |
191 | * We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below | 191 | * We only map available memory above HSA size. Memory below HSA size |
192 | * ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function. | 192 | * is read on demand using the copy_oldmem_page() function. |
193 | */ | 193 | */ |
194 | static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma, | 194 | static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma, |
195 | unsigned long from, | 195 | unsigned long from, |
196 | unsigned long pfn, | 196 | unsigned long pfn, |
197 | unsigned long size, pgprot_t prot) | 197 | unsigned long size, pgprot_t prot) |
198 | { | 198 | { |
199 | unsigned long hsa_end = sclp_get_hsa_size(); | ||
199 | unsigned long size_hsa; | 200 | unsigned long size_hsa; |
200 | 201 | ||
201 | if (pfn < ZFCPDUMP_HSA_SIZE >> PAGE_SHIFT) { | 202 | if (pfn < hsa_end >> PAGE_SHIFT) { |
202 | size_hsa = min(size, ZFCPDUMP_HSA_SIZE - (pfn << PAGE_SHIFT)); | 203 | size_hsa = min(size, hsa_end - (pfn << PAGE_SHIFT)); |
203 | if (size == size_hsa) | 204 | if (size == size_hsa) |
204 | return 0; | 205 | return 0; |
205 | size -= size_hsa; | 206 | size -= size_hsa; |
@@ -238,9 +239,9 @@ int copy_from_oldmem(void *dest, void *src, size_t count) | |||
238 | return rc; | 239 | return rc; |
239 | } | 240 | } |
240 | } else { | 241 | } else { |
241 | if ((unsigned long) src < ZFCPDUMP_HSA_SIZE) { | 242 | unsigned long hsa_end = sclp_get_hsa_size(); |
242 | copied = min(count, | 243 | if ((unsigned long) src < hsa_end) { |
243 | ZFCPDUMP_HSA_SIZE - (unsigned long) src); | 244 | copied = min(count, hsa_end - (unsigned long) src); |
244 | rc = memcpy_hsa(dest, (unsigned long) src, copied, 0); | 245 | rc = memcpy_hsa(dest, (unsigned long) src, copied, 0); |
245 | if (rc) | 246 | if (rc) |
246 | return rc; | 247 | return rc; |
@@ -580,6 +581,9 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size) | |||
580 | /* If elfcorehdr= has been passed via cmdline, we use that one */ | 581 | /* If elfcorehdr= has been passed via cmdline, we use that one */ |
581 | if (elfcorehdr_addr != ELFCORE_ADDR_MAX) | 582 | if (elfcorehdr_addr != ELFCORE_ADDR_MAX) |
582 | return 0; | 583 | return 0; |
584 | /* If we cannot get HSA size for zfcpdump return error */ | ||
585 | if (ipl_info.type == IPL_TYPE_FCP_DUMP && !sclp_get_hsa_size()) | ||
586 | return -ENODEV; | ||
583 | mem_chunk_cnt = get_mem_chunk_cnt(); | 587 | mem_chunk_cnt = get_mem_chunk_cnt(); |
584 | 588 | ||
585 | alloc_size = 0x1000 + get_cpu_cnt() * 0x300 + | 589 | alloc_size = 0x1000 + get_cpu_cnt() * 0x300 + |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 96543ac400a7..c0462f45cf1b 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -484,6 +484,7 @@ void __init startup_init(void) | |||
484 | detect_machine_facilities(); | 484 | detect_machine_facilities(); |
485 | setup_topology(); | 485 | setup_topology(); |
486 | sclp_facilities_detect(); | 486 | sclp_facilities_detect(); |
487 | sclp_hsa_size_detect(); | ||
487 | #ifdef CONFIG_DYNAMIC_FTRACE | 488 | #ifdef CONFIG_DYNAMIC_FTRACE |
488 | S390_lowcore.ftrace_func = (unsigned long)ftrace_caller; | 489 | S390_lowcore.ftrace_func = (unsigned long)ftrace_caller; |
489 | #endif | 490 | #endif |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index ffe1c53264a7..4444875266ee 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -471,8 +471,9 @@ static void __init setup_memory_end(void) | |||
471 | 471 | ||
472 | 472 | ||
473 | #ifdef CONFIG_ZFCPDUMP | 473 | #ifdef CONFIG_ZFCPDUMP |
474 | if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) { | 474 | if (ipl_info.type == IPL_TYPE_FCP_DUMP && |
475 | memory_end = ZFCPDUMP_HSA_SIZE; | 475 | !OLDMEM_BASE && sclp_get_hsa_size()) { |
476 | memory_end = sclp_get_hsa_size(); | ||
476 | memory_end_set = 1; | 477 | memory_end_set = 1; |
477 | } | 478 | } |
478 | #endif | 479 | #endif |
@@ -586,7 +587,7 @@ static unsigned long __init find_crash_base(unsigned long crash_size, | |||
586 | crash_base = (chunk->addr + chunk->size) - crash_size; | 587 | crash_base = (chunk->addr + chunk->size) - crash_size; |
587 | if (crash_base < crash_size) | 588 | if (crash_base < crash_size) |
588 | continue; | 589 | continue; |
589 | if (crash_base < ZFCPDUMP_HSA_SIZE_MAX) | 590 | if (crash_base < sclp_get_hsa_size()) |
590 | continue; | 591 | continue; |
591 | if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE) | 592 | if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE) |
592 | continue; | 593 | continue; |
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index 17821a026c9c..b69ab17f13fa 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile | |||
@@ -3,7 +3,8 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ | 5 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ |
6 | sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o | 6 | sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o \ |
7 | sclp_early.o | ||
7 | 8 | ||
8 | obj-$(CONFIG_TN3270) += raw3270.o | 9 | obj-$(CONFIG_TN3270) += raw3270.o |
9 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o | 10 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o |
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 40d1406289ed..9cb8076f66c4 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
@@ -172,6 +172,7 @@ int sclp_deactivate(void); | |||
172 | int sclp_reactivate(void); | 172 | int sclp_reactivate(void); |
173 | int sclp_service_call(sclp_cmdw_t command, void *sccb); | 173 | int sclp_service_call(sclp_cmdw_t command, void *sccb); |
174 | int sclp_sync_request(sclp_cmdw_t command, void *sccb); | 174 | int sclp_sync_request(sclp_cmdw_t command, void *sccb); |
175 | int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb); | ||
175 | 176 | ||
176 | int sclp_sdias_init(void); | 177 | int sclp_sdias_init(void); |
177 | void sclp_sdias_exit(void); | 178 | void sclp_sdias_exit(void); |
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 77df9cb00688..5bbe6db988b9 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
@@ -59,7 +59,7 @@ static u8 sclp_fac84; | |||
59 | static unsigned long long rzm; | 59 | static unsigned long long rzm; |
60 | static unsigned long long rnmax; | 60 | static unsigned long long rnmax; |
61 | 61 | ||
62 | static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) | 62 | int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) |
63 | { | 63 | { |
64 | int rc; | 64 | int rc; |
65 | 65 | ||
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c new file mode 100644 index 000000000000..775112964eef --- /dev/null +++ b/drivers/s390/char/sclp_early.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * SCLP early driver | ||
3 | * | ||
4 | * Copyright IBM Corp. 2013 | ||
5 | */ | ||
6 | |||
7 | #define KMSG_COMPONENT "sclp_early" | ||
8 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
9 | |||
10 | #include <asm/sclp.h> | ||
11 | #include <asm/ipl.h> | ||
12 | #include "sclp_sdias.h" | ||
13 | #include "sclp.h" | ||
14 | |||
15 | static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); | ||
16 | static unsigned long sclp_hsa_size; | ||
17 | |||
18 | static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) | ||
19 | { | ||
20 | int rc; | ||
21 | |||
22 | do { | ||
23 | rc = sclp_cmd_sync_early(cmd, sccb); | ||
24 | } while (rc == -EBUSY); | ||
25 | |||
26 | if (rc) | ||
27 | return -EIO; | ||
28 | if (((struct sccb_header *) sccb)->response_code != 0x0020) | ||
29 | return -EIO; | ||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | static void __init sccb_init_eq_size(struct sdias_sccb *sccb) | ||
34 | { | ||
35 | memset(sccb, 0, sizeof(*sccb)); | ||
36 | |||
37 | sccb->hdr.length = sizeof(*sccb); | ||
38 | sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf); | ||
39 | sccb->evbuf.hdr.type = EVTYP_SDIAS; | ||
40 | sccb->evbuf.event_qual = SDIAS_EQ_SIZE; | ||
41 | sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP; | ||
42 | sccb->evbuf.event_id = 4712; | ||
43 | sccb->evbuf.dbs = 1; | ||
44 | } | ||
45 | |||
46 | static int __init sclp_set_event_mask(unsigned long receive_mask, | ||
47 | unsigned long send_mask) | ||
48 | { | ||
49 | struct init_sccb *sccb = (void *) &sccb_early; | ||
50 | |||
51 | memset(sccb, 0, sizeof(*sccb)); | ||
52 | sccb->header.length = sizeof(*sccb); | ||
53 | sccb->mask_length = sizeof(sccb_mask_t); | ||
54 | sccb->receive_mask = receive_mask; | ||
55 | sccb->send_mask = send_mask; | ||
56 | return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); | ||
57 | } | ||
58 | |||
59 | static long __init sclp_hsa_size_init(void) | ||
60 | { | ||
61 | struct sdias_sccb *sccb = (void *) &sccb_early; | ||
62 | |||
63 | sccb_init_eq_size(sccb); | ||
64 | if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb)) | ||
65 | return -EIO; | ||
66 | if (sccb->evbuf.blk_cnt != 0) | ||
67 | return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE; | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static long __init sclp_hsa_copy_wait(void) | ||
72 | { | ||
73 | struct sccb_header *sccb = (void *) &sccb_early; | ||
74 | |||
75 | memset(sccb, 0, PAGE_SIZE); | ||
76 | sccb->length = PAGE_SIZE; | ||
77 | if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb)) | ||
78 | return -EIO; | ||
79 | return (((struct sdias_sccb *) sccb)->evbuf.blk_cnt - 1) * PAGE_SIZE; | ||
80 | } | ||
81 | |||
82 | unsigned long sclp_get_hsa_size(void) | ||
83 | { | ||
84 | return sclp_hsa_size; | ||
85 | } | ||
86 | |||
87 | void __init sclp_hsa_size_detect(void) | ||
88 | { | ||
89 | long size; | ||
90 | |||
91 | /* First try synchronous interface (LPAR) */ | ||
92 | if (sclp_set_event_mask(0, 0x40000010)) | ||
93 | return; | ||
94 | size = sclp_hsa_size_init(); | ||
95 | if (size < 0) | ||
96 | return; | ||
97 | if (size != 0) | ||
98 | goto out; | ||
99 | /* Then try asynchronous interface (z/VM) */ | ||
100 | if (sclp_set_event_mask(0x00000010, 0x40000010)) | ||
101 | return; | ||
102 | size = sclp_hsa_size_init(); | ||
103 | if (size < 0) | ||
104 | return; | ||
105 | size = sclp_hsa_copy_wait(); | ||
106 | if (size < 0) | ||
107 | return; | ||
108 | out: | ||
109 | sclp_set_event_mask(0, 0); | ||
110 | sclp_hsa_size = size; | ||
111 | } | ||
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index ffb1fcf0bf5b..3d8e4d63f514 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -328,9 +328,9 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count, | |||
328 | mem_offs = 0; | 328 | mem_offs = 0; |
329 | 329 | ||
330 | /* Copy from HSA data */ | 330 | /* Copy from HSA data */ |
331 | if (*ppos < (ZFCPDUMP_HSA_SIZE + HEADER_SIZE)) { | 331 | if (*ppos < sclp_get_hsa_size() + HEADER_SIZE) { |
332 | size = min((count - hdr_count), (size_t) (ZFCPDUMP_HSA_SIZE | 332 | size = min((count - hdr_count), |
333 | - mem_start)); | 333 | (size_t) (sclp_get_hsa_size() - mem_start)); |
334 | rc = memcpy_hsa_user(buf + hdr_count, mem_start, size); | 334 | rc = memcpy_hsa_user(buf + hdr_count, mem_start, size); |
335 | if (rc) | 335 | if (rc) |
336 | goto fail; | 336 | goto fail; |
@@ -490,7 +490,7 @@ static ssize_t zcore_hsa_read(struct file *filp, char __user *buf, | |||
490 | static char str[18]; | 490 | static char str[18]; |
491 | 491 | ||
492 | if (hsa_available) | 492 | if (hsa_available) |
493 | snprintf(str, sizeof(str), "%lx\n", ZFCPDUMP_HSA_SIZE); | 493 | snprintf(str, sizeof(str), "%lx\n", sclp_get_hsa_size()); |
494 | else | 494 | else |
495 | snprintf(str, sizeof(str), "0\n"); | 495 | snprintf(str, sizeof(str), "0\n"); |
496 | return simple_read_from_buffer(buf, count, ppos, str, strlen(str)); | 496 | return simple_read_from_buffer(buf, count, ppos, str, strlen(str)); |
@@ -584,17 +584,9 @@ static int __init sys_info_init(enum arch_id arch, unsigned long mem_end) | |||
584 | 584 | ||
585 | static int __init check_sdias(void) | 585 | static int __init check_sdias(void) |
586 | { | 586 | { |
587 | int rc, act_hsa_size; | 587 | if (!sclp_get_hsa_size()) { |
588 | |||
589 | rc = sclp_sdias_blk_count(); | ||
590 | if (rc < 0) { | ||
591 | TRACE("Could not determine HSA size\n"); | 588 | TRACE("Could not determine HSA size\n"); |
592 | return rc; | 589 | return -ENODEV; |
593 | } | ||
594 | act_hsa_size = (rc - 1) * PAGE_SIZE; | ||
595 | if (act_hsa_size < ZFCPDUMP_HSA_SIZE) { | ||
596 | TRACE("HSA size too small: %i\n", act_hsa_size); | ||
597 | return -EINVAL; | ||
598 | } | 590 | } |
599 | return 0; | 591 | return 0; |
600 | } | 592 | } |
@@ -662,7 +654,7 @@ static int __init zcore_reipl_init(void) | |||
662 | ipl_block = (void *) __get_free_page(GFP_KERNEL); | 654 | ipl_block = (void *) __get_free_page(GFP_KERNEL); |
663 | if (!ipl_block) | 655 | if (!ipl_block) |
664 | return -ENOMEM; | 656 | return -ENOMEM; |
665 | if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE) | 657 | if (ipib_info.ipib < sclp_get_hsa_size()) |
666 | rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); | 658 | rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); |
667 | else | 659 | else |
668 | rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); | 660 | rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); |