1 /*
2  * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
3  * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
4  * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2
8  * as published by the Free Software Foundation
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  */
15 
16 #include <linux/etherdevice.h>
17 #include "mt76x0.h"
18 
19 static int
20 mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
21 {
22 	int ret;
23 
24 	cancel_delayed_work_sync(&dev->cal_work);
25 	if (mt76_is_mmio(dev)) {
26 		tasklet_disable(&dev->pre_tbtt_tasklet);
27 		tasklet_disable(&dev->dfs_pd.dfs_tasklet);
28 	}
29 
30 	mt76_set_channel(&dev->mt76);
31 	ret = mt76x0_phy_set_channel(dev, chandef);
32 
33 	/* channel cycle counters read-and-clear */
34 	mt76_rr(dev, MT_CH_IDLE);
35 	mt76_rr(dev, MT_CH_BUSY);
36 
37 	if (mt76_is_mmio(dev)) {
38 		mt76x02_dfs_init_params(dev);
39 		tasklet_enable(&dev->pre_tbtt_tasklet);
40 		tasklet_enable(&dev->dfs_pd.dfs_tasklet);
41 	}
42 	mt76_txq_schedule_all(&dev->mt76);
43 
44 	return ret;
45 }
46 
47 int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
48 {
49 	struct mt76x02_dev *dev = hw->priv;
50 	int ret = 0;
51 
52 	mutex_lock(&dev->mt76.mutex);
53 
54 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
55 		ieee80211_stop_queues(hw);
56 		ret = mt76x0_set_channel(dev, &hw->conf.chandef);
57 		ieee80211_wake_queues(hw);
58 	}
59 
60 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
61 		dev->mt76.txpower_conf = hw->conf.power_level * 2;
62 
63 		if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
64 			mt76x0_phy_set_txpower(dev);
65 	}
66 
67 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
68 		if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
69 			dev->mt76.rxfilter |= MT_RX_FILTR_CFG_PROMISC;
70 		else
71 			dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
72 
73 		mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
74 	}
75 
76 	mutex_unlock(&dev->mt76.mutex);
77 
78 	return ret;
79 }
80 EXPORT_SYMBOL_GPL(mt76x0_config);
81