diff options
| -rw-r--r-- | arch/powerpc/kernel/iommu.c | 5 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/dart_iommu.c | 12 |
2 files changed, 16 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index ff5a6ce027b8..8226c6cb348a 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
| @@ -215,7 +215,8 @@ static unsigned long iommu_range_alloc(struct device *dev, | |||
| 215 | spin_lock_irqsave(&(pool->lock), flags); | 215 | spin_lock_irqsave(&(pool->lock), flags); |
| 216 | 216 | ||
| 217 | again: | 217 | again: |
| 218 | if ((pass == 0) && handle && *handle) | 218 | if ((pass == 0) && handle && *handle && |
| 219 | (*handle >= pool->start) && (*handle < pool->end)) | ||
| 219 | start = *handle; | 220 | start = *handle; |
| 220 | else | 221 | else |
| 221 | start = pool->hint; | 222 | start = pool->hint; |
| @@ -236,7 +237,9 @@ again: | |||
| 236 | * but on second pass, start at 0 in pool 0. | 237 | * but on second pass, start at 0 in pool 0. |
| 237 | */ | 238 | */ |
| 238 | if ((start & mask) >= limit || pass > 0) { | 239 | if ((start & mask) >= limit || pass > 0) { |
| 240 | spin_unlock(&(pool->lock)); | ||
| 239 | pool = &(tbl->pools[0]); | 241 | pool = &(tbl->pools[0]); |
| 242 | spin_lock(&(pool->lock)); | ||
| 240 | start = pool->start; | 243 | start = pool->start; |
| 241 | } else { | 244 | } else { |
| 242 | start &= mask; | 245 | start &= mask; |
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 8ef63a01e345..bd968a43a48b 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
| @@ -73,11 +73,16 @@ static int dart_is_u4; | |||
| 73 | 73 | ||
| 74 | #define DBG(...) | 74 | #define DBG(...) |
| 75 | 75 | ||
| 76 | static DEFINE_SPINLOCK(invalidate_lock); | ||
| 77 | |||
| 76 | static inline void dart_tlb_invalidate_all(void) | 78 | static inline void dart_tlb_invalidate_all(void) |
| 77 | { | 79 | { |
| 78 | unsigned long l = 0; | 80 | unsigned long l = 0; |
| 79 | unsigned int reg, inv_bit; | 81 | unsigned int reg, inv_bit; |
| 80 | unsigned long limit; | 82 | unsigned long limit; |
| 83 | unsigned long flags; | ||
| 84 | |||
| 85 | spin_lock_irqsave(&invalidate_lock, flags); | ||
| 81 | 86 | ||
| 82 | DBG("dart: flush\n"); | 87 | DBG("dart: flush\n"); |
| 83 | 88 | ||
| @@ -110,12 +115,17 @@ retry: | |||
| 110 | panic("DART: TLB did not flush after waiting a long " | 115 | panic("DART: TLB did not flush after waiting a long " |
| 111 | "time. Buggy U3 ?"); | 116 | "time. Buggy U3 ?"); |
| 112 | } | 117 | } |
| 118 | |||
| 119 | spin_unlock_irqrestore(&invalidate_lock, flags); | ||
| 113 | } | 120 | } |
| 114 | 121 | ||
| 115 | static inline void dart_tlb_invalidate_one(unsigned long bus_rpn) | 122 | static inline void dart_tlb_invalidate_one(unsigned long bus_rpn) |
| 116 | { | 123 | { |
| 117 | unsigned int reg; | 124 | unsigned int reg; |
| 118 | unsigned int l, limit; | 125 | unsigned int l, limit; |
| 126 | unsigned long flags; | ||
| 127 | |||
| 128 | spin_lock_irqsave(&invalidate_lock, flags); | ||
| 119 | 129 | ||
| 120 | reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE | | 130 | reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE | |
| 121 | (bus_rpn & DART_CNTL_U4_IONE_MASK); | 131 | (bus_rpn & DART_CNTL_U4_IONE_MASK); |
| @@ -137,6 +147,8 @@ wait_more: | |||
| 137 | panic("DART: TLB did not flush after waiting a long " | 147 | panic("DART: TLB did not flush after waiting a long " |
| 138 | "time. Buggy U4 ?"); | 148 | "time. Buggy U4 ?"); |
| 139 | } | 149 | } |
| 150 | |||
| 151 | spin_unlock_irqrestore(&invalidate_lock, flags); | ||
| 140 | } | 152 | } |
| 141 | 153 | ||
| 142 | static void dart_flush(struct iommu_table *tbl) | 154 | static void dart_flush(struct iommu_table *tbl) |
