xref: /openbmc/linux/drivers/s390/char/sclp_cmd.c (revision 22246614)
1 /*
2  *  drivers/s390/char/sclp_cmd.c
3  *
4  *    Copyright IBM Corp. 2007
5  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
6  *		 Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
7  */
8 
9 #include <linux/completion.h>
10 #include <linux/init.h>
11 #include <linux/errno.h>
12 #include <linux/slab.h>
13 #include <linux/string.h>
14 #include <asm/chpid.h>
15 #include <asm/sclp.h>
16 #include "sclp.h"
17 
18 #define TAG	"sclp_cmd: "
19 
20 #define SCLP_CMDW_READ_SCP_INFO		0x00020001
21 #define SCLP_CMDW_READ_SCP_INFO_FORCED	0x00120001
22 
23 struct read_info_sccb {
24 	struct	sccb_header header;	/* 0-7 */
25 	u16	rnmax;			/* 8-9 */
26 	u8	rnsize;			/* 10 */
27 	u8	_reserved0[24 - 11];	/* 11-15 */
28 	u8	loadparm[8];		/* 24-31 */
29 	u8	_reserved1[48 - 32];	/* 32-47 */
30 	u64	facilities;		/* 48-55 */
31 	u8	_reserved2[84 - 56];	/* 56-83 */
32 	u8	fac84;			/* 84 */
33 	u8	_reserved3[91 - 85];	/* 85-90 */
34 	u8	flags;			/* 91 */
35 	u8	_reserved4[100 - 92];	/* 92-99 */
36 	u32	rnsize2;		/* 100-103 */
37 	u64	rnmax2;			/* 104-111 */
38 	u8	_reserved5[4096 - 112];	/* 112-4095 */
39 } __attribute__((packed, aligned(PAGE_SIZE)));
40 
41 static struct read_info_sccb __initdata early_read_info_sccb;
42 static int __initdata early_read_info_sccb_valid;
43 
44 u64 sclp_facilities;
45 static u8 sclp_fac84;
46 
47 static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
48 {
49 	int rc;
50 
51 	__ctl_set_bit(0, 9);
52 	rc = sclp_service_call(cmd, sccb);
53 	if (rc)
54 		goto out;
55 	__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
56 			PSW_MASK_WAIT | PSW_DEFAULT_KEY);
57 	local_irq_disable();
58 out:
59 	/* Contents of the sccb might have changed. */
60 	barrier();
61 	__ctl_clear_bit(0, 9);
62 	return rc;
63 }
64 
65 void __init sclp_read_info_early(void)
66 {
67 	int rc;
68 	int i;
69 	struct read_info_sccb *sccb;
70 	sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
71 				  SCLP_CMDW_READ_SCP_INFO};
72 
73 	sccb = &early_read_info_sccb;
74 	for (i = 0; i < ARRAY_SIZE(commands); i++) {
75 		do {
76 			memset(sccb, 0, sizeof(*sccb));
77 			sccb->header.length = sizeof(*sccb);
78 			sccb->header.control_mask[2] = 0x80;
79 			rc = sclp_cmd_sync_early(commands[i], sccb);
80 		} while (rc == -EBUSY);
81 
82 		if (rc)
83 			break;
84 		if (sccb->header.response_code == 0x10) {
85 			early_read_info_sccb_valid = 1;
86 			break;
87 		}
88 		if (sccb->header.response_code != 0x1f0)
89 			break;
90 	}
91 }
92 
93 void __init sclp_facilities_detect(void)
94 {
95 	if (!early_read_info_sccb_valid)
96 		return;
97 	sclp_facilities = early_read_info_sccb.facilities;
98 	sclp_fac84 = early_read_info_sccb.fac84;
99 }
100 
101 unsigned long long __init sclp_memory_detect(void)
102 {
103 	unsigned long long memsize;
104 	struct read_info_sccb *sccb;
105 
106 	if (!early_read_info_sccb_valid)
107 		return 0;
108 	sccb = &early_read_info_sccb;
109 	if (sccb->rnsize)
110 		memsize = sccb->rnsize << 20;
111 	else
112 		memsize = sccb->rnsize2 << 20;
113 	if (sccb->rnmax)
114 		memsize *= sccb->rnmax;
115 	else
116 		memsize *= sccb->rnmax2;
117 	return memsize;
118 }
119 
120 /*
121  * This function will be called after sclp_memory_detect(), which gets called
122  * early from early.c code. Therefore the sccb should have valid contents.
123  */
124 void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
125 {
126 	struct read_info_sccb *sccb;
127 
128 	if (!early_read_info_sccb_valid)
129 		return;
130 	sccb = &early_read_info_sccb;
131 	info->is_valid = 1;
132 	if (sccb->flags & 0x2)
133 		info->has_dump = 1;
134 	memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
135 }
136 
137 static void sclp_sync_callback(struct sclp_req *req, void *data)
138 {
139 	struct completion *completion = data;
140 
141 	complete(completion);
142 }
143 
144 static int do_sync_request(sclp_cmdw_t cmd, void *sccb)
145 {
146 	struct completion completion;
147 	struct sclp_req *request;
148 	int rc;
149 
150 	request = kzalloc(sizeof(*request), GFP_KERNEL);
151 	if (!request)
152 		return -ENOMEM;
153 	request->command = cmd;
154 	request->sccb = sccb;
155 	request->status = SCLP_REQ_FILLED;
156 	request->callback = sclp_sync_callback;
157 	request->callback_data = &completion;
158 	init_completion(&completion);
159 
160 	/* Perform sclp request. */
161 	rc = sclp_add_request(request);
162 	if (rc)
163 		goto out;
164 	wait_for_completion(&completion);
165 
166 	/* Check response. */
167 	if (request->status != SCLP_REQ_DONE) {
168 		printk(KERN_WARNING TAG "sync request failed "
169 		       "(cmd=0x%08x, status=0x%02x)\n", cmd, request->status);
170 		rc = -EIO;
171 	}
172 out:
173 	kfree(request);
174 	return rc;
175 }
176 
177 /*
178  * CPU configuration related functions.
179  */
180 
181 #define SCLP_CMDW_READ_CPU_INFO		0x00010001
182 #define SCLP_CMDW_CONFIGURE_CPU		0x00110001
183 #define SCLP_CMDW_DECONFIGURE_CPU	0x00100001
184 
185 struct read_cpu_info_sccb {
186 	struct	sccb_header header;
187 	u16	nr_configured;
188 	u16	offset_configured;
189 	u16	nr_standby;
190 	u16	offset_standby;
191 	u8	reserved[4096 - 16];
192 } __attribute__((packed, aligned(PAGE_SIZE)));
193 
194 static void sclp_fill_cpu_info(struct sclp_cpu_info *info,
195 			       struct read_cpu_info_sccb *sccb)
196 {
197 	char *page = (char *) sccb;
198 
199 	memset(info, 0, sizeof(*info));
200 	info->configured = sccb->nr_configured;
201 	info->standby = sccb->nr_standby;
202 	info->combined = sccb->nr_configured + sccb->nr_standby;
203 	info->has_cpu_type = sclp_fac84 & 0x1;
204 	memcpy(&info->cpu, page + sccb->offset_configured,
205 	       info->combined * sizeof(struct sclp_cpu_entry));
206 }
207 
208 int sclp_get_cpu_info(struct sclp_cpu_info *info)
209 {
210 	int rc;
211 	struct read_cpu_info_sccb *sccb;
212 
213 	if (!SCLP_HAS_CPU_INFO)
214 		return -EOPNOTSUPP;
215 	sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
216 	if (!sccb)
217 		return -ENOMEM;
218 	sccb->header.length = sizeof(*sccb);
219 	rc = do_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb);
220 	if (rc)
221 		goto out;
222 	if (sccb->header.response_code != 0x0010) {
223 		printk(KERN_WARNING TAG "readcpuinfo failed "
224 		       "(response=0x%04x)\n", sccb->header.response_code);
225 		rc = -EIO;
226 		goto out;
227 	}
228 	sclp_fill_cpu_info(info, sccb);
229 out:
230 	free_page((unsigned long) sccb);
231 	return rc;
232 }
233 
234 struct cpu_configure_sccb {
235 	struct sccb_header header;
236 } __attribute__((packed, aligned(8)));
237 
238 static int do_cpu_configure(sclp_cmdw_t cmd)
239 {
240 	struct cpu_configure_sccb *sccb;
241 	int rc;
242 
243 	if (!SCLP_HAS_CPU_RECONFIG)
244 		return -EOPNOTSUPP;
245 	/*
246 	 * This is not going to cross a page boundary since we force
247 	 * kmalloc to have a minimum alignment of 8 bytes on s390.
248 	 */
249 	sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA);
250 	if (!sccb)
251 		return -ENOMEM;
252 	sccb->header.length = sizeof(*sccb);
253 	rc = do_sync_request(cmd, sccb);
254 	if (rc)
255 		goto out;
256 	switch (sccb->header.response_code) {
257 	case 0x0020:
258 	case 0x0120:
259 		break;
260 	default:
261 		printk(KERN_WARNING TAG "configure cpu failed (cmd=0x%08x, "
262 		       "response=0x%04x)\n", cmd, sccb->header.response_code);
263 		rc = -EIO;
264 		break;
265 	}
266 out:
267 	kfree(sccb);
268 	return rc;
269 }
270 
271 int sclp_cpu_configure(u8 cpu)
272 {
273 	return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8);
274 }
275 
276 int sclp_cpu_deconfigure(u8 cpu)
277 {
278 	return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);
279 }
280 
281 /*
282  * Channel path configuration related functions.
283  */
284 
285 #define SCLP_CMDW_CONFIGURE_CHPATH		0x000f0001
286 #define SCLP_CMDW_DECONFIGURE_CHPATH		0x000e0001
287 #define SCLP_CMDW_READ_CHPATH_INFORMATION	0x00030001
288 
289 struct chp_cfg_sccb {
290 	struct sccb_header header;
291 	u8 ccm;
292 	u8 reserved[6];
293 	u8 cssid;
294 } __attribute__((packed));
295 
296 static int do_chp_configure(sclp_cmdw_t cmd)
297 {
298 	struct chp_cfg_sccb *sccb;
299 	int rc;
300 
301 	if (!SCLP_HAS_CHP_RECONFIG)
302 		return -EOPNOTSUPP;
303 	/* Prepare sccb. */
304 	sccb = (struct chp_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
305 	if (!sccb)
306 		return -ENOMEM;
307 	sccb->header.length = sizeof(*sccb);
308 	rc = do_sync_request(cmd, sccb);
309 	if (rc)
310 		goto out;
311 	switch (sccb->header.response_code) {
312 	case 0x0020:
313 	case 0x0120:
314 	case 0x0440:
315 	case 0x0450:
316 		break;
317 	default:
318 		printk(KERN_WARNING TAG "configure channel-path failed "
319 		       "(cmd=0x%08x, response=0x%04x)\n", cmd,
320 		       sccb->header.response_code);
321 		rc = -EIO;
322 		break;
323 	}
324 out:
325 	free_page((unsigned long) sccb);
326 	return rc;
327 }
328 
329 /**
330  * sclp_chp_configure - perform configure channel-path sclp command
331  * @chpid: channel-path ID
332  *
333  * Perform configure channel-path command sclp command for specified chpid.
334  * Return 0 after command successfully finished, non-zero otherwise.
335  */
336 int sclp_chp_configure(struct chp_id chpid)
337 {
338 	return do_chp_configure(SCLP_CMDW_CONFIGURE_CHPATH | chpid.id << 8);
339 }
340 
341 /**
342  * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
343  * @chpid: channel-path ID
344  *
345  * Perform deconfigure channel-path command sclp command for specified chpid
346  * and wait for completion. On success return 0. Return non-zero otherwise.
347  */
348 int sclp_chp_deconfigure(struct chp_id chpid)
349 {
350 	return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8);
351 }
352 
353 struct chp_info_sccb {
354 	struct sccb_header header;
355 	u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
356 	u8 standby[SCLP_CHP_INFO_MASK_SIZE];
357 	u8 configured[SCLP_CHP_INFO_MASK_SIZE];
358 	u8 ccm;
359 	u8 reserved[6];
360 	u8 cssid;
361 } __attribute__((packed));
362 
363 /**
364  * sclp_chp_read_info - perform read channel-path information sclp command
365  * @info: resulting channel-path information data
366  *
367  * Perform read channel-path information sclp command and wait for completion.
368  * On success, store channel-path information in @info and return 0. Return
369  * non-zero otherwise.
370  */
371 int sclp_chp_read_info(struct sclp_chp_info *info)
372 {
373 	struct chp_info_sccb *sccb;
374 	int rc;
375 
376 	if (!SCLP_HAS_CHP_INFO)
377 		return -EOPNOTSUPP;
378 	/* Prepare sccb. */
379 	sccb = (struct chp_info_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
380 	if (!sccb)
381 		return -ENOMEM;
382 	sccb->header.length = sizeof(*sccb);
383 	rc = do_sync_request(SCLP_CMDW_READ_CHPATH_INFORMATION, sccb);
384 	if (rc)
385 		goto out;
386 	if (sccb->header.response_code != 0x0010) {
387 		printk(KERN_WARNING TAG "read channel-path info failed "
388 		       "(response=0x%04x)\n", sccb->header.response_code);
389 		rc = -EIO;
390 		goto out;
391 	}
392 	memcpy(info->recognized, sccb->recognized, SCLP_CHP_INFO_MASK_SIZE);
393 	memcpy(info->standby, sccb->standby, SCLP_CHP_INFO_MASK_SIZE);
394 	memcpy(info->configured, sccb->configured, SCLP_CHP_INFO_MASK_SIZE);
395 out:
396 	free_page((unsigned long) sccb);
397 	return rc;
398 }
399