diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 7061398341d59ac21ffab3affb29216ca973460e..fb317bf2c3780df747180766bd76fa9753f44e81 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -460,7 +460,7 @@ startup: #ifndef CONFIG_MARCH_G5 # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST - stfl __LC_STFL_FAC_LIST # store facility list + .insn s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list tm __LC_STFL_FAC_LIST,0x01 # stfle available ? jz 0f la %r0,0 diff --git a/arch/s390/kernel/switch_cpu.S b/arch/s390/kernel/switch_cpu.S index 469f11b574facd8a819de59fe2e6796e0f60cd35..20530dd2eab13ef9f780076edf5a6a23e2b6d9b6 100644 --- a/arch/s390/kernel/switch_cpu.S +++ b/arch/s390/kernel/switch_cpu.S @@ -46,7 +46,9 @@ smp_restart_cpu: ltr %r4,%r4 /* New stack ? */ jz 1f lr %r15,%r4 -1: basr %r14,%r2 +1: lr %r14,%r2 /* r14: Function to call */ + lr %r2,%r3 /* r2 : Parameter for function*/ + basr %r14,%r14 /* Call function */ .gprregs_addr: .long .gprregs diff --git a/arch/s390/kernel/switch_cpu64.S b/arch/s390/kernel/switch_cpu64.S index d94aacc898cb99830bf85e458df2fd9a9e522481..5be3f43898f99584e6626f95c43210271e55c3b8 100644 --- a/arch/s390/kernel/switch_cpu64.S +++ b/arch/s390/kernel/switch_cpu64.S @@ -42,7 +42,9 @@ smp_restart_cpu: ltgr %r4,%r4 /* New stack ? */ jz 1f lgr %r15,%r4 -1: basr %r14,%r2 +1: lgr %r14,%r2 /* r14: Function to call */ + lgr %r2,%r3 /* r2 : Parameter for function*/ + basr %r14,%r14 /* Call function */ .section .data,"aw",@progbits .gprregs: diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c index 3d48f4db246d2a2caf8ec43f4dd38cf272200aba..4952872d6f0ae1c05c58bd7d046fe24029aef5ac 100644 --- a/arch/s390/oprofile/hwsampler.c +++ b/arch/s390/oprofile/hwsampler.c @@ -517,12 +517,8 @@ static int stop_sampling(int cpu) static int check_hardware_prerequisites(void) { - unsigned long long facility_bits[2]; - - memcpy(facility_bits, S390_lowcore.stfle_fac_list, 32); - if (!(facility_bits[1] & (1ULL << 59))) + if (!test_facility(68)) return -EOPNOTSUPP; - return 0; } /* diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index df14c51f653224d37b6ac29c87ad4a778f2b2af9..8e04c00cf0ad10d522128b97e33cefcf3b870adf 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -541,15 +541,24 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, int force, ret; unsigned long i; - if (!dev_fsm_final_state(cdev) && - cdev->private->state != DEV_STATE_DISCONNECTED) - return -EAGAIN; + /* Prevent conflict between multiple on-/offline processing requests. */ if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0) return -EAGAIN; + /* Prevent conflict between internal I/Os and on-/offline processing. */ + if (!dev_fsm_final_state(cdev) && + cdev->private->state != DEV_STATE_DISCONNECTED) { + ret = -EAGAIN; + goto out_onoff; + } + /* Prevent conflict between pending work and on-/offline processing.*/ + if (work_pending(&cdev->private->todo_work)) { + ret = -EAGAIN; + goto out_onoff; + } if (cdev->drv && !try_module_get(cdev->drv->driver.owner)) { - atomic_set(&cdev->private->onoff, 0); - return -EINVAL; + ret = -EINVAL; + goto out_onoff; } if (!strncmp(buf, "force\n", count)) { force = 1; @@ -574,6 +583,7 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, out: if (cdev->drv) module_put(cdev->drv->driver.owner); +out_onoff: atomic_set(&cdev->private->onoff, 0); return (ret < 0) ? ret : count; } @@ -1311,10 +1321,12 @@ static int purge_fn(struct device *dev, void *data) spin_lock_irq(cdev->ccwlock); if (is_blacklisted(id->ssid, id->devno) && - (cdev->private->state == DEV_STATE_OFFLINE)) { + (cdev->private->state == DEV_STATE_OFFLINE) && + (atomic_cmpxchg(&cdev->private->onoff, 0, 1) == 0)) { CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", id->ssid, id->devno); ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); + atomic_set(&cdev->private->onoff, 0); } spin_unlock_irq(cdev->ccwlock); /* Abort loop in case of pending signal. */ diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 479c665e9e7c25f91996eeb287770384009c9b7a..c532ba929ccde2c0c802edcf4ad870a7a78cf484 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1649,26 +1649,26 @@ static int __init init_QDIO(void) { int rc; - rc = qdio_setup_init(); + rc = qdio_debug_init(); if (rc) return rc; + rc = qdio_setup_init(); + if (rc) + goto out_debug; rc = tiqdio_allocate_memory(); if (rc) goto out_cache; - rc = qdio_debug_init(); - if (rc) - goto out_ti; rc = tiqdio_register_thinints(); if (rc) - goto out_debug; + goto out_ti; return 0; -out_debug: - qdio_debug_exit(); out_ti: tiqdio_free_memory(); out_cache: qdio_setup_exit(); +out_debug: + qdio_debug_exit(); return rc; } @@ -1676,8 +1676,8 @@ static void __exit exit_QDIO(void) { tiqdio_unregister_thinints(); tiqdio_free_memory(); - qdio_debug_exit(); qdio_setup_exit(); + qdio_debug_exit(); } module_init(init_QDIO);