Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 23 Oct 2013 07:10:25 +0000 (08:10 +0100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 23 Oct 2013 07:10:25 +0000 (08:10 +0100)
Pull s390 fixes from Martin Schwidefsky:
 "Several last minute bug fixes.

  Two of them are on the larger side for rc7, the dasd format patch for
  older storage devices and the store-clock-fast patch where we have
  been to optimistic with an optimization"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/time: correct use of store clock fast
  s390/vmlogrdr: fix array access in vmlogrdr_open()
  s390/compat,signal: fix return value of copy_siginfo_(to|from)_user32()
  s390/dasd: check for availability of prefix command during format
  s390/mm,kvm: fix software dirty bits vs. kvm for old machines

arch/s390/include/asm/pgtable.h
arch/s390/include/asm/timex.h
arch/s390/kernel/compat_signal.c
arch/s390/kernel/debug.c
arch/s390/kvm/interrupt.c
arch/s390/lib/delay.c
drivers/s390/block/dasd_eckd.c
drivers/s390/char/sclp.c
drivers/s390/char/vmlogrdr.c
drivers/s390/cio/cio.c
drivers/s390/cio/qdio_main.c

index 9b60a36c348d5422dc325463bcb26efeee64161d..2204400d0bd58d4a1e45c82394ff5cbd100aa2cc 100644 (file)
@@ -748,7 +748,9 @@ static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry)
 
 static inline void pgste_set_pte(pte_t *ptep, pte_t entry)
 {
-       if (!MACHINE_HAS_ESOP && (pte_val(entry) & _PAGE_WRITE)) {
+       if (!MACHINE_HAS_ESOP &&
+           (pte_val(entry) & _PAGE_PRESENT) &&
+           (pte_val(entry) & _PAGE_WRITE)) {
                /*
                 * Without enhanced suppression-on-protection force
                 * the dirty bit on for all writable ptes.
index 8ad8af915032a32573e06548e90d89ea7563349c..819b94d2272054d318fdd12c31b8718a9e4bb0bd 100644 (file)
@@ -71,30 +71,30 @@ static inline void local_tick_enable(unsigned long long comp)
 
 typedef unsigned long long cycles_t;
 
-static inline unsigned long long get_tod_clock(void)
-{
-       unsigned long long clk;
-
-#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
-       asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
-#else
-       asm volatile("stck %0" : "=Q" (clk) : : "cc");
-#endif
-       return clk;
-}
-
 static inline void get_tod_clock_ext(char *clk)
 {
        asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
 }
 
-static inline unsigned long long get_tod_clock_xt(void)
+static inline unsigned long long get_tod_clock(void)
 {
        unsigned char clk[16];
        get_tod_clock_ext(clk);
        return *((unsigned long long *)&clk[1]);
 }
 
+static inline unsigned long long get_tod_clock_fast(void)
+{
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+       unsigned long long clk;
+
+       asm volatile("stckf %0" : "=Q" (clk) : : "cc");
+       return clk;
+#else
+       return get_tod_clock();
+#endif
+}
+
 static inline cycles_t get_cycles(void)
 {
        return (cycles_t) get_tod_clock() >> 2;
@@ -125,7 +125,7 @@ extern u64 sched_clock_base_cc;
  */
 static inline unsigned long long get_tod_clock_monotonic(void)
 {
-       return get_tod_clock_xt() - sched_clock_base_cc;
+       return get_tod_clock() - sched_clock_base_cc;
 }
 
 /**
index 1389b637dae55018e3eab8b18dd3f44e9440e078..adaa9e9478d83fb77a2e91a41de0934f84acfb66 100644 (file)
@@ -99,7 +99,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
                        break;
                }
        }
-       return err;
+       return err ? -EFAULT : 0;
 }
 
 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
@@ -148,7 +148,7 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
                        break;
                }
        }
-       return err;
+       return err ? -EFAULT : 0;
 }
 
 static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
index f1279dc2e1bcecae2a12ea246096f1458b2de77f..17d62fe5d7b70554c36b8f85b34da23d86c90407 100644 (file)
@@ -867,7 +867,7 @@ static inline void
 debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
                        int exception)
 {
-       active->id.stck = get_tod_clock();
+       active->id.stck = get_tod_clock_fast();
        active->id.fields.cpuid = smp_processor_id();
        active->caller = __builtin_return_address(0);
        active->id.fields.exception = exception;
index 7f35cb33e5102008244b4fd1376954400f2d0009..7f1f7ac5cf7f8a2c3f3966d4fe96fa23af90ea04 100644 (file)
@@ -385,7 +385,7 @@ static int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
        }
 
        if ((!rc) && (vcpu->arch.sie_block->ckc <
-               get_tod_clock() + vcpu->arch.sie_block->epoch)) {
+               get_tod_clock_fast() + vcpu->arch.sie_block->epoch)) {
                if ((!psw_extint_disabled(vcpu)) &&
                        (vcpu->arch.sie_block->gcr[0] & 0x800ul))
                        rc = 1;
@@ -425,7 +425,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
                goto no_timer;
        }
 
-       now = get_tod_clock() + vcpu->arch.sie_block->epoch;
+       now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
        if (vcpu->arch.sie_block->ckc < now) {
                __unset_cpu_idle(vcpu);
                return 0;
@@ -515,7 +515,7 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
        }
 
        if ((vcpu->arch.sie_block->ckc <
-               get_tod_clock() + vcpu->arch.sie_block->epoch))
+               get_tod_clock_fast() + vcpu->arch.sie_block->epoch))
                __try_deliver_ckc_interrupt(vcpu);
 
        if (atomic_read(&fi->active)) {
index 57c87d7d7ede01add784c291f31a82f502ca877e..a9f3d0042d58ba849b8c624f23915d88d03d6f70 100644 (file)
@@ -44,7 +44,7 @@ static void __udelay_disabled(unsigned long long usecs)
        do {
                set_clock_comparator(end);
                vtime_stop_cpu();
-       } while (get_tod_clock() < end);
+       } while (get_tod_clock_fast() < end);
        lockdep_on();
        __ctl_load(cr0, 0, 0);
        __ctl_load(cr6, 6, 6);
@@ -55,7 +55,7 @@ static void __udelay_enabled(unsigned long long usecs)
 {
        u64 clock_saved, end;
 
-       end = get_tod_clock() + (usecs << 12);
+       end = get_tod_clock_fast() + (usecs << 12);
        do {
                clock_saved = 0;
                if (end < S390_lowcore.clock_comparator) {
@@ -65,7 +65,7 @@ static void __udelay_enabled(unsigned long long usecs)
                vtime_stop_cpu();
                if (clock_saved)
                        local_tick_enable(clock_saved);
-       } while (get_tod_clock() < end);
+       } while (get_tod_clock_fast() < end);
 }
 
 /*
@@ -109,8 +109,8 @@ void udelay_simple(unsigned long long usecs)
 {
        u64 end;
 
-       end = get_tod_clock() + (usecs << 12);
-       while (get_tod_clock() < end)
+       end = get_tod_clock_fast() + (usecs << 12);
+       while (get_tod_clock_fast() < end)
                cpu_relax();
 }
 
@@ -120,10 +120,10 @@ void __ndelay(unsigned long long nsecs)
 
        nsecs <<= 9;
        do_div(nsecs, 125);
-       end = get_tod_clock() + nsecs;
+       end = get_tod_clock_fast() + nsecs;
        if (nsecs & ~0xfffUL)
                __udelay(nsecs >> 12);
-       while (get_tod_clock() < end)
+       while (get_tod_clock_fast() < end)
                barrier();
 }
 EXPORT_SYMBOL(__ndelay);
index 5adb2042e824fc30815ea891c54b89526680b4eb..cee7e2708a1fe35359eb81cc458d939e50ad1906 100644 (file)
@@ -2077,6 +2077,7 @@ dasd_eckd_build_format(struct dasd_device *base,
        int intensity = 0;
        int r0_perm;
        int nr_tracks;
+       int use_prefix;
 
        startdev = dasd_alias_get_start_dev(base);
        if (!startdev)
@@ -2106,28 +2107,46 @@ dasd_eckd_build_format(struct dasd_device *base,
                intensity = fdata->intensity;
        }
 
+       use_prefix = base_priv->features.feature[8] & 0x01;
+
        switch (intensity) {
        case 0x00:      /* Normal format */
        case 0x08:      /* Normal format, use cdl. */
                cplength = 2 + (rpt*nr_tracks);
-               datasize = sizeof(struct PFX_eckd_data) +
-                       sizeof(struct LO_eckd_data) +
-                       rpt * nr_tracks * sizeof(struct eckd_count);
+               if (use_prefix)
+                       datasize = sizeof(struct PFX_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               rpt * nr_tracks * sizeof(struct eckd_count);
+               else
+                       datasize = sizeof(struct DE_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               rpt * nr_tracks * sizeof(struct eckd_count);
                break;
        case 0x01:      /* Write record zero and format track. */
        case 0x09:      /* Write record zero and format track, use cdl. */
                cplength = 2 + rpt * nr_tracks;
-               datasize = sizeof(struct PFX_eckd_data) +
-                       sizeof(struct LO_eckd_data) +
-                       sizeof(struct eckd_count) +
-                       rpt * nr_tracks * sizeof(struct eckd_count);
+               if (use_prefix)
+                       datasize = sizeof(struct PFX_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               sizeof(struct eckd_count) +
+                               rpt * nr_tracks * sizeof(struct eckd_count);
+               else
+                       datasize = sizeof(struct DE_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               sizeof(struct eckd_count) +
+                               rpt * nr_tracks * sizeof(struct eckd_count);
                break;
        case 0x04:      /* Invalidate track. */
        case 0x0c:      /* Invalidate track, use cdl. */
                cplength = 3;
-               datasize = sizeof(struct PFX_eckd_data) +
-                       sizeof(struct LO_eckd_data) +
-                       sizeof(struct eckd_count);
+               if (use_prefix)
+                       datasize = sizeof(struct PFX_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               sizeof(struct eckd_count);
+               else
+                       datasize = sizeof(struct DE_eckd_data) +
+                               sizeof(struct LO_eckd_data) +
+                               sizeof(struct eckd_count);
                break;
        default:
                dev_warn(&startdev->cdev->dev,
@@ -2147,14 +2166,25 @@ dasd_eckd_build_format(struct dasd_device *base,
 
        switch (intensity & ~0x08) {
        case 0x00: /* Normal format. */
-               prefix(ccw++, (struct PFX_eckd_data *) data,
-                      fdata->start_unit, fdata->stop_unit,
-                      DASD_ECKD_CCW_WRITE_CKD, base, startdev);
-               /* grant subsystem permission to format R0 */
-               if (r0_perm)
-                       ((struct PFX_eckd_data *)data)
-                               ->define_extent.ga_extended |= 0x04;
-               data += sizeof(struct PFX_eckd_data);
+               if (use_prefix) {
+                       prefix(ccw++, (struct PFX_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_CKD, base, startdev);
+                       /* grant subsystem permission to format R0 */
+                       if (r0_perm)
+                               ((struct PFX_eckd_data *)data)
+                                       ->define_extent.ga_extended |= 0x04;
+                       data += sizeof(struct PFX_eckd_data);
+               } else {
+                       define_extent(ccw++, (struct DE_eckd_data *) data,
+                                     fdata->start_unit, fdata->stop_unit,
+                                     DASD_ECKD_CCW_WRITE_CKD, startdev);
+                       /* grant subsystem permission to format R0 */
+                       if (r0_perm)
+                               ((struct DE_eckd_data *) data)
+                                       ->ga_extended |= 0x04;
+                       data += sizeof(struct DE_eckd_data);
+               }
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
                              fdata->start_unit, 0, rpt*nr_tracks,
@@ -2163,11 +2193,18 @@ dasd_eckd_build_format(struct dasd_device *base,
                data += sizeof(struct LO_eckd_data);
                break;
        case 0x01: /* Write record zero + format track. */
-               prefix(ccw++, (struct PFX_eckd_data *) data,
-                      fdata->start_unit, fdata->stop_unit,
-                      DASD_ECKD_CCW_WRITE_RECORD_ZERO,
-                      base, startdev);
-               data += sizeof(struct PFX_eckd_data);
+               if (use_prefix) {
+                       prefix(ccw++, (struct PFX_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_RECORD_ZERO,
+                              base, startdev);
+                       data += sizeof(struct PFX_eckd_data);
+               } else {
+                       define_extent(ccw++, (struct DE_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_RECORD_ZERO, startdev);
+                       data += sizeof(struct DE_eckd_data);
+               }
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
                              fdata->start_unit, 0, rpt * nr_tracks + 1,
@@ -2176,10 +2213,17 @@ dasd_eckd_build_format(struct dasd_device *base,
                data += sizeof(struct LO_eckd_data);
                break;
        case 0x04: /* Invalidate track. */
-               prefix(ccw++, (struct PFX_eckd_data *) data,
-                      fdata->start_unit, fdata->stop_unit,
-                      DASD_ECKD_CCW_WRITE_CKD, base, startdev);
-               data += sizeof(struct PFX_eckd_data);
+               if (use_prefix) {
+                       prefix(ccw++, (struct PFX_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_CKD, base, startdev);
+                       data += sizeof(struct PFX_eckd_data);
+               } else {
+                       define_extent(ccw++, (struct DE_eckd_data *) data,
+                              fdata->start_unit, fdata->stop_unit,
+                              DASD_ECKD_CCW_WRITE_CKD, startdev);
+                       data += sizeof(struct DE_eckd_data);
+               }
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
                              fdata->start_unit, 0, 1,
index a3aa374799dcf99bd334b6e49c8d7753838fbdc3..1fe264379e0d10b57ddca456ce16b72c23535ccb 100644 (file)
@@ -486,7 +486,7 @@ sclp_sync_wait(void)
        timeout = 0;
        if (timer_pending(&sclp_request_timer)) {
                /* Get timeout TOD value */
-               timeout = get_tod_clock() +
+               timeout = get_tod_clock_fast() +
                          sclp_tod_from_jiffies(sclp_request_timer.expires -
                                                jiffies);
        }
@@ -508,7 +508,7 @@ sclp_sync_wait(void)
        while (sclp_running_state != sclp_running_state_idle) {
                /* Check for expired request timer */
                if (timer_pending(&sclp_request_timer) &&
-                   get_tod_clock() > timeout &&
+                   get_tod_clock_fast() > timeout &&
                    del_timer(&sclp_request_timer))
                        sclp_request_timer.function(sclp_request_timer.data);
                cpu_relax();
index 9b3a24e8d3a0e0dfec9ffcbf1757ddd37f66329e..cf31d3321dab86b889b16fa5e3b9b2e433c3992d 100644 (file)
@@ -313,7 +313,7 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp)
        int ret;
 
        dev_num = iminor(inode);
-       if (dev_num > MAXMINOR)
+       if (dev_num >= MAXMINOR)
                return -ENODEV;
        logptr = &sys_ser[dev_num];
 
index d7da67a31c77f606ef68445f9da446b521a4abf1..88e35d85d205f7c21de1f81860865386a7845289 100644 (file)
@@ -878,9 +878,9 @@ static void css_reset(void)
                        atomic_inc(&chpid_reset_count);
        }
        /* Wait for machine check for all channel paths. */
-       timeout = get_tod_clock() + (RCHP_TIMEOUT << 12);
+       timeout = get_tod_clock_fast() + (RCHP_TIMEOUT << 12);
        while (atomic_read(&chpid_reset_count) != 0) {
-               if (get_tod_clock() > timeout)
+               if (get_tod_clock_fast() > timeout)
                        break;
                cpu_relax();
        }
index 8ed52aa4912269405158e300f1c983577b29caec..bbd3e511c771addebda2639675d85664b3191494 100644 (file)
@@ -338,10 +338,10 @@ again:
                retries++;
 
                if (!start_time) {
-                       start_time = get_tod_clock();
+                       start_time = get_tod_clock_fast();
                        goto again;
                }
-               if ((get_tod_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE)
+               if (get_tod_clock_fast() - start_time < QDIO_BUSY_BIT_PATIENCE)
                        goto again;
        }
        if (retries) {
@@ -504,7 +504,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
        int count, stop;
        unsigned char state = 0;
 
-       q->timestamp = get_tod_clock();
+       q->timestamp = get_tod_clock_fast();
 
        /*
         * Don't check 128 buffers, as otherwise qdio_inbound_q_moved
@@ -595,7 +595,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q)
         * At this point we know, that inbound first_to_check
         * has (probably) not moved (see qdio_inbound_processing).
         */
-       if (get_tod_clock() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) {
+       if (get_tod_clock_fast() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) {
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x",
                              q->first_to_check);
                return 1;
@@ -728,7 +728,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
        int count, stop;
        unsigned char state = 0;
 
-       q->timestamp = get_tod_clock();
+       q->timestamp = get_tod_clock_fast();
 
        if (need_siga_sync(q))
                if (((queue_type(q) != QDIO_IQDIO_QFMT) &&