xref: /linux/drivers/s390/char/sclp_cmd.c (revision 5148fa52a12fa1b97c730b2fe321f2aad7ea041c)
1 /*
2  * Copyright IBM Corp. 2007, 2009
3  *
4  * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
5  *	      Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
6  */
7 
8 #define KMSG_COMPONENT "sclp_cmd"
9 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10 
11 #include <linux/completion.h>
12 #include <linux/init.h>
13 #include <linux/errno.h>
14 #include <linux/err.h>
15 #include <linux/slab.h>
16 #include <linux/string.h>
17 #include <linux/mm.h>
18 #include <linux/mmzone.h>
19 #include <linux/memory.h>
20 #include <linux/platform_device.h>
21 #include <asm/chpid.h>
22 #include <asm/sclp.h>
23 #include <asm/setup.h>
24 #include <asm/ctl_reg.h>
25 
26 #include "sclp.h"
27 
28 #define SCLP_CMDW_READ_SCP_INFO		0x00020001
29 #define SCLP_CMDW_READ_SCP_INFO_FORCED	0x00120001
30 
31 struct read_info_sccb {
32 	struct	sccb_header header;	/* 0-7 */
33 	u16	rnmax;			/* 8-9 */
34 	u8	rnsize;			/* 10 */
35 	u8	_reserved0[24 - 11];	/* 11-15 */
36 	u8	loadparm[8];		/* 24-31 */
37 	u8	_reserved1[48 - 32];	/* 32-47 */
38 	u64	facilities;		/* 48-55 */
39 	u8	_reserved2[84 - 56];	/* 56-83 */
40 	u8	fac84;			/* 84 */
41 	u8	_reserved3[91 - 85];	/* 85-90 */
42 	u8	flags;			/* 91 */
43 	u8	_reserved4[100 - 92];	/* 92-99 */
44 	u32	rnsize2;		/* 100-103 */
45 	u64	rnmax2;			/* 104-111 */
46 	u8	_reserved5[4096 - 112];	/* 112-4095 */
47 } __attribute__((packed, aligned(PAGE_SIZE)));
48 
49 static struct read_info_sccb __initdata early_read_info_sccb;
50 static int __initdata early_read_info_sccb_valid;
51 
52 u64 sclp_facilities;
53 static u8 sclp_fac84;
54 static unsigned long long rzm;
55 static unsigned long long rnmax;
56 
57 static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
58 {
59 	int rc;
60 
61 	__ctl_set_bit(0, 9);
62 	rc = sclp_service_call(cmd, sccb);
63 	if (rc)
64 		goto out;
65 	__load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA |
66 			PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT);
67 	local_irq_disable();
68 out:
69 	/* Contents of the sccb might have changed. */
70 	barrier();
71 	__ctl_clear_bit(0, 9);
72 	return rc;
73 }
74 
75 static void __init sclp_read_info_early(void)
76 {
77 	int rc;
78 	int i;
79 	struct read_info_sccb *sccb;
80 	sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
81 				  SCLP_CMDW_READ_SCP_INFO};
82 
83 	sccb = &early_read_info_sccb;
84 	for (i = 0; i < ARRAY_SIZE(commands); i++) {
85 		do {
86 			memset(sccb, 0, sizeof(*sccb));
87 			sccb->header.length = sizeof(*sccb);
88 			sccb->header.function_code = 0x80;
89 			sccb->header.control_mask[2] = 0x80;
90 			rc = sclp_cmd_sync_early(commands[i], sccb);
91 		} while (rc == -EBUSY);
92 
93 		if (rc)
94 			break;
95 		if (sccb->header.response_code == 0x10) {
96 			early_read_info_sccb_valid = 1;
97 			break;
98 		}
99 		if (sccb->header.response_code != 0x1f0)
100 			break;
101 	}
102 }
103 
104 void __init sclp_facilities_detect(void)
105 {
106 	struct read_info_sccb *sccb;
107 
108 	sclp_read_info_early();
109 	if (!early_read_info_sccb_valid)
110 		return;
111 
112 	sccb = &early_read_info_sccb;
113 	sclp_facilities = sccb->facilities;
114 	sclp_fac84 = sccb->fac84;
115 	rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
116 	rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
117 	rzm <<= 20;
118 }
119 
120 unsigned long long sclp_get_rnmax(void)
121 {
122 	return rnmax;
123 }
124 
125 unsigned long long sclp_get_rzm(void)
126 {
127 	return rzm;
128 }
129 
130 /*
131  * This function will be called after sclp_facilities_detect(), which gets
132  * called from early.c code. Therefore the sccb should have valid contents.
133  */
134 void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
135 {
136 	struct read_info_sccb *sccb;
137 
138 	if (!early_read_info_sccb_valid)
139 		return;
140 	sccb = &early_read_info_sccb;
141 	info->is_valid = 1;
142 	if (sccb->flags & 0x2)
143 		info->has_dump = 1;
144 	memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
145 }
146 
147 static void sclp_sync_callback(struct sclp_req *req, void *data)
148 {
149 	struct completion *completion = data;
150 
151 	complete(completion);
152 }
153 
154 static int do_sync_request(sclp_cmdw_t cmd, void *sccb)
155 {
156 	struct completion completion;
157 	struct sclp_req *request;
158 	int rc;
159 
160 	request = kzalloc(sizeof(*request), GFP_KERNEL);
161 	if (!request)
162 		return -ENOMEM;
163 	request->command = cmd;
164 	request->sccb = sccb;
165 	request->status = SCLP_REQ_FILLED;
166 	request->callback = sclp_sync_callback;
167 	request->callback_data = &completion;
168 	init_completion(&completion);
169 
170 	/* Perform sclp request. */
171 	rc = sclp_add_request(request);
172 	if (rc)
173 		goto out;
174 	wait_for_completion(&completion);
175 
176 	/* Check response. */
177 	if (request->status != SCLP_REQ_DONE) {
178 		pr_warning("sync request failed (cmd=0x%08x, "
179 			   "status=0x%02x)\n", cmd, request->status);
180 		rc = -EIO;
181 	}
182 out:
183 	kfree(request);
184 	return rc;
185 }
186 
187 /*
188  * CPU configuration related functions.
189  */
190 
191 #define SCLP_CMDW_READ_CPU_INFO		0x00010001
192 #define SCLP_CMDW_CONFIGURE_CPU		0x00110001
193 #define SCLP_CMDW_DECONFIGURE_CPU	0x00100001
194 
195 struct read_cpu_info_sccb {
196 	struct	sccb_header header;
197 	u16	nr_configured;
198 	u16	offset_configured;
199 	u16	nr_standby;
200 	u16	offset_standby;
201 	u8	reserved[4096 - 16];
202 } __attribute__((packed, aligned(PAGE_SIZE)));
203 
204 static void sclp_fill_cpu_info(struct sclp_cpu_info *info,
205 			       struct read_cpu_info_sccb *sccb)
206 {
207 	char *page = (char *) sccb;
208 
209 	memset(info, 0, sizeof(*info));
210 	info->configured = sccb->nr_configured;
211 	info->standby = sccb->nr_standby;
212 	info->combined = sccb->nr_configured + sccb->nr_standby;
213 	info->has_cpu_type = sclp_fac84 & 0x1;
214 	memcpy(&info->cpu, page + sccb->offset_configured,
215 	       info->combined * sizeof(struct sclp_cpu_entry));
216 }
217 
218 int sclp_get_cpu_info(struct sclp_cpu_info *info)
219 {
220 	int rc;
221 	struct read_cpu_info_sccb *sccb;
222 
223 	if (!SCLP_HAS_CPU_INFO)
224 		return -EOPNOTSUPP;
225 	sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
226 	if (!sccb)
227 		return -ENOMEM;
228 	sccb->header.length = sizeof(*sccb);
229 	rc = do_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb);
230 	if (rc)
231 		goto out;
232 	if (sccb->header.response_code != 0x0010) {
233 		pr_warning("readcpuinfo failed (response=0x%04x)\n",
234 			   sccb->header.response_code);
235 		rc = -EIO;
236 		goto out;
237 	}
238 	sclp_fill_cpu_info(info, sccb);
239 out:
240 	free_page((unsigned long) sccb);
241 	return rc;
242 }
243 
244 struct cpu_configure_sccb {
245 	struct sccb_header header;
246 } __attribute__((packed, aligned(8)));
247 
248 static int do_cpu_configure(sclp_cmdw_t cmd)
249 {
250 	struct cpu_configure_sccb *sccb;
251 	int rc;
252 
253 	if (!SCLP_HAS_CPU_RECONFIG)
254 		return -EOPNOTSUPP;
255 	/*
256 	 * This is not going to cross a page boundary since we force
257 	 * kmalloc to have a minimum alignment of 8 bytes on s390.
258 	 */
259 	sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA);
260 	if (!sccb)
261 		return -ENOMEM;
262 	sccb->header.length = sizeof(*sccb);
263 	rc = do_sync_request(cmd, sccb);
264 	if (rc)
265 		goto out;
266 	switch (sccb->header.response_code) {
267 	case 0x0020:
268 	case 0x0120:
269 		break;
270 	default:
271 		pr_warning("configure cpu failed (cmd=0x%08x, "
272 			   "response=0x%04x)\n", cmd,
273 			   sccb->header.response_code);
274 		rc = -EIO;
275 		break;
276 	}
277 out:
278 	kfree(sccb);
279 	return rc;
280 }
281 
282 int sclp_cpu_configure(u8 cpu)
283 {
284 	return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8);
285 }
286 
287 int sclp_cpu_deconfigure(u8 cpu)
288 {
289 	return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);
290 }
291 
292 #ifdef CONFIG_MEMORY_HOTPLUG
293 
294 static DEFINE_MUTEX(sclp_mem_mutex);
295 static LIST_HEAD(sclp_mem_list);
296 static u8 sclp_max_storage_id;
297 static unsigned long sclp_storage_ids[256 / BITS_PER_LONG];
298 static int sclp_mem_state_changed;
299 
300 struct memory_increment {
301 	struct list_head list;
302 	u16 rn;
303 	int standby;
304 	int usecount;
305 };
306 
307 struct assign_storage_sccb {
308 	struct sccb_header header;
309 	u16 rn;
310 } __packed;
311 
312 int arch_get_memory_phys_device(unsigned long start_pfn)
313 {
314 	if (!rzm)
315 		return 0;
316 	return PFN_PHYS(start_pfn) >> ilog2(rzm);
317 }
318 
319 static unsigned long long rn2addr(u16 rn)
320 {
321 	return (unsigned long long) (rn - 1) * rzm;
322 }
323 
324 static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)
325 {
326 	struct assign_storage_sccb *sccb;
327 	int rc;
328 
329 	sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
330 	if (!sccb)
331 		return -ENOMEM;
332 	sccb->header.length = PAGE_SIZE;
333 	sccb->rn = rn;
334 	rc = do_sync_request(cmd, sccb);
335 	if (rc)
336 		goto out;
337 	switch (sccb->header.response_code) {
338 	case 0x0020:
339 	case 0x0120:
340 		break;
341 	default:
342 		pr_warning("assign storage failed (cmd=0x%08x, "
343 			   "response=0x%04x, rn=0x%04x)\n", cmd,
344 			   sccb->header.response_code, rn);
345 		rc = -EIO;
346 		break;
347 	}
348 out:
349 	free_page((unsigned long) sccb);
350 	return rc;
351 }
352 
353 static int sclp_assign_storage(u16 rn)
354 {
355 	unsigned long long start, address;
356 	int rc;
357 
358 	rc = do_assign_storage(0x000d0001, rn);
359 	if (rc)
360 		goto out;
361 	start = address = rn2addr(rn);
362 	for (; address < start + rzm; address += PAGE_SIZE)
363 		page_set_storage_key(address, PAGE_DEFAULT_KEY, 0);
364 out:
365 	return rc;
366 }
367 
368 static int sclp_unassign_storage(u16 rn)
369 {
370 	return do_assign_storage(0x000c0001, rn);
371 }
372 
373 struct attach_storage_sccb {
374 	struct sccb_header header;
375 	u16 :16;
376 	u16 assigned;
377 	u32 :32;
378 	u32 entries[0];
379 } __packed;
380 
381 static int sclp_attach_storage(u8 id)
382 {
383 	struct attach_storage_sccb *sccb;
384 	int rc;
385 	int i;
386 
387 	sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
388 	if (!sccb)
389 		return -ENOMEM;
390 	sccb->header.length = PAGE_SIZE;
391 	rc = do_sync_request(0x00080001 | id << 8, sccb);
392 	if (rc)
393 		goto out;
394 	switch (sccb->header.response_code) {
395 	case 0x0020:
396 		set_bit(id, sclp_storage_ids);
397 		for (i = 0; i < sccb->assigned; i++) {
398 			if (sccb->entries[i])
399 				sclp_unassign_storage(sccb->entries[i] >> 16);
400 		}
401 		break;
402 	default:
403 		rc = -EIO;
404 		break;
405 	}
406 out:
407 	free_page((unsigned long) sccb);
408 	return rc;
409 }
410 
411 static int sclp_mem_change_state(unsigned long start, unsigned long size,
412 				 int online)
413 {
414 	struct memory_increment *incr;
415 	unsigned long long istart;
416 	int rc = 0;
417 
418 	list_for_each_entry(incr, &sclp_mem_list, list) {
419 		istart = rn2addr(incr->rn);
420 		if (start + size - 1 < istart)
421 			break;
422 		if (start > istart + rzm - 1)
423 			continue;
424 		if (online) {
425 			if (incr->usecount++)
426 				continue;
427 			/*
428 			 * Don't break the loop if one assign fails. Loop may
429 			 * be walked again on CANCEL and we can't save
430 			 * information if state changed before or not.
431 			 * So continue and increase usecount for all increments.
432 			 */
433 			rc |= sclp_assign_storage(incr->rn);
434 		} else {
435 			if (--incr->usecount)
436 				continue;
437 			sclp_unassign_storage(incr->rn);
438 		}
439 	}
440 	return rc ? -EIO : 0;
441 }
442 
443 static int sclp_mem_notifier(struct notifier_block *nb,
444 			     unsigned long action, void *data)
445 {
446 	unsigned long start, size;
447 	struct memory_notify *arg;
448 	unsigned char id;
449 	int rc = 0;
450 
451 	arg = data;
452 	start = arg->start_pfn << PAGE_SHIFT;
453 	size = arg->nr_pages << PAGE_SHIFT;
454 	mutex_lock(&sclp_mem_mutex);
455 	for_each_clear_bit(id, sclp_storage_ids, sclp_max_storage_id + 1)
456 		sclp_attach_storage(id);
457 	switch (action) {
458 	case MEM_ONLINE:
459 	case MEM_GOING_OFFLINE:
460 	case MEM_CANCEL_OFFLINE:
461 		break;
462 	case MEM_GOING_ONLINE:
463 		rc = sclp_mem_change_state(start, size, 1);
464 		break;
465 	case MEM_CANCEL_ONLINE:
466 		sclp_mem_change_state(start, size, 0);
467 		break;
468 	case MEM_OFFLINE:
469 		sclp_mem_change_state(start, size, 0);
470 		break;
471 	default:
472 		rc = -EINVAL;
473 		break;
474 	}
475 	if (!rc)
476 		sclp_mem_state_changed = 1;
477 	mutex_unlock(&sclp_mem_mutex);
478 	return rc ? NOTIFY_BAD : NOTIFY_OK;
479 }
480 
481 static struct notifier_block sclp_mem_nb = {
482 	.notifier_call = sclp_mem_notifier,
483 };
484 
485 static void __init add_memory_merged(u16 rn)
486 {
487 	static u16 first_rn, num;
488 	unsigned long long start, size;
489 
490 	if (rn && first_rn && (first_rn + num == rn)) {
491 		num++;
492 		return;
493 	}
494 	if (!first_rn)
495 		goto skip_add;
496 	start = rn2addr(first_rn);
497 	size = (unsigned long long ) num * rzm;
498 	if (start >= VMEM_MAX_PHYS)
499 		goto skip_add;
500 	if (start + size > VMEM_MAX_PHYS)
501 		size = VMEM_MAX_PHYS - start;
502 	if (memory_end_set && (start >= memory_end))
503 		goto skip_add;
504 	if (memory_end_set && (start + size > memory_end))
505 		size = memory_end - start;
506 	add_memory(0, start, size);
507 skip_add:
508 	first_rn = rn;
509 	num = 1;
510 }
511 
512 static void __init sclp_add_standby_memory(void)
513 {
514 	struct memory_increment *incr;
515 
516 	list_for_each_entry(incr, &sclp_mem_list, list)
517 		if (incr->standby)
518 			add_memory_merged(incr->rn);
519 	add_memory_merged(0);
520 }
521 
522 static void __init insert_increment(u16 rn, int standby, int assigned)
523 {
524 	struct memory_increment *incr, *new_incr;
525 	struct list_head *prev;
526 	u16 last_rn;
527 
528 	new_incr = kzalloc(sizeof(*new_incr), GFP_KERNEL);
529 	if (!new_incr)
530 		return;
531 	new_incr->rn = rn;
532 	new_incr->standby = standby;
533 	if (!standby)
534 		new_incr->usecount = 1;
535 	last_rn = 0;
536 	prev = &sclp_mem_list;
537 	list_for_each_entry(incr, &sclp_mem_list, list) {
538 		if (assigned && incr->rn > rn)
539 			break;
540 		if (!assigned && incr->rn - last_rn > 1)
541 			break;
542 		last_rn = incr->rn;
543 		prev = &incr->list;
544 	}
545 	if (!assigned)
546 		new_incr->rn = last_rn + 1;
547 	if (new_incr->rn > rnmax) {
548 		kfree(new_incr);
549 		return;
550 	}
551 	list_add(&new_incr->list, prev);
552 }
553 
554 static int sclp_mem_freeze(struct device *dev)
555 {
556 	if (!sclp_mem_state_changed)
557 		return 0;
558 	pr_err("Memory hotplug state changed, suspend refused.\n");
559 	return -EPERM;
560 }
561 
562 struct read_storage_sccb {
563 	struct sccb_header header;
564 	u16 max_id;
565 	u16 assigned;
566 	u16 standby;
567 	u16 :16;
568 	u32 entries[0];
569 } __packed;
570 
571 static const struct dev_pm_ops sclp_mem_pm_ops = {
572 	.freeze		= sclp_mem_freeze,
573 };
574 
575 static struct platform_driver sclp_mem_pdrv = {
576 	.driver = {
577 		.name	= "sclp_mem",
578 		.pm	= &sclp_mem_pm_ops,
579 	},
580 };
581 
582 static int __init sclp_detect_standby_memory(void)
583 {
584 	struct platform_device *sclp_pdev;
585 	struct read_storage_sccb *sccb;
586 	int i, id, assigned, rc;
587 
588 	if (!early_read_info_sccb_valid)
589 		return 0;
590 	if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL)
591 		return 0;
592 	rc = -ENOMEM;
593 	sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA);
594 	if (!sccb)
595 		goto out;
596 	assigned = 0;
597 	for (id = 0; id <= sclp_max_storage_id; id++) {
598 		memset(sccb, 0, PAGE_SIZE);
599 		sccb->header.length = PAGE_SIZE;
600 		rc = do_sync_request(0x00040001 | id << 8, sccb);
601 		if (rc)
602 			goto out;
603 		switch (sccb->header.response_code) {
604 		case 0x0010:
605 			set_bit(id, sclp_storage_ids);
606 			for (i = 0; i < sccb->assigned; i++) {
607 				if (!sccb->entries[i])
608 					continue;
609 				assigned++;
610 				insert_increment(sccb->entries[i] >> 16, 0, 1);
611 			}
612 			break;
613 		case 0x0310:
614 			break;
615 		case 0x0410:
616 			for (i = 0; i < sccb->assigned; i++) {
617 				if (!sccb->entries[i])
618 					continue;
619 				assigned++;
620 				insert_increment(sccb->entries[i] >> 16, 1, 1);
621 			}
622 			break;
623 		default:
624 			rc = -EIO;
625 			break;
626 		}
627 		if (!rc)
628 			sclp_max_storage_id = sccb->max_id;
629 	}
630 	if (rc || list_empty(&sclp_mem_list))
631 		goto out;
632 	for (i = 1; i <= rnmax - assigned; i++)
633 		insert_increment(0, 1, 0);
634 	rc = register_memory_notifier(&sclp_mem_nb);
635 	if (rc)
636 		goto out;
637 	rc = platform_driver_register(&sclp_mem_pdrv);
638 	if (rc)
639 		goto out;
640 	sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0);
641 	rc = IS_ERR(sclp_pdev) ? PTR_ERR(sclp_pdev) : 0;
642 	if (rc)
643 		goto out_driver;
644 	sclp_add_standby_memory();
645 	goto out;
646 out_driver:
647 	platform_driver_unregister(&sclp_mem_pdrv);
648 out:
649 	free_page((unsigned long) sccb);
650 	return rc;
651 }
652 __initcall(sclp_detect_standby_memory);
653 
654 #endif /* CONFIG_MEMORY_HOTPLUG */
655 
656 /*
657  * Channel path configuration related functions.
658  */
659 
660 #define SCLP_CMDW_CONFIGURE_CHPATH		0x000f0001
661 #define SCLP_CMDW_DECONFIGURE_CHPATH		0x000e0001
662 #define SCLP_CMDW_READ_CHPATH_INFORMATION	0x00030001
663 
664 struct chp_cfg_sccb {
665 	struct sccb_header header;
666 	u8 ccm;
667 	u8 reserved[6];
668 	u8 cssid;
669 } __attribute__((packed));
670 
671 static int do_chp_configure(sclp_cmdw_t cmd)
672 {
673 	struct chp_cfg_sccb *sccb;
674 	int rc;
675 
676 	if (!SCLP_HAS_CHP_RECONFIG)
677 		return -EOPNOTSUPP;
678 	/* Prepare sccb. */
679 	sccb = (struct chp_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
680 	if (!sccb)
681 		return -ENOMEM;
682 	sccb->header.length = sizeof(*sccb);
683 	rc = do_sync_request(cmd, sccb);
684 	if (rc)
685 		goto out;
686 	switch (sccb->header.response_code) {
687 	case 0x0020:
688 	case 0x0120:
689 	case 0x0440:
690 	case 0x0450:
691 		break;
692 	default:
693 		pr_warning("configure channel-path failed "
694 			   "(cmd=0x%08x, response=0x%04x)\n", cmd,
695 			   sccb->header.response_code);
696 		rc = -EIO;
697 		break;
698 	}
699 out:
700 	free_page((unsigned long) sccb);
701 	return rc;
702 }
703 
704 /**
705  * sclp_chp_configure - perform configure channel-path sclp command
706  * @chpid: channel-path ID
707  *
708  * Perform configure channel-path command sclp command for specified chpid.
709  * Return 0 after command successfully finished, non-zero otherwise.
710  */
711 int sclp_chp_configure(struct chp_id chpid)
712 {
713 	return do_chp_configure(SCLP_CMDW_CONFIGURE_CHPATH | chpid.id << 8);
714 }
715 
716 /**
717  * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
718  * @chpid: channel-path ID
719  *
720  * Perform deconfigure channel-path command sclp command for specified chpid
721  * and wait for completion. On success return 0. Return non-zero otherwise.
722  */
723 int sclp_chp_deconfigure(struct chp_id chpid)
724 {
725 	return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8);
726 }
727 
728 struct chp_info_sccb {
729 	struct sccb_header header;
730 	u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
731 	u8 standby[SCLP_CHP_INFO_MASK_SIZE];
732 	u8 configured[SCLP_CHP_INFO_MASK_SIZE];
733 	u8 ccm;
734 	u8 reserved[6];
735 	u8 cssid;
736 } __attribute__((packed));
737 
738 /**
739  * sclp_chp_read_info - perform read channel-path information sclp command
740  * @info: resulting channel-path information data
741  *
742  * Perform read channel-path information sclp command and wait for completion.
743  * On success, store channel-path information in @info and return 0. Return
744  * non-zero otherwise.
745  */
746 int sclp_chp_read_info(struct sclp_chp_info *info)
747 {
748 	struct chp_info_sccb *sccb;
749 	int rc;
750 
751 	if (!SCLP_HAS_CHP_INFO)
752 		return -EOPNOTSUPP;
753 	/* Prepare sccb. */
754 	sccb = (struct chp_info_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
755 	if (!sccb)
756 		return -ENOMEM;
757 	sccb->header.length = sizeof(*sccb);
758 	rc = do_sync_request(SCLP_CMDW_READ_CHPATH_INFORMATION, sccb);
759 	if (rc)
760 		goto out;
761 	if (sccb->header.response_code != 0x0010) {
762 		pr_warning("read channel-path info failed "
763 			   "(response=0x%04x)\n", sccb->header.response_code);
764 		rc = -EIO;
765 		goto out;
766 	}
767 	memcpy(info->recognized, sccb->recognized, SCLP_CHP_INFO_MASK_SIZE);
768 	memcpy(info->standby, sccb->standby, SCLP_CHP_INFO_MASK_SIZE);
769 	memcpy(info->configured, sccb->configured, SCLP_CHP_INFO_MASK_SIZE);
770 out:
771 	free_page((unsigned long) sccb);
772 	return rc;
773 }
774