s390 bug fixes for 2.6.26-rc4
Subsystems (3)
cover s390 bug fixes for 2.6.26-rc4
Greetings,
another batch of s390 patches for 2.6.26, all of them bug fixes.
The shortlog:
Christian Borntraeger (1):
[S390] s390 types: make dma_addr_t 64 bit capable
Gerald Schaefer (1):
[S390] appldata: prevent cpu hotplug when walking cpu_online_map.
Hans-Joachim Picht (1):
[S390] fix sparsemem related compile error with allnoconfig on s390
Heiko Carstens (3):
[S390] Fix section mismatch warnings. [S390] showmem: Only walk spanned pages. [S390] sclp_vt220: fix scheduling while atomic bug.
Martin Schwidefsky (3):
[S390] 3270: fix race with stack local wait_queue_head_t. [S390] tape: fix race with stack local wait_queue_head_t. [S390] disassembler: fix idte instruction format.
Michael Holzheu (1):
[S390] tape: Fix race condition in tape block device driver
Stefan Haberland (1):
[S390] dasd: use a generic wait_queue for sleep_on
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 1/11 fix sparsemem related compile error with allnoconfig on s390
From: Hans-Joachim Picht <[email protected]>
On s390 make allnoconfig fails with the following build error:
arch/s390/mm/init.c: In function 'show_mem':arch/s390/mm/init.c:55: error: implicit declaration of function 'pfn_valid' make[1]: *** [arch/s390/mm/init.o] Error 1
make: *** [arch/s390/mm] Error 2
This problem can by fixed ensuring that ARCH_SELECT_MEMORY_MODEL is always turned on.
---
arch/s390/Kconfig | 3 +++ 1 file changed, 3 insertions(+)
arch/s390/Kconfig +3 -0
@@ -308,6 +308,9 @@ config ARCH_SPARSEMEM_ENABLE config ARCH_SPARSEMEM_DEFAULT def_bool y +config ARCH_SELECT_MEMORY_MODEL + def_bool y + source "mm/Kconfig" comment "I/O subsystem configuration"
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 2/11 tape: Fix race condition in tape block device driver
In reply to Martin SchwidefskyFrom: Michael Holzheu <[email protected]>
Due to incorrect function call sequence it can happen that a tape block request is finished before the request is taken from the block request queue.
The following sequence leads to that condition:
* tapeblock_start_request() -> start CCW program
* Request finishes -> IO interrupt
* tapeblock_end_request()
* end_that_request_last()
If blkdev_dequeue_request() has not been called before end_that_request_last(), a kernel bug is triggered in end_that_request_last() because the request is still queued. To solve that problem blkdev_dequeue_request() has to be called before starting the CCW program.
---
drivers/s390/char/tape_block.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/s390/char/tape_block.c +2 -2
@@ -179,11 +179,11 @@ tapeblock_requeue(struct work_struct *wotapeblock_end_request (req, -EIO );continue ; } +blkdev_dequeue_request (req); + nr_queued++;spin_unlock_irq (&device->blk_data.request_queue_lock); rc =tapeblock_start_request (device, req);spin_lock_irq (&device->blk_data.request_queue_lock); -blkdev_dequeue_request (req); - nr_queued++; }spin_unlock_irq (&device->blk_data.request_queue_lock);atomic_set (&device->blk_data.requeue_scheduled,0 );
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 3/11 s390 types: make dma_addr_t 64 bit capable
In reply to Martin SchwidefskyFrom: Christian Borntraeger <[email protected]>
virtio tests with guests larger than 4 GB revealed that the dma_addr_t definition for s390 did not make it into the 64bit world. This patch changes the definition on s390 to have an u64 on 64bit and u32 on 32bit systems.
---
include/asm-s390/types.h | 6 ++++++ 1 file changed, 6 insertions(+)
include/asm-s390/types.h +6 -0
@@ -40,7 +40,13 @@ typedef __signed__ long saddr_t; #ifndef __ASSEMBLY__ +typedef u64 dma64_addr_t; +#ifdef __s390x__ +/* DMA addresses come in 32-bit and 64-bit flavours. */ +typedef u64 dma_addr_t; +#else typedef u32 dma_addr_t; +#endif #ifndef __s390x__ typedef union {
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 4/11 Fix section mismatch warnings.
In reply to Martin SchwidefskyFrom: Heiko Carstens <[email protected]>
This fixes the last remaining section mismatch warnings in s390 architecture code. It reveals also a real bug introduced by... me with git commit 2069e978d5a6e7b45d58027e3de7f879b8c5e488 ("[S390] sparsemem vmemmap: initialize memmap.")
Calling the generic vmemmap_alloc_block() function to get initialized memory is a nice idea, however that function is __meminit annotated and therefore the function might be gone if we try to call it later. This can happen if a DCSS segment gets added.
So basically revert the patch and clear the memmap explicitly to fix the original bug.
---
arch/s390/kernel/smp.c | 2 +- arch/s390/mm/vmem.c | 18 +++++++++++++----- drivers/s390/char/sclp_config.c | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-)
arch/s390/kernel/smp.c +1 -1
@@ -1089,7 +1089,7 @@ out:#ifdef CONFIG_HOTPLUG_CPU -int smp_rescan_cpus (void ) +int __ref smp_rescan_cpus (void ) {cpumask_t newcpus;int cpu;
arch/s390/mm/vmem.c +13 -5
@@ -27,12 +27,19 @@ struct memory_segment {static LIST_HEAD (mem_segs); -static pud_t *vmem_pud_alloc (void ) +static void __ref *vmem_alloc_pages (unsigned int order) +{ +if (slab_is_available ()) +return (void *)__get_free_pages (GFP_KERNEL , order); +return alloc_bootmem_pages ((1 << order) *PAGE_SIZE ); +} + +static inline pud_t *vmem_pud_alloc (void ) {pud_t *pud =NULL ;#ifdef CONFIG_64BIT - pud =vmemmap_alloc_block (PAGE_SIZE *4 ,0 ); + pud =vmem_alloc_pages (2 );if (!pud)return NULL ;clear_table ((unsigned long *) pud, _REGION3_ENTRY_EMPTY,PAGE_SIZE *4 );
@@ -40,12 +47,12 @@ static pud_t *vmem_pud_alloc(void)return pud; } -static pmd_t *vmem_pmd_alloc (void ) +static inline pmd_t *vmem_pmd_alloc (void ) {pmd_t *pmd =NULL ;#ifdef CONFIG_64BIT - pmd =vmemmap_alloc_block (PAGE_SIZE *4 ,0 ); + pmd =vmem_alloc_pages (2 );if (!pmd)return NULL ;clear_table ((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY,PAGE_SIZE *4 );
@@ -207,13 +214,14 @@ int __meminit vmemmap_populate(struct paif (pte_none (*pt_dir)) {unsigned long new_page; - new_page =__pa (vmemmap_alloc_block (PAGE_SIZE ,0 )); + new_page =__pa (vmem_alloc_pages (0 ));if (!new_page) goto out; pte =pfn_pte (new_page >>PAGE_SHIFT ,PAGE_KERNEL ); *pt_dir = pte; } } +memset (start,0 , nr *sizeof (struct page )); ret =0 ; out:flush_tlb_kernel_range (start_addr, end_addr);
drivers/s390/char/sclp_config.c +1 -1
@@ -40,7 +40,7 @@ static void sclp_cpu_capability_notify(sput_online_cpus (); } -static void sclp_cpu_change_notify (struct work_struct *work) +static void __ref sclp_cpu_change_notify (struct work_struct *work) {smp_rescan_cpus (); }
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 5/11 appldata: prevent cpu hotplug when walking cpu_online_map.
In reply to Martin SchwidefskyFrom: Gerald Schaefer <[email protected]>
Use get_online_cpus() to prevent cpu hotplug in situations where for_each_online_cpu() is called.
---
arch/s390/appldata/appldata_base.c | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/s390/appldata/appldata_base.c +8 -0
@@ -130,6 +130,7 @@ static void appldata_work_fn(struct workP_DEBUG (" -= Work Queue =-\n" ); i =0 ; +get_online_cpus ();spin_lock (&appldata_ops_lock);list_for_each (lh, &appldata_ops_list) { ops = list_entry(lh, struct appldata_ops, list);
@@ -140,6 +141,7 @@ static void appldata_work_fn(struct work } }spin_unlock (&appldata_ops_lock); +put_online_cpus (); }/*
@@ -266,12 +268,14 @@ appldata_timer_handler(ctl_table *ctl, i len = *lenp;if (copy_from_user (buf, buffer, len >sizeof (buf) ?sizeof (buf) : len))return -EFAULT ; +get_online_cpus ();spin_lock (&appldata_timer_lock);if (buf[0 ] =='1' )__appldata_vtimer_setup (APPLDATA_ADD_TIMER );else if (buf[0 ] =='0' )__appldata_vtimer_setup (APPLDATA_DEL_TIMER );spin_unlock (&appldata_timer_lock); +put_online_cpus (); out: *lenp = len; *ppos += len;
@@ -314,10 +318,12 @@ appldata_interval_handler(ctl_table *ctlreturn -EINVAL ; } +get_online_cpus ();spin_lock (&appldata_timer_lock); appldata_interval = interval;__appldata_vtimer_setup (APPLDATA_MOD_TIMER );spin_unlock (&appldata_timer_lock); +put_online_cpus ();P_INFO ("Monitoring CPU interval set to %u milliseconds.\n" , interval);
@@ -556,8 +562,10 @@ static int __init appldata_init(void)return -ENOMEM ; } +get_online_cpus ();for_each_online_cpu (i)appldata_online_cpu (i); +put_online_cpus ();/* Register cpu hotplug notifier */ register_hotcpu_notifier (&appldata_nb);
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 6/11 showmem: Only walk spanned pages.
In reply to Martin SchwidefskyFrom: Heiko Carstens <[email protected]>
Convert show_mem() so its nearly the same as on x86/powerpc. Gives us proper locking and we get also rid of the only use of max_mapnr. Also the number of pages was contained in an int which might not be sufficient not too far in the future.
---
arch/s390/mm/init.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-)
arch/s390/mm/init.c +23 -19
@@ -44,30 +44,34 @@ char empty_zero_page[PAGE_SIZE] __attrivoid show_mem (void ) { -int i, total =0 , reserved =0 ; -int shared =0 , cached =0 ; +unsigned long i, total =0 , reserved =0 ; +unsigned long shared =0 , cached =0 ; +unsigned long flags;struct page *page; +pg_data_t *pgdat;printk ("Mem-info:\n" );show_free_areas (); - i = max_mapnr; -while (i-- >0 ) { -if (!pfn_valid (i)) -continue ; - page =pfn_to_page (i); - total++; -if (PageReserved (page)) - reserved++; -else if (PageSwapCache (page)) - cached++; -else if (page_count (page)) - shared +=page_count (page) -1 ; +for_each_online_pgdat (pgdat) { +pgdat_resize_lock (pgdat, &flags); +for (i =0 ; i < pgdat->node_spanned_pages; i++) { +if (!pfn_valid (pgdat->node_start_pfn + i)) +continue ; + page =pfn_to_page (pgdat->node_start_pfn + i); + total++; +if (PageReserved (page)) + reserved++; +else if (PageSwapCache (page)) + cached++; +else if (page_count (page)) + shared +=page_count (page) -1 ; + } +pgdat_resize_unlock (pgdat, &flags); } -printk ("%d pages of RAM\n" , total); -printk ("%d reserved pages\n" , reserved); -printk ("%d pages shared\n" , shared); -printk ("%d pages swap cached\n" , cached); - +printk ("%ld pages of RAM\n" , total); +printk ("%ld reserved pages\n" , reserved); +printk ("%ld pages shared\n" , shared); +printk ("%ld pages swap cached\n" , cached);printk ("%lu pages dirty\n" ,global_page_state (NR_FILE_DIRTY ));printk ("%lu pages writeback\n" ,global_page_state (NR_WRITEBACK ));printk ("%lu pages mapped\n" ,global_page_state (NR_FILE_MAPPED ));
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
Re: [patch 06/11] showmem: Only walk spanned pages.
Hi,
Quoted 72 lines · Martin Schwidefsky
From: Heiko Carstens <[email protected]>
Convert
show_mem()so its nearly the same as on x86/powerpc. Gives us proper locking and we get also rid of the only use ofmax_mapnr. Also the number of pages was contained in an int which might not be sufficient not too far in the future.Signed-off-by Heiko Carstens <[email protected]>Signed-off-by Martin Schwidefsky <[email protected]>---
arch/s390/mm/init.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-)Index:
quilt-2.6/arch/s390/mm/init.c
===================================================================arch/s390/mm/init.c +23
-19@@ -44,30 +44,34 @@ char empty_zero_page[PAGE_SIZE] __attrivoid show_mem (void ) { -int i, total =0 , reserved =0 ; -int shared =0 , cached =0 ; +unsigned long i, total =0 , reserved =0 ; +unsigned long shared =0 , cached =0 ; +unsigned long flags;struct page *page; +pg_data_t *pgdat;printk ("Mem-info:\n" );show_free_areas (); - i = max_mapnr; -while (i-- >0 ) { -if (!pfn_valid (i)) -continue ; - page =pfn_to_page (i); - total++; -if (PageReserved (page)) - reserved++; -else if (PageSwapCache (page)) - cached++; -else if (page_count (page)) - shared +=page_count (page) -1 ; +for_each_online_pgdat (pgdat) { +pgdat_resize_lock (pgdat, &flags); +for (i =0 ; i < pgdat->node_spanned_pages; i++) { +if (!pfn_valid (pgdat->node_start_pfn + i)) +continue ; + page =pfn_to_page (pgdat->node_start_pfn + i); + total++; +if (PageReserved (page)) + reserved++; +else if (PageSwapCache (page)) + cached++; +else if (page_count (page)) + shared +=page_count (page) -1 ; + } +pgdat_resize_unlock (pgdat, &flags); } -printk ("%d pages of RAM\n" , total); -printk ("%d reserved pages\n" , reserved); -printk ("%d pages shared\n" , shared); -printk ("%d pages swap cached\n" , cached); - +printk ("%ld pages of RAM\n" , total); +printk ("%ld reserved pages\n" , reserved); +printk ("%ld pages shared\n" , shared); +printk ("%ld pages swap cached\n" , cached);printk ("%lu pages dirty\n" ,global_page_state (NR_FILE_DIRTY ));printk ("%lu pages writeback\n" ,global_page_state (NR_WRITEBACK ));
Quoted 1 line
printk("%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
These are redundant, check show_free_areas().
Hannes
Re: [patch 06/11] showmem: Only walk spanned pages.
Quoted 5 lines · Johannes Weiner
arch/s390/mm/init.c char empty_zero_page[PAGE_SIZE] __attri · line 77
Quoted 3 lines
arch/s390/mm/init.c +0
-0printk ("%lu pages dirty\n" ,global_page_state (NR_FILE_DIRTY ));printk ("%lu pages writeback\n" ,global_page_state (NR_WRITEBACK ));printk ("%lu pages mapped\n" ,global_page_state (NR_FILE_MAPPED ));These are redundant, check
show_free_areas().
Indeed. Removed them. Thanks!
Btw. what's up with your show_mem() cleanup patch series? I thought it would be merged before 2.6.26 and now it isn't even in -mm?
Re: [patch 06/11] showmem: Only walk spanned pages.
Hi,
Quoted 11 lines · Heiko Carstens
Quoted 5 lines · Johannes Weiner
arch/s390/mm/init.c char empty_zero_page[PAGE_SIZE] __attri · line 77
Quoted 3 lines
arch/s390/mm/init.c +0
-0printk ("%lu pages dirty\n" ,global_page_state (NR_FILE_DIRTY ));printk ("%lu pages writeback\n" ,global_page_state (NR_WRITEBACK ));printk ("%lu pages mapped\n" ,global_page_state (NR_FILE_MAPPED ));These are redundant, check
show_free_areas().Indeed. Removed them. Thanks!
Btw. what's up with your
show_mem()cleanup patch series? I thought it would be merged before 2.6.26 and now it isn't even in -mm?
It interfered with my stupid `remove free swap space display' series which is not yet completely in mainline (and no more in -mm). I wanted to wait until it trickled in but I think I will include the remaining patches into the generic show_mem series and send them out soon, obsoleting the old series...
Remaining unpatched show_mem()s in mainline are are um, sparc, sh, m32r, alpha, sparc64 and xtensa.
Hannes
PATCH 7/11 sclp_vt220: fix scheduling while atomic bug.
In reply to Martin SchwidefskyFrom: Heiko Carstens <[email protected]>
The driver incorrectly assumed that putchar will only be called from schedulable process context and therefore blocked and waited if no free output buffers where available.
Since putchar may also be called from BH context this may lead to deadlocks.
To fix this just return the number of characters accepted and let the upper layer handle the rest.
The console write function will busy wait (sclp_sync_wait) until a buffer is available again.
---
drivers/s390/char/sclp_vt220.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-)
drivers/s390/char/sclp_vt220.c +7 -20
@@ -71,9 +71,6 @@ static struct list_head sclp_vt220_outqu/* Number of requests in outqueue */ static int sclp_vt220_outqueue_count; -/* Wait queue used to delay write requests while we've run out of buffers */ -static wait_queue_head_t sclp_vt220_waitq; -/* Timer used for delaying write requests to merge subsequent messages into * a single buffer */ static struct timer_list sclp_vt220_timer;
@@ -133,7 +130,6 @@ sclp_vt220_process_queue(struct sclp_vt2 }while (request &&__sclp_vt220_emit (request));if (request ==NULL && sclp_vt220_flush_later)sclp_vt220_emit_current (); -wake_up (&sclp_vt220_waitq);/* Check if the tty needs a wake up call */ if (sclp_vt220_tty !=NULL ) {tty_wakeup (sclp_vt220_tty);
@@ -383,7 +379,7 @@ sclp_vt220_timeout(unsigned long data)*/ static int __sclp_vt220_write (const unsigned char *buf,int count,int do_schedule, -int convertlf,int may_schedule) +int convertlf,int may_fail) {unsigned long flags;void *page;
@@ -395,15 +391,14 @@ __sclp_vt220_write(const unsigned char * overall_written =0 ;spin_lock_irqsave (&sclp_vt220_lock, flags); do { - /* Create a sclp output buffer if none exists yet */ + /* Create an sclp output buffer if none exists yet */ if (sclp_vt220_current_request == NULL) { while (list_empty(&sclp_vt220_empty)) { spin_unlock_irqrestore(&sclp_vt220_lock, flags); - if (in_interrupt() || !may_schedule) - sclp_sync_wait(); + if (may_fail) + goto out; else - wait_event(sclp_vt220_waitq, - !list_empty(&sclp_vt220_empty)); + sclp_sync_wait(); spin_lock_irqsave(&sclp_vt220_lock, flags); } page = (void *) sclp_vt220_empty.next;
@@ -437,6 +432,7 @@ __sclp_vt220_write(const unsigned char *add_timer (&sclp_vt220_timer); }spin_unlock_irqrestore (&sclp_vt220_lock, flags); +out:return overall_written; }
@@ -520,19 +516,11 @@ sclp_vt220_close(struct tty_struct *tty,* character to the tty device. If the kernel uses this routine, * it must call the flush_chars() routine (if defined) when it is * done stuffing characters into the driver. -* -* NOTE: include/linux/tty_driver.h specifies that a character should be -* ignored if there is no room in the queue. This driver implements a different -* semantic in that it will block when there is no more room left. -* -* FIXME: putchar can currently be called from BH and other non blocking -* handlers so this semantic isn't a good idea. */ static int sclp_vt220_put_char (struct tty_struct *tty,unsigned char ch) { -__sclp_vt220_write (&ch,1 ,0 ,0 ,1 ); -return 1 ; +return __sclp_vt220_write (&ch,1 ,0 ,0 ,1 ); }/*
@@ -653,7 +641,6 @@ static int __init __sclp_vt220_init(voidspin_lock_init (&sclp_vt220_lock);INIT_LIST_HEAD (&sclp_vt220_empty);INIT_LIST_HEAD (&sclp_vt220_outqueue); -init_waitqueue_head (&sclp_vt220_waitq);init_timer (&sclp_vt220_timer); sclp_vt220_current_request =NULL ; sclp_vt220_buffered_chars =0 ;
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 8/11 dasd: use a generic wait_queue for sleep_on
In reply to Martin SchwidefskyFrom: Stefan Haberland <[email protected]>
Use a generic wait_queue to prevent the wait_queue in dasd_sleep_on_ functions from being referenced by callback_data while it does not exist any more.
---
drivers/s390/block/dasd.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
drivers/s390/block/dasd.c +14 -14
@@ -63,6 +63,7 @@ static void dasd_return_cqr_cb(struct da*/ static wait_queue_head_t dasd_init_waitq;static wait_queue_head_t dasd_flush_wq; +static wait_queue_head_t generic_waitq;/* * Allocate memory for a new device structure.
@@ -1151,11 +1152,15 @@ static void __dasd_device_process_final_struct list_head *l, *n;struct dasd_ccw_req *cqr;struct dasd_block *block; +void (*callback)(struct dasd_ccw_req *,void *data); +void *callback_data;list_for_each_safe (l, n, final_queue) { cqr = list_entry(l, struct dasd_ccw_req, devlist);list_del_init (&cqr->devlist); block = cqr->block; + callback = cqr->callback; + callback_data = cqr->callback_data;if (block)spin_lock_bh (&block->queue_lock);switch (cqr->status) {
@@ -1176,7 +1181,7 @@ static void __dasd_device_process_final_BUG (); }if (cqr->callback !=NULL ) - (cqr->callback)(cqr, cqr->callback_data); + (callback)(cqr, callback_data);if (block)spin_unlock_bh (&block->queue_lock); }
@@ -1406,17 +1411,15 @@ static inline int _wait_for_wakeup(struc*/ int dasd_sleep_on (struct dasd_ccw_req *cqr) { -wait_queue_head_t wait_q;struct dasd_device *device;int rc; device = cqr->startdev; -init_waitqueue_head (&wait_q); cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &wait_q; + cqr->callback_data = (void *) &generic_waitq;dasd_add_request_tail (cqr); -wait_event (wait_q,_wait_for_wakeup (cqr)); +wait_event (generic_waitq,_wait_for_wakeup (cqr));/* Request status is either done or failed. */ rc = (cqr->status ==DASD_CQR_DONE ) ?0 : -EIO ;
@@ -1429,20 +1432,18 @@ int dasd_sleep_on(struct dasd_ccw_req *c*/ int dasd_sleep_on_interruptible (struct dasd_ccw_req *cqr) { -wait_queue_head_t wait_q;struct dasd_device *device;int rc; device = cqr->startdev; -init_waitqueue_head (&wait_q); cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &wait_q; + cqr->callback_data = (void *) &generic_waitq;dasd_add_request_tail (cqr); - rc =wait_event_interruptible (wait_q,_wait_for_wakeup (cqr)); + rc =wait_event_interruptible (generic_waitq,_wait_for_wakeup (cqr));if (rc == -ERESTARTSYS ) {dasd_cancel_req (cqr);/* wait (non-interruptible) for final status */ -wait_event (wait_q,_wait_for_wakeup (cqr)); +wait_event (generic_waitq,_wait_for_wakeup (cqr)); } rc = (cqr->status ==DASD_CQR_DONE ) ?0 : -EIO ;return rc;
@@ -1466,7 +1467,6 @@ static inline int _dasd_term_running_cqrint dasd_sleep_on_immediatly (struct dasd_ccw_req *cqr) { -wait_queue_head_t wait_q;struct dasd_device *device;int rc;
@@ -1478,9 +1478,8 @@ int dasd_sleep_on_immediatly(struct dasdreturn rc; } -init_waitqueue_head (&wait_q); cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &wait_q; + cqr->callback_data = (void *) &generic_waitq; cqr->status =DASD_CQR_QUEUED ;list_add (&cqr->devlist, &device->ccw_queue);
@@ -1489,7 +1488,7 @@ int dasd_sleep_on_immediatly(struct dasdspin_unlock_irq (get_ccwdev_lock (device->cdev)); -wait_event (wait_q,_wait_for_wakeup (cqr)); +wait_event (generic_waitq,_wait_for_wakeup (cqr));/* Request status is either done or failed. */ rc = (cqr->status ==DASD_CQR_DONE ) ?0 : -EIO ;
@@ -2430,6 +2429,7 @@ static int __init dasd_init(void)init_waitqueue_head (&dasd_init_waitq);init_waitqueue_head (&dasd_flush_wq); +init_waitqueue_head (&generic_waitq);/* register 'common' DASD debug area, used for all DBF_XXX calls */ dasd_debug_area =debug_register ("dasd" ,1 ,1 ,8 *sizeof (long ));
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 9/11 3270: fix race with stack local wait_queue_head_t.
In reply to Martin SchwidefskyFrom: Martin Schwidefsky <[email protected]>
A wait_event call with a stack local wait_queue_head_t structure that is used to do the wake up for the wait_event is inherently racy. After the wait_event finished the wake_up call might not have completed yet. Remove the stack local wait_queue_head_t from raw3270_start_init and use the global raw3270_wait_queue instead.
---
drivers/s390/char/raw3270.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/s390/char/raw3270.c +4 -5
@@ -549,7 +549,6 @@ raw3270_start_init(struct raw3270 *rp, s struct raw3270_request *rq) {unsigned long flags; -wait_queue_head_t wq;int rc;#ifdef CONFIG_TN3270_CONSOLE
@@ -566,20 +565,20 @@ raw3270_start_init(struct raw3270 *rp, sreturn rq->rc; }#endif -init_waitqueue_head (&wq); rq->callback = raw3270_wake_init; - rq->callback_data = &wq; + rq->callback_data = &raw3270_wait_queue;spin_lock_irqsave (get_ccwdev_lock (view->dev->cdev), flags); rc =__raw3270_start (rp, view, rq);spin_unlock_irqrestore (get_ccwdev_lock (view->dev->cdev), flags);if (rc)return rc;/* Now wait for the completion. */ - rc =wait_event_interruptible (wq,raw3270_request_final (rq)); + rc =wait_event_interruptible (raw3270_wait_queue, +raw3270_request_final (rq));if (rc == -ERESTARTSYS ) {/* Interrupted by a signal. */ raw3270_halt_io (view->dev, rq);/* No wait for the halt to complete. */ -wait_event (wq,raw3270_request_final (rq)); +wait_event (raw3270_wait_queue,raw3270_request_final (rq));return -ERESTARTSYS ; }return rq->rc;
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 10/11 tape: fix race with stack local wait_queue_head_t.
In reply to Martin SchwidefskyFrom: Martin Schwidefsky <[email protected]>
A wait_event call with a stack local wait_queue_head_t structure that is used to do the wake up for the wait_event is inherently racy. After the wait_event finished the wake_up call might not have completed yet. Replace the stack local wait_queue_head_t in tape_do_io and tape_do_io_interruptible with a per device wait queue.
---
drivers/s390/char/tape.h | 3 +++ drivers/s390/char/tape_core.c | 16 +++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-)
drivers/s390/char/tape_core.c +7 -9
@@ -449,6 +449,7 @@ tape_alloc_device(void)INIT_LIST_HEAD (&device->req_queue);INIT_LIST_HEAD (&device->node);init_waitqueue_head (&device->state_change_wq); +init_waitqueue_head (&device->wait_queue); device->tape_state =TS_INIT ; device->medium_state =MS_UNKNOWN ; *device->modeset_byte =0 ;
@@ -954,21 +955,19 @@ __tape_wake_up(struct tape_request *requint tape_do_io (struct tape_device *device,struct tape_request *request) { -wait_queue_head_t wq;int rc; -init_waitqueue_head (&wq);spin_lock_irq (get_ccwdev_lock (device->cdev));/* Setup callback */ request->callback = __tape_wake_up; - request->callback_data = &wq; + request->callback_data = &device->wait_queue;/* Add request to request queue and try to start it. */ rc =__tape_start_request (device, request);spin_unlock_irq (get_ccwdev_lock (device->cdev));if (rc)return rc;/* Request added to the queue. Wait for its completion. */ -wait_event (wq, (request->callback ==NULL )); +wait_event (device->wait_queue, (request->callback ==NULL ));/* Get rc from request */ return request->rc; }
@@ -989,20 +988,19 @@ int tape_do_io_interruptible(struct tape_device *device, struct tape_request *request) { - wait_queue_head_t wq; int rc; -init_waitqueue_head (&wq);spin_lock_irq (get_ccwdev_lock (device->cdev));/* Setup callback */ request->callback = __tape_wake_up_interruptible; - request->callback_data = &wq; + request->callback_data = &device->wait_queue; rc =__tape_start_request (device, request);spin_unlock_irq (get_ccwdev_lock (device->cdev));if (rc)return rc;/* Request added to the queue. Wait for its completion. */ - rc =wait_event_interruptible (wq, (request->callback ==NULL )); + rc =wait_event_interruptible (device->wait_queue, + (request->callback ==NULL ));if (rc != -ERESTARTSYS )/* Request finished normally. */ return request->rc;
@@ -1015,7 +1013,7 @@ tape_do_io_interruptible(struct tape_dev/* Wait for the interrupt that acknowledges the halt. */ do { rc =wait_event_interruptible ( - wq, + device->wait_queue, (request->callback ==NULL ) ); }while (rc == -ERESTARTSYS );
drivers/s390/char/tape.h +3 -0
@@ -231,6 +231,9 @@ struct tape_device {/* Request queue. */ struct list_head req_queue; +/* Request wait queue. */ +wait_queue_head_t wait_queue; +/* Each tape device has (currently) two minor numbers. */ int first_minor;
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 11/11 disassembler: fix idte instruction format.
In reply to Martin SchwidefskyFrom: Martin Schwidefsky <[email protected]>
The correct instruction format of idte is "idte r1,r3,r2" with r1 at bit 24, r3 at bit 16 and r2 at bit 28.
---
arch/s390/kernel/dis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/dis.c +1 -1
@@ -208,7 +208,7 @@ static const unsigned char formats[][7] [INSTR_RRF_F0FF] = { 0xff, F_16,F_24,F_28,0,0,0 }, /* e.g. madbr */ [INSTR_RRF_FUFF] = { 0xff, F_24,F_16,F_28,U4_20,0,0 },/* e.g. didbr */ [INSTR_RRF_RURR] = { 0xff, R_24,R_28,R_16,U4_20,0,0 },/* e.g. .insn */ - [INSTR_RRF_R0RR] = { 0xff, R_24,R_28,R_16,0,0,0 }, /* e.g. idte */ + [INSTR_RRF_R0RR] = { 0xff, R_24,R_16,R_28,0,0,0 }, /* e.g. idte */ [INSTR_RRF_U0FF] = { 0xff, F_24,U4_16,F_28,0,0,0 }, /* e.g. fixr */ [INSTR_RRF_U0RF] = { 0xff, R_24,U4_16,F_28,0,0,0 }, /* e.g. cfebr */ [INSTR_RRF_M0RR] = { 0xff, R_24,R_28,M_16,0,0,0 }, /* e.g. sske */
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.