10e3d6777SRyder Lee // SPDX-License-Identifier: ISC 217f1de56SFelix Fietkau /* 317f1de56SFelix Fietkau * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 417f1de56SFelix Fietkau */ 5781eef5bSFelix Fietkau #include <linux/sched.h> 617f1de56SFelix Fietkau #include <linux/of.h> 717f1de56SFelix Fietkau #include "mt76.h" 817f1de56SFelix Fietkau 917f1de56SFelix Fietkau #define CHAN2G(_idx, _freq) { \ 1017f1de56SFelix Fietkau .band = NL80211_BAND_2GHZ, \ 1117f1de56SFelix Fietkau .center_freq = (_freq), \ 1217f1de56SFelix Fietkau .hw_value = (_idx), \ 1317f1de56SFelix Fietkau .max_power = 30, \ 1417f1de56SFelix Fietkau } 1517f1de56SFelix Fietkau 1617f1de56SFelix Fietkau #define CHAN5G(_idx, _freq) { \ 1717f1de56SFelix Fietkau .band = NL80211_BAND_5GHZ, \ 1817f1de56SFelix Fietkau .center_freq = (_freq), \ 1917f1de56SFelix Fietkau .hw_value = (_idx), \ 2017f1de56SFelix Fietkau .max_power = 30, \ 2117f1de56SFelix Fietkau } 2217f1de56SFelix Fietkau 2317f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_2ghz[] = { 2417f1de56SFelix Fietkau CHAN2G(1, 2412), 2517f1de56SFelix Fietkau CHAN2G(2, 2417), 2617f1de56SFelix Fietkau CHAN2G(3, 2422), 2717f1de56SFelix Fietkau CHAN2G(4, 2427), 2817f1de56SFelix Fietkau CHAN2G(5, 2432), 2917f1de56SFelix Fietkau CHAN2G(6, 2437), 3017f1de56SFelix Fietkau CHAN2G(7, 2442), 3117f1de56SFelix Fietkau CHAN2G(8, 2447), 3217f1de56SFelix Fietkau CHAN2G(9, 2452), 3317f1de56SFelix Fietkau CHAN2G(10, 2457), 3417f1de56SFelix Fietkau CHAN2G(11, 2462), 3517f1de56SFelix Fietkau CHAN2G(12, 2467), 3617f1de56SFelix Fietkau CHAN2G(13, 2472), 3717f1de56SFelix Fietkau CHAN2G(14, 2484), 3817f1de56SFelix Fietkau }; 3917f1de56SFelix Fietkau 4017f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_5ghz[] = { 4117f1de56SFelix Fietkau CHAN5G(36, 5180), 4217f1de56SFelix Fietkau CHAN5G(40, 5200), 4317f1de56SFelix Fietkau CHAN5G(44, 5220), 4417f1de56SFelix Fietkau CHAN5G(48, 5240), 4517f1de56SFelix Fietkau 4617f1de56SFelix Fietkau CHAN5G(52, 5260), 4717f1de56SFelix Fietkau CHAN5G(56, 5280), 4817f1de56SFelix Fietkau CHAN5G(60, 5300), 4917f1de56SFelix Fietkau CHAN5G(64, 5320), 5017f1de56SFelix Fietkau 5117f1de56SFelix Fietkau CHAN5G(100, 5500), 5217f1de56SFelix Fietkau CHAN5G(104, 5520), 5317f1de56SFelix Fietkau CHAN5G(108, 5540), 5417f1de56SFelix Fietkau CHAN5G(112, 5560), 5517f1de56SFelix Fietkau CHAN5G(116, 5580), 5617f1de56SFelix Fietkau CHAN5G(120, 5600), 5717f1de56SFelix Fietkau CHAN5G(124, 5620), 5817f1de56SFelix Fietkau CHAN5G(128, 5640), 5917f1de56SFelix Fietkau CHAN5G(132, 5660), 6017f1de56SFelix Fietkau CHAN5G(136, 5680), 6117f1de56SFelix Fietkau CHAN5G(140, 5700), 629da82fb7SMarkus Theil CHAN5G(144, 5720), 6317f1de56SFelix Fietkau 6417f1de56SFelix Fietkau CHAN5G(149, 5745), 6517f1de56SFelix Fietkau CHAN5G(153, 5765), 6617f1de56SFelix Fietkau CHAN5G(157, 5785), 6717f1de56SFelix Fietkau CHAN5G(161, 5805), 6817f1de56SFelix Fietkau CHAN5G(165, 5825), 699da82fb7SMarkus Theil CHAN5G(169, 5845), 709da82fb7SMarkus Theil CHAN5G(173, 5865), 7117f1de56SFelix Fietkau }; 7217f1de56SFelix Fietkau 7317f1de56SFelix Fietkau static const struct ieee80211_tpt_blink mt76_tpt_blink[] = { 7417f1de56SFelix Fietkau { .throughput = 0 * 1024, .blink_time = 334 }, 7517f1de56SFelix Fietkau { .throughput = 1 * 1024, .blink_time = 260 }, 7617f1de56SFelix Fietkau { .throughput = 5 * 1024, .blink_time = 220 }, 7717f1de56SFelix Fietkau { .throughput = 10 * 1024, .blink_time = 190 }, 7817f1de56SFelix Fietkau { .throughput = 20 * 1024, .blink_time = 170 }, 7917f1de56SFelix Fietkau { .throughput = 50 * 1024, .blink_time = 150 }, 8017f1de56SFelix Fietkau { .throughput = 70 * 1024, .blink_time = 130 }, 8117f1de56SFelix Fietkau { .throughput = 100 * 1024, .blink_time = 110 }, 8217f1de56SFelix Fietkau { .throughput = 200 * 1024, .blink_time = 80 }, 8317f1de56SFelix Fietkau { .throughput = 300 * 1024, .blink_time = 50 }, 8417f1de56SFelix Fietkau }; 8517f1de56SFelix Fietkau 8654b8fdebSLorenzo Bianconi struct ieee80211_rate mt76_rates[] = { 8754b8fdebSLorenzo Bianconi CCK_RATE(0, 10), 8854b8fdebSLorenzo Bianconi CCK_RATE(1, 20), 8954b8fdebSLorenzo Bianconi CCK_RATE(2, 55), 9054b8fdebSLorenzo Bianconi CCK_RATE(3, 110), 9154b8fdebSLorenzo Bianconi OFDM_RATE(11, 60), 9254b8fdebSLorenzo Bianconi OFDM_RATE(15, 90), 9354b8fdebSLorenzo Bianconi OFDM_RATE(10, 120), 9454b8fdebSLorenzo Bianconi OFDM_RATE(14, 180), 9554b8fdebSLorenzo Bianconi OFDM_RATE(9, 240), 9654b8fdebSLorenzo Bianconi OFDM_RATE(13, 360), 9754b8fdebSLorenzo Bianconi OFDM_RATE(8, 480), 9854b8fdebSLorenzo Bianconi OFDM_RATE(12, 540), 9954b8fdebSLorenzo Bianconi }; 10054b8fdebSLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_rates); 10154b8fdebSLorenzo Bianconi 102*502604f5SYN Chen static const struct cfg80211_sar_freq_ranges mt76_sar_freq_ranges[] = { 103*502604f5SYN Chen { .start_freq = 2402, .end_freq = 2494, }, 104*502604f5SYN Chen { .start_freq = 5150, .end_freq = 5350, }, 105*502604f5SYN Chen { .start_freq = 5350, .end_freq = 5470, }, 106*502604f5SYN Chen { .start_freq = 5470, .end_freq = 5725, }, 107*502604f5SYN Chen { .start_freq = 5725, .end_freq = 5950, }, 108*502604f5SYN Chen }; 109*502604f5SYN Chen 110*502604f5SYN Chen const struct cfg80211_sar_capa mt76_sar_capa = { 111*502604f5SYN Chen .type = NL80211_SAR_TYPE_POWER, 112*502604f5SYN Chen .num_freq_ranges = ARRAY_SIZE(mt76_sar_freq_ranges), 113*502604f5SYN Chen .freq_ranges = &mt76_sar_freq_ranges[0], 114*502604f5SYN Chen }; 115*502604f5SYN Chen EXPORT_SYMBOL_GPL(mt76_sar_capa); 116*502604f5SYN Chen 11717f1de56SFelix Fietkau static int mt76_led_init(struct mt76_dev *dev) 11817f1de56SFelix Fietkau { 11917f1de56SFelix Fietkau struct device_node *np = dev->dev->of_node; 12017f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 12117f1de56SFelix Fietkau int led_pin; 12217f1de56SFelix Fietkau 12317f1de56SFelix Fietkau if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set) 12417f1de56SFelix Fietkau return 0; 12517f1de56SFelix Fietkau 12617f1de56SFelix Fietkau snprintf(dev->led_name, sizeof(dev->led_name), 12717f1de56SFelix Fietkau "mt76-%s", wiphy_name(hw->wiphy)); 12817f1de56SFelix Fietkau 12917f1de56SFelix Fietkau dev->led_cdev.name = dev->led_name; 13017f1de56SFelix Fietkau dev->led_cdev.default_trigger = 13117f1de56SFelix Fietkau ieee80211_create_tpt_led_trigger(hw, 13217f1de56SFelix Fietkau IEEE80211_TPT_LEDTRIG_FL_RADIO, 13317f1de56SFelix Fietkau mt76_tpt_blink, 13417f1de56SFelix Fietkau ARRAY_SIZE(mt76_tpt_blink)); 13517f1de56SFelix Fietkau 13617f1de56SFelix Fietkau np = of_get_child_by_name(np, "led"); 13717f1de56SFelix Fietkau if (np) { 13817f1de56SFelix Fietkau if (!of_property_read_u32(np, "led-sources", &led_pin)) 13917f1de56SFelix Fietkau dev->led_pin = led_pin; 14017f1de56SFelix Fietkau dev->led_al = of_property_read_bool(np, "led-active-low"); 14117f1de56SFelix Fietkau } 14217f1de56SFelix Fietkau 14336f7e2b2SFelix Fietkau return led_classdev_register(dev->dev, &dev->led_cdev); 14436f7e2b2SFelix Fietkau } 14536f7e2b2SFelix Fietkau 14636f7e2b2SFelix Fietkau static void mt76_led_cleanup(struct mt76_dev *dev) 14736f7e2b2SFelix Fietkau { 14836f7e2b2SFelix Fietkau if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set) 14936f7e2b2SFelix Fietkau return; 15036f7e2b2SFelix Fietkau 15136f7e2b2SFelix Fietkau led_classdev_unregister(&dev->led_cdev); 15217f1de56SFelix Fietkau } 15317f1de56SFelix Fietkau 154bb3e3fecSRyder Lee static void mt76_init_stream_cap(struct mt76_phy *phy, 155551e1ef4SLorenzo Bianconi struct ieee80211_supported_band *sband, 156551e1ef4SLorenzo Bianconi bool vht) 157551e1ef4SLorenzo Bianconi { 158551e1ef4SLorenzo Bianconi struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; 159bb3e3fecSRyder Lee int i, nstream = hweight8(phy->antenna_mask); 160551e1ef4SLorenzo Bianconi struct ieee80211_sta_vht_cap *vht_cap; 161551e1ef4SLorenzo Bianconi u16 mcs_map = 0; 162551e1ef4SLorenzo Bianconi 163551e1ef4SLorenzo Bianconi if (nstream > 1) 164551e1ef4SLorenzo Bianconi ht_cap->cap |= IEEE80211_HT_CAP_TX_STBC; 165551e1ef4SLorenzo Bianconi else 166551e1ef4SLorenzo Bianconi ht_cap->cap &= ~IEEE80211_HT_CAP_TX_STBC; 167551e1ef4SLorenzo Bianconi 168551e1ef4SLorenzo Bianconi for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) 169551e1ef4SLorenzo Bianconi ht_cap->mcs.rx_mask[i] = i < nstream ? 0xff : 0; 170551e1ef4SLorenzo Bianconi 171551e1ef4SLorenzo Bianconi if (!vht) 172551e1ef4SLorenzo Bianconi return; 173551e1ef4SLorenzo Bianconi 174551e1ef4SLorenzo Bianconi vht_cap = &sband->vht_cap; 175551e1ef4SLorenzo Bianconi if (nstream > 1) 176551e1ef4SLorenzo Bianconi vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; 177551e1ef4SLorenzo Bianconi else 178551e1ef4SLorenzo Bianconi vht_cap->cap &= ~IEEE80211_VHT_CAP_TXSTBC; 179551e1ef4SLorenzo Bianconi 180551e1ef4SLorenzo Bianconi for (i = 0; i < 8; i++) { 181551e1ef4SLorenzo Bianconi if (i < nstream) 182551e1ef4SLorenzo Bianconi mcs_map |= (IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2)); 183551e1ef4SLorenzo Bianconi else 184551e1ef4SLorenzo Bianconi mcs_map |= 185551e1ef4SLorenzo Bianconi (IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2)); 186551e1ef4SLorenzo Bianconi } 187551e1ef4SLorenzo Bianconi vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); 188551e1ef4SLorenzo Bianconi vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); 189551e1ef4SLorenzo Bianconi } 190551e1ef4SLorenzo Bianconi 191bb3e3fecSRyder Lee void mt76_set_stream_caps(struct mt76_phy *phy, bool vht) 1925ebdc3e0SLorenzo Bianconi { 19348dbce5cSLorenzo Bianconi if (phy->cap.has_2ghz) 194bb3e3fecSRyder Lee mt76_init_stream_cap(phy, &phy->sband_2g.sband, false); 19548dbce5cSLorenzo Bianconi if (phy->cap.has_5ghz) 196bb3e3fecSRyder Lee mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht); 1975ebdc3e0SLorenzo Bianconi } 1985ebdc3e0SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_set_stream_caps); 1995ebdc3e0SLorenzo Bianconi 20017f1de56SFelix Fietkau static int 20177af762eSLorenzo Bianconi mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband, 20217f1de56SFelix Fietkau const struct ieee80211_channel *chan, int n_chan, 20317f1de56SFelix Fietkau struct ieee80211_rate *rates, int n_rates, bool vht) 20417f1de56SFelix Fietkau { 20517f1de56SFelix Fietkau struct ieee80211_supported_band *sband = &msband->sband; 20617f1de56SFelix Fietkau struct ieee80211_sta_vht_cap *vht_cap; 20777af762eSLorenzo Bianconi struct ieee80211_sta_ht_cap *ht_cap; 20877af762eSLorenzo Bianconi struct mt76_dev *dev = phy->dev; 20917f1de56SFelix Fietkau void *chanlist; 21017f1de56SFelix Fietkau int size; 21117f1de56SFelix Fietkau 21217f1de56SFelix Fietkau size = n_chan * sizeof(*chan); 21317f1de56SFelix Fietkau chanlist = devm_kmemdup(dev->dev, chan, size, GFP_KERNEL); 21417f1de56SFelix Fietkau if (!chanlist) 21517f1de56SFelix Fietkau return -ENOMEM; 21617f1de56SFelix Fietkau 217a86854d0SKees Cook msband->chan = devm_kcalloc(dev->dev, n_chan, sizeof(*msband->chan), 21817f1de56SFelix Fietkau GFP_KERNEL); 21917f1de56SFelix Fietkau if (!msband->chan) 22017f1de56SFelix Fietkau return -ENOMEM; 22117f1de56SFelix Fietkau 22217f1de56SFelix Fietkau sband->channels = chanlist; 22317f1de56SFelix Fietkau sband->n_channels = n_chan; 22417f1de56SFelix Fietkau sband->bitrates = rates; 22517f1de56SFelix Fietkau sband->n_bitrates = n_rates; 22617f1de56SFelix Fietkau 22717f1de56SFelix Fietkau ht_cap = &sband->ht_cap; 22817f1de56SFelix Fietkau ht_cap->ht_supported = true; 22917f1de56SFelix Fietkau ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 23017f1de56SFelix Fietkau IEEE80211_HT_CAP_GRN_FLD | 23117f1de56SFelix Fietkau IEEE80211_HT_CAP_SGI_20 | 23217f1de56SFelix Fietkau IEEE80211_HT_CAP_SGI_40 | 23317f1de56SFelix Fietkau (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 23417f1de56SFelix Fietkau 23517f1de56SFelix Fietkau ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 23617f1de56SFelix Fietkau ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 23717f1de56SFelix Fietkau 23877af762eSLorenzo Bianconi mt76_init_stream_cap(phy, sband, vht); 239551e1ef4SLorenzo Bianconi 24017f1de56SFelix Fietkau if (!vht) 24117f1de56SFelix Fietkau return 0; 24217f1de56SFelix Fietkau 24317f1de56SFelix Fietkau vht_cap = &sband->vht_cap; 24417f1de56SFelix Fietkau vht_cap->vht_supported = true; 24517f1de56SFelix Fietkau vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC | 24617f1de56SFelix Fietkau IEEE80211_VHT_CAP_RXSTBC_1 | 24749149d3fSFelix Fietkau IEEE80211_VHT_CAP_SHORT_GI_80 | 248f1103fa6SRyder Lee IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | 249f1103fa6SRyder Lee IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | 25049149d3fSFelix Fietkau (3 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); 25117f1de56SFelix Fietkau 25217f1de56SFelix Fietkau return 0; 25317f1de56SFelix Fietkau } 25417f1de56SFelix Fietkau 25517f1de56SFelix Fietkau static int 25677af762eSLorenzo Bianconi mt76_init_sband_2g(struct mt76_phy *phy, struct ieee80211_rate *rates, 25717f1de56SFelix Fietkau int n_rates) 25817f1de56SFelix Fietkau { 25977af762eSLorenzo Bianconi phy->hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; 26017f1de56SFelix Fietkau 26177af762eSLorenzo Bianconi return mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz, 26277af762eSLorenzo Bianconi ARRAY_SIZE(mt76_channels_2ghz), rates, 26377af762eSLorenzo Bianconi n_rates, false); 26417f1de56SFelix Fietkau } 26517f1de56SFelix Fietkau 26617f1de56SFelix Fietkau static int 26777af762eSLorenzo Bianconi mt76_init_sband_5g(struct mt76_phy *phy, struct ieee80211_rate *rates, 26817f1de56SFelix Fietkau int n_rates, bool vht) 26917f1de56SFelix Fietkau { 27077af762eSLorenzo Bianconi phy->hw->wiphy->bands[NL80211_BAND_5GHZ] = &phy->sband_5g.sband; 27117f1de56SFelix Fietkau 27277af762eSLorenzo Bianconi return mt76_init_sband(phy, &phy->sband_5g, mt76_channels_5ghz, 27377af762eSLorenzo Bianconi ARRAY_SIZE(mt76_channels_5ghz), rates, 27477af762eSLorenzo Bianconi n_rates, vht); 27517f1de56SFelix Fietkau } 27617f1de56SFelix Fietkau 27717f1de56SFelix Fietkau static void 278c89d3625SFelix Fietkau mt76_check_sband(struct mt76_phy *phy, struct mt76_sband *msband, 279c89d3625SFelix Fietkau enum nl80211_band band) 28017f1de56SFelix Fietkau { 281c89d3625SFelix Fietkau struct ieee80211_supported_band *sband = &msband->sband; 28217f1de56SFelix Fietkau bool found = false; 28317f1de56SFelix Fietkau int i; 28417f1de56SFelix Fietkau 28517f1de56SFelix Fietkau if (!sband) 28617f1de56SFelix Fietkau return; 28717f1de56SFelix Fietkau 28817f1de56SFelix Fietkau for (i = 0; i < sband->n_channels; i++) { 28917f1de56SFelix Fietkau if (sband->channels[i].flags & IEEE80211_CHAN_DISABLED) 29017f1de56SFelix Fietkau continue; 29117f1de56SFelix Fietkau 29217f1de56SFelix Fietkau found = true; 29317f1de56SFelix Fietkau break; 29417f1de56SFelix Fietkau } 29517f1de56SFelix Fietkau 296c89d3625SFelix Fietkau if (found) { 297c89d3625SFelix Fietkau phy->chandef.chan = &sband->channels[0]; 298c89d3625SFelix Fietkau phy->chan_state = &msband->chan[0]; 29917f1de56SFelix Fietkau return; 300c89d3625SFelix Fietkau } 30117f1de56SFelix Fietkau 30217f1de56SFelix Fietkau sband->n_channels = 0; 303c89d3625SFelix Fietkau phy->hw->wiphy->bands[band] = NULL; 30417f1de56SFelix Fietkau } 30517f1de56SFelix Fietkau 306c89d3625SFelix Fietkau static void 30798df2baeSLorenzo Bianconi mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) 308c89d3625SFelix Fietkau { 30998df2baeSLorenzo Bianconi struct mt76_dev *dev = phy->dev; 310c89d3625SFelix Fietkau struct wiphy *wiphy = hw->wiphy; 311c89d3625SFelix Fietkau 312c89d3625SFelix Fietkau SET_IEEE80211_DEV(hw, dev->dev); 31398df2baeSLorenzo Bianconi SET_IEEE80211_PERM_ADDR(hw, phy->macaddr); 314c89d3625SFelix Fietkau 315c89d3625SFelix Fietkau wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; 316dd89a013SLorenzo Bianconi wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH | 317b807b368SLorenzo Bianconi WIPHY_FLAG_SUPPORTS_TDLS | 318b807b368SLorenzo Bianconi WIPHY_FLAG_AP_UAPSD; 319c89d3625SFelix Fietkau 320c89d3625SFelix Fietkau wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); 321c89d3625SFelix Fietkau wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); 322d9c54264SFelix Fietkau wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL); 323c89d3625SFelix Fietkau 324c89d3625SFelix Fietkau wiphy->available_antennas_tx = dev->phy.antenna_mask; 325c89d3625SFelix Fietkau wiphy->available_antennas_rx = dev->phy.antenna_mask; 326c89d3625SFelix Fietkau 327c89d3625SFelix Fietkau hw->txq_data_size = sizeof(struct mt76_txq); 328b807b368SLorenzo Bianconi hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL; 329c9619dfaSShayne Chen 330c9619dfaSShayne Chen if (!hw->max_tx_fragments) 331c89d3625SFelix Fietkau hw->max_tx_fragments = 16; 332c89d3625SFelix Fietkau 333c89d3625SFelix Fietkau ieee80211_hw_set(hw, SIGNAL_DBM); 334c89d3625SFelix Fietkau ieee80211_hw_set(hw, AMPDU_AGGREGATION); 335c89d3625SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); 336c89d3625SFelix Fietkau ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); 337c89d3625SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); 338c89d3625SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); 339ed89b893SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); 340b443e55fSRyder Lee 341b443e55fSRyder Lee if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) { 342c89d3625SFelix Fietkau ieee80211_hw_set(hw, TX_AMSDU); 343c89d3625SFelix Fietkau ieee80211_hw_set(hw, TX_FRAG_LIST); 344b443e55fSRyder Lee } 345d39b52e3SSean Wang 346c89d3625SFelix Fietkau ieee80211_hw_set(hw, MFP_CAPABLE); 347c89d3625SFelix Fietkau ieee80211_hw_set(hw, AP_LINK_PS); 348c89d3625SFelix Fietkau ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); 349c89d3625SFelix Fietkau } 350c89d3625SFelix Fietkau 351c89d3625SFelix Fietkau struct mt76_phy * 352c89d3625SFelix Fietkau mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, 353c89d3625SFelix Fietkau const struct ieee80211_ops *ops) 354c89d3625SFelix Fietkau { 355c89d3625SFelix Fietkau struct ieee80211_hw *hw; 356db78a791SLorenzo Bianconi unsigned int phy_size; 357c89d3625SFelix Fietkau struct mt76_phy *phy; 358c89d3625SFelix Fietkau 359c89d3625SFelix Fietkau phy_size = ALIGN(sizeof(*phy), 8); 360db78a791SLorenzo Bianconi hw = ieee80211_alloc_hw(size + phy_size, ops); 361c89d3625SFelix Fietkau if (!hw) 362c89d3625SFelix Fietkau return NULL; 363c89d3625SFelix Fietkau 364c89d3625SFelix Fietkau phy = hw->priv; 365c89d3625SFelix Fietkau phy->dev = dev; 366c89d3625SFelix Fietkau phy->hw = hw; 367db78a791SLorenzo Bianconi phy->priv = hw->priv + phy_size; 368c89d3625SFelix Fietkau 3698af414e8SLorenzo Bianconi hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; 3708af414e8SLorenzo Bianconi hw->wiphy->interface_modes = 3718af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_STATION) | 3728af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_AP) | 3738af414e8SLorenzo Bianconi #ifdef CONFIG_MAC80211_MESH 3748af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_MESH_POINT) | 3758af414e8SLorenzo Bianconi #endif 3768af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_P2P_CLIENT) | 3778af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_P2P_GO) | 3788af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_ADHOC); 3798af414e8SLorenzo Bianconi 380c89d3625SFelix Fietkau return phy; 381c89d3625SFelix Fietkau } 382c89d3625SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_alloc_phy); 383c89d3625SFelix Fietkau 384db78a791SLorenzo Bianconi int mt76_register_phy(struct mt76_phy *phy, bool vht, 385db78a791SLorenzo Bianconi struct ieee80211_rate *rates, int n_rates) 386c89d3625SFelix Fietkau { 387c89d3625SFelix Fietkau int ret; 388c89d3625SFelix Fietkau 38998df2baeSLorenzo Bianconi mt76_phy_init(phy, phy->hw); 390db78a791SLorenzo Bianconi 391db78a791SLorenzo Bianconi if (phy->cap.has_2ghz) { 392db78a791SLorenzo Bianconi ret = mt76_init_sband_2g(phy, rates, n_rates); 393db78a791SLorenzo Bianconi if (ret) 394db78a791SLorenzo Bianconi return ret; 395db78a791SLorenzo Bianconi } 396db78a791SLorenzo Bianconi 397db78a791SLorenzo Bianconi if (phy->cap.has_5ghz) { 398db78a791SLorenzo Bianconi ret = mt76_init_sband_5g(phy, rates + 4, n_rates - 4, vht); 399db78a791SLorenzo Bianconi if (ret) 400db78a791SLorenzo Bianconi return ret; 401db78a791SLorenzo Bianconi } 402db78a791SLorenzo Bianconi 403db78a791SLorenzo Bianconi wiphy_read_of_freq_limits(phy->hw->wiphy); 404db78a791SLorenzo Bianconi mt76_check_sband(phy, &phy->sband_2g, NL80211_BAND_2GHZ); 405db78a791SLorenzo Bianconi mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ); 406db78a791SLorenzo Bianconi 407c89d3625SFelix Fietkau ret = ieee80211_register_hw(phy->hw); 408c89d3625SFelix Fietkau if (ret) 409c89d3625SFelix Fietkau return ret; 410c89d3625SFelix Fietkau 411c89d3625SFelix Fietkau phy->dev->phy2 = phy; 412db78a791SLorenzo Bianconi 413c89d3625SFelix Fietkau return 0; 414c89d3625SFelix Fietkau } 415c89d3625SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_register_phy); 416c89d3625SFelix Fietkau 417db78a791SLorenzo Bianconi void mt76_unregister_phy(struct mt76_phy *phy) 418c89d3625SFelix Fietkau { 419c89d3625SFelix Fietkau struct mt76_dev *dev = phy->dev; 420c89d3625SFelix Fietkau 421c89d3625SFelix Fietkau mt76_tx_status_check(dev, NULL, true); 422c89d3625SFelix Fietkau ieee80211_unregister_hw(phy->hw); 42394b6df08SFelix Fietkau dev->phy2 = NULL; 424c89d3625SFelix Fietkau } 425c89d3625SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_unregister_phy); 426c89d3625SFelix Fietkau 427a85b590cSFelix Fietkau struct mt76_dev * 428c0f7b25aSLorenzo Bianconi mt76_alloc_device(struct device *pdev, unsigned int size, 429c0f7b25aSLorenzo Bianconi const struct ieee80211_ops *ops, 430c0f7b25aSLorenzo Bianconi const struct mt76_driver_ops *drv_ops) 431a85b590cSFelix Fietkau { 432a85b590cSFelix Fietkau struct ieee80211_hw *hw; 433ac24dd35SFelix Fietkau struct mt76_phy *phy; 434a85b590cSFelix Fietkau struct mt76_dev *dev; 435e5443256SFelix Fietkau int i; 436a85b590cSFelix Fietkau 437a85b590cSFelix Fietkau hw = ieee80211_alloc_hw(size, ops); 438a85b590cSFelix Fietkau if (!hw) 439a85b590cSFelix Fietkau return NULL; 440a85b590cSFelix Fietkau 441a85b590cSFelix Fietkau dev = hw->priv; 442a85b590cSFelix Fietkau dev->hw = hw; 443c0f7b25aSLorenzo Bianconi dev->dev = pdev; 444c0f7b25aSLorenzo Bianconi dev->drv = drv_ops; 445c0f7b25aSLorenzo Bianconi 446ac24dd35SFelix Fietkau phy = &dev->phy; 447ac24dd35SFelix Fietkau phy->dev = dev; 448ac24dd35SFelix Fietkau phy->hw = hw; 449ac24dd35SFelix Fietkau 450a85b590cSFelix Fietkau spin_lock_init(&dev->rx_lock); 451a85b590cSFelix Fietkau spin_lock_init(&dev->lock); 452a85b590cSFelix Fietkau spin_lock_init(&dev->cc_lock); 453108a4861SStanislaw Gruszka mutex_init(&dev->mutex); 45426e40d4cSFelix Fietkau init_waitqueue_head(&dev->tx_wait); 45588046b2cSFelix Fietkau skb_queue_head_init(&dev->status_list); 456a85b590cSFelix Fietkau 45709872957SLorenzo Bianconi skb_queue_head_init(&dev->mcu.res_q); 45809872957SLorenzo Bianconi init_waitqueue_head(&dev->mcu.wait); 45909872957SLorenzo Bianconi mutex_init(&dev->mcu.mutex); 460781eef5bSFelix Fietkau dev->tx_worker.fn = mt76_tx_worker; 46109872957SLorenzo Bianconi 4628af414e8SLorenzo Bianconi hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; 4638af414e8SLorenzo Bianconi hw->wiphy->interface_modes = 4648af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_STATION) | 4658af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_AP) | 4668af414e8SLorenzo Bianconi #ifdef CONFIG_MAC80211_MESH 4678af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_MESH_POINT) | 4688af414e8SLorenzo Bianconi #endif 4698af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_P2P_CLIENT) | 4708af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_P2P_GO) | 4718af414e8SLorenzo Bianconi BIT(NL80211_IFTYPE_ADHOC); 4728af414e8SLorenzo Bianconi 47351252cc5SLorenzo Bianconi spin_lock_init(&dev->token_lock); 47451252cc5SLorenzo Bianconi idr_init(&dev->token); 47551252cc5SLorenzo Bianconi 476e5443256SFelix Fietkau INIT_LIST_HEAD(&dev->txwi_cache); 477e5443256SFelix Fietkau 478e5443256SFelix Fietkau for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) 479e5443256SFelix Fietkau skb_queue_head_init(&dev->rx_skb[i]); 480e5443256SFelix Fietkau 481a86f1d01SLorenzo Bianconi dev->wq = alloc_ordered_workqueue("mt76", 0); 482a86f1d01SLorenzo Bianconi if (!dev->wq) { 483a86f1d01SLorenzo Bianconi ieee80211_free_hw(hw); 484a86f1d01SLorenzo Bianconi return NULL; 485a86f1d01SLorenzo Bianconi } 486a86f1d01SLorenzo Bianconi 487a85b590cSFelix Fietkau return dev; 488a85b590cSFelix Fietkau } 489a85b590cSFelix Fietkau EXPORT_SYMBOL_GPL(mt76_alloc_device); 490a85b590cSFelix Fietkau 49117f1de56SFelix Fietkau int mt76_register_device(struct mt76_dev *dev, bool vht, 49217f1de56SFelix Fietkau struct ieee80211_rate *rates, int n_rates) 49317f1de56SFelix Fietkau { 49417f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 495c89d3625SFelix Fietkau struct mt76_phy *phy = &dev->phy; 49617f1de56SFelix Fietkau int ret; 49717f1de56SFelix Fietkau 49817f1de56SFelix Fietkau dev_set_drvdata(dev->dev, dev); 49998df2baeSLorenzo Bianconi mt76_phy_init(phy, hw); 50017f1de56SFelix Fietkau 50148dbce5cSLorenzo Bianconi if (phy->cap.has_2ghz) { 50277af762eSLorenzo Bianconi ret = mt76_init_sband_2g(phy, rates, n_rates); 50317f1de56SFelix Fietkau if (ret) 50417f1de56SFelix Fietkau return ret; 50517f1de56SFelix Fietkau } 50617f1de56SFelix Fietkau 50748dbce5cSLorenzo Bianconi if (phy->cap.has_5ghz) { 50877af762eSLorenzo Bianconi ret = mt76_init_sband_5g(phy, rates + 4, n_rates - 4, vht); 50917f1de56SFelix Fietkau if (ret) 51017f1de56SFelix Fietkau return ret; 51117f1de56SFelix Fietkau } 51217f1de56SFelix Fietkau 513c89d3625SFelix Fietkau wiphy_read_of_freq_limits(hw->wiphy); 514c89d3625SFelix Fietkau mt76_check_sband(&dev->phy, &phy->sband_2g, NL80211_BAND_2GHZ); 515c89d3625SFelix Fietkau mt76_check_sband(&dev->phy, &phy->sband_5g, NL80211_BAND_5GHZ); 51617f1de56SFelix Fietkau 517b374e868SArnd Bergmann if (IS_ENABLED(CONFIG_MT76_LEDS)) { 51817f1de56SFelix Fietkau ret = mt76_led_init(dev); 51917f1de56SFelix Fietkau if (ret) 52017f1de56SFelix Fietkau return ret; 521b374e868SArnd Bergmann } 52217f1de56SFelix Fietkau 523781eef5bSFelix Fietkau ret = ieee80211_register_hw(hw); 524781eef5bSFelix Fietkau if (ret) 525781eef5bSFelix Fietkau return ret; 526781eef5bSFelix Fietkau 527781eef5bSFelix Fietkau WARN_ON(mt76_worker_setup(hw, &dev->tx_worker, NULL, "tx")); 528781eef5bSFelix Fietkau sched_set_fifo_low(dev->tx_worker.task); 529781eef5bSFelix Fietkau 530781eef5bSFelix Fietkau return 0; 53117f1de56SFelix Fietkau } 53217f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_register_device); 53317f1de56SFelix Fietkau 53417f1de56SFelix Fietkau void mt76_unregister_device(struct mt76_dev *dev) 53517f1de56SFelix Fietkau { 53617f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 53717f1de56SFelix Fietkau 538d68f4e43SArnd Bergmann if (IS_ENABLED(CONFIG_MT76_LEDS)) 53936f7e2b2SFelix Fietkau mt76_led_cleanup(dev); 54079d1c94cSFelix Fietkau mt76_tx_status_check(dev, NULL, true); 54117f1de56SFelix Fietkau ieee80211_unregister_hw(hw); 54217f1de56SFelix Fietkau } 54317f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_unregister_device); 54417f1de56SFelix Fietkau 545def34a2fSLorenzo Bianconi void mt76_free_device(struct mt76_dev *dev) 546def34a2fSLorenzo Bianconi { 547781eef5bSFelix Fietkau mt76_worker_teardown(&dev->tx_worker); 548a86f1d01SLorenzo Bianconi if (dev->wq) { 549a86f1d01SLorenzo Bianconi destroy_workqueue(dev->wq); 550a86f1d01SLorenzo Bianconi dev->wq = NULL; 551a86f1d01SLorenzo Bianconi } 552def34a2fSLorenzo Bianconi ieee80211_free_hw(dev->hw); 553def34a2fSLorenzo Bianconi } 554def34a2fSLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_free_device); 555def34a2fSLorenzo Bianconi 556cc4b3c13SLorenzo Bianconi static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q) 557cc4b3c13SLorenzo Bianconi { 558cc4b3c13SLorenzo Bianconi struct sk_buff *skb = phy->rx_amsdu[q].head; 5592c2bdd23SFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 560cc4b3c13SLorenzo Bianconi struct mt76_dev *dev = phy->dev; 561cc4b3c13SLorenzo Bianconi 562cc4b3c13SLorenzo Bianconi phy->rx_amsdu[q].head = NULL; 563cc4b3c13SLorenzo Bianconi phy->rx_amsdu[q].tail = NULL; 5642c2bdd23SFelix Fietkau 5652c2bdd23SFelix Fietkau /* 5662c2bdd23SFelix Fietkau * Validate if the amsdu has a proper first subframe. 5672c2bdd23SFelix Fietkau * A single MSDU can be parsed as A-MSDU when the unauthenticated A-MSDU 5682c2bdd23SFelix Fietkau * flag of the QoS header gets flipped. In such cases, the first 5692c2bdd23SFelix Fietkau * subframe has a LLC/SNAP header in the location of the destination 5702c2bdd23SFelix Fietkau * address. 5712c2bdd23SFelix Fietkau */ 5722c2bdd23SFelix Fietkau if (skb_shinfo(skb)->frag_list) { 5732c2bdd23SFelix Fietkau int offset = 0; 5742c2bdd23SFelix Fietkau 5752c2bdd23SFelix Fietkau if (!(status->flag & RX_FLAG_8023)) { 5762c2bdd23SFelix Fietkau offset = ieee80211_get_hdrlen_from_skb(skb); 5772c2bdd23SFelix Fietkau 5782c2bdd23SFelix Fietkau if ((status->flag & 5792c2bdd23SFelix Fietkau (RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED)) == 5802c2bdd23SFelix Fietkau RX_FLAG_DECRYPTED) 5812c2bdd23SFelix Fietkau offset += 8; 5822c2bdd23SFelix Fietkau } 5832c2bdd23SFelix Fietkau 5842c2bdd23SFelix Fietkau if (ether_addr_equal(skb->data + offset, rfc1042_header)) { 5852c2bdd23SFelix Fietkau dev_kfree_skb(skb); 5862c2bdd23SFelix Fietkau return; 5872c2bdd23SFelix Fietkau } 5882c2bdd23SFelix Fietkau } 589cc4b3c13SLorenzo Bianconi __skb_queue_tail(&dev->rx_skb[q], skb); 590cc4b3c13SLorenzo Bianconi } 591cc4b3c13SLorenzo Bianconi 592cc4b3c13SLorenzo Bianconi static void mt76_rx_release_burst(struct mt76_phy *phy, enum mt76_rxq_id q, 593cc4b3c13SLorenzo Bianconi struct sk_buff *skb) 594cc4b3c13SLorenzo Bianconi { 595cc4b3c13SLorenzo Bianconi struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 596cc4b3c13SLorenzo Bianconi 597cc4b3c13SLorenzo Bianconi if (phy->rx_amsdu[q].head && 598cc4b3c13SLorenzo Bianconi (!status->amsdu || status->first_amsdu || 599cc4b3c13SLorenzo Bianconi status->seqno != phy->rx_amsdu[q].seqno)) 600cc4b3c13SLorenzo Bianconi mt76_rx_release_amsdu(phy, q); 601cc4b3c13SLorenzo Bianconi 602cc4b3c13SLorenzo Bianconi if (!phy->rx_amsdu[q].head) { 603cc4b3c13SLorenzo Bianconi phy->rx_amsdu[q].tail = &skb_shinfo(skb)->frag_list; 604cc4b3c13SLorenzo Bianconi phy->rx_amsdu[q].seqno = status->seqno; 605cc4b3c13SLorenzo Bianconi phy->rx_amsdu[q].head = skb; 606cc4b3c13SLorenzo Bianconi } else { 607cc4b3c13SLorenzo Bianconi *phy->rx_amsdu[q].tail = skb; 608cc4b3c13SLorenzo Bianconi phy->rx_amsdu[q].tail = &skb->next; 609cc4b3c13SLorenzo Bianconi } 610cc4b3c13SLorenzo Bianconi 611cc4b3c13SLorenzo Bianconi if (!status->amsdu || status->last_amsdu) 612cc4b3c13SLorenzo Bianconi mt76_rx_release_amsdu(phy, q); 613cc4b3c13SLorenzo Bianconi } 614cc4b3c13SLorenzo Bianconi 61517f1de56SFelix Fietkau void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) 61617f1de56SFelix Fietkau { 617011849e0SFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 618011849e0SFelix Fietkau struct mt76_phy *phy = mt76_dev_phy(dev, status->ext_phy); 619011849e0SFelix Fietkau 620011849e0SFelix Fietkau if (!test_bit(MT76_STATE_RUNNING, &phy->state)) { 62117f1de56SFelix Fietkau dev_kfree_skb(skb); 62217f1de56SFelix Fietkau return; 62317f1de56SFelix Fietkau } 62417f1de56SFelix Fietkau 625f0efa862SFelix Fietkau #ifdef CONFIG_NL80211_TESTMODE 626c918c74dSShayne Chen if (phy->test.state == MT76_TM_STATE_RX_FRAMES) { 627c918c74dSShayne Chen phy->test.rx_stats.packets[q]++; 628f0efa862SFelix Fietkau if (status->flag & RX_FLAG_FAILED_FCS_CRC) 629c918c74dSShayne Chen phy->test.rx_stats.fcs_error[q]++; 630f0efa862SFelix Fietkau } 631f0efa862SFelix Fietkau #endif 632cc4b3c13SLorenzo Bianconi 633cc4b3c13SLorenzo Bianconi mt76_rx_release_burst(phy, q, skb); 63417f1de56SFelix Fietkau } 63517f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_rx); 63617f1de56SFelix Fietkau 6375a95ca41SFelix Fietkau bool mt76_has_tx_pending(struct mt76_phy *phy) 63826e40d4cSFelix Fietkau { 639af005f26SLorenzo Bianconi struct mt76_queue *q; 64091990519SLorenzo Bianconi int i; 6415a95ca41SFelix Fietkau 6425a95ca41SFelix Fietkau for (i = 0; i < __MT_TXQ_MAX; i++) { 64391990519SLorenzo Bianconi q = phy->q_tx[i]; 644af005f26SLorenzo Bianconi if (q && q->queued) 64526e40d4cSFelix Fietkau return true; 64626e40d4cSFelix Fietkau } 64726e40d4cSFelix Fietkau 64826e40d4cSFelix Fietkau return false; 64926e40d4cSFelix Fietkau } 65039d501d9SStanislaw Gruszka EXPORT_SYMBOL_GPL(mt76_has_tx_pending); 65126e40d4cSFelix Fietkau 6520fd0eb54SFelix Fietkau static struct mt76_channel_state * 65396747a51SFelix Fietkau mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c) 6540fd0eb54SFelix Fietkau { 6550fd0eb54SFelix Fietkau struct mt76_sband *msband; 6560fd0eb54SFelix Fietkau int idx; 6570fd0eb54SFelix Fietkau 6580fd0eb54SFelix Fietkau if (c->band == NL80211_BAND_2GHZ) 65996747a51SFelix Fietkau msband = &phy->sband_2g; 6600fd0eb54SFelix Fietkau else 66196747a51SFelix Fietkau msband = &phy->sband_5g; 6620fd0eb54SFelix Fietkau 6630fd0eb54SFelix Fietkau idx = c - &msband->sband.channels[0]; 6640fd0eb54SFelix Fietkau return &msband->chan[idx]; 6650fd0eb54SFelix Fietkau } 6660fd0eb54SFelix Fietkau 66704414240SLorenzo Bianconi void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time) 66896747a51SFelix Fietkau { 66996747a51SFelix Fietkau struct mt76_channel_state *state = phy->chan_state; 67096747a51SFelix Fietkau 67196747a51SFelix Fietkau state->cc_active += ktime_to_us(ktime_sub(time, 67296747a51SFelix Fietkau phy->survey_time)); 67396747a51SFelix Fietkau phy->survey_time = time; 67496747a51SFelix Fietkau } 67504414240SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_update_survey_active_time); 67696747a51SFelix Fietkau 677c560b137SRyder Lee void mt76_update_survey(struct mt76_phy *phy) 6785ce09c1aSFelix Fietkau { 679c560b137SRyder Lee struct mt76_dev *dev = phy->dev; 680aec65e48SFelix Fietkau ktime_t cur_time; 681aec65e48SFelix Fietkau 6825ce09c1aSFelix Fietkau if (dev->drv->update_survey) 683c560b137SRyder Lee dev->drv->update_survey(phy); 6845ce09c1aSFelix Fietkau 685aec65e48SFelix Fietkau cur_time = ktime_get_boottime(); 686c560b137SRyder Lee mt76_update_survey_active_time(phy, cur_time); 687aec65e48SFelix Fietkau 6885ce09c1aSFelix Fietkau if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) { 689c560b137SRyder Lee struct mt76_channel_state *state = phy->chan_state; 69096747a51SFelix Fietkau 691237312c5SLorenzo Bianconi spin_lock_bh(&dev->cc_lock); 6925ce09c1aSFelix Fietkau state->cc_bss_rx += dev->cur_cc_bss_rx; 6935ce09c1aSFelix Fietkau dev->cur_cc_bss_rx = 0; 694237312c5SLorenzo Bianconi spin_unlock_bh(&dev->cc_lock); 6955ce09c1aSFelix Fietkau } 6965ce09c1aSFelix Fietkau } 6975ce09c1aSFelix Fietkau EXPORT_SYMBOL_GPL(mt76_update_survey); 6985ce09c1aSFelix Fietkau 69996747a51SFelix Fietkau void mt76_set_channel(struct mt76_phy *phy) 70017f1de56SFelix Fietkau { 70196747a51SFelix Fietkau struct mt76_dev *dev = phy->dev; 70296747a51SFelix Fietkau struct ieee80211_hw *hw = phy->hw; 70317f1de56SFelix Fietkau struct cfg80211_chan_def *chandef = &hw->conf.chandef; 70417f1de56SFelix Fietkau bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; 70526e40d4cSFelix Fietkau int timeout = HZ / 5; 70617f1de56SFelix Fietkau 7075a95ca41SFelix Fietkau wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout); 708c560b137SRyder Lee mt76_update_survey(phy); 70917f1de56SFelix Fietkau 71096747a51SFelix Fietkau phy->chandef = *chandef; 71196747a51SFelix Fietkau phy->chan_state = mt76_channel_state(phy, chandef->chan); 71217f1de56SFelix Fietkau 71317f1de56SFelix Fietkau if (!offchannel) 71496747a51SFelix Fietkau phy->main_chan = chandef->chan; 71517f1de56SFelix Fietkau 71696747a51SFelix Fietkau if (chandef->chan != phy->main_chan) 71796747a51SFelix Fietkau memset(phy->chan_state, 0, sizeof(*phy->chan_state)); 71817f1de56SFelix Fietkau } 71917f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_set_channel); 72017f1de56SFelix Fietkau 72117f1de56SFelix Fietkau int mt76_get_survey(struct ieee80211_hw *hw, int idx, 72217f1de56SFelix Fietkau struct survey_info *survey) 72317f1de56SFelix Fietkau { 72496747a51SFelix Fietkau struct mt76_phy *phy = hw->priv; 72596747a51SFelix Fietkau struct mt76_dev *dev = phy->dev; 72617f1de56SFelix Fietkau struct mt76_sband *sband; 72717f1de56SFelix Fietkau struct ieee80211_channel *chan; 72817f1de56SFelix Fietkau struct mt76_channel_state *state; 72917f1de56SFelix Fietkau int ret = 0; 73017f1de56SFelix Fietkau 731237312c5SLorenzo Bianconi mutex_lock(&dev->mutex); 73217f1de56SFelix Fietkau if (idx == 0 && dev->drv->update_survey) 733c560b137SRyder Lee mt76_update_survey(phy); 73417f1de56SFelix Fietkau 73596747a51SFelix Fietkau sband = &phy->sband_2g; 73617f1de56SFelix Fietkau if (idx >= sband->sband.n_channels) { 73717f1de56SFelix Fietkau idx -= sband->sband.n_channels; 73896747a51SFelix Fietkau sband = &phy->sband_5g; 73917f1de56SFelix Fietkau } 74017f1de56SFelix Fietkau 741237312c5SLorenzo Bianconi if (idx >= sband->sband.n_channels) { 742237312c5SLorenzo Bianconi ret = -ENOENT; 743237312c5SLorenzo Bianconi goto out; 744237312c5SLorenzo Bianconi } 74517f1de56SFelix Fietkau 74617f1de56SFelix Fietkau chan = &sband->sband.channels[idx]; 74796747a51SFelix Fietkau state = mt76_channel_state(phy, chan); 74817f1de56SFelix Fietkau 74917f1de56SFelix Fietkau memset(survey, 0, sizeof(*survey)); 75017f1de56SFelix Fietkau survey->channel = chan; 75117f1de56SFelix Fietkau survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY; 752ea565833SFelix Fietkau survey->filled |= dev->drv->survey_flags; 753e5051965SFelix Fietkau if (state->noise) 754e5051965SFelix Fietkau survey->filled |= SURVEY_INFO_NOISE_DBM; 755e5051965SFelix Fietkau 75696747a51SFelix Fietkau if (chan == phy->main_chan) { 75717f1de56SFelix Fietkau survey->filled |= SURVEY_INFO_IN_USE; 75817f1de56SFelix Fietkau 7595ce09c1aSFelix Fietkau if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) 7605ce09c1aSFelix Fietkau survey->filled |= SURVEY_INFO_TIME_BSS_RX; 7615ce09c1aSFelix Fietkau } 7625ce09c1aSFelix Fietkau 76317f1de56SFelix Fietkau survey->time_busy = div_u64(state->cc_busy, 1000); 7646bfa6e38SLorenzo Bianconi survey->time_rx = div_u64(state->cc_rx, 1000); 765237312c5SLorenzo Bianconi survey->time = div_u64(state->cc_active, 1000); 766e5051965SFelix Fietkau survey->noise = state->noise; 767237312c5SLorenzo Bianconi 768237312c5SLorenzo Bianconi spin_lock_bh(&dev->cc_lock); 769237312c5SLorenzo Bianconi survey->time_bss_rx = div_u64(state->cc_bss_rx, 1000); 770ea565833SFelix Fietkau survey->time_tx = div_u64(state->cc_tx, 1000); 77117f1de56SFelix Fietkau spin_unlock_bh(&dev->cc_lock); 77217f1de56SFelix Fietkau 773237312c5SLorenzo Bianconi out: 774237312c5SLorenzo Bianconi mutex_unlock(&dev->mutex); 775237312c5SLorenzo Bianconi 77617f1de56SFelix Fietkau return ret; 77717f1de56SFelix Fietkau } 77817f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_get_survey); 77917f1de56SFelix Fietkau 78030ce7f44SFelix Fietkau void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid, 78130ce7f44SFelix Fietkau struct ieee80211_key_conf *key) 78230ce7f44SFelix Fietkau { 78330ce7f44SFelix Fietkau struct ieee80211_key_seq seq; 78430ce7f44SFelix Fietkau int i; 78530ce7f44SFelix Fietkau 78630ce7f44SFelix Fietkau wcid->rx_check_pn = false; 78730ce7f44SFelix Fietkau 78830ce7f44SFelix Fietkau if (!key) 78930ce7f44SFelix Fietkau return; 79030ce7f44SFelix Fietkau 79101cfc1b4SLorenzo Bianconi if (key->cipher != WLAN_CIPHER_SUITE_CCMP) 79201cfc1b4SLorenzo Bianconi return; 79330ce7f44SFelix Fietkau 79401cfc1b4SLorenzo Bianconi wcid->rx_check_pn = true; 79530ce7f44SFelix Fietkau for (i = 0; i < IEEE80211_NUM_TIDS; i++) { 79630ce7f44SFelix Fietkau ieee80211_get_key_rx_seq(key, i, &seq); 79730ce7f44SFelix Fietkau memcpy(wcid->rx_key_pn[i], seq.ccmp.pn, sizeof(seq.ccmp.pn)); 79830ce7f44SFelix Fietkau } 79930ce7f44SFelix Fietkau } 80030ce7f44SFelix Fietkau EXPORT_SYMBOL(mt76_wcid_key_setup); 80130ce7f44SFelix Fietkau 802bfc394ddSFelix Fietkau static void 803bfc394ddSFelix Fietkau mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, 804bfc394ddSFelix Fietkau struct ieee80211_hw **hw, 805bfc394ddSFelix Fietkau struct ieee80211_sta **sta) 8064e34249eSFelix Fietkau { 8074e34249eSFelix Fietkau struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 8084e34249eSFelix Fietkau struct mt76_rx_status mstat; 8094e34249eSFelix Fietkau 8104e34249eSFelix Fietkau mstat = *((struct mt76_rx_status *)skb->cb); 8114e34249eSFelix Fietkau memset(status, 0, sizeof(*status)); 8124e34249eSFelix Fietkau 8134e34249eSFelix Fietkau status->flag = mstat.flag; 8144e34249eSFelix Fietkau status->freq = mstat.freq; 8154e34249eSFelix Fietkau status->enc_flags = mstat.enc_flags; 8164e34249eSFelix Fietkau status->encoding = mstat.encoding; 8174e34249eSFelix Fietkau status->bw = mstat.bw; 818af4a2f2fSRyder Lee status->he_ru = mstat.he_ru; 819af4a2f2fSRyder Lee status->he_gi = mstat.he_gi; 820af4a2f2fSRyder Lee status->he_dcm = mstat.he_dcm; 8214e34249eSFelix Fietkau status->rate_idx = mstat.rate_idx; 8224e34249eSFelix Fietkau status->nss = mstat.nss; 8234e34249eSFelix Fietkau status->band = mstat.band; 8244e34249eSFelix Fietkau status->signal = mstat.signal; 8254e34249eSFelix Fietkau status->chains = mstat.chains; 826d515fdcaSFelix Fietkau status->ampdu_reference = mstat.ampdu_ref; 8270fda6d7bSRyder Lee status->device_timestamp = mstat.timestamp; 8280fda6d7bSRyder Lee status->mactime = mstat.timestamp; 8294e34249eSFelix Fietkau 8304e34249eSFelix Fietkau BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb)); 83113381dcdSRyder Lee BUILD_BUG_ON(sizeof(status->chain_signal) != 83213381dcdSRyder Lee sizeof(mstat.chain_signal)); 83313381dcdSRyder Lee memcpy(status->chain_signal, mstat.chain_signal, 83413381dcdSRyder Lee sizeof(mstat.chain_signal)); 8359c68a57bSFelix Fietkau 836bfc394ddSFelix Fietkau *sta = wcid_to_sta(mstat.wcid); 837bfc394ddSFelix Fietkau *hw = mt76_phy_hw(dev, mstat.ext_phy); 8384e34249eSFelix Fietkau } 8394e34249eSFelix Fietkau 84030ce7f44SFelix Fietkau static int 84130ce7f44SFelix Fietkau mt76_check_ccmp_pn(struct sk_buff *skb) 84230ce7f44SFelix Fietkau { 84330ce7f44SFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 84430ce7f44SFelix Fietkau struct mt76_wcid *wcid = status->wcid; 84530ce7f44SFelix Fietkau struct ieee80211_hdr *hdr; 846e195dad1SFelix Fietkau u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; 84730ce7f44SFelix Fietkau int ret; 84830ce7f44SFelix Fietkau 84930ce7f44SFelix Fietkau if (!(status->flag & RX_FLAG_DECRYPTED)) 85030ce7f44SFelix Fietkau return 0; 85130ce7f44SFelix Fietkau 85230ce7f44SFelix Fietkau if (!wcid || !wcid->rx_check_pn) 85330ce7f44SFelix Fietkau return 0; 85430ce7f44SFelix Fietkau 85530ce7f44SFelix Fietkau if (!(status->flag & RX_FLAG_IV_STRIPPED)) { 85630ce7f44SFelix Fietkau /* 85730ce7f44SFelix Fietkau * Validate the first fragment both here and in mac80211 85830ce7f44SFelix Fietkau * All further fragments will be validated by mac80211 only. 85930ce7f44SFelix Fietkau */ 86077ae1d5eSRyder Lee hdr = mt76_skb_get_hdr(skb); 86130ce7f44SFelix Fietkau if (ieee80211_is_frag(hdr) && 86230ce7f44SFelix Fietkau !ieee80211_is_first_frag(hdr->frame_control)) 86330ce7f44SFelix Fietkau return 0; 86430ce7f44SFelix Fietkau } 86530ce7f44SFelix Fietkau 86630ce7f44SFelix Fietkau BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0])); 867e195dad1SFelix Fietkau ret = memcmp(status->iv, wcid->rx_key_pn[tidno], 86830ce7f44SFelix Fietkau sizeof(status->iv)); 86930ce7f44SFelix Fietkau if (ret <= 0) 87030ce7f44SFelix Fietkau return -EINVAL; /* replay */ 87130ce7f44SFelix Fietkau 872e195dad1SFelix Fietkau memcpy(wcid->rx_key_pn[tidno], status->iv, sizeof(status->iv)); 87330ce7f44SFelix Fietkau 87430ce7f44SFelix Fietkau if (status->flag & RX_FLAG_IV_STRIPPED) 87530ce7f44SFelix Fietkau status->flag |= RX_FLAG_PN_VALIDATED; 87630ce7f44SFelix Fietkau 87730ce7f44SFelix Fietkau return 0; 87830ce7f44SFelix Fietkau } 87930ce7f44SFelix Fietkau 880d71ef286SFelix Fietkau static void 8815ce09c1aSFelix Fietkau mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status, 8825ce09c1aSFelix Fietkau int len) 8835ce09c1aSFelix Fietkau { 8845ce09c1aSFelix Fietkau struct mt76_wcid *wcid = status->wcid; 88585b7a5d0SLorenzo Bianconi struct ieee80211_rx_status info = { 88685b7a5d0SLorenzo Bianconi .enc_flags = status->enc_flags, 88785b7a5d0SLorenzo Bianconi .rate_idx = status->rate_idx, 88885b7a5d0SLorenzo Bianconi .encoding = status->encoding, 88985b7a5d0SLorenzo Bianconi .band = status->band, 89085b7a5d0SLorenzo Bianconi .nss = status->nss, 89185b7a5d0SLorenzo Bianconi .bw = status->bw, 89285b7a5d0SLorenzo Bianconi }; 8935ce09c1aSFelix Fietkau struct ieee80211_sta *sta; 8945ce09c1aSFelix Fietkau u32 airtime; 895e195dad1SFelix Fietkau u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; 8965ce09c1aSFelix Fietkau 89785b7a5d0SLorenzo Bianconi airtime = ieee80211_calc_rx_airtime(dev->hw, &info, len); 898237312c5SLorenzo Bianconi spin_lock(&dev->cc_lock); 8995ce09c1aSFelix Fietkau dev->cur_cc_bss_rx += airtime; 900237312c5SLorenzo Bianconi spin_unlock(&dev->cc_lock); 9015ce09c1aSFelix Fietkau 9025ce09c1aSFelix Fietkau if (!wcid || !wcid->sta) 9035ce09c1aSFelix Fietkau return; 9045ce09c1aSFelix Fietkau 9055ce09c1aSFelix Fietkau sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); 906e195dad1SFelix Fietkau ieee80211_sta_register_airtime(sta, tidno, 0, airtime); 9075ce09c1aSFelix Fietkau } 9085ce09c1aSFelix Fietkau 9095ce09c1aSFelix Fietkau static void 9105ce09c1aSFelix Fietkau mt76_airtime_flush_ampdu(struct mt76_dev *dev) 9115ce09c1aSFelix Fietkau { 9125ce09c1aSFelix Fietkau struct mt76_wcid *wcid; 9135ce09c1aSFelix Fietkau int wcid_idx; 9145ce09c1aSFelix Fietkau 9155ce09c1aSFelix Fietkau if (!dev->rx_ampdu_len) 9165ce09c1aSFelix Fietkau return; 9175ce09c1aSFelix Fietkau 9185ce09c1aSFelix Fietkau wcid_idx = dev->rx_ampdu_status.wcid_idx; 919bf5238b2SFelix Fietkau if (wcid_idx < ARRAY_SIZE(dev->wcid)) 9205ce09c1aSFelix Fietkau wcid = rcu_dereference(dev->wcid[wcid_idx]); 9215ce09c1aSFelix Fietkau else 9225ce09c1aSFelix Fietkau wcid = NULL; 9235ce09c1aSFelix Fietkau dev->rx_ampdu_status.wcid = wcid; 9245ce09c1aSFelix Fietkau 9255ce09c1aSFelix Fietkau mt76_airtime_report(dev, &dev->rx_ampdu_status, dev->rx_ampdu_len); 9265ce09c1aSFelix Fietkau 9275ce09c1aSFelix Fietkau dev->rx_ampdu_len = 0; 9285ce09c1aSFelix Fietkau dev->rx_ampdu_ref = 0; 9295ce09c1aSFelix Fietkau } 9305ce09c1aSFelix Fietkau 9315ce09c1aSFelix Fietkau static void 9325ce09c1aSFelix Fietkau mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb) 9335ce09c1aSFelix Fietkau { 9345ce09c1aSFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 9355ce09c1aSFelix Fietkau struct mt76_wcid *wcid = status->wcid; 9365ce09c1aSFelix Fietkau 9375ce09c1aSFelix Fietkau if (!(dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME)) 9385ce09c1aSFelix Fietkau return; 9395ce09c1aSFelix Fietkau 9405ce09c1aSFelix Fietkau if (!wcid || !wcid->sta) { 941e195dad1SFelix Fietkau struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); 942e195dad1SFelix Fietkau 943e195dad1SFelix Fietkau if (status->flag & RX_FLAG_8023) 944e195dad1SFelix Fietkau return; 945e195dad1SFelix Fietkau 94698df2baeSLorenzo Bianconi if (!ether_addr_equal(hdr->addr1, dev->phy.macaddr)) 9475ce09c1aSFelix Fietkau return; 9485ce09c1aSFelix Fietkau 9495ce09c1aSFelix Fietkau wcid = NULL; 9505ce09c1aSFelix Fietkau } 9515ce09c1aSFelix Fietkau 9525ce09c1aSFelix Fietkau if (!(status->flag & RX_FLAG_AMPDU_DETAILS) || 9535ce09c1aSFelix Fietkau status->ampdu_ref != dev->rx_ampdu_ref) 9545ce09c1aSFelix Fietkau mt76_airtime_flush_ampdu(dev); 9555ce09c1aSFelix Fietkau 9565ce09c1aSFelix Fietkau if (status->flag & RX_FLAG_AMPDU_DETAILS) { 9575ce09c1aSFelix Fietkau if (!dev->rx_ampdu_len || 9585ce09c1aSFelix Fietkau status->ampdu_ref != dev->rx_ampdu_ref) { 9595ce09c1aSFelix Fietkau dev->rx_ampdu_status = *status; 9605ce09c1aSFelix Fietkau dev->rx_ampdu_status.wcid_idx = wcid ? wcid->idx : 0xff; 9615ce09c1aSFelix Fietkau dev->rx_ampdu_ref = status->ampdu_ref; 9625ce09c1aSFelix Fietkau } 9635ce09c1aSFelix Fietkau 9645ce09c1aSFelix Fietkau dev->rx_ampdu_len += skb->len; 9655ce09c1aSFelix Fietkau return; 9665ce09c1aSFelix Fietkau } 9675ce09c1aSFelix Fietkau 9685ce09c1aSFelix Fietkau mt76_airtime_report(dev, status, skb->len); 9695ce09c1aSFelix Fietkau } 9705ce09c1aSFelix Fietkau 9715ce09c1aSFelix Fietkau static void 972ef13edc0SFelix Fietkau mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) 973d71ef286SFelix Fietkau { 974d71ef286SFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 97577ae1d5eSRyder Lee struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); 976d71ef286SFelix Fietkau struct ieee80211_sta *sta; 977bfc394ddSFelix Fietkau struct ieee80211_hw *hw; 978d71ef286SFelix Fietkau struct mt76_wcid *wcid = status->wcid; 979e195dad1SFelix Fietkau u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; 980d71ef286SFelix Fietkau bool ps; 981d71ef286SFelix Fietkau 982bfc394ddSFelix Fietkau hw = mt76_phy_hw(dev, status->ext_phy); 983e195dad1SFelix Fietkau if (ieee80211_is_pspoll(hdr->frame_control) && !wcid && 984e195dad1SFelix Fietkau !(status->flag & RX_FLAG_8023)) { 985bfc394ddSFelix Fietkau sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); 98636d91096SFelix Fietkau if (sta) 98736d91096SFelix Fietkau wcid = status->wcid = (struct mt76_wcid *)sta->drv_priv; 98836d91096SFelix Fietkau } 98936d91096SFelix Fietkau 9905ce09c1aSFelix Fietkau mt76_airtime_check(dev, skb); 9915ce09c1aSFelix Fietkau 992d71ef286SFelix Fietkau if (!wcid || !wcid->sta) 993d71ef286SFelix Fietkau return; 994d71ef286SFelix Fietkau 995d71ef286SFelix Fietkau sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); 996d71ef286SFelix Fietkau 99702e5a769SFelix Fietkau if (status->signal <= 0) 99802e5a769SFelix Fietkau ewma_signal_add(&wcid->rssi, -status->signal); 99902e5a769SFelix Fietkau 1000ef13edc0SFelix Fietkau wcid->inactive_count = 0; 1001ef13edc0SFelix Fietkau 1002e195dad1SFelix Fietkau if (status->flag & RX_FLAG_8023) 1003e195dad1SFelix Fietkau return; 1004e195dad1SFelix Fietkau 1005d71ef286SFelix Fietkau if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags)) 1006d71ef286SFelix Fietkau return; 1007d71ef286SFelix Fietkau 1008d71ef286SFelix Fietkau if (ieee80211_is_pspoll(hdr->frame_control)) { 1009d71ef286SFelix Fietkau ieee80211_sta_pspoll(sta); 1010d71ef286SFelix Fietkau return; 1011d71ef286SFelix Fietkau } 1012d71ef286SFelix Fietkau 1013d71ef286SFelix Fietkau if (ieee80211_has_morefrags(hdr->frame_control) || 1014d71ef286SFelix Fietkau !(ieee80211_is_mgmt(hdr->frame_control) || 1015d71ef286SFelix Fietkau ieee80211_is_data(hdr->frame_control))) 1016d71ef286SFelix Fietkau return; 1017d71ef286SFelix Fietkau 1018d71ef286SFelix Fietkau ps = ieee80211_has_pm(hdr->frame_control); 1019d71ef286SFelix Fietkau 1020d71ef286SFelix Fietkau if (ps && (ieee80211_is_data_qos(hdr->frame_control) || 1021d71ef286SFelix Fietkau ieee80211_is_qos_nullfunc(hdr->frame_control))) 1022e195dad1SFelix Fietkau ieee80211_sta_uapsd_trigger(sta, tidno); 1023d71ef286SFelix Fietkau 1024d71ef286SFelix Fietkau if (!!test_bit(MT_WCID_FLAG_PS, &wcid->flags) == ps) 1025d71ef286SFelix Fietkau return; 1026d71ef286SFelix Fietkau 102711b2a25fSFelix Fietkau if (ps) 1028d71ef286SFelix Fietkau set_bit(MT_WCID_FLAG_PS, &wcid->flags); 102911b2a25fSFelix Fietkau else 1030d71ef286SFelix Fietkau clear_bit(MT_WCID_FLAG_PS, &wcid->flags); 1031d71ef286SFelix Fietkau 1032d71ef286SFelix Fietkau dev->drv->sta_ps(dev, sta, ps); 10339f67c277SFelix Fietkau ieee80211_sta_ps_transition(sta, ps); 1034d71ef286SFelix Fietkau } 1035d71ef286SFelix Fietkau 10369d9d738bSFelix Fietkau void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, 103781e850efSLorenzo Bianconi struct napi_struct *napi) 103817f1de56SFelix Fietkau { 10399c68a57bSFelix Fietkau struct ieee80211_sta *sta; 1040bfc394ddSFelix Fietkau struct ieee80211_hw *hw; 10413298b1f8SFelix Fietkau struct sk_buff *skb, *tmp; 10423298b1f8SFelix Fietkau LIST_HEAD(list); 10439d9d738bSFelix Fietkau 1044c3d7c82aSFelix Fietkau spin_lock(&dev->rx_lock); 10459d9d738bSFelix Fietkau while ((skb = __skb_dequeue(frames)) != NULL) { 1046cc4b3c13SLorenzo Bianconi struct sk_buff *nskb = skb_shinfo(skb)->frag_list; 1047cc4b3c13SLorenzo Bianconi 104830ce7f44SFelix Fietkau if (mt76_check_ccmp_pn(skb)) { 104930ce7f44SFelix Fietkau dev_kfree_skb(skb); 105030ce7f44SFelix Fietkau continue; 105130ce7f44SFelix Fietkau } 105230ce7f44SFelix Fietkau 1053cc4b3c13SLorenzo Bianconi skb_shinfo(skb)->frag_list = NULL; 1054bfc394ddSFelix Fietkau mt76_rx_convert(dev, skb, &hw, &sta); 10553298b1f8SFelix Fietkau ieee80211_rx_list(hw, sta, skb, &list); 1056cc4b3c13SLorenzo Bianconi 1057cc4b3c13SLorenzo Bianconi /* subsequent amsdu frames */ 1058cc4b3c13SLorenzo Bianconi while (nskb) { 1059cc4b3c13SLorenzo Bianconi skb = nskb; 1060cc4b3c13SLorenzo Bianconi nskb = nskb->next; 1061cc4b3c13SLorenzo Bianconi skb->next = NULL; 1062cc4b3c13SLorenzo Bianconi 1063cc4b3c13SLorenzo Bianconi mt76_rx_convert(dev, skb, &hw, &sta); 1064cc4b3c13SLorenzo Bianconi ieee80211_rx_list(hw, sta, skb, &list); 1065cc4b3c13SLorenzo Bianconi } 10669d9d738bSFelix Fietkau } 1067c3d7c82aSFelix Fietkau spin_unlock(&dev->rx_lock); 10683298b1f8SFelix Fietkau 10693298b1f8SFelix Fietkau if (!napi) { 10703298b1f8SFelix Fietkau netif_receive_skb_list(&list); 10713298b1f8SFelix Fietkau return; 10723298b1f8SFelix Fietkau } 10733298b1f8SFelix Fietkau 10743298b1f8SFelix Fietkau list_for_each_entry_safe(skb, tmp, &list, list) { 10753298b1f8SFelix Fietkau skb_list_del_init(skb); 10763298b1f8SFelix Fietkau napi_gro_receive(napi, skb); 10773298b1f8SFelix Fietkau } 10789d9d738bSFelix Fietkau } 10799d9d738bSFelix Fietkau 108081e850efSLorenzo Bianconi void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q, 108181e850efSLorenzo Bianconi struct napi_struct *napi) 10829d9d738bSFelix Fietkau { 1083aee5b8cfSFelix Fietkau struct sk_buff_head frames; 108417f1de56SFelix Fietkau struct sk_buff *skb; 108517f1de56SFelix Fietkau 1086aee5b8cfSFelix Fietkau __skb_queue_head_init(&frames); 1087aee5b8cfSFelix Fietkau 1088d71ef286SFelix Fietkau while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) { 1089ef13edc0SFelix Fietkau mt76_check_sta(dev, skb); 1090aee5b8cfSFelix Fietkau mt76_rx_aggr_reorder(skb, &frames); 1091d71ef286SFelix Fietkau } 1092aee5b8cfSFelix Fietkau 109381e850efSLorenzo Bianconi mt76_rx_complete(dev, &frames, napi); 10944e34249eSFelix Fietkau } 109581e850efSLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_rx_poll_complete); 1096723b90dcSFelix Fietkau 1097e28487eaSFelix Fietkau static int 1098e28487eaSFelix Fietkau mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, 1099426e8e41SFelix Fietkau struct ieee80211_sta *sta, bool ext_phy) 1100e28487eaSFelix Fietkau { 1101e28487eaSFelix Fietkau struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; 1102e28487eaSFelix Fietkau int ret; 1103e28487eaSFelix Fietkau int i; 1104e28487eaSFelix Fietkau 1105e28487eaSFelix Fietkau mutex_lock(&dev->mutex); 1106e28487eaSFelix Fietkau 1107e28487eaSFelix Fietkau ret = dev->drv->sta_add(dev, vif, sta); 1108e28487eaSFelix Fietkau if (ret) 1109e28487eaSFelix Fietkau goto out; 1110e28487eaSFelix Fietkau 1111e28487eaSFelix Fietkau for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { 1112e28487eaSFelix Fietkau struct mt76_txq *mtxq; 1113e28487eaSFelix Fietkau 1114e28487eaSFelix Fietkau if (!sta->txq[i]) 1115e28487eaSFelix Fietkau continue; 1116e28487eaSFelix Fietkau 1117e28487eaSFelix Fietkau mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; 1118e28487eaSFelix Fietkau mtxq->wcid = wcid; 1119e28487eaSFelix Fietkau } 1120e28487eaSFelix Fietkau 1121ef13edc0SFelix Fietkau ewma_signal_init(&wcid->rssi); 1122426e8e41SFelix Fietkau if (ext_phy) 1123426e8e41SFelix Fietkau mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx); 1124c7d2d631SFelix Fietkau wcid->ext_phy = ext_phy; 1125e28487eaSFelix Fietkau rcu_assign_pointer(dev->wcid[wcid->idx], wcid); 1126e28487eaSFelix Fietkau 1127e28487eaSFelix Fietkau out: 1128e28487eaSFelix Fietkau mutex_unlock(&dev->mutex); 1129e28487eaSFelix Fietkau 1130e28487eaSFelix Fietkau return ret; 1131e28487eaSFelix Fietkau } 1132e28487eaSFelix Fietkau 113313f61dfcSLorenzo Bianconi void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, 1134723b90dcSFelix Fietkau struct ieee80211_sta *sta) 1135723b90dcSFelix Fietkau { 1136723b90dcSFelix Fietkau struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; 113713f61dfcSLorenzo Bianconi int i, idx = wcid->idx; 1138723b90dcSFelix Fietkau 113958bab0d4SFelix Fietkau for (i = 0; i < ARRAY_SIZE(wcid->aggr); i++) 114058bab0d4SFelix Fietkau mt76_rx_aggr_stop(dev, wcid, i); 114158bab0d4SFelix Fietkau 1142e28487eaSFelix Fietkau if (dev->drv->sta_remove) 1143e28487eaSFelix Fietkau dev->drv->sta_remove(dev, vif, sta); 1144e28487eaSFelix Fietkau 1145723b90dcSFelix Fietkau mt76_tx_status_check(dev, wcid, true); 1146426e8e41SFelix Fietkau mt76_wcid_mask_clear(dev->wcid_mask, idx); 1147426e8e41SFelix Fietkau mt76_wcid_mask_clear(dev->wcid_phy_mask, idx); 114813f61dfcSLorenzo Bianconi } 114913f61dfcSLorenzo Bianconi EXPORT_SYMBOL_GPL(__mt76_sta_remove); 1150e28487eaSFelix Fietkau 115113f61dfcSLorenzo Bianconi static void 115213f61dfcSLorenzo Bianconi mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, 115313f61dfcSLorenzo Bianconi struct ieee80211_sta *sta) 115413f61dfcSLorenzo Bianconi { 115513f61dfcSLorenzo Bianconi mutex_lock(&dev->mutex); 115613f61dfcSLorenzo Bianconi __mt76_sta_remove(dev, vif, sta); 1157723b90dcSFelix Fietkau mutex_unlock(&dev->mutex); 1158723b90dcSFelix Fietkau } 1159e28487eaSFelix Fietkau 1160e28487eaSFelix Fietkau int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1161e28487eaSFelix Fietkau struct ieee80211_sta *sta, 1162e28487eaSFelix Fietkau enum ieee80211_sta_state old_state, 1163e28487eaSFelix Fietkau enum ieee80211_sta_state new_state) 1164e28487eaSFelix Fietkau { 1165426e8e41SFelix Fietkau struct mt76_phy *phy = hw->priv; 1166426e8e41SFelix Fietkau struct mt76_dev *dev = phy->dev; 1167426e8e41SFelix Fietkau bool ext_phy = phy != &dev->phy; 1168e28487eaSFelix Fietkau 1169e28487eaSFelix Fietkau if (old_state == IEEE80211_STA_NOTEXIST && 1170e28487eaSFelix Fietkau new_state == IEEE80211_STA_NONE) 1171426e8e41SFelix Fietkau return mt76_sta_add(dev, vif, sta, ext_phy); 1172e28487eaSFelix Fietkau 11739c193de5SFelix Fietkau if (old_state == IEEE80211_STA_AUTH && 11749c193de5SFelix Fietkau new_state == IEEE80211_STA_ASSOC && 11759c193de5SFelix Fietkau dev->drv->sta_assoc) 11769c193de5SFelix Fietkau dev->drv->sta_assoc(dev, vif, sta); 11779c193de5SFelix Fietkau 1178e28487eaSFelix Fietkau if (old_state == IEEE80211_STA_NONE && 1179e28487eaSFelix Fietkau new_state == IEEE80211_STA_NOTEXIST) 1180e28487eaSFelix Fietkau mt76_sta_remove(dev, vif, sta); 1181e28487eaSFelix Fietkau 1182e28487eaSFelix Fietkau return 0; 1183e28487eaSFelix Fietkau } 1184e28487eaSFelix Fietkau EXPORT_SYMBOL_GPL(mt76_sta_state); 11859313faacSFelix Fietkau 118643ba1922SFelix Fietkau void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 118743ba1922SFelix Fietkau struct ieee80211_sta *sta) 118843ba1922SFelix Fietkau { 118943ba1922SFelix Fietkau struct mt76_phy *phy = hw->priv; 119043ba1922SFelix Fietkau struct mt76_dev *dev = phy->dev; 119143ba1922SFelix Fietkau struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; 119243ba1922SFelix Fietkau 119343ba1922SFelix Fietkau mutex_lock(&dev->mutex); 119443ba1922SFelix Fietkau rcu_assign_pointer(dev->wcid[wcid->idx], NULL); 119543ba1922SFelix Fietkau mutex_unlock(&dev->mutex); 119643ba1922SFelix Fietkau } 119743ba1922SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove); 119843ba1922SFelix Fietkau 11999313faacSFelix Fietkau int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 12009313faacSFelix Fietkau int *dbm) 12019313faacSFelix Fietkau { 1202beaaeb6bSFelix Fietkau struct mt76_phy *phy = hw->priv; 1203beaaeb6bSFelix Fietkau int n_chains = hweight8(phy->antenna_mask); 120407cda406SFelix Fietkau int delta = mt76_tx_power_nss_delta(n_chains); 12059313faacSFelix Fietkau 120607cda406SFelix Fietkau *dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2); 12079313faacSFelix Fietkau 12089313faacSFelix Fietkau return 0; 12099313faacSFelix Fietkau } 12109313faacSFelix Fietkau EXPORT_SYMBOL_GPL(mt76_get_txpower); 1211e7173858SFelix Fietkau 1212e7173858SFelix Fietkau static void 1213e7173858SFelix Fietkau __mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) 1214e7173858SFelix Fietkau { 12158552a434SJohn Crispin if (vif->csa_active && ieee80211_beacon_cntdwn_is_complete(vif)) 1216e7173858SFelix Fietkau ieee80211_csa_finish(vif); 1217e7173858SFelix Fietkau } 1218e7173858SFelix Fietkau 1219e7173858SFelix Fietkau void mt76_csa_finish(struct mt76_dev *dev) 1220e7173858SFelix Fietkau { 1221e7173858SFelix Fietkau if (!dev->csa_complete) 1222e7173858SFelix Fietkau return; 1223e7173858SFelix Fietkau 1224e7173858SFelix Fietkau ieee80211_iterate_active_interfaces_atomic(dev->hw, 1225e7173858SFelix Fietkau IEEE80211_IFACE_ITER_RESUME_ALL, 1226e7173858SFelix Fietkau __mt76_csa_finish, dev); 1227e7173858SFelix Fietkau 1228e7173858SFelix Fietkau dev->csa_complete = 0; 1229e7173858SFelix Fietkau } 1230e7173858SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_csa_finish); 1231e7173858SFelix Fietkau 1232e7173858SFelix Fietkau static void 1233e7173858SFelix Fietkau __mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif) 1234e7173858SFelix Fietkau { 1235e7173858SFelix Fietkau struct mt76_dev *dev = priv; 1236e7173858SFelix Fietkau 1237e7173858SFelix Fietkau if (!vif->csa_active) 1238e7173858SFelix Fietkau return; 1239e7173858SFelix Fietkau 12408552a434SJohn Crispin dev->csa_complete |= ieee80211_beacon_cntdwn_is_complete(vif); 1241e7173858SFelix Fietkau } 1242e7173858SFelix Fietkau 1243e7173858SFelix Fietkau void mt76_csa_check(struct mt76_dev *dev) 1244e7173858SFelix Fietkau { 1245e7173858SFelix Fietkau ieee80211_iterate_active_interfaces_atomic(dev->hw, 1246e7173858SFelix Fietkau IEEE80211_IFACE_ITER_RESUME_ALL, 1247e7173858SFelix Fietkau __mt76_csa_check, dev); 1248e7173858SFelix Fietkau } 1249e7173858SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_csa_check); 125087d53103SStanislaw Gruszka 125187d53103SStanislaw Gruszka int 125287d53103SStanislaw Gruszka mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) 125387d53103SStanislaw Gruszka { 125487d53103SStanislaw Gruszka return 0; 125587d53103SStanislaw Gruszka } 125687d53103SStanislaw Gruszka EXPORT_SYMBOL_GPL(mt76_set_tim); 1257eadfd98fSLorenzo Bianconi 1258eadfd98fSLorenzo Bianconi void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) 1259eadfd98fSLorenzo Bianconi { 1260eadfd98fSLorenzo Bianconi struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 1261eadfd98fSLorenzo Bianconi int hdr_len = ieee80211_get_hdrlen_from_skb(skb); 1262eadfd98fSLorenzo Bianconi u8 *hdr, *pn = status->iv; 1263eadfd98fSLorenzo Bianconi 1264eadfd98fSLorenzo Bianconi __skb_push(skb, 8); 1265eadfd98fSLorenzo Bianconi memmove(skb->data, skb->data + 8, hdr_len); 1266eadfd98fSLorenzo Bianconi hdr = skb->data + hdr_len; 1267eadfd98fSLorenzo Bianconi 1268eadfd98fSLorenzo Bianconi hdr[0] = pn[5]; 1269eadfd98fSLorenzo Bianconi hdr[1] = pn[4]; 1270eadfd98fSLorenzo Bianconi hdr[2] = 0; 1271eadfd98fSLorenzo Bianconi hdr[3] = 0x20 | (key_id << 6); 1272eadfd98fSLorenzo Bianconi hdr[4] = pn[3]; 1273eadfd98fSLorenzo Bianconi hdr[5] = pn[2]; 1274eadfd98fSLorenzo Bianconi hdr[6] = pn[1]; 1275eadfd98fSLorenzo Bianconi hdr[7] = pn[0]; 1276eadfd98fSLorenzo Bianconi 1277eadfd98fSLorenzo Bianconi status->flag &= ~RX_FLAG_IV_STRIPPED; 1278eadfd98fSLorenzo Bianconi } 1279eadfd98fSLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_insert_ccmp_hdr); 1280d2679d65SLorenzo Bianconi 1281d2679d65SLorenzo Bianconi int mt76_get_rate(struct mt76_dev *dev, 1282d2679d65SLorenzo Bianconi struct ieee80211_supported_band *sband, 1283d2679d65SLorenzo Bianconi int idx, bool cck) 1284d2679d65SLorenzo Bianconi { 1285d2679d65SLorenzo Bianconi int i, offset = 0, len = sband->n_bitrates; 1286d2679d65SLorenzo Bianconi 1287d2679d65SLorenzo Bianconi if (cck) { 128896747a51SFelix Fietkau if (sband == &dev->phy.sband_5g.sband) 1289d2679d65SLorenzo Bianconi return 0; 1290d2679d65SLorenzo Bianconi 1291d2679d65SLorenzo Bianconi idx &= ~BIT(2); /* short preamble */ 129296747a51SFelix Fietkau } else if (sband == &dev->phy.sband_2g.sband) { 1293d2679d65SLorenzo Bianconi offset = 4; 1294d2679d65SLorenzo Bianconi } 1295d2679d65SLorenzo Bianconi 1296d2679d65SLorenzo Bianconi for (i = offset; i < len; i++) { 1297d2679d65SLorenzo Bianconi if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) 1298d2679d65SLorenzo Bianconi return i; 1299d2679d65SLorenzo Bianconi } 1300d2679d65SLorenzo Bianconi 1301d2679d65SLorenzo Bianconi return 0; 1302d2679d65SLorenzo Bianconi } 1303d2679d65SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_get_rate); 13048b8ab5c2SLorenzo Bianconi 13058b8ab5c2SLorenzo Bianconi void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 13068b8ab5c2SLorenzo Bianconi const u8 *mac) 13078b8ab5c2SLorenzo Bianconi { 1308011849e0SFelix Fietkau struct mt76_phy *phy = hw->priv; 13098b8ab5c2SLorenzo Bianconi 1310011849e0SFelix Fietkau set_bit(MT76_SCANNING, &phy->state); 13118b8ab5c2SLorenzo Bianconi } 13128b8ab5c2SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_sw_scan); 13138b8ab5c2SLorenzo Bianconi 13148b8ab5c2SLorenzo Bianconi void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 13158b8ab5c2SLorenzo Bianconi { 1316011849e0SFelix Fietkau struct mt76_phy *phy = hw->priv; 13178b8ab5c2SLorenzo Bianconi 1318011849e0SFelix Fietkau clear_bit(MT76_SCANNING, &phy->state); 13198b8ab5c2SLorenzo Bianconi } 13208b8ab5c2SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_sw_scan_complete); 1321e49c76d4SLorenzo Bianconi 1322e49c76d4SLorenzo Bianconi int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) 1323e49c76d4SLorenzo Bianconi { 1324beaaeb6bSFelix Fietkau struct mt76_phy *phy = hw->priv; 1325beaaeb6bSFelix Fietkau struct mt76_dev *dev = phy->dev; 1326e49c76d4SLorenzo Bianconi 1327e49c76d4SLorenzo Bianconi mutex_lock(&dev->mutex); 1328beaaeb6bSFelix Fietkau *tx_ant = phy->antenna_mask; 1329beaaeb6bSFelix Fietkau *rx_ant = phy->antenna_mask; 1330e49c76d4SLorenzo Bianconi mutex_unlock(&dev->mutex); 1331e49c76d4SLorenzo Bianconi 1332e49c76d4SLorenzo Bianconi return 0; 1333e49c76d4SLorenzo Bianconi } 1334e49c76d4SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_get_antenna); 1335b671da33SLorenzo Bianconi 1336b1cb42adSLorenzo Bianconi struct mt76_queue * 1337b1cb42adSLorenzo Bianconi mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, 1338b1cb42adSLorenzo Bianconi int ring_base) 1339b671da33SLorenzo Bianconi { 1340b671da33SLorenzo Bianconi struct mt76_queue *hwq; 1341b671da33SLorenzo Bianconi int err; 1342b671da33SLorenzo Bianconi 1343b671da33SLorenzo Bianconi hwq = devm_kzalloc(dev->dev, sizeof(*hwq), GFP_KERNEL); 1344b671da33SLorenzo Bianconi if (!hwq) 1345b1cb42adSLorenzo Bianconi return ERR_PTR(-ENOMEM); 1346b671da33SLorenzo Bianconi 1347b671da33SLorenzo Bianconi err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base); 1348b671da33SLorenzo Bianconi if (err < 0) 1349b1cb42adSLorenzo Bianconi return ERR_PTR(err); 1350b671da33SLorenzo Bianconi 1351b1cb42adSLorenzo Bianconi return hwq; 1352b671da33SLorenzo Bianconi } 1353b1cb42adSLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_init_queue); 1354