[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>
This commit is contained in:
Cornelia Huck
2006-01-06 00:19:25 -08:00
committed by Linus Torvalds
parent 678a395b35
commit fb6958a594
16 changed files with 354 additions and 165 deletions

View File

@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/css.c
* driver for channel subsystem
* $Revision: 1.85 $
* $Revision: 1.93 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -23,6 +23,7 @@
int need_rescan = 0;
int css_init_done = 0;
static int max_ssid = 0;
struct channel_subsystem *css[__MAX_CSSID + 1];
@@ -37,10 +38,13 @@ for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
init_subchannel_id(&schid);
ret = -ENODEV;
do {
ret = fn(schid, data);
if (ret)
break;
} while (schid.sch_no++ < __MAX_SUBCHANNEL);
do {
ret = fn(schid, data);
if (ret)
break;
} while (schid.sch_no++ < __MAX_SUBCHANNEL);
schid.sch_no = 0;
} while (schid.ssid++ < max_ssid);
return ret;
}
@@ -205,8 +209,8 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow)
return -EAGAIN; /* Will be done on the slow path. */
}
event = css_get_subchannel_status(sch, schid);
CIO_MSG_EVENT(4, "Evaluating schid %04x, event %d, %s, %s path.\n",
schid.sch_no, event,
CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n",
schid.ssid, schid.sch_no, event,
sch?(disc?"disconnected":"normal"):"unknown",
slow?"slow":"fast");
switch (event) {
@@ -352,19 +356,23 @@ css_reiterate_subchannels(void)
* Called from the machine check handler for subchannel report words.
*/
int
css_process_crw(int irq)
css_process_crw(int rsid1, int rsid2)
{
int ret;
struct subchannel_id mchk_schid;
CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq);
CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n",
rsid1, rsid2);
if (need_rescan)
/* We need to iterate all subchannels anyway. */
return -EAGAIN;
init_subchannel_id(&mchk_schid);
mchk_schid.sch_no = irq;
mchk_schid.sch_no = rsid1;
if (rsid2 != 0)
mchk_schid.ssid = (rsid2 >> 8) & 3;
/*
* Since we are always presented with IPI in the CRW, we have to
* use stsch() to find out if the subchannel in question has come
@@ -465,12 +473,23 @@ init_channel_subsystem (void)
if ((ret = bus_register(&css_bus_type)))
goto out;
/* Try to enable MSS. */
ret = chsc_enable_facility(CHSC_SDA_OC_MSS);
switch (ret) {
case 0: /* Success. */
max_ssid = __MAX_SSID;
break;
case -ENOMEM:
goto out_bus;
default:
max_ssid = 0;
}
/* Setup css structure. */
for (i = 0; i <= __MAX_CSSID; i++) {
css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL);
if (!css[i]) {
ret = -ENOMEM;
goto out_bus;
goto out_unregister;
}
setup_css(i);
ret = device_register(&css[i]->device);
@@ -485,11 +504,12 @@ init_channel_subsystem (void)
return 0;
out_free:
kfree(css[i]);
out_bus:
out_unregister:
while (i > 0) {
i--;
device_unregister(&css[i]->device);
}
out_bus:
bus_unregister(&css_bus_type);
out:
return ret;