.. | .. |
---|
16 | 16 | #include <linux/mutex.h> |
---|
17 | 17 | #include <linux/rculist.h> |
---|
18 | 18 | #include <linux/slab.h> |
---|
| 19 | +#include <linux/dmapool.h> |
---|
19 | 20 | |
---|
20 | 21 | #include <asm/airq.h> |
---|
21 | 22 | #include <asm/isc.h> |
---|
| 23 | +#include <asm/cio.h> |
---|
22 | 24 | |
---|
23 | 25 | #include "cio.h" |
---|
24 | 26 | #include "cio_debug.h" |
---|
.. | .. |
---|
26 | 28 | |
---|
27 | 29 | static DEFINE_SPINLOCK(airq_lists_lock); |
---|
28 | 30 | static struct hlist_head airq_lists[MAX_ISC+1]; |
---|
| 31 | + |
---|
| 32 | +static struct dma_pool *airq_iv_cache; |
---|
29 | 33 | |
---|
30 | 34 | /** |
---|
31 | 35 | * register_adapter_interrupt() - register adapter interrupt handler |
---|
.. | .. |
---|
95 | 99 | rcu_read_lock(); |
---|
96 | 100 | hlist_for_each_entry_rcu(airq, head, list) |
---|
97 | 101 | if ((*airq->lsi_ptr & airq->lsi_mask) != 0) |
---|
98 | | - airq->handler(airq); |
---|
| 102 | + airq->handler(airq, !tpi_info->directed_irq); |
---|
99 | 103 | rcu_read_unlock(); |
---|
100 | 104 | |
---|
101 | 105 | return IRQ_HANDLED; |
---|
102 | 106 | } |
---|
103 | 107 | |
---|
104 | | -static struct irqaction airq_interrupt = { |
---|
105 | | - .name = "AIO", |
---|
106 | | - .handler = do_airq_interrupt, |
---|
107 | | -}; |
---|
108 | | - |
---|
109 | 108 | void __init init_airq_interrupts(void) |
---|
110 | 109 | { |
---|
111 | 110 | irq_set_chip_and_handler(THIN_INTERRUPT, |
---|
112 | 111 | &dummy_irq_chip, handle_percpu_irq); |
---|
113 | | - setup_irq(THIN_INTERRUPT, &airq_interrupt); |
---|
| 112 | + if (request_irq(THIN_INTERRUPT, do_airq_interrupt, 0, "AIO", NULL)) |
---|
| 113 | + panic("Failed to register AIO interrupt\n"); |
---|
| 114 | +} |
---|
| 115 | + |
---|
| 116 | +static inline unsigned long iv_size(unsigned long bits) |
---|
| 117 | +{ |
---|
| 118 | + return BITS_TO_LONGS(bits) * sizeof(unsigned long); |
---|
114 | 119 | } |
---|
115 | 120 | |
---|
116 | 121 | /** |
---|
.. | .. |
---|
129 | 134 | if (!iv) |
---|
130 | 135 | goto out; |
---|
131 | 136 | iv->bits = bits; |
---|
132 | | - size = BITS_TO_LONGS(bits) * sizeof(unsigned long); |
---|
133 | | - iv->vector = kzalloc(size, GFP_KERNEL); |
---|
134 | | - if (!iv->vector) |
---|
135 | | - goto out_free; |
---|
| 137 | + iv->flags = flags; |
---|
| 138 | + size = iv_size(bits); |
---|
| 139 | + |
---|
| 140 | + if (flags & AIRQ_IV_CACHELINE) { |
---|
| 141 | + if ((cache_line_size() * BITS_PER_BYTE) < bits |
---|
| 142 | + || !airq_iv_cache) |
---|
| 143 | + goto out_free; |
---|
| 144 | + |
---|
| 145 | + iv->vector = dma_pool_zalloc(airq_iv_cache, GFP_KERNEL, |
---|
| 146 | + &iv->vector_dma); |
---|
| 147 | + if (!iv->vector) |
---|
| 148 | + goto out_free; |
---|
| 149 | + } else { |
---|
| 150 | + iv->vector = cio_dma_zalloc(size); |
---|
| 151 | + if (!iv->vector) |
---|
| 152 | + goto out_free; |
---|
| 153 | + } |
---|
136 | 154 | if (flags & AIRQ_IV_ALLOC) { |
---|
137 | 155 | iv->avail = kmalloc(size, GFP_KERNEL); |
---|
138 | 156 | if (!iv->avail) |
---|
.. | .. |
---|
165 | 183 | kfree(iv->ptr); |
---|
166 | 184 | kfree(iv->bitlock); |
---|
167 | 185 | kfree(iv->avail); |
---|
168 | | - kfree(iv->vector); |
---|
| 186 | + if (iv->flags & AIRQ_IV_CACHELINE && iv->vector) |
---|
| 187 | + dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); |
---|
| 188 | + else |
---|
| 189 | + cio_dma_free(iv->vector, size); |
---|
169 | 190 | kfree(iv); |
---|
170 | 191 | out: |
---|
171 | 192 | return NULL; |
---|
.. | .. |
---|
181 | 202 | kfree(iv->data); |
---|
182 | 203 | kfree(iv->ptr); |
---|
183 | 204 | kfree(iv->bitlock); |
---|
184 | | - kfree(iv->vector); |
---|
| 205 | + if (iv->flags & AIRQ_IV_CACHELINE) |
---|
| 206 | + dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); |
---|
| 207 | + else |
---|
| 208 | + cio_dma_free(iv->vector, iv_size(iv->bits)); |
---|
185 | 209 | kfree(iv->avail); |
---|
186 | 210 | kfree(iv); |
---|
187 | 211 | } |
---|
.. | .. |
---|
275 | 299 | return bit; |
---|
276 | 300 | } |
---|
277 | 301 | EXPORT_SYMBOL(airq_iv_scan); |
---|
| 302 | + |
---|
| 303 | +int __init airq_init(void) |
---|
| 304 | +{ |
---|
| 305 | + airq_iv_cache = dma_pool_create("airq_iv_cache", cio_get_dma_css_dev(), |
---|
| 306 | + cache_line_size(), |
---|
| 307 | + cache_line_size(), PAGE_SIZE); |
---|
| 308 | + if (!airq_iv_cache) |
---|
| 309 | + return -ENOMEM; |
---|
| 310 | + return 0; |
---|
| 311 | +} |
---|