Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/s390/linux

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
  • Loading branch information
Linus Torvalds committed Oct 23, 2013
2 parents 9033832 + 8c071b0 commit 320437a
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 65 deletions.
4 changes: 3 additions & 1 deletion arch/s390/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
28 changes: 14 additions & 14 deletions arch/s390/include/asm/timex.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions arch/s390/kernel/compat_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions arch/s390/kvm/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down
14 changes: 7 additions & 7 deletions arch/s390/lib/delay.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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) {
Expand All @@ -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);
}

/*
Expand Down Expand Up @@ -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();
}

Expand All @@ -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);
98 changes: 71 additions & 27 deletions drivers/s390/block/dasd_eckd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions drivers/s390/char/sclp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion drivers/s390/char/vmlogrdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand Down
4 changes: 2 additions & 2 deletions drivers/s390/cio/cio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
10 changes: 5 additions & 5 deletions drivers/s390/cio/qdio_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,10 +338,10 @@ static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) &&
Expand Down

0 comments on commit 320437a

Please sign in to comment.