aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorCornelia Huck <cohuck@de.ibm.com>2006-01-06 03:19:25 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:52 -0500
commitfb6958a594da49ece869793e6ec163b89fc5f79f (patch)
tree0746cc23ab13a059f9a34d7fc134aaf6410d07b8 /drivers/s390
parent678a395b356a98368a93c3640252502b70c3676f (diff)
[PATCH] s390: multiple subchannel sets support
Add support for multiple subchannel sets. Works with arbitrary devices in subchannel set 1 and is transparent to device drivers. Although currently only two subchannel sets are available, this will work with the architectured maximum number of subchannel sets as well. Signed-off-by: Cornelia Huck <cohuck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/blacklist.c86
-rw-r--r--drivers/s390/cio/blacklist.h2
-rw-r--r--drivers/s390/cio/chsc.c68
-rw-r--r--drivers/s390/cio/chsc.h4
-rw-r--r--drivers/s390/cio/cio.c35
-rw-r--r--drivers/s390/cio/css.c44
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device.c22
-rw-r--r--drivers/s390/cio/device_fsm.c15
-rw-r--r--drivers/s390/cio/device_id.c22
-rw-r--r--drivers/s390/cio/device_pgid.c40
-rw-r--r--drivers/s390/cio/device_status.c10
-rw-r--r--drivers/s390/cio/ioasm.h29
-rw-r--r--drivers/s390/cio/qdio.c81
-rw-r--r--drivers/s390/cio/schid.h3
-rw-r--r--drivers/s390/s390mach.c56
16 files changed, 354 insertions, 165 deletions
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index daea41c63329..2d444cb2fdf7 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/s390/cio/blacklist.c 2 * drivers/s390/cio/blacklist.c
3 * S/390 common I/O routines -- blacklisting of specific devices 3 * S/390 common I/O routines -- blacklisting of specific devices
4 * $Revision: 1.35 $ 4 * $Revision: 1.39 $
5 * 5 *
6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
@@ -35,10 +35,10 @@
35 * These can be single devices or ranges of devices 35 * These can be single devices or ranges of devices
36 */ 36 */
37 37
38/* 65536 bits to indicate if a devno is blacklisted or not */ 38/* 65536 bits for each set to indicate if a devno is blacklisted or not */
39#define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \ 39#define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \
40 (8*sizeof(long))) 40 (8*sizeof(long)))
41static unsigned long bl_dev[__BL_DEV_WORDS]; 41static unsigned long bl_dev[__MAX_SSID + 1][__BL_DEV_WORDS];
42typedef enum {add, free} range_action; 42typedef enum {add, free} range_action;
43 43
44/* 44/*
@@ -46,21 +46,23 @@ typedef enum {add, free} range_action;
46 * (Un-)blacklist the devices from-to 46 * (Un-)blacklist the devices from-to
47 */ 47 */
48static inline void 48static inline void
49blacklist_range (range_action action, unsigned int from, unsigned int to) 49blacklist_range (range_action action, unsigned int from, unsigned int to,
50 unsigned int ssid)
50{ 51{
51 if (!to) 52 if (!to)
52 to = from; 53 to = from;
53 54
54 if (from > to || to > __MAX_SUBCHANNEL) { 55 if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) {
55 printk (KERN_WARNING "Invalid blacklist range " 56 printk (KERN_WARNING "Invalid blacklist range "
56 "0x%04x to 0x%04x, skipping\n", from, to); 57 "0.%x.%04x to 0.%x.%04x, skipping\n",
58 ssid, from, ssid, to);
57 return; 59 return;
58 } 60 }
59 for (; from <= to; from++) { 61 for (; from <= to; from++) {
60 if (action == add) 62 if (action == add)
61 set_bit (from, bl_dev); 63 set_bit (from, bl_dev[ssid]);
62 else 64 else
63 clear_bit (from, bl_dev); 65 clear_bit (from, bl_dev[ssid]);
64 } 66 }
65} 67}
66 68
@@ -70,7 +72,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to)
70 * Shamelessly grabbed from dasd_devmap.c. 72 * Shamelessly grabbed from dasd_devmap.c.
71 */ 73 */
72static inline int 74static inline int
73blacklist_busid(char **str, int *id0, int *id1, int *devno) 75blacklist_busid(char **str, int *id0, int *ssid, int *devno)
74{ 76{
75 int val, old_style; 77 int val, old_style;
76 char *sav; 78 char *sav;
@@ -87,7 +89,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
87 goto confused; 89 goto confused;
88 val = simple_strtoul(*str, str, 16); 90 val = simple_strtoul(*str, str, 16);
89 if (old_style || (*str)[0] != '.') { 91 if (old_style || (*str)[0] != '.') {
90 *id0 = *id1 = 0; 92 *id0 = *ssid = 0;
91 if (val < 0 || val > 0xffff) 93 if (val < 0 || val > 0xffff)
92 goto confused; 94 goto confused;
93 *devno = val; 95 *devno = val;
@@ -106,7 +108,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
106 val = simple_strtoul(*str, str, 16); 108 val = simple_strtoul(*str, str, 16);
107 if (val < 0 || val > 0xff || (*str)++[0] != '.') 109 if (val < 0 || val > 0xff || (*str)++[0] != '.')
108 goto confused; 110 goto confused;
109 *id1 = val; 111 *ssid = val;
110 if (!isxdigit((*str)[0])) /* We require at least one hex digit */ 112 if (!isxdigit((*str)[0])) /* We require at least one hex digit */
111 goto confused; 113 goto confused;
112 val = simple_strtoul(*str, str, 16); 114 val = simple_strtoul(*str, str, 16);
@@ -126,7 +128,7 @@ confused:
126static inline int 128static inline int
127blacklist_parse_parameters (char *str, range_action action) 129blacklist_parse_parameters (char *str, range_action action)
128{ 130{
129 unsigned int from, to, from_id0, to_id0, from_id1, to_id1; 131 unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid;
130 132
131 while (*str != 0 && *str != '\n') { 133 while (*str != 0 && *str != '\n') {
132 range_action ra = action; 134 range_action ra = action;
@@ -143,23 +145,25 @@ blacklist_parse_parameters (char *str, range_action action)
143 */ 145 */
144 if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 || 146 if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 ||
145 strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) { 147 strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) {
146 from = 0; 148 int j;
147 to = __MAX_SUBCHANNEL; 149
148 str += 3; 150 str += 3;
151 for (j=0; j <= __MAX_SSID; j++)
152 blacklist_range(ra, 0, __MAX_SUBCHANNEL, j);
149 } else { 153 } else {
150 int rc; 154 int rc;
151 155
152 rc = blacklist_busid(&str, &from_id0, 156 rc = blacklist_busid(&str, &from_id0,
153 &from_id1, &from); 157 &from_ssid, &from);
154 if (rc) 158 if (rc)
155 continue; 159 continue;
156 to = from; 160 to = from;
157 to_id0 = from_id0; 161 to_id0 = from_id0;
158 to_id1 = from_id1; 162 to_ssid = from_ssid;
159 if (*str == '-') { 163 if (*str == '-') {
160 str++; 164 str++;
161 rc = blacklist_busid(&str, &to_id0, 165 rc = blacklist_busid(&str, &to_id0,
162 &to_id1, &to); 166 &to_ssid, &to);
163 if (rc) 167 if (rc)
164 continue; 168 continue;
165 } 169 }
@@ -169,18 +173,19 @@ blacklist_parse_parameters (char *str, range_action action)
169 strsep(&str, ",\n")); 173 strsep(&str, ",\n"));
170 continue; 174 continue;
171 } 175 }
172 if ((from_id0 != to_id0) || (from_id1 != to_id1)) { 176 if ((from_id0 != to_id0) ||
177 (from_ssid != to_ssid)) {
173 printk(KERN_WARNING "invalid cio_ignore range " 178 printk(KERN_WARNING "invalid cio_ignore range "
174 "%x.%x.%04x-%x.%x.%04x\n", 179 "%x.%x.%04x-%x.%x.%04x\n",
175 from_id0, from_id1, from, 180 from_id0, from_ssid, from,
176 to_id0, to_id1, to); 181 to_id0, to_ssid, to);
177 continue; 182 continue;
178 } 183 }
184 pr_debug("blacklist_setup: adding range "
185 "from %x.%x.%04x to %x.%x.%04x\n",
186 from_id0, from_ssid, from, to_id0, to_ssid, to);
187 blacklist_range (ra, from, to, to_ssid);
179 } 188 }
180 /* FIXME: ignoring id0 and id1 here. */
181 pr_debug("blacklist_setup: adding range "
182 "from 0.0.%04x to 0.0.%04x\n", from, to);
183 blacklist_range (ra, from, to);
184 } 189 }
185 return 1; 190 return 1;
186} 191}
@@ -214,9 +219,9 @@ __setup ("cio_ignore=", blacklist_setup);
214 * Used by validate_subchannel() 219 * Used by validate_subchannel()
215 */ 220 */
216int 221int
217is_blacklisted (int devno) 222is_blacklisted (int ssid, int devno)
218{ 223{
219 return test_bit (devno, bl_dev); 224 return test_bit (devno, bl_dev[ssid]);
220} 225}
221 226
222#ifdef CONFIG_PROC_FS 227#ifdef CONFIG_PROC_FS
@@ -283,6 +288,7 @@ blacklist_parse_proc_parameters (char *buf)
283/* Iterator struct for all devices. */ 288/* Iterator struct for all devices. */
284struct ccwdev_iter { 289struct ccwdev_iter {
285 int devno; 290 int devno;
291 int ssid;
286 int in_range; 292 int in_range;
287}; 293};
288 294
@@ -291,13 +297,14 @@ cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
291{ 297{
292 struct ccwdev_iter *iter; 298 struct ccwdev_iter *iter;
293 299
294 if (*offset > __MAX_SUBCHANNEL) 300 if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
295 return NULL; 301 return NULL;
296 iter = kmalloc(sizeof(struct ccwdev_iter), GFP_KERNEL); 302 iter = kmalloc(sizeof(struct ccwdev_iter), GFP_KERNEL);
297 if (!iter) 303 if (!iter)
298 return ERR_PTR(-ENOMEM); 304 return ERR_PTR(-ENOMEM);
299 memset(iter, 0, sizeof(struct ccwdev_iter)); 305 memset(iter, 0, sizeof(struct ccwdev_iter));
300 iter->devno = *offset; 306 iter->ssid = *offset / (__MAX_SUBCHANNEL + 1);
307 iter->devno = *offset % (__MAX_SUBCHANNEL + 1);
301 return iter; 308 return iter;
302} 309}
303 310
@@ -313,10 +320,16 @@ cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
313{ 320{
314 struct ccwdev_iter *iter; 321 struct ccwdev_iter *iter;
315 322
316 if (*offset > __MAX_SUBCHANNEL) 323 if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
317 return NULL; 324 return NULL;
318 iter = (struct ccwdev_iter *)it; 325 iter = (struct ccwdev_iter *)it;
319 iter->devno++; 326 if (iter->devno == __MAX_SUBCHANNEL) {
327 iter->devno = 0;
328 iter->ssid++;
329 if (iter->ssid > __MAX_SSID)
330 return NULL;
331 } else
332 iter->devno++;
320 (*offset)++; 333 (*offset)++;
321 return iter; 334 return iter;
322} 335}
@@ -327,23 +340,24 @@ cio_ignore_proc_seq_show(struct seq_file *s, void *it)
327 struct ccwdev_iter *iter; 340 struct ccwdev_iter *iter;
328 341
329 iter = (struct ccwdev_iter *)it; 342 iter = (struct ccwdev_iter *)it;
330 if (!is_blacklisted(iter->devno)) 343 if (!is_blacklisted(iter->ssid, iter->devno))
331 /* Not blacklisted, nothing to output. */ 344 /* Not blacklisted, nothing to output. */
332 return 0; 345 return 0;
333 if (!iter->in_range) { 346 if (!iter->in_range) {
334 /* First device in range. */ 347 /* First device in range. */
335 if ((iter->devno == __MAX_SUBCHANNEL) || 348 if ((iter->devno == __MAX_SUBCHANNEL) ||
336 !is_blacklisted(iter->devno + 1)) 349 !is_blacklisted(iter->ssid, iter->devno + 1))
337 /* Singular device. */ 350 /* Singular device. */
338 return seq_printf(s, "0.0.%04x\n", iter->devno); 351 return seq_printf(s, "0.%x.%04x\n",
352 iter->ssid, iter->devno);
339 iter->in_range = 1; 353 iter->in_range = 1;
340 return seq_printf(s, "0.0.%04x-", iter->devno); 354 return seq_printf(s, "0.%x.%04x-", iter->ssid, iter->devno);
341 } 355 }
342 if ((iter->devno == __MAX_SUBCHANNEL) || 356 if ((iter->devno == __MAX_SUBCHANNEL) ||
343 !is_blacklisted(iter->devno + 1)) { 357 !is_blacklisted(iter->ssid, iter->devno + 1)) {
344 /* Last device in range. */ 358 /* Last device in range. */
345 iter->in_range = 0; 359 iter->in_range = 0;
346 return seq_printf(s, "0.0.%04x\n", iter->devno); 360 return seq_printf(s, "0.%x.%04x\n", iter->ssid, iter->devno);
347 } 361 }
348 return 0; 362 return 0;
349} 363}
diff --git a/drivers/s390/cio/blacklist.h b/drivers/s390/cio/blacklist.h
index fb42cafbe57c..95e25c1df922 100644
--- a/drivers/s390/cio/blacklist.h
+++ b/drivers/s390/cio/blacklist.h
@@ -1,6 +1,6 @@
1#ifndef S390_BLACKLIST_H 1#ifndef S390_BLACKLIST_H
2#define S390_BLACKLIST_H 2#define S390_BLACKLIST_H
3 3
4extern int is_blacklisted (int devno); 4extern int is_blacklisted (int ssid, int devno);
5 5
6#endif 6#endif
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index ebd924962df0..7270808c02d1 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/s390/cio/chsc.c 2 * drivers/s390/cio/chsc.c
3 * S/390 common I/O routines -- channel subsystem call 3 * S/390 common I/O routines -- channel subsystem call
4 * $Revision: 1.120 $ 4 * $Revision: 1.126 $
5 * 5 *
6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
@@ -75,7 +75,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
75 75
76 struct { 76 struct {
77 struct chsc_header request; 77 struct chsc_header request;
78 u16 reserved1; 78 u16 reserved1a:10;
79 u16 ssid:2;
80 u16 reserved1b:4;
79 u16 f_sch; /* first subchannel */ 81 u16 f_sch; /* first subchannel */
80 u16 reserved2; 82 u16 reserved2;
81 u16 l_sch; /* last subchannel */ 83 u16 l_sch; /* last subchannel */
@@ -102,6 +104,7 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
102 .code = 0x0004, 104 .code = 0x0004,
103 }; 105 };
104 106
107 ssd_area->ssid = sch->schid.ssid;
105 ssd_area->f_sch = sch->schid.sch_no; 108 ssd_area->f_sch = sch->schid.sch_no;
106 ssd_area->l_sch = sch->schid.sch_no; 109 ssd_area->l_sch = sch->schid.sch_no;
107 110
@@ -145,8 +148,8 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
145 */ 148 */
146 if (ssd_area->st > 3) { /* uhm, that looks strange... */ 149 if (ssd_area->st > 3) { /* uhm, that looks strange... */
147 CIO_CRW_EVENT(0, "Strange subchannel type %d" 150 CIO_CRW_EVENT(0, "Strange subchannel type %d"
148 " for sch %04x\n", ssd_area->st, 151 " for sch 0.%x.%04x\n", ssd_area->st,
149 sch->schid.sch_no); 152 sch->schid.ssid, sch->schid.sch_no);
150 /* 153 /*
151 * There may have been a new subchannel type defined in the 154 * There may have been a new subchannel type defined in the
152 * time since this code was written; since we don't know which 155 * time since this code was written; since we don't know which
@@ -155,8 +158,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
155 return 0; 158 return 0;
156 } else { 159 } else {
157 const char *type[4] = {"I/O", "chsc", "message", "ADM"}; 160 const char *type[4] = {"I/O", "chsc", "message", "ADM"};
158 CIO_CRW_EVENT(6, "ssd: sch %04x is %s subchannel\n", 161 CIO_CRW_EVENT(6, "ssd: sch 0.%x.%04x is %s subchannel\n",
159 sch->schid.sch_no, type[ssd_area->st]); 162 sch->schid.ssid, sch->schid.sch_no,
163 type[ssd_area->st]);
160 164
161 sch->ssd_info.valid = 1; 165 sch->ssd_info.valid = 1;
162 sch->ssd_info.type = ssd_area->st; 166 sch->ssd_info.type = ssd_area->st;
@@ -364,7 +368,7 @@ s390_process_res_acc_new_sch(struct subchannel_id schid)
364 * that beast may be on we'll have to do a stsch 368 * that beast may be on we'll have to do a stsch
365 * on all devices, grr... 369 * on all devices, grr...
366 */ 370 */
367 if (stsch(schid, &schib)) 371 if (stsch_err(schid, &schib))
368 /* We're through */ 372 /* We're through */
369 return need_rescan ? -EAGAIN : -ENXIO; 373 return need_rescan ? -EAGAIN : -ENXIO;
370 374
@@ -818,7 +822,7 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)
818 put_device(&sch->dev); 822 put_device(&sch->dev);
819 return 0; 823 return 0;
820 } 824 }
821 if (stsch(schid, &schib)) 825 if (stsch_err(schid, &schib))
822 /* We're through */ 826 /* We're through */
823 return -ENXIO; 827 return -ENXIO;
824 /* Put it on the slow path. */ 828 /* Put it on the slow path. */
@@ -1078,6 +1082,54 @@ chsc_alloc_sei_area(void)
1078 return (sei_page ? 0 : -ENOMEM); 1082 return (sei_page ? 0 : -ENOMEM);
1079} 1083}
1080 1084
1085int __init
1086chsc_enable_facility(int operation_code)
1087{
1088 int ret;
1089 struct {
1090 struct chsc_header request;
1091 u8 reserved1:4;
1092 u8 format:4;
1093 u8 reserved2;
1094 u16 operation_code;
1095 u32 reserved3;
1096 u32 reserved4;
1097 u32 operation_data_area[252];
1098 struct chsc_header response;
1099 u32 reserved5:4;
1100 u32 format2:4;
1101 u32 reserved6:24;
1102 } *sda_area;
1103
1104 sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);
1105 if (!sda_area)
1106 return -ENOMEM;
1107 sda_area->request = (struct chsc_header) {
1108 .length = 0x0400,
1109 .code = 0x0031,
1110 };
1111 sda_area->operation_code = operation_code;
1112
1113 ret = chsc(sda_area);
1114 if (ret > 0) {
1115 ret = (ret == 3) ? -ENODEV : -EBUSY;
1116 goto out;
1117 }
1118 switch (sda_area->response.code) {
1119 case 0x0003: /* invalid request block */
1120 case 0x0007:
1121 ret = -EINVAL;
1122 break;
1123 case 0x0004: /* command not provided */
1124 case 0x0101: /* facility not provided */
1125 ret = -EOPNOTSUPP;
1126 break;
1127 }
1128 out:
1129 free_page((unsigned long)sda_area);
1130 return ret;
1131}
1132
1081subsys_initcall(chsc_alloc_sei_area); 1133subsys_initcall(chsc_alloc_sei_area);
1082 1134
1083struct css_general_char css_general_characteristics; 1135struct css_general_char css_general_characteristics;
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 170083ca4349..44e4b4bb1c5a 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -5,6 +5,8 @@
5#define CHSC_SEI_ACC_LINKADDR 2 5#define CHSC_SEI_ACC_LINKADDR 2
6#define CHSC_SEI_ACC_FULLLINKADDR 3 6#define CHSC_SEI_ACC_FULLLINKADDR 3
7 7
8#define CHSC_SDA_OC_MSS 0x2
9
8struct chsc_header { 10struct chsc_header {
9 u16 length; 11 u16 length;
10 u16 code; 12 u16 code;
@@ -64,6 +66,8 @@ extern int css_characteristics_avail;
64 66
65extern void *chsc_get_chp_desc(struct subchannel*, int); 67extern void *chsc_get_chp_desc(struct subchannel*, int);
66 68
69extern int chsc_enable_facility(int);
70
67#define to_channelpath(dev) container_of(dev, struct channel_path, dev) 71#define to_channelpath(dev) container_of(dev, struct channel_path, dev)
68 72
69#endif 73#endif
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 3eb6cb608fc9..6f274f4f92eb 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/s390/cio/cio.c 2 * drivers/s390/cio/cio.c
3 * S/390 common I/O routines -- low level i/o calls 3 * S/390 common I/O routines -- low level i/o calls
4 * $Revision: 1.135 $ 4 * $Revision: 1.138 $
5 * 5 *
6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
@@ -166,7 +166,8 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
166 stsch (sch->schid, &sch->schib); 166 stsch (sch->schid, &sch->schib);
167 167
168 CIO_MSG_EVENT(0, "cio_start: 'not oper' status for " 168 CIO_MSG_EVENT(0, "cio_start: 'not oper' status for "
169 "subchannel %04x!\n", sch->schid.sch_no); 169 "subchannel 0.%x.%04x!\n", sch->schid.ssid,
170 sch->schid.sch_no);
170 sprintf(dbf_text, "no%s", sch->dev.bus_id); 171 sprintf(dbf_text, "no%s", sch->dev.bus_id);
171 CIO_TRACE_EVENT(0, dbf_text); 172 CIO_TRACE_EVENT(0, dbf_text);
172 CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); 173 CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
@@ -522,15 +523,18 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
522 spin_lock_init(&sch->lock); 523 spin_lock_init(&sch->lock);
523 524
524 /* Set a name for the subchannel */ 525 /* Set a name for the subchannel */
525 snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", schid.sch_no); 526 snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
527 schid.sch_no);
526 528
527 /* 529 /*
528 * The first subchannel that is not-operational (ccode==3) 530 * The first subchannel that is not-operational (ccode==3)
529 * indicates that there aren't any more devices available. 531 * indicates that there aren't any more devices available.
532 * If stsch gets an exception, it means the current subchannel set
533 * is not valid.
530 */ 534 */
531 ccode = stsch (schid, &sch->schib); 535 ccode = stsch_err (schid, &sch->schib);
532 if (ccode) 536 if (ccode)
533 return -ENXIO; 537 return (ccode == 3) ? -ENXIO : ccode;
534 538
535 sch->schid = schid; 539 sch->schid = schid;
536 /* Copy subchannel type from path management control word. */ 540 /* Copy subchannel type from path management control word. */
@@ -541,9 +545,9 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
541 */ 545 */
542 if (sch->st != 0) { 546 if (sch->st != 0) {
543 CIO_DEBUG(KERN_INFO, 0, 547 CIO_DEBUG(KERN_INFO, 0,
544 "Subchannel %04X reports " 548 "Subchannel 0.%x.%04x reports "
545 "non-I/O subchannel type %04X\n", 549 "non-I/O subchannel type %04X\n",
546 sch->schid.sch_no, sch->st); 550 sch->schid.ssid, sch->schid.sch_no, sch->st);
547 /* We stop here for non-io subchannels. */ 551 /* We stop here for non-io subchannels. */
548 return sch->st; 552 return sch->st;
549 } 553 }
@@ -554,26 +558,29 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
554 return -ENODEV; 558 return -ENODEV;
555 559
556 /* Devno is valid. */ 560 /* Devno is valid. */
557 if (is_blacklisted (sch->schib.pmcw.dev)) { 561 if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
558 /* 562 /*
559 * This device must not be known to Linux. So we simply 563 * This device must not be known to Linux. So we simply
560 * say that there is no device and return ENODEV. 564 * say that there is no device and return ENODEV.
561 */ 565 */
562 CIO_MSG_EVENT(0, "Blacklisted device detected " 566 CIO_MSG_EVENT(0, "Blacklisted device detected "
563 "at devno %04X\n", sch->schib.pmcw.dev); 567 "at devno %04X, subchannel set %x\n",
568 sch->schib.pmcw.dev, sch->schid.ssid);
564 return -ENODEV; 569 return -ENODEV;
565 } 570 }
566 sch->opm = 0xff; 571 sch->opm = 0xff;
567 chsc_validate_chpids(sch); 572 if (!cio_is_console(sch->schid))
573 chsc_validate_chpids(sch);
568 sch->lpm = sch->schib.pmcw.pim & 574 sch->lpm = sch->schib.pmcw.pim &
569 sch->schib.pmcw.pam & 575 sch->schib.pmcw.pam &
570 sch->schib.pmcw.pom & 576 sch->schib.pmcw.pom &
571 sch->opm; 577 sch->opm;
572 578
573 CIO_DEBUG(KERN_INFO, 0, 579 CIO_DEBUG(KERN_INFO, 0,
574 "Detected device %04X on subchannel %04X" 580 "Detected device %04x on subchannel 0.%x.%04X"
575 " - PIM = %02X, PAM = %02X, POM = %02X\n", 581 " - PIM = %02X, PAM = %02X, POM = %02X\n",
576 sch->schib.pmcw.dev, sch->schid.sch_no, sch->schib.pmcw.pim, 582 sch->schib.pmcw.dev, sch->schid.ssid,
583 sch->schid.sch_no, sch->schib.pmcw.pim,
577 sch->schib.pmcw.pam, sch->schib.pmcw.pom); 584 sch->schib.pmcw.pam, sch->schib.pmcw.pom);
578 585
579 /* 586 /*
@@ -693,7 +700,7 @@ wait_cons_dev (void)
693static int 700static int
694cio_test_for_console(struct subchannel_id schid, void *data) 701cio_test_for_console(struct subchannel_id schid, void *data)
695{ 702{
696 if (stsch(schid, &console_subchannel.schib) != 0) 703 if (stsch_err(schid, &console_subchannel.schib) != 0)
697 return -ENXIO; 704 return -ENXIO;
698 if (console_subchannel.schib.pmcw.dnv && 705 if (console_subchannel.schib.pmcw.dnv &&
699 console_subchannel.schib.pmcw.dev == 706 console_subchannel.schib.pmcw.dev ==
@@ -841,7 +848,7 @@ __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
841{ 848{
842 struct schib schib; 849 struct schib schib;
843 850
844 if (stsch(schid, &schib)) 851 if (stsch_err(schid, &schib))
845 return -ENXIO; 852 return -ENXIO;
846 if (!schib.pmcw.ena) 853 if (!schib.pmcw.ena)
847 return 0; 854 return 0;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index b6225cbbbee7..9e9d4a157a4c 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/s390/cio/css.c 2 * drivers/s390/cio/css.c
3 * driver for channel subsystem 3 * driver for channel subsystem
4 * $Revision: 1.85 $ 4 * $Revision: 1.93 $
5 * 5 *
6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
@@ -23,6 +23,7 @@
23 23
24int need_rescan = 0; 24int need_rescan = 0;
25int css_init_done = 0; 25int css_init_done = 0;
26static int max_ssid = 0;
26 27
27struct channel_subsystem *css[__MAX_CSSID + 1]; 28struct channel_subsystem *css[__MAX_CSSID + 1];
28 29
@@ -37,10 +38,13 @@ for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
37 init_subchannel_id(&schid); 38 init_subchannel_id(&schid);
38 ret = -ENODEV; 39 ret = -ENODEV;
39 do { 40 do {
40 ret = fn(schid, data); 41 do {
41 if (ret) 42 ret = fn(schid, data);
42 break; 43 if (ret)
43 } while (schid.sch_no++ < __MAX_SUBCHANNEL); 44 break;
45 } while (schid.sch_no++ < __MAX_SUBCHANNEL);
46 schid.sch_no = 0;
47 } while (schid.ssid++ < max_ssid);
44 return ret; 48 return ret;
45} 49}
46 50
@@ -205,8 +209,8 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow)
205 return -EAGAIN; /* Will be done on the slow path. */ 209 return -EAGAIN; /* Will be done on the slow path. */
206 } 210 }
207 event = css_get_subchannel_status(sch, schid); 211 event = css_get_subchannel_status(sch, schid);
208 CIO_MSG_EVENT(4, "Evaluating schid %04x, event %d, %s, %s path.\n", 212 CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n",
209 schid.sch_no, event, 213 schid.ssid, schid.sch_no, event,
210 sch?(disc?"disconnected":"normal"):"unknown", 214 sch?(disc?"disconnected":"normal"):"unknown",
211 slow?"slow":"fast"); 215 slow?"slow":"fast");
212 switch (event) { 216 switch (event) {
@@ -352,19 +356,23 @@ css_reiterate_subchannels(void)
352 * Called from the machine check handler for subchannel report words. 356 * Called from the machine check handler for subchannel report words.
353 */ 357 */
354int 358int
355css_process_crw(int irq) 359css_process_crw(int rsid1, int rsid2)
356{ 360{
357 int ret; 361 int ret;
358 struct subchannel_id mchk_schid; 362 struct subchannel_id mchk_schid;
359 363
360 CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq); 364 CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n",
365 rsid1, rsid2);
361 366
362 if (need_rescan) 367 if (need_rescan)
363 /* We need to iterate all subchannels anyway. */ 368 /* We need to iterate all subchannels anyway. */
364 return -EAGAIN; 369 return -EAGAIN;
365 370
366 init_subchannel_id(&mchk_schid); 371 init_subchannel_id(&mchk_schid);
367 mchk_schid.sch_no = irq; 372 mchk_schid.sch_no = rsid1;
373 if (rsid2 != 0)
374 mchk_schid.ssid = (rsid2 >> 8) & 3;
375
368 /* 376 /*
369 * Since we are always presented with IPI in the CRW, we have to 377 * Since we are always presented with IPI in the CRW, we have to
370 * use stsch() to find out if the subchannel in question has come 378 * use stsch() to find out if the subchannel in question has come
@@ -465,12 +473,23 @@ init_channel_subsystem (void)
465 if ((ret = bus_register(&css_bus_type))) 473 if ((ret = bus_register(&css_bus_type)))
466 goto out; 474 goto out;
467 475
476 /* Try to enable MSS. */
477 ret = chsc_enable_facility(CHSC_SDA_OC_MSS);
478 switch (ret) {
479 case 0: /* Success. */
480 max_ssid = __MAX_SSID;
481 break;
482 case -ENOMEM:
483 goto out_bus;
484 default:
485 max_ssid = 0;
486 }
468 /* Setup css structure. */ 487 /* Setup css structure. */
469 for (i = 0; i <= __MAX_CSSID; i++) { 488 for (i = 0; i <= __MAX_CSSID; i++) {
470 css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); 489 css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL);
471 if (!css[i]) { 490 if (!css[i]) {
472 ret = -ENOMEM; 491 ret = -ENOMEM;
473 goto out_bus; 492 goto out_unregister;
474 } 493 }
475 setup_css(i); 494 setup_css(i);
476 ret = device_register(&css[i]->device); 495 ret = device_register(&css[i]->device);
@@ -485,11 +504,12 @@ init_channel_subsystem (void)
485 return 0; 504 return 0;
486out_free: 505out_free:
487 kfree(css[i]); 506 kfree(css[i]);
488out_bus: 507out_unregister:
489 while (i > 0) { 508 while (i > 0) {
490 i--; 509 i--;
491 device_unregister(&css[i]->device); 510 device_unregister(&css[i]->device);
492 } 511 }
512out_bus:
493 bus_unregister(&css_bus_type); 513 bus_unregister(&css_bus_type);
494out: 514out:
495 return ret; 515 return ret;
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index b74659cab0af..251ebd7a7d3a 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -77,6 +77,7 @@ struct ccw_device_private {
77 unsigned long registered; 77 unsigned long registered;
78 __u16 devno; /* device number */ 78 __u16 devno; /* device number */
79 __u16 sch_no; /* subchannel number */ 79 __u16 sch_no; /* subchannel number */
80 __u8 ssid; /* subchannel set id */
80 __u8 imask; /* lpm mask for SNID/SID/SPGID */ 81 __u8 imask; /* lpm mask for SNID/SID/SPGID */
81 int iretry; /* retry counter SNID/SID/SPGID */ 82 int iretry; /* retry counter SNID/SID/SPGID */
82 struct { 83 struct {
@@ -135,6 +136,7 @@ extern int css_init_done;
135extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); 136extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
136 137
137#define __MAX_SUBCHANNEL 65535 138#define __MAX_SUBCHANNEL 65535
139#define __MAX_SSID 3
138#define __MAX_CHPID 255 140#define __MAX_CHPID 255
139#define __MAX_CSSID 0 141#define __MAX_CSSID 0
140 142
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index ba9f7c11f63f..fa3e4c0a2536 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -535,7 +535,8 @@ ccw_device_register(struct ccw_device *cdev)
535} 535}
536 536
537struct match_data { 537struct match_data {
538 unsigned int devno; 538 unsigned int devno;
539 unsigned int ssid;
539 struct ccw_device * sibling; 540 struct ccw_device * sibling;
540}; 541};
541 542
@@ -548,6 +549,7 @@ match_devno(struct device * dev, void * data)
548 cdev = to_ccwdev(dev); 549 cdev = to_ccwdev(dev);
549 if ((cdev->private->state == DEV_STATE_DISCONNECTED) && 550 if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
550 (cdev->private->devno == d->devno) && 551 (cdev->private->devno == d->devno) &&
552 (cdev->private->ssid == d->ssid) &&
551 (cdev != d->sibling)) { 553 (cdev != d->sibling)) {
552 cdev->private->state = DEV_STATE_NOT_OPER; 554 cdev->private->state = DEV_STATE_NOT_OPER;
553 return 1; 555 return 1;
@@ -556,11 +558,13 @@ match_devno(struct device * dev, void * data)
556} 558}
557 559
558static struct ccw_device * 560static struct ccw_device *
559get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling) 561get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid,
562 struct ccw_device *sibling)
560{ 563{
561 struct device *dev; 564 struct device *dev;
562 struct match_data data = { 565 struct match_data data = {
563 .devno = devno, 566 .devno = devno,
567 .ssid = ssid,
564 .sibling = sibling, 568 .sibling = sibling,
565 }; 569 };
566 570
@@ -616,7 +620,7 @@ ccw_device_do_unreg_rereg(void *data)
616 620
617 need_rename = 1; 621 need_rename = 1;
618 other_cdev = get_disc_ccwdev_by_devno(sch->schib.pmcw.dev, 622 other_cdev = get_disc_ccwdev_by_devno(sch->schib.pmcw.dev,
619 cdev); 623 sch->schid.ssid, cdev);
620 if (other_cdev) { 624 if (other_cdev) {
621 struct subchannel *other_sch; 625 struct subchannel *other_sch;
622 626
@@ -639,8 +643,8 @@ ccw_device_do_unreg_rereg(void *data)
639 if (test_and_clear_bit(1, &cdev->private->registered)) 643 if (test_and_clear_bit(1, &cdev->private->registered))
640 device_del(&cdev->dev); 644 device_del(&cdev->dev);
641 if (need_rename) 645 if (need_rename)
642 snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", 646 snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
643 sch->schib.pmcw.dev); 647 sch->schid.ssid, sch->schib.pmcw.dev);
644 PREPARE_WORK(&cdev->private->kick_work, 648 PREPARE_WORK(&cdev->private->kick_work,
645 ccw_device_add_changed, (void *)cdev); 649 ccw_device_add_changed, (void *)cdev);
646 queue_work(ccw_device_work, &cdev->private->kick_work); 650 queue_work(ccw_device_work, &cdev->private->kick_work);
@@ -769,9 +773,11 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
769 sch->dev.driver_data = cdev; 773 sch->dev.driver_data = cdev;
770 sch->driver = &io_subchannel_driver; 774 sch->driver = &io_subchannel_driver;
771 cdev->ccwlock = &sch->lock; 775 cdev->ccwlock = &sch->lock;
776
772 /* Init private data. */ 777 /* Init private data. */
773 priv = cdev->private; 778 priv = cdev->private;
774 priv->devno = sch->schib.pmcw.dev; 779 priv->devno = sch->schib.pmcw.dev;
780 priv->ssid = sch->schid.ssid;
775 priv->sch_no = sch->schid.sch_no; 781 priv->sch_no = sch->schid.sch_no;
776 priv->state = DEV_STATE_NOT_OPER; 782 priv->state = DEV_STATE_NOT_OPER;
777 INIT_LIST_HEAD(&priv->cmb_list); 783 INIT_LIST_HEAD(&priv->cmb_list);
@@ -779,8 +785,8 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
779 init_timer(&priv->timer); 785 init_timer(&priv->timer);
780 786
781 /* Set an initial name for the device. */ 787 /* Set an initial name for the device. */
782 snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", 788 snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
783 sch->schib.pmcw.dev); 789 sch->schid.ssid, sch->schib.pmcw.dev);
784 790
785 /* Increase counter of devices currently in recognition. */ 791 /* Increase counter of devices currently in recognition. */
786 atomic_inc(&ccw_device_init_count); 792 atomic_inc(&ccw_device_init_count);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 9efeae75ad28..23d12b65e5fa 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -257,8 +257,9 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
257 switch (state) { 257 switch (state) {
258 case DEV_STATE_NOT_OPER: 258 case DEV_STATE_NOT_OPER:
259 CIO_DEBUG(KERN_WARNING, 2, 259 CIO_DEBUG(KERN_WARNING, 2,
260 "SenseID : unknown device %04x on subchannel %04x\n", 260 "SenseID : unknown device %04x on subchannel "
261 cdev->private->devno, sch->schid.sch_no); 261 "0.%x.%04x\n", cdev->private->devno,
262 sch->schid.ssid, sch->schid.sch_no);
262 break; 263 break;
263 case DEV_STATE_OFFLINE: 264 case DEV_STATE_OFFLINE:
264 if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { 265 if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
@@ -282,16 +283,18 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
282 return; 283 return;
283 } 284 }
284 /* Issue device info message. */ 285 /* Issue device info message. */
285 CIO_DEBUG(KERN_INFO, 2, "SenseID : device %04x reports: " 286 CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: "
286 "CU Type/Mod = %04X/%02X, Dev Type/Mod = " 287 "CU Type/Mod = %04X/%02X, Dev Type/Mod = "
287 "%04X/%02X\n", cdev->private->devno, 288 "%04X/%02X\n",
289 cdev->private->ssid, cdev->private->devno,
288 cdev->id.cu_type, cdev->id.cu_model, 290 cdev->id.cu_type, cdev->id.cu_model,
289 cdev->id.dev_type, cdev->id.dev_model); 291 cdev->id.dev_type, cdev->id.dev_model);
290 break; 292 break;
291 case DEV_STATE_BOXED: 293 case DEV_STATE_BOXED:
292 CIO_DEBUG(KERN_WARNING, 2, 294 CIO_DEBUG(KERN_WARNING, 2,
293 "SenseID : boxed device %04x on subchannel %04x\n", 295 "SenseID : boxed device %04x on subchannel "
294 cdev->private->devno, sch->schid.sch_no); 296 "0.%x.%04x\n", cdev->private->devno,
297 sch->schid.ssid, sch->schid.sch_no);
295 break; 298 break;
296 } 299 }
297 cdev->private->state = state; 300 cdev->private->state = state;
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 207881ec7aaf..3c77c3fd461d 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -256,16 +256,17 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
256 * sense id information. So, for intervention required, 256 * sense id information. So, for intervention required,
257 * we use the "whack it until it talks" strategy... 257 * we use the "whack it until it talks" strategy...
258 */ 258 */
259 CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel %04x " 259 CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel "
260 "reports cmd reject\n", 260 "0.%x.%04x reports cmd reject\n",
261 cdev->private->devno, sch->schid.sch_no); 261 cdev->private->devno, sch->schid.ssid,
262 sch->schid.sch_no);
262 return -EOPNOTSUPP; 263 return -EOPNOTSUPP;
263 } 264 }
264 if (irb->esw.esw0.erw.cons) { 265 if (irb->esw.esw0.erw.cons) {
265 CIO_MSG_EVENT(2, "SenseID : UC on dev %04x, " 266 CIO_MSG_EVENT(2, "SenseID : UC on dev 0.%x.%04x, "
266 "lpum %02X, cnt %02d, sns :" 267 "lpum %02X, cnt %02d, sns :"
267 " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", 268 " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
268 cdev->private->devno, 269 cdev->private->ssid, cdev->private->devno,
269 irb->esw.esw0.sublog.lpum, 270 irb->esw.esw0.sublog.lpum,
270 irb->esw.esw0.erw.scnt, 271 irb->esw.esw0.erw.scnt,
271 irb->ecw[0], irb->ecw[1], 272 irb->ecw[0], irb->ecw[1],
@@ -277,16 +278,17 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
277 if (irb->scsw.cc == 3) { 278 if (irb->scsw.cc == 3) {
278 if ((sch->orb.lpm & 279 if ((sch->orb.lpm &
279 sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0) 280 sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
280 CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x on" 281 CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x "
281 " subchannel %04x is 'not operational'\n", 282 "on subchannel 0.%x.%04x is "
282 sch->orb.lpm, cdev->private->devno, 283 "'not operational'\n", sch->orb.lpm,
284 cdev->private->devno, sch->schid.ssid,
283 sch->schid.sch_no); 285 sch->schid.sch_no);
284 return -EACCES; 286 return -EACCES;
285 } 287 }
286 /* Hmm, whatever happened, try again. */ 288 /* Hmm, whatever happened, try again. */
287 CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on " 289 CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on "
288 "subchannel %04x returns status %02X%02X\n", 290 "subchannel 0.%x.%04x returns status %02X%02X\n",
289 cdev->private->devno, sch->schid.sch_no, 291 cdev->private->devno, sch->schid.ssid, sch->schid.sch_no,
290 irb->scsw.dstat, irb->scsw.cstat); 292 irb->scsw.dstat, irb->scsw.cstat);
291 return -EAGAIN; 293 return -EAGAIN;
292} 294}
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 3c89d70b9c09..052832d03d38 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -57,10 +57,10 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
57 if (ret != -EACCES) 57 if (ret != -EACCES)
58 return ret; 58 return ret;
59 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel " 59 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
60 "%04x, lpm %02X, became 'not " 60 "0.%x.%04x, lpm %02X, became 'not "
61 "operational'\n", 61 "operational'\n",
62 cdev->private->devno, sch->schid.sch_no, 62 cdev->private->devno, sch->schid.ssid,
63 cdev->private->imask); 63 sch->schid.sch_no, cdev->private->imask);
64 64
65 } 65 }
66 cdev->private->imask >>= 1; 66 cdev->private->imask >>= 1;
@@ -106,10 +106,10 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
106 return -EOPNOTSUPP; 106 return -EOPNOTSUPP;
107 } 107 }
108 if (irb->esw.esw0.erw.cons) { 108 if (irb->esw.esw0.erw.cons) {
109 CIO_MSG_EVENT(2, "SNID - device %04x, unit check, " 109 CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, "
110 "lpum %02X, cnt %02d, sns : " 110 "lpum %02X, cnt %02d, sns : "
111 "%02X%02X%02X%02X %02X%02X%02X%02X ...\n", 111 "%02X%02X%02X%02X %02X%02X%02X%02X ...\n",
112 cdev->private->devno, 112 cdev->private->ssid, cdev->private->devno,
113 irb->esw.esw0.sublog.lpum, 113 irb->esw.esw0.sublog.lpum,
114 irb->esw.esw0.erw.scnt, 114 irb->esw.esw0.erw.scnt,
115 irb->ecw[0], irb->ecw[1], 115 irb->ecw[0], irb->ecw[1],
@@ -119,16 +119,17 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
119 return -EAGAIN; 119 return -EAGAIN;
120 } 120 }
121 if (irb->scsw.cc == 3) { 121 if (irb->scsw.cc == 3) {
122 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel " 122 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
123 "%04x, lpm %02X, became 'not operational'\n", 123 " lpm %02X, became 'not operational'\n",
124 cdev->private->devno, sch->schid.sch_no, 124 cdev->private->devno, sch->schid.ssid,
125 sch->orb.lpm); 125 sch->schid.sch_no, sch->orb.lpm);
126 return -EACCES; 126 return -EACCES;
127 } 127 }
128 if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) { 128 if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
129 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel %04x " 129 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x "
130 "is reserved by someone else\n", 130 "is reserved by someone else\n",
131 cdev->private->devno, sch->schid.sch_no); 131 cdev->private->devno, sch->schid.ssid,
132 sch->schid.sch_no);
132 return -EUSERS; 133 return -EUSERS;
133 } 134 }
134 return 0; 135 return 0;
@@ -237,8 +238,9 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
237 sch->lpm &= ~cdev->private->imask; 238 sch->lpm &= ~cdev->private->imask;
238 sch->vpm &= ~cdev->private->imask; 239 sch->vpm &= ~cdev->private->imask;
239 CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " 240 CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
240 "%04x, lpm %02X, became 'not operational'\n", 241 "0.%x.%04x, lpm %02X, became 'not operational'\n",
241 cdev->private->devno, sch->schid.sch_no, cdev->private->imask); 242 cdev->private->devno, sch->schid.ssid,
243 sch->schid.sch_no, cdev->private->imask);
242 return ret; 244 return ret;
243} 245}
244 246
@@ -260,8 +262,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
260 if (irb->ecw[0] & SNS0_CMD_REJECT) 262 if (irb->ecw[0] & SNS0_CMD_REJECT)
261 return -EOPNOTSUPP; 263 return -EOPNOTSUPP;
262 /* Hmm, whatever happened, try again. */ 264 /* Hmm, whatever happened, try again. */
263 CIO_MSG_EVENT(2, "SPID - device %04x, unit check, cnt %02d, " 265 CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, "
266 "cnt %02d, "
264 "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n", 267 "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
268 cdev->private->ssid,
265 cdev->private->devno, irb->esw.esw0.erw.scnt, 269 cdev->private->devno, irb->esw.esw0.erw.scnt,
266 irb->ecw[0], irb->ecw[1], 270 irb->ecw[0], irb->ecw[1],
267 irb->ecw[2], irb->ecw[3], 271 irb->ecw[2], irb->ecw[3],
@@ -270,10 +274,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
270 return -EAGAIN; 274 return -EAGAIN;
271 } 275 }
272 if (irb->scsw.cc == 3) { 276 if (irb->scsw.cc == 3) {
273 CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " 277 CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
274 "%04x, lpm %02X, became 'not operational'\n", 278 " lpm %02X, became 'not operational'\n",
275 cdev->private->devno, sch->schid.sch_no, 279 cdev->private->devno, sch->schid.ssid,
276 cdev->private->imask); 280 sch->schid.sch_no, cdev->private->imask);
277 return -EACCES; 281 return -EACCES;
278 } 282 }
279 return 0; 283 return 0;
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 929f8fb505f2..db09c209098b 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -36,9 +36,10 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
36 36
37 CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check " 37 CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check "
38 "received" 38 "received"
39 " ... device %04X on subchannel %04X, dev_stat " 39 " ... device %04x on subchannel 0.%x.%04x, dev_stat "
40 ": %02X sch_stat : %02X\n", 40 ": %02X sch_stat : %02X\n",
41 cdev->private->devno, cdev->private->sch_no, 41 cdev->private->devno, cdev->private->ssid,
42 cdev->private->sch_no,
42 irb->scsw.dstat, irb->scsw.cstat); 43 irb->scsw.dstat, irb->scsw.cstat);
43 44
44 if (irb->scsw.cc != 3) { 45 if (irb->scsw.cc != 3) {
@@ -61,8 +62,9 @@ ccw_device_path_notoper(struct ccw_device *cdev)
61 sch = to_subchannel(cdev->dev.parent); 62 sch = to_subchannel(cdev->dev.parent);
62 stsch (sch->schid, &sch->schib); 63 stsch (sch->schid, &sch->schib);
63 64
64 CIO_MSG_EVENT(0, "%s(%04x) - path(s) %02x are " 65 CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are "
65 "not operational \n", __FUNCTION__, sch->schid.sch_no, 66 "not operational \n", __FUNCTION__,
67 sch->schid.ssid, sch->schid.sch_no,
66 sch->schib.pmcw.pnom); 68 sch->schib.pmcw.pnom);
67 69
68 sch->lpm &= ~sch->schib.pmcw.pnom; 70 sch->lpm &= ~sch->schib.pmcw.pnom;
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 66c882e52f32..62b0e2ad507f 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -38,6 +38,35 @@ static inline int stsch(struct subchannel_id schid,
38 return ccode; 38 return ccode;
39} 39}
40 40
41static inline int stsch_err(struct subchannel_id schid,
42 volatile struct schib *addr)
43{
44 int ccode;
45
46 __asm__ __volatile__(
47 " lhi %0,%3\n"
48 " lr 1,%1\n"
49 " stsch 0(%2)\n"
50 "0: ipm %0\n"
51 " srl %0,28\n"
52 "1:\n"
53#ifdef CONFIG_ARCH_S390X
54 ".section __ex_table,\"a\"\n"
55 " .align 8\n"
56 " .quad 0b,1b\n"
57 ".previous"
58#else
59 ".section __ex_table,\"a\"\n"
60 " .align 4\n"
61 " .long 0b,1b\n"
62 ".previous"
63#endif
64 : "=&d" (ccode)
65 : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
66 : "cc", "1" );
67 return ccode;
68}
69
41static inline int msch(struct subchannel_id schid, 70static inline int msch(struct subchannel_id schid,
42 volatile struct schib *addr) 71 volatile struct schib *addr)
43{ 72{
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 5c7001b5c7a1..035c77af9cd3 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,7 +56,7 @@
56#include "ioasm.h" 56#include "ioasm.h"
57#include "chsc.h" 57#include "chsc.h"
58 58
59#define VERSION_QDIO_C "$Revision: 1.113 $" 59#define VERSION_QDIO_C "$Revision: 1.114 $"
60 60
61/****************** MODULE PARAMETER VARIABLES ********************/ 61/****************** MODULE PARAMETER VARIABLES ********************/
62MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); 62MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -2066,21 +2066,22 @@ qdio_timeout_handler(struct ccw_device *cdev)
2066 2066
2067 switch (irq_ptr->state) { 2067 switch (irq_ptr->state) {
2068 case QDIO_IRQ_STATE_INACTIVE: 2068 case QDIO_IRQ_STATE_INACTIVE:
2069 QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n", 2069 QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: timed out\n",
2070 irq_ptr->schid.sch_no); 2070 irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
2071 QDIO_DBF_TEXT2(1,setup,"eq:timeo"); 2071 QDIO_DBF_TEXT2(1,setup,"eq:timeo");
2072 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 2072 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
2073 break; 2073 break;
2074 case QDIO_IRQ_STATE_CLEANUP: 2074 case QDIO_IRQ_STATE_CLEANUP:
2075 QDIO_PRINT_INFO("Did not get interrupt on cleanup, irq=0x%x.\n", 2075 QDIO_PRINT_INFO("Did not get interrupt on cleanup, "
2076 irq_ptr->schid.sch_no); 2076 "irq=0.%x.%x.\n",
2077 irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
2077 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 2078 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
2078 break; 2079 break;
2079 case QDIO_IRQ_STATE_ESTABLISHED: 2080 case QDIO_IRQ_STATE_ESTABLISHED:
2080 case QDIO_IRQ_STATE_ACTIVE: 2081 case QDIO_IRQ_STATE_ACTIVE:
2081 /* I/O has been terminated by common I/O layer. */ 2082 /* I/O has been terminated by common I/O layer. */
2082 QDIO_PRINT_INFO("Queues on irq %04x killed by cio.\n", 2083 QDIO_PRINT_INFO("Queues on irq 0.%x.%04x killed by cio.\n",
2083 irq_ptr->schid.sch_no); 2084 irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
2084 QDIO_DBF_TEXT2(1, trace, "cio:term"); 2085 QDIO_DBF_TEXT2(1, trace, "cio:term");
2085 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); 2086 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
2086 if (get_device(&cdev->dev)) { 2087 if (get_device(&cdev->dev)) {
@@ -2273,7 +2274,9 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
2273 unsigned char qdioac; 2274 unsigned char qdioac;
2274 struct { 2275 struct {
2275 struct chsc_header request; 2276 struct chsc_header request;
2276 u16 reserved1; 2277 u16 reserved1:10;
2278 u16 ssid:2;
2279 u16 fmt:4;
2277 u16 first_sch; 2280 u16 first_sch;
2278 u16 reserved2; 2281 u16 reserved2;
2279 u16 last_sch; 2282 u16 last_sch;
@@ -2318,12 +2321,13 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
2318 }; 2321 };
2319 ssqd_area->first_sch = irq_ptr->schid.sch_no; 2322 ssqd_area->first_sch = irq_ptr->schid.sch_no;
2320 ssqd_area->last_sch = irq_ptr->schid.sch_no; 2323 ssqd_area->last_sch = irq_ptr->schid.sch_no;
2324 ssqd_area->ssid = irq_ptr->schid.ssid;
2321 result = chsc(ssqd_area); 2325 result = chsc(ssqd_area);
2322 2326
2323 if (result) { 2327 if (result) {
2324 QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ 2328 QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
2325 "SIGAs for sch x%x.\n", 2329 "SIGAs for sch 0.%x.%x.\n", result,
2326 result, irq_ptr->schid.sch_no); 2330 irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
2327 qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || 2331 qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
2328 CHSC_FLAG_SIGA_OUTPUT_NECESSARY || 2332 CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
2329 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ 2333 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
@@ -2333,8 +2337,9 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
2333 2337
2334 if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) { 2338 if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
2335 QDIO_PRINT_WARN("response upon checking SIGA needs " \ 2339 QDIO_PRINT_WARN("response upon checking SIGA needs " \
2336 "is 0x%x. Using all SIGAs for sch x%x.\n", 2340 "is 0x%x. Using all SIGAs for sch 0.%x.%x.\n",
2337 ssqd_area->response.code, irq_ptr->schid.sch_no); 2341 ssqd_area->response.code,
2342 irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
2338 qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || 2343 qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
2339 CHSC_FLAG_SIGA_OUTPUT_NECESSARY || 2344 CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
2340 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ 2345 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
@@ -2344,8 +2349,9 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
2344 if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) || 2349 if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
2345 !(ssqd_area->flags & CHSC_FLAG_VALIDITY) || 2350 !(ssqd_area->flags & CHSC_FLAG_VALIDITY) ||
2346 (ssqd_area->sch != irq_ptr->schid.sch_no)) { 2351 (ssqd_area->sch != irq_ptr->schid.sch_no)) {
2347 QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \ 2352 QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
2348 "using all SIGAs.\n",irq_ptr->schid.sch_no); 2353 "using all SIGAs.\n",
2354 irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
2349 qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | 2355 qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
2350 CHSC_FLAG_SIGA_OUTPUT_NECESSARY | 2356 CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
2351 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */ 2357 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */
@@ -2453,7 +2459,8 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
2453 scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); 2459 scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
2454 if (!scssc_area) { 2460 if (!scssc_area) {
2455 QDIO_PRINT_WARN("No memory for setting indicators on " \ 2461 QDIO_PRINT_WARN("No memory for setting indicators on " \
2456 "subchannel x%x.\n", irq_ptr->schid.sch_no); 2462 "subchannel 0.%x.%x.\n",
2463 irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
2457 return -ENOMEM; 2464 return -ENOMEM;
2458 } 2465 }
2459 scssc_area->request = (struct chsc_header) { 2466 scssc_area->request = (struct chsc_header) {
@@ -2479,8 +2486,9 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
2479 2486
2480 result = chsc(scssc_area); 2487 result = chsc(scssc_area);
2481 if (result) { 2488 if (result) {
2482 QDIO_PRINT_WARN("could not set indicators on irq x%x, " \ 2489 QDIO_PRINT_WARN("could not set indicators on irq 0.%x.%x, " \
2483 "cc=%i.\n",irq_ptr->schid.sch_no,result); 2490 "cc=%i.\n",
2491 irq_ptr->schid.ssid, irq_ptr->schid.sch_no,result);
2484 result = -EIO; 2492 result = -EIO;
2485 goto out; 2493 goto out;
2486 } 2494 }
@@ -2536,7 +2544,8 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
2536 scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); 2544 scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
2537 if (!scsscf_area) { 2545 if (!scsscf_area) {
2538 QDIO_PRINT_WARN("No memory for setting delay target on " \ 2546 QDIO_PRINT_WARN("No memory for setting delay target on " \
2539 "subchannel x%x.\n", irq_ptr->schid.sch_no); 2547 "subchannel 0.%x.%x.\n",
2548 irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
2540 return -ENOMEM; 2549 return -ENOMEM;
2541 } 2550 }
2542 scsscf_area->request = (struct chsc_header) { 2551 scsscf_area->request = (struct chsc_header) {
@@ -2548,8 +2557,9 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
2548 2557
2549 result=chsc(scsscf_area); 2558 result=chsc(scsscf_area);
2550 if (result) { 2559 if (result) {
2551 QDIO_PRINT_WARN("could not set delay target on irq x%x, " \ 2560 QDIO_PRINT_WARN("could not set delay target on irq 0.%x.%x, " \
2552 "cc=%i. Continuing.\n",irq_ptr->schid.sch_no, 2561 "cc=%i. Continuing.\n",
2562 irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
2553 result); 2563 result);
2554 result = -EIO; 2564 result = -EIO;
2555 goto out; 2565 goto out;
@@ -2870,8 +2880,9 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
2870 QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int)); 2880 QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int));
2871 QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int)); 2881 QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int));
2872 QDIO_PRINT_ERR("received check condition on establish " \ 2882 QDIO_PRINT_ERR("received check condition on establish " \
2873 "queues on irq 0x%x (cs=x%x, ds=x%x).\n", 2883 "queues on irq 0.%x.%x (cs=x%x, ds=x%x).\n",
2874 irq_ptr->schid.sch_no,cstat,dstat); 2884 irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
2885 cstat,dstat);
2875 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR); 2886 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR);
2876 } 2887 }
2877 2888
@@ -2879,9 +2890,10 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
2879 QDIO_DBF_TEXT2(1,setup,"eq:no de"); 2890 QDIO_DBF_TEXT2(1,setup,"eq:no de");
2880 QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); 2891 QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));
2881 QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); 2892 QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));
2882 QDIO_PRINT_ERR("establish queues on irq %04x: didn't get " 2893 QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: didn't get "
2883 "device end: dstat=%02x, cstat=%02x\n", 2894 "device end: dstat=%02x, cstat=%02x\n",
2884 irq_ptr->schid.sch_no, dstat, cstat); 2895 irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
2896 dstat, cstat);
2885 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 2897 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
2886 return 1; 2898 return 1;
2887 } 2899 }
@@ -2890,9 +2902,9 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
2890 QDIO_DBF_TEXT2(1,setup,"eq:badio"); 2902 QDIO_DBF_TEXT2(1,setup,"eq:badio");
2891 QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); 2903 QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));
2892 QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); 2904 QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));
2893 QDIO_PRINT_ERR("establish queues on irq %04x: got " 2905 QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: got "
2894 "the following devstat: dstat=%02x, " 2906 "the following devstat: dstat=%02x, "
2895 "cstat=%02x\n", 2907 "cstat=%02x\n", irq_ptr->schid.ssid,
2896 irq_ptr->schid.sch_no, dstat, cstat); 2908 irq_ptr->schid.sch_no, dstat, cstat);
2897 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); 2909 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
2898 return 1; 2910 return 1;
@@ -3041,7 +3053,8 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
3041 QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*)); 3053 QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*));
3042 if (!irq_ptr->dev_st_chg_ind) { 3054 if (!irq_ptr->dev_st_chg_ind) {
3043 QDIO_PRINT_WARN("no indicator location available " \ 3055 QDIO_PRINT_WARN("no indicator location available " \
3044 "for irq 0x%x\n",irq_ptr->schid.sch_no); 3056 "for irq 0.%x.%x\n",
3057 irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
3045 qdio_release_irq_memory(irq_ptr); 3058 qdio_release_irq_memory(irq_ptr);
3046 return -ENOBUFS; 3059 return -ENOBUFS;
3047 } 3060 }
@@ -3198,9 +3211,10 @@ qdio_establish(struct qdio_initialize *init_data)
3198 sprintf(dbf_text,"eq:io%4x",result); 3211 sprintf(dbf_text,"eq:io%4x",result);
3199 QDIO_DBF_TEXT2(1,setup,dbf_text); 3212 QDIO_DBF_TEXT2(1,setup,dbf_text);
3200 } 3213 }
3201 QDIO_PRINT_WARN("establish queues on irq %04x: do_IO " \ 3214 QDIO_PRINT_WARN("establish queues on irq 0.%x.%04x: do_IO " \
3202 "returned %i, next try returned %i\n", 3215 "returned %i, next try returned %i\n",
3203 irq_ptr->schid.sch_no,result,result2); 3216 irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
3217 result, result2);
3204 result=result2; 3218 result=result2;
3205 if (result) 3219 if (result)
3206 ccw_device_set_timeout(cdev, 0); 3220 ccw_device_set_timeout(cdev, 0);
@@ -3298,9 +3312,10 @@ qdio_activate(struct ccw_device *cdev, int flags)
3298 sprintf(dbf_text,"aq:io%4x",result); 3312 sprintf(dbf_text,"aq:io%4x",result);
3299 QDIO_DBF_TEXT2(1,setup,dbf_text); 3313 QDIO_DBF_TEXT2(1,setup,dbf_text);
3300 } 3314 }
3301 QDIO_PRINT_WARN("activate queues on irq %04x: do_IO " \ 3315 QDIO_PRINT_WARN("activate queues on irq 0.%x.%04x: do_IO " \
3302 "returned %i, next try returned %i\n", 3316 "returned %i, next try returned %i\n",
3303 irq_ptr->schid.sch_no,result,result2); 3317 irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
3318 result, result2);
3304 result=result2; 3319 result=result2;
3305 } 3320 }
3306 3321
diff --git a/drivers/s390/cio/schid.h b/drivers/s390/cio/schid.h
index 220d97882341..54328fec5ade 100644
--- a/drivers/s390/cio/schid.h
+++ b/drivers/s390/cio/schid.h
@@ -2,7 +2,8 @@
2#define S390_SCHID_H 2#define S390_SCHID_H
3 3
4struct subchannel_id { 4struct subchannel_id {
5 __u32 reserved:15; 5 __u32 reserved:13;
6 __u32 ssid:2;
6 __u32 one:1; 7 __u32 one:1;
7 __u32 sch_no:16; 8 __u32 sch_no:16;
8} __attribute__ ((packed,aligned(4))); 9} __attribute__ ((packed,aligned(4)));
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 4191fd9d4d11..7dad597ff86e 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -23,7 +23,7 @@
23 23
24static struct semaphore m_sem; 24static struct semaphore m_sem;
25 25
26extern int css_process_crw(int); 26extern int css_process_crw(int, int);
27extern int chsc_process_crw(void); 27extern int chsc_process_crw(void);
28extern int chp_process_crw(int, int); 28extern int chp_process_crw(int, int);
29extern void css_reiterate_subchannels(void); 29extern void css_reiterate_subchannels(void);
@@ -49,9 +49,10 @@ s390_handle_damage(char *msg)
49static int 49static int
50s390_collect_crw_info(void *param) 50s390_collect_crw_info(void *param)
51{ 51{
52 struct crw crw; 52 struct crw crw[2];
53 int ccode, ret, slow; 53 int ccode, ret, slow;
54 struct semaphore *sem; 54 struct semaphore *sem;
55 unsigned int chain;
55 56
56 sem = (struct semaphore *)param; 57 sem = (struct semaphore *)param;
57 /* Set a nice name. */ 58 /* Set a nice name. */
@@ -59,25 +60,50 @@ s390_collect_crw_info(void *param)
59repeat: 60repeat:
60 down_interruptible(sem); 61 down_interruptible(sem);
61 slow = 0; 62 slow = 0;
63 chain = 0;
62 while (1) { 64 while (1) {
63 ccode = stcrw(&crw); 65 if (unlikely(chain > 1)) {
66 struct crw tmp_crw;
67
68 printk(KERN_WARNING"%s: Code does not support more "
69 "than two chained crws; please report to "
70 "linux390@de.ibm.com!\n", __FUNCTION__);
71 ccode = stcrw(&tmp_crw);
72 printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
73 "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
74 __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
75 tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
76 tmp_crw.erc, tmp_crw.rsid);
77 printk(KERN_WARNING"%s: This was crw number %x in the "
78 "chain\n", __FUNCTION__, chain);
79 if (ccode != 0)
80 break;
81 chain = tmp_crw.chn ? chain + 1 : 0;
82 continue;
83 }
84 ccode = stcrw(&crw[chain]);
64 if (ccode != 0) 85 if (ccode != 0)
65 break; 86 break;
66 DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " 87 DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, "
67 "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", 88 "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
68 crw.slct, crw.oflw, crw.chn, crw.rsc, crw.anc, 89 crw[chain].slct, crw[chain].oflw, crw[chain].chn,
69 crw.erc, crw.rsid); 90 crw[chain].rsc, crw[chain].anc, crw[chain].erc,
91 crw[chain].rsid);
70 /* Check for overflows. */ 92 /* Check for overflows. */
71 if (crw.oflw) { 93 if (crw[chain].oflw) {
72 pr_debug("%s: crw overflow detected!\n", __FUNCTION__); 94 pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
73 css_reiterate_subchannels(); 95 css_reiterate_subchannels();
96 chain = 0;
74 slow = 1; 97 slow = 1;
75 continue; 98 continue;
76 } 99 }
77 switch (crw.rsc) { 100 switch (crw[chain].rsc) {
78 case CRW_RSC_SCH: 101 case CRW_RSC_SCH:
79 pr_debug("source is subchannel %04X\n", crw.rsid); 102 if (crw[0].chn && !chain)
80 ret = css_process_crw (crw.rsid); 103 break;
104 pr_debug("source is subchannel %04X\n", crw[0].rsid);
105 ret = css_process_crw (crw[0].rsid,
106 chain ? crw[1].rsid : 0);
81 if (ret == -EAGAIN) 107 if (ret == -EAGAIN)
82 slow = 1; 108 slow = 1;
83 break; 109 break;
@@ -85,18 +111,18 @@ repeat:
85 pr_debug("source is monitoring facility\n"); 111 pr_debug("source is monitoring facility\n");
86 break; 112 break;
87 case CRW_RSC_CPATH: 113 case CRW_RSC_CPATH:
88 pr_debug("source is channel path %02X\n", crw.rsid); 114 pr_debug("source is channel path %02X\n", crw[0].rsid);
89 switch (crw.erc) { 115 switch (crw[0].erc) {
90 case CRW_ERC_IPARM: /* Path has come. */ 116 case CRW_ERC_IPARM: /* Path has come. */
91 ret = chp_process_crw(crw.rsid, 1); 117 ret = chp_process_crw(crw[0].rsid, 1);
92 break; 118 break;
93 case CRW_ERC_PERRI: /* Path has gone. */ 119 case CRW_ERC_PERRI: /* Path has gone. */
94 case CRW_ERC_PERRN: 120 case CRW_ERC_PERRN:
95 ret = chp_process_crw(crw.rsid, 0); 121 ret = chp_process_crw(crw[0].rsid, 0);
96 break; 122 break;
97 default: 123 default:
98 pr_debug("Don't know how to handle erc=%x\n", 124 pr_debug("Don't know how to handle erc=%x\n",
99 crw.erc); 125 crw[0].erc);
100 ret = 0; 126 ret = 0;
101 } 127 }
102 if (ret == -EAGAIN) 128 if (ret == -EAGAIN)
@@ -115,6 +141,8 @@ repeat:
115 pr_debug("unknown source\n"); 141 pr_debug("unknown source\n");
116 break; 142 break;
117 } 143 }
144 /* chain is always 0 or 1 here. */
145 chain = crw[chain].chn ? chain + 1 : 0;
118 } 146 }
119 if (slow) 147 if (slow)
120 queue_work(slow_path_wq, &slow_path_work); 148 queue_work(slow_path_wq, &slow_path_work);