diff options
-rw-r--r-- | drivers/s390/cio/cio.c | 40 | ||||
-rw-r--r-- | drivers/s390/cio/cio.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 11 |
3 files changed, 23 insertions, 30 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5130d7c67239..4b8f29f83421 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -526,34 +526,19 @@ int cio_disable_subchannel(struct subchannel *sch) | |||
526 | } | 526 | } |
527 | EXPORT_SYMBOL_GPL(cio_disable_subchannel); | 527 | EXPORT_SYMBOL_GPL(cio_disable_subchannel); |
528 | 528 | ||
529 | static int cio_check_devno_blacklisted(struct subchannel *sch) | ||
530 | { | ||
531 | if (is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev)) { | ||
532 | /* | ||
533 | * This device must not be known to Linux. So we simply | ||
534 | * say that there is no device and return ENODEV. | ||
535 | */ | ||
536 | CIO_MSG_EVENT(6, "Blacklisted device detected " | ||
537 | "at devno %04X, subchannel set %x\n", | ||
538 | sch->schib.pmcw.dev, sch->schid.ssid); | ||
539 | return -ENODEV; | ||
540 | } | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | /** | 529 | /** |
545 | * cio_validate_subchannel - basic validation of subchannel | 530 | * cio_validate_subchannel - basic validation of subchannel |
546 | * @sch: subchannel structure to be filled out | ||
547 | * @schid: subchannel id | 531 | * @schid: subchannel id |
532 | * @schib: subchannel information block to be filled out | ||
548 | * | 533 | * |
549 | * Find out subchannel type and initialize struct subchannel. | 534 | * Check if subchannel is valid and should be used. |
550 | * Return codes: | 535 | * Return codes: |
551 | * 0 on success | 536 | * 0 on success |
552 | * -ENXIO for non-defined subchannels | 537 | * -ENXIO for non-defined subchannels |
553 | * -ENODEV for invalid subchannels or blacklisted devices | 538 | * -ENODEV for invalid subchannels or blacklisted devices |
554 | * -EIO for subchannels in an invalid subchannel set | 539 | * -EIO for subchannels in an invalid subchannel set |
555 | */ | 540 | */ |
556 | int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) | 541 | int cio_validate_subchannel(struct subchannel_id schid, struct schib *schib) |
557 | { | 542 | { |
558 | char dbf_txt[15]; | 543 | char dbf_txt[15]; |
559 | int ccode; | 544 | int ccode; |
@@ -568,21 +553,24 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) | |||
568 | * If stsch gets an exception, it means the current subchannel set | 553 | * If stsch gets an exception, it means the current subchannel set |
569 | * is not valid. | 554 | * is not valid. |
570 | */ | 555 | */ |
571 | ccode = stsch(schid, &sch->schib); | 556 | ccode = stsch(schid, schib); |
572 | if (ccode) { | 557 | if (ccode) { |
573 | err = (ccode == 3) ? -ENXIO : ccode; | 558 | err = (ccode == 3) ? -ENXIO : ccode; |
574 | goto out; | 559 | goto out; |
575 | } | 560 | } |
576 | sch->st = sch->schib.pmcw.st; | ||
577 | sch->schid = schid; | ||
578 | 561 | ||
579 | switch (sch->st) { | 562 | switch (schib->pmcw.st) { |
580 | case SUBCHANNEL_TYPE_IO: | 563 | case SUBCHANNEL_TYPE_IO: |
581 | case SUBCHANNEL_TYPE_MSG: | 564 | case SUBCHANNEL_TYPE_MSG: |
582 | if (!css_sch_is_valid(&sch->schib)) | 565 | if (!css_sch_is_valid(schib)) |
583 | err = -ENODEV; | 566 | err = -ENODEV; |
584 | else | 567 | else if (is_blacklisted(schid.ssid, schib->pmcw.dev)) { |
585 | err = cio_check_devno_blacklisted(sch); | 568 | CIO_MSG_EVENT(6, "Blacklisted device detected " |
569 | "at devno %04X, subchannel set %x\n", | ||
570 | schib->pmcw.dev, schid.ssid); | ||
571 | err = -ENODEV; | ||
572 | } else | ||
573 | err = 0; | ||
586 | break; | 574 | break; |
587 | default: | 575 | default: |
588 | err = 0; | 576 | err = 0; |
@@ -591,7 +579,7 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) | |||
591 | goto out; | 579 | goto out; |
592 | 580 | ||
593 | CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n", | 581 | CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n", |
594 | sch->schid.ssid, sch->schid.sch_no, sch->st); | 582 | schid.ssid, schid.sch_no, schib->pmcw.st); |
595 | out: | 583 | out: |
596 | return err; | 584 | return err; |
597 | } | 585 | } |
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index 94cd813bdcfe..234aa068dd8f 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h | |||
@@ -119,7 +119,7 @@ DECLARE_PER_CPU(struct irb, cio_irb); | |||
119 | 119 | ||
120 | #define to_subchannel(n) container_of(n, struct subchannel, dev) | 120 | #define to_subchannel(n) container_of(n, struct subchannel, dev) |
121 | 121 | ||
122 | extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); | 122 | extern int cio_validate_subchannel(struct subchannel_id, struct schib *); |
123 | extern int cio_enable_subchannel(struct subchannel *, u32); | 123 | extern int cio_enable_subchannel(struct subchannel *, u32); |
124 | extern int cio_disable_subchannel (struct subchannel *); | 124 | extern int cio_disable_subchannel (struct subchannel *); |
125 | extern int cio_cancel (struct subchannel *); | 125 | extern int cio_cancel (struct subchannel *); |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index e608e8cad88e..e4d6537cdd87 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -171,15 +171,20 @@ static void css_subchannel_release(struct device *dev) | |||
171 | struct subchannel *css_alloc_subchannel(struct subchannel_id schid) | 171 | struct subchannel *css_alloc_subchannel(struct subchannel_id schid) |
172 | { | 172 | { |
173 | struct subchannel *sch; | 173 | struct subchannel *sch; |
174 | struct schib schib; | ||
174 | int ret; | 175 | int ret; |
175 | 176 | ||
177 | ret = cio_validate_subchannel(schid, &schib); | ||
178 | if (ret < 0) | ||
179 | return ERR_PTR(ret); | ||
180 | |||
176 | sch = kzalloc(sizeof(*sch), GFP_KERNEL | GFP_DMA); | 181 | sch = kzalloc(sizeof(*sch), GFP_KERNEL | GFP_DMA); |
177 | if (!sch) | 182 | if (!sch) |
178 | return ERR_PTR(-ENOMEM); | 183 | return ERR_PTR(-ENOMEM); |
179 | 184 | ||
180 | ret = cio_validate_subchannel(sch, schid); | 185 | sch->schid = schid; |
181 | if (ret < 0) | 186 | sch->schib = schib; |
182 | goto err; | 187 | sch->st = schib.pmcw.st; |
183 | 188 | ||
184 | ret = css_sch_create_locks(sch); | 189 | ret = css_sch_create_locks(sch); |
185 | if (ret) | 190 | if (ret) |