aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/s390/cio/chp.h1
-rw-r--r--drivers/s390/cio/cio.c126
-rw-r--r--drivers/s390/cio/css.c19
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device.c38
5 files changed, 85 insertions, 101 deletions
diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h
index 65286563c592..59c2fc069d9e 100644
--- a/drivers/s390/cio/chp.h
+++ b/drivers/s390/cio/chp.h
@@ -12,6 +12,7 @@
12#include <linux/device.h> 12#include <linux/device.h>
13#include <asm/chpid.h> 13#include <asm/chpid.h>
14#include "chsc.h" 14#include "chsc.h"
15#include "css.h"
15 16
16#define CHP_STATUS_STANDBY 0 17#define CHP_STATUS_STANDBY 0
17#define CHP_STATUS_CONFIGURED 1 18#define CHP_STATUS_CONFIGURED 1
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/* 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
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index a76956512b2d..b7f4b52c5a9a 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -121,25 +121,6 @@ css_alloc_subchannel(struct subchannel_id schid)
121 kfree(sch); 121 kfree(sch);
122 return ERR_PTR(ret); 122 return ERR_PTR(ret);
123 } 123 }
124
125 if (sch->st != SUBCHANNEL_TYPE_IO) {
126 /* For now we ignore all non-io subchannels. */
127 kfree(sch);
128 return ERR_PTR(-EINVAL);
129 }
130
131 /*
132 * Set intparm to subchannel address.
133 * This is fine even on 64bit since the subchannel is always located
134 * under 2G.
135 */
136 sch->schib.pmcw.intparm = (u32)(addr_t)sch;
137 ret = cio_modify(sch);
138 if (ret) {
139 kfree(sch->lock);
140 kfree(sch);
141 return ERR_PTR(ret);
142 }
143 return sch; 124 return sch;
144} 125}
145 126
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index e1913518f354..bfe0ada43f2c 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -60,8 +60,6 @@ struct pgid {
60 60
61/* 61/*
62 * A css driver handles all subchannels of one type. 62 * A css driver handles all subchannels of one type.
63 * Currently, we only care about I/O subchannels (type 0), these
64 * have a ccw_device connected to them.
65 */ 63 */
66struct subchannel; 64struct subchannel;
67struct css_driver { 65struct css_driver {
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index e22813db74a2..0ed5a81260bc 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -24,6 +24,7 @@
24#include <asm/param.h> /* HZ */ 24#include <asm/param.h> /* HZ */
25#include <asm/cmb.h> 25#include <asm/cmb.h>
26 26
27#include "chp.h"
27#include "cio.h" 28#include "cio.h"
28#include "cio_debug.h" 29#include "cio_debug.h"
29#include "css.h" 30#include "css.h"
@@ -1037,7 +1038,6 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
1037 struct ccw_device_private *priv; 1038 struct ccw_device_private *priv;
1038 1039
1039 sch_set_cdev(sch, cdev); 1040 sch_set_cdev(sch, cdev);
1040 sch->driver = &io_subchannel_driver;
1041 cdev->ccwlock = sch->lock; 1041 cdev->ccwlock = sch->lock;
1042 1042
1043 /* Init private data. */ 1043 /* Init private data. */
@@ -1122,8 +1122,33 @@ static void io_subchannel_irq(struct subchannel *sch)
1122 dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); 1122 dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
1123} 1123}
1124 1124
1125static int 1125static void io_subchannel_init_fields(struct subchannel *sch)
1126io_subchannel_probe (struct subchannel *sch) 1126{
1127 if (cio_is_console(sch->schid))
1128 sch->opm = 0xff;
1129 else
1130 sch->opm = chp_get_sch_opm(sch);
1131 sch->lpm = sch->schib.pmcw.pam & sch->opm;
1132 sch->isc = cio_is_console(sch->schid) ? 1 : 3;
1133
1134 CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X"
1135 " - PIM = %02X, PAM = %02X, POM = %02X\n",
1136 sch->schib.pmcw.dev, sch->schid.ssid,
1137 sch->schid.sch_no, sch->schib.pmcw.pim,
1138 sch->schib.pmcw.pam, sch->schib.pmcw.pom);
1139 /* Initially set up some fields in the pmcw. */
1140 sch->schib.pmcw.ena = 0;
1141 sch->schib.pmcw.csense = 1; /* concurrent sense */
1142 if ((sch->lpm & (sch->lpm - 1)) != 0)
1143 sch->schib.pmcw.mp = 1; /* multipath mode */
1144 /* clean up possible residual cmf stuff */
1145 sch->schib.pmcw.mme = 0;
1146 sch->schib.pmcw.mbfc = 0;
1147 sch->schib.pmcw.mbi = 0;
1148 sch->schib.mba = 0;
1149}
1150
1151static int io_subchannel_probe(struct subchannel *sch)
1127{ 1152{
1128 struct ccw_device *cdev; 1153 struct ccw_device *cdev;
1129 int rc; 1154 int rc;
@@ -1152,6 +1177,7 @@ io_subchannel_probe (struct subchannel *sch)
1152 get_device(&cdev->dev); 1177 get_device(&cdev->dev);
1153 return 0; 1178 return 0;
1154 } 1179 }
1180 io_subchannel_init_fields(sch);
1155 /* 1181 /*
1156 * First check if a fitting device may be found amongst the 1182 * First check if a fitting device may be found amongst the
1157 * disconnected devices or in the orphanage. 1183 * disconnected devices or in the orphanage.
@@ -1297,14 +1323,16 @@ spinlock_t * cio_get_console_lock(void)
1297 return &ccw_console_lock; 1323 return &ccw_console_lock;
1298} 1324}
1299 1325
1300static int 1326static int ccw_device_console_enable(struct ccw_device *cdev,
1301ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch) 1327 struct subchannel *sch)
1302{ 1328{
1303 int rc; 1329 int rc;
1304 1330
1305 /* Attach subchannel private data. */ 1331 /* Attach subchannel private data. */
1306 sch->private = cio_get_console_priv(); 1332 sch->private = cio_get_console_priv();
1307 memset(sch->private, 0, sizeof(struct io_subchannel_private)); 1333 memset(sch->private, 0, sizeof(struct io_subchannel_private));
1334 io_subchannel_init_fields(sch);
1335 sch->driver = &io_subchannel_driver;
1308 /* Initialize the ccw_device structure. */ 1336 /* Initialize the ccw_device structure. */
1309 cdev->dev.parent= &sch->dev; 1337 cdev->dev.parent= &sch->dev;
1310 rc = io_subchannel_recog(cdev, sch); 1338 rc = io_subchannel_recog(cdev, sch);