diff options
Diffstat (limited to 'arch/sparc64/kernel/sbus.c')
-rw-r--r-- | arch/sparc64/kernel/sbus.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 14d9c3a21b9a..89f5e019f24c 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c | |||
@@ -117,19 +117,42 @@ 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 | ||
120 | static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) | 120 | static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction) |
121 | { | 121 | { |
122 | iommu->strbuf_flushflag = 0UL; | 122 | unsigned long n; |
123 | while (npages--) | 123 | int limit; |
124 | upa_writeq(base + (npages << IO_PAGE_SHIFT), | 124 | |
125 | n = npages; | ||
126 | while (n--) | ||
127 | upa_writeq(base + (n << IO_PAGE_SHIFT), | ||
125 | iommu->strbuf_regs + STRBUF_PFLUSH); | 128 | iommu->strbuf_regs + STRBUF_PFLUSH); |
126 | 129 | ||
130 | /* If the device could not have possibly put dirty data into | ||
131 | * the streaming cache, no flush-flag synchronization needs | ||
132 | * to be performed. | ||
133 | */ | ||
134 | if (direction == SBUS_DMA_TODEVICE) | ||
135 | return; | ||
136 | |||
137 | iommu->strbuf_flushflag = 0UL; | ||
138 | |||
127 | /* Whoopee cushion! */ | 139 | /* Whoopee cushion! */ |
128 | upa_writeq(__pa(&iommu->strbuf_flushflag), | 140 | upa_writeq(__pa(&iommu->strbuf_flushflag), |
129 | iommu->strbuf_regs + STRBUF_FSYNC); | 141 | iommu->strbuf_regs + STRBUF_FSYNC); |
130 | upa_readq(iommu->sbus_control_reg); | 142 | upa_readq(iommu->sbus_control_reg); |
131 | while (iommu->strbuf_flushflag == 0UL) | 143 | |
144 | limit = 100000; | ||
145 | while (iommu->strbuf_flushflag == 0UL) { | ||
146 | limit--; | ||
147 | if (!limit) | ||
148 | break; | ||
149 | udelay(1); | ||
132 | membar("#LoadLoad"); | 150 | membar("#LoadLoad"); |
151 | } | ||
152 | if (!limit) | ||
153 | printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout " | ||
154 | "vaddr[%08x] npages[%ld]\n", | ||
155 | base, npages); | ||
133 | } | 156 | } |
134 | 157 | ||
135 | static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) | 158 | static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) |
@@ -406,7 +429,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, | |||
406 | 429 | ||
407 | spin_lock_irqsave(&iommu->lock, flags); | 430 | spin_lock_irqsave(&iommu->lock, flags); |
408 | free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); | 431 | free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); |
409 | strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); | 432 | sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT, direction); |
410 | spin_unlock_irqrestore(&iommu->lock, flags); | 433 | spin_unlock_irqrestore(&iommu->lock, flags); |
411 | } | 434 | } |
412 | 435 | ||
@@ -569,7 +592,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int | |||
569 | iommu = sdev->bus->iommu; | 592 | iommu = sdev->bus->iommu; |
570 | spin_lock_irqsave(&iommu->lock, flags); | 593 | spin_lock_irqsave(&iommu->lock, flags); |
571 | free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); | 594 | free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); |
572 | strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); | 595 | sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT, direction); |
573 | spin_unlock_irqrestore(&iommu->lock, flags); | 596 | spin_unlock_irqrestore(&iommu->lock, flags); |
574 | } | 597 | } |
575 | 598 | ||
@@ -581,7 +604,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)); | 604 | size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); |
582 | 605 | ||
583 | spin_lock_irqsave(&iommu->lock, flags); | 606 | spin_lock_irqsave(&iommu->lock, flags); |
584 | strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); | 607 | sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT, direction); |
585 | spin_unlock_irqrestore(&iommu->lock, flags); | 608 | spin_unlock_irqrestore(&iommu->lock, flags); |
586 | } | 609 | } |
587 | 610 | ||
@@ -605,7 +628,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; | 628 | size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; |
606 | 629 | ||
607 | spin_lock_irqsave(&iommu->lock, flags); | 630 | spin_lock_irqsave(&iommu->lock, flags); |
608 | strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); | 631 | sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT, direction); |
609 | spin_unlock_irqrestore(&iommu->lock, flags); | 632 | spin_unlock_irqrestore(&iommu->lock, flags); |
610 | } | 633 | } |
611 | 634 | ||