summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.ibm.com>2018-06-25 05:23:26 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2018-07-17 01:27:54 -0400
commit05b217f4c5573f34f6799698f7d4162c702132bc (patch)
tree5678caf88c1ae544b4f3f81f4cdc8332d0ba19b5
parent71aa11a40d1a1d80196b55d8dd95be2bc4c1649e (diff)
s390/css: validate subchannel prior to allocation
In css_alloc_subchannel we allocate the subchannel and do a validation of the subchannel (to decide if we should look for devices via this subchannel). On a typical LPAR we find lots of subchannels to be invalid (because there is no device attached or the device is blacklisted) leading to lots of useless kmalloc and kfree calls. This patch changes the order to only allocate the subchannels that have been found valid. Signed-off-by: Sebastian Ott <sebott@linux.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-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)