diff options
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r-- | drivers/s390/cio/cio.c | 56 |
1 files changed, 28 insertions, 28 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 326f4cc7f92c..3db2c386546f 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -114,6 +114,7 @@ cio_tpi(void) | |||
114 | struct tpi_info *tpi_info; | 114 | struct tpi_info *tpi_info; |
115 | struct subchannel *sch; | 115 | struct subchannel *sch; |
116 | struct irb *irb; | 116 | struct irb *irb; |
117 | int irq_context; | ||
117 | 118 | ||
118 | tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID; | 119 | tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID; |
119 | if (tpi (NULL) != 1) | 120 | if (tpi (NULL) != 1) |
@@ -126,7 +127,9 @@ cio_tpi(void) | |||
126 | sch = (struct subchannel *)(unsigned long)tpi_info->intparm; | 127 | sch = (struct subchannel *)(unsigned long)tpi_info->intparm; |
127 | if (!sch) | 128 | if (!sch) |
128 | return 1; | 129 | return 1; |
129 | local_bh_disable(); | 130 | irq_context = in_interrupt(); |
131 | if (!irq_context) | ||
132 | local_bh_disable(); | ||
130 | irq_enter (); | 133 | irq_enter (); |
131 | spin_lock(sch->lock); | 134 | spin_lock(sch->lock); |
132 | memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); | 135 | memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); |
@@ -134,7 +137,8 @@ cio_tpi(void) | |||
134 | sch->driver->irq(sch); | 137 | sch->driver->irq(sch); |
135 | spin_unlock(sch->lock); | 138 | spin_unlock(sch->lock); |
136 | irq_exit (); | 139 | irq_exit (); |
137 | _local_bh_enable(); | 140 | if (!irq_context) |
141 | _local_bh_enable(); | ||
138 | return 1; | 142 | return 1; |
139 | } | 143 | } |
140 | 144 | ||
@@ -153,7 +157,7 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) | |||
153 | CIO_MSG_EVENT(2, "cio_start: 'not oper' status for " | 157 | CIO_MSG_EVENT(2, "cio_start: 'not oper' status for " |
154 | "subchannel 0.%x.%04x!\n", sch->schid.ssid, | 158 | "subchannel 0.%x.%04x!\n", sch->schid.ssid, |
155 | sch->schid.sch_no); | 159 | sch->schid.sch_no); |
156 | sprintf(dbf_text, "no%s", sch->dev.bus_id); | 160 | sprintf(dbf_text, "no%s", dev_name(&sch->dev)); |
157 | CIO_TRACE_EVENT(0, dbf_text); | 161 | CIO_TRACE_EVENT(0, dbf_text); |
158 | CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); | 162 | CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); |
159 | 163 | ||
@@ -171,7 +175,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ | |||
171 | union orb *orb; | 175 | union orb *orb; |
172 | 176 | ||
173 | CIO_TRACE_EVENT(4, "stIO"); | 177 | CIO_TRACE_EVENT(4, "stIO"); |
174 | CIO_TRACE_EVENT(4, sch->dev.bus_id); | 178 | CIO_TRACE_EVENT(4, dev_name(&sch->dev)); |
175 | 179 | ||
176 | orb = &to_io_private(sch)->orb; | 180 | orb = &to_io_private(sch)->orb; |
177 | memset(orb, 0, sizeof(union orb)); | 181 | memset(orb, 0, sizeof(union orb)); |
@@ -232,7 +236,7 @@ cio_resume (struct subchannel *sch) | |||
232 | int ccode; | 236 | int ccode; |
233 | 237 | ||
234 | CIO_TRACE_EVENT (4, "resIO"); | 238 | CIO_TRACE_EVENT (4, "resIO"); |
235 | CIO_TRACE_EVENT (4, sch->dev.bus_id); | 239 | CIO_TRACE_EVENT(4, dev_name(&sch->dev)); |
236 | 240 | ||
237 | ccode = rsch (sch->schid); | 241 | ccode = rsch (sch->schid); |
238 | 242 | ||
@@ -269,7 +273,7 @@ cio_halt(struct subchannel *sch) | |||
269 | return -ENODEV; | 273 | return -ENODEV; |
270 | 274 | ||
271 | CIO_TRACE_EVENT (2, "haltIO"); | 275 | CIO_TRACE_EVENT (2, "haltIO"); |
272 | CIO_TRACE_EVENT (2, sch->dev.bus_id); | 276 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
273 | 277 | ||
274 | /* | 278 | /* |
275 | * Issue "Halt subchannel" and process condition code | 279 | * Issue "Halt subchannel" and process condition code |
@@ -304,7 +308,7 @@ cio_clear(struct subchannel *sch) | |||
304 | return -ENODEV; | 308 | return -ENODEV; |
305 | 309 | ||
306 | CIO_TRACE_EVENT (2, "clearIO"); | 310 | CIO_TRACE_EVENT (2, "clearIO"); |
307 | CIO_TRACE_EVENT (2, sch->dev.bus_id); | 311 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
308 | 312 | ||
309 | /* | 313 | /* |
310 | * Issue "Clear subchannel" and process condition code | 314 | * Issue "Clear subchannel" and process condition code |
@@ -340,7 +344,7 @@ cio_cancel (struct subchannel *sch) | |||
340 | return -ENODEV; | 344 | return -ENODEV; |
341 | 345 | ||
342 | CIO_TRACE_EVENT (2, "cancelIO"); | 346 | CIO_TRACE_EVENT (2, "cancelIO"); |
343 | CIO_TRACE_EVENT (2, sch->dev.bus_id); | 347 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
344 | 348 | ||
345 | ccode = xsch (sch->schid); | 349 | ccode = xsch (sch->schid); |
346 | 350 | ||
@@ -404,7 +408,7 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm) | |||
404 | int ret; | 408 | int ret; |
405 | 409 | ||
406 | CIO_TRACE_EVENT (2, "ensch"); | 410 | CIO_TRACE_EVENT (2, "ensch"); |
407 | CIO_TRACE_EVENT (2, sch->dev.bus_id); | 411 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
408 | 412 | ||
409 | if (sch_is_pseudo_sch(sch)) | 413 | if (sch_is_pseudo_sch(sch)) |
410 | return -EINVAL; | 414 | return -EINVAL; |
@@ -454,7 +458,7 @@ int cio_disable_subchannel(struct subchannel *sch) | |||
454 | int ret; | 458 | int ret; |
455 | 459 | ||
456 | CIO_TRACE_EVENT (2, "dissch"); | 460 | CIO_TRACE_EVENT (2, "dissch"); |
457 | CIO_TRACE_EVENT (2, sch->dev.bus_id); | 461 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
458 | 462 | ||
459 | if (sch_is_pseudo_sch(sch)) | 463 | if (sch_is_pseudo_sch(sch)) |
460 | return 0; | 464 | return 0; |
@@ -571,8 +575,10 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) | |||
571 | } | 575 | } |
572 | mutex_init(&sch->reg_mutex); | 576 | mutex_init(&sch->reg_mutex); |
573 | /* Set a name for the subchannel */ | 577 | /* Set a name for the subchannel */ |
574 | snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid, | 578 | if (cio_is_console(schid)) |
575 | schid.sch_no); | 579 | sch->dev.init_name = cio_get_console_sch_name(schid); |
580 | else | ||
581 | dev_set_name(&sch->dev, "0.%x.%04x", schid.ssid, schid.sch_no); | ||
576 | 582 | ||
577 | /* | 583 | /* |
578 | * The first subchannel that is not-operational (ccode==3) | 584 | * The first subchannel that is not-operational (ccode==3) |
@@ -677,6 +683,7 @@ do_IRQ (struct pt_regs *regs) | |||
677 | 683 | ||
678 | #ifdef CONFIG_CCW_CONSOLE | 684 | #ifdef CONFIG_CCW_CONSOLE |
679 | static struct subchannel console_subchannel; | 685 | static struct subchannel console_subchannel; |
686 | static char console_sch_name[10] = "0.x.xxxx"; | ||
680 | static struct io_subchannel_private console_priv; | 687 | static struct io_subchannel_private console_priv; |
681 | static int console_subchannel_in_use; | 688 | static int console_subchannel_in_use; |
682 | 689 | ||
@@ -827,6 +834,12 @@ cio_get_console_subchannel(void) | |||
827 | return &console_subchannel; | 834 | return &console_subchannel; |
828 | } | 835 | } |
829 | 836 | ||
837 | const char *cio_get_console_sch_name(struct subchannel_id schid) | ||
838 | { | ||
839 | snprintf(console_sch_name, 10, "0.%x.%04x", schid.ssid, schid.sch_no); | ||
840 | return (const char *)console_sch_name; | ||
841 | } | ||
842 | |||
830 | #endif | 843 | #endif |
831 | static int | 844 | static int |
832 | __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) | 845 | __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) |
@@ -846,19 +859,6 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) | |||
846 | return -EBUSY; /* uhm... */ | 859 | return -EBUSY; /* uhm... */ |
847 | } | 860 | } |
848 | 861 | ||
849 | /* we can't use the normal udelay here, since it enables external interrupts */ | ||
850 | |||
851 | static void udelay_reset(unsigned long usecs) | ||
852 | { | ||
853 | uint64_t start_cc, end_cc; | ||
854 | |||
855 | asm volatile ("STCK %0" : "=m" (start_cc)); | ||
856 | do { | ||
857 | cpu_relax(); | ||
858 | asm volatile ("STCK %0" : "=m" (end_cc)); | ||
859 | } while (((end_cc - start_cc)/4096) < usecs); | ||
860 | } | ||
861 | |||
862 | static int | 862 | static int |
863 | __clear_io_subchannel_easy(struct subchannel_id schid) | 863 | __clear_io_subchannel_easy(struct subchannel_id schid) |
864 | { | 864 | { |
@@ -874,7 +874,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid) | |||
874 | if (schid_equal(&ti.schid, &schid)) | 874 | if (schid_equal(&ti.schid, &schid)) |
875 | return 0; | 875 | return 0; |
876 | } | 876 | } |
877 | udelay_reset(100); | 877 | udelay_simple(100); |
878 | } | 878 | } |
879 | return -EBUSY; | 879 | return -EBUSY; |
880 | } | 880 | } |
@@ -882,7 +882,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid) | |||
882 | static void __clear_chsc_subchannel_easy(void) | 882 | static void __clear_chsc_subchannel_easy(void) |
883 | { | 883 | { |
884 | /* It seems we can only wait for a bit here :/ */ | 884 | /* It seems we can only wait for a bit here :/ */ |
885 | udelay_reset(100); | 885 | udelay_simple(100); |
886 | } | 886 | } |
887 | 887 | ||
888 | static int pgm_check_occured; | 888 | static int pgm_check_occured; |
@@ -892,7 +892,7 @@ static void cio_reset_pgm_check_handler(void) | |||
892 | pgm_check_occured = 1; | 892 | pgm_check_occured = 1; |
893 | } | 893 | } |
894 | 894 | ||
895 | static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr) | 895 | static int stsch_reset(struct subchannel_id schid, struct schib *addr) |
896 | { | 896 | { |
897 | int rc; | 897 | int rc; |
898 | 898 | ||