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:40 -0500 |
commit | e657d8fe2faf49ed5d35e2325bd0f1712b8058cd (patch) | |
tree | 420f6c638e1a42f3a83135eff827dd4832544023 /drivers | |
parent | f8049e3e869f6de644e4302b3d85d06e185ddced (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/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 |
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 | ||
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); |