| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: ISC |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> |
|---|
| 3 | | - * |
|---|
| 4 | | - * Permission to use, copy, modify, and/or distribute this software for any |
|---|
| 5 | | - * purpose with or without fee is hereby granted, provided that the above |
|---|
| 6 | | - * copyright notice and this permission notice appear in all copies. |
|---|
| 7 | | - * |
|---|
| 8 | | - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|---|
| 9 | | - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|---|
| 10 | | - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|---|
| 11 | | - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|---|
| 12 | | - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|---|
| 13 | | - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|---|
| 14 | | - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|---|
| 15 | 4 | */ |
|---|
| 16 | 5 | |
|---|
| 17 | 6 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 24 | 13 | |
|---|
| 25 | 14 | timeout /= 10; |
|---|
| 26 | 15 | do { |
|---|
| 27 | | - cur = dev->bus->rr(dev, offset) & mask; |
|---|
| 16 | + cur = __mt76_rr(dev, offset) & mask; |
|---|
| 28 | 17 | if (cur == val) |
|---|
| 29 | 18 | return true; |
|---|
| 30 | 19 | |
|---|
| .. | .. |
|---|
| 42 | 31 | |
|---|
| 43 | 32 | timeout /= 10; |
|---|
| 44 | 33 | do { |
|---|
| 45 | | - cur = dev->bus->rr(dev, offset) & mask; |
|---|
| 34 | + cur = __mt76_rr(dev, offset) & mask; |
|---|
| 46 | 35 | if (cur == val) |
|---|
| 47 | 36 | return true; |
|---|
| 48 | 37 | |
|---|
| .. | .. |
|---|
| 53 | 42 | } |
|---|
| 54 | 43 | EXPORT_SYMBOL_GPL(__mt76_poll_msec); |
|---|
| 55 | 44 | |
|---|
| 56 | | -int mt76_wcid_alloc(unsigned long *mask, int size) |
|---|
| 45 | +int mt76_wcid_alloc(u32 *mask, int size) |
|---|
| 57 | 46 | { |
|---|
| 58 | 47 | int i, idx = 0, cur; |
|---|
| 59 | 48 | |
|---|
| 60 | | - for (i = 0; i < size / BITS_PER_LONG; i++) { |
|---|
| 49 | + for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { |
|---|
| 61 | 50 | idx = ffs(~mask[i]); |
|---|
| 62 | 51 | if (!idx) |
|---|
| 63 | 52 | continue; |
|---|
| 64 | 53 | |
|---|
| 65 | 54 | idx--; |
|---|
| 66 | | - cur = i * BITS_PER_LONG + idx; |
|---|
| 55 | + cur = i * 32 + idx; |
|---|
| 67 | 56 | if (cur >= size) |
|---|
| 68 | 57 | break; |
|---|
| 69 | 58 | |
|---|
| .. | .. |
|---|
| 75 | 64 | } |
|---|
| 76 | 65 | EXPORT_SYMBOL_GPL(mt76_wcid_alloc); |
|---|
| 77 | 66 | |
|---|
| 67 | +int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy) |
|---|
| 68 | +{ |
|---|
| 69 | + struct mt76_wcid *wcid; |
|---|
| 70 | + int i, j, min_rssi = 0; |
|---|
| 71 | + s8 cur_rssi; |
|---|
| 72 | + |
|---|
| 73 | + local_bh_disable(); |
|---|
| 74 | + rcu_read_lock(); |
|---|
| 75 | + |
|---|
| 76 | + for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { |
|---|
| 77 | + u32 mask = dev->wcid_mask[i]; |
|---|
| 78 | + u32 phy_mask = dev->wcid_phy_mask[i]; |
|---|
| 79 | + |
|---|
| 80 | + if (!mask) |
|---|
| 81 | + continue; |
|---|
| 82 | + |
|---|
| 83 | + for (j = i * 32; mask; j++, mask >>= 1, phy_mask >>= 1) { |
|---|
| 84 | + if (!(mask & 1)) |
|---|
| 85 | + continue; |
|---|
| 86 | + |
|---|
| 87 | + if (!!(phy_mask & 1) != ext_phy) |
|---|
| 88 | + continue; |
|---|
| 89 | + |
|---|
| 90 | + wcid = rcu_dereference(dev->wcid[j]); |
|---|
| 91 | + if (!wcid) |
|---|
| 92 | + continue; |
|---|
| 93 | + |
|---|
| 94 | + spin_lock(&dev->rx_lock); |
|---|
| 95 | + if (wcid->inactive_count++ < 5) |
|---|
| 96 | + cur_rssi = -ewma_signal_read(&wcid->rssi); |
|---|
| 97 | + else |
|---|
| 98 | + cur_rssi = 0; |
|---|
| 99 | + spin_unlock(&dev->rx_lock); |
|---|
| 100 | + |
|---|
| 101 | + if (cur_rssi < min_rssi) |
|---|
| 102 | + min_rssi = cur_rssi; |
|---|
| 103 | + } |
|---|
| 104 | + } |
|---|
| 105 | + |
|---|
| 106 | + rcu_read_unlock(); |
|---|
| 107 | + local_bh_enable(); |
|---|
| 108 | + |
|---|
| 109 | + return min_rssi; |
|---|
| 110 | +} |
|---|
| 111 | +EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi); |
|---|
| 112 | + |
|---|
| 113 | +int __mt76_worker_fn(void *ptr) |
|---|
| 114 | +{ |
|---|
| 115 | + struct mt76_worker *w = ptr; |
|---|
| 116 | + |
|---|
| 117 | + while (!kthread_should_stop()) { |
|---|
| 118 | + set_current_state(TASK_INTERRUPTIBLE); |
|---|
| 119 | + |
|---|
| 120 | + if (kthread_should_park()) { |
|---|
| 121 | + kthread_parkme(); |
|---|
| 122 | + continue; |
|---|
| 123 | + } |
|---|
| 124 | + |
|---|
| 125 | + if (!test_and_clear_bit(MT76_WORKER_SCHEDULED, &w->state)) { |
|---|
| 126 | + schedule(); |
|---|
| 127 | + continue; |
|---|
| 128 | + } |
|---|
| 129 | + |
|---|
| 130 | + set_bit(MT76_WORKER_RUNNING, &w->state); |
|---|
| 131 | + set_current_state(TASK_RUNNING); |
|---|
| 132 | + w->fn(w); |
|---|
| 133 | + cond_resched(); |
|---|
| 134 | + clear_bit(MT76_WORKER_RUNNING, &w->state); |
|---|
| 135 | + } |
|---|
| 136 | + |
|---|
| 137 | + return 0; |
|---|
| 138 | +} |
|---|
| 139 | +EXPORT_SYMBOL_GPL(__mt76_worker_fn); |
|---|
| 140 | + |
|---|
| 78 | 141 | MODULE_LICENSE("Dual BSD/GPL"); |
|---|