parisc: ensure broadcast tlb purge runs single threaded
The TLB flushing functions on hppa, which causes PxTLB broadcasts on the system bus, needs to be protected by irq-safe spinlocks to avoid irq handlers to deadlock the kernel. The deadlocks only happened during I/O intensive loads and triggered pretty seldom, which is why this bug went so long unnoticed. Signed-off-by: Helge Deller <deller@gmx.de> [edited to use spin_lock_irqsave on UP as well since we'd been locking there all this time anyway, --kyle] Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>
This commit is contained in:
committed by
Kyle McMartin
parent
84be31be37
commit
e82a3b7512
@@ -90,12 +90,14 @@ static inline int map_pte_uncached(pte_t * pte,
|
||||
if (end > PMD_SIZE)
|
||||
end = PMD_SIZE;
|
||||
do {
|
||||
unsigned long flags;
|
||||
|
||||
if (!pte_none(*pte))
|
||||
printk(KERN_ERR "map_pte_uncached: page already exists\n");
|
||||
set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
|
||||
purge_tlb_start();
|
||||
purge_tlb_start(flags);
|
||||
pdtlb_kernel(orig_vaddr);
|
||||
purge_tlb_end();
|
||||
purge_tlb_end(flags);
|
||||
vaddr += PAGE_SIZE;
|
||||
orig_vaddr += PAGE_SIZE;
|
||||
(*paddr_ptr) += PAGE_SIZE;
|
||||
@@ -168,11 +170,13 @@ static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr,
|
||||
if (end > PMD_SIZE)
|
||||
end = PMD_SIZE;
|
||||
do {
|
||||
unsigned long flags;
|
||||
pte_t page = *pte;
|
||||
|
||||
pte_clear(&init_mm, vaddr, pte);
|
||||
purge_tlb_start();
|
||||
purge_tlb_start(flags);
|
||||
pdtlb_kernel(orig_vaddr);
|
||||
purge_tlb_end();
|
||||
purge_tlb_end(flags);
|
||||
vaddr += PAGE_SIZE;
|
||||
orig_vaddr += PAGE_SIZE;
|
||||
pte++;
|
||||
|
Reference in New Issue
Block a user