diff options
| -rw-r--r-- | arch/s390/Kconfig | 3 | ||||
| -rw-r--r-- | arch/s390/kernel/process.c | 15 | ||||
| -rw-r--r-- | arch/s390/kernel/smp.c | 53 | ||||
| -rw-r--r-- | arch/s390/kernel/time.c | 2 | ||||
| -rw-r--r-- | arch/s390/lib/uaccess_std.c | 8 | ||||
| -rw-r--r-- | drivers/s390/block/dasd.c | 12 | ||||
| -rw-r--r-- | drivers/s390/block/dcssblk.c | 2 | ||||
| -rw-r--r-- | drivers/s390/char/sclp.c | 12 | ||||
| -rw-r--r-- | drivers/s390/char/sclp.h | 6 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_config.c | 2 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_cpi_sys.c | 2 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_rw.c | 4 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_vt220.c | 2 | ||||
| -rw-r--r-- | drivers/s390/cio/device.c | 15 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio.c | 13 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio.h | 2 | ||||
| -rw-r--r-- | include/asm-s390/bitops.h | 20 |
17 files changed, 103 insertions, 70 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 92a4f7b4323a..b21444b681b6 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
| @@ -100,7 +100,8 @@ config NR_CPUS | |||
| 100 | int "Maximum number of CPUs (2-64)" | 100 | int "Maximum number of CPUs (2-64)" |
| 101 | range 2 64 | 101 | range 2 64 |
| 102 | depends on SMP | 102 | depends on SMP |
| 103 | default "32" | 103 | default "32" if !64BIT |
| 104 | default "64" if 64BIT | ||
| 104 | help | 105 | help |
| 105 | This allows you to specify the maximum number of CPUs which this | 106 | This allows you to specify the maximum number of CPUs which this |
| 106 | kernel will support. The maximum supported value is 64 and the | 107 | kernel will support. The maximum supported value is 64 and the |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index a6a4729e0e94..1c59ec161cf8 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
| @@ -114,24 +114,27 @@ extern void s390_handle_mcck(void); | |||
| 114 | static void default_idle(void) | 114 | static void default_idle(void) |
| 115 | { | 115 | { |
| 116 | int cpu, rc; | 116 | int cpu, rc; |
| 117 | int nr_calls = 0; | ||
| 118 | void *hcpu; | ||
| 117 | #ifdef CONFIG_SMP | 119 | #ifdef CONFIG_SMP |
| 118 | struct s390_idle_data *idle; | 120 | struct s390_idle_data *idle; |
| 119 | #endif | 121 | #endif |
| 120 | 122 | ||
| 121 | /* CPU is going idle. */ | 123 | /* CPU is going idle. */ |
| 122 | cpu = smp_processor_id(); | 124 | cpu = smp_processor_id(); |
| 123 | 125 | hcpu = (void *)(long)cpu; | |
| 124 | local_irq_disable(); | 126 | local_irq_disable(); |
| 125 | if (need_resched()) { | 127 | if (need_resched()) { |
| 126 | local_irq_enable(); | 128 | local_irq_enable(); |
| 127 | return; | 129 | return; |
| 128 | } | 130 | } |
| 129 | 131 | ||
| 130 | rc = atomic_notifier_call_chain(&idle_chain, | 132 | rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1, |
| 131 | S390_CPU_IDLE, (void *)(long) cpu); | 133 | &nr_calls); |
| 132 | if (rc != NOTIFY_OK && rc != NOTIFY_DONE) | 134 | if (rc == NOTIFY_BAD) { |
| 133 | BUG(); | 135 | nr_calls--; |
| 134 | if (rc != NOTIFY_OK) { | 136 | __atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE, |
| 137 | hcpu, nr_calls, NULL); | ||
| 135 | local_irq_enable(); | 138 | local_irq_enable(); |
| 136 | return; | 139 | return; |
| 137 | } | 140 | } |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 85060659fb12..818bd09c0260 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
| @@ -626,13 +626,17 @@ static int __cpuinit smp_alloc_lowcore(int cpu) | |||
| 626 | if (!lowcore) | 626 | if (!lowcore) |
| 627 | return -ENOMEM; | 627 | return -ENOMEM; |
| 628 | async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); | 628 | async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); |
| 629 | if (!async_stack) | ||
| 630 | goto out_async_stack; | ||
| 631 | panic_stack = __get_free_page(GFP_KERNEL); | 629 | panic_stack = __get_free_page(GFP_KERNEL); |
| 632 | if (!panic_stack) | 630 | if (!panic_stack || !async_stack) |
| 633 | goto out_panic_stack; | 631 | goto out; |
| 634 | 632 | /* | |
| 635 | *lowcore = S390_lowcore; | 633 | * Only need to copy the first 512 bytes from address 0. But since |
| 634 | * the compiler emits a warning if src == NULL for memcpy use copy_page | ||
| 635 | * instead. Copies more than needed but this code is not performance | ||
| 636 | * critical. | ||
| 637 | */ | ||
| 638 | copy_page(lowcore, &S390_lowcore); | ||
| 639 | memset((void *)lowcore + 512, 0, sizeof(*lowcore) - 512); | ||
| 636 | lowcore->async_stack = async_stack + ASYNC_SIZE; | 640 | lowcore->async_stack = async_stack + ASYNC_SIZE; |
| 637 | lowcore->panic_stack = panic_stack + PAGE_SIZE; | 641 | lowcore->panic_stack = panic_stack + PAGE_SIZE; |
| 638 | 642 | ||
| @@ -653,9 +657,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu) | |||
| 653 | out_save_area: | 657 | out_save_area: |
| 654 | free_page(panic_stack); | 658 | free_page(panic_stack); |
| 655 | #endif | 659 | #endif |
| 656 | out_panic_stack: | 660 | out: |
| 657 | free_pages(async_stack, ASYNC_ORDER); | 661 | free_pages(async_stack, ASYNC_ORDER); |
| 658 | out_async_stack: | ||
| 659 | free_pages((unsigned long) lowcore, lc_order); | 662 | free_pages((unsigned long) lowcore, lc_order); |
| 660 | return -ENOMEM; | 663 | return -ENOMEM; |
| 661 | } | 664 | } |
| @@ -719,8 +722,8 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
| 719 | cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; | 722 | cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; |
| 720 | cpu_lowcore->current_task = (unsigned long) idle; | 723 | cpu_lowcore->current_task = (unsigned long) idle; |
| 721 | cpu_lowcore->cpu_data.cpu_nr = cpu; | 724 | cpu_lowcore->cpu_data.cpu_nr = cpu; |
| 722 | cpu_lowcore->softirq_pending = 0; | 725 | cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; |
| 723 | cpu_lowcore->ext_call_fast = 0; | 726 | cpu_lowcore->ipl_device = S390_lowcore.ipl_device; |
| 724 | eieio(); | 727 | eieio(); |
| 725 | 728 | ||
| 726 | while (signal_processor(cpu, sigp_restart) == sigp_busy) | 729 | while (signal_processor(cpu, sigp_restart) == sigp_busy) |
| @@ -797,23 +800,43 @@ void cpu_die(void) | |||
| 797 | 800 | ||
| 798 | void __init smp_prepare_cpus(unsigned int max_cpus) | 801 | void __init smp_prepare_cpus(unsigned int max_cpus) |
| 799 | { | 802 | { |
| 803 | #ifndef CONFIG_64BIT | ||
| 804 | unsigned long save_area = 0; | ||
| 805 | #endif | ||
| 806 | unsigned long async_stack, panic_stack; | ||
| 807 | struct _lowcore *lowcore; | ||
| 800 | unsigned int cpu; | 808 | unsigned int cpu; |
| 809 | int lc_order; | ||
| 801 | 810 | ||
| 802 | smp_detect_cpus(); | 811 | smp_detect_cpus(); |
| 803 | 812 | ||
| 804 | /* request the 0x1201 emergency signal external interrupt */ | 813 | /* request the 0x1201 emergency signal external interrupt */ |
| 805 | if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) | 814 | if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) |
| 806 | panic("Couldn't request external interrupt 0x1201"); | 815 | panic("Couldn't request external interrupt 0x1201"); |
| 807 | memset(lowcore_ptr, 0, sizeof(lowcore_ptr)); | ||
| 808 | print_cpu_info(&S390_lowcore.cpu_data); | 816 | print_cpu_info(&S390_lowcore.cpu_data); |
| 809 | smp_alloc_lowcore(smp_processor_id()); | ||
| 810 | 817 | ||
| 818 | /* Reallocate current lowcore, but keep its contents. */ | ||
| 819 | lc_order = sizeof(long) == 8 ? 1 : 0; | ||
| 820 | lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order); | ||
| 821 | panic_stack = __get_free_page(GFP_KERNEL); | ||
| 822 | async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); | ||
| 811 | #ifndef CONFIG_64BIT | 823 | #ifndef CONFIG_64BIT |
| 812 | if (MACHINE_HAS_IEEE) | 824 | if (MACHINE_HAS_IEEE) |
| 813 | ctl_set_bit(14, 29); /* enable extended save area */ | 825 | save_area = get_zeroed_page(GFP_KERNEL); |
| 814 | #endif | 826 | #endif |
| 815 | set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]); | 827 | local_irq_disable(); |
| 816 | 828 | local_mcck_disable(); | |
| 829 | lowcore_ptr[smp_processor_id()] = lowcore; | ||
| 830 | *lowcore = S390_lowcore; | ||
| 831 | lowcore->panic_stack = panic_stack + PAGE_SIZE; | ||
| 832 | lowcore->async_stack = async_stack + ASYNC_SIZE; | ||
| 833 | #ifndef CONFIG_64BIT | ||
| 834 | if (MACHINE_HAS_IEEE) | ||
| 835 | lowcore->extended_save_area_addr = (u32) save_area; | ||
| 836 | #endif | ||
| 837 | set_prefix((u32)(unsigned long) lowcore); | ||
| 838 | local_mcck_enable(); | ||
| 839 | local_irq_enable(); | ||
| 817 | for_each_possible_cpu(cpu) | 840 | for_each_possible_cpu(cpu) |
| 818 | if (cpu != smp_processor_id()) | 841 | if (cpu != smp_processor_id()) |
| 819 | smp_create_idle(cpu); | 842 | smp_create_idle(cpu); |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 3bbac1293be4..76a5dd1b4ce9 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
| @@ -744,7 +744,6 @@ static void etr_adjust_time(unsigned long long clock, unsigned long long delay) | |||
| 744 | } | 744 | } |
| 745 | } | 745 | } |
| 746 | 746 | ||
| 747 | #ifdef CONFIG_SMP | ||
| 748 | static void etr_sync_cpu_start(void *dummy) | 747 | static void etr_sync_cpu_start(void *dummy) |
| 749 | { | 748 | { |
| 750 | int *in_sync = dummy; | 749 | int *in_sync = dummy; |
| @@ -777,7 +776,6 @@ static void etr_sync_cpu_start(void *dummy) | |||
| 777 | static void etr_sync_cpu_end(void *dummy) | 776 | static void etr_sync_cpu_end(void *dummy) |
| 778 | { | 777 | { |
| 779 | } | 778 | } |
| 780 | #endif /* CONFIG_SMP */ | ||
| 781 | 779 | ||
| 782 | /* | 780 | /* |
| 783 | * Sync the TOD clock using the port refered to by aibp. This port | 781 | * Sync the TOD clock using the port refered to by aibp. This port |
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c index 28c4500a58d0..d2ffbadb51a7 100644 --- a/arch/s390/lib/uaccess_std.c +++ b/arch/s390/lib/uaccess_std.c | |||
| @@ -293,10 +293,10 @@ int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval) | |||
| 293 | 293 | ||
| 294 | asm volatile( | 294 | asm volatile( |
| 295 | " sacf 256\n" | 295 | " sacf 256\n" |
| 296 | " cs %1,%4,0(%5)\n" | 296 | "0: cs %1,%4,0(%5)\n" |
| 297 | "0: lr %0,%1\n" | 297 | "1: lr %0,%1\n" |
| 298 | "1: sacf 0\n" | 298 | "2: sacf 0\n" |
| 299 | EX_TABLE(0b,1b) | 299 | EX_TABLE(0b,2b) EX_TABLE(1b,2b) |
| 300 | : "=d" (ret), "+d" (oldval), "=m" (*uaddr) | 300 | : "=d" (ret), "+d" (oldval), "=m" (*uaddr) |
| 301 | : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) | 301 | : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) |
| 302 | : "cc", "memory" ); | 302 | : "cc", "memory" ); |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d984e0fae630..ccf46c96adb4 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -1149,12 +1149,14 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, | |||
| 1149 | { | 1149 | { |
| 1150 | struct list_head *l, *n; | 1150 | struct list_head *l, *n; |
| 1151 | struct dasd_ccw_req *cqr; | 1151 | struct dasd_ccw_req *cqr; |
| 1152 | struct dasd_block *block; | ||
| 1152 | 1153 | ||
| 1153 | list_for_each_safe(l, n, final_queue) { | 1154 | list_for_each_safe(l, n, final_queue) { |
| 1154 | cqr = list_entry(l, struct dasd_ccw_req, devlist); | 1155 | cqr = list_entry(l, struct dasd_ccw_req, devlist); |
| 1155 | list_del_init(&cqr->devlist); | 1156 | list_del_init(&cqr->devlist); |
| 1156 | if (cqr->block) | 1157 | block = cqr->block; |
| 1157 | spin_lock_bh(&cqr->block->queue_lock); | 1158 | if (block) |
| 1159 | spin_lock_bh(&block->queue_lock); | ||
| 1158 | switch (cqr->status) { | 1160 | switch (cqr->status) { |
| 1159 | case DASD_CQR_SUCCESS: | 1161 | case DASD_CQR_SUCCESS: |
| 1160 | cqr->status = DASD_CQR_DONE; | 1162 | cqr->status = DASD_CQR_DONE; |
| @@ -1172,15 +1174,13 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, | |||
| 1172 | cqr, cqr->status); | 1174 | cqr, cqr->status); |
| 1173 | BUG(); | 1175 | BUG(); |
| 1174 | } | 1176 | } |
| 1175 | if (cqr->block) | ||
| 1176 | spin_unlock_bh(&cqr->block->queue_lock); | ||
| 1177 | if (cqr->callback != NULL) | 1177 | if (cqr->callback != NULL) |
| 1178 | (cqr->callback)(cqr, cqr->callback_data); | 1178 | (cqr->callback)(cqr, cqr->callback_data); |
| 1179 | if (block) | ||
| 1180 | spin_unlock_bh(&block->queue_lock); | ||
| 1179 | } | 1181 | } |
| 1180 | } | 1182 | } |
| 1181 | 1183 | ||
| 1182 | |||
| 1183 | |||
| 1184 | /* | 1184 | /* |
| 1185 | * Take a look at the first request on the ccw queue and check | 1185 | * Take a look at the first request on the ccw queue and check |
| 1186 | * if it reached its expire time. If so, terminate the IO. | 1186 | * if it reached its expire time. If so, terminate the IO. |
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 3faf0538b328..e6c94dbfdeaa 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
| @@ -666,7 +666,7 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) | |||
| 666 | page_addr = (unsigned long) | 666 | page_addr = (unsigned long) |
| 667 | page_address(bvec->bv_page) + bvec->bv_offset; | 667 | page_address(bvec->bv_page) + bvec->bv_offset; |
| 668 | source_addr = dev_info->start + (index<<12) + bytes_done; | 668 | source_addr = dev_info->start + (index<<12) + bytes_done; |
| 669 | if (unlikely(page_addr & 4095) != 0 || (bvec->bv_len & 4095) != 0) | 669 | if (unlikely((page_addr & 4095) != 0) || (bvec->bv_len & 4095) != 0) |
| 670 | // More paranoia. | 670 | // More paranoia. |
| 671 | goto fail; | 671 | goto fail; |
| 672 | if (bio_data_dir(bio) == READ) { | 672 | if (bio_data_dir(bio) == READ) { |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 25629b92dec3..2c7a1ee6b041 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
| @@ -29,10 +29,10 @@ static ext_int_info_t ext_int_info_hwc; | |||
| 29 | /* Lock to protect internal data consistency. */ | 29 | /* Lock to protect internal data consistency. */ |
| 30 | static DEFINE_SPINLOCK(sclp_lock); | 30 | static DEFINE_SPINLOCK(sclp_lock); |
| 31 | 31 | ||
| 32 | /* Mask of events that we can receive from the sclp interface. */ | 32 | /* Mask of events that we can send to the sclp interface. */ |
| 33 | static sccb_mask_t sclp_receive_mask; | 33 | static sccb_mask_t sclp_receive_mask; |
| 34 | 34 | ||
| 35 | /* Mask of events that we can send to the sclp interface. */ | 35 | /* Mask of events that we can receive from the sclp interface. */ |
| 36 | static sccb_mask_t sclp_send_mask; | 36 | static sccb_mask_t sclp_send_mask; |
| 37 | 37 | ||
| 38 | /* List of registered event listeners and senders. */ | 38 | /* List of registered event listeners and senders. */ |
| @@ -380,7 +380,7 @@ sclp_interrupt_handler(__u16 code) | |||
| 380 | } | 380 | } |
| 381 | sclp_running_state = sclp_running_state_idle; | 381 | sclp_running_state = sclp_running_state_idle; |
| 382 | } | 382 | } |
| 383 | if (evbuf_pending && sclp_receive_mask != 0 && | 383 | if (evbuf_pending && |
| 384 | sclp_activation_state == sclp_activation_state_active) | 384 | sclp_activation_state == sclp_activation_state_active) |
| 385 | __sclp_queue_read_req(); | 385 | __sclp_queue_read_req(); |
| 386 | spin_unlock(&sclp_lock); | 386 | spin_unlock(&sclp_lock); |
| @@ -459,8 +459,8 @@ sclp_dispatch_state_change(void) | |||
| 459 | reg = NULL; | 459 | reg = NULL; |
| 460 | list_for_each(l, &sclp_reg_list) { | 460 | list_for_each(l, &sclp_reg_list) { |
| 461 | reg = list_entry(l, struct sclp_register, list); | 461 | reg = list_entry(l, struct sclp_register, list); |
| 462 | receive_mask = reg->receive_mask & sclp_receive_mask; | 462 | receive_mask = reg->send_mask & sclp_receive_mask; |
| 463 | send_mask = reg->send_mask & sclp_send_mask; | 463 | send_mask = reg->receive_mask & sclp_send_mask; |
| 464 | if (reg->sclp_receive_mask != receive_mask || | 464 | if (reg->sclp_receive_mask != receive_mask || |
| 465 | reg->sclp_send_mask != send_mask) { | 465 | reg->sclp_send_mask != send_mask) { |
| 466 | reg->sclp_receive_mask = receive_mask; | 466 | reg->sclp_receive_mask = receive_mask; |
| @@ -615,8 +615,8 @@ struct init_sccb { | |||
| 615 | u16 mask_length; | 615 | u16 mask_length; |
| 616 | sccb_mask_t receive_mask; | 616 | sccb_mask_t receive_mask; |
| 617 | sccb_mask_t send_mask; | 617 | sccb_mask_t send_mask; |
| 618 | sccb_mask_t sclp_send_mask; | ||
| 619 | sccb_mask_t sclp_receive_mask; | 618 | sccb_mask_t sclp_receive_mask; |
| 619 | sccb_mask_t sclp_send_mask; | ||
| 620 | } __attribute__((packed)); | 620 | } __attribute__((packed)); |
| 621 | 621 | ||
| 622 | /* Prepare init mask request. Called while sclp_lock is locked. */ | 622 | /* Prepare init mask request. Called while sclp_lock is locked. */ |
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index aa8186d18aee..bac80e856f97 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
| @@ -122,11 +122,13 @@ struct sclp_req { | |||
| 122 | /* of some routines it wants to be called from the low level driver */ | 122 | /* of some routines it wants to be called from the low level driver */ |
| 123 | struct sclp_register { | 123 | struct sclp_register { |
| 124 | struct list_head list; | 124 | struct list_head list; |
| 125 | /* event masks this user is registered for */ | 125 | /* User wants to receive: */ |
| 126 | sccb_mask_t receive_mask; | 126 | sccb_mask_t receive_mask; |
| 127 | /* User wants to send: */ | ||
| 127 | sccb_mask_t send_mask; | 128 | sccb_mask_t send_mask; |
| 128 | /* actually present events */ | 129 | /* H/W can receive: */ |
| 129 | sccb_mask_t sclp_receive_mask; | 130 | sccb_mask_t sclp_receive_mask; |
| 131 | /* H/W can send: */ | ||
| 130 | sccb_mask_t sclp_send_mask; | 132 | sccb_mask_t sclp_send_mask; |
| 131 | /* called if event type availability changes */ | 133 | /* called if event type availability changes */ |
| 132 | void (*state_change_fn)(struct sclp_register *); | 134 | void (*state_change_fn)(struct sclp_register *); |
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c index 9dc77f14fa52..b8f35bc52b7b 100644 --- a/drivers/s390/char/sclp_config.c +++ b/drivers/s390/char/sclp_config.c | |||
| @@ -64,7 +64,7 @@ static int __init sclp_conf_init(void) | |||
| 64 | return rc; | 64 | return rc; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | if (!(sclp_conf_register.sclp_receive_mask & EVTYP_CONFMGMDATA_MASK)) { | 67 | if (!(sclp_conf_register.sclp_send_mask & EVTYP_CONFMGMDATA_MASK)) { |
| 68 | printk(KERN_WARNING TAG "no configuration management.\n"); | 68 | printk(KERN_WARNING TAG "no configuration management.\n"); |
| 69 | sclp_unregister(&sclp_conf_register); | 69 | sclp_unregister(&sclp_conf_register); |
| 70 | rc = -ENOSYS; | 70 | rc = -ENOSYS; |
diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c index 41617032afdc..9f37456222e9 100644 --- a/drivers/s390/char/sclp_cpi_sys.c +++ b/drivers/s390/char/sclp_cpi_sys.c | |||
| @@ -129,7 +129,7 @@ static int cpi_req(void) | |||
| 129 | "to hardware console.\n"); | 129 | "to hardware console.\n"); |
| 130 | goto out; | 130 | goto out; |
| 131 | } | 131 | } |
| 132 | if (!(sclp_cpi_event.sclp_send_mask & EVTYP_CTLPROGIDENT_MASK)) { | 132 | if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) { |
| 133 | printk(KERN_WARNING "cpi: no control program " | 133 | printk(KERN_WARNING "cpi: no control program " |
| 134 | "identification support\n"); | 134 | "identification support\n"); |
| 135 | rc = -EOPNOTSUPP; | 135 | rc = -EOPNOTSUPP; |
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c index ad7195d3de0c..da09781b32f7 100644 --- a/drivers/s390/char/sclp_rw.c +++ b/drivers/s390/char/sclp_rw.c | |||
| @@ -452,10 +452,10 @@ sclp_emit_buffer(struct sclp_buffer *buffer, | |||
| 452 | return -EIO; | 452 | return -EIO; |
| 453 | 453 | ||
| 454 | sccb = buffer->sccb; | 454 | sccb = buffer->sccb; |
| 455 | if (sclp_rw_event.sclp_send_mask & EVTYP_MSG_MASK) | 455 | if (sclp_rw_event.sclp_receive_mask & EVTYP_MSG_MASK) |
| 456 | /* Use normal write message */ | 456 | /* Use normal write message */ |
| 457 | sccb->msg_buf.header.type = EVTYP_MSG; | 457 | sccb->msg_buf.header.type = EVTYP_MSG; |
| 458 | else if (sclp_rw_event.sclp_send_mask & EVTYP_PMSGCMD_MASK) | 458 | else if (sclp_rw_event.sclp_receive_mask & EVTYP_PMSGCMD_MASK) |
| 459 | /* Use write priority message */ | 459 | /* Use write priority message */ |
| 460 | sccb->msg_buf.header.type = EVTYP_PMSGCMD; | 460 | sccb->msg_buf.header.type = EVTYP_PMSGCMD; |
| 461 | else | 461 | else |
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index f47f4a768be5..92f527201792 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c | |||
| @@ -202,7 +202,7 @@ sclp_vt220_callback(struct sclp_req *request, void *data) | |||
| 202 | static int | 202 | static int |
| 203 | __sclp_vt220_emit(struct sclp_vt220_request *request) | 203 | __sclp_vt220_emit(struct sclp_vt220_request *request) |
| 204 | { | 204 | { |
| 205 | if (!(sclp_vt220_register.sclp_send_mask & EVTYP_VT220MSG_MASK)) { | 205 | if (!(sclp_vt220_register.sclp_receive_mask & EVTYP_VT220MSG_MASK)) { |
| 206 | request->sclp_req.status = SCLP_REQ_FAILED; | 206 | request->sclp_req.status = SCLP_REQ_FAILED; |
| 207 | return -EIO; | 207 | return -EIO; |
| 208 | } | 208 | } |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index d35dc3f25d06..fec004f62bcf 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | #include "io_sch.h" | 32 | #include "io_sch.h" |
| 33 | 33 | ||
| 34 | static struct timer_list recovery_timer; | 34 | static struct timer_list recovery_timer; |
| 35 | static spinlock_t recovery_lock; | 35 | static DEFINE_SPINLOCK(recovery_lock); |
| 36 | static int recovery_phase; | 36 | static int recovery_phase; |
| 37 | static const unsigned long recovery_delay[] = { 3, 30, 300 }; | 37 | static const unsigned long recovery_delay[] = { 3, 30, 300 }; |
| 38 | 38 | ||
| @@ -1535,7 +1535,7 @@ static int recovery_check(struct device *dev, void *data) | |||
| 1535 | return 0; | 1535 | return 0; |
| 1536 | } | 1536 | } |
| 1537 | 1537 | ||
| 1538 | static void recovery_func(unsigned long data) | 1538 | static void recovery_work_func(struct work_struct *unused) |
| 1539 | { | 1539 | { |
| 1540 | int redo = 0; | 1540 | int redo = 0; |
| 1541 | 1541 | ||
| @@ -1553,6 +1553,17 @@ static void recovery_func(unsigned long data) | |||
| 1553 | CIO_MSG_EVENT(2, "recovery: end\n"); | 1553 | CIO_MSG_EVENT(2, "recovery: end\n"); |
| 1554 | } | 1554 | } |
| 1555 | 1555 | ||
| 1556 | static DECLARE_WORK(recovery_work, recovery_work_func); | ||
| 1557 | |||
| 1558 | static void recovery_func(unsigned long data) | ||
| 1559 | { | ||
| 1560 | /* | ||
| 1561 | * We can't do our recovery in softirq context and it's not | ||
| 1562 | * performance critical, so we schedule it. | ||
| 1563 | */ | ||
| 1564 | schedule_work(&recovery_work); | ||
| 1565 | } | ||
| 1566 | |||
| 1556 | void ccw_device_schedule_recovery(void) | 1567 | void ccw_device_schedule_recovery(void) |
| 1557 | { | 1568 | { |
| 1558 | unsigned long flags; | 1569 | unsigned long flags; |
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 097fc0967e9d..2b5bfb7c69e5 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | 32 | ||
| 33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
| 34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
| 35 | 35 | #include <linux/delay.h> | |
| 36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
| 37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
| 38 | #include <linux/proc_fs.h> | 38 | #include <linux/proc_fs.h> |
| @@ -1215,9 +1215,6 @@ tiqdio_is_inbound_q_done(struct qdio_q *q) | |||
| 1215 | 1215 | ||
| 1216 | if (!no_used) | 1216 | if (!no_used) |
| 1217 | return 1; | 1217 | return 1; |
| 1218 | if (!q->siga_sync && !irq->is_qebsm) | ||
| 1219 | /* we'll check for more primed buffers in qeth_stop_polling */ | ||
| 1220 | return 0; | ||
| 1221 | if (irq->is_qebsm) { | 1218 | if (irq->is_qebsm) { |
| 1222 | count = 1; | 1219 | count = 1; |
| 1223 | start_buf = q->first_to_check; | 1220 | start_buf = q->first_to_check; |
| @@ -3332,13 +3329,7 @@ qdio_activate(struct ccw_device *cdev, int flags) | |||
| 3332 | } | 3329 | } |
| 3333 | } | 3330 | } |
| 3334 | 3331 | ||
| 3335 | wait_event_interruptible_timeout(cdev->private->wait_q, | 3332 | msleep(QDIO_ACTIVATE_TIMEOUT); |
| 3336 | ((irq_ptr->state == | ||
| 3337 | QDIO_IRQ_STATE_STOPPED) || | ||
| 3338 | (irq_ptr->state == | ||
| 3339 | QDIO_IRQ_STATE_ERR)), | ||
| 3340 | QDIO_ACTIVATE_TIMEOUT); | ||
| 3341 | |||
| 3342 | switch (irq_ptr->state) { | 3333 | switch (irq_ptr->state) { |
| 3343 | case QDIO_IRQ_STATE_STOPPED: | 3334 | case QDIO_IRQ_STATE_STOPPED: |
| 3344 | case QDIO_IRQ_STATE_ERR: | 3335 | case QDIO_IRQ_STATE_ERR: |
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 37870e4e938e..da8a272fd75b 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
| @@ -57,10 +57,10 @@ | |||
| 57 | of the queue to 0 */ | 57 | of the queue to 0 */ |
| 58 | 58 | ||
| 59 | #define QDIO_ESTABLISH_TIMEOUT (1*HZ) | 59 | #define QDIO_ESTABLISH_TIMEOUT (1*HZ) |
| 60 | #define QDIO_ACTIVATE_TIMEOUT (5*HZ) | ||
| 61 | #define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ) | 60 | #define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ) |
| 62 | #define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ) | 61 | #define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ) |
| 63 | #define QDIO_FORCE_CHECK_TIMEOUT (10*HZ) | 62 | #define QDIO_FORCE_CHECK_TIMEOUT (10*HZ) |
| 63 | #define QDIO_ACTIVATE_TIMEOUT (5) /* 5 ms */ | ||
| 64 | 64 | ||
| 65 | enum qdio_irq_states { | 65 | enum qdio_irq_states { |
| 66 | QDIO_IRQ_STATE_INACTIVE, | 66 | QDIO_IRQ_STATE_INACTIVE, |
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index ab83c844d04c..965394e69452 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h | |||
| @@ -456,16 +456,18 @@ static inline unsigned long __ffz_word_loop(const unsigned long *addr, | |||
| 456 | 456 | ||
| 457 | asm volatile( | 457 | asm volatile( |
| 458 | #ifndef __s390x__ | 458 | #ifndef __s390x__ |
| 459 | " ahi %1,31\n" | 459 | " ahi %1,-1\n" |
| 460 | " srl %1,5\n" | 460 | " sra %1,5\n" |
| 461 | " jz 1f\n" | ||
| 461 | "0: c %2,0(%0,%3)\n" | 462 | "0: c %2,0(%0,%3)\n" |
| 462 | " jne 1f\n" | 463 | " jne 1f\n" |
| 463 | " la %0,4(%0)\n" | 464 | " la %0,4(%0)\n" |
| 464 | " brct %1,0b\n" | 465 | " brct %1,0b\n" |
| 465 | "1:\n" | 466 | "1:\n" |
| 466 | #else | 467 | #else |
| 467 | " aghi %1,63\n" | 468 | " aghi %1,-1\n" |
| 468 | " srlg %1,%1,6\n" | 469 | " srag %1,%1,6\n" |
| 470 | " jz 1f\n" | ||
| 469 | "0: cg %2,0(%0,%3)\n" | 471 | "0: cg %2,0(%0,%3)\n" |
| 470 | " jne 1f\n" | 472 | " jne 1f\n" |
| 471 | " la %0,8(%0)\n" | 473 | " la %0,8(%0)\n" |
| @@ -491,16 +493,18 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr, | |||
| 491 | 493 | ||
| 492 | asm volatile( | 494 | asm volatile( |
| 493 | #ifndef __s390x__ | 495 | #ifndef __s390x__ |
| 494 | " ahi %1,31\n" | 496 | " ahi %1,-1\n" |
| 495 | " srl %1,5\n" | 497 | " sra %1,5\n" |
| 498 | " jz 1f\n" | ||
| 496 | "0: c %2,0(%0,%3)\n" | 499 | "0: c %2,0(%0,%3)\n" |
| 497 | " jne 1f\n" | 500 | " jne 1f\n" |
| 498 | " la %0,4(%0)\n" | 501 | " la %0,4(%0)\n" |
| 499 | " brct %1,0b\n" | 502 | " brct %1,0b\n" |
| 500 | "1:\n" | 503 | "1:\n" |
| 501 | #else | 504 | #else |
| 502 | " aghi %1,63\n" | 505 | " aghi %1,-1\n" |
| 503 | " srlg %1,%1,6\n" | 506 | " srag %1,%1,6\n" |
| 507 | " jz 1f\n" | ||
| 504 | "0: cg %2,0(%0,%3)\n" | 508 | "0: cg %2,0(%0,%3)\n" |
| 505 | " jne 1f\n" | 509 | " jne 1f\n" |
| 506 | " la %0,8(%0)\n" | 510 | " la %0,8(%0)\n" |
