18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2016 Facebook
48c2ecf20Sopenharmony_ci * Copyright (C) 2013-2014 Jens Axboe
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/sched.h>
88c2ecf20Sopenharmony_ci#include <linux/random.h>
98c2ecf20Sopenharmony_ci#include <linux/sbitmap.h>
108c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/*
138c2ecf20Sopenharmony_ci * See if we have deferred clears that we can batch move
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_cistatic inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	unsigned long mask, val;
188c2ecf20Sopenharmony_ci	bool ret = false;
198c2ecf20Sopenharmony_ci	unsigned long flags;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sb->map[index].swap_lock, flags);
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	if (!sb->map[index].cleared)
248c2ecf20Sopenharmony_ci		goto out_unlock;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	/*
278c2ecf20Sopenharmony_ci	 * First get a stable cleared mask, setting the old mask to 0.
288c2ecf20Sopenharmony_ci	 */
298c2ecf20Sopenharmony_ci	mask = xchg(&sb->map[index].cleared, 0);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	/*
328c2ecf20Sopenharmony_ci	 * Now clear the masked bits in our free word
338c2ecf20Sopenharmony_ci	 */
348c2ecf20Sopenharmony_ci	do {
358c2ecf20Sopenharmony_ci		val = sb->map[index].word;
368c2ecf20Sopenharmony_ci	} while (cmpxchg(&sb->map[index].word, val, val & ~mask) != val);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	ret = true;
398c2ecf20Sopenharmony_ciout_unlock:
408c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sb->map[index].swap_lock, flags);
418c2ecf20Sopenharmony_ci	return ret;
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ciint sbitmap_init_node(struct sbitmap *sb, unsigned int depth, int shift,
458c2ecf20Sopenharmony_ci		      gfp_t flags, int node)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	unsigned int bits_per_word;
488c2ecf20Sopenharmony_ci	unsigned int i;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (shift < 0) {
518c2ecf20Sopenharmony_ci		shift = ilog2(BITS_PER_LONG);
528c2ecf20Sopenharmony_ci		/*
538c2ecf20Sopenharmony_ci		 * If the bitmap is small, shrink the number of bits per word so
548c2ecf20Sopenharmony_ci		 * we spread over a few cachelines, at least. If less than 4
558c2ecf20Sopenharmony_ci		 * bits, just forget about it, it's not going to work optimally
568c2ecf20Sopenharmony_ci		 * anyway.
578c2ecf20Sopenharmony_ci		 */
588c2ecf20Sopenharmony_ci		if (depth >= 4) {
598c2ecf20Sopenharmony_ci			while ((4U << shift) > depth)
608c2ecf20Sopenharmony_ci				shift--;
618c2ecf20Sopenharmony_ci		}
628c2ecf20Sopenharmony_ci	}
638c2ecf20Sopenharmony_ci	bits_per_word = 1U << shift;
648c2ecf20Sopenharmony_ci	if (bits_per_word > BITS_PER_LONG)
658c2ecf20Sopenharmony_ci		return -EINVAL;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	sb->shift = shift;
688c2ecf20Sopenharmony_ci	sb->depth = depth;
698c2ecf20Sopenharmony_ci	sb->map_nr = DIV_ROUND_UP(sb->depth, bits_per_word);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	if (depth == 0) {
728c2ecf20Sopenharmony_ci		sb->map = NULL;
738c2ecf20Sopenharmony_ci		return 0;
748c2ecf20Sopenharmony_ci	}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	sb->map = kcalloc_node(sb->map_nr, sizeof(*sb->map), flags, node);
778c2ecf20Sopenharmony_ci	if (!sb->map)
788c2ecf20Sopenharmony_ci		return -ENOMEM;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	for (i = 0; i < sb->map_nr; i++) {
818c2ecf20Sopenharmony_ci		sb->map[i].depth = min(depth, bits_per_word);
828c2ecf20Sopenharmony_ci		depth -= sb->map[i].depth;
838c2ecf20Sopenharmony_ci		spin_lock_init(&sb->map[i].swap_lock);
848c2ecf20Sopenharmony_ci	}
858c2ecf20Sopenharmony_ci	return 0;
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_init_node);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_civoid sbitmap_resize(struct sbitmap *sb, unsigned int depth)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	unsigned int bits_per_word = 1U << sb->shift;
928c2ecf20Sopenharmony_ci	unsigned int i;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	for (i = 0; i < sb->map_nr; i++)
958c2ecf20Sopenharmony_ci		sbitmap_deferred_clear(sb, i);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	sb->depth = depth;
988c2ecf20Sopenharmony_ci	sb->map_nr = DIV_ROUND_UP(sb->depth, bits_per_word);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	for (i = 0; i < sb->map_nr; i++) {
1018c2ecf20Sopenharmony_ci		sb->map[i].depth = min(depth, bits_per_word);
1028c2ecf20Sopenharmony_ci		depth -= sb->map[i].depth;
1038c2ecf20Sopenharmony_ci	}
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_resize);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic int __sbitmap_get_word(unsigned long *word, unsigned long depth,
1088c2ecf20Sopenharmony_ci			      unsigned int hint, bool wrap)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	unsigned int orig_hint = hint;
1118c2ecf20Sopenharmony_ci	int nr;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	while (1) {
1148c2ecf20Sopenharmony_ci		nr = find_next_zero_bit(word, depth, hint);
1158c2ecf20Sopenharmony_ci		if (unlikely(nr >= depth)) {
1168c2ecf20Sopenharmony_ci			/*
1178c2ecf20Sopenharmony_ci			 * We started with an offset, and we didn't reset the
1188c2ecf20Sopenharmony_ci			 * offset to 0 in a failure case, so start from 0 to
1198c2ecf20Sopenharmony_ci			 * exhaust the map.
1208c2ecf20Sopenharmony_ci			 */
1218c2ecf20Sopenharmony_ci			if (orig_hint && hint && wrap) {
1228c2ecf20Sopenharmony_ci				hint = orig_hint = 0;
1238c2ecf20Sopenharmony_ci				continue;
1248c2ecf20Sopenharmony_ci			}
1258c2ecf20Sopenharmony_ci			return -1;
1268c2ecf20Sopenharmony_ci		}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci		if (!test_and_set_bit_lock(nr, word))
1298c2ecf20Sopenharmony_ci			break;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci		hint = nr + 1;
1328c2ecf20Sopenharmony_ci		if (hint >= depth - 1)
1338c2ecf20Sopenharmony_ci			hint = 0;
1348c2ecf20Sopenharmony_ci	}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	return nr;
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic int sbitmap_find_bit_in_index(struct sbitmap *sb, int index,
1408c2ecf20Sopenharmony_ci				     unsigned int alloc_hint, bool round_robin)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	int nr;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	do {
1458c2ecf20Sopenharmony_ci		nr = __sbitmap_get_word(&sb->map[index].word,
1468c2ecf20Sopenharmony_ci					sb->map[index].depth, alloc_hint,
1478c2ecf20Sopenharmony_ci					!round_robin);
1488c2ecf20Sopenharmony_ci		if (nr != -1)
1498c2ecf20Sopenharmony_ci			break;
1508c2ecf20Sopenharmony_ci		if (!sbitmap_deferred_clear(sb, index))
1518c2ecf20Sopenharmony_ci			break;
1528c2ecf20Sopenharmony_ci	} while (1);
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	return nr;
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ciint sbitmap_get(struct sbitmap *sb, unsigned int alloc_hint, bool round_robin)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	unsigned int i, index;
1608c2ecf20Sopenharmony_ci	int nr = -1;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	index = SB_NR_TO_INDEX(sb, alloc_hint);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	/*
1658c2ecf20Sopenharmony_ci	 * Unless we're doing round robin tag allocation, just use the
1668c2ecf20Sopenharmony_ci	 * alloc_hint to find the right word index. No point in looping
1678c2ecf20Sopenharmony_ci	 * twice in find_next_zero_bit() for that case.
1688c2ecf20Sopenharmony_ci	 */
1698c2ecf20Sopenharmony_ci	if (round_robin)
1708c2ecf20Sopenharmony_ci		alloc_hint = SB_NR_TO_BIT(sb, alloc_hint);
1718c2ecf20Sopenharmony_ci	else
1728c2ecf20Sopenharmony_ci		alloc_hint = 0;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	for (i = 0; i < sb->map_nr; i++) {
1758c2ecf20Sopenharmony_ci		nr = sbitmap_find_bit_in_index(sb, index, alloc_hint,
1768c2ecf20Sopenharmony_ci						round_robin);
1778c2ecf20Sopenharmony_ci		if (nr != -1) {
1788c2ecf20Sopenharmony_ci			nr += index << sb->shift;
1798c2ecf20Sopenharmony_ci			break;
1808c2ecf20Sopenharmony_ci		}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci		/* Jump to next index. */
1838c2ecf20Sopenharmony_ci		alloc_hint = 0;
1848c2ecf20Sopenharmony_ci		if (++index >= sb->map_nr)
1858c2ecf20Sopenharmony_ci			index = 0;
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	return nr;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_get);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ciint sbitmap_get_shallow(struct sbitmap *sb, unsigned int alloc_hint,
1938c2ecf20Sopenharmony_ci			unsigned long shallow_depth)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	unsigned int i, index;
1968c2ecf20Sopenharmony_ci	int nr = -1;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	index = SB_NR_TO_INDEX(sb, alloc_hint);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	for (i = 0; i < sb->map_nr; i++) {
2018c2ecf20Sopenharmony_ciagain:
2028c2ecf20Sopenharmony_ci		nr = __sbitmap_get_word(&sb->map[index].word,
2038c2ecf20Sopenharmony_ci					min(sb->map[index].depth, shallow_depth),
2048c2ecf20Sopenharmony_ci					SB_NR_TO_BIT(sb, alloc_hint), true);
2058c2ecf20Sopenharmony_ci		if (nr != -1) {
2068c2ecf20Sopenharmony_ci			nr += index << sb->shift;
2078c2ecf20Sopenharmony_ci			break;
2088c2ecf20Sopenharmony_ci		}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci		if (sbitmap_deferred_clear(sb, index))
2118c2ecf20Sopenharmony_ci			goto again;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci		/* Jump to next index. */
2148c2ecf20Sopenharmony_ci		index++;
2158c2ecf20Sopenharmony_ci		alloc_hint = index << sb->shift;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci		if (index >= sb->map_nr) {
2188c2ecf20Sopenharmony_ci			index = 0;
2198c2ecf20Sopenharmony_ci			alloc_hint = 0;
2208c2ecf20Sopenharmony_ci		}
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	return nr;
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_get_shallow);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cibool sbitmap_any_bit_set(const struct sbitmap *sb)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	unsigned int i;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	for (i = 0; i < sb->map_nr; i++) {
2328c2ecf20Sopenharmony_ci		if (sb->map[i].word & ~sb->map[i].cleared)
2338c2ecf20Sopenharmony_ci			return true;
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci	return false;
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_any_bit_set);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cistatic unsigned int __sbitmap_weight(const struct sbitmap *sb, bool set)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	unsigned int i, weight = 0;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	for (i = 0; i < sb->map_nr; i++) {
2448c2ecf20Sopenharmony_ci		const struct sbitmap_word *word = &sb->map[i];
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci		if (set)
2478c2ecf20Sopenharmony_ci			weight += bitmap_weight(&word->word, word->depth);
2488c2ecf20Sopenharmony_ci		else
2498c2ecf20Sopenharmony_ci			weight += bitmap_weight(&word->cleared, word->depth);
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci	return weight;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic unsigned int sbitmap_weight(const struct sbitmap *sb)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	return __sbitmap_weight(sb, true);
2578c2ecf20Sopenharmony_ci}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_cistatic unsigned int sbitmap_cleared(const struct sbitmap *sb)
2608c2ecf20Sopenharmony_ci{
2618c2ecf20Sopenharmony_ci	return __sbitmap_weight(sb, false);
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_civoid sbitmap_show(struct sbitmap *sb, struct seq_file *m)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	seq_printf(m, "depth=%u\n", sb->depth);
2678c2ecf20Sopenharmony_ci	seq_printf(m, "busy=%u\n", sbitmap_weight(sb) - sbitmap_cleared(sb));
2688c2ecf20Sopenharmony_ci	seq_printf(m, "cleared=%u\n", sbitmap_cleared(sb));
2698c2ecf20Sopenharmony_ci	seq_printf(m, "bits_per_word=%u\n", 1U << sb->shift);
2708c2ecf20Sopenharmony_ci	seq_printf(m, "map_nr=%u\n", sb->map_nr);
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_show);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cistatic inline void emit_byte(struct seq_file *m, unsigned int offset, u8 byte)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	if ((offset & 0xf) == 0) {
2778c2ecf20Sopenharmony_ci		if (offset != 0)
2788c2ecf20Sopenharmony_ci			seq_putc(m, '\n');
2798c2ecf20Sopenharmony_ci		seq_printf(m, "%08x:", offset);
2808c2ecf20Sopenharmony_ci	}
2818c2ecf20Sopenharmony_ci	if ((offset & 0x1) == 0)
2828c2ecf20Sopenharmony_ci		seq_putc(m, ' ');
2838c2ecf20Sopenharmony_ci	seq_printf(m, "%02x", byte);
2848c2ecf20Sopenharmony_ci}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_civoid sbitmap_bitmap_show(struct sbitmap *sb, struct seq_file *m)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	u8 byte = 0;
2898c2ecf20Sopenharmony_ci	unsigned int byte_bits = 0;
2908c2ecf20Sopenharmony_ci	unsigned int offset = 0;
2918c2ecf20Sopenharmony_ci	int i;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	for (i = 0; i < sb->map_nr; i++) {
2948c2ecf20Sopenharmony_ci		unsigned long word = READ_ONCE(sb->map[i].word);
2958c2ecf20Sopenharmony_ci		unsigned long cleared = READ_ONCE(sb->map[i].cleared);
2968c2ecf20Sopenharmony_ci		unsigned int word_bits = READ_ONCE(sb->map[i].depth);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci		word &= ~cleared;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci		while (word_bits > 0) {
3018c2ecf20Sopenharmony_ci			unsigned int bits = min(8 - byte_bits, word_bits);
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci			byte |= (word & (BIT(bits) - 1)) << byte_bits;
3048c2ecf20Sopenharmony_ci			byte_bits += bits;
3058c2ecf20Sopenharmony_ci			if (byte_bits == 8) {
3068c2ecf20Sopenharmony_ci				emit_byte(m, offset, byte);
3078c2ecf20Sopenharmony_ci				byte = 0;
3088c2ecf20Sopenharmony_ci				byte_bits = 0;
3098c2ecf20Sopenharmony_ci				offset++;
3108c2ecf20Sopenharmony_ci			}
3118c2ecf20Sopenharmony_ci			word >>= bits;
3128c2ecf20Sopenharmony_ci			word_bits -= bits;
3138c2ecf20Sopenharmony_ci		}
3148c2ecf20Sopenharmony_ci	}
3158c2ecf20Sopenharmony_ci	if (byte_bits) {
3168c2ecf20Sopenharmony_ci		emit_byte(m, offset, byte);
3178c2ecf20Sopenharmony_ci		offset++;
3188c2ecf20Sopenharmony_ci	}
3198c2ecf20Sopenharmony_ci	if (offset)
3208c2ecf20Sopenharmony_ci		seq_putc(m, '\n');
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_bitmap_show);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cistatic unsigned int sbq_calc_wake_batch(struct sbitmap_queue *sbq,
3258c2ecf20Sopenharmony_ci					unsigned int depth)
3268c2ecf20Sopenharmony_ci{
3278c2ecf20Sopenharmony_ci	unsigned int wake_batch;
3288c2ecf20Sopenharmony_ci	unsigned int shallow_depth;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	/*
3318c2ecf20Sopenharmony_ci	 * For each batch, we wake up one queue. We need to make sure that our
3328c2ecf20Sopenharmony_ci	 * batch size is small enough that the full depth of the bitmap,
3338c2ecf20Sopenharmony_ci	 * potentially limited by a shallow depth, is enough to wake up all of
3348c2ecf20Sopenharmony_ci	 * the queues.
3358c2ecf20Sopenharmony_ci	 *
3368c2ecf20Sopenharmony_ci	 * Each full word of the bitmap has bits_per_word bits, and there might
3378c2ecf20Sopenharmony_ci	 * be a partial word. There are depth / bits_per_word full words and
3388c2ecf20Sopenharmony_ci	 * depth % bits_per_word bits left over. In bitwise arithmetic:
3398c2ecf20Sopenharmony_ci	 *
3408c2ecf20Sopenharmony_ci	 * bits_per_word = 1 << shift
3418c2ecf20Sopenharmony_ci	 * depth / bits_per_word = depth >> shift
3428c2ecf20Sopenharmony_ci	 * depth % bits_per_word = depth & ((1 << shift) - 1)
3438c2ecf20Sopenharmony_ci	 *
3448c2ecf20Sopenharmony_ci	 * Each word can be limited to sbq->min_shallow_depth bits.
3458c2ecf20Sopenharmony_ci	 */
3468c2ecf20Sopenharmony_ci	shallow_depth = min(1U << sbq->sb.shift, sbq->min_shallow_depth);
3478c2ecf20Sopenharmony_ci	depth = ((depth >> sbq->sb.shift) * shallow_depth +
3488c2ecf20Sopenharmony_ci		 min(depth & ((1U << sbq->sb.shift) - 1), shallow_depth));
3498c2ecf20Sopenharmony_ci	wake_batch = clamp_t(unsigned int, depth / SBQ_WAIT_QUEUES, 1,
3508c2ecf20Sopenharmony_ci			     SBQ_WAKE_BATCH);
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	return wake_batch;
3538c2ecf20Sopenharmony_ci}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ciint sbitmap_queue_init_node(struct sbitmap_queue *sbq, unsigned int depth,
3568c2ecf20Sopenharmony_ci			    int shift, bool round_robin, gfp_t flags, int node)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	int ret;
3598c2ecf20Sopenharmony_ci	int i;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	ret = sbitmap_init_node(&sbq->sb, depth, shift, flags, node);
3628c2ecf20Sopenharmony_ci	if (ret)
3638c2ecf20Sopenharmony_ci		return ret;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	sbq->alloc_hint = alloc_percpu_gfp(unsigned int, flags);
3668c2ecf20Sopenharmony_ci	if (!sbq->alloc_hint) {
3678c2ecf20Sopenharmony_ci		sbitmap_free(&sbq->sb);
3688c2ecf20Sopenharmony_ci		return -ENOMEM;
3698c2ecf20Sopenharmony_ci	}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	if (depth && !round_robin) {
3728c2ecf20Sopenharmony_ci		for_each_possible_cpu(i)
3738c2ecf20Sopenharmony_ci			*per_cpu_ptr(sbq->alloc_hint, i) = prandom_u32() % depth;
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	sbq->min_shallow_depth = UINT_MAX;
3778c2ecf20Sopenharmony_ci	sbq->wake_batch = sbq_calc_wake_batch(sbq, depth);
3788c2ecf20Sopenharmony_ci	atomic_set(&sbq->wake_index, 0);
3798c2ecf20Sopenharmony_ci	atomic_set(&sbq->ws_active, 0);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	sbq->ws = kzalloc_node(SBQ_WAIT_QUEUES * sizeof(*sbq->ws), flags, node);
3828c2ecf20Sopenharmony_ci	if (!sbq->ws) {
3838c2ecf20Sopenharmony_ci		free_percpu(sbq->alloc_hint);
3848c2ecf20Sopenharmony_ci		sbitmap_free(&sbq->sb);
3858c2ecf20Sopenharmony_ci		return -ENOMEM;
3868c2ecf20Sopenharmony_ci	}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	for (i = 0; i < SBQ_WAIT_QUEUES; i++) {
3898c2ecf20Sopenharmony_ci		init_waitqueue_head(&sbq->ws[i].wait);
3908c2ecf20Sopenharmony_ci		atomic_set(&sbq->ws[i].wait_cnt, sbq->wake_batch);
3918c2ecf20Sopenharmony_ci	}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	sbq->round_robin = round_robin;
3948c2ecf20Sopenharmony_ci	return 0;
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_queue_init_node);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cistatic void sbitmap_queue_update_wake_batch(struct sbitmap_queue *sbq,
3998c2ecf20Sopenharmony_ci					    unsigned int depth)
4008c2ecf20Sopenharmony_ci{
4018c2ecf20Sopenharmony_ci	unsigned int wake_batch = sbq_calc_wake_batch(sbq, depth);
4028c2ecf20Sopenharmony_ci	int i;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	if (sbq->wake_batch != wake_batch) {
4058c2ecf20Sopenharmony_ci		WRITE_ONCE(sbq->wake_batch, wake_batch);
4068c2ecf20Sopenharmony_ci		/*
4078c2ecf20Sopenharmony_ci		 * Pairs with the memory barrier in sbitmap_queue_wake_up()
4088c2ecf20Sopenharmony_ci		 * to ensure that the batch size is updated before the wait
4098c2ecf20Sopenharmony_ci		 * counts.
4108c2ecf20Sopenharmony_ci		 */
4118c2ecf20Sopenharmony_ci		smp_mb();
4128c2ecf20Sopenharmony_ci		for (i = 0; i < SBQ_WAIT_QUEUES; i++)
4138c2ecf20Sopenharmony_ci			atomic_set(&sbq->ws[i].wait_cnt, 1);
4148c2ecf20Sopenharmony_ci	}
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_civoid sbitmap_queue_resize(struct sbitmap_queue *sbq, unsigned int depth)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	sbitmap_queue_update_wake_batch(sbq, depth);
4208c2ecf20Sopenharmony_ci	sbitmap_resize(&sbq->sb, depth);
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_queue_resize);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ciint __sbitmap_queue_get(struct sbitmap_queue *sbq)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	unsigned int hint, depth;
4278c2ecf20Sopenharmony_ci	int nr;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	hint = this_cpu_read(*sbq->alloc_hint);
4308c2ecf20Sopenharmony_ci	depth = READ_ONCE(sbq->sb.depth);
4318c2ecf20Sopenharmony_ci	if (unlikely(hint >= depth)) {
4328c2ecf20Sopenharmony_ci		hint = depth ? prandom_u32() % depth : 0;
4338c2ecf20Sopenharmony_ci		this_cpu_write(*sbq->alloc_hint, hint);
4348c2ecf20Sopenharmony_ci	}
4358c2ecf20Sopenharmony_ci	nr = sbitmap_get(&sbq->sb, hint, sbq->round_robin);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	if (nr == -1) {
4388c2ecf20Sopenharmony_ci		/* If the map is full, a hint won't do us much good. */
4398c2ecf20Sopenharmony_ci		this_cpu_write(*sbq->alloc_hint, 0);
4408c2ecf20Sopenharmony_ci	} else if (nr == hint || unlikely(sbq->round_robin)) {
4418c2ecf20Sopenharmony_ci		/* Only update the hint if we used it. */
4428c2ecf20Sopenharmony_ci		hint = nr + 1;
4438c2ecf20Sopenharmony_ci		if (hint >= depth - 1)
4448c2ecf20Sopenharmony_ci			hint = 0;
4458c2ecf20Sopenharmony_ci		this_cpu_write(*sbq->alloc_hint, hint);
4468c2ecf20Sopenharmony_ci	}
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	return nr;
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__sbitmap_queue_get);
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ciint __sbitmap_queue_get_shallow(struct sbitmap_queue *sbq,
4538c2ecf20Sopenharmony_ci				unsigned int shallow_depth)
4548c2ecf20Sopenharmony_ci{
4558c2ecf20Sopenharmony_ci	unsigned int hint, depth;
4568c2ecf20Sopenharmony_ci	int nr;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	WARN_ON_ONCE(shallow_depth < sbq->min_shallow_depth);
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	hint = this_cpu_read(*sbq->alloc_hint);
4618c2ecf20Sopenharmony_ci	depth = READ_ONCE(sbq->sb.depth);
4628c2ecf20Sopenharmony_ci	if (unlikely(hint >= depth)) {
4638c2ecf20Sopenharmony_ci		hint = depth ? prandom_u32() % depth : 0;
4648c2ecf20Sopenharmony_ci		this_cpu_write(*sbq->alloc_hint, hint);
4658c2ecf20Sopenharmony_ci	}
4668c2ecf20Sopenharmony_ci	nr = sbitmap_get_shallow(&sbq->sb, hint, shallow_depth);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	if (nr == -1) {
4698c2ecf20Sopenharmony_ci		/* If the map is full, a hint won't do us much good. */
4708c2ecf20Sopenharmony_ci		this_cpu_write(*sbq->alloc_hint, 0);
4718c2ecf20Sopenharmony_ci	} else if (nr == hint || unlikely(sbq->round_robin)) {
4728c2ecf20Sopenharmony_ci		/* Only update the hint if we used it. */
4738c2ecf20Sopenharmony_ci		hint = nr + 1;
4748c2ecf20Sopenharmony_ci		if (hint >= depth - 1)
4758c2ecf20Sopenharmony_ci			hint = 0;
4768c2ecf20Sopenharmony_ci		this_cpu_write(*sbq->alloc_hint, hint);
4778c2ecf20Sopenharmony_ci	}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	return nr;
4808c2ecf20Sopenharmony_ci}
4818c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__sbitmap_queue_get_shallow);
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_civoid sbitmap_queue_min_shallow_depth(struct sbitmap_queue *sbq,
4848c2ecf20Sopenharmony_ci				     unsigned int min_shallow_depth)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	sbq->min_shallow_depth = min_shallow_depth;
4878c2ecf20Sopenharmony_ci	sbitmap_queue_update_wake_batch(sbq, sbq->sb.depth);
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_queue_min_shallow_depth);
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_cistatic struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq)
4928c2ecf20Sopenharmony_ci{
4938c2ecf20Sopenharmony_ci	int i, wake_index;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	if (!atomic_read(&sbq->ws_active))
4968c2ecf20Sopenharmony_ci		return NULL;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	wake_index = atomic_read(&sbq->wake_index);
4998c2ecf20Sopenharmony_ci	for (i = 0; i < SBQ_WAIT_QUEUES; i++) {
5008c2ecf20Sopenharmony_ci		struct sbq_wait_state *ws = &sbq->ws[wake_index];
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci		if (waitqueue_active(&ws->wait)) {
5038c2ecf20Sopenharmony_ci			if (wake_index != atomic_read(&sbq->wake_index))
5048c2ecf20Sopenharmony_ci				atomic_set(&sbq->wake_index, wake_index);
5058c2ecf20Sopenharmony_ci			return ws;
5068c2ecf20Sopenharmony_ci		}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci		wake_index = sbq_index_inc(wake_index);
5098c2ecf20Sopenharmony_ci	}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	return NULL;
5128c2ecf20Sopenharmony_ci}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_cistatic bool __sbq_wake_up(struct sbitmap_queue *sbq)
5158c2ecf20Sopenharmony_ci{
5168c2ecf20Sopenharmony_ci	struct sbq_wait_state *ws;
5178c2ecf20Sopenharmony_ci	unsigned int wake_batch;
5188c2ecf20Sopenharmony_ci	int wait_cnt;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	ws = sbq_wake_ptr(sbq);
5218c2ecf20Sopenharmony_ci	if (!ws)
5228c2ecf20Sopenharmony_ci		return false;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	wait_cnt = atomic_dec_return(&ws->wait_cnt);
5258c2ecf20Sopenharmony_ci	if (wait_cnt <= 0) {
5268c2ecf20Sopenharmony_ci		int ret;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci		wake_batch = READ_ONCE(sbq->wake_batch);
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci		/*
5318c2ecf20Sopenharmony_ci		 * Pairs with the memory barrier in sbitmap_queue_resize() to
5328c2ecf20Sopenharmony_ci		 * ensure that we see the batch size update before the wait
5338c2ecf20Sopenharmony_ci		 * count is reset.
5348c2ecf20Sopenharmony_ci		 */
5358c2ecf20Sopenharmony_ci		smp_mb__before_atomic();
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci		/*
5388c2ecf20Sopenharmony_ci		 * For concurrent callers of this, the one that failed the
5398c2ecf20Sopenharmony_ci		 * atomic_cmpxhcg() race should call this function again
5408c2ecf20Sopenharmony_ci		 * to wakeup a new batch on a different 'ws'.
5418c2ecf20Sopenharmony_ci		 */
5428c2ecf20Sopenharmony_ci		ret = atomic_cmpxchg(&ws->wait_cnt, wait_cnt, wake_batch);
5438c2ecf20Sopenharmony_ci		if (ret == wait_cnt) {
5448c2ecf20Sopenharmony_ci			sbq_index_atomic_inc(&sbq->wake_index);
5458c2ecf20Sopenharmony_ci			wake_up_nr(&ws->wait, wake_batch);
5468c2ecf20Sopenharmony_ci			return false;
5478c2ecf20Sopenharmony_ci		}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci		return true;
5508c2ecf20Sopenharmony_ci	}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	return false;
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_civoid sbitmap_queue_wake_up(struct sbitmap_queue *sbq)
5568c2ecf20Sopenharmony_ci{
5578c2ecf20Sopenharmony_ci	while (__sbq_wake_up(sbq))
5588c2ecf20Sopenharmony_ci		;
5598c2ecf20Sopenharmony_ci}
5608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_queue_wake_up);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_civoid sbitmap_queue_clear(struct sbitmap_queue *sbq, unsigned int nr,
5638c2ecf20Sopenharmony_ci			 unsigned int cpu)
5648c2ecf20Sopenharmony_ci{
5658c2ecf20Sopenharmony_ci	/*
5668c2ecf20Sopenharmony_ci	 * Once the clear bit is set, the bit may be allocated out.
5678c2ecf20Sopenharmony_ci	 *
5688c2ecf20Sopenharmony_ci	 * Orders READ/WRITE on the asssociated instance(such as request
5698c2ecf20Sopenharmony_ci	 * of blk_mq) by this bit for avoiding race with re-allocation,
5708c2ecf20Sopenharmony_ci	 * and its pair is the memory barrier implied in __sbitmap_get_word.
5718c2ecf20Sopenharmony_ci	 *
5728c2ecf20Sopenharmony_ci	 * One invariant is that the clear bit has to be zero when the bit
5738c2ecf20Sopenharmony_ci	 * is in use.
5748c2ecf20Sopenharmony_ci	 */
5758c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
5768c2ecf20Sopenharmony_ci	sbitmap_deferred_clear_bit(&sbq->sb, nr);
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	/*
5798c2ecf20Sopenharmony_ci	 * Pairs with the memory barrier in set_current_state() to ensure the
5808c2ecf20Sopenharmony_ci	 * proper ordering of clear_bit_unlock()/waitqueue_active() in the waker
5818c2ecf20Sopenharmony_ci	 * and test_and_set_bit_lock()/prepare_to_wait()/finish_wait() in the
5828c2ecf20Sopenharmony_ci	 * waiter. See the comment on waitqueue_active().
5838c2ecf20Sopenharmony_ci	 */
5848c2ecf20Sopenharmony_ci	smp_mb__after_atomic();
5858c2ecf20Sopenharmony_ci	sbitmap_queue_wake_up(sbq);
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	if (likely(!sbq->round_robin && nr < sbq->sb.depth))
5888c2ecf20Sopenharmony_ci		*per_cpu_ptr(sbq->alloc_hint, cpu) = nr;
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_queue_clear);
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_civoid sbitmap_queue_wake_all(struct sbitmap_queue *sbq)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	int i, wake_index;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	/*
5978c2ecf20Sopenharmony_ci	 * Pairs with the memory barrier in set_current_state() like in
5988c2ecf20Sopenharmony_ci	 * sbitmap_queue_wake_up().
5998c2ecf20Sopenharmony_ci	 */
6008c2ecf20Sopenharmony_ci	smp_mb();
6018c2ecf20Sopenharmony_ci	wake_index = atomic_read(&sbq->wake_index);
6028c2ecf20Sopenharmony_ci	for (i = 0; i < SBQ_WAIT_QUEUES; i++) {
6038c2ecf20Sopenharmony_ci		struct sbq_wait_state *ws = &sbq->ws[wake_index];
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci		if (waitqueue_active(&ws->wait))
6068c2ecf20Sopenharmony_ci			wake_up(&ws->wait);
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci		wake_index = sbq_index_inc(wake_index);
6098c2ecf20Sopenharmony_ci	}
6108c2ecf20Sopenharmony_ci}
6118c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_queue_wake_all);
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_civoid sbitmap_queue_show(struct sbitmap_queue *sbq, struct seq_file *m)
6148c2ecf20Sopenharmony_ci{
6158c2ecf20Sopenharmony_ci	bool first;
6168c2ecf20Sopenharmony_ci	int i;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	sbitmap_show(&sbq->sb, m);
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	seq_puts(m, "alloc_hint={");
6218c2ecf20Sopenharmony_ci	first = true;
6228c2ecf20Sopenharmony_ci	for_each_possible_cpu(i) {
6238c2ecf20Sopenharmony_ci		if (!first)
6248c2ecf20Sopenharmony_ci			seq_puts(m, ", ");
6258c2ecf20Sopenharmony_ci		first = false;
6268c2ecf20Sopenharmony_ci		seq_printf(m, "%u", *per_cpu_ptr(sbq->alloc_hint, i));
6278c2ecf20Sopenharmony_ci	}
6288c2ecf20Sopenharmony_ci	seq_puts(m, "}\n");
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	seq_printf(m, "wake_batch=%u\n", sbq->wake_batch);
6318c2ecf20Sopenharmony_ci	seq_printf(m, "wake_index=%d\n", atomic_read(&sbq->wake_index));
6328c2ecf20Sopenharmony_ci	seq_printf(m, "ws_active=%d\n", atomic_read(&sbq->ws_active));
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	seq_puts(m, "ws={\n");
6358c2ecf20Sopenharmony_ci	for (i = 0; i < SBQ_WAIT_QUEUES; i++) {
6368c2ecf20Sopenharmony_ci		struct sbq_wait_state *ws = &sbq->ws[i];
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci		seq_printf(m, "\t{.wait_cnt=%d, .wait=%s},\n",
6398c2ecf20Sopenharmony_ci			   atomic_read(&ws->wait_cnt),
6408c2ecf20Sopenharmony_ci			   waitqueue_active(&ws->wait) ? "active" : "inactive");
6418c2ecf20Sopenharmony_ci	}
6428c2ecf20Sopenharmony_ci	seq_puts(m, "}\n");
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	seq_printf(m, "round_robin=%d\n", sbq->round_robin);
6458c2ecf20Sopenharmony_ci	seq_printf(m, "min_shallow_depth=%u\n", sbq->min_shallow_depth);
6468c2ecf20Sopenharmony_ci}
6478c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_queue_show);
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_civoid sbitmap_add_wait_queue(struct sbitmap_queue *sbq,
6508c2ecf20Sopenharmony_ci			    struct sbq_wait_state *ws,
6518c2ecf20Sopenharmony_ci			    struct sbq_wait *sbq_wait)
6528c2ecf20Sopenharmony_ci{
6538c2ecf20Sopenharmony_ci	if (!sbq_wait->sbq) {
6548c2ecf20Sopenharmony_ci		sbq_wait->sbq = sbq;
6558c2ecf20Sopenharmony_ci		atomic_inc(&sbq->ws_active);
6568c2ecf20Sopenharmony_ci		add_wait_queue(&ws->wait, &sbq_wait->wait);
6578c2ecf20Sopenharmony_ci	}
6588c2ecf20Sopenharmony_ci}
6598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_add_wait_queue);
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_civoid sbitmap_del_wait_queue(struct sbq_wait *sbq_wait)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	list_del_init(&sbq_wait->wait.entry);
6648c2ecf20Sopenharmony_ci	if (sbq_wait->sbq) {
6658c2ecf20Sopenharmony_ci		atomic_dec(&sbq_wait->sbq->ws_active);
6668c2ecf20Sopenharmony_ci		sbq_wait->sbq = NULL;
6678c2ecf20Sopenharmony_ci	}
6688c2ecf20Sopenharmony_ci}
6698c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_del_wait_queue);
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_civoid sbitmap_prepare_to_wait(struct sbitmap_queue *sbq,
6728c2ecf20Sopenharmony_ci			     struct sbq_wait_state *ws,
6738c2ecf20Sopenharmony_ci			     struct sbq_wait *sbq_wait, int state)
6748c2ecf20Sopenharmony_ci{
6758c2ecf20Sopenharmony_ci	if (!sbq_wait->sbq) {
6768c2ecf20Sopenharmony_ci		atomic_inc(&sbq->ws_active);
6778c2ecf20Sopenharmony_ci		sbq_wait->sbq = sbq;
6788c2ecf20Sopenharmony_ci	}
6798c2ecf20Sopenharmony_ci	prepare_to_wait_exclusive(&ws->wait, &sbq_wait->wait, state);
6808c2ecf20Sopenharmony_ci}
6818c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_prepare_to_wait);
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_civoid sbitmap_finish_wait(struct sbitmap_queue *sbq, struct sbq_wait_state *ws,
6848c2ecf20Sopenharmony_ci			 struct sbq_wait *sbq_wait)
6858c2ecf20Sopenharmony_ci{
6868c2ecf20Sopenharmony_ci	finish_wait(&ws->wait, &sbq_wait->wait);
6878c2ecf20Sopenharmony_ci	if (sbq_wait->sbq) {
6888c2ecf20Sopenharmony_ci		atomic_dec(&sbq->ws_active);
6898c2ecf20Sopenharmony_ci		sbq_wait->sbq = NULL;
6908c2ecf20Sopenharmony_ci	}
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sbitmap_finish_wait);
693