aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r--drivers/s390/cio/cio.c52
1 files changed, 20 insertions, 32 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 9cb129ab5be5..ea1defba5693 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -22,6 +22,7 @@
22#include <asm/setup.h> 22#include <asm/setup.h>
23#include <asm/reset.h> 23#include <asm/reset.h>
24#include <asm/ipl.h> 24#include <asm/ipl.h>
25#include <asm/chpid.h>
25#include "airq.h" 26#include "airq.h"
26#include "cio.h" 27#include "cio.h"
27#include "css.h" 28#include "css.h"
@@ -29,6 +30,7 @@
29#include "ioasm.h" 30#include "ioasm.h"
30#include "blacklist.h" 31#include "blacklist.h"
31#include "cio_debug.h" 32#include "cio_debug.h"
33#include "chp.h"
32#include "../s390mach.h" 34#include "../s390mach.h"
33 35
34debug_info_t *cio_debug_msg_id; 36debug_info_t *cio_debug_msg_id;
@@ -592,9 +594,10 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
592 err = -ENODEV; 594 err = -ENODEV;
593 goto out; 595 goto out;
594 } 596 }
595 sch->opm = 0xff; 597 if (cio_is_console(sch->schid))
596 if (!cio_is_console(sch->schid)) 598 sch->opm = 0xff;
597 chsc_validate_chpids(sch); 599 else
600 sch->opm = chp_get_sch_opm(sch);
598 sch->lpm = sch->schib.pmcw.pam & sch->opm; 601 sch->lpm = sch->schib.pmcw.pam & sch->opm;
599 602
600 CIO_DEBUG(KERN_INFO, 0, 603 CIO_DEBUG(KERN_INFO, 0,
@@ -954,6 +957,7 @@ static void css_reset(void)
954{ 957{
955 int i, ret; 958 int i, ret;
956 unsigned long long timeout; 959 unsigned long long timeout;
960 struct chp_id chpid;
957 961
958 /* Reset subchannels. */ 962 /* Reset subchannels. */
959 for_each_subchannel(__shutdown_subchannel_easy, NULL); 963 for_each_subchannel(__shutdown_subchannel_easy, NULL);
@@ -963,8 +967,10 @@ static void css_reset(void)
963 __ctl_set_bit(14, 28); 967 __ctl_set_bit(14, 28);
964 /* Temporarily reenable machine checks. */ 968 /* Temporarily reenable machine checks. */
965 local_mcck_enable(); 969 local_mcck_enable();
970 chp_id_init(&chpid);
966 for (i = 0; i <= __MAX_CHPID; i++) { 971 for (i = 0; i <= __MAX_CHPID; i++) {
967 ret = rchp(i); 972 chpid.id = i;
973 ret = rchp(chpid);
968 if ((ret == 0) || (ret == 2)) 974 if ((ret == 0) || (ret == 2))
969 /* 975 /*
970 * rchp either succeeded, or another rchp is already 976 * rchp either succeeded, or another rchp is already
@@ -1048,37 +1054,19 @@ void reipl_ccw_dev(struct ccw_dev_id *devid)
1048 do_reipl_asm(*((__u32*)&schid)); 1054 do_reipl_asm(*((__u32*)&schid));
1049} 1055}
1050 1056
1051static struct schib __initdata ipl_schib; 1057int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo)
1052
1053/*
1054 * ipl_save_parameters gets called very early. It is not allowed to access
1055 * anything in the bss section at all. The bss section is not cleared yet,
1056 * but may contain some ipl parameters written by the firmware.
1057 * These parameters (if present) are copied to 0x2000.
1058 * To avoid corruption of the ipl parameters, all variables used by this
1059 * function must reside on the stack or in the data section.
1060 */
1061void ipl_save_parameters(void)
1062{ 1058{
1063 struct subchannel_id schid; 1059 struct subchannel_id schid;
1064 unsigned int *ipl_ptr; 1060 struct schib schib;
1065 void *src, *dst;
1066 1061
1067 schid = *(struct subchannel_id *)__LC_SUBCHANNEL_ID; 1062 schid = *(struct subchannel_id *)__LC_SUBCHANNEL_ID;
1068 if (!schid.one) 1063 if (!schid.one)
1069 return; 1064 return -ENODEV;
1070 if (stsch(schid, &ipl_schib)) 1065 if (stsch(schid, &schib))
1071 return; 1066 return -ENODEV;
1072 if (!ipl_schib.pmcw.dnv) 1067 if (!schib.pmcw.dnv)
1073 return; 1068 return -ENODEV;
1074 ipl_devno = ipl_schib.pmcw.dev; 1069 iplinfo->devno = schib.pmcw.dev;
1075 ipl_flags |= IPL_DEVNO_VALID; 1070 iplinfo->is_qdio = schib.pmcw.qf;
1076 if (!ipl_schib.pmcw.qf) 1071 return 0;
1077 return;
1078 ipl_flags |= IPL_PARMBLOCK_VALID;
1079 ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR;
1080 src = (void *)(unsigned long)*ipl_ptr;
1081 dst = (void *)IPL_PARMBLOCK_ORIGIN;
1082 memmove(dst, src, PAGE_SIZE);
1083 *ipl_ptr = IPL_PARMBLOCK_ORIGIN;
1084} 1072}