diff options
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r-- | drivers/s390/cio/cio.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 07a4cbfc243..ad2b3792984 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -646,7 +646,7 @@ do_IRQ (struct pt_regs *regs) * Make sure that the i/o interrupt did not "overtake" * the last HZ timer interrupt. */ - account_ticks(); + account_ticks(S390_lowcore.int_clock); /* * Get interrupt information from lowcore */ @@ -850,6 +850,19 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) return -EBUSY; /* uhm... */ } +/* we can't use the normal udelay here, since it enables external interrupts */ + +static void udelay_reset(unsigned long usecs) +{ + uint64_t start_cc, end_cc; + + asm volatile ("STCK %0" : "=m" (start_cc)); + do { + cpu_relax(); + asm volatile ("STCK %0" : "=m" (end_cc)); + } while (((end_cc - start_cc)/4096) < usecs); +} + static inline int __clear_subchannel_easy(struct subchannel_id schid) { @@ -865,7 +878,7 @@ __clear_subchannel_easy(struct subchannel_id schid) if (schid_equal(&ti.schid, &schid)) return 0; } - udelay(100); + udelay_reset(100); } return -EBUSY; } |