diff options
author | Cornelia Huck <cohuck@de.ibm.com> | 2006-01-06 03:19:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 11:33:52 -0500 |
commit | fb6958a594da49ece869793e6ec163b89fc5f79f (patch) | |
tree | 0746cc23ab13a059f9a34d7fc134aaf6410d07b8 /drivers/s390/cio/cio.c | |
parent | 678a395b356a98368a93c3640252502b70c3676f (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/cio.c')
-rw-r--r-- | drivers/s390/cio/cio.c | 35 |
1 files changed, 21 insertions, 14 deletions
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) | |||
693 | static int | 700 | static int |
694 | cio_test_for_console(struct subchannel_id schid, void *data) | 701 | cio_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; |