| .. | .. |
|---|
| 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 | +} |
|---|