aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2013-11-13 04:38:27 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-11-15 08:08:40 -0500
commite657d8fe2faf49ed5d35e2325bd0f1712b8058cd (patch)
tree420f6c638e1a42f3a83135eff827dd4832544023 /drivers
parentf8049e3e869f6de644e4302b3d85d06e185ddced (diff)
s390/sclp: Determine HSA size dynamically for zfcpdump
Currently we have hardcoded the HSA size to 32 MiB. With this patch the HSA size is determined dynamically via SCLP in 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/Makefile3
-rw-r--r--drivers/s390/char/sclp.h1
-rw-r--r--drivers/s390/char/sclp_cmd.c2
-rw-r--r--drivers/s390/char/sclp_early.c111
-rw-r--r--drivers/s390/char/zcore.c22
5 files changed, 122 insertions, 17 deletions
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
5obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ 5obj-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
8obj-$(CONFIG_TN3270) += raw3270.o 9obj-$(CONFIG_TN3270) += raw3270.o
9obj-$(CONFIG_TN3270_CONSOLE) += con3270.o 10obj-$(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);
172int sclp_reactivate(void); 172int sclp_reactivate(void);
173int sclp_service_call(sclp_cmdw_t command, void *sccb); 173int sclp_service_call(sclp_cmdw_t command, void *sccb);
174int sclp_sync_request(sclp_cmdw_t command, void *sccb); 174int sclp_sync_request(sclp_cmdw_t command, void *sccb);
175int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb);
175 176
176int sclp_sdias_init(void); 177int sclp_sdias_init(void);
177void sclp_sdias_exit(void); 178void 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;
59static unsigned long long rzm; 59static unsigned long long rzm;
60static unsigned long long rnmax; 60static unsigned long long rnmax;
61 61
62static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) 62int __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
15static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE);
16static unsigned long sclp_hsa_size;
17
18static 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
33static 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
46static 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
59static 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
71static 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
82unsigned long sclp_get_hsa_size(void)
83{
84 return sclp_hsa_size;
85}
86
87void __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;
108out:
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
585static int __init check_sdias(void) 585static 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);