xref: /linux/drivers/net/wireless/mediatek/mt76/mac80211.c (revision 17f1de56df051229988aab37e01971c9713c4a31)
1*17f1de56SFelix Fietkau /*
2*17f1de56SFelix Fietkau  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
3*17f1de56SFelix Fietkau  *
4*17f1de56SFelix Fietkau  * Permission to use, copy, modify, and/or distribute this software for any
5*17f1de56SFelix Fietkau  * purpose with or without fee is hereby granted, provided that the above
6*17f1de56SFelix Fietkau  * copyright notice and this permission notice appear in all copies.
7*17f1de56SFelix Fietkau  *
8*17f1de56SFelix Fietkau  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*17f1de56SFelix Fietkau  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*17f1de56SFelix Fietkau  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*17f1de56SFelix Fietkau  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*17f1de56SFelix Fietkau  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*17f1de56SFelix Fietkau  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*17f1de56SFelix Fietkau  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*17f1de56SFelix Fietkau  */
16*17f1de56SFelix Fietkau #include <linux/of.h>
17*17f1de56SFelix Fietkau #include "mt76.h"
18*17f1de56SFelix Fietkau 
19*17f1de56SFelix Fietkau #define CHAN2G(_idx, _freq) {			\
20*17f1de56SFelix Fietkau 	.band = NL80211_BAND_2GHZ,		\
21*17f1de56SFelix Fietkau 	.center_freq = (_freq),			\
22*17f1de56SFelix Fietkau 	.hw_value = (_idx),			\
23*17f1de56SFelix Fietkau 	.max_power = 30,			\
24*17f1de56SFelix Fietkau }
25*17f1de56SFelix Fietkau 
26*17f1de56SFelix Fietkau #define CHAN5G(_idx, _freq) {			\
27*17f1de56SFelix Fietkau 	.band = NL80211_BAND_5GHZ,		\
28*17f1de56SFelix Fietkau 	.center_freq = (_freq),			\
29*17f1de56SFelix Fietkau 	.hw_value = (_idx),			\
30*17f1de56SFelix Fietkau 	.max_power = 30,			\
31*17f1de56SFelix Fietkau }
32*17f1de56SFelix Fietkau 
33*17f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_2ghz[] = {
34*17f1de56SFelix Fietkau 	CHAN2G(1, 2412),
35*17f1de56SFelix Fietkau 	CHAN2G(2, 2417),
36*17f1de56SFelix Fietkau 	CHAN2G(3, 2422),
37*17f1de56SFelix Fietkau 	CHAN2G(4, 2427),
38*17f1de56SFelix Fietkau 	CHAN2G(5, 2432),
39*17f1de56SFelix Fietkau 	CHAN2G(6, 2437),
40*17f1de56SFelix Fietkau 	CHAN2G(7, 2442),
41*17f1de56SFelix Fietkau 	CHAN2G(8, 2447),
42*17f1de56SFelix Fietkau 	CHAN2G(9, 2452),
43*17f1de56SFelix Fietkau 	CHAN2G(10, 2457),
44*17f1de56SFelix Fietkau 	CHAN2G(11, 2462),
45*17f1de56SFelix Fietkau 	CHAN2G(12, 2467),
46*17f1de56SFelix Fietkau 	CHAN2G(13, 2472),
47*17f1de56SFelix Fietkau 	CHAN2G(14, 2484),
48*17f1de56SFelix Fietkau };
49*17f1de56SFelix Fietkau 
50*17f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_5ghz[] = {
51*17f1de56SFelix Fietkau 	CHAN5G(36, 5180),
52*17f1de56SFelix Fietkau 	CHAN5G(40, 5200),
53*17f1de56SFelix Fietkau 	CHAN5G(44, 5220),
54*17f1de56SFelix Fietkau 	CHAN5G(48, 5240),
55*17f1de56SFelix Fietkau 
56*17f1de56SFelix Fietkau 	CHAN5G(52, 5260),
57*17f1de56SFelix Fietkau 	CHAN5G(56, 5280),
58*17f1de56SFelix Fietkau 	CHAN5G(60, 5300),
59*17f1de56SFelix Fietkau 	CHAN5G(64, 5320),
60*17f1de56SFelix Fietkau 
61*17f1de56SFelix Fietkau 	CHAN5G(100, 5500),
62*17f1de56SFelix Fietkau 	CHAN5G(104, 5520),
63*17f1de56SFelix Fietkau 	CHAN5G(108, 5540),
64*17f1de56SFelix Fietkau 	CHAN5G(112, 5560),
65*17f1de56SFelix Fietkau 	CHAN5G(116, 5580),
66*17f1de56SFelix Fietkau 	CHAN5G(120, 5600),
67*17f1de56SFelix Fietkau 	CHAN5G(124, 5620),
68*17f1de56SFelix Fietkau 	CHAN5G(128, 5640),
69*17f1de56SFelix Fietkau 	CHAN5G(132, 5660),
70*17f1de56SFelix Fietkau 	CHAN5G(136, 5680),
71*17f1de56SFelix Fietkau 	CHAN5G(140, 5700),
72*17f1de56SFelix Fietkau 
73*17f1de56SFelix Fietkau 	CHAN5G(149, 5745),
74*17f1de56SFelix Fietkau 	CHAN5G(153, 5765),
75*17f1de56SFelix Fietkau 	CHAN5G(157, 5785),
76*17f1de56SFelix Fietkau 	CHAN5G(161, 5805),
77*17f1de56SFelix Fietkau 	CHAN5G(165, 5825),
78*17f1de56SFelix Fietkau };
79*17f1de56SFelix Fietkau 
80*17f1de56SFelix Fietkau static const struct ieee80211_tpt_blink mt76_tpt_blink[] = {
81*17f1de56SFelix Fietkau 	{ .throughput =   0 * 1024, .blink_time = 334 },
82*17f1de56SFelix Fietkau 	{ .throughput =   1 * 1024, .blink_time = 260 },
83*17f1de56SFelix Fietkau 	{ .throughput =   5 * 1024, .blink_time = 220 },
84*17f1de56SFelix Fietkau 	{ .throughput =  10 * 1024, .blink_time = 190 },
85*17f1de56SFelix Fietkau 	{ .throughput =  20 * 1024, .blink_time = 170 },
86*17f1de56SFelix Fietkau 	{ .throughput =  50 * 1024, .blink_time = 150 },
87*17f1de56SFelix Fietkau 	{ .throughput =  70 * 1024, .blink_time = 130 },
88*17f1de56SFelix Fietkau 	{ .throughput = 100 * 1024, .blink_time = 110 },
89*17f1de56SFelix Fietkau 	{ .throughput = 200 * 1024, .blink_time =  80 },
90*17f1de56SFelix Fietkau 	{ .throughput = 300 * 1024, .blink_time =  50 },
91*17f1de56SFelix Fietkau };
92*17f1de56SFelix Fietkau 
93*17f1de56SFelix Fietkau static int mt76_led_init(struct mt76_dev *dev)
94*17f1de56SFelix Fietkau {
95*17f1de56SFelix Fietkau 	struct device_node *np = dev->dev->of_node;
96*17f1de56SFelix Fietkau 	struct ieee80211_hw *hw = dev->hw;
97*17f1de56SFelix Fietkau 	int led_pin;
98*17f1de56SFelix Fietkau 
99*17f1de56SFelix Fietkau 	if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set)
100*17f1de56SFelix Fietkau 		return 0;
101*17f1de56SFelix Fietkau 
102*17f1de56SFelix Fietkau 	snprintf(dev->led_name, sizeof(dev->led_name),
103*17f1de56SFelix Fietkau 		 "mt76-%s", wiphy_name(hw->wiphy));
104*17f1de56SFelix Fietkau 
105*17f1de56SFelix Fietkau 	dev->led_cdev.name = dev->led_name;
106*17f1de56SFelix Fietkau 	dev->led_cdev.default_trigger =
107*17f1de56SFelix Fietkau 		ieee80211_create_tpt_led_trigger(hw,
108*17f1de56SFelix Fietkau 					IEEE80211_TPT_LEDTRIG_FL_RADIO,
109*17f1de56SFelix Fietkau 					mt76_tpt_blink,
110*17f1de56SFelix Fietkau 					ARRAY_SIZE(mt76_tpt_blink));
111*17f1de56SFelix Fietkau 
112*17f1de56SFelix Fietkau 	np = of_get_child_by_name(np, "led");
113*17f1de56SFelix Fietkau 	if (np) {
114*17f1de56SFelix Fietkau 		if (!of_property_read_u32(np, "led-sources", &led_pin))
115*17f1de56SFelix Fietkau 			dev->led_pin = led_pin;
116*17f1de56SFelix Fietkau 		dev->led_al = of_property_read_bool(np, "led-active-low");
117*17f1de56SFelix Fietkau 	}
118*17f1de56SFelix Fietkau 
119*17f1de56SFelix Fietkau 	return devm_led_classdev_register(dev->dev, &dev->led_cdev);
120*17f1de56SFelix Fietkau }
121*17f1de56SFelix Fietkau 
122*17f1de56SFelix Fietkau static int
123*17f1de56SFelix Fietkau mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband,
124*17f1de56SFelix Fietkau 		const struct ieee80211_channel *chan, int n_chan,
125*17f1de56SFelix Fietkau 		struct ieee80211_rate *rates, int n_rates, bool vht)
126*17f1de56SFelix Fietkau {
127*17f1de56SFelix Fietkau 	struct ieee80211_supported_band *sband = &msband->sband;
128*17f1de56SFelix Fietkau 	struct ieee80211_sta_ht_cap *ht_cap;
129*17f1de56SFelix Fietkau 	struct ieee80211_sta_vht_cap *vht_cap;
130*17f1de56SFelix Fietkau 	void *chanlist;
131*17f1de56SFelix Fietkau 	u16 mcs_map;
132*17f1de56SFelix Fietkau 	int size;
133*17f1de56SFelix Fietkau 
134*17f1de56SFelix Fietkau 	size = n_chan * sizeof(*chan);
135*17f1de56SFelix Fietkau 	chanlist = devm_kmemdup(dev->dev, chan, size, GFP_KERNEL);
136*17f1de56SFelix Fietkau 	if (!chanlist)
137*17f1de56SFelix Fietkau 		return -ENOMEM;
138*17f1de56SFelix Fietkau 
139*17f1de56SFelix Fietkau 	msband->chan = devm_kzalloc(dev->dev, n_chan * sizeof(*msband->chan),
140*17f1de56SFelix Fietkau 				    GFP_KERNEL);
141*17f1de56SFelix Fietkau 	if (!msband->chan)
142*17f1de56SFelix Fietkau 		return -ENOMEM;
143*17f1de56SFelix Fietkau 
144*17f1de56SFelix Fietkau 	sband->channels = chanlist;
145*17f1de56SFelix Fietkau 	sband->n_channels = n_chan;
146*17f1de56SFelix Fietkau 	sband->bitrates = rates;
147*17f1de56SFelix Fietkau 	sband->n_bitrates = n_rates;
148*17f1de56SFelix Fietkau 	dev->chandef.chan = &sband->channels[0];
149*17f1de56SFelix Fietkau 
150*17f1de56SFelix Fietkau 	ht_cap = &sband->ht_cap;
151*17f1de56SFelix Fietkau 	ht_cap->ht_supported = true;
152*17f1de56SFelix Fietkau 	ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
153*17f1de56SFelix Fietkau 		       IEEE80211_HT_CAP_GRN_FLD |
154*17f1de56SFelix Fietkau 		       IEEE80211_HT_CAP_SGI_20 |
155*17f1de56SFelix Fietkau 		       IEEE80211_HT_CAP_SGI_40 |
156*17f1de56SFelix Fietkau 		       IEEE80211_HT_CAP_TX_STBC |
157*17f1de56SFelix Fietkau 		       (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
158*17f1de56SFelix Fietkau 
159*17f1de56SFelix Fietkau 	ht_cap->mcs.rx_mask[0] = 0xff;
160*17f1de56SFelix Fietkau 	ht_cap->mcs.rx_mask[1] = 0xff;
161*17f1de56SFelix Fietkau 	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
162*17f1de56SFelix Fietkau 	ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
163*17f1de56SFelix Fietkau 	ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
164*17f1de56SFelix Fietkau 
165*17f1de56SFelix Fietkau 	if (!vht)
166*17f1de56SFelix Fietkau 		return 0;
167*17f1de56SFelix Fietkau 
168*17f1de56SFelix Fietkau 	vht_cap = &sband->vht_cap;
169*17f1de56SFelix Fietkau 	vht_cap->vht_supported = true;
170*17f1de56SFelix Fietkau 
171*17f1de56SFelix Fietkau 	mcs_map = (IEEE80211_VHT_MCS_SUPPORT_0_9 << (0 * 2)) |
172*17f1de56SFelix Fietkau 		  (IEEE80211_VHT_MCS_SUPPORT_0_9 << (1 * 2)) |
173*17f1de56SFelix Fietkau 		  (IEEE80211_VHT_MCS_NOT_SUPPORTED << (2 * 2)) |
174*17f1de56SFelix Fietkau 		  (IEEE80211_VHT_MCS_NOT_SUPPORTED << (3 * 2)) |
175*17f1de56SFelix Fietkau 		  (IEEE80211_VHT_MCS_NOT_SUPPORTED << (4 * 2)) |
176*17f1de56SFelix Fietkau 		  (IEEE80211_VHT_MCS_NOT_SUPPORTED << (5 * 2)) |
177*17f1de56SFelix Fietkau 		  (IEEE80211_VHT_MCS_NOT_SUPPORTED << (6 * 2)) |
178*17f1de56SFelix Fietkau 		  (IEEE80211_VHT_MCS_NOT_SUPPORTED << (7 * 2));
179*17f1de56SFelix Fietkau 
180*17f1de56SFelix Fietkau 	vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
181*17f1de56SFelix Fietkau 	vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
182*17f1de56SFelix Fietkau 	vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC |
183*17f1de56SFelix Fietkau 			IEEE80211_VHT_CAP_TXSTBC |
184*17f1de56SFelix Fietkau 			IEEE80211_VHT_CAP_RXSTBC_1 |
185*17f1de56SFelix Fietkau 			IEEE80211_VHT_CAP_SHORT_GI_80;
186*17f1de56SFelix Fietkau 
187*17f1de56SFelix Fietkau 	return 0;
188*17f1de56SFelix Fietkau }
189*17f1de56SFelix Fietkau 
190*17f1de56SFelix Fietkau static int
191*17f1de56SFelix Fietkau mt76_init_sband_2g(struct mt76_dev *dev, struct ieee80211_rate *rates,
192*17f1de56SFelix Fietkau 		   int n_rates)
193*17f1de56SFelix Fietkau {
194*17f1de56SFelix Fietkau 	dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->sband_2g.sband;
195*17f1de56SFelix Fietkau 
196*17f1de56SFelix Fietkau 	return mt76_init_sband(dev, &dev->sband_2g,
197*17f1de56SFelix Fietkau 			       mt76_channels_2ghz,
198*17f1de56SFelix Fietkau 			       ARRAY_SIZE(mt76_channels_2ghz),
199*17f1de56SFelix Fietkau 			       rates, n_rates, false);
200*17f1de56SFelix Fietkau }
201*17f1de56SFelix Fietkau 
202*17f1de56SFelix Fietkau static int
203*17f1de56SFelix Fietkau mt76_init_sband_5g(struct mt76_dev *dev, struct ieee80211_rate *rates,
204*17f1de56SFelix Fietkau 		   int n_rates, bool vht)
205*17f1de56SFelix Fietkau {
206*17f1de56SFelix Fietkau 	dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->sband_5g.sband;
207*17f1de56SFelix Fietkau 
208*17f1de56SFelix Fietkau 	return mt76_init_sband(dev, &dev->sband_5g,
209*17f1de56SFelix Fietkau 			       mt76_channels_5ghz,
210*17f1de56SFelix Fietkau 			       ARRAY_SIZE(mt76_channels_5ghz),
211*17f1de56SFelix Fietkau 			       rates, n_rates, vht);
212*17f1de56SFelix Fietkau }
213*17f1de56SFelix Fietkau 
214*17f1de56SFelix Fietkau static void
215*17f1de56SFelix Fietkau mt76_check_sband(struct mt76_dev *dev, int band)
216*17f1de56SFelix Fietkau {
217*17f1de56SFelix Fietkau 	struct ieee80211_supported_band *sband = dev->hw->wiphy->bands[band];
218*17f1de56SFelix Fietkau 	bool found = false;
219*17f1de56SFelix Fietkau 	int i;
220*17f1de56SFelix Fietkau 
221*17f1de56SFelix Fietkau 	if (!sband)
222*17f1de56SFelix Fietkau 		return;
223*17f1de56SFelix Fietkau 
224*17f1de56SFelix Fietkau 	for (i = 0; i < sband->n_channels; i++) {
225*17f1de56SFelix Fietkau 		if (sband->channels[i].flags & IEEE80211_CHAN_DISABLED)
226*17f1de56SFelix Fietkau 			continue;
227*17f1de56SFelix Fietkau 
228*17f1de56SFelix Fietkau 		found = true;
229*17f1de56SFelix Fietkau 		break;
230*17f1de56SFelix Fietkau 	}
231*17f1de56SFelix Fietkau 
232*17f1de56SFelix Fietkau 	if (found)
233*17f1de56SFelix Fietkau 		return;
234*17f1de56SFelix Fietkau 
235*17f1de56SFelix Fietkau 	sband->n_channels = 0;
236*17f1de56SFelix Fietkau 	dev->hw->wiphy->bands[band] = NULL;
237*17f1de56SFelix Fietkau }
238*17f1de56SFelix Fietkau 
239*17f1de56SFelix Fietkau int mt76_register_device(struct mt76_dev *dev, bool vht,
240*17f1de56SFelix Fietkau 			 struct ieee80211_rate *rates, int n_rates)
241*17f1de56SFelix Fietkau {
242*17f1de56SFelix Fietkau 	struct ieee80211_hw *hw = dev->hw;
243*17f1de56SFelix Fietkau 	struct wiphy *wiphy = hw->wiphy;
244*17f1de56SFelix Fietkau 	int ret;
245*17f1de56SFelix Fietkau 
246*17f1de56SFelix Fietkau 	dev_set_drvdata(dev->dev, dev);
247*17f1de56SFelix Fietkau 
248*17f1de56SFelix Fietkau 	spin_lock_init(&dev->lock);
249*17f1de56SFelix Fietkau 	spin_lock_init(&dev->cc_lock);
250*17f1de56SFelix Fietkau 	INIT_LIST_HEAD(&dev->txwi_cache);
251*17f1de56SFelix Fietkau 
252*17f1de56SFelix Fietkau 	SET_IEEE80211_DEV(hw, dev->dev);
253*17f1de56SFelix Fietkau 	SET_IEEE80211_PERM_ADDR(hw, dev->macaddr);
254*17f1de56SFelix Fietkau 
255*17f1de56SFelix Fietkau 	wiphy->interface_modes =
256*17f1de56SFelix Fietkau 		BIT(NL80211_IFTYPE_STATION) |
257*17f1de56SFelix Fietkau 		BIT(NL80211_IFTYPE_AP) |
258*17f1de56SFelix Fietkau #ifdef CONFIG_MAC80211_MESH
259*17f1de56SFelix Fietkau 		BIT(NL80211_IFTYPE_MESH_POINT) |
260*17f1de56SFelix Fietkau #endif
261*17f1de56SFelix Fietkau 		BIT(NL80211_IFTYPE_ADHOC);
262*17f1de56SFelix Fietkau 
263*17f1de56SFelix Fietkau 	wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
264*17f1de56SFelix Fietkau 
265*17f1de56SFelix Fietkau 	hw->txq_data_size = sizeof(struct mt76_txq);
266*17f1de56SFelix Fietkau 	hw->max_tx_fragments = 16;
267*17f1de56SFelix Fietkau 
268*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SIGNAL_DBM);
269*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
270*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
271*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
272*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
273*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
274*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
275*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
276*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, TX_AMSDU);
277*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, TX_FRAG_LIST);
278*17f1de56SFelix Fietkau 	ieee80211_hw_set(hw, MFP_CAPABLE);
279*17f1de56SFelix Fietkau 
280*17f1de56SFelix Fietkau 	wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
281*17f1de56SFelix Fietkau 
282*17f1de56SFelix Fietkau 	if (dev->cap.has_2ghz) {
283*17f1de56SFelix Fietkau 		ret = mt76_init_sband_2g(dev, rates, n_rates);
284*17f1de56SFelix Fietkau 		if (ret)
285*17f1de56SFelix Fietkau 			return ret;
286*17f1de56SFelix Fietkau 	}
287*17f1de56SFelix Fietkau 
288*17f1de56SFelix Fietkau 	if (dev->cap.has_5ghz) {
289*17f1de56SFelix Fietkau 		ret = mt76_init_sband_5g(dev, rates + 4, n_rates - 4, vht);
290*17f1de56SFelix Fietkau 		if (ret)
291*17f1de56SFelix Fietkau 			return ret;
292*17f1de56SFelix Fietkau 	}
293*17f1de56SFelix Fietkau 
294*17f1de56SFelix Fietkau 	wiphy_read_of_freq_limits(dev->hw->wiphy);
295*17f1de56SFelix Fietkau 	mt76_check_sband(dev, NL80211_BAND_2GHZ);
296*17f1de56SFelix Fietkau 	mt76_check_sband(dev, NL80211_BAND_5GHZ);
297*17f1de56SFelix Fietkau 
298*17f1de56SFelix Fietkau 	ret = mt76_led_init(dev);
299*17f1de56SFelix Fietkau 	if (ret)
300*17f1de56SFelix Fietkau 		return ret;
301*17f1de56SFelix Fietkau 
302*17f1de56SFelix Fietkau 	return ieee80211_register_hw(hw);
303*17f1de56SFelix Fietkau }
304*17f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_register_device);
305*17f1de56SFelix Fietkau 
306*17f1de56SFelix Fietkau void mt76_unregister_device(struct mt76_dev *dev)
307*17f1de56SFelix Fietkau {
308*17f1de56SFelix Fietkau 	struct ieee80211_hw *hw = dev->hw;
309*17f1de56SFelix Fietkau 
310*17f1de56SFelix Fietkau 	ieee80211_unregister_hw(hw);
311*17f1de56SFelix Fietkau 	mt76_tx_free(dev);
312*17f1de56SFelix Fietkau }
313*17f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_unregister_device);
314*17f1de56SFelix Fietkau 
315*17f1de56SFelix Fietkau void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
316*17f1de56SFelix Fietkau {
317*17f1de56SFelix Fietkau 	if (!test_bit(MT76_STATE_RUNNING, &dev->state)) {
318*17f1de56SFelix Fietkau 		dev_kfree_skb(skb);
319*17f1de56SFelix Fietkau 		return;
320*17f1de56SFelix Fietkau 	}
321*17f1de56SFelix Fietkau 
322*17f1de56SFelix Fietkau 	__skb_queue_tail(&dev->rx_skb[q], skb);
323*17f1de56SFelix Fietkau }
324*17f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_rx);
325*17f1de56SFelix Fietkau 
326*17f1de56SFelix Fietkau void mt76_set_channel(struct mt76_dev *dev)
327*17f1de56SFelix Fietkau {
328*17f1de56SFelix Fietkau 	struct ieee80211_hw *hw = dev->hw;
329*17f1de56SFelix Fietkau 	struct cfg80211_chan_def *chandef = &hw->conf.chandef;
330*17f1de56SFelix Fietkau 	struct mt76_channel_state *state;
331*17f1de56SFelix Fietkau 	bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL;
332*17f1de56SFelix Fietkau 
333*17f1de56SFelix Fietkau 	if (dev->drv->update_survey)
334*17f1de56SFelix Fietkau 		dev->drv->update_survey(dev);
335*17f1de56SFelix Fietkau 
336*17f1de56SFelix Fietkau 	dev->chandef = *chandef;
337*17f1de56SFelix Fietkau 
338*17f1de56SFelix Fietkau 	if (!offchannel)
339*17f1de56SFelix Fietkau 		dev->main_chan = chandef->chan;
340*17f1de56SFelix Fietkau 
341*17f1de56SFelix Fietkau 	if (chandef->chan != dev->main_chan) {
342*17f1de56SFelix Fietkau 		state = mt76_channel_state(dev, chandef->chan);
343*17f1de56SFelix Fietkau 		memset(state, 0, sizeof(*state));
344*17f1de56SFelix Fietkau 	}
345*17f1de56SFelix Fietkau }
346*17f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_set_channel);
347*17f1de56SFelix Fietkau 
348*17f1de56SFelix Fietkau int mt76_get_survey(struct ieee80211_hw *hw, int idx,
349*17f1de56SFelix Fietkau 		    struct survey_info *survey)
350*17f1de56SFelix Fietkau {
351*17f1de56SFelix Fietkau 	struct mt76_dev *dev = hw->priv;
352*17f1de56SFelix Fietkau 	struct mt76_sband *sband;
353*17f1de56SFelix Fietkau 	struct ieee80211_channel *chan;
354*17f1de56SFelix Fietkau 	struct mt76_channel_state *state;
355*17f1de56SFelix Fietkau 	int ret = 0;
356*17f1de56SFelix Fietkau 
357*17f1de56SFelix Fietkau 	if (idx == 0 && dev->drv->update_survey)
358*17f1de56SFelix Fietkau 		dev->drv->update_survey(dev);
359*17f1de56SFelix Fietkau 
360*17f1de56SFelix Fietkau 	sband = &dev->sband_2g;
361*17f1de56SFelix Fietkau 	if (idx >= sband->sband.n_channels) {
362*17f1de56SFelix Fietkau 		idx -= sband->sband.n_channels;
363*17f1de56SFelix Fietkau 		sband = &dev->sband_5g;
364*17f1de56SFelix Fietkau 	}
365*17f1de56SFelix Fietkau 
366*17f1de56SFelix Fietkau 	if (idx >= sband->sband.n_channels)
367*17f1de56SFelix Fietkau 		return -ENOENT;
368*17f1de56SFelix Fietkau 
369*17f1de56SFelix Fietkau 	chan = &sband->sband.channels[idx];
370*17f1de56SFelix Fietkau 	state = mt76_channel_state(dev, chan);
371*17f1de56SFelix Fietkau 
372*17f1de56SFelix Fietkau 	memset(survey, 0, sizeof(*survey));
373*17f1de56SFelix Fietkau 	survey->channel = chan;
374*17f1de56SFelix Fietkau 	survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY;
375*17f1de56SFelix Fietkau 	if (chan == dev->main_chan)
376*17f1de56SFelix Fietkau 		survey->filled |= SURVEY_INFO_IN_USE;
377*17f1de56SFelix Fietkau 
378*17f1de56SFelix Fietkau 	spin_lock_bh(&dev->cc_lock);
379*17f1de56SFelix Fietkau 	survey->time = div_u64(state->cc_active, 1000);
380*17f1de56SFelix Fietkau 	survey->time_busy = div_u64(state->cc_busy, 1000);
381*17f1de56SFelix Fietkau 	spin_unlock_bh(&dev->cc_lock);
382*17f1de56SFelix Fietkau 
383*17f1de56SFelix Fietkau 	return ret;
384*17f1de56SFelix Fietkau }
385*17f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_get_survey);
386*17f1de56SFelix Fietkau 
387*17f1de56SFelix Fietkau void mt76_rx_complete(struct mt76_dev *dev, enum mt76_rxq_id q)
388*17f1de56SFelix Fietkau {
389*17f1de56SFelix Fietkau 	struct sk_buff *skb;
390*17f1de56SFelix Fietkau 
391*17f1de56SFelix Fietkau 	while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL)
392*17f1de56SFelix Fietkau 		ieee80211_rx_napi(dev->hw, NULL, skb, &dev->napi[q]);
393*17f1de56SFelix Fietkau }
394