117f1de56SFelix Fietkau /*
217f1de56SFelix Fietkau  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
317f1de56SFelix Fietkau  *
417f1de56SFelix Fietkau  * Permission to use, copy, modify, and/or distribute this software for any
517f1de56SFelix Fietkau  * purpose with or without fee is hereby granted, provided that the above
617f1de56SFelix Fietkau  * copyright notice and this permission notice appear in all copies.
717f1de56SFelix Fietkau  *
817f1de56SFelix Fietkau  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
917f1de56SFelix Fietkau  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1017f1de56SFelix Fietkau  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1117f1de56SFelix Fietkau  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1217f1de56SFelix Fietkau  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1317f1de56SFelix Fietkau  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1417f1de56SFelix Fietkau  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1517f1de56SFelix Fietkau  */
1617f1de56SFelix Fietkau 
1717f1de56SFelix Fietkau #include <linux/module.h>
1817f1de56SFelix Fietkau #include "mt76.h"
1917f1de56SFelix Fietkau 
2017f1de56SFelix Fietkau bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
2117f1de56SFelix Fietkau 		 int timeout)
2217f1de56SFelix Fietkau {
2317f1de56SFelix Fietkau 	u32 cur;
2417f1de56SFelix Fietkau 
2517f1de56SFelix Fietkau 	timeout /= 10;
2617f1de56SFelix Fietkau 	do {
2717f1de56SFelix Fietkau 		cur = dev->bus->rr(dev, offset) & mask;
2817f1de56SFelix Fietkau 		if (cur == val)
2917f1de56SFelix Fietkau 			return true;
3017f1de56SFelix Fietkau 
3117f1de56SFelix Fietkau 		udelay(10);
3217f1de56SFelix Fietkau 	} while (timeout-- > 0);
3317f1de56SFelix Fietkau 
3417f1de56SFelix Fietkau 	return false;
3517f1de56SFelix Fietkau }
3617f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(__mt76_poll);
3717f1de56SFelix Fietkau 
3817f1de56SFelix Fietkau bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
3917f1de56SFelix Fietkau 		      int timeout)
4017f1de56SFelix Fietkau {
4117f1de56SFelix Fietkau 	u32 cur;
4217f1de56SFelix Fietkau 
4317f1de56SFelix Fietkau 	timeout /= 10;
4417f1de56SFelix Fietkau 	do {
4517f1de56SFelix Fietkau 		cur = dev->bus->rr(dev, offset) & mask;
4617f1de56SFelix Fietkau 		if (cur == val)
4717f1de56SFelix Fietkau 			return true;
4817f1de56SFelix Fietkau 
4917f1de56SFelix Fietkau 		usleep_range(10000, 20000);
5017f1de56SFelix Fietkau 	} while (timeout-- > 0);
5117f1de56SFelix Fietkau 
5217f1de56SFelix Fietkau 	return false;
5317f1de56SFelix Fietkau }
5417f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(__mt76_poll_msec);
5517f1de56SFelix Fietkau 
5617f1de56SFelix Fietkau int mt76_wcid_alloc(unsigned long *mask, int size)
5717f1de56SFelix Fietkau {
5817f1de56SFelix Fietkau 	int i, idx = 0, cur;
5917f1de56SFelix Fietkau 
6017f1de56SFelix Fietkau 	for (i = 0; i < size / BITS_PER_LONG; i++) {
6117f1de56SFelix Fietkau 		idx = ffs(~mask[i]);
6217f1de56SFelix Fietkau 		if (!idx)
6317f1de56SFelix Fietkau 			continue;
6417f1de56SFelix Fietkau 
6517f1de56SFelix Fietkau 		idx--;
6617f1de56SFelix Fietkau 		cur = i * BITS_PER_LONG + idx;
6717f1de56SFelix Fietkau 		if (cur >= size)
6817f1de56SFelix Fietkau 			break;
6917f1de56SFelix Fietkau 
7017f1de56SFelix Fietkau 		mask[i] |= BIT(idx);
7117f1de56SFelix Fietkau 		return cur;
7217f1de56SFelix Fietkau 	}
7317f1de56SFelix Fietkau 
7417f1de56SFelix Fietkau 	return -1;
7517f1de56SFelix Fietkau }
7617f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
7717f1de56SFelix Fietkau 
78ef13edc0SFelix Fietkau int mt76_get_min_avg_rssi(struct mt76_dev *dev)
79ef13edc0SFelix Fietkau {
80ef13edc0SFelix Fietkau 	struct mt76_wcid *wcid;
81ef13edc0SFelix Fietkau 	int i, j, min_rssi = 0;
82ef13edc0SFelix Fietkau 	s8 cur_rssi;
83ef13edc0SFelix Fietkau 
84ef13edc0SFelix Fietkau 	local_bh_disable();
85ef13edc0SFelix Fietkau 	rcu_read_lock();
86ef13edc0SFelix Fietkau 
87ef13edc0SFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
88ef13edc0SFelix Fietkau 		unsigned long mask = dev->wcid_mask[i];
89ef13edc0SFelix Fietkau 
90ef13edc0SFelix Fietkau 		if (!mask)
91ef13edc0SFelix Fietkau 			continue;
92ef13edc0SFelix Fietkau 
93ef13edc0SFelix Fietkau 		for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
94ef13edc0SFelix Fietkau 			if (!(mask & 1))
95ef13edc0SFelix Fietkau 				continue;
96ef13edc0SFelix Fietkau 
97ef13edc0SFelix Fietkau 			wcid = rcu_dereference(dev->wcid[j]);
98ef13edc0SFelix Fietkau 			if (!wcid)
99ef13edc0SFelix Fietkau 				continue;
100ef13edc0SFelix Fietkau 
101ef13edc0SFelix Fietkau 			spin_lock(&dev->rx_lock);
102ef13edc0SFelix Fietkau 			if (wcid->inactive_count++ < 5)
103ef13edc0SFelix Fietkau 				cur_rssi = ewma_signal_read(&wcid->rssi);
104ef13edc0SFelix Fietkau 			else
105ef13edc0SFelix Fietkau 				cur_rssi = 0;
106ef13edc0SFelix Fietkau 			spin_unlock(&dev->rx_lock);
107ef13edc0SFelix Fietkau 
108ef13edc0SFelix Fietkau 			if (cur_rssi < min_rssi)
109ef13edc0SFelix Fietkau 				min_rssi = cur_rssi;
110ef13edc0SFelix Fietkau 		}
111ef13edc0SFelix Fietkau 	}
112ef13edc0SFelix Fietkau 
113ef13edc0SFelix Fietkau 	rcu_read_unlock();
114ef13edc0SFelix Fietkau 	local_bh_enable();
115ef13edc0SFelix Fietkau 
116ef13edc0SFelix Fietkau 	return min_rssi;
117ef13edc0SFelix Fietkau }
118ef13edc0SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi);
119ef13edc0SFelix Fietkau 
12017f1de56SFelix Fietkau MODULE_LICENSE("Dual BSD/GPL");
121