diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/scm_blk.c | 24 | ||||
-rw-r--r-- | drivers/s390/block/scm_blk_cluster.c | 2 | ||||
-rw-r--r-- | drivers/s390/char/Makefile | 3 | ||||
-rw-r--r-- | drivers/s390/char/fs3270.c | 1 | ||||
-rw-r--r-- | drivers/s390/char/sclp.h | 5 | ||||
-rw-r--r-- | drivers/s390/char/sclp_cmd.c | 180 | ||||
-rw-r--r-- | drivers/s390/char/sclp_early.c | 264 | ||||
-rw-r--r-- | drivers/s390/char/sclp_sdias.c | 78 | ||||
-rw-r--r-- | drivers/s390/char/sclp_sdias.h | 46 | ||||
-rw-r--r-- | drivers/s390/char/zcore.c | 22 | ||||
-rw-r--r-- | drivers/s390/cio/eadm_sch.c | 10 | ||||
-rw-r--r-- | drivers/s390/cio/scm.c | 45 |
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 | ||
121 | static int scm_open(struct block_device *blkdev, fmode_t mode) | ||
122 | { | ||
123 | return scm_get_ref(); | ||
124 | } | ||
125 | |||
126 | static void scm_release(struct gendisk *gendisk, fmode_t mode) | ||
127 | { | ||
128 | scm_put_ref(); | ||
129 | } | ||
130 | |||
131 | static const struct block_device_operations scm_blk_devops = { | ||
132 | .owner = THIS_MODULE, | ||
133 | .open = scm_open, | ||
134 | .release = scm_release, | ||
135 | }; | ||
136 | |||
137 | static bool scm_permit_request(struct scm_blk_dev *bdev, struct request *req) | 121 | static 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 | ||
322 | restart: | 306 | restart: |
323 | if (!scm_start_aob(scmrq->aob)) | 307 | if (!eadm_start_aob(scmrq->aob)) |
324 | return; | 308 | return; |
325 | 309 | ||
326 | requeue: | 310 | requeue: |
@@ -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 | ||
350 | static const struct block_device_operations scm_blk_devops = { | ||
351 | .owner = THIS_MODULE, | ||
352 | }; | ||
353 | |||
366 | int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev) | 354 | int 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) | |||
187 | void scm_initiate_cluster_request(struct scm_request *scmrq) | 187 | void 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 | ||
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/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 | |||
564 | fs3270_exit(void) | 564 | fs3270_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 | ||
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) |
@@ -179,6 +180,10 @@ void sclp_sdias_exit(void); | |||
179 | extern int sclp_console_pages; | 180 | extern int sclp_console_pages; |
180 | extern int sclp_console_drop; | 181 | extern int sclp_console_drop; |
181 | 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; | ||
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 | |||
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 | static 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 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 | |||
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; | ||
40 | static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); | ||
41 | static unsigned long sclp_hsa_size; | ||
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_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 | |||
114 | bool __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 | |||
127 | bool __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 | |||
138 | unsigned long long sclp_get_rnmax(void) | ||
139 | { | ||
140 | return sclp_rnmax; | ||
141 | } | ||
142 | |||
143 | unsigned 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 | */ | ||
152 | void __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 | |||
165 | static 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 | |||
180 | static 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 | |||
193 | static 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 | |||
206 | static 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 | |||
218 | static 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 | |||
229 | unsigned long sclp_get_hsa_size(void) | ||
230 | { | ||
231 | return sclp_hsa_size; | ||
232 | } | ||
233 | |||
234 | static 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; | ||
255 | out: | ||
256 | sclp_hsa_size = size; | ||
257 | } | ||
258 | |||
259 | void __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 | |||
34 | static struct debug_info *sdias_dbf; | 26 | static struct debug_info *sdias_dbf; |
35 | 27 | ||
36 | static struct sclp_register sclp_sdias_register = { | 28 | static struct sclp_register sclp_sdias_register = { |
37 | .send_mask = EVTYP_SDIAS_MASK, | 29 | .send_mask = EVTYP_SDIAS_MASK, |
38 | }; | 30 | }; |
39 | 31 | ||
40 | struct 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 | |||
60 | struct sdias_sccb { | ||
61 | struct sccb_header hdr; | ||
62 | struct sdias_evbuf evbuf; | ||
63 | } __attribute__((packed)); | ||
64 | |||
65 | static struct sdias_sccb sccb __attribute__((aligned(4096))); | 32 | static struct sdias_sccb sccb __attribute__((aligned(4096))); |
66 | static struct sdias_evbuf sdias_evbuf; | 33 | static 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 | } |
258 | out: | 224 | out: |
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 | |||
21 | struct 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 | |||
41 | struct 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 | ||
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); |
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 | ||
193 | static int eadm_start_aob(struct aob *aob) | 193 | int 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 | } |
221 | EXPORT_SYMBOL_GPL(eadm_start_aob); | ||
221 | 222 | ||
222 | static int eadm_subchannel_probe(struct subchannel *sch) | 223 | static 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 | ||
383 | static struct eadm_ops eadm_ops = { | ||
384 | .eadm_start = eadm_start_aob, | ||
385 | .owner = THIS_MODULE, | ||
386 | }; | ||
387 | |||
388 | static int __init eadm_sch_init(void) | 384 | static 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 | ||
410 | cleanup: | 405 | cleanup: |
@@ -415,7 +410,6 @@ cleanup: | |||
415 | 410 | ||
416 | static void __exit eadm_sch_exit(void) | 411 | static 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 | ||
17 | static struct device *scm_root; | 17 | static struct device *scm_root; |
18 | static struct eadm_ops *eadm_ops; | ||
19 | static 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 | } |
74 | EXPORT_SYMBOL_GPL(scm_driver_unregister); | 72 | EXPORT_SYMBOL_GPL(scm_driver_unregister); |
75 | 73 | ||
76 | int 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 | } | ||
87 | EXPORT_SYMBOL_GPL(scm_get_ref); | ||
88 | |||
89 | void scm_put_ref(void) | ||
90 | { | ||
91 | mutex_lock(&eadm_ops_mutex); | ||
92 | module_put(eadm_ops->owner); | ||
93 | mutex_unlock(&eadm_ops_mutex); | ||
94 | } | ||
95 | EXPORT_SYMBOL_GPL(scm_put_ref); | ||
96 | |||
97 | void 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 | } | ||
103 | EXPORT_SYMBOL_GPL(register_eadm_ops); | ||
104 | |||
105 | void 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 | } | ||
111 | EXPORT_SYMBOL_GPL(unregister_eadm_ops); | ||
112 | |||
113 | int scm_start_aob(struct aob *aob) | ||
114 | { | ||
115 | return eadm_ops->eadm_start(aob); | ||
116 | } | ||
117 | EXPORT_SYMBOL_GPL(scm_start_aob); | ||
118 | |||
119 | void scm_irq_handler(struct aob *aob, int error) | 74 | void 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; |