2 * drivers/s390/char/sclp_cmd.c
4 * Copyright IBM Corp. 2007
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
6 * Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
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>
18 #define TAG "sclp_cmd: "
20 #define SCLP_CMDW_READ_SCP_INFO 0x00020001
21 #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
23 struct read_info_sccb {
24 struct sccb_header header; /* 0-7 */
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 */
33 u8 _reserved3[91 - 85]; /* 85-90 */
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)));
41 static struct read_info_sccb __initdata early_read_info_sccb;
42 static int __initdata early_read_info_sccb_valid;
47 static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
52 rc = sclp_service_call(cmd, sccb);
55 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
56 PSW_MASK_WAIT | PSW_DEFAULT_KEY);
59 /* Contents of the sccb might have changed. */
61 __ctl_clear_bit(0, 9);
65 void __init sclp_read_info_early(void)
69 struct read_info_sccb *sccb;
70 sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
71 SCLP_CMDW_READ_SCP_INFO};
73 sccb = &early_read_info_sccb;
74 for (i = 0; i < ARRAY_SIZE(commands); i++) {
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);
84 if (sccb->header.response_code == 0x10) {
85 early_read_info_sccb_valid = 1;
88 if (sccb->header.response_code != 0x1f0)
93 void __init sclp_facilities_detect(void)
95 if (!early_read_info_sccb_valid)
97 sclp_facilities = early_read_info_sccb.facilities;
98 sclp_fac84 = early_read_info_sccb.fac84;
101 unsigned long long __init sclp_memory_detect(void)
103 unsigned long long memsize;
104 struct read_info_sccb *sccb;
106 if (!early_read_info_sccb_valid)
108 sccb = &early_read_info_sccb;
110 memsize = sccb->rnsize << 20;
112 memsize = sccb->rnsize2 << 20;
114 memsize *= sccb->rnmax;
116 memsize *= sccb->rnmax2;
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.
124 void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
126 struct read_info_sccb *sccb;
128 if (!early_read_info_sccb_valid)
130 sccb = &early_read_info_sccb;
132 if (sccb->flags & 0x2)
134 memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
137 static void sclp_sync_callback(struct sclp_req *req, void *data)
139 struct completion *completion = data;
141 complete(completion);
144 static int do_sync_request(sclp_cmdw_t cmd, void *sccb)
146 struct completion completion;
147 struct sclp_req *request;
150 request = kzalloc(sizeof(*request), GFP_KERNEL);
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);
160 /* Perform sclp request. */
161 rc = sclp_add_request(request);
164 wait_for_completion(&completion);
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);
178 * CPU configuration related functions.
181 #define SCLP_CMDW_READ_CPU_INFO 0x00010001
182 #define SCLP_CMDW_CONFIGURE_CPU 0x00110001
183 #define SCLP_CMDW_DECONFIGURE_CPU 0x00100001
185 struct read_cpu_info_sccb {
186 struct sccb_header header;
188 u16 offset_configured;
191 u8 reserved[4096 - 16];
192 } __attribute__((packed, aligned(PAGE_SIZE)));
194 static void sclp_fill_cpu_info(struct sclp_cpu_info *info,
195 struct read_cpu_info_sccb *sccb)
197 char *page = (char *) sccb;
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));
208 int sclp_get_cpu_info(struct sclp_cpu_info *info)
211 struct read_cpu_info_sccb *sccb;
213 if (!SCLP_HAS_CPU_INFO)
215 sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
218 sccb->header.length = sizeof(*sccb);
219 rc = do_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb);
222 if (sccb->header.response_code != 0x0010) {
223 printk(KERN_WARNING TAG "readcpuinfo failed "
224 "(response=0x%04x)\n", sccb->header.response_code);
228 sclp_fill_cpu_info(info, sccb);
230 free_page((unsigned long) sccb);
234 struct cpu_configure_sccb {
235 struct sccb_header header;
236 } __attribute__((packed, aligned(8)));
238 static int do_cpu_configure(sclp_cmdw_t cmd)
240 struct cpu_configure_sccb *sccb;
243 if (!SCLP_HAS_CPU_RECONFIG)
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.
249 sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA);
252 sccb->header.length = sizeof(*sccb);
253 rc = do_sync_request(cmd, sccb);
256 switch (sccb->header.response_code) {
261 printk(KERN_WARNING TAG "configure cpu failed (cmd=0x%08x, "
262 "response=0x%04x)\n", cmd, sccb->header.response_code);
271 int sclp_cpu_configure(u8 cpu)
273 return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8);
276 int sclp_cpu_deconfigure(u8 cpu)
278 return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);
282 * Channel path configuration related functions.
285 #define SCLP_CMDW_CONFIGURE_CHPATH 0x000f0001
286 #define SCLP_CMDW_DECONFIGURE_CHPATH 0x000e0001
287 #define SCLP_CMDW_READ_CHPATH_INFORMATION 0x00030001
289 struct chp_cfg_sccb {
290 struct sccb_header header;
294 } __attribute__((packed));
296 static int do_chp_configure(sclp_cmdw_t cmd)
298 struct chp_cfg_sccb *sccb;
301 if (!SCLP_HAS_CHP_RECONFIG)
304 sccb = (struct chp_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
307 sccb->header.length = sizeof(*sccb);
308 rc = do_sync_request(cmd, sccb);
311 switch (sccb->header.response_code) {
318 printk(KERN_WARNING TAG "configure channel-path failed "
319 "(cmd=0x%08x, response=0x%04x)\n", cmd,
320 sccb->header.response_code);
325 free_page((unsigned long) sccb);
330 * sclp_chp_configure - perform configure channel-path sclp command
331 * @chpid: channel-path ID
333 * Perform configure channel-path command sclp command for specified chpid.
334 * Return 0 after command successfully finished, non-zero otherwise.
336 int sclp_chp_configure(struct chp_id chpid)
338 return do_chp_configure(SCLP_CMDW_CONFIGURE_CHPATH | chpid.id << 8);
342 * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
343 * @chpid: channel-path ID
345 * Perform deconfigure channel-path command sclp command for specified chpid
346 * and wait for completion. On success return 0. Return non-zero otherwise.
348 int sclp_chp_deconfigure(struct chp_id chpid)
350 return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8);
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];
361 } __attribute__((packed));
364 * sclp_chp_read_info - perform read channel-path information sclp command
365 * @info: resulting channel-path information data
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.
371 int sclp_chp_read_info(struct sclp_chp_info *info)
373 struct chp_info_sccb *sccb;
376 if (!SCLP_HAS_CHP_INFO)
379 sccb = (struct chp_info_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
382 sccb->header.length = sizeof(*sccb);
383 rc = do_sync_request(SCLP_CMDW_READ_CHPATH_INFORMATION, sccb);
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);
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);
396 free_page((unsigned long) sccb);