xref: /linux/drivers/net/wireless/mediatek/mt76/mac80211.c (revision 49149d3f1c6bfb314db1f386cf5067e5151ee0aa)
117f1de56SFelix Fietkau /*
217f1de56SFelix Fietkau  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
317f1de56SFelix Fietkau  *
417f1de56SFelix Fietkau  * Permission to use, copy, modify, and/or distribute this software for any
517f1de56SFelix Fietkau  * purpose with or without fee is hereby granted, provided that the above
617f1de56SFelix Fietkau  * copyright notice and this permission notice appear in all copies.
717f1de56SFelix Fietkau  *
817f1de56SFelix Fietkau  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
917f1de56SFelix Fietkau  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1017f1de56SFelix Fietkau  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1117f1de56SFelix Fietkau  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1217f1de56SFelix Fietkau  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1317f1de56SFelix Fietkau  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1417f1de56SFelix Fietkau  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1517f1de56SFelix Fietkau  */
1617f1de56SFelix Fietkau #include <linux/of.h>
1717f1de56SFelix Fietkau #include "mt76.h"
1817f1de56SFelix Fietkau 
1917f1de56SFelix Fietkau #define CHAN2G(_idx, _freq) {			\
2017f1de56SFelix Fietkau 	.band = NL80211_BAND_2GHZ,		\
2117f1de56SFelix Fietkau 	.center_freq = (_freq),			\
2217f1de56SFelix Fietkau 	.hw_value = (_idx),			\
2317f1de56SFelix Fietkau 	.max_power = 30,			\
2417f1de56SFelix Fietkau }
2517f1de56SFelix Fietkau 
2617f1de56SFelix Fietkau #define CHAN5G(_idx, _freq) {			\
2717f1de56SFelix Fietkau 	.band = NL80211_BAND_5GHZ,		\
2817f1de56SFelix Fietkau 	.center_freq = (_freq),			\
2917f1de56SFelix Fietkau 	.hw_value = (_idx),			\
3017f1de56SFelix Fietkau 	.max_power = 30,			\
3117f1de56SFelix Fietkau }
3217f1de56SFelix Fietkau 
3317f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_2ghz[] = {
3417f1de56SFelix Fietkau 	CHAN2G(1, 2412),
3517f1de56SFelix Fietkau 	CHAN2G(2, 2417),
3617f1de56SFelix Fietkau 	CHAN2G(3, 2422),
3717f1de56SFelix Fietkau 	CHAN2G(4, 2427),
3817f1de56SFelix Fietkau 	CHAN2G(5, 2432),
3917f1de56SFelix Fietkau 	CHAN2G(6, 2437),
4017f1de56SFelix Fietkau 	CHAN2G(7, 2442),
4117f1de56SFelix Fietkau 	CHAN2G(8, 2447),
4217f1de56SFelix Fietkau 	CHAN2G(9, 2452),
4317f1de56SFelix Fietkau 	CHAN2G(10, 2457),
4417f1de56SFelix Fietkau 	CHAN2G(11, 2462),
4517f1de56SFelix Fietkau 	CHAN2G(12, 2467),
4617f1de56SFelix Fietkau 	CHAN2G(13, 2472),
4717f1de56SFelix Fietkau 	CHAN2G(14, 2484),
4817f1de56SFelix Fietkau };
4917f1de56SFelix Fietkau 
5017f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_5ghz[] = {
5117f1de56SFelix Fietkau 	CHAN5G(36, 5180),
5217f1de56SFelix Fietkau 	CHAN5G(40, 5200),
5317f1de56SFelix Fietkau 	CHAN5G(44, 5220),
5417f1de56SFelix Fietkau 	CHAN5G(48, 5240),
5517f1de56SFelix Fietkau 
5617f1de56SFelix Fietkau 	CHAN5G(52, 5260),
5717f1de56SFelix Fietkau 	CHAN5G(56, 5280),
5817f1de56SFelix Fietkau 	CHAN5G(60, 5300),
5917f1de56SFelix Fietkau 	CHAN5G(64, 5320),
6017f1de56SFelix Fietkau 
6117f1de56SFelix Fietkau 	CHAN5G(100, 5500),
6217f1de56SFelix Fietkau 	CHAN5G(104, 5520),
6317f1de56SFelix Fietkau 	CHAN5G(108, 5540),
6417f1de56SFelix Fietkau 	CHAN5G(112, 5560),
6517f1de56SFelix Fietkau 	CHAN5G(116, 5580),
6617f1de56SFelix Fietkau 	CHAN5G(120, 5600),
6717f1de56SFelix Fietkau 	CHAN5G(124, 5620),
6817f1de56SFelix Fietkau 	CHAN5G(128, 5640),
6917f1de56SFelix Fietkau 	CHAN5G(132, 5660),
7017f1de56SFelix Fietkau 	CHAN5G(136, 5680),
7117f1de56SFelix Fietkau 	CHAN5G(140, 5700),
7217f1de56SFelix Fietkau 
7317f1de56SFelix Fietkau 	CHAN5G(149, 5745),
7417f1de56SFelix Fietkau 	CHAN5G(153, 5765),
7517f1de56SFelix Fietkau 	CHAN5G(157, 5785),
7617f1de56SFelix Fietkau 	CHAN5G(161, 5805),
7717f1de56SFelix Fietkau 	CHAN5G(165, 5825),
7817f1de56SFelix Fietkau };
7917f1de56SFelix Fietkau 
8017f1de56SFelix Fietkau static const struct ieee80211_tpt_blink mt76_tpt_blink[] = {
8117f1de56SFelix Fietkau 	{ .throughput =   0 * 1024, .blink_time = 334 },
8217f1de56SFelix Fietkau 	{ .throughput =   1 * 1024, .blink_time = 260 },
8317f1de56SFelix Fietkau 	{ .throughput =   5 * 1024, .blink_time = 220 },
8417f1de56SFelix Fietkau 	{ .throughput =  10 * 1024, .blink_time = 190 },
8517f1de56SFelix Fietkau 	{ .throughput =  20 * 1024, .blink_time = 170 },
8617f1de56SFelix Fietkau 	{ .throughput =  50 * 1024, .blink_time = 150 },
8717f1de56SFelix Fietkau 	{ .throughput =  70 * 1024, .blink_time = 130 },
8817f1de56SFelix Fietkau 	{ .throughput = 100 * 1024, .blink_time = 110 },
8917f1de56SFelix Fietkau 	{ .throughput = 200 * 1024, .blink_time =  80 },
9017f1de56SFelix Fietkau 	{ .throughput = 300 * 1024, .blink_time =  50 },
9117f1de56SFelix Fietkau };
9217f1de56SFelix Fietkau 
9317f1de56SFelix Fietkau static int mt76_led_init(struct mt76_dev *dev)
9417f1de56SFelix Fietkau {
9517f1de56SFelix Fietkau 	struct device_node *np = dev->dev->of_node;
9617f1de56SFelix Fietkau 	struct ieee80211_hw *hw = dev->hw;
9717f1de56SFelix Fietkau 	int led_pin;
9817f1de56SFelix Fietkau 
9917f1de56SFelix Fietkau 	if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set)
10017f1de56SFelix Fietkau 		return 0;
10117f1de56SFelix Fietkau 
10217f1de56SFelix Fietkau 	snprintf(dev->led_name, sizeof(dev->led_name),
10317f1de56SFelix Fietkau 		 "mt76-%s", wiphy_name(hw->wiphy));
10417f1de56SFelix Fietkau 
10517f1de56SFelix Fietkau 	dev->led_cdev.name = dev->led_name;
10617f1de56SFelix Fietkau 	dev->led_cdev.default_trigger =
10717f1de56SFelix Fietkau 		ieee80211_create_tpt_led_trigger(hw,
10817f1de56SFelix Fietkau 					IEEE80211_TPT_LEDTRIG_FL_RADIO,
10917f1de56SFelix Fietkau 					mt76_tpt_blink,
11017f1de56SFelix Fietkau 					ARRAY_SIZE(mt76_tpt_blink));
11117f1de56SFelix Fietkau 
11217f1de56SFelix Fietkau 	np = of_get_child_by_name(np, "led");
11317f1de56SFelix Fietkau 	if (np) {
11417f1de56SFelix Fietkau 		if (!of_property_read_u32(np, "led-sources", &led_pin))
11517f1de56SFelix Fietkau 			dev->led_pin = led_pin;
11617f1de56SFelix Fietkau 		dev->led_al = of_property_read_bool(np, "led-active-low");
11717f1de56SFelix Fietkau 	}
11817f1de56SFelix Fietkau 
11917f1de56SFelix Fietkau 	return devm_led_classdev_register(dev->dev, &dev->led_cdev);
12017f1de56SFelix Fietkau }
12117f1de56SFelix Fietkau 
122551e1ef4SLorenzo Bianconi static void mt76_init_stream_cap(struct mt76_dev *dev,
123551e1ef4SLorenzo Bianconi 				 struct ieee80211_supported_band *sband,
124551e1ef4SLorenzo Bianconi 				 bool vht)
125551e1ef4SLorenzo Bianconi {
126551e1ef4SLorenzo Bianconi 	struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
127551e1ef4SLorenzo Bianconi 	int i, nstream = __sw_hweight8(dev->antenna_mask);
128551e1ef4SLorenzo Bianconi 	struct ieee80211_sta_vht_cap *vht_cap;
129551e1ef4SLorenzo Bianconi 	u16 mcs_map = 0;
130551e1ef4SLorenzo Bianconi 
131551e1ef4SLorenzo Bianconi 	if (nstream > 1)
132551e1ef4SLorenzo Bianconi 		ht_cap->cap |= IEEE80211_HT_CAP_TX_STBC;
133551e1ef4SLorenzo Bianconi 	else
134551e1ef4SLorenzo Bianconi 		ht_cap->cap &= ~IEEE80211_HT_CAP_TX_STBC;
135551e1ef4SLorenzo Bianconi 
136551e1ef4SLorenzo Bianconi 	for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
137551e1ef4SLorenzo Bianconi 		ht_cap->mcs.rx_mask[i] = i < nstream ? 0xff : 0;
138551e1ef4SLorenzo Bianconi 
139551e1ef4SLorenzo Bianconi 	if (!vht)
140551e1ef4SLorenzo Bianconi 		return;
141551e1ef4SLorenzo Bianconi 
142551e1ef4SLorenzo Bianconi 	vht_cap = &sband->vht_cap;
143551e1ef4SLorenzo Bianconi 	if (nstream > 1)
144551e1ef4SLorenzo Bianconi 		vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
145551e1ef4SLorenzo Bianconi 	else
146551e1ef4SLorenzo Bianconi 		vht_cap->cap &= ~IEEE80211_VHT_CAP_TXSTBC;
147551e1ef4SLorenzo Bianconi 
148551e1ef4SLorenzo Bianconi 	for (i = 0; i < 8; i++) {
149551e1ef4SLorenzo Bianconi 		if (i < nstream)
150551e1ef4SLorenzo Bianconi 			mcs_map |= (IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2));
151551e1ef4SLorenzo Bianconi 		else
152551e1ef4SLorenzo Bianconi 			mcs_map |=
153551e1ef4SLorenzo Bianconi 				(IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2));
154551e1ef4SLorenzo Bianconi 	}
155551e1ef4SLorenzo Bianconi 	vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
156551e1ef4SLorenzo Bianconi 	vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
157551e1ef4SLorenzo Bianconi }
158551e1ef4SLorenzo Bianconi 
1595ebdc3e0SLorenzo Bianconi void mt76_set_stream_caps(struct mt76_dev *dev, bool vht)
1605ebdc3e0SLorenzo Bianconi {
1615ebdc3e0SLorenzo Bianconi 	if (dev->cap.has_2ghz)
1625ebdc3e0SLorenzo Bianconi 		mt76_init_stream_cap(dev, &dev->sband_2g.sband, false);
1635ebdc3e0SLorenzo Bianconi 	if (dev->cap.has_5ghz)
1645ebdc3e0SLorenzo Bianconi 		mt76_init_stream_cap(dev, &dev->sband_5g.sband, vht);
1655ebdc3e0SLorenzo Bianconi }
1665ebdc3e0SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_set_stream_caps);
1675ebdc3e0SLorenzo Bianconi 
16817f1de56SFelix Fietkau static int
16917f1de56SFelix Fietkau mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband,
17017f1de56SFelix Fietkau 		const struct ieee80211_channel *chan, int n_chan,
17117f1de56SFelix Fietkau 		struct ieee80211_rate *rates, int n_rates, bool vht)
17217f1de56SFelix Fietkau {
17317f1de56SFelix Fietkau 	struct ieee80211_supported_band *sband = &msband->sband;
17417f1de56SFelix Fietkau 	struct ieee80211_sta_ht_cap *ht_cap;
17517f1de56SFelix Fietkau 	struct ieee80211_sta_vht_cap *vht_cap;
17617f1de56SFelix Fietkau 	void *chanlist;
17717f1de56SFelix Fietkau 	int size;
17817f1de56SFelix Fietkau 
17917f1de56SFelix Fietkau 	size = n_chan * sizeof(*chan);
18017f1de56SFelix Fietkau 	chanlist = devm_kmemdup(dev->dev, chan, size, GFP_KERNEL);
18117f1de56SFelix Fietkau 	if (!chanlist)
18217f1de56SFelix Fietkau 		return -ENOMEM;
18317f1de56SFelix Fietkau 
18417f1de56SFelix Fietkau 	msband->chan = devm_kzalloc(dev->dev, n_chan * sizeof(*msband->chan),
18517f1de56SFelix Fietkau 				    GFP_KERNEL);
18617f1de56SFelix Fietkau 	if (!msband->chan)
18717f1de56SFelix Fietkau 		return -ENOMEM;
18817f1de56SFelix Fietkau 
18917f1de56SFelix Fietkau 	sband->channels = chanlist;
19017f1de56SFelix Fietkau 	sband->n_channels = n_chan;
19117f1de56SFelix Fietkau 	sband->bitrates = rates;
19217f1de56SFelix Fietkau 	sband->n_bitrates = n_rates;
19317f1de56SFelix Fietkau 	dev->chandef.chan = &sband->channels[0];
19417f1de56SFelix Fietkau 
19517f1de56SFelix Fietkau 	ht_cap = &sband->ht_cap;
19617f1de56SFelix Fietkau 	ht_cap->ht_supported = true;
19717f1de56SFelix Fietkau 	ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
19817f1de56SFelix Fietkau 		       IEEE80211_HT_CAP_GRN_FLD |
19917f1de56SFelix Fietkau 		       IEEE80211_HT_CAP_SGI_20 |
20017f1de56SFelix Fietkau 		       IEEE80211_HT_CAP_SGI_40 |
20117f1de56SFelix Fietkau 		       (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
20217f1de56SFelix Fietkau 
20317f1de56SFelix Fietkau 	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
20417f1de56SFelix Fietkau 	ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
20517f1de56SFelix Fietkau 	ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
20617f1de56SFelix Fietkau 
207551e1ef4SLorenzo Bianconi 	mt76_init_stream_cap(dev, sband, vht);
208551e1ef4SLorenzo Bianconi 
20917f1de56SFelix Fietkau 	if (!vht)
21017f1de56SFelix Fietkau 		return 0;
21117f1de56SFelix Fietkau 
21217f1de56SFelix Fietkau 	vht_cap = &sband->vht_cap;
21317f1de56SFelix Fietkau 	vht_cap->vht_supported = true;
21417f1de56SFelix Fietkau 	vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC |
21517f1de56SFelix Fietkau 			IEEE80211_VHT_CAP_RXSTBC_1 |
216*49149d3fSFelix Fietkau 			IEEE80211_VHT_CAP_SHORT_GI_80 |
217*49149d3fSFelix Fietkau 			(3 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
21817f1de56SFelix Fietkau 
21917f1de56SFelix Fietkau 	return 0;
22017f1de56SFelix Fietkau }
22117f1de56SFelix Fietkau 
22217f1de56SFelix Fietkau static int
22317f1de56SFelix Fietkau mt76_init_sband_2g(struct mt76_dev *dev, struct ieee80211_rate *rates,
22417f1de56SFelix Fietkau 		   int n_rates)
22517f1de56SFelix Fietkau {
22617f1de56SFelix Fietkau 	dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->sband_2g.sband;
22717f1de56SFelix Fietkau 
22817f1de56SFelix Fietkau 	return mt76_init_sband(dev, &dev->sband_2g,
22917f1de56SFelix Fietkau 			       mt76_channels_2ghz,
23017f1de56SFelix Fietkau 			       ARRAY_SIZE(mt76_channels_2ghz),
23117f1de56SFelix Fietkau 			       rates, n_rates, false);
23217f1de56SFelix Fietkau }
23317f1de56SFelix Fietkau 
23417f1de56SFelix Fietkau static int
23517f1de56SFelix Fietkau mt76_init_sband_5g(struct mt76_dev *dev, struct ieee80211_rate *rates,
23617f1de56SFelix Fietkau 		   int n_rates, bool vht)
23717f1de56SFelix Fietkau {
23817f1de56SFelix Fietkau 	dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->sband_5g.sband;
23917f1de56SFelix Fietkau 
24017f1de56SFelix Fietkau 	return mt76_init_sband(dev, &dev->sband_5g,
24117f1de56SFelix Fietkau 			       mt76_channels_5ghz,
24217f1de56SFelix Fietkau 			       ARRAY_SIZE(mt76_channels_5ghz),
24317f1de56SFelix Fietkau 			       rates, n_rates, vht);
24417f1de56SFelix Fietkau }
24517f1de56SFelix Fietkau 
24617f1de56SFelix Fietkau static void
24717f1de56SFelix Fietkau mt76_check_sband(struct mt76_dev *dev, int band)
24817f1de56SFelix Fietkau {
24917f1de56SFelix Fietkau 	struct ieee80211_supported_band *sband = dev->hw->wiphy->bands[band];
25017f1de56SFelix Fietkau 	bool found = false;
25117f1de56SFelix Fietkau 	int i;
25217f1de56SFelix Fietkau 
25317f1de56SFelix Fietkau 	if (!sband)
25417f1de56SFelix Fietkau 		return;
25517f1de56SFelix Fietkau 
25617f1de56SFelix Fietkau 	for (i = 0; i < sband->n_channels; i++) {
25717f1de56SFelix Fietkau 		if (sband->channels[i].flags & IEEE80211_CHAN_DISABLED)
25817f1de56SFelix Fietkau 			continue;
25917f1de56SFelix Fietkau 
26017f1de56SFelix Fietkau 		found = true;
26117f1de56SFelix Fietkau 		break;
26217f1de56SFelix Fietkau 	}
26317f1de56SFelix Fietkau 
26417f1de56SFelix Fietkau 	if (found)
26517f1de56SFelix Fietkau 		return;
26617f1de56SFelix Fietkau 
26717f1de56SFelix Fietkau 	sband->n_channels = 0;
26817f1de56SFelix Fietkau 	dev->hw->wiphy->bands[band] = NULL;
26917f1de56SFelix Fietkau }
27017f1de56SFelix Fietkau 
27117f1de56SFelix Fietkau int mt76_register_device(struct mt76_dev *dev, bool vht,
27217f1de56SFelix Fietkau 			 struct ieee80211_rate *rates, int n_rates)
27317f1de56SFelix Fietkau {
27417f1de56SFelix Fietkau 	struct ieee80211_hw *hw = dev->hw;
27517f1de56SFelix Fietkau 	struct wiphy *wiphy = hw->wiphy;
27617f1de56SFelix Fietkau 	int ret;
27717f1de56SFelix Fietkau 
27817f1de56SFelix Fietkau 	dev_set_drvdata(dev->dev, dev);
27917f1de56SFelix Fietkau 
28017f1de56SFelix Fietkau 	spin_lock_init(&dev->lock);
28117f1de56SFelix Fietkau 	spin_lock_init(&dev->cc_lock);
28217f1de56SFelix Fietkau 	INIT_LIST_HEAD(&dev->txwi_cache);
28317f1de56SFelix Fietkau 
28417f1de56SFelix Fietkau 	SET_IEEE80211_DEV(hw, dev->dev);
28517f1de56SFelix Fietkau 	SET_IEEE80211_PERM_ADDR(hw, dev->macaddr);
28617f1de56SFelix Fietkau 
28717f1de56SFelix Fietkau 	wiphy->interface_modes =
28817f1de56SFelix Fietkau 		BIT(NL80211_IFTYPE_STATION) |
28917f1de56SFelix Fietkau 		BIT(NL80211_IFTYPE_AP) |
29017f1de56SFelix Fietkau #ifdef CONFIG_MAC80211_MESH
29117f1de56SFelix Fietkau 		BIT(NL80211_IFTYPE_MESH_POINT) |
29217f1de56SFelix Fietkau #endif
29317f1de56SFelix Fietkau 		BIT(NL80211_IFTYPE_ADHOC);
29417f1de56SFelix Fietkau 
29517f1de56SFelix Fietkau 	wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
29617f1de56SFelix Fietkau 
29724114a5fSLorenzo Bianconi 	wiphy->available_antennas_tx = dev->antenna_mask;
29824114a5fSLorenzo Bianconi 	wiphy->available_antennas_rx = dev->antenna_mask;
29924114a5fSLorenzo Bianconi 
30017f1de56SFelix Fietkau 	hw->txq_data_size = sizeof(struct mt76_txq);
30117f1de56SFelix Fietkau 	hw->max_tx_fragments = 16;
30217f1de56SFelix Fietkau 
30317f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SIGNAL_DBM);
30417f1de56SFelix Fietkau 	ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
30517f1de56SFelix Fietkau 	ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
30617f1de56SFelix Fietkau 	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
30717f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
30817f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
30917f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
31017f1de56SFelix Fietkau 	ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
31117f1de56SFelix Fietkau 	ieee80211_hw_set(hw, TX_AMSDU);
31217f1de56SFelix Fietkau 	ieee80211_hw_set(hw, TX_FRAG_LIST);
31317f1de56SFelix Fietkau 	ieee80211_hw_set(hw, MFP_CAPABLE);
314d71ef286SFelix Fietkau 	ieee80211_hw_set(hw, AP_LINK_PS);
31517f1de56SFelix Fietkau 
31617f1de56SFelix Fietkau 	wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
31717f1de56SFelix Fietkau 
31817f1de56SFelix Fietkau 	if (dev->cap.has_2ghz) {
31917f1de56SFelix Fietkau 		ret = mt76_init_sband_2g(dev, rates, n_rates);
32017f1de56SFelix Fietkau 		if (ret)
32117f1de56SFelix Fietkau 			return ret;
32217f1de56SFelix Fietkau 	}
32317f1de56SFelix Fietkau 
32417f1de56SFelix Fietkau 	if (dev->cap.has_5ghz) {
32517f1de56SFelix Fietkau 		ret = mt76_init_sband_5g(dev, rates + 4, n_rates - 4, vht);
32617f1de56SFelix Fietkau 		if (ret)
32717f1de56SFelix Fietkau 			return ret;
32817f1de56SFelix Fietkau 	}
32917f1de56SFelix Fietkau 
33017f1de56SFelix Fietkau 	wiphy_read_of_freq_limits(dev->hw->wiphy);
33117f1de56SFelix Fietkau 	mt76_check_sband(dev, NL80211_BAND_2GHZ);
33217f1de56SFelix Fietkau 	mt76_check_sband(dev, NL80211_BAND_5GHZ);
33317f1de56SFelix Fietkau 
33417f1de56SFelix Fietkau 	ret = mt76_led_init(dev);
33517f1de56SFelix Fietkau 	if (ret)
33617f1de56SFelix Fietkau 		return ret;
33717f1de56SFelix Fietkau 
33817f1de56SFelix Fietkau 	return ieee80211_register_hw(hw);
33917f1de56SFelix Fietkau }
34017f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_register_device);
34117f1de56SFelix Fietkau 
34217f1de56SFelix Fietkau void mt76_unregister_device(struct mt76_dev *dev)
34317f1de56SFelix Fietkau {
34417f1de56SFelix Fietkau 	struct ieee80211_hw *hw = dev->hw;
34517f1de56SFelix Fietkau 
34617f1de56SFelix Fietkau 	ieee80211_unregister_hw(hw);
34717f1de56SFelix Fietkau 	mt76_tx_free(dev);
34817f1de56SFelix Fietkau }
34917f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_unregister_device);
35017f1de56SFelix Fietkau 
35117f1de56SFelix Fietkau void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
35217f1de56SFelix Fietkau {
35317f1de56SFelix Fietkau 	if (!test_bit(MT76_STATE_RUNNING, &dev->state)) {
35417f1de56SFelix Fietkau 		dev_kfree_skb(skb);
35517f1de56SFelix Fietkau 		return;
35617f1de56SFelix Fietkau 	}
35717f1de56SFelix Fietkau 
35817f1de56SFelix Fietkau 	__skb_queue_tail(&dev->rx_skb[q], skb);
35917f1de56SFelix Fietkau }
36017f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_rx);
36117f1de56SFelix Fietkau 
36217f1de56SFelix Fietkau void mt76_set_channel(struct mt76_dev *dev)
36317f1de56SFelix Fietkau {
36417f1de56SFelix Fietkau 	struct ieee80211_hw *hw = dev->hw;
36517f1de56SFelix Fietkau 	struct cfg80211_chan_def *chandef = &hw->conf.chandef;
36617f1de56SFelix Fietkau 	struct mt76_channel_state *state;
36717f1de56SFelix Fietkau 	bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL;
36817f1de56SFelix Fietkau 
36917f1de56SFelix Fietkau 	if (dev->drv->update_survey)
37017f1de56SFelix Fietkau 		dev->drv->update_survey(dev);
37117f1de56SFelix Fietkau 
37217f1de56SFelix Fietkau 	dev->chandef = *chandef;
37317f1de56SFelix Fietkau 
37417f1de56SFelix Fietkau 	if (!offchannel)
37517f1de56SFelix Fietkau 		dev->main_chan = chandef->chan;
37617f1de56SFelix Fietkau 
37717f1de56SFelix Fietkau 	if (chandef->chan != dev->main_chan) {
37817f1de56SFelix Fietkau 		state = mt76_channel_state(dev, chandef->chan);
37917f1de56SFelix Fietkau 		memset(state, 0, sizeof(*state));
38017f1de56SFelix Fietkau 	}
38117f1de56SFelix Fietkau }
38217f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_set_channel);
38317f1de56SFelix Fietkau 
38417f1de56SFelix Fietkau int mt76_get_survey(struct ieee80211_hw *hw, int idx,
38517f1de56SFelix Fietkau 		    struct survey_info *survey)
38617f1de56SFelix Fietkau {
38717f1de56SFelix Fietkau 	struct mt76_dev *dev = hw->priv;
38817f1de56SFelix Fietkau 	struct mt76_sband *sband;
38917f1de56SFelix Fietkau 	struct ieee80211_channel *chan;
39017f1de56SFelix Fietkau 	struct mt76_channel_state *state;
39117f1de56SFelix Fietkau 	int ret = 0;
39217f1de56SFelix Fietkau 
39317f1de56SFelix Fietkau 	if (idx == 0 && dev->drv->update_survey)
39417f1de56SFelix Fietkau 		dev->drv->update_survey(dev);
39517f1de56SFelix Fietkau 
39617f1de56SFelix Fietkau 	sband = &dev->sband_2g;
39717f1de56SFelix Fietkau 	if (idx >= sband->sband.n_channels) {
39817f1de56SFelix Fietkau 		idx -= sband->sband.n_channels;
39917f1de56SFelix Fietkau 		sband = &dev->sband_5g;
40017f1de56SFelix Fietkau 	}
40117f1de56SFelix Fietkau 
40217f1de56SFelix Fietkau 	if (idx >= sband->sband.n_channels)
40317f1de56SFelix Fietkau 		return -ENOENT;
40417f1de56SFelix Fietkau 
40517f1de56SFelix Fietkau 	chan = &sband->sband.channels[idx];
40617f1de56SFelix Fietkau 	state = mt76_channel_state(dev, chan);
40717f1de56SFelix Fietkau 
40817f1de56SFelix Fietkau 	memset(survey, 0, sizeof(*survey));
40917f1de56SFelix Fietkau 	survey->channel = chan;
41017f1de56SFelix Fietkau 	survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY;
41117f1de56SFelix Fietkau 	if (chan == dev->main_chan)
41217f1de56SFelix Fietkau 		survey->filled |= SURVEY_INFO_IN_USE;
41317f1de56SFelix Fietkau 
41417f1de56SFelix Fietkau 	spin_lock_bh(&dev->cc_lock);
41517f1de56SFelix Fietkau 	survey->time = div_u64(state->cc_active, 1000);
41617f1de56SFelix Fietkau 	survey->time_busy = div_u64(state->cc_busy, 1000);
41717f1de56SFelix Fietkau 	spin_unlock_bh(&dev->cc_lock);
41817f1de56SFelix Fietkau 
41917f1de56SFelix Fietkau 	return ret;
42017f1de56SFelix Fietkau }
42117f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_get_survey);
42217f1de56SFelix Fietkau 
42330ce7f44SFelix Fietkau void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
42430ce7f44SFelix Fietkau 			 struct ieee80211_key_conf *key)
42530ce7f44SFelix Fietkau {
42630ce7f44SFelix Fietkau 	struct ieee80211_key_seq seq;
42730ce7f44SFelix Fietkau 	int i;
42830ce7f44SFelix Fietkau 
42930ce7f44SFelix Fietkau 	wcid->rx_check_pn = false;
43030ce7f44SFelix Fietkau 
43130ce7f44SFelix Fietkau 	if (!key)
43230ce7f44SFelix Fietkau 		return;
43330ce7f44SFelix Fietkau 
43430ce7f44SFelix Fietkau 	if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
43530ce7f44SFelix Fietkau 		wcid->rx_check_pn = true;
43630ce7f44SFelix Fietkau 
43730ce7f44SFelix Fietkau 	for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
43830ce7f44SFelix Fietkau 		ieee80211_get_key_rx_seq(key, i, &seq);
43930ce7f44SFelix Fietkau 		memcpy(wcid->rx_key_pn[i], seq.ccmp.pn, sizeof(seq.ccmp.pn));
44030ce7f44SFelix Fietkau 	}
44130ce7f44SFelix Fietkau }
44230ce7f44SFelix Fietkau EXPORT_SYMBOL(mt76_wcid_key_setup);
44330ce7f44SFelix Fietkau 
4449d9d738bSFelix Fietkau static struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb)
4454e34249eSFelix Fietkau {
4464e34249eSFelix Fietkau 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
4474e34249eSFelix Fietkau 	struct mt76_rx_status mstat;
4484e34249eSFelix Fietkau 
4494e34249eSFelix Fietkau 	mstat = *((struct mt76_rx_status *) skb->cb);
4504e34249eSFelix Fietkau 	memset(status, 0, sizeof(*status));
4514e34249eSFelix Fietkau 
4524e34249eSFelix Fietkau 	status->flag = mstat.flag;
4534e34249eSFelix Fietkau 	status->freq = mstat.freq;
4544e34249eSFelix Fietkau 	status->enc_flags = mstat.enc_flags;
4554e34249eSFelix Fietkau 	status->encoding = mstat.encoding;
4564e34249eSFelix Fietkau 	status->bw = mstat.bw;
4574e34249eSFelix Fietkau 	status->rate_idx = mstat.rate_idx;
4584e34249eSFelix Fietkau 	status->nss = mstat.nss;
4594e34249eSFelix Fietkau 	status->band = mstat.band;
4604e34249eSFelix Fietkau 	status->signal = mstat.signal;
4614e34249eSFelix Fietkau 	status->chains = mstat.chains;
4624e34249eSFelix Fietkau 
4634e34249eSFelix Fietkau 	BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb));
4644e34249eSFelix Fietkau 	BUILD_BUG_ON(sizeof(status->chain_signal) != sizeof(mstat.chain_signal));
4654e34249eSFelix Fietkau 	memcpy(status->chain_signal, mstat.chain_signal, sizeof(mstat.chain_signal));
4669c68a57bSFelix Fietkau 
4679c68a57bSFelix Fietkau 	return wcid_to_sta(mstat.wcid);
4684e34249eSFelix Fietkau }
4694e34249eSFelix Fietkau 
47030ce7f44SFelix Fietkau static int
47130ce7f44SFelix Fietkau mt76_check_ccmp_pn(struct sk_buff *skb)
47230ce7f44SFelix Fietkau {
47330ce7f44SFelix Fietkau 	struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
47430ce7f44SFelix Fietkau 	struct mt76_wcid *wcid = status->wcid;
47530ce7f44SFelix Fietkau 	struct ieee80211_hdr *hdr;
47630ce7f44SFelix Fietkau 	int ret;
47730ce7f44SFelix Fietkau 
47830ce7f44SFelix Fietkau 	if (!(status->flag & RX_FLAG_DECRYPTED))
47930ce7f44SFelix Fietkau 		return 0;
48030ce7f44SFelix Fietkau 
48130ce7f44SFelix Fietkau 	if (!wcid || !wcid->rx_check_pn)
48230ce7f44SFelix Fietkau 		return 0;
48330ce7f44SFelix Fietkau 
48430ce7f44SFelix Fietkau 	if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
48530ce7f44SFelix Fietkau 		/*
48630ce7f44SFelix Fietkau 		 * Validate the first fragment both here and in mac80211
48730ce7f44SFelix Fietkau 		 * All further fragments will be validated by mac80211 only.
48830ce7f44SFelix Fietkau 		 */
48930ce7f44SFelix Fietkau 		hdr = (struct ieee80211_hdr *) skb->data;
49030ce7f44SFelix Fietkau 		if (ieee80211_is_frag(hdr) &&
49130ce7f44SFelix Fietkau 		    !ieee80211_is_first_frag(hdr->frame_control))
49230ce7f44SFelix Fietkau 			return 0;
49330ce7f44SFelix Fietkau 	}
49430ce7f44SFelix Fietkau 
49530ce7f44SFelix Fietkau 	BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0]));
49630ce7f44SFelix Fietkau 	ret = memcmp(status->iv, wcid->rx_key_pn[status->tid],
49730ce7f44SFelix Fietkau 		     sizeof(status->iv));
49830ce7f44SFelix Fietkau 	if (ret <= 0)
49930ce7f44SFelix Fietkau 		return -EINVAL; /* replay */
50030ce7f44SFelix Fietkau 
50130ce7f44SFelix Fietkau 	memcpy(wcid->rx_key_pn[status->tid], status->iv, sizeof(status->iv));
50230ce7f44SFelix Fietkau 
50330ce7f44SFelix Fietkau 	if (status->flag & RX_FLAG_IV_STRIPPED)
50430ce7f44SFelix Fietkau 		status->flag |= RX_FLAG_PN_VALIDATED;
50530ce7f44SFelix Fietkau 
50630ce7f44SFelix Fietkau 	return 0;
50730ce7f44SFelix Fietkau }
50830ce7f44SFelix Fietkau 
509d71ef286SFelix Fietkau static void
510d71ef286SFelix Fietkau mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb)
511d71ef286SFelix Fietkau {
512d71ef286SFelix Fietkau 	struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
513d71ef286SFelix Fietkau 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
514d71ef286SFelix Fietkau 	struct ieee80211_sta *sta;
515d71ef286SFelix Fietkau 	struct mt76_wcid *wcid = status->wcid;
516d71ef286SFelix Fietkau 	bool ps;
517d71ef286SFelix Fietkau 
518d71ef286SFelix Fietkau 	if (!wcid || !wcid->sta)
519d71ef286SFelix Fietkau 		return;
520d71ef286SFelix Fietkau 
521d71ef286SFelix Fietkau 	sta = container_of((void *) wcid, struct ieee80211_sta, drv_priv);
522d71ef286SFelix Fietkau 
523d71ef286SFelix Fietkau 	if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags))
524d71ef286SFelix Fietkau 		return;
525d71ef286SFelix Fietkau 
526d71ef286SFelix Fietkau 	if (ieee80211_is_pspoll(hdr->frame_control)) {
527d71ef286SFelix Fietkau 		ieee80211_sta_pspoll(sta);
528d71ef286SFelix Fietkau 		return;
529d71ef286SFelix Fietkau 	}
530d71ef286SFelix Fietkau 
531d71ef286SFelix Fietkau 	if (ieee80211_has_morefrags(hdr->frame_control) ||
532d71ef286SFelix Fietkau 		!(ieee80211_is_mgmt(hdr->frame_control) ||
533d71ef286SFelix Fietkau 		  ieee80211_is_data(hdr->frame_control)))
534d71ef286SFelix Fietkau 		return;
535d71ef286SFelix Fietkau 
536d71ef286SFelix Fietkau 	ps = ieee80211_has_pm(hdr->frame_control);
537d71ef286SFelix Fietkau 
538d71ef286SFelix Fietkau 	if (ps && (ieee80211_is_data_qos(hdr->frame_control) ||
539d71ef286SFelix Fietkau 		   ieee80211_is_qos_nullfunc(hdr->frame_control)))
540d71ef286SFelix Fietkau 		ieee80211_sta_uapsd_trigger(sta, status->tid);
541d71ef286SFelix Fietkau 
542d71ef286SFelix Fietkau 	if (!!test_bit(MT_WCID_FLAG_PS, &wcid->flags) == ps)
543d71ef286SFelix Fietkau 		return;
544d71ef286SFelix Fietkau 
54511b2a25fSFelix Fietkau 	if (ps)
546d71ef286SFelix Fietkau 		set_bit(MT_WCID_FLAG_PS, &wcid->flags);
54711b2a25fSFelix Fietkau 	else
548d71ef286SFelix Fietkau 		clear_bit(MT_WCID_FLAG_PS, &wcid->flags);
549d71ef286SFelix Fietkau 
550d71ef286SFelix Fietkau 	ieee80211_sta_ps_transition(sta, ps);
551d71ef286SFelix Fietkau 	dev->drv->sta_ps(dev, sta, ps);
552d71ef286SFelix Fietkau }
553d71ef286SFelix Fietkau 
5549d9d738bSFelix Fietkau void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
5559d9d738bSFelix Fietkau 		      int queue)
55617f1de56SFelix Fietkau {
5579d9d738bSFelix Fietkau 	struct napi_struct *napi = NULL;
5589c68a57bSFelix Fietkau 	struct ieee80211_sta *sta;
5599d9d738bSFelix Fietkau 	struct sk_buff *skb;
5609d9d738bSFelix Fietkau 
5619d9d738bSFelix Fietkau 	if (queue >= 0)
5629d9d738bSFelix Fietkau 	    napi = &dev->napi[queue];
5639d9d738bSFelix Fietkau 
5649d9d738bSFelix Fietkau 	while ((skb = __skb_dequeue(frames)) != NULL) {
56530ce7f44SFelix Fietkau 		if (mt76_check_ccmp_pn(skb)) {
56630ce7f44SFelix Fietkau 			dev_kfree_skb(skb);
56730ce7f44SFelix Fietkau 			continue;
56830ce7f44SFelix Fietkau 		}
56930ce7f44SFelix Fietkau 
5709d9d738bSFelix Fietkau 		sta = mt76_rx_convert(skb);
5719d9d738bSFelix Fietkau 		ieee80211_rx_napi(dev->hw, sta, skb, napi);
5729d9d738bSFelix Fietkau 	}
5739d9d738bSFelix Fietkau }
5749d9d738bSFelix Fietkau 
5759d9d738bSFelix Fietkau void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q)
5769d9d738bSFelix Fietkau {
577aee5b8cfSFelix Fietkau 	struct sk_buff_head frames;
57817f1de56SFelix Fietkau 	struct sk_buff *skb;
57917f1de56SFelix Fietkau 
580aee5b8cfSFelix Fietkau 	__skb_queue_head_init(&frames);
581aee5b8cfSFelix Fietkau 
582d71ef286SFelix Fietkau 	while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) {
583d71ef286SFelix Fietkau 		mt76_check_ps(dev, skb);
584aee5b8cfSFelix Fietkau 		mt76_rx_aggr_reorder(skb, &frames);
585d71ef286SFelix Fietkau 	}
586aee5b8cfSFelix Fietkau 
5879d9d738bSFelix Fietkau 	mt76_rx_complete(dev, &frames, q);
5884e34249eSFelix Fietkau }
589