aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/sbus.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-05-11 14:37:00 -0400
committerDavid S. Miller <davem@davemloft.net>2005-05-11 14:37:00 -0400
commit4dbc30fb27ac4e647e6efadb382ff7d38c3d368e (patch)
treee2fb7329e60be37e17f133a28ab6a5e77007db32 /arch/sparc64/kernel/sbus.c
parente4fdee8e3b41239242a8f421a28736ef8e08ca55 (diff)
[SPARC64]: Add timeouts to streaming buffer synchronization.
If some hardware error occurs and the flush flag never updates, we will hang forever in these routines. Add a timeout, and print out a diagnostic if it is reached. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/sbus.c')
-rw-r--r--arch/sparc64/kernel/sbus.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 14d9c3a21b9a..d3eca98e1fe7 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -117,19 +117,34 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages
117 117
118#define STRBUF_TAG_VALID 0x02UL 118#define STRBUF_TAG_VALID 0x02UL
119 119
120static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) 120static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
121{ 121{
122 unsigned long n;
123 int limit;
124
122 iommu->strbuf_flushflag = 0UL; 125 iommu->strbuf_flushflag = 0UL;
123 while (npages--) 126 n = npages;
124 upa_writeq(base + (npages << IO_PAGE_SHIFT), 127 while (n--)
128 upa_writeq(base + (n << IO_PAGE_SHIFT),
125 iommu->strbuf_regs + STRBUF_PFLUSH); 129 iommu->strbuf_regs + STRBUF_PFLUSH);
126 130
127 /* Whoopee cushion! */ 131 /* Whoopee cushion! */
128 upa_writeq(__pa(&iommu->strbuf_flushflag), 132 upa_writeq(__pa(&iommu->strbuf_flushflag),
129 iommu->strbuf_regs + STRBUF_FSYNC); 133 iommu->strbuf_regs + STRBUF_FSYNC);
130 upa_readq(iommu->sbus_control_reg); 134 upa_readq(iommu->sbus_control_reg);
131 while (iommu->strbuf_flushflag == 0UL) 135
136 limit = 10000;
137 while (iommu->strbuf_flushflag == 0UL) {
138 limit--;
139 if (!limit)
140 break;
141 udelay(10);
132 membar("#LoadLoad"); 142 membar("#LoadLoad");
143 }
144 if (!limit)
145 printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
146 "vaddr[%08x] npages[%ld]\n",
147 base, npages);
133} 148}
134 149
135static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) 150static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
@@ -406,7 +421,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size,
406 421
407 spin_lock_irqsave(&iommu->lock, flags); 422 spin_lock_irqsave(&iommu->lock, flags);
408 free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); 423 free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);
409 strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); 424 sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
410 spin_unlock_irqrestore(&iommu->lock, flags); 425 spin_unlock_irqrestore(&iommu->lock, flags);
411} 426}
412 427
@@ -569,7 +584,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int
569 iommu = sdev->bus->iommu; 584 iommu = sdev->bus->iommu;
570 spin_lock_irqsave(&iommu->lock, flags); 585 spin_lock_irqsave(&iommu->lock, flags);
571 free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); 586 free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT);
572 strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); 587 sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
573 spin_unlock_irqrestore(&iommu->lock, flags); 588 spin_unlock_irqrestore(&iommu->lock, flags);
574} 589}
575 590
@@ -581,7 +596,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t
581 size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); 596 size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK));
582 597
583 spin_lock_irqsave(&iommu->lock, flags); 598 spin_lock_irqsave(&iommu->lock, flags);
584 strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); 599 sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
585 spin_unlock_irqrestore(&iommu->lock, flags); 600 spin_unlock_irqrestore(&iommu->lock, flags);
586} 601}
587 602
@@ -605,7 +620,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int
605 size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; 620 size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base;
606 621
607 spin_lock_irqsave(&iommu->lock, flags); 622 spin_lock_irqsave(&iommu->lock, flags);
608 strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); 623 sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
609 spin_unlock_irqrestore(&iommu->lock, flags); 624 spin_unlock_irqrestore(&iommu->lock, flags);
610} 625}
611 626