1 // SPDX-License-Identifier: ISC 2 /* 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 */ 5 6 #include <linux/module.h> 7 #include "mt76.h" 8 9 bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, 10 int timeout) 11 { 12 u32 cur; 13 14 timeout /= 10; 15 do { 16 cur = dev->bus->rr(dev, offset) & mask; 17 if (cur == val) 18 return true; 19 20 udelay(10); 21 } while (timeout-- > 0); 22 23 return false; 24 } 25 EXPORT_SYMBOL_GPL(__mt76_poll); 26 27 bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, 28 int timeout) 29 { 30 u32 cur; 31 32 timeout /= 10; 33 do { 34 cur = dev->bus->rr(dev, offset) & mask; 35 if (cur == val) 36 return true; 37 38 usleep_range(10000, 20000); 39 } while (timeout-- > 0); 40 41 return false; 42 } 43 EXPORT_SYMBOL_GPL(__mt76_poll_msec); 44 45 int mt76_wcid_alloc(unsigned long *mask, int size) 46 { 47 int i, idx = 0, cur; 48 49 for (i = 0; i < size / BITS_PER_LONG; i++) { 50 idx = ffs(~mask[i]); 51 if (!idx) 52 continue; 53 54 idx--; 55 cur = i * BITS_PER_LONG + idx; 56 if (cur >= size) 57 break; 58 59 mask[i] |= BIT(idx); 60 return cur; 61 } 62 63 return -1; 64 } 65 EXPORT_SYMBOL_GPL(mt76_wcid_alloc); 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 unsigned long mask = dev->wcid_mask[i]; 78 unsigned long phy_mask = dev->wcid_phy_mask[i]; 79 80 if (!mask) 81 continue; 82 83 for (j = i * BITS_PER_LONG; 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 MODULE_LICENSE("Dual BSD/GPL"); 114