aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2014-02-13 07:02:32 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-02-21 02:50:22 -0500
commitfe7c30a420761654777d3cc15412fc7626407e93 (patch)
tree95f4377d7aced89fb5511fa2de3521e30347dac8 /drivers/s390/cio
parentec66ad66a0de87866be347b5ecc83bd46427f53b (diff)
s390/airq: add support for irq ranges
Add airq_iv_alloc and airq_iv_free to allocate and free consecutive ranges of irqs from the interrupt vector. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/airq.c66
1 files changed, 41 insertions, 25 deletions
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index f055df0b167f..445564c790f6 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -186,55 +186,71 @@ void airq_iv_release(struct airq_iv *iv)
186EXPORT_SYMBOL(airq_iv_release); 186EXPORT_SYMBOL(airq_iv_release);
187 187
188/** 188/**
189 * airq_iv_alloc_bit - allocate an irq bit from an interrupt vector 189 * airq_iv_alloc - allocate irq bits from an interrupt vector
190 * @iv: pointer to an interrupt vector structure 190 * @iv: pointer to an interrupt vector structure
191 * @num: number of consecutive irq bits to allocate
191 * 192 *
192 * Returns the bit number of the allocated irq, or -1UL if no bit 193 * Returns the bit number of the first irq in the allocated block of irqs,
193 * is available or the AIRQ_IV_ALLOC flag has not been specified 194 * or -1UL if no bit is available or the AIRQ_IV_ALLOC flag has not been
195 * specified
194 */ 196 */
195unsigned long airq_iv_alloc_bit(struct airq_iv *iv) 197unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num)
196{ 198{
197 unsigned long bit; 199 unsigned long bit, i;
198 200
199 if (!iv->avail) 201 if (!iv->avail || num == 0)
200 return -1UL; 202 return -1UL;
201 spin_lock(&iv->lock); 203 spin_lock(&iv->lock);
202 bit = find_first_bit_inv(iv->avail, iv->bits); 204 bit = find_first_bit_inv(iv->avail, iv->bits);
203 if (bit < iv->bits) { 205 while (bit + num <= iv->bits) {
204 clear_bit_inv(bit, iv->avail); 206 for (i = 1; i < num; i++)
205 if (bit >= iv->end) 207 if (!test_bit_inv(bit + i, iv->avail))
206 iv->end = bit + 1; 208 break;
207 } else 209 if (i >= num) {
210 /* Found a suitable block of irqs */
211 for (i = 0; i < num; i++)
212 clear_bit_inv(bit + i, iv->avail);
213 if (bit + num >= iv->end)
214 iv->end = bit + num + 1;
215 break;
216 }
217 bit = find_next_bit_inv(iv->avail, iv->bits, bit + i + 1);
218 }
219 if (bit + num > iv->bits)
208 bit = -1UL; 220 bit = -1UL;
209 spin_unlock(&iv->lock); 221 spin_unlock(&iv->lock);
210 return bit; 222 return bit;
211 223
212} 224}
213EXPORT_SYMBOL(airq_iv_alloc_bit); 225EXPORT_SYMBOL(airq_iv_alloc);
214 226
215/** 227/**
216 * airq_iv_free_bit - free an irq bit of an interrupt vector 228 * airq_iv_free - free irq bits of an interrupt vector
217 * @iv: pointer to interrupt vector structure 229 * @iv: pointer to interrupt vector structure
218 * @bit: number of the irq bit to free 230 * @bit: number of the first irq bit to free
231 * @num: number of consecutive irq bits to free
219 */ 232 */
220void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) 233void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num)
221{ 234{
222 if (!iv->avail) 235 unsigned long i;
236
237 if (!iv->avail || num == 0)
223 return; 238 return;
224 spin_lock(&iv->lock); 239 spin_lock(&iv->lock);
225 /* Clear (possibly left over) interrupt bit */ 240 for (i = 0; i < num; i++) {
226 clear_bit_inv(bit, iv->vector); 241 /* Clear (possibly left over) interrupt bit */
227 /* Make the bit position available again */ 242 clear_bit_inv(bit + i, iv->vector);
228 set_bit_inv(bit, iv->avail); 243 /* Make the bit positions available again */
229 if (bit == iv->end - 1) { 244 set_bit_inv(bit + i, iv->avail);
245 }
246 if (bit + num >= iv->end) {
230 /* Find new end of bit-field */ 247 /* Find new end of bit-field */
231 while (--iv->end > 0) 248 while (iv->end > 0 && !test_bit_inv(iv->end - 1, iv->avail))
232 if (!test_bit_inv(iv->end - 1, iv->avail)) 249 iv->end--;
233 break;
234 } 250 }
235 spin_unlock(&iv->lock); 251 spin_unlock(&iv->lock);
236} 252}
237EXPORT_SYMBOL(airq_iv_free_bit); 253EXPORT_SYMBOL(airq_iv_free);
238 254
239/** 255/**
240 * airq_iv_scan - scan interrupt vector for non-zero bits 256 * airq_iv_scan - scan interrupt vector for non-zero bits