xref: /openbmc/linux/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
10e3d6777SRyder Lee // SPDX-License-Identifier: ISC
21613c621SLorenzo Bianconi /*
31613c621SLorenzo Bianconi  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
41613c621SLorenzo Bianconi  */
51613c621SLorenzo Bianconi 
61613c621SLorenzo Bianconi #include "mt76x2.h"
7ad571c93SLorenzo Bianconi #include "../mt76x02_mac.h"
81613c621SLorenzo Bianconi 
91613c621SLorenzo Bianconi static int
mt76x2_start(struct ieee80211_hw * hw)101613c621SLorenzo Bianconi mt76x2_start(struct ieee80211_hw *hw)
111613c621SLorenzo Bianconi {
12e40803f2SLorenzo Bianconi 	struct mt76x02_dev *dev = hw->priv;
131613c621SLorenzo Bianconi 
14ad571c93SLorenzo Bianconi 	mt76x02_mac_start(dev);
15fd6c2dfaSFelix Fietkau 	mt76x2_phy_start(dev);
161613c621SLorenzo Bianconi 
17a782f8bfSLorenzo Bianconi 	ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
182e405024SFelix Fietkau 				     MT_MAC_WORK_INTERVAL);
19c1e0d2beSLorenzo Bianconi 	ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
20c1e0d2beSLorenzo Bianconi 				     MT_WATCHDOG_TIME);
211613c621SLorenzo Bianconi 
22011849e0SFelix Fietkau 	set_bit(MT76_STATE_RUNNING, &dev->mphy.state);
23091a79fdSStanislaw Gruszka 	return 0;
241613c621SLorenzo Bianconi }
251613c621SLorenzo Bianconi 
261613c621SLorenzo Bianconi static void
mt76x2_stop(struct ieee80211_hw * hw)271613c621SLorenzo Bianconi mt76x2_stop(struct ieee80211_hw *hw)
281613c621SLorenzo Bianconi {
29e40803f2SLorenzo Bianconi 	struct mt76x02_dev *dev = hw->priv;
301613c621SLorenzo Bianconi 
31011849e0SFelix Fietkau 	clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
321613c621SLorenzo Bianconi 	mt76x2_stop_hardware(dev);
331613c621SLorenzo Bianconi }
341613c621SLorenzo Bianconi 
35fd6c2dfaSFelix Fietkau static void
mt76x2_set_channel(struct mt76x02_dev * dev,struct cfg80211_chan_def * chandef)36e40803f2SLorenzo Bianconi mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
371613c621SLorenzo Bianconi {
381613c621SLorenzo Bianconi 	cancel_delayed_work_sync(&dev->cal_work);
396e4caaeaSLorenzo Bianconi 	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
406e4caaeaSLorenzo Bianconi 	tasklet_disable(&dev->dfs_pd.dfs_tasklet);
411613c621SLorenzo Bianconi 
426e4caaeaSLorenzo Bianconi 	mutex_lock(&dev->mt76.mutex);
43011849e0SFelix Fietkau 	set_bit(MT76_RESET, &dev->mphy.state);
441613c621SLorenzo Bianconi 
4596747a51SFelix Fietkau 	mt76_set_channel(&dev->mphy);
461613c621SLorenzo Bianconi 
471613c621SLorenzo Bianconi 	mt76x2_mac_stop(dev, true);
48fd6c2dfaSFelix Fietkau 	mt76x2_phy_set_channel(dev, chandef);
491613c621SLorenzo Bianconi 
50aec65e48SFelix Fietkau 	mt76x02_mac_cc_reset(dev);
51e6cb3291SLorenzo Bianconi 	mt76x02_dfs_init_params(dev);
521613c621SLorenzo Bianconi 
531613c621SLorenzo Bianconi 	mt76x2_mac_resume(dev);
541613c621SLorenzo Bianconi 
55011849e0SFelix Fietkau 	clear_bit(MT76_RESET, &dev->mphy.state);
566e4caaeaSLorenzo Bianconi 	mutex_unlock(&dev->mt76.mutex);
576e4caaeaSLorenzo Bianconi 
586e4caaeaSLorenzo Bianconi 	tasklet_enable(&dev->dfs_pd.dfs_tasklet);
596e4caaeaSLorenzo Bianconi 	tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
601613c621SLorenzo Bianconi 
619fba6d07SFelix Fietkau 	mt76_txq_schedule_all(&dev->mphy);
621613c621SLorenzo Bianconi }
631613c621SLorenzo Bianconi 
641613c621SLorenzo Bianconi static int
mt76x2_config(struct ieee80211_hw * hw,u32 changed)651613c621SLorenzo Bianconi mt76x2_config(struct ieee80211_hw *hw, u32 changed)
661613c621SLorenzo Bianconi {
67e40803f2SLorenzo Bianconi 	struct mt76x02_dev *dev = hw->priv;
681613c621SLorenzo Bianconi 
691613c621SLorenzo Bianconi 	mutex_lock(&dev->mt76.mutex);
701613c621SLorenzo Bianconi 
711613c621SLorenzo Bianconi 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
721613c621SLorenzo Bianconi 		if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
731613c621SLorenzo Bianconi 			dev->mt76.rxfilter |= MT_RX_FILTR_CFG_PROMISC;
741613c621SLorenzo Bianconi 		else
751613c621SLorenzo Bianconi 			dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
761613c621SLorenzo Bianconi 
771613c621SLorenzo Bianconi 		mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
781613c621SLorenzo Bianconi 	}
791613c621SLorenzo Bianconi 
801613c621SLorenzo Bianconi 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
81*633f77b5SLorenzo Bianconi 		struct mt76_phy *mphy = &dev->mphy;
821613c621SLorenzo Bianconi 
83*633f77b5SLorenzo Bianconi 		dev->txpower_conf = hw->conf.power_level * 2;
84*633f77b5SLorenzo Bianconi 		dev->txpower_conf = mt76_get_sar_power(mphy,
85*633f77b5SLorenzo Bianconi 						       mphy->chandef.chan,
86*633f77b5SLorenzo Bianconi 						       dev->txpower_conf);
871613c621SLorenzo Bianconi 		/* convert to per-chain power for 2x2 devices */
889e5f6dd7SFelix Fietkau 		dev->txpower_conf -= 6;
891613c621SLorenzo Bianconi 
90011849e0SFelix Fietkau 		if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
911613c621SLorenzo Bianconi 			mt76x2_phy_set_txpower(dev);
929e5f6dd7SFelix Fietkau 			mt76x02_tx_set_txpwr_auto(dev, dev->txpower_conf);
931613c621SLorenzo Bianconi 		}
941613c621SLorenzo Bianconi 	}
951613c621SLorenzo Bianconi 
966e4caaeaSLorenzo Bianconi 	mutex_unlock(&dev->mt76.mutex);
976e4caaeaSLorenzo Bianconi 
981613c621SLorenzo Bianconi 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
991613c621SLorenzo Bianconi 		ieee80211_stop_queues(hw);
100fd6c2dfaSFelix Fietkau 		mt76x2_set_channel(dev, &hw->conf.chandef);
1011613c621SLorenzo Bianconi 		ieee80211_wake_queues(hw);
1021613c621SLorenzo Bianconi 	}
1031613c621SLorenzo Bianconi 
104fd6c2dfaSFelix Fietkau 	return 0;
1051613c621SLorenzo Bianconi }
1061613c621SLorenzo Bianconi 
1071613c621SLorenzo Bianconi static void
mt76x2_flush(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u32 queues,bool drop)1081613c621SLorenzo Bianconi mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1091613c621SLorenzo Bianconi 	     u32 queues, bool drop)
1101613c621SLorenzo Bianconi {
1111613c621SLorenzo Bianconi }
1121613c621SLorenzo Bianconi 
mt76x2_set_antenna(struct ieee80211_hw * hw,u32 tx_ant,u32 rx_ant)1131613c621SLorenzo Bianconi static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
1141613c621SLorenzo Bianconi 			      u32 rx_ant)
1151613c621SLorenzo Bianconi {
116e40803f2SLorenzo Bianconi 	struct mt76x02_dev *dev = hw->priv;
1171613c621SLorenzo Bianconi 
1181613c621SLorenzo Bianconi 	if (!tx_ant || tx_ant > 3 || tx_ant != rx_ant)
1191613c621SLorenzo Bianconi 		return -EINVAL;
1201613c621SLorenzo Bianconi 
1211613c621SLorenzo Bianconi 	mutex_lock(&dev->mt76.mutex);
1221613c621SLorenzo Bianconi 
123b9027e08SLorenzo Bianconi 	dev->mphy.chainmask = (tx_ant == 3) ? 0x202 : 0x101;
124beaaeb6bSFelix Fietkau 	dev->mphy.antenna_mask = tx_ant;
1251613c621SLorenzo Bianconi 
126bb3e3fecSRyder Lee 	mt76_set_stream_caps(&dev->mphy, true);
1271613c621SLorenzo Bianconi 	mt76x2_phy_set_antenna(dev);
1281613c621SLorenzo Bianconi 
1291613c621SLorenzo Bianconi 	mutex_unlock(&dev->mt76.mutex);
1301613c621SLorenzo Bianconi 
1311613c621SLorenzo Bianconi 	return 0;
1321613c621SLorenzo Bianconi }
1331613c621SLorenzo Bianconi 
1341613c621SLorenzo Bianconi const struct ieee80211_ops mt76x2_ops = {
1352f0308d0SLorenzo Bianconi 	.tx = mt76x02_tx,
1361613c621SLorenzo Bianconi 	.start = mt76x2_start,
1371613c621SLorenzo Bianconi 	.stop = mt76x2_stop,
1381613c621SLorenzo Bianconi 	.add_interface = mt76x02_add_interface,
1391613c621SLorenzo Bianconi 	.remove_interface = mt76x02_remove_interface,
1401613c621SLorenzo Bianconi 	.config = mt76x2_config,
1411613c621SLorenzo Bianconi 	.configure_filter = mt76x02_configure_filter,
142cc726268SLorenzo Bianconi 	.bss_info_changed = mt76x02_bss_info_changed,
143e28487eaSFelix Fietkau 	.sta_state = mt76_sta_state,
14443ba1922SFelix Fietkau 	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
1451613c621SLorenzo Bianconi 	.set_key = mt76x02_set_key,
1461613c621SLorenzo Bianconi 	.conf_tx = mt76x02_conf_tx,
1478b8ab5c2SLorenzo Bianconi 	.sw_scan_start = mt76_sw_scan,
148c2756a1cSLorenzo Bianconi 	.sw_scan_complete = mt76x02_sw_scan_complete,
1491613c621SLorenzo Bianconi 	.flush = mt76x2_flush,
1501613c621SLorenzo Bianconi 	.ampdu_action = mt76x02_ampdu_action,
1519313faacSFelix Fietkau 	.get_txpower = mt76_get_txpower,
1521613c621SLorenzo Bianconi 	.wake_tx_queue = mt76_wake_tx_queue,
1531613c621SLorenzo Bianconi 	.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
1541613c621SLorenzo Bianconi 	.release_buffered_frames = mt76_release_buffered_frames,
15536704051SLorenzo Bianconi 	.set_coverage_class = mt76x02_set_coverage_class,
1561613c621SLorenzo Bianconi 	.get_survey = mt76_get_survey,
15787d53103SStanislaw Gruszka 	.set_tim = mt76_set_tim,
1581613c621SLorenzo Bianconi 	.set_antenna = mt76x2_set_antenna,
159e49c76d4SLorenzo Bianconi 	.get_antenna = mt76_get_antenna,
160317ed42bSLorenzo Bianconi 	.set_rts_threshold = mt76x02_set_rts_threshold,
161fd6c2dfaSFelix Fietkau 	.reconfig_complete = mt76x02_reconfig_complete,
162*633f77b5SLorenzo Bianconi 	.set_sar_specs = mt76x2_set_sar_specs,
1631613c621SLorenzo Bianconi };
1641613c621SLorenzo Bianconi 
165