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