Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[pandora-kernel.git] / arch / s390 / kernel / ipl.c
1 /*
2  *  arch/s390/kernel/ipl.c
3  *    ipl/reipl/dump support for Linux on s390.
4  *
5  *    Copyright (C) IBM Corp. 2005,2006
6  *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
7  *               Heiko Carstens <heiko.carstens@de.ibm.com>
8  *               Volker Sameske <sameske@de.ibm.com>
9  */
10
11 #include <linux/types.h>
12 #include <linux/module.h>
13 #include <linux/device.h>
14 #include <linux/delay.h>
15 #include <linux/reboot.h>
16 #include <linux/ctype.h>
17 #include <asm/ipl.h>
18 #include <asm/smp.h>
19 #include <asm/setup.h>
20 #include <asm/cpcmd.h>
21 #include <asm/cio.h>
22 #include <asm/ebcdic.h>
23 #include <asm/reset.h>
24 #include <asm/sclp.h>
25
26 #define IPL_PARM_BLOCK_VERSION 0
27
28 #define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
29 #define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
30 #define SCCB_FLAG (s390_readinfo_sccb.flags)
31
32 enum ipl_type {
33         IPL_TYPE_NONE    = 1,
34         IPL_TYPE_UNKNOWN = 2,
35         IPL_TYPE_CCW     = 4,
36         IPL_TYPE_FCP     = 8,
37         IPL_TYPE_NSS     = 16,
38 };
39
40 #define IPL_NONE_STR     "none"
41 #define IPL_UNKNOWN_STR  "unknown"
42 #define IPL_CCW_STR      "ccw"
43 #define IPL_FCP_STR      "fcp"
44 #define IPL_NSS_STR      "nss"
45
46 /*
47  * Must be in data section since the bss section
48  * is not cleared when these are accessed.
49  */
50 u16 ipl_devno __attribute__((__section__(".data"))) = 0;
51 u32 ipl_flags __attribute__((__section__(".data"))) = 0;
52
53 static char *ipl_type_str(enum ipl_type type)
54 {
55         switch (type) {
56         case IPL_TYPE_NONE:
57                 return IPL_NONE_STR;
58         case IPL_TYPE_CCW:
59                 return IPL_CCW_STR;
60         case IPL_TYPE_FCP:
61                 return IPL_FCP_STR;
62         case IPL_TYPE_NSS:
63                 return IPL_NSS_STR;
64         case IPL_TYPE_UNKNOWN:
65         default:
66                 return IPL_UNKNOWN_STR;
67         }
68 }
69
70 enum ipl_method {
71         IPL_METHOD_NONE,
72         IPL_METHOD_CCW_CIO,
73         IPL_METHOD_CCW_DIAG,
74         IPL_METHOD_CCW_VM,
75         IPL_METHOD_FCP_RO_DIAG,
76         IPL_METHOD_FCP_RW_DIAG,
77         IPL_METHOD_FCP_RO_VM,
78         IPL_METHOD_NSS,
79 };
80
81 enum shutdown_action {
82         SHUTDOWN_REIPL,
83         SHUTDOWN_DUMP,
84         SHUTDOWN_STOP,
85 };
86
87 #define SHUTDOWN_REIPL_STR "reipl"
88 #define SHUTDOWN_DUMP_STR  "dump"
89 #define SHUTDOWN_STOP_STR  "stop"
90
91 static char *shutdown_action_str(enum shutdown_action action)
92 {
93         switch (action) {
94         case SHUTDOWN_REIPL:
95                 return SHUTDOWN_REIPL_STR;
96         case SHUTDOWN_DUMP:
97                 return SHUTDOWN_DUMP_STR;
98         case SHUTDOWN_STOP:
99                 return SHUTDOWN_STOP_STR;
100         default:
101                 return NULL;
102         }
103 }
104
105 static int diag308_set_works = 0;
106
107 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
108
109 static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
110 static enum ipl_method reipl_method = IPL_METHOD_NONE;
111 static struct ipl_parameter_block *reipl_block_fcp;
112 static struct ipl_parameter_block *reipl_block_ccw;
113
114 static char reipl_nss_name[NSS_NAME_SIZE + 1];
115
116 static int dump_capabilities = IPL_TYPE_NONE;
117 static enum ipl_type dump_type = IPL_TYPE_NONE;
118 static enum ipl_method dump_method = IPL_METHOD_NONE;
119 static struct ipl_parameter_block *dump_block_fcp;
120 static struct ipl_parameter_block *dump_block_ccw;
121
122 static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
123
124 int diag308(unsigned long subcode, void *addr)
125 {
126         register unsigned long _addr asm("0") = (unsigned long) addr;
127         register unsigned long _rc asm("1") = 0;
128
129         asm volatile(
130                 "       diag    %0,%2,0x308\n"
131                 "0:\n"
132                 EX_TABLE(0b,0b)
133                 : "+d" (_addr), "+d" (_rc)
134                 : "d" (subcode) : "cc", "memory");
135         return _rc;
136 }
137
138 /* SYSFS */
139
140 #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value)             \
141 static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
142                 char *page)                                             \
143 {                                                                       \
144         return sprintf(page, _format, _value);                          \
145 }                                                                       \
146 static struct subsys_attribute sys_##_prefix##_##_name##_attr =         \
147         __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
148
149 #define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)   \
150 static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
151                 char *page)                                             \
152 {                                                                       \
153         return sprintf(page, _fmt_out,                                  \
154                         (unsigned long long) _value);                   \
155 }                                                                       \
156 static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
157                 const char *buf, size_t len)                            \
158 {                                                                       \
159         unsigned long long value;                                       \
160         if (sscanf(buf, _fmt_in, &value) != 1)                          \
161                 return -EINVAL;                                         \
162         _value = value;                                                 \
163         return len;                                                     \
164 }                                                                       \
165 static struct subsys_attribute sys_##_prefix##_##_name##_attr =         \
166         __ATTR(_name,(S_IRUGO | S_IWUSR),                               \
167                         sys_##_prefix##_##_name##_show,                 \
168                         sys_##_prefix##_##_name##_store);
169
170 #define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
171 static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
172                 char *page)                                             \
173 {                                                                       \
174         return sprintf(page, _fmt_out, _value);                         \
175 }                                                                       \
176 static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
177                 const char *buf, size_t len)                            \
178 {                                                                       \
179         if (sscanf(buf, _fmt_in, _value) != 1)                          \
180                 return -EINVAL;                                         \
181         return len;                                                     \
182 }                                                                       \
183 static struct subsys_attribute sys_##_prefix##_##_name##_attr =         \
184         __ATTR(_name,(S_IRUGO | S_IWUSR),                               \
185                         sys_##_prefix##_##_name##_show,                 \
186                         sys_##_prefix##_##_name##_store);
187
188 static void make_attrs_ro(struct attribute **attrs)
189 {
190         while (*attrs) {
191                 (*attrs)->mode = S_IRUGO;
192                 attrs++;
193         }
194 }
195
196 /*
197  * ipl section
198  */
199
200 static enum ipl_type ipl_get_type(void)
201 {
202         struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
203
204         if (ipl_flags & IPL_NSS_VALID)
205                 return IPL_TYPE_NSS;
206         if (!(ipl_flags & IPL_DEVNO_VALID))
207                 return IPL_TYPE_UNKNOWN;
208         if (!(ipl_flags & IPL_PARMBLOCK_VALID))
209                 return IPL_TYPE_CCW;
210         if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION)
211                 return IPL_TYPE_UNKNOWN;
212         if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
213                 return IPL_TYPE_UNKNOWN;
214         return IPL_TYPE_FCP;
215 }
216
217 static ssize_t ipl_type_show(struct subsystem *subsys, char *page)
218 {
219         return sprintf(page, "%s\n", ipl_type_str(ipl_get_type()));
220 }
221
222 static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
223
224 static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page)
225 {
226         struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
227
228         switch (ipl_get_type()) {
229         case IPL_TYPE_CCW:
230                 return sprintf(page, "0.0.%04x\n", ipl_devno);
231         case IPL_TYPE_FCP:
232                 return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
233         default:
234                 return 0;
235         }
236 }
237
238 static struct subsys_attribute sys_ipl_device_attr =
239         __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
240
241 static ssize_t ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off,
242                                   size_t count)
243 {
244         unsigned int size = IPL_PARMBLOCK_SIZE;
245
246         if (off > size)
247                 return 0;
248         if (off + count > size)
249                 count = size - off;
250         memcpy(buf, (void *)IPL_PARMBLOCK_START + off, count);
251         return count;
252 }
253
254 static struct bin_attribute ipl_parameter_attr = {
255         .attr = {
256                 .name = "binary_parameter",
257                 .mode = S_IRUGO,
258                 .owner = THIS_MODULE,
259         },
260         .size = PAGE_SIZE,
261         .read = &ipl_parameter_read,
262 };
263
264 static ssize_t ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off,
265         size_t count)
266 {
267         unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
268         void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
269
270         if (off > size)
271                 return 0;
272         if (off + count > size)
273                 count = size - off;
274         memcpy(buf, scp_data + off, count);
275         return count;
276 }
277
278 static struct bin_attribute ipl_scp_data_attr = {
279         .attr = {
280                 .name = "scp_data",
281                 .mode = S_IRUGO,
282                 .owner = THIS_MODULE,
283         },
284         .size = PAGE_SIZE,
285         .read = &ipl_scp_data_read,
286 };
287
288 /* FCP ipl device attributes */
289
290 DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long)
291                    IPL_PARMBLOCK_START->ipl_info.fcp.wwpn);
292 DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long)
293                    IPL_PARMBLOCK_START->ipl_info.fcp.lun);
294 DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
295                    IPL_PARMBLOCK_START->ipl_info.fcp.bootprog);
296 DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
297                    IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
298
299 static struct attribute *ipl_fcp_attrs[] = {
300         &sys_ipl_type_attr.attr,
301         &sys_ipl_device_attr.attr,
302         &sys_ipl_fcp_wwpn_attr.attr,
303         &sys_ipl_fcp_lun_attr.attr,
304         &sys_ipl_fcp_bootprog_attr.attr,
305         &sys_ipl_fcp_br_lba_attr.attr,
306         NULL,
307 };
308
309 static struct attribute_group ipl_fcp_attr_group = {
310         .attrs = ipl_fcp_attrs,
311 };
312
313 /* CCW ipl device attributes */
314
315 static ssize_t ipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
316 {
317         char loadparm[LOADPARM_LEN + 1] = {};
318
319         if (!SCCB_VALID)
320                 return sprintf(page, "#unknown#\n");
321         memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN);
322         EBCASC(loadparm, LOADPARM_LEN);
323         strstrip(loadparm);
324         return sprintf(page, "%s\n", loadparm);
325 }
326
327 static struct subsys_attribute sys_ipl_ccw_loadparm_attr =
328         __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
329
330 static struct attribute *ipl_ccw_attrs[] = {
331         &sys_ipl_type_attr.attr,
332         &sys_ipl_device_attr.attr,
333         &sys_ipl_ccw_loadparm_attr.attr,
334         NULL,
335 };
336
337 static struct attribute_group ipl_ccw_attr_group = {
338         .attrs = ipl_ccw_attrs,
339 };
340
341 /* NSS ipl device attributes */
342
343 DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
344
345 static struct attribute *ipl_nss_attrs[] = {
346         &sys_ipl_type_attr.attr,
347         &sys_ipl_nss_name_attr.attr,
348         NULL,
349 };
350
351 static struct attribute_group ipl_nss_attr_group = {
352         .attrs = ipl_nss_attrs,
353 };
354
355 /* UNKNOWN ipl device attributes */
356
357 static struct attribute *ipl_unknown_attrs[] = {
358         &sys_ipl_type_attr.attr,
359         NULL,
360 };
361
362 static struct attribute_group ipl_unknown_attr_group = {
363         .attrs = ipl_unknown_attrs,
364 };
365
366 static decl_subsys(ipl, NULL, NULL);
367
368 /*
369  * reipl section
370  */
371
372 /* FCP reipl device attributes */
373
374 DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
375                    reipl_block_fcp->ipl_info.fcp.wwpn);
376 DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n",
377                    reipl_block_fcp->ipl_info.fcp.lun);
378 DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
379                    reipl_block_fcp->ipl_info.fcp.bootprog);
380 DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
381                    reipl_block_fcp->ipl_info.fcp.br_lba);
382 DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
383                    reipl_block_fcp->ipl_info.fcp.devno);
384
385 static struct attribute *reipl_fcp_attrs[] = {
386         &sys_reipl_fcp_device_attr.attr,
387         &sys_reipl_fcp_wwpn_attr.attr,
388         &sys_reipl_fcp_lun_attr.attr,
389         &sys_reipl_fcp_bootprog_attr.attr,
390         &sys_reipl_fcp_br_lba_attr.attr,
391         NULL,
392 };
393
394 static struct attribute_group reipl_fcp_attr_group = {
395         .name  = IPL_FCP_STR,
396         .attrs = reipl_fcp_attrs,
397 };
398
399 /* CCW reipl device attributes */
400
401 DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
402         reipl_block_ccw->ipl_info.ccw.devno);
403
404 static void reipl_get_ascii_loadparm(char *loadparm)
405 {
406         memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param,
407                LOADPARM_LEN);
408         EBCASC(loadparm, LOADPARM_LEN);
409         loadparm[LOADPARM_LEN] = 0;
410         strstrip(loadparm);
411 }
412
413 static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
414 {
415         char buf[LOADPARM_LEN + 1];
416
417         reipl_get_ascii_loadparm(buf);
418         return sprintf(page, "%s\n", buf);
419 }
420
421 static ssize_t reipl_ccw_loadparm_store(struct subsystem *subsys,
422                                         const char *buf, size_t len)
423 {
424         int i, lp_len;
425
426         /* ignore trailing newline */
427         lp_len = len;
428         if ((len > 0) && (buf[len - 1] == '\n'))
429                 lp_len--;
430         /* loadparm can have max 8 characters and must not start with a blank */
431         if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
432                 return -EINVAL;
433         /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
434         for (i = 0; i < lp_len; i++) {
435                 if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
436                     (buf[i] == '.'))
437                         continue;
438                 return -EINVAL;
439         }
440         /* initialize loadparm with blanks */
441         memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN);
442         /* copy and convert to ebcdic */
443         memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len);
444         ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN);
445         return len;
446 }
447
448 static struct subsys_attribute sys_reipl_ccw_loadparm_attr =
449         __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
450                reipl_ccw_loadparm_store);
451
452 static struct attribute *reipl_ccw_attrs[] = {
453         &sys_reipl_ccw_device_attr.attr,
454         &sys_reipl_ccw_loadparm_attr.attr,
455         NULL,
456 };
457
458 static struct attribute_group reipl_ccw_attr_group = {
459         .name  = IPL_CCW_STR,
460         .attrs = reipl_ccw_attrs,
461 };
462
463
464 /* NSS reipl device attributes */
465
466 DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name);
467
468 static struct attribute *reipl_nss_attrs[] = {
469         &sys_reipl_nss_name_attr.attr,
470         NULL,
471 };
472
473 static struct attribute_group reipl_nss_attr_group = {
474         .name  = IPL_NSS_STR,
475         .attrs = reipl_nss_attrs,
476 };
477
478 /* reipl type */
479
480 static int reipl_set_type(enum ipl_type type)
481 {
482         if (!(reipl_capabilities & type))
483                 return -EINVAL;
484
485         switch(type) {
486         case IPL_TYPE_CCW:
487                 if (MACHINE_IS_VM)
488                         reipl_method = IPL_METHOD_CCW_VM;
489                 else
490                         reipl_method = IPL_METHOD_CCW_CIO;
491                 break;
492         case IPL_TYPE_FCP:
493                 if (diag308_set_works)
494                         reipl_method = IPL_METHOD_FCP_RW_DIAG;
495                 else if (MACHINE_IS_VM)
496                         reipl_method = IPL_METHOD_FCP_RO_VM;
497                 else
498                         reipl_method = IPL_METHOD_FCP_RO_DIAG;
499                 break;
500         case IPL_TYPE_NSS:
501                 reipl_method = IPL_METHOD_NSS;
502                 break;
503         default:
504                 reipl_method = IPL_METHOD_NONE;
505         }
506         reipl_type = type;
507         return 0;
508 }
509
510 static ssize_t reipl_type_show(struct subsystem *subsys, char *page)
511 {
512         return sprintf(page, "%s\n", ipl_type_str(reipl_type));
513 }
514
515 static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf,
516                                 size_t len)
517 {
518         int rc = -EINVAL;
519
520         if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
521                 rc = reipl_set_type(IPL_TYPE_CCW);
522         else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
523                 rc = reipl_set_type(IPL_TYPE_FCP);
524         else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
525                 rc = reipl_set_type(IPL_TYPE_NSS);
526         return (rc != 0) ? rc : len;
527 }
528
529 static struct subsys_attribute reipl_type_attr =
530                 __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
531
532 static decl_subsys(reipl, NULL, NULL);
533
534 /*
535  * dump section
536  */
537
538 /* FCP dump device attributes */
539
540 DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
541                    dump_block_fcp->ipl_info.fcp.wwpn);
542 DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
543                    dump_block_fcp->ipl_info.fcp.lun);
544 DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
545                    dump_block_fcp->ipl_info.fcp.bootprog);
546 DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
547                    dump_block_fcp->ipl_info.fcp.br_lba);
548 DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
549                    dump_block_fcp->ipl_info.fcp.devno);
550
551 static struct attribute *dump_fcp_attrs[] = {
552         &sys_dump_fcp_device_attr.attr,
553         &sys_dump_fcp_wwpn_attr.attr,
554         &sys_dump_fcp_lun_attr.attr,
555         &sys_dump_fcp_bootprog_attr.attr,
556         &sys_dump_fcp_br_lba_attr.attr,
557         NULL,
558 };
559
560 static struct attribute_group dump_fcp_attr_group = {
561         .name  = IPL_FCP_STR,
562         .attrs = dump_fcp_attrs,
563 };
564
565 /* CCW dump device attributes */
566
567 DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
568                    dump_block_ccw->ipl_info.ccw.devno);
569
570 static struct attribute *dump_ccw_attrs[] = {
571         &sys_dump_ccw_device_attr.attr,
572         NULL,
573 };
574
575 static struct attribute_group dump_ccw_attr_group = {
576         .name  = IPL_CCW_STR,
577         .attrs = dump_ccw_attrs,
578 };
579
580 /* dump type */
581
582 static int dump_set_type(enum ipl_type type)
583 {
584         if (!(dump_capabilities & type))
585                 return -EINVAL;
586         switch(type) {
587         case IPL_TYPE_CCW:
588                 if (MACHINE_IS_VM)
589                         dump_method = IPL_METHOD_CCW_VM;
590                 else
591                         dump_method = IPL_METHOD_CCW_CIO;
592                 break;
593         case IPL_TYPE_FCP:
594                 dump_method = IPL_METHOD_FCP_RW_DIAG;
595                 break;
596         default:
597                 dump_method = IPL_METHOD_NONE;
598         }
599         dump_type = type;
600         return 0;
601 }
602
603 static ssize_t dump_type_show(struct subsystem *subsys, char *page)
604 {
605         return sprintf(page, "%s\n", ipl_type_str(dump_type));
606 }
607
608 static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
609                                size_t len)
610 {
611         int rc = -EINVAL;
612
613         if (strncmp(buf, IPL_NONE_STR, strlen(IPL_NONE_STR)) == 0)
614                 rc = dump_set_type(IPL_TYPE_NONE);
615         else if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
616                 rc = dump_set_type(IPL_TYPE_CCW);
617         else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
618                 rc = dump_set_type(IPL_TYPE_FCP);
619         return (rc != 0) ? rc : len;
620 }
621
622 static struct subsys_attribute dump_type_attr =
623                 __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
624
625 static decl_subsys(dump, NULL, NULL);
626
627 /*
628  * Shutdown actions section
629  */
630
631 static decl_subsys(shutdown_actions, NULL, NULL);
632
633 /* on panic */
634
635 static ssize_t on_panic_show(struct subsystem *subsys, char *page)
636 {
637         return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
638 }
639
640 static ssize_t on_panic_store(struct subsystem *subsys, const char *buf,
641                               size_t len)
642 {
643         if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
644                 on_panic_action = SHUTDOWN_REIPL;
645         else if (strncmp(buf, SHUTDOWN_DUMP_STR,
646                          strlen(SHUTDOWN_DUMP_STR)) == 0)
647                 on_panic_action = SHUTDOWN_DUMP;
648         else if (strncmp(buf, SHUTDOWN_STOP_STR,
649                          strlen(SHUTDOWN_STOP_STR)) == 0)
650                 on_panic_action = SHUTDOWN_STOP;
651         else
652                 return -EINVAL;
653
654         return len;
655 }
656
657 static struct subsys_attribute on_panic_attr =
658                 __ATTR(on_panic, 0644, on_panic_show, on_panic_store);
659
660 void do_reipl(void)
661 {
662         struct ccw_dev_id devid;
663         static char buf[100];
664         char loadparm[LOADPARM_LEN + 1];
665
666         switch (reipl_method) {
667         case IPL_METHOD_CCW_CIO:
668                 devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
669                 if (ipl_get_type() == IPL_TYPE_CCW && devid.devno == ipl_devno)
670                         diag308(DIAG308_IPL, NULL);
671                 devid.ssid  = 0;
672                 reipl_ccw_dev(&devid);
673                 break;
674         case IPL_METHOD_CCW_VM:
675                 reipl_get_ascii_loadparm(loadparm);
676                 if (strlen(loadparm) == 0)
677                         sprintf(buf, "IPL %X",
678                                 reipl_block_ccw->ipl_info.ccw.devno);
679                 else
680                         sprintf(buf, "IPL %X LOADPARM '%s'",
681                                 reipl_block_ccw->ipl_info.ccw.devno, loadparm);
682                 __cpcmd(buf, NULL, 0, NULL);
683                 break;
684         case IPL_METHOD_CCW_DIAG:
685                 diag308(DIAG308_SET, reipl_block_ccw);
686                 diag308(DIAG308_IPL, NULL);
687                 break;
688         case IPL_METHOD_FCP_RW_DIAG:
689                 diag308(DIAG308_SET, reipl_block_fcp);
690                 diag308(DIAG308_IPL, NULL);
691                 break;
692         case IPL_METHOD_FCP_RO_DIAG:
693                 diag308(DIAG308_IPL, NULL);
694                 break;
695         case IPL_METHOD_FCP_RO_VM:
696                 __cpcmd("IPL", NULL, 0, NULL);
697                 break;
698         case IPL_METHOD_NSS:
699                 sprintf(buf, "IPL %s", reipl_nss_name);
700                 __cpcmd(buf, NULL, 0, NULL);
701                 break;
702         case IPL_METHOD_NONE:
703         default:
704                 if (MACHINE_IS_VM)
705                         __cpcmd("IPL", NULL, 0, NULL);
706                 diag308(DIAG308_IPL, NULL);
707                 break;
708         }
709         signal_processor(smp_processor_id(), sigp_stop_and_store_status);
710 }
711
712 static void do_dump(void)
713 {
714         struct ccw_dev_id devid;
715         static char buf[100];
716
717         switch (dump_method) {
718         case IPL_METHOD_CCW_CIO:
719                 smp_send_stop();
720                 devid.devno = dump_block_ccw->ipl_info.ccw.devno;
721                 devid.ssid  = 0;
722                 reipl_ccw_dev(&devid);
723                 break;
724         case IPL_METHOD_CCW_VM:
725                 smp_send_stop();
726                 sprintf(buf, "STORE STATUS");
727                 __cpcmd(buf, NULL, 0, NULL);
728                 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
729                 __cpcmd(buf, NULL, 0, NULL);
730                 break;
731         case IPL_METHOD_CCW_DIAG:
732                 diag308(DIAG308_SET, dump_block_ccw);
733                 diag308(DIAG308_DUMP, NULL);
734                 break;
735         case IPL_METHOD_FCP_RW_DIAG:
736                 diag308(DIAG308_SET, dump_block_fcp);
737                 diag308(DIAG308_DUMP, NULL);
738                 break;
739         case IPL_METHOD_NONE:
740         default:
741                 return;
742         }
743         printk(KERN_EMERG "Dump failed!\n");
744 }
745
746 /* init functions */
747
748 static int __init ipl_register_fcp_files(void)
749 {
750         int rc;
751
752         rc = sysfs_create_group(&ipl_subsys.kset.kobj,
753                                 &ipl_fcp_attr_group);
754         if (rc)
755                 goto out;
756         rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
757                                    &ipl_parameter_attr);
758         if (rc)
759                 goto out_ipl_parm;
760         rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
761                                    &ipl_scp_data_attr);
762         if (!rc)
763                 goto out;
764
765         sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr);
766
767 out_ipl_parm:
768         sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
769 out:
770         return rc;
771 }
772
773 static int __init ipl_init(void)
774 {
775         int rc;
776
777         rc = firmware_register(&ipl_subsys);
778         if (rc)
779                 return rc;
780         switch (ipl_get_type()) {
781         case IPL_TYPE_CCW:
782                 rc = sysfs_create_group(&ipl_subsys.kset.kobj,
783                                         &ipl_ccw_attr_group);
784                 break;
785         case IPL_TYPE_FCP:
786                 rc = ipl_register_fcp_files();
787                 break;
788         case IPL_TYPE_NSS:
789                 rc = sysfs_create_group(&ipl_subsys.kset.kobj,
790                                         &ipl_nss_attr_group);
791                 break;
792         default:
793                 rc = sysfs_create_group(&ipl_subsys.kset.kobj,
794                                         &ipl_unknown_attr_group);
795                 break;
796         }
797         if (rc)
798                 firmware_unregister(&ipl_subsys);
799         return rc;
800 }
801
802 static void __init reipl_probe(void)
803 {
804         void *buffer;
805
806         buffer = (void *) get_zeroed_page(GFP_KERNEL);
807         if (!buffer)
808                 return;
809         if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
810                 diag308_set_works = 1;
811         free_page((unsigned long)buffer);
812 }
813
814 static int __init reipl_nss_init(void)
815 {
816         int rc;
817
818         if (!MACHINE_IS_VM)
819                 return 0;
820         rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group);
821         if (rc)
822                 return rc;
823         strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
824         reipl_capabilities |= IPL_TYPE_NSS;
825         return 0;
826 }
827
828 static int __init reipl_ccw_init(void)
829 {
830         int rc;
831
832         reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
833         if (!reipl_block_ccw)
834                 return -ENOMEM;
835         rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_ccw_attr_group);
836         if (rc) {
837                 free_page((unsigned long)reipl_block_ccw);
838                 return rc;
839         }
840         reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
841         reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
842         reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
843         reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
844         /* check if read scp info worked and set loadparm */
845         if (SCCB_VALID)
846                 memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
847                        SCCB_LOADPARM, LOADPARM_LEN);
848         else
849                 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
850                 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
851                        LOADPARM_LEN);
852         /* FIXME: check for diag308_set_works when enabling diag ccw reipl */
853         if (!MACHINE_IS_VM)
854                 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
855         if (ipl_get_type() == IPL_TYPE_CCW)
856                 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
857         reipl_capabilities |= IPL_TYPE_CCW;
858         return 0;
859 }
860
861 static int __init reipl_fcp_init(void)
862 {
863         int rc;
864
865         if ((!diag308_set_works) && (ipl_get_type() != IPL_TYPE_FCP))
866                 return 0;
867         if ((!diag308_set_works) && (ipl_get_type() == IPL_TYPE_FCP))
868                 make_attrs_ro(reipl_fcp_attrs);
869
870         reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
871         if (!reipl_block_fcp)
872                 return -ENOMEM;
873         rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_fcp_attr_group);
874         if (rc) {
875                 free_page((unsigned long)reipl_block_fcp);
876                 return rc;
877         }
878         if (ipl_get_type() == IPL_TYPE_FCP) {
879                 memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
880         } else {
881                 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
882                 reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
883                 reipl_block_fcp->hdr.blk0_len =
884                         sizeof(reipl_block_fcp->ipl_info.fcp);
885                 reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
886                 reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
887         }
888         reipl_capabilities |= IPL_TYPE_FCP;
889         return 0;
890 }
891
892 static int __init reipl_init(void)
893 {
894         int rc;
895
896         rc = firmware_register(&reipl_subsys);
897         if (rc)
898                 return rc;
899         rc = subsys_create_file(&reipl_subsys, &reipl_type_attr);
900         if (rc) {
901                 firmware_unregister(&reipl_subsys);
902                 return rc;
903         }
904         rc = reipl_ccw_init();
905         if (rc)
906                 return rc;
907         rc = reipl_fcp_init();
908         if (rc)
909                 return rc;
910         rc = reipl_nss_init();
911         if (rc)
912                 return rc;
913         rc = reipl_set_type(ipl_get_type());
914         if (rc)
915                 return rc;
916         return 0;
917 }
918
919 static int __init dump_ccw_init(void)
920 {
921         int rc;
922
923         dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
924         if (!dump_block_ccw)
925                 return -ENOMEM;
926         rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_ccw_attr_group);
927         if (rc) {
928                 free_page((unsigned long)dump_block_ccw);
929                 return rc;
930         }
931         dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
932         dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
933         dump_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
934         dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
935         dump_capabilities |= IPL_TYPE_CCW;
936         return 0;
937 }
938
939 static int __init dump_fcp_init(void)
940 {
941         int rc;
942
943         if(!(SCCB_FLAG & 0x2) || !SCCB_VALID)
944                 return 0; /* LDIPL DUMP is not installed */
945         if (!diag308_set_works)
946                 return 0;
947         dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
948         if (!dump_block_fcp)
949                 return -ENOMEM;
950         rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_fcp_attr_group);
951         if (rc) {
952                 free_page((unsigned long)dump_block_fcp);
953                 return rc;
954         }
955         dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
956         dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
957         dump_block_fcp->hdr.blk0_len = sizeof(dump_block_fcp->ipl_info.fcp);
958         dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
959         dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
960         dump_capabilities |= IPL_TYPE_FCP;
961         return 0;
962 }
963
964 #define SHUTDOWN_ON_PANIC_PRIO 0
965
966 static int shutdown_on_panic_notify(struct notifier_block *self,
967                                     unsigned long event, void *data)
968 {
969         if (on_panic_action == SHUTDOWN_DUMP)
970                 do_dump();
971         else if (on_panic_action == SHUTDOWN_REIPL)
972                 do_reipl();
973         return NOTIFY_OK;
974 }
975
976 static struct notifier_block shutdown_on_panic_nb = {
977         .notifier_call = shutdown_on_panic_notify,
978         .priority = SHUTDOWN_ON_PANIC_PRIO
979 };
980
981 static int __init dump_init(void)
982 {
983         int rc;
984
985         rc = firmware_register(&dump_subsys);
986         if (rc)
987                 return rc;
988         rc = subsys_create_file(&dump_subsys, &dump_type_attr);
989         if (rc) {
990                 firmware_unregister(&dump_subsys);
991                 return rc;
992         }
993         rc = dump_ccw_init();
994         if (rc)
995                 return rc;
996         rc = dump_fcp_init();
997         if (rc)
998                 return rc;
999         dump_set_type(IPL_TYPE_NONE);
1000         return 0;
1001 }
1002
1003 static int __init shutdown_actions_init(void)
1004 {
1005         int rc;
1006
1007         rc = firmware_register(&shutdown_actions_subsys);
1008         if (rc)
1009                 return rc;
1010         rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr);
1011         if (rc) {
1012                 firmware_unregister(&shutdown_actions_subsys);
1013                 return rc;
1014         }
1015         atomic_notifier_chain_register(&panic_notifier_list,
1016                                        &shutdown_on_panic_nb);
1017         return 0;
1018 }
1019
1020 static int __init s390_ipl_init(void)
1021 {
1022         int rc;
1023
1024         reipl_probe();
1025         rc = ipl_init();
1026         if (rc)
1027                 return rc;
1028         rc = reipl_init();
1029         if (rc)
1030                 return rc;
1031         rc = dump_init();
1032         if (rc)
1033                 return rc;
1034         rc = shutdown_actions_init();
1035         if (rc)
1036                 return rc;
1037         return 0;
1038 }
1039
1040 __initcall(s390_ipl_init);
1041
1042 static LIST_HEAD(rcall);
1043 static DEFINE_MUTEX(rcall_mutex);
1044
1045 void register_reset_call(struct reset_call *reset)
1046 {
1047         mutex_lock(&rcall_mutex);
1048         list_add(&reset->list, &rcall);
1049         mutex_unlock(&rcall_mutex);
1050 }
1051 EXPORT_SYMBOL_GPL(register_reset_call);
1052
1053 void unregister_reset_call(struct reset_call *reset)
1054 {
1055         mutex_lock(&rcall_mutex);
1056         list_del(&reset->list);
1057         mutex_unlock(&rcall_mutex);
1058 }
1059 EXPORT_SYMBOL_GPL(unregister_reset_call);
1060
1061 static void do_reset_calls(void)
1062 {
1063         struct reset_call *reset;
1064
1065         list_for_each_entry(reset, &rcall, list)
1066                 reset->fn();
1067 }
1068
1069 extern __u32 dump_prefix_page;
1070
1071 void s390_reset_system(void)
1072 {
1073         struct _lowcore *lc;
1074
1075         lc = (struct _lowcore *)(unsigned long) store_prefix();
1076
1077         /* Stack for interrupt/machine check handler */
1078         lc->panic_stack = S390_lowcore.panic_stack;
1079
1080         /* Save prefix page address for dump case */
1081         dump_prefix_page = (unsigned long) lc;
1082
1083         /* Disable prefixing */
1084         set_prefix(0);
1085
1086         /* Disable lowcore protection */
1087         __ctl_clear_bit(0,28);
1088
1089         /* Set new machine check handler */
1090         S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
1091         S390_lowcore.mcck_new_psw.addr =
1092                 PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
1093
1094         /* Set new program check handler */
1095         S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
1096         S390_lowcore.program_new_psw.addr =
1097                 PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
1098
1099         do_reset_calls();
1100 }