aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/css.c
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/cio/css.c
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/cio/css.c')
-rw-r--r--drivers/s390/cio/css.c44
1 files changed, 32 insertions, 12 deletions
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;