summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/cio/cio.c40
-rw-r--r--drivers/s390/cio/cio.h2
-rw-r--r--drivers/s390/cio/css.c11
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}
527EXPORT_SYMBOL_GPL(cio_disable_subchannel); 527EXPORT_SYMBOL_GPL(cio_disable_subchannel);
528 528
529static 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 */
556int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) 541int 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);
595out: 583out:
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
122extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); 122extern int cio_validate_subchannel(struct subchannel_id, struct schib *);
123extern int cio_enable_subchannel(struct subchannel *, u32); 123extern int cio_enable_subchannel(struct subchannel *, u32);
124extern int cio_disable_subchannel (struct subchannel *); 124extern int cio_disable_subchannel (struct subchannel *);
125extern int cio_cancel (struct subchannel *); 125extern 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)
171struct subchannel *css_alloc_subchannel(struct subchannel_id schid) 171struct 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)