aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/scm_blk.c24
-rw-r--r--drivers/s390/block/scm_blk_cluster.c2
-rw-r--r--drivers/s390/char/Makefile3
-rw-r--r--drivers/s390/char/fs3270.c1
-rw-r--r--drivers/s390/char/sclp.h5
-rw-r--r--drivers/s390/char/sclp_cmd.c180
-rw-r--r--drivers/s390/char/sclp_early.c264
-rw-r--r--drivers/s390/char/sclp_sdias.c78
-rw-r--r--drivers/s390/char/sclp_sdias.h46
-rw-r--r--drivers/s390/char/zcore.c22
-rw-r--r--drivers/s390/cio/eadm_sch.c10
-rw-r--r--drivers/s390/cio/scm.c45
12 files changed, 365 insertions, 315 deletions
diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c
index 548209a9c43c..d0ab5019d885 100644
--- a/drivers/s390/block/scm_blk.c
+++ b/drivers/s390/block/scm_blk.c
@@ -118,22 +118,6 @@ static void scm_request_done(struct scm_request *scmrq)
118 spin_unlock_irqrestore(&list_lock, flags); 118 spin_unlock_irqrestore(&list_lock, flags);
119} 119}
120 120
121static int scm_open(struct block_device *blkdev, fmode_t mode)
122{
123 return scm_get_ref();
124}
125
126static void scm_release(struct gendisk *gendisk, fmode_t mode)
127{
128 scm_put_ref();
129}
130
131static const struct block_device_operations scm_blk_devops = {
132 .owner = THIS_MODULE,
133 .open = scm_open,
134 .release = scm_release,
135};
136
137static bool scm_permit_request(struct scm_blk_dev *bdev, struct request *req) 121static bool scm_permit_request(struct scm_blk_dev *bdev, struct request *req)
138{ 122{
139 return rq_data_dir(req) != WRITE || bdev->state != SCM_WR_PROHIBIT; 123 return rq_data_dir(req) != WRITE || bdev->state != SCM_WR_PROHIBIT;
@@ -256,7 +240,7 @@ static void scm_blk_request(struct request_queue *rq)
256 atomic_inc(&bdev->queued_reqs); 240 atomic_inc(&bdev->queued_reqs);
257 blk_start_request(req); 241 blk_start_request(req);
258 242
259 ret = scm_start_aob(scmrq->aob); 243 ret = eadm_start_aob(scmrq->aob);
260 if (ret) { 244 if (ret) {
261 SCM_LOG(5, "no subchannel"); 245 SCM_LOG(5, "no subchannel");
262 scm_request_requeue(scmrq); 246 scm_request_requeue(scmrq);
@@ -320,7 +304,7 @@ static void scm_blk_handle_error(struct scm_request *scmrq)
320 } 304 }
321 305
322restart: 306restart:
323 if (!scm_start_aob(scmrq->aob)) 307 if (!eadm_start_aob(scmrq->aob))
324 return; 308 return;
325 309
326requeue: 310requeue:
@@ -363,6 +347,10 @@ static void scm_blk_tasklet(struct scm_blk_dev *bdev)
363 blk_run_queue(bdev->rq); 347 blk_run_queue(bdev->rq);
364} 348}
365 349
350static const struct block_device_operations scm_blk_devops = {
351 .owner = THIS_MODULE,
352};
353
366int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev) 354int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
367{ 355{
368 struct request_queue *rq; 356 struct request_queue *rq;
diff --git a/drivers/s390/block/scm_blk_cluster.c b/drivers/s390/block/scm_blk_cluster.c
index c0d102e3a48b..27f930cd657f 100644
--- a/drivers/s390/block/scm_blk_cluster.c
+++ b/drivers/s390/block/scm_blk_cluster.c
@@ -187,7 +187,7 @@ bool scm_need_cluster_request(struct scm_request *scmrq)
187void scm_initiate_cluster_request(struct scm_request *scmrq) 187void scm_initiate_cluster_request(struct scm_request *scmrq)
188{ 188{
189 scm_prepare_cluster_request(scmrq); 189 scm_prepare_cluster_request(scmrq);
190 if (scm_start_aob(scmrq->aob)) 190 if (eadm_start_aob(scmrq->aob))
191 scm_request_requeue(scmrq); 191 scm_request_requeue(scmrq);
192} 192}
193 193
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/fs3270.c b/drivers/s390/char/fs3270.c
index f93cc32eb818..71e974738014 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -564,6 +564,7 @@ static void __exit
564fs3270_exit(void) 564fs3270_exit(void)
565{ 565{
566 raw3270_unregister_notifier(&fs3270_notifier); 566 raw3270_unregister_notifier(&fs3270_notifier);
567 device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, 0));
567 __unregister_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270"); 568 __unregister_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270");
568} 569}
569 570
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index 40d1406289ed..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
101extern u64 sclp_facilities; 101extern 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)
@@ -179,6 +180,10 @@ void sclp_sdias_exit(void);
179extern int sclp_console_pages; 180extern int sclp_console_pages;
180extern int sclp_console_drop; 181extern int sclp_console_drop;
181extern unsigned long sclp_console_full; 182extern unsigned long sclp_console_full;
183extern u8 sclp_fac84;
184extern unsigned long long sclp_rzm;
185extern unsigned long long sclp_rnmax;
186extern __initdata int sclp_early_read_info_sccb_valid;
182 187
183/* useful inlines */ 188/* useful inlines */
184 189
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 77df9cb00688..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
34struct 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
53static struct init_sccb __initdata early_event_mask_sccb __aligned(PAGE_SIZE);
54static struct read_info_sccb __initdata early_read_info_sccb;
55static int __initdata early_read_info_sccb_valid;
56
57u64 sclp_facilities;
58static u8 sclp_fac84;
59static unsigned long long rzm;
60static unsigned long long rnmax;
61
62static 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();
73out:
74 /* Contents of the sccb might have changed. */
75 barrier();
76 __ctl_clear_bit(0, 9);
77 return rc;
78}
79
80static 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
109static 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
122void __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
142bool __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
155bool __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
166unsigned long long sclp_get_rnmax(void)
167{
168 return rnmax;
169}
170
171unsigned 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 */
180void __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
193static void sclp_sync_callback(struct sclp_req *req, void *data) 31static 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
357int arch_get_memory_phys_device(unsigned long start_pfn) 195int 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
364static unsigned long long rn2addr(u16 rn) 202static 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
369static int do_assign_storage(sclp_cmdw_t cmd, u16 rn) 207static 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
new file mode 100644
index 000000000000..f7aa080e9b28
--- /dev/null
+++ b/drivers/s390/char/sclp_early.c
@@ -0,0 +1,264 @@
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/ctl_reg.h>
11#include <asm/sclp.h>
12#include <asm/ipl.h>
13#include "sclp_sdias.h"
14#include "sclp.h"
15
16#define SCLP_CMDW_READ_SCP_INFO 0x00020001
17#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
18
19struct 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
38static __initdata struct init_sccb early_event_mask_sccb __aligned(PAGE_SIZE);
39static __initdata struct read_info_sccb early_read_info_sccb;
40static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE);
41static unsigned long sclp_hsa_size;
42
43__initdata int sclp_early_read_info_sccb_valid;
44u64 sclp_facilities;
45u8 sclp_fac84;
46unsigned long long sclp_rzm;
47unsigned long long sclp_rnmax;
48
49static 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();
60out:
61 /* Contents of the sccb might have changed. */
62 barrier();
63 __ctl_clear_bit(0, 9);
64 return rc;
65}
66
67static 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
96static void __init sclp_facilities_detect(void)
97{
98 struct read_info_sccb *sccb;
99
100 sclp_read_info_early();
101 if (!sclp_early_read_info_sccb_valid)
102 return;
103
104 sccb = &early_read_info_sccb;
105 sclp_facilities = sccb->facilities;
106 sclp_fac84 = sccb->fac84;
107 if (sccb->fac85 & 0x02)
108 S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
109 sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
110 sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
111 sclp_rzm <<= 20;
112}
113
114bool __init sclp_has_linemode(void)
115{
116 struct init_sccb *sccb = &early_event_mask_sccb;
117
118 if (sccb->header.response_code != 0x20)
119 return 0;
120 if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK)))
121 return 0;
122 if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
123 return 0;
124 return 1;
125}
126
127bool __init sclp_has_vt220(void)
128{
129 struct init_sccb *sccb = &early_event_mask_sccb;
130
131 if (sccb->header.response_code != 0x20)
132 return 0;
133 if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK)
134 return 1;
135 return 0;
136}
137
138unsigned long long sclp_get_rnmax(void)
139{
140 return sclp_rnmax;
141}
142
143unsigned long long sclp_get_rzm(void)
144{
145 return sclp_rzm;
146}
147
148/*
149 * This function will be called after sclp_facilities_detect(), which gets
150 * called from early.c code. Therefore the sccb should have valid contents.
151 */
152void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
153{
154 struct read_info_sccb *sccb;
155
156 if (!sclp_early_read_info_sccb_valid)
157 return;
158 sccb = &early_read_info_sccb;
159 info->is_valid = 1;
160 if (sccb->flags & 0x2)
161 info->has_dump = 1;
162 memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
163}
164
165static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb)
166{
167 int rc;
168
169 do {
170 rc = sclp_cmd_sync_early(cmd, sccb);
171 } while (rc == -EBUSY);
172
173 if (rc)
174 return -EIO;
175 if (((struct sccb_header *) sccb)->response_code != 0x0020)
176 return -EIO;
177 return 0;
178}
179
180static void __init sccb_init_eq_size(struct sdias_sccb *sccb)
181{
182 memset(sccb, 0, sizeof(*sccb));
183
184 sccb->hdr.length = sizeof(*sccb);
185 sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf);
186 sccb->evbuf.hdr.type = EVTYP_SDIAS;
187 sccb->evbuf.event_qual = SDIAS_EQ_SIZE;
188 sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP;
189 sccb->evbuf.event_id = 4712;
190 sccb->evbuf.dbs = 1;
191}
192
193static int __init sclp_set_event_mask(unsigned long receive_mask,
194 unsigned long send_mask)
195{
196 struct init_sccb *sccb = (void *) &sccb_early;
197
198 memset(sccb, 0, sizeof(*sccb));
199 sccb->header.length = sizeof(*sccb);
200 sccb->mask_length = sizeof(sccb_mask_t);
201 sccb->receive_mask = receive_mask;
202 sccb->send_mask = send_mask;
203 return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb);
204}
205
206static long __init sclp_hsa_size_init(void)
207{
208 struct sdias_sccb *sccb = (void *) &sccb_early;
209
210 sccb_init_eq_size(sccb);
211 if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb))
212 return -EIO;
213 if (sccb->evbuf.blk_cnt != 0)
214 return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE;
215 return 0;
216}
217
218static long __init sclp_hsa_copy_wait(void)
219{
220 struct sccb_header *sccb = (void *) &sccb_early;
221
222 memset(sccb, 0, PAGE_SIZE);
223 sccb->length = PAGE_SIZE;
224 if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb))
225 return -EIO;
226 return (((struct sdias_sccb *) sccb)->evbuf.blk_cnt - 1) * PAGE_SIZE;
227}
228
229unsigned long sclp_get_hsa_size(void)
230{
231 return sclp_hsa_size;
232}
233
234static void __init sclp_hsa_size_detect(void)
235{
236 long size;
237
238 /* First try synchronous interface (LPAR) */
239 if (sclp_set_event_mask(0, 0x40000010))
240 return;
241 size = sclp_hsa_size_init();
242 if (size < 0)
243 return;
244 if (size != 0)
245 goto out;
246 /* Then try asynchronous interface (z/VM) */
247 if (sclp_set_event_mask(0x00000010, 0x40000010))
248 return;
249 size = sclp_hsa_size_init();
250 if (size < 0)
251 return;
252 size = sclp_hsa_copy_wait();
253 if (size < 0)
254 return;
255out:
256 sclp_hsa_size = size;
257}
258
259void __init sclp_early_detect(void)
260{
261 sclp_facilities_detect();
262 sclp_hsa_size_detect();
263 sclp_set_event_mask(0, 0);
264}
diff --git a/drivers/s390/char/sclp_sdias.c b/drivers/s390/char/sclp_sdias.c
index b1032931a1c4..561a0414b352 100644
--- a/drivers/s390/char/sclp_sdias.c
+++ b/drivers/s390/char/sclp_sdias.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Sclp "store data in absolut storage" 2 * SCLP "store data in absolute storage"
3 * 3 *
4 * Copyright IBM Corp. 2003, 2007 4 * Copyright IBM Corp. 2003, 2013
5 * Author(s): Michael Holzheu 5 * Author(s): Michael Holzheu
6 */ 6 */
7 7
@@ -14,6 +14,7 @@
14#include <asm/debug.h> 14#include <asm/debug.h>
15#include <asm/ipl.h> 15#include <asm/ipl.h>
16 16
17#include "sclp_sdias.h"
17#include "sclp.h" 18#include "sclp.h"
18#include "sclp_rw.h" 19#include "sclp_rw.h"
19 20
@@ -22,46 +23,12 @@
22#define SDIAS_RETRIES 300 23#define SDIAS_RETRIES 300
23#define SDIAS_SLEEP_TICKS 50 24#define SDIAS_SLEEP_TICKS 50
24 25
25#define EQ_STORE_DATA 0x0
26#define EQ_SIZE 0x1
27#define DI_FCP_DUMP 0x0
28#define ASA_SIZE_32 0x0
29#define ASA_SIZE_64 0x1
30#define EVSTATE_ALL_STORED 0x0
31#define EVSTATE_NO_DATA 0x3
32#define EVSTATE_PART_STORED 0x10
33
34static struct debug_info *sdias_dbf; 26static struct debug_info *sdias_dbf;
35 27
36static struct sclp_register sclp_sdias_register = { 28static struct sclp_register sclp_sdias_register = {
37 .send_mask = EVTYP_SDIAS_MASK, 29 .send_mask = EVTYP_SDIAS_MASK,
38}; 30};
39 31
40struct sdias_evbuf {
41 struct evbuf_header hdr;
42 u8 event_qual;
43 u8 data_id;
44 u64 reserved2;
45 u32 event_id;
46 u16 reserved3;
47 u8 asa_size;
48 u8 event_status;
49 u32 reserved4;
50 u32 blk_cnt;
51 u64 asa;
52 u32 reserved5;
53 u32 fbn;
54 u32 reserved6;
55 u32 lbn;
56 u16 reserved7;
57 u16 dbs;
58} __attribute__((packed));
59
60struct sdias_sccb {
61 struct sccb_header hdr;
62 struct sdias_evbuf evbuf;
63} __attribute__((packed));
64
65static struct sdias_sccb sccb __attribute__((aligned(4096))); 32static struct sdias_sccb sccb __attribute__((aligned(4096)));
66static struct sdias_evbuf sdias_evbuf; 33static struct sdias_evbuf sdias_evbuf;
67 34
@@ -148,8 +115,8 @@ int sclp_sdias_blk_count(void)
148 sccb.hdr.length = sizeof(sccb); 115 sccb.hdr.length = sizeof(sccb);
149 sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf); 116 sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf);
150 sccb.evbuf.hdr.type = EVTYP_SDIAS; 117 sccb.evbuf.hdr.type = EVTYP_SDIAS;
151 sccb.evbuf.event_qual = EQ_SIZE; 118 sccb.evbuf.event_qual = SDIAS_EQ_SIZE;
152 sccb.evbuf.data_id = DI_FCP_DUMP; 119 sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP;
153 sccb.evbuf.event_id = 4712; 120 sccb.evbuf.event_id = 4712;
154 sccb.evbuf.dbs = 1; 121 sccb.evbuf.dbs = 1;
155 122
@@ -208,13 +175,13 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)
208 sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf); 175 sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf);
209 sccb.evbuf.hdr.type = EVTYP_SDIAS; 176 sccb.evbuf.hdr.type = EVTYP_SDIAS;
210 sccb.evbuf.hdr.flags = 0; 177 sccb.evbuf.hdr.flags = 0;
211 sccb.evbuf.event_qual = EQ_STORE_DATA; 178 sccb.evbuf.event_qual = SDIAS_EQ_STORE_DATA;
212 sccb.evbuf.data_id = DI_FCP_DUMP; 179 sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP;
213 sccb.evbuf.event_id = 4712; 180 sccb.evbuf.event_id = 4712;
214#ifdef CONFIG_64BIT 181#ifdef CONFIG_64BIT
215 sccb.evbuf.asa_size = ASA_SIZE_64; 182 sccb.evbuf.asa_size = SDIAS_ASA_SIZE_64;
216#else 183#else
217 sccb.evbuf.asa_size = ASA_SIZE_32; 184 sccb.evbuf.asa_size = SDIAS_ASA_SIZE_32;
218#endif 185#endif
219 sccb.evbuf.event_status = 0; 186 sccb.evbuf.event_status = 0;
220 sccb.evbuf.blk_cnt = nr_blks; 187 sccb.evbuf.blk_cnt = nr_blks;
@@ -240,20 +207,19 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)
240 } 207 }
241 208
242 switch (sdias_evbuf.event_status) { 209 switch (sdias_evbuf.event_status) {
243 case EVSTATE_ALL_STORED: 210 case SDIAS_EVSTATE_ALL_STORED:
244 TRACE("all stored\n"); 211 TRACE("all stored\n");
245 break; 212 break;
246 case EVSTATE_PART_STORED: 213 case SDIAS_EVSTATE_PART_STORED:
247 TRACE("part stored: %i\n", sdias_evbuf.blk_cnt); 214 TRACE("part stored: %i\n", sdias_evbuf.blk_cnt);
248 break; 215 break;
249 case EVSTATE_NO_DATA: 216 case SDIAS_EVSTATE_NO_DATA:
250 TRACE("no data\n"); 217 TRACE("no data\n");
251 /* fall through */ 218 /* fall through */
252 default: 219 default:
253 pr_err("Error from SCLP while copying hsa. " 220 pr_err("Error from SCLP while copying hsa. Event status = %x\n",
254 "Event status = %x\n", 221 sdias_evbuf.event_status);
255 sdias_evbuf.event_status); 222 rc = -EIO;
256 rc = -EIO;
257 } 223 }
258out: 224out:
259 mutex_unlock(&sdias_mutex); 225 mutex_unlock(&sdias_mutex);
diff --git a/drivers/s390/char/sclp_sdias.h b/drivers/s390/char/sclp_sdias.h
new file mode 100644
index 000000000000..f2431c414150
--- /dev/null
+++ b/drivers/s390/char/sclp_sdias.h
@@ -0,0 +1,46 @@
1/*
2 * SCLP "store data in absolute storage"
3 *
4 * Copyright IBM Corp. 2003, 2013
5 */
6
7#ifndef SCLP_SDIAS_H
8#define SCLP_SDIAS_H
9
10#include "sclp.h"
11
12#define SDIAS_EQ_STORE_DATA 0x0
13#define SDIAS_EQ_SIZE 0x1
14#define SDIAS_DI_FCP_DUMP 0x0
15#define SDIAS_ASA_SIZE_32 0x0
16#define SDIAS_ASA_SIZE_64 0x1
17#define SDIAS_EVSTATE_ALL_STORED 0x0
18#define SDIAS_EVSTATE_NO_DATA 0x3
19#define SDIAS_EVSTATE_PART_STORED 0x10
20
21struct sdias_evbuf {
22 struct evbuf_header hdr;
23 u8 event_qual;
24 u8 data_id;
25 u64 reserved2;
26 u32 event_id;
27 u16 reserved3;
28 u8 asa_size;
29 u8 event_status;
30 u32 reserved4;
31 u32 blk_cnt;
32 u64 asa;
33 u32 reserved5;
34 u32 fbn;
35 u32 reserved6;
36 u32 lbn;
37 u16 reserved7;
38 u16 dbs;
39} __packed;
40
41struct sdias_sccb {
42 struct sccb_header hdr;
43 struct sdias_evbuf evbuf;
44} __packed;
45
46#endif /* SCLP_SDIAS_H */
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);
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index aca7bfc113aa..3a2ee4a740b4 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -190,7 +190,7 @@ static struct subchannel *eadm_get_idle_sch(void)
190 return NULL; 190 return NULL;
191} 191}
192 192
193static int eadm_start_aob(struct aob *aob) 193int eadm_start_aob(struct aob *aob)
194{ 194{
195 struct eadm_private *private; 195 struct eadm_private *private;
196 struct subchannel *sch; 196 struct subchannel *sch;
@@ -218,6 +218,7 @@ out_unlock:
218 218
219 return ret; 219 return ret;
220} 220}
221EXPORT_SYMBOL_GPL(eadm_start_aob);
221 222
222static int eadm_subchannel_probe(struct subchannel *sch) 223static int eadm_subchannel_probe(struct subchannel *sch)
223{ 224{
@@ -380,11 +381,6 @@ static struct css_driver eadm_subchannel_driver = {
380 .restore = eadm_subchannel_restore, 381 .restore = eadm_subchannel_restore,
381}; 382};
382 383
383static struct eadm_ops eadm_ops = {
384 .eadm_start = eadm_start_aob,
385 .owner = THIS_MODULE,
386};
387
388static int __init eadm_sch_init(void) 384static int __init eadm_sch_init(void)
389{ 385{
390 int ret; 386 int ret;
@@ -404,7 +400,6 @@ static int __init eadm_sch_init(void)
404 if (ret) 400 if (ret)
405 goto cleanup; 401 goto cleanup;
406 402
407 register_eadm_ops(&eadm_ops);
408 return ret; 403 return ret;
409 404
410cleanup: 405cleanup:
@@ -415,7 +410,6 @@ cleanup:
415 410
416static void __exit eadm_sch_exit(void) 411static void __exit eadm_sch_exit(void)
417{ 412{
418 unregister_eadm_ops(&eadm_ops);
419 css_driver_unregister(&eadm_subchannel_driver); 413 css_driver_unregister(&eadm_subchannel_driver);
420 isc_unregister(EADM_SCH_ISC); 414 isc_unregister(EADM_SCH_ISC);
421 debug_unregister(eadm_debug); 415 debug_unregister(eadm_debug);
diff --git a/drivers/s390/cio/scm.c b/drivers/s390/cio/scm.c
index 46ec25632e8b..15268edc54ae 100644
--- a/drivers/s390/cio/scm.c
+++ b/drivers/s390/cio/scm.c
@@ -15,8 +15,6 @@
15#include "chsc.h" 15#include "chsc.h"
16 16
17static struct device *scm_root; 17static struct device *scm_root;
18static struct eadm_ops *eadm_ops;
19static DEFINE_MUTEX(eadm_ops_mutex);
20 18
21#define to_scm_dev(n) container_of(n, struct scm_device, dev) 19#define to_scm_dev(n) container_of(n, struct scm_device, dev)
22#define to_scm_drv(d) container_of(d, struct scm_driver, drv) 20#define to_scm_drv(d) container_of(d, struct scm_driver, drv)
@@ -73,49 +71,6 @@ void scm_driver_unregister(struct scm_driver *scmdrv)
73} 71}
74EXPORT_SYMBOL_GPL(scm_driver_unregister); 72EXPORT_SYMBOL_GPL(scm_driver_unregister);
75 73
76int scm_get_ref(void)
77{
78 int ret = 0;
79
80 mutex_lock(&eadm_ops_mutex);
81 if (!eadm_ops || !try_module_get(eadm_ops->owner))
82 ret = -ENOENT;
83 mutex_unlock(&eadm_ops_mutex);
84
85 return ret;
86}
87EXPORT_SYMBOL_GPL(scm_get_ref);
88
89void scm_put_ref(void)
90{
91 mutex_lock(&eadm_ops_mutex);
92 module_put(eadm_ops->owner);
93 mutex_unlock(&eadm_ops_mutex);
94}
95EXPORT_SYMBOL_GPL(scm_put_ref);
96
97void register_eadm_ops(struct eadm_ops *ops)
98{
99 mutex_lock(&eadm_ops_mutex);
100 eadm_ops = ops;
101 mutex_unlock(&eadm_ops_mutex);
102}
103EXPORT_SYMBOL_GPL(register_eadm_ops);
104
105void unregister_eadm_ops(struct eadm_ops *ops)
106{
107 mutex_lock(&eadm_ops_mutex);
108 eadm_ops = NULL;
109 mutex_unlock(&eadm_ops_mutex);
110}
111EXPORT_SYMBOL_GPL(unregister_eadm_ops);
112
113int scm_start_aob(struct aob *aob)
114{
115 return eadm_ops->eadm_start(aob);
116}
117EXPORT_SYMBOL_GPL(scm_start_aob);
118
119void scm_irq_handler(struct aob *aob, int error) 74void scm_irq_handler(struct aob *aob, int error)
120{ 75{
121 struct aob_rq_header *aobrq = (void *) aob->request.data; 76 struct aob_rq_header *aobrq = (void *) aob->request.data;