0001
0002
0003
0004
0005
0006 #include <linux/module.h>
0007 #include "mt76.h"
0008
0009 bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
0010 int timeout)
0011 {
0012 u32 cur;
0013
0014 timeout /= 10;
0015 do {
0016 cur = __mt76_rr(dev, offset) & mask;
0017 if (cur == val)
0018 return true;
0019
0020 udelay(10);
0021 } while (timeout-- > 0);
0022
0023 return false;
0024 }
0025 EXPORT_SYMBOL_GPL(__mt76_poll);
0026
0027 bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
0028 int timeout)
0029 {
0030 u32 cur;
0031
0032 timeout /= 10;
0033 do {
0034 cur = __mt76_rr(dev, offset) & mask;
0035 if (cur == val)
0036 return true;
0037
0038 usleep_range(10000, 20000);
0039 } while (timeout-- > 0);
0040
0041 return false;
0042 }
0043 EXPORT_SYMBOL_GPL(__mt76_poll_msec);
0044
0045 int mt76_wcid_alloc(u32 *mask, int size)
0046 {
0047 int i, idx = 0, cur;
0048
0049 for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
0050 idx = ffs(~mask[i]);
0051 if (!idx)
0052 continue;
0053
0054 idx--;
0055 cur = i * 32 + idx;
0056 if (cur >= size)
0057 break;
0058
0059 mask[i] |= BIT(idx);
0060 return cur;
0061 }
0062
0063 return -1;
0064 }
0065 EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
0066
0067 int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy)
0068 {
0069 struct mt76_wcid *wcid;
0070 int i, j, min_rssi = 0;
0071 s8 cur_rssi;
0072
0073 local_bh_disable();
0074 rcu_read_lock();
0075
0076 for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
0077 u32 mask = dev->wcid_mask[i];
0078 u32 phy_mask = dev->wcid_phy_mask[i];
0079
0080 if (!mask)
0081 continue;
0082
0083 for (j = i * 32; mask; j++, mask >>= 1, phy_mask >>= 1) {
0084 if (!(mask & 1))
0085 continue;
0086
0087 if (!!(phy_mask & 1) != ext_phy)
0088 continue;
0089
0090 wcid = rcu_dereference(dev->wcid[j]);
0091 if (!wcid)
0092 continue;
0093
0094 spin_lock(&dev->rx_lock);
0095 if (wcid->inactive_count++ < 5)
0096 cur_rssi = -ewma_signal_read(&wcid->rssi);
0097 else
0098 cur_rssi = 0;
0099 spin_unlock(&dev->rx_lock);
0100
0101 if (cur_rssi < min_rssi)
0102 min_rssi = cur_rssi;
0103 }
0104 }
0105
0106 rcu_read_unlock();
0107 local_bh_enable();
0108
0109 return min_rssi;
0110 }
0111 EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi);
0112
0113 int __mt76_worker_fn(void *ptr)
0114 {
0115 struct mt76_worker *w = ptr;
0116
0117 while (!kthread_should_stop()) {
0118 set_current_state(TASK_INTERRUPTIBLE);
0119
0120 if (kthread_should_park()) {
0121 kthread_parkme();
0122 continue;
0123 }
0124
0125 if (!test_and_clear_bit(MT76_WORKER_SCHEDULED, &w->state)) {
0126 schedule();
0127 continue;
0128 }
0129
0130 set_bit(MT76_WORKER_RUNNING, &w->state);
0131 set_current_state(TASK_RUNNING);
0132 w->fn(w);
0133 cond_resched();
0134 clear_bit(MT76_WORKER_RUNNING, &w->state);
0135 }
0136
0137 return 0;
0138 }
0139 EXPORT_SYMBOL_GPL(__mt76_worker_fn);
0140
0141 MODULE_LICENSE("Dual BSD/GPL");