diff options
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r-- | drivers/s390/cio/cio.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index ae1bf231d089..b3a56dc5f68a 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -122,7 +122,7 @@ cio_get_options (struct subchannel *sch) | |||
122 | * Use tpi to get a pending interrupt, call the interrupt handler and | 122 | * Use tpi to get a pending interrupt, call the interrupt handler and |
123 | * return a pointer to the subchannel structure. | 123 | * return a pointer to the subchannel structure. |
124 | */ | 124 | */ |
125 | static inline int | 125 | static int |
126 | cio_tpi(void) | 126 | cio_tpi(void) |
127 | { | 127 | { |
128 | struct tpi_info *tpi_info; | 128 | struct tpi_info *tpi_info; |
@@ -152,7 +152,7 @@ cio_tpi(void) | |||
152 | return 1; | 152 | return 1; |
153 | } | 153 | } |
154 | 154 | ||
155 | static inline int | 155 | static int |
156 | cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) | 156 | cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) |
157 | { | 157 | { |
158 | char dbf_text[15]; | 158 | char dbf_text[15]; |
@@ -585,7 +585,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
585 | * This device must not be known to Linux. So we simply | 585 | * This device must not be known to Linux. So we simply |
586 | * say that there is no device and return ENODEV. | 586 | * say that there is no device and return ENODEV. |
587 | */ | 587 | */ |
588 | CIO_MSG_EVENT(0, "Blacklisted device detected " | 588 | CIO_MSG_EVENT(4, "Blacklisted device detected " |
589 | "at devno %04X, subchannel set %x\n", | 589 | "at devno %04X, subchannel set %x\n", |
590 | sch->schib.pmcw.dev, sch->schid.ssid); | 590 | sch->schib.pmcw.dev, sch->schid.ssid); |
591 | err = -ENODEV; | 591 | err = -ENODEV; |
@@ -646,7 +646,7 @@ do_IRQ (struct pt_regs *regs) | |||
646 | * Make sure that the i/o interrupt did not "overtake" | 646 | * Make sure that the i/o interrupt did not "overtake" |
647 | * the last HZ timer interrupt. | 647 | * the last HZ timer interrupt. |
648 | */ | 648 | */ |
649 | account_ticks(); | 649 | account_ticks(S390_lowcore.int_clock); |
650 | /* | 650 | /* |
651 | * Get interrupt information from lowcore | 651 | * Get interrupt information from lowcore |
652 | */ | 652 | */ |
@@ -832,7 +832,7 @@ cio_get_console_subchannel(void) | |||
832 | } | 832 | } |
833 | 833 | ||
834 | #endif | 834 | #endif |
835 | static inline int | 835 | static int |
836 | __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) | 836 | __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) |
837 | { | 837 | { |
838 | int retry, cc; | 838 | int retry, cc; |
@@ -850,7 +850,20 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) | |||
850 | return -EBUSY; /* uhm... */ | 850 | return -EBUSY; /* uhm... */ |
851 | } | 851 | } |
852 | 852 | ||
853 | static inline int | 853 | /* we can't use the normal udelay here, since it enables external interrupts */ |
854 | |||
855 | static void udelay_reset(unsigned long usecs) | ||
856 | { | ||
857 | uint64_t start_cc, end_cc; | ||
858 | |||
859 | asm volatile ("STCK %0" : "=m" (start_cc)); | ||
860 | do { | ||
861 | cpu_relax(); | ||
862 | asm volatile ("STCK %0" : "=m" (end_cc)); | ||
863 | } while (((end_cc - start_cc)/4096) < usecs); | ||
864 | } | ||
865 | |||
866 | static int | ||
854 | __clear_subchannel_easy(struct subchannel_id schid) | 867 | __clear_subchannel_easy(struct subchannel_id schid) |
855 | { | 868 | { |
856 | int retry; | 869 | int retry; |
@@ -865,7 +878,7 @@ __clear_subchannel_easy(struct subchannel_id schid) | |||
865 | if (schid_equal(&ti.schid, &schid)) | 878 | if (schid_equal(&ti.schid, &schid)) |
866 | return 0; | 879 | return 0; |
867 | } | 880 | } |
868 | udelay(100); | 881 | udelay_reset(100); |
869 | } | 882 | } |
870 | return -EBUSY; | 883 | return -EBUSY; |
871 | } | 884 | } |
@@ -882,11 +895,11 @@ static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr) | |||
882 | int rc; | 895 | int rc; |
883 | 896 | ||
884 | pgm_check_occured = 0; | 897 | pgm_check_occured = 0; |
885 | s390_reset_pgm_handler = cio_reset_pgm_check_handler; | 898 | s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; |
886 | rc = stsch(schid, addr); | 899 | rc = stsch(schid, addr); |
887 | s390_reset_pgm_handler = NULL; | 900 | s390_base_pgm_handler_fn = NULL; |
888 | 901 | ||
889 | /* The program check handler could have changed pgm_check_occured */ | 902 | /* The program check handler could have changed pgm_check_occured. */ |
890 | barrier(); | 903 | barrier(); |
891 | 904 | ||
892 | if (pgm_check_occured) | 905 | if (pgm_check_occured) |
@@ -944,7 +957,7 @@ static void css_reset(void) | |||
944 | /* Reset subchannels. */ | 957 | /* Reset subchannels. */ |
945 | for_each_subchannel(__shutdown_subchannel_easy, NULL); | 958 | for_each_subchannel(__shutdown_subchannel_easy, NULL); |
946 | /* Reset channel paths. */ | 959 | /* Reset channel paths. */ |
947 | s390_reset_mcck_handler = s390_reset_chpids_mcck_handler; | 960 | s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler; |
948 | /* Enable channel report machine checks. */ | 961 | /* Enable channel report machine checks. */ |
949 | __ctl_set_bit(14, 28); | 962 | __ctl_set_bit(14, 28); |
950 | /* Temporarily reenable machine checks. */ | 963 | /* Temporarily reenable machine checks. */ |
@@ -969,7 +982,7 @@ static void css_reset(void) | |||
969 | local_mcck_disable(); | 982 | local_mcck_disable(); |
970 | /* Disable channel report machine checks. */ | 983 | /* Disable channel report machine checks. */ |
971 | __ctl_clear_bit(14, 28); | 984 | __ctl_clear_bit(14, 28); |
972 | s390_reset_mcck_handler = NULL; | 985 | s390_base_mcck_handler_fn = NULL; |
973 | } | 986 | } |
974 | 987 | ||
975 | static struct reset_call css_reset_call = { | 988 | static struct reset_call css_reset_call = { |