[S390] Standby cpu activation/deactivation.
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / s390 / char / sclp_cmd.c
blobba004fd43c05ad651275759f51e26fc9fb0b218e
1 /*
2 * drivers/s390/char/sclp_cmd.c
4 * Copyright IBM Corp. 2007
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6 */
8 #include <linux/completion.h>
9 #include <linux/init.h>
10 #include <linux/errno.h>
11 #include <linux/slab.h>
12 #include <linux/string.h>
13 #include <asm/sclp.h>
14 #include "sclp.h"
16 #define TAG "sclp_cmd: "
18 #define SCLP_CMDW_READ_SCP_INFO 0x00020001
19 #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
21 struct read_info_sccb {
22 struct sccb_header header; /* 0-7 */
23 u16 rnmax; /* 8-9 */
24 u8 rnsize; /* 10 */
25 u8 _reserved0[24 - 11]; /* 11-15 */
26 u8 loadparm[8]; /* 24-31 */
27 u8 _reserved1[48 - 32]; /* 32-47 */
28 u64 facilities; /* 48-55 */
29 u8 _reserved2[84 - 56]; /* 56-83 */
30 u8 fac84; /* 84 */
31 u8 _reserved3[91 - 85]; /* 85-90 */
32 u8 flags; /* 91 */
33 u8 _reserved4[100 - 92]; /* 92-99 */
34 u32 rnsize2; /* 100-103 */
35 u64 rnmax2; /* 104-111 */
36 u8 _reserved5[4096 - 112]; /* 112-4095 */
37 } __attribute__((packed, aligned(PAGE_SIZE)));
39 static struct read_info_sccb __initdata early_read_info_sccb;
40 static int __initdata early_read_info_sccb_valid;
42 u64 sclp_facilities;
43 static u8 sclp_fac84;
45 static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
47 int rc;
49 __ctl_set_bit(0, 9);
50 rc = sclp_service_call(cmd, sccb);
51 if (rc)
52 goto out;
53 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
54 PSW_MASK_WAIT | PSW_DEFAULT_KEY);
55 local_irq_disable();
56 out:
57 /* Contents of the sccb might have changed. */
58 barrier();
59 __ctl_clear_bit(0, 9);
60 return rc;
63 void __init sclp_read_info_early(void)
65 int rc;
66 int i;
67 struct read_info_sccb *sccb;
68 sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
69 SCLP_CMDW_READ_SCP_INFO};
71 sccb = &early_read_info_sccb;
72 for (i = 0; i < ARRAY_SIZE(commands); i++) {
73 do {
74 memset(sccb, 0, sizeof(*sccb));
75 sccb->header.length = sizeof(*sccb);
76 sccb->header.control_mask[2] = 0x80;
77 rc = sclp_cmd_sync_early(commands[i], sccb);
78 } while (rc == -EBUSY);
80 if (rc)
81 break;
82 if (sccb->header.response_code == 0x10) {
83 early_read_info_sccb_valid = 1;
84 break;
86 if (sccb->header.response_code != 0x1f0)
87 break;
91 void __init sclp_facilities_detect(void)
93 if (!early_read_info_sccb_valid)
94 return;
95 sclp_facilities = early_read_info_sccb.facilities;
96 sclp_fac84 = early_read_info_sccb.fac84;
99 unsigned long long __init sclp_memory_detect(void)
101 unsigned long long memsize;
102 struct read_info_sccb *sccb;
104 if (!early_read_info_sccb_valid)
105 return 0;
106 sccb = &early_read_info_sccb;
107 if (sccb->rnsize)
108 memsize = sccb->rnsize << 20;
109 else
110 memsize = sccb->rnsize2 << 20;
111 if (sccb->rnmax)
112 memsize *= sccb->rnmax;
113 else
114 memsize *= sccb->rnmax2;
115 return memsize;
119 * This function will be called after sclp_memory_detect(), which gets called
120 * early from early.c code. Therefore the sccb should have valid contents.
122 void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
124 struct read_info_sccb *sccb;
126 if (!early_read_info_sccb_valid)
127 return;
128 sccb = &early_read_info_sccb;
129 info->is_valid = 1;
130 if (sccb->flags & 0x2)
131 info->has_dump = 1;
132 memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
135 static void sclp_sync_callback(struct sclp_req *req, void *data)
137 struct completion *completion = data;
139 complete(completion);
142 static int do_sync_request(sclp_cmdw_t cmd, void *sccb)
144 struct completion completion;
145 struct sclp_req *request;
146 int rc;
148 request = kzalloc(sizeof(*request), GFP_KERNEL);
149 if (!request)
150 return -ENOMEM;
151 request->command = cmd;
152 request->sccb = sccb;
153 request->status = SCLP_REQ_FILLED;
154 request->callback = sclp_sync_callback;
155 request->callback_data = &completion;
156 init_completion(&completion);
158 /* Perform sclp request. */
159 rc = sclp_add_request(request);
160 if (rc)
161 goto out;
162 wait_for_completion(&completion);
164 /* Check response. */
165 if (request->status != SCLP_REQ_DONE) {
166 printk(KERN_WARNING TAG "sync request failed "
167 "(cmd=0x%08x, status=0x%02x)\n", cmd, request->status);
168 rc = -EIO;
170 out:
171 kfree(request);
172 return rc;
176 * CPU configuration related functions.
179 #define SCLP_CMDW_READ_CPU_INFO 0x00010001
180 #define SCLP_CMDW_CONFIGURE_CPU 0x00110001
181 #define SCLP_CMDW_DECONFIGURE_CPU 0x00100001
183 struct read_cpu_info_sccb {
184 struct sccb_header header;
185 u16 nr_configured;
186 u16 offset_configured;
187 u16 nr_standby;
188 u16 offset_standby;
189 u8 reserved[4096 - 16];
190 } __attribute__((packed, aligned(PAGE_SIZE)));
192 static struct read_cpu_info_sccb __initdata early_read_cpu_info_sccb;
193 static struct sclp_cpu_info __initdata sclp_cpu_info;
195 static void sclp_fill_cpu_info(struct sclp_cpu_info *info,
196 struct read_cpu_info_sccb *sccb)
198 char *page = (char *) sccb;
200 memset(info, 0, sizeof(*info));
201 info->configured = sccb->nr_configured;
202 info->standby = sccb->nr_standby;
203 info->combined = sccb->nr_configured + sccb->nr_standby;
204 info->has_cpu_type = sclp_fac84 & 0x1;
205 memcpy(&info->cpu, page + sccb->offset_configured,
206 info->combined * sizeof(struct sclp_cpu_entry));
209 void __init sclp_read_cpu_info_early(void)
211 int rc;
212 struct read_cpu_info_sccb *sccb;
214 if (!SCLP_HAS_CPU_INFO)
215 return;
217 sccb = &early_read_cpu_info_sccb;
218 do {
219 memset(sccb, 0, sizeof(*sccb));
220 sccb->header.length = sizeof(*sccb);
221 rc = sclp_cmd_sync_early(SCLP_CMDW_READ_CPU_INFO, sccb);
222 } while (rc == -EBUSY);
224 if (rc)
225 return;
226 if (sccb->header.response_code != 0x10)
227 return;
228 sclp_fill_cpu_info(&sclp_cpu_info, sccb);
231 static int __init sclp_get_cpu_info_early(struct sclp_cpu_info *info)
233 if (!SCLP_HAS_CPU_INFO)
234 return -EOPNOTSUPP;
235 *info = sclp_cpu_info;
236 return 0;
239 static int sclp_get_cpu_info_late(struct sclp_cpu_info *info)
241 int rc;
242 struct read_cpu_info_sccb *sccb;
244 if (!SCLP_HAS_CPU_INFO)
245 return -EOPNOTSUPP;
246 sccb = (struct read_cpu_info_sccb *) __get_free_page(GFP_KERNEL
247 | GFP_DMA);
248 if (!sccb)
249 return -ENOMEM;
250 memset(sccb, 0, sizeof(*sccb));
251 sccb->header.length = sizeof(*sccb);
252 rc = do_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb);
253 if (rc)
254 goto out;
255 if (sccb->header.response_code != 0x0010) {
256 printk(KERN_WARNING TAG "readcpuinfo failed "
257 "(response=0x%04x)\n", sccb->header.response_code);
258 rc = -EIO;
259 goto out;
261 sclp_fill_cpu_info(info, sccb);
262 out:
263 free_page((unsigned long) sccb);
264 return rc;
267 int __init_refok sclp_get_cpu_info(struct sclp_cpu_info *info)
269 if (slab_is_available())
270 return sclp_get_cpu_info_late(info);
271 return sclp_get_cpu_info_early(info);
274 struct cpu_configure_sccb {
275 struct sccb_header header;
276 } __attribute__((packed, aligned(8)));
278 static int do_cpu_configure(sclp_cmdw_t cmd)
280 struct cpu_configure_sccb *sccb;
281 int rc;
283 if (!SCLP_HAS_CPU_RECONFIG)
284 return -EOPNOTSUPP;
286 * This is not going to cross a page boundary since we force
287 * kmalloc to have a minimum alignment of 8 bytes on s390.
289 sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA);
290 if (!sccb)
291 return -ENOMEM;
292 sccb->header.length = sizeof(*sccb);
293 rc = do_sync_request(cmd, sccb);
294 if (rc)
295 goto out;
296 switch (sccb->header.response_code) {
297 case 0x0020:
298 case 0x0120:
299 break;
300 default:
301 printk(KERN_WARNING TAG "configure cpu failed (cmd=0x%08x, "
302 "response=0x%04x)\n", cmd, sccb->header.response_code);
303 rc = -EIO;
304 break;
306 out:
307 kfree(sccb);
308 return rc;
311 int sclp_cpu_configure(u8 cpu)
313 return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8);
316 int sclp_cpu_deconfigure(u8 cpu)
318 return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);