Commit | Line | Data |
---|---|---|
0e3d6777 | 1 | // SPDX-License-Identifier: ISC |
7bc04215 FF |
2 | /* |
3 | * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> | |
7bc04215 FF |
4 | */ |
5 | ||
6 | #include "mt76x2.h" | |
7 | ||
8 | static int | |
9 | mt76x2_start(struct ieee80211_hw *hw) | |
10 | { | |
e40803f2 | 11 | struct mt76x02_dev *dev = hw->priv; |
7bc04215 FF |
12 | int ret; |
13 | ||
7bc04215 FF |
14 | ret = mt76x2_mac_start(dev); |
15 | if (ret) | |
091a79fd | 16 | return ret; |
7bc04215 FF |
17 | |
18 | ret = mt76x2_phy_start(dev); | |
19 | if (ret) | |
091a79fd | 20 | return ret; |
7bc04215 | 21 | |
37426fb6 | 22 | ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, |
2e405024 | 23 | MT_MAC_WORK_INTERVAL); |
c1e0d2be LB |
24 | ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work, |
25 | MT_WATCHDOG_TIME); | |
7bc04215 FF |
26 | |
27 | set_bit(MT76_STATE_RUNNING, &dev->mt76.state); | |
091a79fd | 28 | return 0; |
7bc04215 FF |
29 | } |
30 | ||
31 | static void | |
32 | mt76x2_stop(struct ieee80211_hw *hw) | |
33 | { | |
e40803f2 | 34 | struct mt76x02_dev *dev = hw->priv; |
7bc04215 | 35 | |
7bc04215 FF |
36 | clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); |
37 | mt76x2_stop_hardware(dev); | |
7bc04215 FF |
38 | } |
39 | ||
7bc04215 | 40 | static int |
e40803f2 | 41 | mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) |
7bc04215 FF |
42 | { |
43 | int ret; | |
44 | ||
a164a942 | 45 | cancel_delayed_work_sync(&dev->cal_work); |
6e4caaea LB |
46 | tasklet_disable(&dev->mt76.pre_tbtt_tasklet); |
47 | tasklet_disable(&dev->dfs_pd.dfs_tasklet); | |
a164a942 | 48 | |
6e4caaea | 49 | mutex_lock(&dev->mt76.mutex); |
a164a942 FF |
50 | set_bit(MT76_RESET, &dev->mt76.state); |
51 | ||
7bc04215 FF |
52 | mt76_set_channel(&dev->mt76); |
53 | ||
7bc04215 FF |
54 | mt76x2_mac_stop(dev, true); |
55 | ret = mt76x2_phy_set_channel(dev, chandef); | |
56 | ||
57 | /* channel cycle counters read-and-clear */ | |
58 | mt76_rr(dev, MT_CH_IDLE); | |
59 | mt76_rr(dev, MT_CH_BUSY); | |
60 | ||
e6cb3291 | 61 | mt76x02_dfs_init_params(dev); |
7bc04215 FF |
62 | |
63 | mt76x2_mac_resume(dev); | |
7bc04215 | 64 | |
a164a942 | 65 | clear_bit(MT76_RESET, &dev->mt76.state); |
6e4caaea LB |
66 | mutex_unlock(&dev->mt76.mutex); |
67 | ||
68 | tasklet_enable(&dev->dfs_pd.dfs_tasklet); | |
69 | tasklet_enable(&dev->mt76.pre_tbtt_tasklet); | |
a164a942 FF |
70 | |
71 | mt76_txq_schedule_all(&dev->mt76); | |
72 | ||
7bc04215 FF |
73 | return ret; |
74 | } | |
75 | ||
76 | static int | |
77 | mt76x2_config(struct ieee80211_hw *hw, u32 changed) | |
78 | { | |
e40803f2 | 79 | struct mt76x02_dev *dev = hw->priv; |
7bc04215 FF |
80 | int ret = 0; |
81 | ||
108a4861 | 82 | mutex_lock(&dev->mt76.mutex); |
7bc04215 | 83 | |
e8be626d FF |
84 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { |
85 | if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) | |
108a4861 | 86 | dev->mt76.rxfilter |= MT_RX_FILTR_CFG_PROMISC; |
e8be626d | 87 | else |
108a4861 | 88 | dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_PROMISC; |
e8be626d | 89 | |
108a4861 | 90 | mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter); |
e8be626d FF |
91 | } |
92 | ||
7bc04215 | 93 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
b6862eff | 94 | dev->mt76.txpower_conf = hw->conf.power_level * 2; |
7bc04215 | 95 | |
53aa29b2 | 96 | /* convert to per-chain power for 2x2 devices */ |
b6862eff | 97 | dev->mt76.txpower_conf -= 6; |
53aa29b2 | 98 | |
7bc04215 FF |
99 | if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) { |
100 | mt76x2_phy_set_txpower(dev); | |
1ea0a1b1 | 101 | mt76x02_tx_set_txpwr_auto(dev, dev->mt76.txpower_conf); |
7bc04215 FF |
102 | } |
103 | } | |
104 | ||
6e4caaea LB |
105 | mutex_unlock(&dev->mt76.mutex); |
106 | ||
7bc04215 FF |
107 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
108 | ieee80211_stop_queues(hw); | |
109 | ret = mt76x2_set_channel(dev, &hw->conf.chandef); | |
110 | ieee80211_wake_queues(hw); | |
111 | } | |
112 | ||
7bc04215 FF |
113 | return ret; |
114 | } | |
115 | ||
7bc04215 FF |
116 | static void |
117 | mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |
118 | u32 queues, bool drop) | |
119 | { | |
120 | } | |
121 | ||
5ebdc3e0 LB |
122 | static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, |
123 | u32 rx_ant) | |
124 | { | |
e40803f2 | 125 | struct mt76x02_dev *dev = hw->priv; |
5ebdc3e0 LB |
126 | |
127 | if (!tx_ant || tx_ant > 3 || tx_ant != rx_ant) | |
128 | return -EINVAL; | |
129 | ||
108a4861 | 130 | mutex_lock(&dev->mt76.mutex); |
5ebdc3e0 | 131 | |
6034b2b0 | 132 | dev->mt76.chainmask = (tx_ant == 3) ? 0x202 : 0x101; |
5ebdc3e0 LB |
133 | dev->mt76.antenna_mask = tx_ant; |
134 | ||
135 | mt76_set_stream_caps(&dev->mt76, true); | |
136 | mt76x2_phy_set_antenna(dev); | |
137 | ||
108a4861 | 138 | mutex_unlock(&dev->mt76.mutex); |
5ebdc3e0 LB |
139 | |
140 | return 0; | |
141 | } | |
142 | ||
143 | static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, | |
144 | u32 *rx_ant) | |
145 | { | |
e40803f2 | 146 | struct mt76x02_dev *dev = hw->priv; |
5ebdc3e0 | 147 | |
108a4861 | 148 | mutex_lock(&dev->mt76.mutex); |
5ebdc3e0 LB |
149 | *tx_ant = dev->mt76.antenna_mask; |
150 | *rx_ant = dev->mt76.antenna_mask; | |
108a4861 | 151 | mutex_unlock(&dev->mt76.mutex); |
5ebdc3e0 LB |
152 | |
153 | return 0; | |
154 | } | |
155 | ||
7bc04215 | 156 | const struct ieee80211_ops mt76x2_ops = { |
2f0308d0 | 157 | .tx = mt76x02_tx, |
7bc04215 FF |
158 | .start = mt76x2_start, |
159 | .stop = mt76x2_stop, | |
212926eb | 160 | .add_interface = mt76x02_add_interface, |
0cd47bae | 161 | .remove_interface = mt76x02_remove_interface, |
7bc04215 | 162 | .config = mt76x2_config, |
108a4861 | 163 | .configure_filter = mt76x02_configure_filter, |
cc726268 | 164 | .bss_info_changed = mt76x02_bss_info_changed, |
e28487ea | 165 | .sta_state = mt76_sta_state, |
60c26859 | 166 | .set_key = mt76x02_set_key, |
10337263 | 167 | .conf_tx = mt76x02_conf_tx, |
c2756a1c LB |
168 | .sw_scan_start = mt76x02_sw_scan, |
169 | .sw_scan_complete = mt76x02_sw_scan_complete, | |
7bc04215 | 170 | .flush = mt76x2_flush, |
22c575c4 | 171 | .ampdu_action = mt76x02_ampdu_action, |
9313faac | 172 | .get_txpower = mt76_get_txpower, |
7bc04215 | 173 | .wake_tx_queue = mt76_wake_tx_queue, |
5327b5ea | 174 | .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update, |
7bc04215 | 175 | .release_buffered_frames = mt76_release_buffered_frames, |
36704051 | 176 | .set_coverage_class = mt76x02_set_coverage_class, |
7bc04215 | 177 | .get_survey = mt76_get_survey, |
87d53103 | 178 | .set_tim = mt76_set_tim, |
5ebdc3e0 LB |
179 | .set_antenna = mt76x2_set_antenna, |
180 | .get_antenna = mt76x2_get_antenna, | |
317ed42b | 181 | .set_rts_threshold = mt76x02_set_rts_threshold, |
7bc04215 FF |
182 | }; |
183 |