143 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>4 */5 6#include <linux/module.h>7#include "mt76.h"8 9bool __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 = __mt76_rr(dev, offset) & mask;17 if (cur == val)18 return true;19 20 udelay(10);21 } while (timeout-- > 0);22 23 return false;24}25EXPORT_SYMBOL_GPL(__mt76_poll);26 27bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,28 int timeout, int tick)29{30 u32 cur;31 32 timeout /= tick;33 do {34 cur = __mt76_rr(dev, offset) & mask;35 if (cur == val)36 return true;37 38 usleep_range(1000 * tick, 2000 * tick);39 } while (timeout-- > 0);40 41 return false;42}43EXPORT_SYMBOL_GPL(____mt76_poll_msec);44 45int mt76_wcid_alloc(u32 *mask, int size)46{47 int i, idx = 0, cur;48 49 for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {50 idx = ffs(~mask[i]);51 if (!idx)52 continue;53 54 idx--;55 cur = i * 32 + idx;56 if (cur >= size)57 break;58 59 mask[i] |= BIT(idx);60 return cur;61 }62 63 return -1;64}65EXPORT_SYMBOL_GPL(mt76_wcid_alloc);66 67int 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 else98 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}111EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi);112 113int __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}139EXPORT_SYMBOL_GPL(__mt76_worker_fn);140 141MODULE_DESCRIPTION("MediaTek MT76x helpers");142MODULE_LICENSE("Dual BSD/GPL");143