Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/css: reduce stsch calls

Both css_evaluate_new_subchannel and cio_validate_subchannel used
stsch and css_sch_is_valid to check for a valid device.

Reduce stsch calls during subchannel evaluation by re-using schib
data. Also the type/devno valid information is only checked once.

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>

authored by

Sebastian Ott and committed by
Martin Schwidefsky
d4f5d79e 05b217f4

+57 -79
+6 -59
drivers/s390/cio/cio.c
··· 526 526 } 527 527 EXPORT_SYMBOL_GPL(cio_disable_subchannel); 528 528 529 - /** 530 - * cio_validate_subchannel - basic validation of subchannel 531 - * @schid: subchannel id 532 - * @schib: subchannel information block to be filled out 533 - * 534 - * Check if subchannel is valid and should be used. 535 - * Return codes: 536 - * 0 on success 537 - * -ENXIO for non-defined subchannels 538 - * -ENODEV for invalid subchannels or blacklisted devices 539 - * -EIO for subchannels in an invalid subchannel set 540 - */ 541 - int cio_validate_subchannel(struct subchannel_id schid, struct schib *schib) 542 - { 543 - char dbf_txt[15]; 544 - int ccode; 545 - int err; 546 - 547 - sprintf(dbf_txt, "valsch%x", schid.sch_no); 548 - CIO_TRACE_EVENT(4, dbf_txt); 549 - 550 - /* 551 - * The first subchannel that is not-operational (ccode==3) 552 - * indicates that there aren't any more devices available. 553 - * If stsch gets an exception, it means the current subchannel set 554 - * is not valid. 555 - */ 556 - ccode = stsch(schid, schib); 557 - if (ccode) { 558 - err = (ccode == 3) ? -ENXIO : ccode; 559 - goto out; 560 - } 561 - 562 - switch (schib->pmcw.st) { 563 - case SUBCHANNEL_TYPE_IO: 564 - case SUBCHANNEL_TYPE_MSG: 565 - if (!css_sch_is_valid(schib)) 566 - err = -ENODEV; 567 - else if (is_blacklisted(schid.ssid, schib->pmcw.dev)) { 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; 574 - break; 575 - default: 576 - err = 0; 577 - } 578 - if (err) 579 - goto out; 580 - 581 - CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n", 582 - schid.ssid, schid.sch_no, schib->pmcw.st); 583 - out: 584 - return err; 585 - } 586 - 587 529 /* 588 530 * do_cio_interrupt() handles all normal I/O device IRQ's 589 531 */ ··· 649 707 { 650 708 struct subchannel_id schid; 651 709 struct subchannel *sch; 710 + struct schib schib; 652 711 int sch_no, ret; 653 712 654 713 sch_no = cio_get_console_sch_no(); ··· 659 716 } 660 717 init_subchannel_id(&schid); 661 718 schid.sch_no = sch_no; 662 - sch = css_alloc_subchannel(schid); 719 + ret = stsch(schid, &schib); 720 + if (ret) 721 + return ERR_PTR(-ENODEV); 722 + 723 + sch = css_alloc_subchannel(schid, &schib); 663 724 if (IS_ERR(sch)) 664 725 return sch; 665 726
-1
drivers/s390/cio/cio.h
··· 119 119 120 120 #define to_subchannel(n) container_of(n, struct subchannel, dev) 121 121 122 - extern int cio_validate_subchannel(struct subchannel_id, struct schib *); 123 122 extern int cio_enable_subchannel(struct subchannel *, u32); 124 123 extern int cio_disable_subchannel (struct subchannel *); 125 124 extern int cio_cancel (struct subchannel *);
+49 -18
drivers/s390/cio/css.c
··· 25 25 26 26 #include "css.h" 27 27 #include "cio.h" 28 + #include "blacklist.h" 28 29 #include "cio_debug.h" 29 30 #include "ioasm.h" 30 31 #include "chsc.h" ··· 169 168 kfree(sch); 170 169 } 171 170 172 - struct subchannel *css_alloc_subchannel(struct subchannel_id schid) 171 + static int css_validate_subchannel(struct subchannel_id schid, 172 + struct schib *schib) 173 + { 174 + int err; 175 + 176 + switch (schib->pmcw.st) { 177 + case SUBCHANNEL_TYPE_IO: 178 + case SUBCHANNEL_TYPE_MSG: 179 + if (!css_sch_is_valid(schib)) 180 + err = -ENODEV; 181 + else if (is_blacklisted(schid.ssid, schib->pmcw.dev)) { 182 + CIO_MSG_EVENT(6, "Blacklisted device detected " 183 + "at devno %04X, subchannel set %x\n", 184 + schib->pmcw.dev, schid.ssid); 185 + err = -ENODEV; 186 + } else 187 + err = 0; 188 + break; 189 + default: 190 + err = 0; 191 + } 192 + if (err) 193 + goto out; 194 + 195 + CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n", 196 + schid.ssid, schid.sch_no, schib->pmcw.st); 197 + out: 198 + return err; 199 + } 200 + 201 + struct subchannel *css_alloc_subchannel(struct subchannel_id schid, 202 + struct schib *schib) 173 203 { 174 204 struct subchannel *sch; 175 - struct schib schib; 176 205 int ret; 177 206 178 - ret = cio_validate_subchannel(schid, &schib); 207 + ret = css_validate_subchannel(schid, schib); 179 208 if (ret < 0) 180 209 return ERR_PTR(ret); 181 210 ··· 214 183 return ERR_PTR(-ENOMEM); 215 184 216 185 sch->schid = schid; 217 - sch->schib = schib; 218 - sch->st = schib.pmcw.st; 186 + sch->schib = *schib; 187 + sch->st = schib->pmcw.st; 219 188 220 189 ret = css_sch_create_locks(sch); 221 190 if (ret) ··· 417 386 return ret; 418 387 } 419 388 420 - static int css_probe_device(struct subchannel_id schid) 389 + static int css_probe_device(struct subchannel_id schid, struct schib *schib) 421 390 { 422 391 struct subchannel *sch; 423 392 int ret; 424 393 425 - sch = css_alloc_subchannel(schid); 394 + sch = css_alloc_subchannel(schid, schib); 426 395 if (IS_ERR(sch)) 427 396 return PTR_ERR(sch); 428 397 ··· 471 440 static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow) 472 441 { 473 442 struct schib schib; 443 + int ccode; 474 444 475 445 if (!slow) { 476 446 /* Will be done on the slow path. */ 477 447 return -EAGAIN; 478 448 } 479 - if (stsch(schid, &schib)) { 480 - /* Subchannel is not provided. */ 481 - return -ENXIO; 482 - } 483 - if (!css_sch_is_valid(&schib)) { 484 - /* Unusable - ignore. */ 485 - return 0; 486 - } 487 - CIO_MSG_EVENT(4, "event: sch 0.%x.%04x, new\n", schid.ssid, 488 - schid.sch_no); 449 + /* 450 + * The first subchannel that is not-operational (ccode==3) 451 + * indicates that there aren't any more devices available. 452 + * If stsch gets an exception, it means the current subchannel set 453 + * is not valid. 454 + */ 455 + ccode = stsch(schid, &schib); 456 + if (ccode) 457 + return (ccode == 3) ? -ENXIO : ccode; 489 458 490 - return css_probe_device(schid); 459 + return css_probe_device(schid, &schib); 491 460 } 492 461 493 462 static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
+2 -1
drivers/s390/cio/css.h
··· 103 103 104 104 extern void css_sch_device_unregister(struct subchannel *); 105 105 extern int css_register_subchannel(struct subchannel *); 106 - extern struct subchannel *css_alloc_subchannel(struct subchannel_id); 106 + extern struct subchannel *css_alloc_subchannel(struct subchannel_id, 107 + struct schib *schib); 107 108 extern struct subchannel *get_subchannel_by_schid(struct subchannel_id); 108 109 extern int css_init_done; 109 110 extern int max_ssid;