[S390] sclp: convert channel path configure code to use sync interface.
[linux-2.6.git] / drivers / s390 / char / sclp_cmd.c
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 struct read_cpu_info_sccb __initdata early_read_cpu_info_sccb;
195 static struct sclp_cpu_info __initdata sclp_cpu_info;
196
197 static void sclp_fill_cpu_info(struct sclp_cpu_info *info,
198                                struct read_cpu_info_sccb *sccb)
199 {
200         char *page = (char *) sccb;
201
202         memset(info, 0, sizeof(*info));
203         info->configured = sccb->nr_configured;
204         info->standby = sccb->nr_standby;
205         info->combined = sccb->nr_configured + sccb->nr_standby;
206         info->has_cpu_type = sclp_fac84 & 0x1;
207         memcpy(&info->cpu, page + sccb->offset_configured,
208                info->combined * sizeof(struct sclp_cpu_entry));
209 }
210
211 void __init sclp_read_cpu_info_early(void)
212 {
213         int rc;
214         struct read_cpu_info_sccb *sccb;
215
216         if (!SCLP_HAS_CPU_INFO)
217                 return;
218
219         sccb = &early_read_cpu_info_sccb;
220         do {
221                 memset(sccb, 0, sizeof(*sccb));
222                 sccb->header.length = sizeof(*sccb);
223                 rc = sclp_cmd_sync_early(SCLP_CMDW_READ_CPU_INFO, sccb);
224         } while (rc == -EBUSY);
225
226         if (rc)
227                 return;
228         if (sccb->header.response_code != 0x10)
229                 return;
230         sclp_fill_cpu_info(&sclp_cpu_info, sccb);
231 }
232
233 static int __init sclp_get_cpu_info_early(struct sclp_cpu_info *info)
234 {
235         if (!SCLP_HAS_CPU_INFO)
236                 return -EOPNOTSUPP;
237         *info = sclp_cpu_info;
238         return 0;
239 }
240
241 static int sclp_get_cpu_info_late(struct sclp_cpu_info *info)
242 {
243         int rc;
244         struct read_cpu_info_sccb *sccb;
245
246         if (!SCLP_HAS_CPU_INFO)
247                 return -EOPNOTSUPP;
248         sccb = (struct read_cpu_info_sccb *)  __get_free_page(GFP_KERNEL
249                                                               | GFP_DMA);
250         if (!sccb)
251                 return -ENOMEM;
252         memset(sccb, 0, sizeof(*sccb));
253         sccb->header.length = sizeof(*sccb);
254         rc = do_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb);
255         if (rc)
256                 goto out;
257         if (sccb->header.response_code != 0x0010) {
258                 printk(KERN_WARNING TAG "readcpuinfo failed "
259                        "(response=0x%04x)\n", sccb->header.response_code);
260                 rc = -EIO;
261                 goto out;
262         }
263         sclp_fill_cpu_info(info, sccb);
264 out:
265         free_page((unsigned long) sccb);
266         return rc;
267 }
268
269 int __init_refok sclp_get_cpu_info(struct sclp_cpu_info *info)
270 {
271         if (slab_is_available())
272                 return sclp_get_cpu_info_late(info);
273         return sclp_get_cpu_info_early(info);
274 }
275
276 struct cpu_configure_sccb {
277         struct sccb_header header;
278 } __attribute__((packed, aligned(8)));
279
280 static int do_cpu_configure(sclp_cmdw_t cmd)
281 {
282         struct cpu_configure_sccb *sccb;
283         int rc;
284
285         if (!SCLP_HAS_CPU_RECONFIG)
286                 return -EOPNOTSUPP;
287         /*
288          * This is not going to cross a page boundary since we force
289          * kmalloc to have a minimum alignment of 8 bytes on s390.
290          */
291         sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA);
292         if (!sccb)
293                 return -ENOMEM;
294         sccb->header.length = sizeof(*sccb);
295         rc = do_sync_request(cmd, sccb);
296         if (rc)
297                 goto out;
298         switch (sccb->header.response_code) {
299         case 0x0020:
300         case 0x0120:
301                 break;
302         default:
303                 printk(KERN_WARNING TAG "configure cpu failed (cmd=0x%08x, "
304                        "response=0x%04x)\n", cmd, sccb->header.response_code);
305                 rc = -EIO;
306                 break;
307         }
308 out:
309         kfree(sccb);
310         return rc;
311 }
312
313 int sclp_cpu_configure(u8 cpu)
314 {
315         return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8);
316 }
317
318 int sclp_cpu_deconfigure(u8 cpu)
319 {
320         return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);
321 }
322
323 /*
324  * Channel path configuration related functions.
325  */
326
327 #define SCLP_CMDW_CONFIGURE_CHPATH              0x000f0001
328 #define SCLP_CMDW_DECONFIGURE_CHPATH            0x000e0001
329 #define SCLP_CMDW_READ_CHPATH_INFORMATION       0x00030001
330
331 struct chp_cfg_sccb {
332         struct sccb_header header;
333         u8 ccm;
334         u8 reserved[6];
335         u8 cssid;
336 } __attribute__((packed));
337
338 static int do_chp_configure(sclp_cmdw_t cmd)
339 {
340         struct chp_cfg_sccb *sccb;
341         int rc;
342
343         if (!SCLP_HAS_CHP_RECONFIG)
344                 return -EOPNOTSUPP;
345         /* Prepare sccb. */
346         sccb = (struct chp_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
347         if (!sccb)
348                 return -ENOMEM;
349         sccb->header.length = sizeof(*sccb);
350         rc = do_sync_request(cmd, sccb);
351         if (rc)
352                 goto out;
353         switch (sccb->header.response_code) {
354         case 0x0020:
355         case 0x0120:
356         case 0x0440:
357         case 0x0450:
358                 break;
359         default:
360                 printk(KERN_WARNING TAG "configure channel-path failed "
361                        "(cmd=0x%08x, response=0x%04x)\n", cmd,
362                        sccb->header.response_code);
363                 rc = -EIO;
364                 break;
365         }
366 out:
367         free_page((unsigned long) sccb);
368         return rc;
369 }
370
371 /**
372  * sclp_chp_configure - perform configure channel-path sclp command
373  * @chpid: channel-path ID
374  *
375  * Perform configure channel-path command sclp command for specified chpid.
376  * Return 0 after command successfully finished, non-zero otherwise.
377  */
378 int sclp_chp_configure(struct chp_id chpid)
379 {
380         return do_chp_configure(SCLP_CMDW_CONFIGURE_CHPATH | chpid.id << 8);
381 }
382
383 /**
384  * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
385  * @chpid: channel-path ID
386  *
387  * Perform deconfigure channel-path command sclp command for specified chpid
388  * and wait for completion. On success return 0. Return non-zero otherwise.
389  */
390 int sclp_chp_deconfigure(struct chp_id chpid)
391 {
392         return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8);
393 }
394
395 struct chp_info_sccb {
396         struct sccb_header header;
397         u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
398         u8 standby[SCLP_CHP_INFO_MASK_SIZE];
399         u8 configured[SCLP_CHP_INFO_MASK_SIZE];
400         u8 ccm;
401         u8 reserved[6];
402         u8 cssid;
403 } __attribute__((packed));
404
405 /**
406  * sclp_chp_read_info - perform read channel-path information sclp command
407  * @info: resulting channel-path information data
408  *
409  * Perform read channel-path information sclp command and wait for completion.
410  * On success, store channel-path information in @info and return 0. Return
411  * non-zero otherwise.
412  */
413 int sclp_chp_read_info(struct sclp_chp_info *info)
414 {
415         struct chp_info_sccb *sccb;
416         int rc;
417
418         if (!SCLP_HAS_CHP_INFO)
419                 return -EOPNOTSUPP;
420         /* Prepare sccb. */
421         sccb = (struct chp_info_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
422         if (!sccb)
423                 return -ENOMEM;
424         sccb->header.length = sizeof(*sccb);
425         rc = do_sync_request(SCLP_CMDW_READ_CHPATH_INFORMATION, sccb);
426         if (rc)
427                 goto out;
428         if (sccb->header.response_code != 0x0010) {
429                 printk(KERN_WARNING TAG "read channel-path info failed "
430                        "(response=0x%04x)\n", sccb->header.response_code);
431                 rc = -EIO;
432                 goto out;
433         }
434         memcpy(info->recognized, sccb->recognized, SCLP_CHP_INFO_MASK_SIZE);
435         memcpy(info->standby, sccb->standby, SCLP_CHP_INFO_MASK_SIZE);
436         memcpy(info->configured, sccb->configured, SCLP_CHP_INFO_MASK_SIZE);
437 out:
438         free_page((unsigned long) sccb);
439         return rc;
440 }