| @@ -2,7 +2,7 @@ · 1 unmodified line |
| 2 | 2 | * drivers/s390/cio/cio.c |
| 3 | 3 | * S/390 common I/O routines -- low level i/o calls |
| 4 | 4 | * |
| 5 | | − * Copyright (C) IBM Corp. 1999,2006 |
| 5 | + * Copyright IBM Corp. 1999,2008 |
| 6 | 6 | * Author(s): Ingo Adlung (adlung@de.ibm.com) |
| 7 | 7 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
| 8 | 8 | * Arnd Bergmann (arndb@de.ibm.com) |
| @@ -494,27 +494,46 @@ int cio_create_sch_lock(struct subchannel *sch) · 485 unmodified lines |
| 494 | 494 | return 0; |
| 495 | 495 | } |
| 496 | 496 | |
| 497 | | −/* |
| 498 | | − * cio_validate_subchannel() |
| 497 | +static int cio_validate_io_subchannel(struct subchannel *sch) |
| 498 | +{ |
| 499 | + /* Initialization for io subchannels. */ |
| 500 | + if (!css_sch_is_valid(&sch->schib)) |
| 501 | + return -ENODEV; |
| 502 | + |
| 503 | + /* Devno is valid. */ |
| 504 | + if (is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev)) { |
| 505 | + /* |
| 506 | + * This device must not be known to Linux. So we simply |
| 507 | + * say that there is no device and return ENODEV. |
| 508 | + */ |
| 509 | + CIO_MSG_EVENT(6, "Blacklisted device detected " |
| 510 | + "at devno %04X, subchannel set %x\n", |
| 511 | + sch->schib.pmcw.dev, sch->schid.ssid); |
| 512 | + return -ENODEV; |
| 513 | + } |
| 514 | + return 0; |
| 515 | +} |
| 516 | + |
| 517 | +/** |
| 518 | + * cio_validate_subchannel - basic validation of subchannel |
| 519 | + * @sch: subchannel structure to be filled out |
| 520 | + * @schid: subchannel id |
| 499 | 521 | * |
| 500 | 522 | * Find out subchannel type and initialize struct subchannel. |
| 501 | 523 | * Return codes: |
| 502 | | − * SUBCHANNEL_TYPE_IO for a normal io subchannel |
| 503 | | − * SUBCHANNEL_TYPE_CHSC for a chsc subchannel |
| 504 | | − * SUBCHANNEL_TYPE_MESSAGE for a messaging subchannel |
| 505 | | − * SUBCHANNEL_TYPE_ADM for a adm(?) subchannel |
| 524 | + * 0 on success |
| 506 | 525 | * -ENXIO for non-defined subchannels |
| 507 | | − * -ENODEV for subchannels with invalid device number or blacklisted devices |
| 526 | + * -ENODEV for invalid subchannels or blacklisted devices |
| 527 | + * -EIO for subchannels in an invalid subchannel set |
| 508 | 528 | */ |
| 509 | | −int |
| 510 | | −cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) |
| 529 | +int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) |
| 511 | 530 | { |
| 512 | 531 | char dbf_txt[15]; |
| 513 | 532 | int ccode; |
| 514 | 533 | int err; |
| 515 | 534 | |
| 516 | | − sprintf (dbf_txt, "valsch%x", schid.sch_no); |
| 517 | | − CIO_TRACE_EVENT (4, dbf_txt); |
| 535 | + sprintf(dbf_txt, "valsch%x", schid.sch_no); |
| 536 | + CIO_TRACE_EVENT(4, dbf_txt); |
| 518 | 537 | |
| 519 | 538 | /* Nuke all fields. */ |
| 520 | 539 | memset(sch, 0, sizeof(struct subchannel)); |
| @@ -545,68 +564,18 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) · 24 unmodified lines |
| 545 | 564 | } |
| 546 | 565 | /* Copy subchannel type from path management control word. */ |
| 547 | 566 | sch->st = sch->schib.pmcw.st; |
| 548 | | − |
| 549 | | − /* |
| 550 | | − * ... just being curious we check for non I/O subchannels |
| 551 | | − */ |
| 552 | | − if (sch->st != 0) { |
| 553 | | − CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports " |
| 554 | | − "non-I/O subchannel type %04X\n", |
| 555 | | − sch->schid.ssid, sch->schid.sch_no, sch->st); |
| 556 | | − /* We stop here for non-io subchannels. */ |
| 557 | | − err = sch->st; |
| 558 | | − goto out; |
| 567 | + switch (sch->st) { |
| 568 | + case SUBCHANNEL_TYPE_IO: |
| 569 | + err = cio_validate_io_subchannel(sch); |
| 570 | + break; |
| 571 | + default: |
| 572 | + err = 0; |
| 559 | 573 | } |
| 560 | | − |
| 561 | | − /* Initialization for io subchannels. */ |
| 562 | | − if (!css_sch_is_valid(&sch->schib)) { |
| 563 | | − err = -ENODEV; |
| 574 | + if (err) |
| 564 | 575 | goto out; |
| 565 | | − } |
| 566 | 576 | |
| 567 | | − /* Devno is valid. */ |
| 568 | | − if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) { |
| 569 | | − /* |
| 570 | | − * This device must not be known to Linux. So we simply |
| 571 | | − * say that there is no device and return ENODEV. |
| 572 | | − */ |
| 573 | | − CIO_MSG_EVENT(6, "Blacklisted device detected " |
| 574 | | − "at devno %04X, subchannel set %x\n", |
| 575 | | − sch->schib.pmcw.dev, sch->schid.ssid); |
| 576 | | − err = -ENODEV; |
| 577 | | − goto out; |
| 578 | | − } |
| 579 | | − if (cio_is_console(sch->schid)) { |
| 580 | | − sch->opm = 0xff; |
| 581 | | − sch->isc = 1; |
| 582 | | − } else { |
| 583 | | − sch->opm = chp_get_sch_opm(sch); |
| 584 | | − sch->isc = 3; |
| 585 | | − } |
| 586 | | − sch->lpm = sch->schib.pmcw.pam & sch->opm; |
| 587 | | − |
| 588 | | − CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X " |
| 589 | | − "- PIM = %02X, PAM = %02X, POM = %02X\n", |
| 590 | | − sch->schib.pmcw.dev, sch->schid.ssid, |
| 591 | | − sch->schid.sch_no, sch->schib.pmcw.pim, |
| 592 | | − sch->schib.pmcw.pam, sch->schib.pmcw.pom); |
| 593 | | − |
| 594 | | − /* |
| 595 | | − * We now have to initially ... |
| 596 | | − * ... enable "concurrent sense" |
| 597 | | − * ... enable "multipath mode" if more than one |
| 598 | | − * CHPID is available. This is done regardless |
| 599 | | − * whether multiple paths are available for us. |
| 600 | | − */ |
| 601 | | − sch->schib.pmcw.csense = 1; /* concurrent sense */ |
| 602 | | − sch->schib.pmcw.ena = 0; |
| 603 | | − if ((sch->lpm & (sch->lpm - 1)) != 0) |
| 604 | | − sch->schib.pmcw.mp = 1; /* multipath mode */ |
| 605 | | − /* clean up possible residual cmf stuff */ |
| 606 | | − sch->schib.pmcw.mme = 0; |
| 607 | | − sch->schib.pmcw.mbfc = 0; |
| 608 | | − sch->schib.pmcw.mbi = 0; |
| 609 | | − sch->schib.mba = 0; |
| 577 | + CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n", |
| 578 | + sch->schid.ssid, sch->schid.sch_no, sch->st); |
| 610 | 579 | return 0; |
| 611 | 580 | out: |
| 612 | 581 | if (!cio_is_console(schid)) |
| @@ -793,7 +762,6 @@ cio_probe_console(void) · 180 unmodified lines |
| 793 | 762 | * enable console I/O-interrupt subclass 1 |
| 794 | 763 | */ |
| 795 | 764 | ctl_set_bit(6, 30); |
| 796 | | − console_subchannel.isc = 1; |
| 797 | 765 | console_subchannel.schib.pmcw.isc = 1; |
| 798 | 766 | console_subchannel.schib.pmcw.intparm = |
| 799 | 767 | (u32)(addr_t)&console_subchannel; |
| @@ -864,7 +832,7 @@ static void udelay_reset(unsigned long usecs) · 64 unmodified lines |
| 864 | 832 | } |
| 865 | 833 | |
| 866 | 834 | static int |
| 867 | | −__clear_subchannel_easy(struct subchannel_id schid) |
| 835 | +__clear_io_subchannel_easy(struct subchannel_id schid) |
| 868 | 836 | { |
| 869 | 837 | int retry; |
| 870 | 838 | |
| @@ -921,11 +889,19 @@ static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) · 50 unmodified lines |
| 921 | 889 | case -ENODEV: |
| 922 | 890 | break; |
| 923 | 891 | default: /* -EBUSY */ |
| 924 | | − if (__clear_subchannel_easy(schid)) |
| 925 | | − break; /* give up... */ |
| 892 | + switch (schib.pmcw.st) { |
| 893 | + case SUBCHANNEL_TYPE_IO: |
| 894 | + if (__clear_io_subchannel_easy(schid)) |
| 895 | + goto out; /* give up... */ |
| 896 | + break; |
| 897 | + default: |
| 898 | + /* No default clear strategy */ |
| 899 | + break; |
| 900 | + } |
| 926 | 901 | stsch(schid, &schib); |
| 927 | 902 | __disable_subchannel_easy(schid, &schib); |
| 928 | 903 | } |
| 904 | +out: |
| 929 | 905 | return 0; |
| 930 | 906 | } |
| 931 | 907 | |