Loading arch/s390/include/asm/airq.h +12 −2 Original line number Diff line number Diff line Loading @@ -44,11 +44,21 @@ struct airq_iv { struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags); void airq_iv_release(struct airq_iv *iv); unsigned long airq_iv_alloc_bit(struct airq_iv *iv); void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit); unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num); void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num); unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, unsigned long end); static inline unsigned long airq_iv_alloc_bit(struct airq_iv *iv) { return airq_iv_alloc(iv, 1); } static inline void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) { airq_iv_free(iv, bit, 1); } static inline unsigned long airq_iv_end(struct airq_iv *iv) { return iv->end; Loading drivers/s390/cio/airq.c +41 −25 Original line number Diff line number Diff line Loading @@ -186,55 +186,71 @@ void airq_iv_release(struct airq_iv *iv) EXPORT_SYMBOL(airq_iv_release); /** * airq_iv_alloc_bit - allocate an irq bit from an interrupt vector * airq_iv_alloc - allocate irq bits from an interrupt vector * @iv: pointer to an interrupt vector structure * @num: number of consecutive irq bits to allocate * * Returns the bit number of the allocated irq, or -1UL if no bit * is available or the AIRQ_IV_ALLOC flag has not been specified * Returns the bit number of the first irq in the allocated block of irqs, * or -1UL if no bit is available or the AIRQ_IV_ALLOC flag has not been * specified */ unsigned long airq_iv_alloc_bit(struct airq_iv *iv) unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num) { unsigned long bit; unsigned long bit, i; if (!iv->avail) if (!iv->avail || num == 0) return -1UL; spin_lock(&iv->lock); bit = find_first_bit_inv(iv->avail, iv->bits); if (bit < iv->bits) { clear_bit_inv(bit, iv->avail); if (bit >= iv->end) iv->end = bit + 1; } else while (bit + num <= iv->bits) { for (i = 1; i < num; i++) if (!test_bit_inv(bit + i, iv->avail)) break; if (i >= num) { /* Found a suitable block of irqs */ for (i = 0; i < num; i++) clear_bit_inv(bit + i, iv->avail); if (bit + num >= iv->end) iv->end = bit + num + 1; break; } bit = find_next_bit_inv(iv->avail, iv->bits, bit + i + 1); } if (bit + num > iv->bits) bit = -1UL; spin_unlock(&iv->lock); return bit; } EXPORT_SYMBOL(airq_iv_alloc_bit); EXPORT_SYMBOL(airq_iv_alloc); /** * airq_iv_free_bit - free an irq bit of an interrupt vector * airq_iv_free - free irq bits of an interrupt vector * @iv: pointer to interrupt vector structure * @bit: number of the irq bit to free * @bit: number of the first irq bit to free * @num: number of consecutive irq bits to free */ void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num) { if (!iv->avail) unsigned long i; if (!iv->avail || num == 0) return; spin_lock(&iv->lock); for (i = 0; i < num; i++) { /* Clear (possibly left over) interrupt bit */ clear_bit_inv(bit, iv->vector); /* Make the bit position available again */ set_bit_inv(bit, iv->avail); if (bit == iv->end - 1) { clear_bit_inv(bit + i, iv->vector); /* Make the bit positions available again */ set_bit_inv(bit + i, iv->avail); } if (bit + num >= iv->end) { /* Find new end of bit-field */ while (--iv->end > 0) if (!test_bit_inv(iv->end - 1, iv->avail)) break; while (iv->end > 0 && !test_bit_inv(iv->end - 1, iv->avail)) iv->end--; } spin_unlock(&iv->lock); } EXPORT_SYMBOL(airq_iv_free_bit); EXPORT_SYMBOL(airq_iv_free); /** * airq_iv_scan - scan interrupt vector for non-zero bits Loading Loading
arch/s390/include/asm/airq.h +12 −2 Original line number Diff line number Diff line Loading @@ -44,11 +44,21 @@ struct airq_iv { struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags); void airq_iv_release(struct airq_iv *iv); unsigned long airq_iv_alloc_bit(struct airq_iv *iv); void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit); unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num); void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num); unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, unsigned long end); static inline unsigned long airq_iv_alloc_bit(struct airq_iv *iv) { return airq_iv_alloc(iv, 1); } static inline void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) { airq_iv_free(iv, bit, 1); } static inline unsigned long airq_iv_end(struct airq_iv *iv) { return iv->end; Loading
drivers/s390/cio/airq.c +41 −25 Original line number Diff line number Diff line Loading @@ -186,55 +186,71 @@ void airq_iv_release(struct airq_iv *iv) EXPORT_SYMBOL(airq_iv_release); /** * airq_iv_alloc_bit - allocate an irq bit from an interrupt vector * airq_iv_alloc - allocate irq bits from an interrupt vector * @iv: pointer to an interrupt vector structure * @num: number of consecutive irq bits to allocate * * Returns the bit number of the allocated irq, or -1UL if no bit * is available or the AIRQ_IV_ALLOC flag has not been specified * Returns the bit number of the first irq in the allocated block of irqs, * or -1UL if no bit is available or the AIRQ_IV_ALLOC flag has not been * specified */ unsigned long airq_iv_alloc_bit(struct airq_iv *iv) unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num) { unsigned long bit; unsigned long bit, i; if (!iv->avail) if (!iv->avail || num == 0) return -1UL; spin_lock(&iv->lock); bit = find_first_bit_inv(iv->avail, iv->bits); if (bit < iv->bits) { clear_bit_inv(bit, iv->avail); if (bit >= iv->end) iv->end = bit + 1; } else while (bit + num <= iv->bits) { for (i = 1; i < num; i++) if (!test_bit_inv(bit + i, iv->avail)) break; if (i >= num) { /* Found a suitable block of irqs */ for (i = 0; i < num; i++) clear_bit_inv(bit + i, iv->avail); if (bit + num >= iv->end) iv->end = bit + num + 1; break; } bit = find_next_bit_inv(iv->avail, iv->bits, bit + i + 1); } if (bit + num > iv->bits) bit = -1UL; spin_unlock(&iv->lock); return bit; } EXPORT_SYMBOL(airq_iv_alloc_bit); EXPORT_SYMBOL(airq_iv_alloc); /** * airq_iv_free_bit - free an irq bit of an interrupt vector * airq_iv_free - free irq bits of an interrupt vector * @iv: pointer to interrupt vector structure * @bit: number of the irq bit to free * @bit: number of the first irq bit to free * @num: number of consecutive irq bits to free */ void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num) { if (!iv->avail) unsigned long i; if (!iv->avail || num == 0) return; spin_lock(&iv->lock); for (i = 0; i < num; i++) { /* Clear (possibly left over) interrupt bit */ clear_bit_inv(bit, iv->vector); /* Make the bit position available again */ set_bit_inv(bit, iv->avail); if (bit == iv->end - 1) { clear_bit_inv(bit + i, iv->vector); /* Make the bit positions available again */ set_bit_inv(bit + i, iv->avail); } if (bit + num >= iv->end) { /* Find new end of bit-field */ while (--iv->end > 0) if (!test_bit_inv(iv->end - 1, iv->avail)) break; while (iv->end > 0 && !test_bit_inv(iv->end - 1, iv->avail)) iv->end--; } spin_unlock(&iv->lock); } EXPORT_SYMBOL(airq_iv_free_bit); EXPORT_SYMBOL(airq_iv_free); /** * airq_iv_scan - scan interrupt vector for non-zero bits Loading