ba004fd43c05ad651275759f51e26fc9fb0b218e
[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  */
7
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"
15
16 #define TAG     "sclp_cmd: "
17
18 #define SCLP_CMDW_READ_SCP_INFO         0x00020001
19 #define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
20
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)));
38
39 static struct read_info_sccb __initdata early_read_info_sccb;
40 static int __initdata early_read_info_sccb_valid;
41
42 u64 sclp_facilities;
43 static u8 sclp_fac84;
44
45 static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
46 {
47         int rc;
48
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;
61 }
62
63 void __init sclp_read_info_early(void)
64 {
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};
70
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);
79
80                 if (rc)
81                         break;
82                 if (sccb->header.response_code == 0x10) {
83                         early_read_info_sccb_valid = 1;
84                         break;
85                 }
86                 if (sccb->header.response_code != 0x1f0)
87                         break;
88         }
89 }
90
91 void __init sclp_facilities_detect(void)
92 {
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;
97 }
98
99 unsigned long long __init sclp_memory_detect(void)
100 {
101         unsigned long long memsize;
102         struct read_info_sccb *sccb;
103
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;
116 }
117
118 /*
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.
121  */
122 void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
123 {
124         struct read_info_sccb *sccb;
125
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);
133 }
134
135 static void sclp_sync_callback(struct sclp_req *req, void *data)
136 {
137         struct completion *completion = data;
138
139         complete(completion);
140 }
141
142 static int do_sync_request(sclp_cmdw_t cmd, void *sccb)
143 {
144         struct completion completion;
145         struct sclp_req *request;
146         int rc;
147
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);
157
158         /* Perform sclp request. */
159         rc = sclp_add_request(request);
160         if (rc)
161                 goto out;
162         wait_for_completion(&completion);
163
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;
169         }
170 out:
171         kfree(request);
172         return rc;
173 }
174
175 /*
176  * CPU configuration related functions.
177  */
178
179 #define SCLP_CMDW_READ_CPU_INFO         0x00010001
180 #define SCLP_CMDW_CONFIGURE_CPU         0x00110001
181 #define SCLP_CMDW_DECONFIGURE_CPU       0x00100001
182
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)));
191
192 static struct read_cpu_info_sccb __initdata early_read_cpu_info_sccb;
193 static struct sclp_cpu_info __initdata sclp_cpu_info;
194
195 static void sclp_fill_cpu_info(struct sclp_cpu_info *info,
196                                struct read_cpu_info_sccb *sccb)
197 {
198         char *page = (char *) sccb;
199
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));
207 }
208
209 void __init sclp_read_cpu_info_early(void)
210 {
211         int rc;
212         struct read_cpu_info_sccb *sccb;
213
214         if (!SCLP_HAS_CPU_INFO)
215                 return;
216
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);
223
224         if (rc)
225                 return;
226         if (sccb->header.response_code != 0x10)
227                 return;
228         sclp_fill_cpu_info(&sclp_cpu_info, sccb);
229 }
230
231 static int __init sclp_get_cpu_info_early(struct sclp_cpu_info *info)
232 {
233         if (!SCLP_HAS_CPU_INFO)
234                 return -EOPNOTSUPP;
235         *info = sclp_cpu_info;
236         return 0;
237 }
238
239 static int sclp_get_cpu_info_late(struct sclp_cpu_info *info)
240 {
241         int rc;
242         struct read_cpu_info_sccb *sccb;
243
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;
260         }
261         sclp_fill_cpu_info(info, sccb);
262 out:
263         free_page((unsigned long) sccb);
264         return rc;
265 }
266
267 int __init_refok sclp_get_cpu_info(struct sclp_cpu_info *info)
268 {
269         if (slab_is_available())
270                 return sclp_get_cpu_info_late(info);
271         return sclp_get_cpu_info_early(info);
272 }
273
274 struct cpu_configure_sccb {
275         struct sccb_header header;
276 } __attribute__((packed, aligned(8)));
277
278 static int do_cpu_configure(sclp_cmdw_t cmd)
279 {
280         struct cpu_configure_sccb *sccb;
281         int rc;
282
283         if (!SCLP_HAS_CPU_RECONFIG)
284                 return -EOPNOTSUPP;
285         /*
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.
288          */
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;
305         }
306 out:
307         kfree(sccb);
308         return rc;
309 }
310
311 int sclp_cpu_configure(u8 cpu)
312 {
313         return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8);
314 }
315
316 int sclp_cpu_deconfigure(u8 cpu)
317 {
318         return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);
319 }