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