aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2008-01-26 08:10:45 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-01-26 08:11:01 -0500
commitb279a4f56d5476a0b9b0a97397f7a7bbe00b9b2f (patch)
tree8f6fe1b5e68ecc0684a88fb67bd6179cf6c59707 /drivers/s390
parent4e8e56c6713398f417317d449f50c08bf2756c66 (diff)
[S390] cio: I/O subchannel specific fields.
Some fields may be !0 only for I/O subchannels. Add some checks where required. Also adapt cio_enable_subchannel() to make the caller specify the intparm, which makes it more generic. Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/chsc.c5
-rw-r--r--drivers/s390/cio/cio.c24
-rw-r--r--drivers/s390/cio/cio.h4
-rw-r--r--drivers/s390/cio/css.c18
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device_fsm.c9
-rw-r--r--drivers/s390/cio/device_ops.c2
7 files changed, 42 insertions, 22 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 44a2ea40806e..12a344c66b46 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -89,7 +89,8 @@ int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
89 /* Copy data */ 89 /* Copy data */
90 ret = 0; 90 ret = 0;
91 memset(ssd, 0, sizeof(struct chsc_ssd_info)); 91 memset(ssd, 0, sizeof(struct chsc_ssd_info));
92 if ((ssd_area->st != 0) && (ssd_area->st != 2)) 92 if ((ssd_area->st != SUBCHANNEL_TYPE_IO) &&
93 (ssd_area->st != SUBCHANNEL_TYPE_MSG))
93 goto out_free; 94 goto out_free;
94 ssd->path_mask = ssd_area->path_mask; 95 ssd->path_mask = ssd_area->path_mask;
95 ssd->fla_valid_mask = ssd_area->fla_valid_mask; 96 ssd->fla_valid_mask = ssd_area->fla_valid_mask;
@@ -158,7 +159,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
158 spin_lock_irq(sch->lock); 159 spin_lock_irq(sch->lock);
159 160
160 stsch(sch->schid, &schib); 161 stsch(sch->schid, &schib);
161 if (!schib.pmcw.dnv) 162 if (!css_sch_is_valid(&schib))
162 goto out_unreg; 163 goto out_unreg;
163 memcpy(&sch->schib, &schib, sizeof(struct schib)); 164 memcpy(&sch->schib, &schib, sizeof(struct schib));
164 /* Check for single path devices. */ 165 /* Check for single path devices. */
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 89ced3408138..f16c15c13f6e 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -406,8 +406,8 @@ cio_modify (struct subchannel *sch)
406/* 406/*
407 * Enable subchannel. 407 * Enable subchannel.
408 */ 408 */
409int 409int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
410cio_enable_subchannel (struct subchannel *sch, unsigned int isc) 410 u32 intparm)
411{ 411{
412 char dbf_txt[15]; 412 char dbf_txt[15];
413 int ccode; 413 int ccode;
@@ -426,7 +426,7 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
426 for (retry = 5, ret = 0; retry > 0; retry--) { 426 for (retry = 5, ret = 0; retry > 0; retry--) {
427 sch->schib.pmcw.ena = 1; 427 sch->schib.pmcw.ena = 1;
428 sch->schib.pmcw.isc = isc; 428 sch->schib.pmcw.isc = isc;
429 sch->schib.pmcw.intparm = (u32)(addr_t)sch; 429 sch->schib.pmcw.intparm = intparm;
430 ret = cio_modify(sch); 430 ret = cio_modify(sch);
431 if (ret == -ENODEV) 431 if (ret == -ENODEV)
432 break; 432 break;
@@ -577,11 +577,8 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
577 } 577 }
578 578
579 /* Initialization for io subchannels. */ 579 /* Initialization for io subchannels. */
580 if (!sch->schib.pmcw.dnv) { 580 if (!css_sch_is_valid(&sch->schib))
581 /* io subchannel but device number is invalid. */ 581 return -ENODEV;
582 err = -ENODEV;
583 goto out;
584 }
585 /* Devno is valid. */ 582 /* Devno is valid. */
586 if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) { 583 if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
587 /* 584 /*
@@ -745,9 +742,9 @@ cio_test_for_console(struct subchannel_id schid, void *data)
745{ 742{
746 if (stsch_err(schid, &console_subchannel.schib) != 0) 743 if (stsch_err(schid, &console_subchannel.schib) != 0)
747 return -ENXIO; 744 return -ENXIO;
748 if (console_subchannel.schib.pmcw.dnv && 745 if ((console_subchannel.schib.pmcw.st == SUBCHANNEL_TYPE_IO) &&
749 console_subchannel.schib.pmcw.dev == 746 console_subchannel.schib.pmcw.dnv &&
750 console_devno) { 747 (console_subchannel.schib.pmcw.dev == console_devno)) {
751 console_irq = schid.sch_no; 748 console_irq = schid.sch_no;
752 return 1; /* found */ 749 return 1; /* found */
753 } 750 }
@@ -765,6 +762,7 @@ cio_get_console_sch_no(void)
765 /* VM provided us with the irq number of the console. */ 762 /* VM provided us with the irq number of the console. */
766 schid.sch_no = console_irq; 763 schid.sch_no = console_irq;
767 if (stsch(schid, &console_subchannel.schib) != 0 || 764 if (stsch(schid, &console_subchannel.schib) != 0 ||
765 (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) ||
768 !console_subchannel.schib.pmcw.dnv) 766 !console_subchannel.schib.pmcw.dnv)
769 return -1; 767 return -1;
770 console_devno = console_subchannel.schib.pmcw.dev; 768 console_devno = console_subchannel.schib.pmcw.dev;
@@ -1029,7 +1027,7 @@ static int __reipl_subchannel_match(struct subchannel_id schid, void *data)
1029 1027
1030 if (stsch_reset(schid, &schib)) 1028 if (stsch_reset(schid, &schib))
1031 return -ENXIO; 1029 return -ENXIO;
1032 if (schib.pmcw.dnv && 1030 if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv &&
1033 (schib.pmcw.dev == match_id->devid.devno) && 1031 (schib.pmcw.dev == match_id->devid.devno) &&
1034 (schid.ssid == match_id->devid.ssid)) { 1032 (schid.ssid == match_id->devid.ssid)) {
1035 match_id->schid = schid; 1033 match_id->schid = schid;
@@ -1075,6 +1073,8 @@ int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo)
1075 return -ENODEV; 1073 return -ENODEV;
1076 if (stsch(schid, &schib)) 1074 if (stsch(schid, &schib))
1077 return -ENODEV; 1075 return -ENODEV;
1076 if (schib.pmcw.st != SUBCHANNEL_TYPE_IO)
1077 return -ENODEV;
1078 if (!schib.pmcw.dnv) 1078 if (!schib.pmcw.dnv)
1079 return -ENODEV; 1079 return -ENODEV;
1080 iplinfo->devno = schib.pmcw.dev; 1080 iplinfo->devno = schib.pmcw.dev;
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index d1483d65049c..52afa4c784de 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -60,7 +60,7 @@ struct subchannel {
60 enum { 60 enum {
61 SUBCHANNEL_TYPE_IO = 0, 61 SUBCHANNEL_TYPE_IO = 0,
62 SUBCHANNEL_TYPE_CHSC = 1, 62 SUBCHANNEL_TYPE_CHSC = 1,
63 SUBCHANNEL_TYPE_MESSAGE = 2, 63 SUBCHANNEL_TYPE_MSG = 2,
64 SUBCHANNEL_TYPE_ADM = 3, 64 SUBCHANNEL_TYPE_ADM = 3,
65 } st; /* subchannel type */ 65 } st; /* subchannel type */
66 66
@@ -85,7 +85,7 @@ struct subchannel {
85#define to_subchannel(n) container_of(n, struct subchannel, dev) 85#define to_subchannel(n) container_of(n, struct subchannel, dev)
86 86
87extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); 87extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
88extern int cio_enable_subchannel (struct subchannel *, unsigned int); 88extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32);
89extern int cio_disable_subchannel (struct subchannel *); 89extern int cio_disable_subchannel (struct subchannel *);
90extern int cio_cancel (struct subchannel *); 90extern int cio_cancel (struct subchannel *);
91extern int cio_clear (struct subchannel *); 91extern int cio_clear (struct subchannel *);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 2520a44fb93d..4d98a0fddedf 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -237,11 +237,25 @@ get_subchannel_by_schid(struct subchannel_id schid)
237 return dev ? to_subchannel(dev) : NULL; 237 return dev ? to_subchannel(dev) : NULL;
238} 238}
239 239
240/**
241 * css_sch_is_valid() - check if a subchannel is valid
242 * @schib: subchannel information block for the subchannel
243 */
244int css_sch_is_valid(struct schib *schib)
245{
246 if ((schib->pmcw.st == SUBCHANNEL_TYPE_IO) && !schib->pmcw.dnv)
247 return 0;
248 return 1;
249}
250EXPORT_SYMBOL_GPL(css_sch_is_valid);
251
240static int css_get_subchannel_status(struct subchannel *sch) 252static int css_get_subchannel_status(struct subchannel *sch)
241{ 253{
242 struct schib schib; 254 struct schib schib;
243 255
244 if (stsch(sch->schid, &schib) || !schib.pmcw.dnv) 256 if (stsch(sch->schid, &schib))
257 return CIO_GONE;
258 if (!css_sch_is_valid(&schib))
245 return CIO_GONE; 259 return CIO_GONE;
246 if (sch->schib.pmcw.dnv && (schib.pmcw.dev != sch->schib.pmcw.dev)) 260 if (sch->schib.pmcw.dnv && (schib.pmcw.dev != sch->schib.pmcw.dev))
247 return CIO_REVALIDATE; 261 return CIO_REVALIDATE;
@@ -349,7 +363,7 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
349 /* Will be done on the slow path. */ 363 /* Will be done on the slow path. */
350 return -EAGAIN; 364 return -EAGAIN;
351 } 365 }
352 if (stsch_err(schid, &schib) || !schib.pmcw.dnv) { 366 if (stsch_err(schid, &schib) || !css_sch_is_valid(&schib)) {
353 /* Unusable - ignore. */ 367 /* Unusable - ignore. */
354 return 0; 368 return 0;
355 } 369 }
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index b2b4a30c285e..ee65761e8254 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -136,6 +136,8 @@ void css_schedule_eval(struct subchannel_id schid);
136void css_schedule_eval_all(void); 136void css_schedule_eval_all(void);
137 137
138int sch_is_pseudo_sch(struct subchannel *); 138int sch_is_pseudo_sch(struct subchannel *);
139struct schib;
140int css_sch_is_valid(struct schib *);
139 141
140extern struct workqueue_struct *slow_path_wq; 142extern struct workqueue_struct *slow_path_wq;
141 143
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 44ce7a3d3857..4804d944fb4d 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -553,7 +553,8 @@ ccw_device_recognition(struct ccw_device *cdev)
553 (cdev->private->state != DEV_STATE_BOXED)) 553 (cdev->private->state != DEV_STATE_BOXED))
554 return -EINVAL; 554 return -EINVAL;
555 sch = to_subchannel(cdev->dev.parent); 555 sch = to_subchannel(cdev->dev.parent);
556 ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc); 556 ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
557 (u32)(addr_t)sch);
557 if (ret != 0) 558 if (ret != 0)
558 /* Couldn't enable the subchannel for i/o. Sick device. */ 559 /* Couldn't enable the subchannel for i/o. Sick device. */
559 return ret; 560 return ret;
@@ -663,7 +664,8 @@ ccw_device_online(struct ccw_device *cdev)
663 sch = to_subchannel(cdev->dev.parent); 664 sch = to_subchannel(cdev->dev.parent);
664 if (css_init_done && !get_device(&cdev->dev)) 665 if (css_init_done && !get_device(&cdev->dev))
665 return -ENODEV; 666 return -ENODEV;
666 ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc); 667 ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
668 (u32)(addr_t)sch);
667 if (ret != 0) { 669 if (ret != 0) {
668 /* Couldn't enable the subchannel for i/o. Sick device. */ 670 /* Couldn't enable the subchannel for i/o. Sick device. */
669 if (ret == -ENODEV) 671 if (ret == -ENODEV)
@@ -1043,7 +1045,8 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
1043 struct subchannel *sch; 1045 struct subchannel *sch;
1044 1046
1045 sch = to_subchannel(cdev->dev.parent); 1047 sch = to_subchannel(cdev->dev.parent);
1046 if (cio_enable_subchannel(sch, sch->schib.pmcw.isc) != 0) 1048 if (cio_enable_subchannel(sch, sch->schib.pmcw.isc,
1049 (u32)(addr_t)sch) != 0)
1047 /* Couldn't enable the subchannel for i/o. Sick device. */ 1050 /* Couldn't enable the subchannel for i/o. Sick device. */
1048 return; 1051 return;
1049 1052
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 7fd2dadc3297..49b58eb0fab8 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -501,7 +501,7 @@ ccw_device_stlck(struct ccw_device *cdev)
501 return -ENOMEM; 501 return -ENOMEM;
502 } 502 }
503 spin_lock_irqsave(sch->lock, flags); 503 spin_lock_irqsave(sch->lock, flags);
504 ret = cio_enable_subchannel(sch, 3); 504 ret = cio_enable_subchannel(sch, 3, (u32)(addr_t)sch);
505 if (ret) 505 if (ret)
506 goto out_unlock; 506 goto out_unlock;
507 /* 507 /*