10e3d6777SRyder Lee // SPDX-License-Identifier: ISC
21613c621SLorenzo Bianconi /*
31613c621SLorenzo Bianconi * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
41613c621SLorenzo Bianconi */
51613c621SLorenzo Bianconi
61613c621SLorenzo Bianconi #include "mt76x2u.h"
7fdb96b06SLorenzo Bianconi #include "../mt76x02_usb.h"
81613c621SLorenzo Bianconi
mt76x2u_start(struct ieee80211_hw * hw)91613c621SLorenzo Bianconi static int mt76x2u_start(struct ieee80211_hw *hw)
101613c621SLorenzo Bianconi {
11e40803f2SLorenzo Bianconi struct mt76x02_dev *dev = hw->priv;
121613c621SLorenzo Bianconi int ret;
131613c621SLorenzo Bianconi
14fdb96b06SLorenzo Bianconi ret = mt76x02u_mac_start(dev);
151613c621SLorenzo Bianconi if (ret)
16091a79fdSStanislaw Gruszka return ret;
171613c621SLorenzo Bianconi
18a782f8bfSLorenzo Bianconi ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
192e405024SFelix Fietkau MT_MAC_WORK_INTERVAL);
20011849e0SFelix Fietkau set_bit(MT76_STATE_RUNNING, &dev->mphy.state);
211613c621SLorenzo Bianconi
22091a79fdSStanislaw Gruszka return 0;
231613c621SLorenzo Bianconi }
241613c621SLorenzo Bianconi
mt76x2u_stop(struct ieee80211_hw * hw)251613c621SLorenzo Bianconi static void mt76x2u_stop(struct ieee80211_hw *hw)
261613c621SLorenzo Bianconi {
27e40803f2SLorenzo Bianconi struct mt76x02_dev *dev = hw->priv;
281613c621SLorenzo Bianconi
29011849e0SFelix Fietkau clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
3039d501d9SStanislaw Gruszka mt76u_stop_tx(&dev->mt76);
311613c621SLorenzo Bianconi mt76x2u_stop_hw(dev);
321613c621SLorenzo Bianconi }
331613c621SLorenzo Bianconi
341613c621SLorenzo Bianconi static int
mt76x2u_set_channel(struct mt76x02_dev * dev,struct cfg80211_chan_def * chandef)35e40803f2SLorenzo Bianconi mt76x2u_set_channel(struct mt76x02_dev *dev,
361613c621SLorenzo Bianconi struct cfg80211_chan_def *chandef)
371613c621SLorenzo Bianconi {
381613c621SLorenzo Bianconi int err;
391613c621SLorenzo Bianconi
401613c621SLorenzo Bianconi cancel_delayed_work_sync(&dev->cal_work);
411920a0ccSLorenzo Bianconi mt76x02_pre_tbtt_enable(dev, false);
426e4caaeaSLorenzo Bianconi
436e4caaeaSLorenzo Bianconi mutex_lock(&dev->mt76.mutex);
44011849e0SFelix Fietkau set_bit(MT76_RESET, &dev->mphy.state);
451613c621SLorenzo Bianconi
4696747a51SFelix Fietkau mt76_set_channel(&dev->mphy);
471613c621SLorenzo Bianconi
481613c621SLorenzo Bianconi mt76x2_mac_stop(dev, false);
491613c621SLorenzo Bianconi
501613c621SLorenzo Bianconi err = mt76x2u_phy_set_channel(dev, chandef);
511613c621SLorenzo Bianconi
52aec65e48SFelix Fietkau mt76x02_mac_cc_reset(dev);
532858f60aSFelix Fietkau mt76x2_mac_resume(dev);
541613c621SLorenzo Bianconi
55011849e0SFelix Fietkau clear_bit(MT76_RESET, &dev->mphy.state);
566e4caaeaSLorenzo Bianconi mutex_unlock(&dev->mt76.mutex);
576e4caaeaSLorenzo Bianconi
581920a0ccSLorenzo Bianconi mt76x02_pre_tbtt_enable(dev, true);
599fba6d07SFelix Fietkau mt76_txq_schedule_all(&dev->mphy);
601613c621SLorenzo Bianconi
611613c621SLorenzo Bianconi return err;
621613c621SLorenzo Bianconi }
631613c621SLorenzo Bianconi
641613c621SLorenzo Bianconi static int
mt76x2u_config(struct ieee80211_hw * hw,u32 changed)651613c621SLorenzo Bianconi mt76x2u_config(struct ieee80211_hw *hw, u32 changed)
661613c621SLorenzo Bianconi {
67e40803f2SLorenzo Bianconi struct mt76x02_dev *dev = hw->priv;
681613c621SLorenzo Bianconi int err = 0;
691613c621SLorenzo Bianconi
701613c621SLorenzo Bianconi mutex_lock(&dev->mt76.mutex);
711613c621SLorenzo Bianconi
721613c621SLorenzo Bianconi if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
731613c621SLorenzo Bianconi if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
741613c621SLorenzo Bianconi dev->mt76.rxfilter |= MT_RX_FILTR_CFG_PROMISC;
751613c621SLorenzo Bianconi else
761613c621SLorenzo Bianconi dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
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
90*633f77b5SLorenzo Bianconi if (test_bit(MT76_STATE_RUNNING, &mphy->state))
911613c621SLorenzo Bianconi mt76x2_phy_set_txpower(dev);
921613c621SLorenzo Bianconi }
931613c621SLorenzo Bianconi
941613c621SLorenzo Bianconi mutex_unlock(&dev->mt76.mutex);
951613c621SLorenzo Bianconi
966e4caaeaSLorenzo Bianconi if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
976e4caaeaSLorenzo Bianconi ieee80211_stop_queues(hw);
986e4caaeaSLorenzo Bianconi err = mt76x2u_set_channel(dev, &hw->conf.chandef);
996e4caaeaSLorenzo Bianconi ieee80211_wake_queues(hw);
1006e4caaeaSLorenzo Bianconi }
1016e4caaeaSLorenzo Bianconi
1021613c621SLorenzo Bianconi return err;
1031613c621SLorenzo Bianconi }
1041613c621SLorenzo Bianconi
1051613c621SLorenzo Bianconi const struct ieee80211_ops mt76x2u_ops = {
1062f0308d0SLorenzo Bianconi .tx = mt76x02_tx,
1071613c621SLorenzo Bianconi .start = mt76x2u_start,
1081613c621SLorenzo Bianconi .stop = mt76x2u_stop,
109f9a043c5SStanislaw Gruszka .add_interface = mt76x02_add_interface,
1101613c621SLorenzo Bianconi .remove_interface = mt76x02_remove_interface,
111e28487eaSFelix Fietkau .sta_state = mt76_sta_state,
11243ba1922SFelix Fietkau .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
1131613c621SLorenzo Bianconi .set_key = mt76x02_set_key,
1141613c621SLorenzo Bianconi .ampdu_action = mt76x02_ampdu_action,
1151613c621SLorenzo Bianconi .config = mt76x2u_config,
1161613c621SLorenzo Bianconi .wake_tx_queue = mt76_wake_tx_queue,
1179446a928SLorenzo Bianconi .bss_info_changed = mt76x02_bss_info_changed,
1181613c621SLorenzo Bianconi .configure_filter = mt76x02_configure_filter,
1191613c621SLorenzo Bianconi .conf_tx = mt76x02_conf_tx,
1208b8ab5c2SLorenzo Bianconi .sw_scan_start = mt76_sw_scan,
121c2756a1cSLorenzo Bianconi .sw_scan_complete = mt76x02_sw_scan_complete,
1221613c621SLorenzo Bianconi .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
1239313faacSFelix Fietkau .get_txpower = mt76_get_txpower,
124168aea24SLorenzo Bianconi .get_survey = mt76_get_survey,
12587d53103SStanislaw Gruszka .set_tim = mt76_set_tim,
1268300ee7cSStanislaw Gruszka .release_buffered_frames = mt76_release_buffered_frames,
127e49c76d4SLorenzo Bianconi .get_antenna = mt76_get_antenna,
128*633f77b5SLorenzo Bianconi .set_sar_specs = mt76x2_set_sar_specs,
1291613c621SLorenzo Bianconi };
130