diff options
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r-- | drivers/s390/cio/cio.c | 106 |
1 files changed, 58 insertions, 48 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 46905345159e..60590a12d529 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -23,11 +23,12 @@ | |||
23 | #include <asm/reset.h> | 23 | #include <asm/reset.h> |
24 | #include <asm/ipl.h> | 24 | #include <asm/ipl.h> |
25 | #include <asm/chpid.h> | 25 | #include <asm/chpid.h> |
26 | #include "airq.h" | 26 | #include <asm/airq.h> |
27 | #include "cio.h" | 27 | #include "cio.h" |
28 | #include "css.h" | 28 | #include "css.h" |
29 | #include "chsc.h" | 29 | #include "chsc.h" |
30 | #include "ioasm.h" | 30 | #include "ioasm.h" |
31 | #include "io_sch.h" | ||
31 | #include "blacklist.h" | 32 | #include "blacklist.h" |
32 | #include "cio_debug.h" | 33 | #include "cio_debug.h" |
33 | #include "chp.h" | 34 | #include "chp.h" |
@@ -56,39 +57,37 @@ __setup ("cio_msg=", cio_setup); | |||
56 | 57 | ||
57 | /* | 58 | /* |
58 | * Function: cio_debug_init | 59 | * Function: cio_debug_init |
59 | * Initializes three debug logs (under /proc/s390dbf) for common I/O: | 60 | * Initializes three debug logs for common I/O: |
60 | * - cio_msg logs the messages which are printk'ed when CONFIG_DEBUG_IO is on | 61 | * - cio_msg logs generic cio messages |
61 | * - cio_trace logs the calling of different functions | 62 | * - cio_trace logs the calling of different functions |
62 | * - cio_crw logs the messages which are printk'ed when CONFIG_DEBUG_CRW is on | 63 | * - cio_crw logs machine check related cio messages |
63 | * debug levels depend on CONFIG_DEBUG_IO resp. CONFIG_DEBUG_CRW | ||
64 | */ | 64 | */ |
65 | static int __init | 65 | static int __init cio_debug_init(void) |
66 | cio_debug_init (void) | ||
67 | { | 66 | { |
68 | cio_debug_msg_id = debug_register ("cio_msg", 16, 4, 16*sizeof (long)); | 67 | cio_debug_msg_id = debug_register("cio_msg", 16, 1, 16 * sizeof(long)); |
69 | if (!cio_debug_msg_id) | 68 | if (!cio_debug_msg_id) |
70 | goto out_unregister; | 69 | goto out_unregister; |
71 | debug_register_view (cio_debug_msg_id, &debug_sprintf_view); | 70 | debug_register_view(cio_debug_msg_id, &debug_sprintf_view); |
72 | debug_set_level (cio_debug_msg_id, 2); | 71 | debug_set_level(cio_debug_msg_id, 2); |
73 | cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 16); | 72 | cio_debug_trace_id = debug_register("cio_trace", 16, 1, 16); |
74 | if (!cio_debug_trace_id) | 73 | if (!cio_debug_trace_id) |
75 | goto out_unregister; | 74 | goto out_unregister; |
76 | debug_register_view (cio_debug_trace_id, &debug_hex_ascii_view); | 75 | debug_register_view(cio_debug_trace_id, &debug_hex_ascii_view); |
77 | debug_set_level (cio_debug_trace_id, 2); | 76 | debug_set_level(cio_debug_trace_id, 2); |
78 | cio_debug_crw_id = debug_register ("cio_crw", 4, 4, 16*sizeof (long)); | 77 | cio_debug_crw_id = debug_register("cio_crw", 16, 1, 16 * sizeof(long)); |
79 | if (!cio_debug_crw_id) | 78 | if (!cio_debug_crw_id) |
80 | goto out_unregister; | 79 | goto out_unregister; |
81 | debug_register_view (cio_debug_crw_id, &debug_sprintf_view); | 80 | debug_register_view(cio_debug_crw_id, &debug_sprintf_view); |
82 | debug_set_level (cio_debug_crw_id, 2); | 81 | debug_set_level(cio_debug_crw_id, 4); |
83 | return 0; | 82 | return 0; |
84 | 83 | ||
85 | out_unregister: | 84 | out_unregister: |
86 | if (cio_debug_msg_id) | 85 | if (cio_debug_msg_id) |
87 | debug_unregister (cio_debug_msg_id); | 86 | debug_unregister(cio_debug_msg_id); |
88 | if (cio_debug_trace_id) | 87 | if (cio_debug_trace_id) |
89 | debug_unregister (cio_debug_trace_id); | 88 | debug_unregister(cio_debug_trace_id); |
90 | if (cio_debug_crw_id) | 89 | if (cio_debug_crw_id) |
91 | debug_unregister (cio_debug_crw_id); | 90 | debug_unregister(cio_debug_crw_id); |
92 | printk(KERN_WARNING"cio: could not initialize debugging\n"); | 91 | printk(KERN_WARNING"cio: could not initialize debugging\n"); |
93 | return -1; | 92 | return -1; |
94 | } | 93 | } |
@@ -147,7 +146,7 @@ cio_tpi(void) | |||
147 | spin_lock(sch->lock); | 146 | spin_lock(sch->lock); |
148 | memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw)); | 147 | memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw)); |
149 | if (sch->driver && sch->driver->irq) | 148 | if (sch->driver && sch->driver->irq) |
150 | sch->driver->irq(&sch->dev); | 149 | sch->driver->irq(sch); |
151 | spin_unlock(sch->lock); | 150 | spin_unlock(sch->lock); |
152 | irq_exit (); | 151 | irq_exit (); |
153 | _local_bh_enable(); | 152 | _local_bh_enable(); |
@@ -184,33 +183,35 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ | |||
184 | { | 183 | { |
185 | char dbf_txt[15]; | 184 | char dbf_txt[15]; |
186 | int ccode; | 185 | int ccode; |
186 | struct orb *orb; | ||
187 | 187 | ||
188 | CIO_TRACE_EVENT (4, "stIO"); | 188 | CIO_TRACE_EVENT(4, "stIO"); |
189 | CIO_TRACE_EVENT (4, sch->dev.bus_id); | 189 | CIO_TRACE_EVENT(4, sch->dev.bus_id); |
190 | 190 | ||
191 | orb = &to_io_private(sch)->orb; | ||
191 | /* sch is always under 2G. */ | 192 | /* sch is always under 2G. */ |
192 | sch->orb.intparm = (__u32)(unsigned long)sch; | 193 | orb->intparm = (u32)(addr_t)sch; |
193 | sch->orb.fmt = 1; | 194 | orb->fmt = 1; |
194 | 195 | ||
195 | sch->orb.pfch = sch->options.prefetch == 0; | 196 | orb->pfch = sch->options.prefetch == 0; |
196 | sch->orb.spnd = sch->options.suspend; | 197 | orb->spnd = sch->options.suspend; |
197 | sch->orb.ssic = sch->options.suspend && sch->options.inter; | 198 | orb->ssic = sch->options.suspend && sch->options.inter; |
198 | sch->orb.lpm = (lpm != 0) ? lpm : sch->lpm; | 199 | orb->lpm = (lpm != 0) ? lpm : sch->lpm; |
199 | #ifdef CONFIG_64BIT | 200 | #ifdef CONFIG_64BIT |
200 | /* | 201 | /* |
201 | * for 64 bit we always support 64 bit IDAWs with 4k page size only | 202 | * for 64 bit we always support 64 bit IDAWs with 4k page size only |
202 | */ | 203 | */ |
203 | sch->orb.c64 = 1; | 204 | orb->c64 = 1; |
204 | sch->orb.i2k = 0; | 205 | orb->i2k = 0; |
205 | #endif | 206 | #endif |
206 | sch->orb.key = key >> 4; | 207 | orb->key = key >> 4; |
207 | /* issue "Start Subchannel" */ | 208 | /* issue "Start Subchannel" */ |
208 | sch->orb.cpa = (__u32) __pa (cpa); | 209 | orb->cpa = (__u32) __pa(cpa); |
209 | ccode = ssch (sch->schid, &sch->orb); | 210 | ccode = ssch(sch->schid, orb); |
210 | 211 | ||
211 | /* process condition code */ | 212 | /* process condition code */ |
212 | sprintf (dbf_txt, "ccode:%d", ccode); | 213 | sprintf(dbf_txt, "ccode:%d", ccode); |
213 | CIO_TRACE_EVENT (4, dbf_txt); | 214 | CIO_TRACE_EVENT(4, dbf_txt); |
214 | 215 | ||
215 | switch (ccode) { | 216 | switch (ccode) { |
216 | case 0: | 217 | case 0: |
@@ -405,8 +406,8 @@ cio_modify (struct subchannel *sch) | |||
405 | /* | 406 | /* |
406 | * Enable subchannel. | 407 | * Enable subchannel. |
407 | */ | 408 | */ |
408 | int | 409 | int cio_enable_subchannel(struct subchannel *sch, unsigned int isc, |
409 | cio_enable_subchannel (struct subchannel *sch, unsigned int isc) | 410 | u32 intparm) |
410 | { | 411 | { |
411 | char dbf_txt[15]; | 412 | char dbf_txt[15]; |
412 | int ccode; | 413 | int ccode; |
@@ -425,7 +426,7 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc) | |||
425 | for (retry = 5, ret = 0; retry > 0; retry--) { | 426 | for (retry = 5, ret = 0; retry > 0; retry--) { |
426 | sch->schib.pmcw.ena = 1; | 427 | sch->schib.pmcw.ena = 1; |
427 | sch->schib.pmcw.isc = isc; | 428 | sch->schib.pmcw.isc = isc; |
428 | sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; | 429 | sch->schib.pmcw.intparm = intparm; |
429 | ret = cio_modify(sch); | 430 | ret = cio_modify(sch); |
430 | if (ret == -ENODEV) | 431 | if (ret == -ENODEV) |
431 | break; | 432 | break; |
@@ -567,7 +568,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
567 | */ | 568 | */ |
568 | if (sch->st != 0) { | 569 | if (sch->st != 0) { |
569 | CIO_DEBUG(KERN_INFO, 0, | 570 | CIO_DEBUG(KERN_INFO, 0, |
570 | "cio: Subchannel 0.%x.%04x reports " | 571 | "Subchannel 0.%x.%04x reports " |
571 | "non-I/O subchannel type %04X\n", | 572 | "non-I/O subchannel type %04X\n", |
572 | sch->schid.ssid, sch->schid.sch_no, sch->st); | 573 | sch->schid.ssid, sch->schid.sch_no, sch->st); |
573 | /* We stop here for non-io subchannels. */ | 574 | /* We stop here for non-io subchannels. */ |
@@ -576,11 +577,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
576 | } | 577 | } |
577 | 578 | ||
578 | /* Initialization for io subchannels. */ | 579 | /* Initialization for io subchannels. */ |
579 | if (!sch->schib.pmcw.dnv) { | 580 | if (!css_sch_is_valid(&sch->schib)) { |
580 | /* io subchannel but device number is invalid. */ | ||
581 | err = -ENODEV; | 581 | err = -ENODEV; |
582 | goto out; | 582 | goto out; |
583 | } | 583 | } |
584 | |||
584 | /* Devno is valid. */ | 585 | /* Devno is valid. */ |
585 | if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) { | 586 | if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) { |
586 | /* | 587 | /* |
@@ -600,7 +601,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
600 | sch->lpm = sch->schib.pmcw.pam & sch->opm; | 601 | sch->lpm = sch->schib.pmcw.pam & sch->opm; |
601 | 602 | ||
602 | CIO_DEBUG(KERN_INFO, 0, | 603 | CIO_DEBUG(KERN_INFO, 0, |
603 | "cio: Detected device %04x on subchannel 0.%x.%04X" | 604 | "Detected device %04x on subchannel 0.%x.%04X" |
604 | " - PIM = %02X, PAM = %02X, POM = %02X\n", | 605 | " - PIM = %02X, PAM = %02X, POM = %02X\n", |
605 | sch->schib.pmcw.dev, sch->schid.ssid, | 606 | sch->schib.pmcw.dev, sch->schid.ssid, |
606 | sch->schid.sch_no, sch->schib.pmcw.pim, | 607 | sch->schid.sch_no, sch->schib.pmcw.pim, |
@@ -680,7 +681,7 @@ do_IRQ (struct pt_regs *regs) | |||
680 | sizeof (irb->scsw)); | 681 | sizeof (irb->scsw)); |
681 | /* Call interrupt handler if there is one. */ | 682 | /* Call interrupt handler if there is one. */ |
682 | if (sch->driver && sch->driver->irq) | 683 | if (sch->driver && sch->driver->irq) |
683 | sch->driver->irq(&sch->dev); | 684 | sch->driver->irq(sch); |
684 | } | 685 | } |
685 | if (sch) | 686 | if (sch) |
686 | spin_unlock(sch->lock); | 687 | spin_unlock(sch->lock); |
@@ -698,8 +699,14 @@ do_IRQ (struct pt_regs *regs) | |||
698 | 699 | ||
699 | #ifdef CONFIG_CCW_CONSOLE | 700 | #ifdef CONFIG_CCW_CONSOLE |
700 | static struct subchannel console_subchannel; | 701 | static struct subchannel console_subchannel; |
702 | static struct io_subchannel_private console_priv; | ||
701 | static int console_subchannel_in_use; | 703 | static int console_subchannel_in_use; |
702 | 704 | ||
705 | void *cio_get_console_priv(void) | ||
706 | { | ||
707 | return &console_priv; | ||
708 | } | ||
709 | |||
703 | /* | 710 | /* |
704 | * busy wait for the next interrupt on the console | 711 | * busy wait for the next interrupt on the console |
705 | */ | 712 | */ |
@@ -738,9 +745,9 @@ cio_test_for_console(struct subchannel_id schid, void *data) | |||
738 | { | 745 | { |
739 | if (stsch_err(schid, &console_subchannel.schib) != 0) | 746 | if (stsch_err(schid, &console_subchannel.schib) != 0) |
740 | return -ENXIO; | 747 | return -ENXIO; |
741 | if (console_subchannel.schib.pmcw.dnv && | 748 | if ((console_subchannel.schib.pmcw.st == SUBCHANNEL_TYPE_IO) && |
742 | console_subchannel.schib.pmcw.dev == | 749 | console_subchannel.schib.pmcw.dnv && |
743 | console_devno) { | 750 | (console_subchannel.schib.pmcw.dev == console_devno)) { |
744 | console_irq = schid.sch_no; | 751 | console_irq = schid.sch_no; |
745 | return 1; /* found */ | 752 | return 1; /* found */ |
746 | } | 753 | } |
@@ -758,6 +765,7 @@ cio_get_console_sch_no(void) | |||
758 | /* VM provided us with the irq number of the console. */ | 765 | /* VM provided us with the irq number of the console. */ |
759 | schid.sch_no = console_irq; | 766 | schid.sch_no = console_irq; |
760 | if (stsch(schid, &console_subchannel.schib) != 0 || | 767 | if (stsch(schid, &console_subchannel.schib) != 0 || |
768 | (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) || | ||
761 | !console_subchannel.schib.pmcw.dnv) | 769 | !console_subchannel.schib.pmcw.dnv) |
762 | return -1; | 770 | return -1; |
763 | console_devno = console_subchannel.schib.pmcw.dev; | 771 | console_devno = console_subchannel.schib.pmcw.dev; |
@@ -804,7 +812,7 @@ cio_probe_console(void) | |||
804 | ctl_set_bit(6, 24); | 812 | ctl_set_bit(6, 24); |
805 | console_subchannel.schib.pmcw.isc = 7; | 813 | console_subchannel.schib.pmcw.isc = 7; |
806 | console_subchannel.schib.pmcw.intparm = | 814 | console_subchannel.schib.pmcw.intparm = |
807 | (__u32)(unsigned long)&console_subchannel; | 815 | (u32)(addr_t)&console_subchannel; |
808 | ret = cio_modify(&console_subchannel); | 816 | ret = cio_modify(&console_subchannel); |
809 | if (ret) { | 817 | if (ret) { |
810 | console_subchannel_in_use = 0; | 818 | console_subchannel_in_use = 0; |
@@ -1022,7 +1030,7 @@ static int __reipl_subchannel_match(struct subchannel_id schid, void *data) | |||
1022 | 1030 | ||
1023 | if (stsch_reset(schid, &schib)) | 1031 | if (stsch_reset(schid, &schib)) |
1024 | return -ENXIO; | 1032 | return -ENXIO; |
1025 | if (schib.pmcw.dnv && | 1033 | if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv && |
1026 | (schib.pmcw.dev == match_id->devid.devno) && | 1034 | (schib.pmcw.dev == match_id->devid.devno) && |
1027 | (schid.ssid == match_id->devid.ssid)) { | 1035 | (schid.ssid == match_id->devid.ssid)) { |
1028 | match_id->schid = schid; | 1036 | match_id->schid = schid; |
@@ -1068,6 +1076,8 @@ int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo) | |||
1068 | return -ENODEV; | 1076 | return -ENODEV; |
1069 | if (stsch(schid, &schib)) | 1077 | if (stsch(schid, &schib)) |
1070 | return -ENODEV; | 1078 | return -ENODEV; |
1079 | if (schib.pmcw.st != SUBCHANNEL_TYPE_IO) | ||
1080 | return -ENODEV; | ||
1071 | if (!schib.pmcw.dnv) | 1081 | if (!schib.pmcw.dnv) |
1072 | return -ENODEV; | 1082 | return -ENODEV; |
1073 | iplinfo->devno = schib.pmcw.dev; | 1083 | iplinfo->devno = schib.pmcw.dev; |