diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-19 11:04:23 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-19 11:04:23 -0500 |
commit | aa3f98037ce3bcf850bb41f7530754d27481a792 (patch) | |
tree | aa539f1e52ea35f7c9f7a3e6e2171d72863e51d4 | |
parent | f6c427663a158056cd8ca71c01f30653e4b313f7 (diff) | |
parent | e5fa443ea05f71b5253818890c6d32174cbab36f (diff) |
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
[S390] qdio: FCP/SCSI write I/O stagnates on LPAR
[S390] Fix futex_atomic_cmpxchg_std inline assembly.
[S390] dcss: Fix Unlikely(x) != y
[S390] sclp: clean up send/receive naming scheme
[S390] etr: fix compile error on !SMP
[S390] qdio: fix qdio_activate timeout handling.
[S390] Initialize per cpu lowcores on cpu hotplug.
[S390] find bit corner case.
[S390] dasd: fix locking in __dasd_device_process_final_queue
[S390] Make sure enabled wait psw is loaded in default_idle.
[S390] Let NR_CPUS default to 32/64 on s390/s390x.
[S390] cio: Do timed recovery on workqueue.
[S390] cio: Remember to initialize recovery_lock.
-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 92a4f7b4323..b21444b681b 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 a6a4729e0e9..1c59ec161cf 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 85060659fb1..818bd09c026 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 3bbac1293be..76a5dd1b4ce 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 28c4500a58d..d2ffbadb51a 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 d984e0fae63..ccf46c96adb 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 3faf0538b32..e6c94dbfdea 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 25629b92dec..2c7a1ee6b04 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 aa8186d18ae..bac80e856f9 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 9dc77f14fa5..b8f35bc52b7 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 41617032afd..9f37456222e 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 ad7195d3de0..da09781b32f 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 f47f4a768be..92f52720179 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 d35dc3f25d0..fec004f62bc 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 097fc0967e9..2b5bfb7c69e 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 37870e4e938..da8a272fd75 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 ab83c844d04..965394e6945 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" |