Skip to content

Commit 61e150f

Browse files
committed
parisc: Fix flush_dcache_page() for usage from irq context
Since at least kernel 6.1, flush_dcache_page() is called with IRQs disabled, e.g. from aio_complete(). But the current implementation for flush_dcache_page() on parisc unintentionally re-enables IRQs, which may lead to deadlocks. Fix it by using xa_lock_irqsave() and xa_unlock_irqrestore() for the flush_dcache_mmap_*lock() macros instead. Cc: [email protected] Cc: [email protected] # 5.18+ Signed-off-by: Helge Deller <[email protected]>
1 parent 6888ff0 commit 61e150f

File tree

2 files changed

+7
-2
lines changed

2 files changed

+7
-2
lines changed

arch/parisc/include/asm/cacheflush.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ void flush_dcache_page(struct page *page);
4848

4949
#define flush_dcache_mmap_lock(mapping) xa_lock_irq(&mapping->i_pages)
5050
#define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages)
51+
#define flush_dcache_mmap_lock_irqsave(mapping, flags) \
52+
xa_lock_irqsave(&mapping->i_pages, flags)
53+
#define flush_dcache_mmap_unlock_irqrestore(mapping, flags) \
54+
xa_unlock_irqrestore(&mapping->i_pages, flags)
5155

5256
#define flush_icache_page(vma,page) do { \
5357
flush_kernel_dcache_page_addr(page_address(page)); \

arch/parisc/kernel/cache.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ void flush_dcache_page(struct page *page)
399399
unsigned long offset;
400400
unsigned long addr, old_addr = 0;
401401
unsigned long count = 0;
402+
unsigned long flags;
402403
pgoff_t pgoff;
403404

404405
if (mapping && !mapping_mapped(mapping)) {
@@ -420,7 +421,7 @@ void flush_dcache_page(struct page *page)
420421
* to flush one address here for them all to become coherent
421422
* on machines that support equivalent aliasing
422423
*/
423-
flush_dcache_mmap_lock(mapping);
424+
flush_dcache_mmap_lock_irqsave(mapping, flags);
424425
vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
425426
offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
426427
addr = mpnt->vm_start + offset;
@@ -460,7 +461,7 @@ void flush_dcache_page(struct page *page)
460461
}
461462
WARN_ON(++count == 4096);
462463
}
463-
flush_dcache_mmap_unlock(mapping);
464+
flush_dcache_mmap_unlock_irqrestore(mapping, flags);
464465
}
465466
EXPORT_SYMBOL(flush_dcache_page);
466467

0 commit comments

Comments
 (0)