aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cio.c
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2008-07-14 03:58:43 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2008-07-14 04:02:05 -0400
commit0ae7a7b250bdf7ee87c8346164ef3c47fb79dfbd (patch)
tree95da6f03f135cf1a754eba262117a2ae8fd072a5 /drivers/s390/cio/cio.c
parentb4a33acb690525c5ca37e177f5cd26c62d3ef976 (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.c126
1 files changed, 51 insertions, 75 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 7b5969ed05c..903e23ae8ed 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/* 497static 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 */
509int 529int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
510cio_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;
611out: 580out:
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
866static int 834static 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 }
904out:
929 return 0; 905 return 0;
930} 906}
931 907