Commit | Line | Data |
---|---|---|
17f1de56 FF |
1 | /* |
2 | * 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 | */ | |
16 | ||
17 | #include <linux/module.h> | |
18 | #include "mt76.h" | |
19 | ||
20 | bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, | |
21 | int timeout) | |
22 | { | |
23 | u32 cur; | |
24 | ||
25 | timeout /= 10; | |
26 | do { | |
27 | cur = dev->bus->rr(dev, offset) & mask; | |
28 | if (cur == val) | |
29 | return true; | |
30 | ||
31 | udelay(10); | |
32 | } while (timeout-- > 0); | |
33 | ||
34 | return false; | |
35 | } | |
36 | EXPORT_SYMBOL_GPL(__mt76_poll); | |
37 | ||
38 | bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, | |
39 | int timeout) | |
40 | { | |
41 | u32 cur; | |
42 | ||
43 | timeout /= 10; | |
44 | do { | |
45 | cur = dev->bus->rr(dev, offset) & mask; | |
46 | if (cur == val) | |
47 | return true; | |
48 | ||
49 | usleep_range(10000, 20000); | |
50 | } while (timeout-- > 0); | |
51 | ||
52 | return false; | |
53 | } | |
54 | EXPORT_SYMBOL_GPL(__mt76_poll_msec); | |
55 | ||
56 | int mt76_wcid_alloc(unsigned long *mask, int size) | |
57 | { | |
58 | int i, idx = 0, cur; | |
59 | ||
60 | for (i = 0; i < size / BITS_PER_LONG; i++) { | |
61 | idx = ffs(~mask[i]); | |
62 | if (!idx) | |
63 | continue; | |
64 | ||
65 | idx--; | |
66 | cur = i * BITS_PER_LONG + idx; | |
67 | if (cur >= size) | |
68 | break; | |
69 | ||
70 | mask[i] |= BIT(idx); | |
71 | return cur; | |
72 | } | |
73 | ||
74 | return -1; | |
75 | } | |
76 | EXPORT_SYMBOL_GPL(mt76_wcid_alloc); | |
77 | ||
ef13edc0 FF |
78 | int mt76_get_min_avg_rssi(struct mt76_dev *dev) |
79 | { | |
80 | struct mt76_wcid *wcid; | |
81 | int i, j, min_rssi = 0; | |
82 | s8 cur_rssi; | |
83 | ||
84 | local_bh_disable(); | |
85 | rcu_read_lock(); | |
86 | ||
87 | for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { | |
88 | unsigned long mask = dev->wcid_mask[i]; | |
89 | ||
90 | if (!mask) | |
91 | continue; | |
92 | ||
93 | for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) { | |
94 | if (!(mask & 1)) | |
95 | continue; | |
96 | ||
97 | wcid = rcu_dereference(dev->wcid[j]); | |
98 | if (!wcid) | |
99 | continue; | |
100 | ||
101 | spin_lock(&dev->rx_lock); | |
102 | if (wcid->inactive_count++ < 5) | |
02e5a769 | 103 | cur_rssi = -ewma_signal_read(&wcid->rssi); |
ef13edc0 FF |
104 | else |
105 | cur_rssi = 0; | |
106 | spin_unlock(&dev->rx_lock); | |
107 | ||
108 | if (cur_rssi < min_rssi) | |
109 | min_rssi = cur_rssi; | |
110 | } | |
111 | } | |
112 | ||
113 | rcu_read_unlock(); | |
114 | local_bh_enable(); | |
115 | ||
116 | return min_rssi; | |
117 | } | |
118 | EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi); | |
119 | ||
17f1de56 | 120 | MODULE_LICENSE("Dual BSD/GPL"); |