diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2008-01-26 08:10:45 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-01-26 08:11:01 -0500 |
commit | b279a4f56d5476a0b9b0a97397f7a7bbe00b9b2f (patch) | |
tree | 8f6fe1b5e68ecc0684a88fb67bd6179cf6c59707 /drivers/s390/cio | |
parent | 4e8e56c6713398f417317d449f50c08bf2756c66 (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/cio')
-rw-r--r-- | drivers/s390/cio/chsc.c | 5 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 24 | ||||
-rw-r--r-- | drivers/s390/cio/cio.h | 4 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 18 | ||||
-rw-r--r-- | drivers/s390/cio/css.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 9 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 2 |
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 | */ |
409 | int | 409 | int cio_enable_subchannel(struct subchannel *sch, unsigned int isc, |
410 | cio_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 | ||
87 | extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); | 87 | extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); |
88 | extern int cio_enable_subchannel (struct subchannel *, unsigned int); | 88 | extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32); |
89 | extern int cio_disable_subchannel (struct subchannel *); | 89 | extern int cio_disable_subchannel (struct subchannel *); |
90 | extern int cio_cancel (struct subchannel *); | 90 | extern int cio_cancel (struct subchannel *); |
91 | extern int cio_clear (struct subchannel *); | 91 | extern 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 | */ | ||
244 | int 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 | } | ||
250 | EXPORT_SYMBOL_GPL(css_sch_is_valid); | ||
251 | |||
240 | static int css_get_subchannel_status(struct subchannel *sch) | 252 | static 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); | |||
136 | void css_schedule_eval_all(void); | 136 | void css_schedule_eval_all(void); |
137 | 137 | ||
138 | int sch_is_pseudo_sch(struct subchannel *); | 138 | int sch_is_pseudo_sch(struct subchannel *); |
139 | struct schib; | ||
140 | int css_sch_is_valid(struct schib *); | ||
139 | 141 | ||
140 | extern struct workqueue_struct *slow_path_wq; | 142 | extern 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 | /* |