diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2008-07-14 03:58:43 -0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-07-14 04:02:05 -0400 |
commit | 0ae7a7b250bdf7ee87c8346164ef3c47fb79dfbd (patch) | |
tree | 95da6f03f135cf1a754eba262117a2ae8fd072a5 /drivers/s390/cio/cio.c | |
parent | b4a33acb690525c5ca37e177f5cd26c62d3ef976 (diff) |
[S390] cio: Register all subchannels.
Register all valid subchannels, not only I/O subchannels.
Move I/O subchannel specific initialization to io_subchannel_probe().
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r-- | drivers/s390/cio/cio.c | 126 |
1 files changed, 51 insertions, 75 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 7b5969ed05cd..903e23ae8ed5 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -2,7 +2,7 @@ | |||
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 | * | 4 | * |
5 | * Copyright (C) IBM Corp. 1999,2006 | 5 | * Copyright IBM Corp. 1999,2008 |
6 | * Author(s): Ingo Adlung (adlung@de.ibm.com) | 6 | * Author(s): Ingo Adlung (adlung@de.ibm.com) |
7 | * Cornelia Huck (cornelia.huck@de.ibm.com) | 7 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
8 | * Arnd Bergmann (arndb@de.ibm.com) | 8 | * Arnd Bergmann (arndb@de.ibm.com) |
@@ -494,27 +494,46 @@ int cio_create_sch_lock(struct subchannel *sch) | |||
494 | return 0; | 494 | return 0; |
495 | } | 495 | } |
496 | 496 | ||
497 | /* | 497 | static int cio_validate_io_subchannel(struct subchannel *sch) |
498 | * cio_validate_subchannel() | 498 | { |
499 | /* Initialization for io subchannels. */ | ||
500 | if (!css_sch_is_valid(&sch->schib)) | ||
501 | return -ENODEV; | ||
502 | |||
503 | /* Devno is valid. */ | ||
504 | if (is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev)) { | ||
505 | /* | ||
506 | * This device must not be known to Linux. So we simply | ||
507 | * say that there is no device and return ENODEV. | ||
508 | */ | ||
509 | CIO_MSG_EVENT(6, "Blacklisted device detected " | ||
510 | "at devno %04X, subchannel set %x\n", | ||
511 | sch->schib.pmcw.dev, sch->schid.ssid); | ||
512 | return -ENODEV; | ||
513 | } | ||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | /** | ||
518 | * cio_validate_subchannel - basic validation of subchannel | ||
519 | * @sch: subchannel structure to be filled out | ||
520 | * @schid: subchannel id | ||
499 | * | 521 | * |
500 | * Find out subchannel type and initialize struct subchannel. | 522 | * Find out subchannel type and initialize struct subchannel. |
501 | * Return codes: | 523 | * Return codes: |
502 | * SUBCHANNEL_TYPE_IO for a normal io subchannel | 524 | * 0 on success |
503 | * SUBCHANNEL_TYPE_CHSC for a chsc subchannel | ||
504 | * SUBCHANNEL_TYPE_MESSAGE for a messaging subchannel | ||
505 | * SUBCHANNEL_TYPE_ADM for a adm(?) subchannel | ||
506 | * -ENXIO for non-defined subchannels | 525 | * -ENXIO for non-defined subchannels |
507 | * -ENODEV for subchannels with invalid device number or blacklisted devices | 526 | * -ENODEV for invalid subchannels or blacklisted devices |
527 | * -EIO for subchannels in an invalid subchannel set | ||
508 | */ | 528 | */ |
509 | int | 529 | int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) |
510 | cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | ||
511 | { | 530 | { |
512 | char dbf_txt[15]; | 531 | char dbf_txt[15]; |
513 | int ccode; | 532 | int ccode; |
514 | int err; | 533 | int err; |
515 | 534 | ||
516 | sprintf (dbf_txt, "valsch%x", schid.sch_no); | 535 | sprintf(dbf_txt, "valsch%x", schid.sch_no); |
517 | CIO_TRACE_EVENT (4, dbf_txt); | 536 | CIO_TRACE_EVENT(4, dbf_txt); |
518 | 537 | ||
519 | /* Nuke all fields. */ | 538 | /* Nuke all fields. */ |
520 | memset(sch, 0, sizeof(struct subchannel)); | 539 | memset(sch, 0, sizeof(struct subchannel)); |
@@ -545,68 +564,18 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
545 | } | 564 | } |
546 | /* Copy subchannel type from path management control word. */ | 565 | /* Copy subchannel type from path management control word. */ |
547 | sch->st = sch->schib.pmcw.st; | 566 | sch->st = sch->schib.pmcw.st; |
548 | 567 | switch (sch->st) { | |
549 | /* | 568 | case SUBCHANNEL_TYPE_IO: |
550 | * ... just being curious we check for non I/O subchannels | 569 | err = cio_validate_io_subchannel(sch); |
551 | */ | 570 | break; |
552 | if (sch->st != 0) { | 571 | default: |
553 | CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports " | 572 | err = 0; |
554 | "non-I/O subchannel type %04X\n", | ||
555 | sch->schid.ssid, sch->schid.sch_no, sch->st); | ||
556 | /* We stop here for non-io subchannels. */ | ||
557 | err = sch->st; | ||
558 | goto out; | ||
559 | } | 573 | } |
560 | 574 | if (err) | |
561 | /* Initialization for io subchannels. */ | ||
562 | if (!css_sch_is_valid(&sch->schib)) { | ||
563 | err = -ENODEV; | ||
564 | goto out; | 575 | goto out; |
565 | } | ||
566 | 576 | ||
567 | /* Devno is valid. */ | 577 | CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n", |
568 | if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) { | 578 | sch->schid.ssid, sch->schid.sch_no, sch->st); |
569 | /* | ||
570 | * This device must not be known to Linux. So we simply | ||
571 | * say that there is no device and return ENODEV. | ||
572 | */ | ||
573 | CIO_MSG_EVENT(6, "Blacklisted device detected " | ||
574 | "at devno %04X, subchannel set %x\n", | ||
575 | sch->schib.pmcw.dev, sch->schid.ssid); | ||
576 | err = -ENODEV; | ||
577 | goto out; | ||
578 | } | ||
579 | if (cio_is_console(sch->schid)) { | ||
580 | sch->opm = 0xff; | ||
581 | sch->isc = 1; | ||
582 | } else { | ||
583 | sch->opm = chp_get_sch_opm(sch); | ||
584 | sch->isc = 3; | ||
585 | } | ||
586 | sch->lpm = sch->schib.pmcw.pam & sch->opm; | ||
587 | |||
588 | CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X " | ||
589 | "- PIM = %02X, PAM = %02X, POM = %02X\n", | ||
590 | sch->schib.pmcw.dev, sch->schid.ssid, | ||
591 | sch->schid.sch_no, sch->schib.pmcw.pim, | ||
592 | sch->schib.pmcw.pam, sch->schib.pmcw.pom); | ||
593 | |||
594 | /* | ||
595 | * We now have to initially ... | ||
596 | * ... enable "concurrent sense" | ||
597 | * ... enable "multipath mode" if more than one | ||
598 | * CHPID is available. This is done regardless | ||
599 | * whether multiple paths are available for us. | ||
600 | */ | ||
601 | sch->schib.pmcw.csense = 1; /* concurrent sense */ | ||
602 | sch->schib.pmcw.ena = 0; | ||
603 | if ((sch->lpm & (sch->lpm - 1)) != 0) | ||
604 | sch->schib.pmcw.mp = 1; /* multipath mode */ | ||
605 | /* clean up possible residual cmf stuff */ | ||
606 | sch->schib.pmcw.mme = 0; | ||
607 | sch->schib.pmcw.mbfc = 0; | ||
608 | sch->schib.pmcw.mbi = 0; | ||
609 | sch->schib.mba = 0; | ||
610 | return 0; | 579 | return 0; |
611 | out: | 580 | out: |
612 | if (!cio_is_console(schid)) | 581 | if (!cio_is_console(schid)) |
@@ -793,7 +762,6 @@ cio_probe_console(void) | |||
793 | * enable console I/O-interrupt subclass 1 | 762 | * enable console I/O-interrupt subclass 1 |
794 | */ | 763 | */ |
795 | ctl_set_bit(6, 30); | 764 | ctl_set_bit(6, 30); |
796 | console_subchannel.isc = 1; | ||
797 | console_subchannel.schib.pmcw.isc = 1; | 765 | console_subchannel.schib.pmcw.isc = 1; |
798 | console_subchannel.schib.pmcw.intparm = | 766 | console_subchannel.schib.pmcw.intparm = |
799 | (u32)(addr_t)&console_subchannel; | 767 | (u32)(addr_t)&console_subchannel; |
@@ -864,7 +832,7 @@ static void udelay_reset(unsigned long usecs) | |||
864 | } | 832 | } |
865 | 833 | ||
866 | static int | 834 | static int |
867 | __clear_subchannel_easy(struct subchannel_id schid) | 835 | __clear_io_subchannel_easy(struct subchannel_id schid) |
868 | { | 836 | { |
869 | int retry; | 837 | int retry; |
870 | 838 | ||
@@ -921,11 +889,19 @@ static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) | |||
921 | case -ENODEV: | 889 | case -ENODEV: |
922 | break; | 890 | break; |
923 | default: /* -EBUSY */ | 891 | default: /* -EBUSY */ |
924 | if (__clear_subchannel_easy(schid)) | 892 | switch (schib.pmcw.st) { |
925 | break; /* give up... */ | 893 | case SUBCHANNEL_TYPE_IO: |
894 | if (__clear_io_subchannel_easy(schid)) | ||
895 | goto out; /* give up... */ | ||
896 | break; | ||
897 | default: | ||
898 | /* No default clear strategy */ | ||
899 | break; | ||
900 | } | ||
926 | stsch(schid, &schib); | 901 | stsch(schid, &schib); |
927 | __disable_subchannel_easy(schid, &schib); | 902 | __disable_subchannel_easy(schid, &schib); |
928 | } | 903 | } |
904 | out: | ||
929 | return 0; | 905 | return 0; |
930 | } | 906 | } |
931 | 907 | ||