hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/s390/cio/airq.c
....@@ -16,9 +16,11 @@
1616 #include <linux/mutex.h>
1717 #include <linux/rculist.h>
1818 #include <linux/slab.h>
19
+#include <linux/dmapool.h>
1920
2021 #include <asm/airq.h>
2122 #include <asm/isc.h>
23
+#include <asm/cio.h>
2224
2325 #include "cio.h"
2426 #include "cio_debug.h"
....@@ -26,6 +28,8 @@
2628
2729 static DEFINE_SPINLOCK(airq_lists_lock);
2830 static struct hlist_head airq_lists[MAX_ISC+1];
31
+
32
+static struct dma_pool *airq_iv_cache;
2933
3034 /**
3135 * register_adapter_interrupt() - register adapter interrupt handler
....@@ -95,22 +99,23 @@
9599 rcu_read_lock();
96100 hlist_for_each_entry_rcu(airq, head, list)
97101 if ((*airq->lsi_ptr & airq->lsi_mask) != 0)
98
- airq->handler(airq);
102
+ airq->handler(airq, !tpi_info->directed_irq);
99103 rcu_read_unlock();
100104
101105 return IRQ_HANDLED;
102106 }
103107
104
-static struct irqaction airq_interrupt = {
105
- .name = "AIO",
106
- .handler = do_airq_interrupt,
107
-};
108
-
109108 void __init init_airq_interrupts(void)
110109 {
111110 irq_set_chip_and_handler(THIN_INTERRUPT,
112111 &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);
114119 }
115120
116121 /**
....@@ -129,10 +134,23 @@
129134 if (!iv)
130135 goto out;
131136 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
+ }
136154 if (flags & AIRQ_IV_ALLOC) {
137155 iv->avail = kmalloc(size, GFP_KERNEL);
138156 if (!iv->avail)
....@@ -165,7 +183,10 @@
165183 kfree(iv->ptr);
166184 kfree(iv->bitlock);
167185 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);
169190 kfree(iv);
170191 out:
171192 return NULL;
....@@ -181,7 +202,10 @@
181202 kfree(iv->data);
182203 kfree(iv->ptr);
183204 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));
185209 kfree(iv->avail);
186210 kfree(iv);
187211 }
....@@ -275,3 +299,13 @@
275299 return bit;
276300 }
277301 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
+}