10e3d6777SRyder Lee // SPDX-License-Identifier: ISC
217f1de56SFelix Fietkau /*
317f1de56SFelix Fietkau * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
417f1de56SFelix Fietkau */
517f1de56SFelix Fietkau
617f1de56SFelix Fietkau #include <linux/module.h>
717f1de56SFelix Fietkau #include "mt76.h"
817f1de56SFelix Fietkau
__mt76_poll(struct mt76_dev * dev,u32 offset,u32 mask,u32 val,int timeout)917f1de56SFelix Fietkau bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
1017f1de56SFelix Fietkau int timeout)
1117f1de56SFelix Fietkau {
1217f1de56SFelix Fietkau u32 cur;
1317f1de56SFelix Fietkau
1417f1de56SFelix Fietkau timeout /= 10;
1517f1de56SFelix Fietkau do {
164a58d5d1SLorenzo Bianconi cur = __mt76_rr(dev, offset) & mask;
1717f1de56SFelix Fietkau if (cur == val)
1817f1de56SFelix Fietkau return true;
1917f1de56SFelix Fietkau
2017f1de56SFelix Fietkau udelay(10);
2117f1de56SFelix Fietkau } while (timeout-- > 0);
2217f1de56SFelix Fietkau
2317f1de56SFelix Fietkau return false;
2417f1de56SFelix Fietkau }
2517f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(__mt76_poll);
2617f1de56SFelix Fietkau
____mt76_poll_msec(struct mt76_dev * dev,u32 offset,u32 mask,u32 val,int timeout,int tick)27*35effe6cSDeren Wu bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
28*35effe6cSDeren Wu int timeout, int tick)
2917f1de56SFelix Fietkau {
3017f1de56SFelix Fietkau u32 cur;
3117f1de56SFelix Fietkau
32*35effe6cSDeren Wu timeout /= tick;
3317f1de56SFelix Fietkau do {
344a58d5d1SLorenzo Bianconi cur = __mt76_rr(dev, offset) & mask;
3517f1de56SFelix Fietkau if (cur == val)
3617f1de56SFelix Fietkau return true;
3717f1de56SFelix Fietkau
38*35effe6cSDeren Wu usleep_range(1000 * tick, 2000 * tick);
3917f1de56SFelix Fietkau } while (timeout-- > 0);
4017f1de56SFelix Fietkau
4117f1de56SFelix Fietkau return false;
4217f1de56SFelix Fietkau }
43*35effe6cSDeren Wu EXPORT_SYMBOL_GPL(____mt76_poll_msec);
4417f1de56SFelix Fietkau
mt76_wcid_alloc(u32 * mask,int size)455e616ad2SFelix Fietkau int mt76_wcid_alloc(u32 *mask, int size)
4617f1de56SFelix Fietkau {
4717f1de56SFelix Fietkau int i, idx = 0, cur;
4817f1de56SFelix Fietkau
495e616ad2SFelix Fietkau for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
5017f1de56SFelix Fietkau idx = ffs(~mask[i]);
5117f1de56SFelix Fietkau if (!idx)
5217f1de56SFelix Fietkau continue;
5317f1de56SFelix Fietkau
5417f1de56SFelix Fietkau idx--;
555e616ad2SFelix Fietkau cur = i * 32 + idx;
5617f1de56SFelix Fietkau if (cur >= size)
5717f1de56SFelix Fietkau break;
5817f1de56SFelix Fietkau
5917f1de56SFelix Fietkau mask[i] |= BIT(idx);
6017f1de56SFelix Fietkau return cur;
6117f1de56SFelix Fietkau }
6217f1de56SFelix Fietkau
6317f1de56SFelix Fietkau return -1;
6417f1de56SFelix Fietkau }
6517f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
6617f1de56SFelix Fietkau
mt76_get_min_avg_rssi(struct mt76_dev * dev,bool ext_phy)678af63fedSFelix Fietkau int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy)
68ef13edc0SFelix Fietkau {
69ef13edc0SFelix Fietkau struct mt76_wcid *wcid;
70ef13edc0SFelix Fietkau int i, j, min_rssi = 0;
71ef13edc0SFelix Fietkau s8 cur_rssi;
72ef13edc0SFelix Fietkau
73ef13edc0SFelix Fietkau local_bh_disable();
74ef13edc0SFelix Fietkau rcu_read_lock();
75ef13edc0SFelix Fietkau
76ef13edc0SFelix Fietkau for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
775e616ad2SFelix Fietkau u32 mask = dev->wcid_mask[i];
785e616ad2SFelix Fietkau u32 phy_mask = dev->wcid_phy_mask[i];
79ef13edc0SFelix Fietkau
80ef13edc0SFelix Fietkau if (!mask)
81ef13edc0SFelix Fietkau continue;
82ef13edc0SFelix Fietkau
835e616ad2SFelix Fietkau for (j = i * 32; mask; j++, mask >>= 1, phy_mask >>= 1) {
84ef13edc0SFelix Fietkau if (!(mask & 1))
85ef13edc0SFelix Fietkau continue;
86ef13edc0SFelix Fietkau
878af63fedSFelix Fietkau if (!!(phy_mask & 1) != ext_phy)
888af63fedSFelix Fietkau continue;
898af63fedSFelix Fietkau
90ef13edc0SFelix Fietkau wcid = rcu_dereference(dev->wcid[j]);
91ef13edc0SFelix Fietkau if (!wcid)
92ef13edc0SFelix Fietkau continue;
93ef13edc0SFelix Fietkau
94ef13edc0SFelix Fietkau spin_lock(&dev->rx_lock);
95ef13edc0SFelix Fietkau if (wcid->inactive_count++ < 5)
9602e5a769SFelix Fietkau cur_rssi = -ewma_signal_read(&wcid->rssi);
97ef13edc0SFelix Fietkau else
98ef13edc0SFelix Fietkau cur_rssi = 0;
99ef13edc0SFelix Fietkau spin_unlock(&dev->rx_lock);
100ef13edc0SFelix Fietkau
101ef13edc0SFelix Fietkau if (cur_rssi < min_rssi)
102ef13edc0SFelix Fietkau min_rssi = cur_rssi;
103ef13edc0SFelix Fietkau }
104ef13edc0SFelix Fietkau }
105ef13edc0SFelix Fietkau
106ef13edc0SFelix Fietkau rcu_read_unlock();
107ef13edc0SFelix Fietkau local_bh_enable();
108ef13edc0SFelix Fietkau
109ef13edc0SFelix Fietkau return min_rssi;
110ef13edc0SFelix Fietkau }
111ef13edc0SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi);
112ef13edc0SFelix Fietkau
__mt76_worker_fn(void * ptr)11330bdd692SFelix Fietkau int __mt76_worker_fn(void *ptr)
11430bdd692SFelix Fietkau {
11530bdd692SFelix Fietkau struct mt76_worker *w = ptr;
11630bdd692SFelix Fietkau
11730bdd692SFelix Fietkau while (!kthread_should_stop()) {
11830bdd692SFelix Fietkau set_current_state(TASK_INTERRUPTIBLE);
11930bdd692SFelix Fietkau
12030bdd692SFelix Fietkau if (kthread_should_park()) {
12130bdd692SFelix Fietkau kthread_parkme();
12230bdd692SFelix Fietkau continue;
12330bdd692SFelix Fietkau }
12430bdd692SFelix Fietkau
12530bdd692SFelix Fietkau if (!test_and_clear_bit(MT76_WORKER_SCHEDULED, &w->state)) {
12630bdd692SFelix Fietkau schedule();
12730bdd692SFelix Fietkau continue;
12830bdd692SFelix Fietkau }
12930bdd692SFelix Fietkau
13030bdd692SFelix Fietkau set_bit(MT76_WORKER_RUNNING, &w->state);
13130bdd692SFelix Fietkau set_current_state(TASK_RUNNING);
13230bdd692SFelix Fietkau w->fn(w);
13330bdd692SFelix Fietkau cond_resched();
13430bdd692SFelix Fietkau clear_bit(MT76_WORKER_RUNNING, &w->state);
13530bdd692SFelix Fietkau }
13630bdd692SFelix Fietkau
13730bdd692SFelix Fietkau return 0;
13830bdd692SFelix Fietkau }
13930bdd692SFelix Fietkau EXPORT_SYMBOL_GPL(__mt76_worker_fn);
14030bdd692SFelix Fietkau
14117f1de56SFelix Fietkau MODULE_LICENSE("Dual BSD/GPL");
142