10e3d6777SRyder Lee // SPDX-License-Identifier: ISC 217f1de56SFelix Fietkau /* 317f1de56SFelix Fietkau * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 417f1de56SFelix Fietkau */ 517f1de56SFelix Fietkau #include <linux/of.h> 617f1de56SFelix Fietkau #include "mt76.h" 717f1de56SFelix Fietkau 817f1de56SFelix Fietkau #define CHAN2G(_idx, _freq) { \ 917f1de56SFelix Fietkau .band = NL80211_BAND_2GHZ, \ 1017f1de56SFelix Fietkau .center_freq = (_freq), \ 1117f1de56SFelix Fietkau .hw_value = (_idx), \ 1217f1de56SFelix Fietkau .max_power = 30, \ 1317f1de56SFelix Fietkau } 1417f1de56SFelix Fietkau 1517f1de56SFelix Fietkau #define CHAN5G(_idx, _freq) { \ 1617f1de56SFelix Fietkau .band = NL80211_BAND_5GHZ, \ 1717f1de56SFelix Fietkau .center_freq = (_freq), \ 1817f1de56SFelix Fietkau .hw_value = (_idx), \ 1917f1de56SFelix Fietkau .max_power = 30, \ 2017f1de56SFelix Fietkau } 2117f1de56SFelix Fietkau 2217f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_2ghz[] = { 2317f1de56SFelix Fietkau CHAN2G(1, 2412), 2417f1de56SFelix Fietkau CHAN2G(2, 2417), 2517f1de56SFelix Fietkau CHAN2G(3, 2422), 2617f1de56SFelix Fietkau CHAN2G(4, 2427), 2717f1de56SFelix Fietkau CHAN2G(5, 2432), 2817f1de56SFelix Fietkau CHAN2G(6, 2437), 2917f1de56SFelix Fietkau CHAN2G(7, 2442), 3017f1de56SFelix Fietkau CHAN2G(8, 2447), 3117f1de56SFelix Fietkau CHAN2G(9, 2452), 3217f1de56SFelix Fietkau CHAN2G(10, 2457), 3317f1de56SFelix Fietkau CHAN2G(11, 2462), 3417f1de56SFelix Fietkau CHAN2G(12, 2467), 3517f1de56SFelix Fietkau CHAN2G(13, 2472), 3617f1de56SFelix Fietkau CHAN2G(14, 2484), 3717f1de56SFelix Fietkau }; 3817f1de56SFelix Fietkau 3917f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_5ghz[] = { 4017f1de56SFelix Fietkau CHAN5G(36, 5180), 4117f1de56SFelix Fietkau CHAN5G(40, 5200), 4217f1de56SFelix Fietkau CHAN5G(44, 5220), 4317f1de56SFelix Fietkau CHAN5G(48, 5240), 4417f1de56SFelix Fietkau 4517f1de56SFelix Fietkau CHAN5G(52, 5260), 4617f1de56SFelix Fietkau CHAN5G(56, 5280), 4717f1de56SFelix Fietkau CHAN5G(60, 5300), 4817f1de56SFelix Fietkau CHAN5G(64, 5320), 4917f1de56SFelix Fietkau 5017f1de56SFelix Fietkau CHAN5G(100, 5500), 5117f1de56SFelix Fietkau CHAN5G(104, 5520), 5217f1de56SFelix Fietkau CHAN5G(108, 5540), 5317f1de56SFelix Fietkau CHAN5G(112, 5560), 5417f1de56SFelix Fietkau CHAN5G(116, 5580), 5517f1de56SFelix Fietkau CHAN5G(120, 5600), 5617f1de56SFelix Fietkau CHAN5G(124, 5620), 5717f1de56SFelix Fietkau CHAN5G(128, 5640), 5817f1de56SFelix Fietkau CHAN5G(132, 5660), 5917f1de56SFelix Fietkau CHAN5G(136, 5680), 6017f1de56SFelix Fietkau CHAN5G(140, 5700), 619da82fb7SMarkus Theil CHAN5G(144, 5720), 6217f1de56SFelix Fietkau 6317f1de56SFelix Fietkau CHAN5G(149, 5745), 6417f1de56SFelix Fietkau CHAN5G(153, 5765), 6517f1de56SFelix Fietkau CHAN5G(157, 5785), 6617f1de56SFelix Fietkau CHAN5G(161, 5805), 6717f1de56SFelix Fietkau CHAN5G(165, 5825), 689da82fb7SMarkus Theil CHAN5G(169, 5845), 699da82fb7SMarkus Theil CHAN5G(173, 5865), 7017f1de56SFelix Fietkau }; 7117f1de56SFelix Fietkau 7217f1de56SFelix Fietkau static const struct ieee80211_tpt_blink mt76_tpt_blink[] = { 7317f1de56SFelix Fietkau { .throughput = 0 * 1024, .blink_time = 334 }, 7417f1de56SFelix Fietkau { .throughput = 1 * 1024, .blink_time = 260 }, 7517f1de56SFelix Fietkau { .throughput = 5 * 1024, .blink_time = 220 }, 7617f1de56SFelix Fietkau { .throughput = 10 * 1024, .blink_time = 190 }, 7717f1de56SFelix Fietkau { .throughput = 20 * 1024, .blink_time = 170 }, 7817f1de56SFelix Fietkau { .throughput = 50 * 1024, .blink_time = 150 }, 7917f1de56SFelix Fietkau { .throughput = 70 * 1024, .blink_time = 130 }, 8017f1de56SFelix Fietkau { .throughput = 100 * 1024, .blink_time = 110 }, 8117f1de56SFelix Fietkau { .throughput = 200 * 1024, .blink_time = 80 }, 8217f1de56SFelix Fietkau { .throughput = 300 * 1024, .blink_time = 50 }, 8317f1de56SFelix Fietkau }; 8417f1de56SFelix Fietkau 8517f1de56SFelix Fietkau static int mt76_led_init(struct mt76_dev *dev) 8617f1de56SFelix Fietkau { 8717f1de56SFelix Fietkau struct device_node *np = dev->dev->of_node; 8817f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 8917f1de56SFelix Fietkau int led_pin; 9017f1de56SFelix Fietkau 9117f1de56SFelix Fietkau if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set) 9217f1de56SFelix Fietkau return 0; 9317f1de56SFelix Fietkau 9417f1de56SFelix Fietkau snprintf(dev->led_name, sizeof(dev->led_name), 9517f1de56SFelix Fietkau "mt76-%s", wiphy_name(hw->wiphy)); 9617f1de56SFelix Fietkau 9717f1de56SFelix Fietkau dev->led_cdev.name = dev->led_name; 9817f1de56SFelix Fietkau dev->led_cdev.default_trigger = 9917f1de56SFelix Fietkau ieee80211_create_tpt_led_trigger(hw, 10017f1de56SFelix Fietkau IEEE80211_TPT_LEDTRIG_FL_RADIO, 10117f1de56SFelix Fietkau mt76_tpt_blink, 10217f1de56SFelix Fietkau ARRAY_SIZE(mt76_tpt_blink)); 10317f1de56SFelix Fietkau 10417f1de56SFelix Fietkau np = of_get_child_by_name(np, "led"); 10517f1de56SFelix Fietkau if (np) { 10617f1de56SFelix Fietkau if (!of_property_read_u32(np, "led-sources", &led_pin)) 10717f1de56SFelix Fietkau dev->led_pin = led_pin; 10817f1de56SFelix Fietkau dev->led_al = of_property_read_bool(np, "led-active-low"); 10917f1de56SFelix Fietkau } 11017f1de56SFelix Fietkau 11136f7e2b2SFelix Fietkau return led_classdev_register(dev->dev, &dev->led_cdev); 11236f7e2b2SFelix Fietkau } 11336f7e2b2SFelix Fietkau 11436f7e2b2SFelix Fietkau static void mt76_led_cleanup(struct mt76_dev *dev) 11536f7e2b2SFelix Fietkau { 11636f7e2b2SFelix Fietkau if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set) 11736f7e2b2SFelix Fietkau return; 11836f7e2b2SFelix Fietkau 11936f7e2b2SFelix Fietkau led_classdev_unregister(&dev->led_cdev); 12017f1de56SFelix Fietkau } 12117f1de56SFelix Fietkau 122bb3e3fecSRyder Lee static void mt76_init_stream_cap(struct mt76_phy *phy, 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; 127bb3e3fecSRyder Lee int i, nstream = hweight8(phy->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 159bb3e3fecSRyder Lee void mt76_set_stream_caps(struct mt76_phy *phy, bool vht) 1605ebdc3e0SLorenzo Bianconi { 161bb3e3fecSRyder Lee if (phy->dev->cap.has_2ghz) 162bb3e3fecSRyder Lee mt76_init_stream_cap(phy, &phy->sband_2g.sband, false); 163bb3e3fecSRyder Lee if (phy->dev->cap.has_5ghz) 164bb3e3fecSRyder Lee mt76_init_stream_cap(phy, &phy->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 184a86854d0SKees Cook msband->chan = devm_kcalloc(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 19417f1de56SFelix Fietkau ht_cap = &sband->ht_cap; 19517f1de56SFelix Fietkau ht_cap->ht_supported = true; 19617f1de56SFelix Fietkau ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 19717f1de56SFelix Fietkau IEEE80211_HT_CAP_GRN_FLD | 19817f1de56SFelix Fietkau IEEE80211_HT_CAP_SGI_20 | 19917f1de56SFelix Fietkau IEEE80211_HT_CAP_SGI_40 | 20017f1de56SFelix Fietkau (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 20117f1de56SFelix Fietkau 20217f1de56SFelix Fietkau ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 20317f1de56SFelix Fietkau ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 20417f1de56SFelix Fietkau 205bb3e3fecSRyder Lee mt76_init_stream_cap(&dev->phy, sband, vht); 206551e1ef4SLorenzo Bianconi 20717f1de56SFelix Fietkau if (!vht) 20817f1de56SFelix Fietkau return 0; 20917f1de56SFelix Fietkau 21017f1de56SFelix Fietkau vht_cap = &sband->vht_cap; 21117f1de56SFelix Fietkau vht_cap->vht_supported = true; 21217f1de56SFelix Fietkau vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC | 21317f1de56SFelix Fietkau IEEE80211_VHT_CAP_RXSTBC_1 | 21449149d3fSFelix Fietkau IEEE80211_VHT_CAP_SHORT_GI_80 | 215f1103fa6SRyder Lee IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | 216f1103fa6SRyder Lee IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | 21749149d3fSFelix 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 { 22696747a51SFelix Fietkau dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->phy.sband_2g.sband; 22717f1de56SFelix Fietkau 22896747a51SFelix Fietkau return mt76_init_sband(dev, &dev->phy.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 { 23896747a51SFelix Fietkau dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->phy.sband_5g.sband; 23917f1de56SFelix Fietkau 24096747a51SFelix Fietkau return mt76_init_sband(dev, &dev->phy.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 247c89d3625SFelix Fietkau mt76_check_sband(struct mt76_phy *phy, struct mt76_sband *msband, 248c89d3625SFelix Fietkau enum nl80211_band band) 24917f1de56SFelix Fietkau { 250c89d3625SFelix Fietkau struct ieee80211_supported_band *sband = &msband->sband; 25117f1de56SFelix Fietkau bool found = false; 25217f1de56SFelix Fietkau int i; 25317f1de56SFelix Fietkau 25417f1de56SFelix Fietkau if (!sband) 25517f1de56SFelix Fietkau return; 25617f1de56SFelix Fietkau 25717f1de56SFelix Fietkau for (i = 0; i < sband->n_channels; i++) { 25817f1de56SFelix Fietkau if (sband->channels[i].flags & IEEE80211_CHAN_DISABLED) 25917f1de56SFelix Fietkau continue; 26017f1de56SFelix Fietkau 26117f1de56SFelix Fietkau found = true; 26217f1de56SFelix Fietkau break; 26317f1de56SFelix Fietkau } 26417f1de56SFelix Fietkau 265c89d3625SFelix Fietkau if (found) { 266c89d3625SFelix Fietkau phy->chandef.chan = &sband->channels[0]; 267c89d3625SFelix Fietkau phy->chan_state = &msband->chan[0]; 26817f1de56SFelix Fietkau return; 269c89d3625SFelix Fietkau } 27017f1de56SFelix Fietkau 27117f1de56SFelix Fietkau sband->n_channels = 0; 272c89d3625SFelix Fietkau phy->hw->wiphy->bands[band] = NULL; 27317f1de56SFelix Fietkau } 27417f1de56SFelix Fietkau 275c89d3625SFelix Fietkau static void 276c89d3625SFelix Fietkau mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) 277c89d3625SFelix Fietkau { 278c89d3625SFelix Fietkau struct wiphy *wiphy = hw->wiphy; 279c89d3625SFelix Fietkau 280c89d3625SFelix Fietkau SET_IEEE80211_DEV(hw, dev->dev); 281c89d3625SFelix Fietkau SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); 282c89d3625SFelix Fietkau 283c89d3625SFelix Fietkau wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; 284dd89a013SLorenzo Bianconi wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH | 285b807b368SLorenzo Bianconi WIPHY_FLAG_SUPPORTS_TDLS | 286b807b368SLorenzo Bianconi WIPHY_FLAG_AP_UAPSD; 287c89d3625SFelix Fietkau 288c89d3625SFelix Fietkau wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); 289c89d3625SFelix Fietkau wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); 290d9c54264SFelix Fietkau wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL); 291c89d3625SFelix Fietkau 292c89d3625SFelix Fietkau wiphy->available_antennas_tx = dev->phy.antenna_mask; 293c89d3625SFelix Fietkau wiphy->available_antennas_rx = dev->phy.antenna_mask; 294c89d3625SFelix Fietkau 295c89d3625SFelix Fietkau hw->txq_data_size = sizeof(struct mt76_txq); 296b807b368SLorenzo Bianconi hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL; 297c9619dfaSShayne Chen 298c9619dfaSShayne Chen if (!hw->max_tx_fragments) 299c89d3625SFelix Fietkau hw->max_tx_fragments = 16; 300c89d3625SFelix Fietkau 301c89d3625SFelix Fietkau ieee80211_hw_set(hw, SIGNAL_DBM); 302c89d3625SFelix Fietkau ieee80211_hw_set(hw, AMPDU_AGGREGATION); 303c89d3625SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); 304c89d3625SFelix Fietkau ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); 305c89d3625SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); 306c89d3625SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); 307c89d3625SFelix Fietkau ieee80211_hw_set(hw, TX_AMSDU); 308c89d3625SFelix Fietkau ieee80211_hw_set(hw, TX_FRAG_LIST); 309c89d3625SFelix Fietkau ieee80211_hw_set(hw, MFP_CAPABLE); 310c89d3625SFelix Fietkau ieee80211_hw_set(hw, AP_LINK_PS); 311c89d3625SFelix Fietkau ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); 312c89d3625SFelix Fietkau ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); 313c89d3625SFelix Fietkau 314c89d3625SFelix Fietkau wiphy->flags |= WIPHY_FLAG_IBSS_RSN; 315c89d3625SFelix Fietkau wiphy->interface_modes = 316c89d3625SFelix Fietkau BIT(NL80211_IFTYPE_STATION) | 317c89d3625SFelix Fietkau BIT(NL80211_IFTYPE_AP) | 318c89d3625SFelix Fietkau #ifdef CONFIG_MAC80211_MESH 319c89d3625SFelix Fietkau BIT(NL80211_IFTYPE_MESH_POINT) | 320c89d3625SFelix Fietkau #endif 32150eb0a88SLorenzo Bianconi BIT(NL80211_IFTYPE_P2P_CLIENT) | 32250eb0a88SLorenzo Bianconi BIT(NL80211_IFTYPE_P2P_GO) | 323c89d3625SFelix Fietkau BIT(NL80211_IFTYPE_ADHOC); 324c89d3625SFelix Fietkau } 325c89d3625SFelix Fietkau 326c89d3625SFelix Fietkau struct mt76_phy * 327c89d3625SFelix Fietkau mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, 328c89d3625SFelix Fietkau const struct ieee80211_ops *ops) 329c89d3625SFelix Fietkau { 330c89d3625SFelix Fietkau struct ieee80211_hw *hw; 331c89d3625SFelix Fietkau struct mt76_phy *phy; 332c89d3625SFelix Fietkau unsigned int phy_size, chan_size; 333c89d3625SFelix Fietkau unsigned int size_2g, size_5g; 334c89d3625SFelix Fietkau void *priv; 335c89d3625SFelix Fietkau 336c89d3625SFelix Fietkau phy_size = ALIGN(sizeof(*phy), 8); 337c89d3625SFelix Fietkau chan_size = sizeof(dev->phy.sband_2g.chan[0]); 338c89d3625SFelix Fietkau size_2g = ALIGN(ARRAY_SIZE(mt76_channels_2ghz) * chan_size, 8); 339c89d3625SFelix Fietkau size_5g = ALIGN(ARRAY_SIZE(mt76_channels_5ghz) * chan_size, 8); 340c89d3625SFelix Fietkau 341c89d3625SFelix Fietkau size += phy_size + size_2g + size_5g; 342c89d3625SFelix Fietkau hw = ieee80211_alloc_hw(size, ops); 343c89d3625SFelix Fietkau if (!hw) 344c89d3625SFelix Fietkau return NULL; 345c89d3625SFelix Fietkau 346c89d3625SFelix Fietkau phy = hw->priv; 347c89d3625SFelix Fietkau phy->dev = dev; 348c89d3625SFelix Fietkau phy->hw = hw; 349c89d3625SFelix Fietkau 350c89d3625SFelix Fietkau mt76_phy_init(dev, hw); 351c89d3625SFelix Fietkau 352c89d3625SFelix Fietkau priv = hw->priv + phy_size; 353c89d3625SFelix Fietkau 354c89d3625SFelix Fietkau phy->sband_2g = dev->phy.sband_2g; 355c89d3625SFelix Fietkau phy->sband_2g.chan = priv; 356c89d3625SFelix Fietkau priv += size_2g; 357c89d3625SFelix Fietkau 358c89d3625SFelix Fietkau phy->sband_5g = dev->phy.sband_5g; 359c89d3625SFelix Fietkau phy->sband_5g.chan = priv; 360c89d3625SFelix Fietkau priv += size_5g; 361c89d3625SFelix Fietkau 362c89d3625SFelix Fietkau phy->priv = priv; 363c89d3625SFelix Fietkau 364c89d3625SFelix Fietkau hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; 365c89d3625SFelix Fietkau hw->wiphy->bands[NL80211_BAND_5GHZ] = &phy->sband_5g.sband; 366c89d3625SFelix Fietkau 367c89d3625SFelix Fietkau mt76_check_sband(phy, &phy->sband_2g, NL80211_BAND_2GHZ); 368c89d3625SFelix Fietkau mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ); 369c89d3625SFelix Fietkau 370c89d3625SFelix Fietkau return phy; 371c89d3625SFelix Fietkau } 372c89d3625SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_alloc_phy); 373c89d3625SFelix Fietkau 374c89d3625SFelix Fietkau int 375c89d3625SFelix Fietkau mt76_register_phy(struct mt76_phy *phy) 376c89d3625SFelix Fietkau { 377c89d3625SFelix Fietkau int ret; 378c89d3625SFelix Fietkau 379c89d3625SFelix Fietkau ret = ieee80211_register_hw(phy->hw); 380c89d3625SFelix Fietkau if (ret) 381c89d3625SFelix Fietkau return ret; 382c89d3625SFelix Fietkau 383c89d3625SFelix Fietkau phy->dev->phy2 = phy; 384c89d3625SFelix Fietkau return 0; 385c89d3625SFelix Fietkau } 386c89d3625SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_register_phy); 387c89d3625SFelix Fietkau 388c89d3625SFelix Fietkau void 389c89d3625SFelix Fietkau mt76_unregister_phy(struct mt76_phy *phy) 390c89d3625SFelix Fietkau { 391c89d3625SFelix Fietkau struct mt76_dev *dev = phy->dev; 392c89d3625SFelix Fietkau 393c89d3625SFelix Fietkau dev->phy2 = NULL; 394c89d3625SFelix Fietkau mt76_tx_status_check(dev, NULL, true); 395c89d3625SFelix Fietkau ieee80211_unregister_hw(phy->hw); 396c89d3625SFelix Fietkau } 397c89d3625SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_unregister_phy); 398c89d3625SFelix Fietkau 399a85b590cSFelix Fietkau struct mt76_dev * 400c0f7b25aSLorenzo Bianconi mt76_alloc_device(struct device *pdev, unsigned int size, 401c0f7b25aSLorenzo Bianconi const struct ieee80211_ops *ops, 402c0f7b25aSLorenzo Bianconi const struct mt76_driver_ops *drv_ops) 403a85b590cSFelix Fietkau { 404a85b590cSFelix Fietkau struct ieee80211_hw *hw; 405ac24dd35SFelix Fietkau struct mt76_phy *phy; 406a85b590cSFelix Fietkau struct mt76_dev *dev; 407e5443256SFelix Fietkau int i; 408a85b590cSFelix Fietkau 409a85b590cSFelix Fietkau hw = ieee80211_alloc_hw(size, ops); 410a85b590cSFelix Fietkau if (!hw) 411a85b590cSFelix Fietkau return NULL; 412a85b590cSFelix Fietkau 413a85b590cSFelix Fietkau dev = hw->priv; 414a85b590cSFelix Fietkau dev->hw = hw; 415c0f7b25aSLorenzo Bianconi dev->dev = pdev; 416c0f7b25aSLorenzo Bianconi dev->drv = drv_ops; 417c0f7b25aSLorenzo Bianconi 418ac24dd35SFelix Fietkau phy = &dev->phy; 419ac24dd35SFelix Fietkau phy->dev = dev; 420ac24dd35SFelix Fietkau phy->hw = hw; 421ac24dd35SFelix Fietkau 422a85b590cSFelix Fietkau spin_lock_init(&dev->rx_lock); 423a85b590cSFelix Fietkau spin_lock_init(&dev->lock); 424a85b590cSFelix Fietkau spin_lock_init(&dev->cc_lock); 425108a4861SStanislaw Gruszka mutex_init(&dev->mutex); 42626e40d4cSFelix Fietkau init_waitqueue_head(&dev->tx_wait); 42788046b2cSFelix Fietkau skb_queue_head_init(&dev->status_list); 428a85b590cSFelix Fietkau 42909872957SLorenzo Bianconi skb_queue_head_init(&dev->mcu.res_q); 43009872957SLorenzo Bianconi init_waitqueue_head(&dev->mcu.wait); 43109872957SLorenzo Bianconi mutex_init(&dev->mcu.mutex); 43209872957SLorenzo Bianconi 433e5443256SFelix Fietkau INIT_LIST_HEAD(&dev->txwi_cache); 434e5443256SFelix Fietkau 435e5443256SFelix Fietkau for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) 436e5443256SFelix Fietkau skb_queue_head_init(&dev->rx_skb[i]); 437e5443256SFelix Fietkau 438c325c9c7SLorenzo Bianconi tasklet_init(&dev->tx_tasklet, mt76_tx_tasklet, (unsigned long)dev); 439c325c9c7SLorenzo Bianconi 440*a86f1d01SLorenzo Bianconi dev->wq = alloc_ordered_workqueue("mt76", 0); 441*a86f1d01SLorenzo Bianconi if (!dev->wq) { 442*a86f1d01SLorenzo Bianconi ieee80211_free_hw(hw); 443*a86f1d01SLorenzo Bianconi return NULL; 444*a86f1d01SLorenzo Bianconi } 445*a86f1d01SLorenzo Bianconi 446a85b590cSFelix Fietkau return dev; 447a85b590cSFelix Fietkau } 448a85b590cSFelix Fietkau EXPORT_SYMBOL_GPL(mt76_alloc_device); 449a85b590cSFelix Fietkau 45017f1de56SFelix Fietkau int mt76_register_device(struct mt76_dev *dev, bool vht, 45117f1de56SFelix Fietkau struct ieee80211_rate *rates, int n_rates) 45217f1de56SFelix Fietkau { 45317f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 454c89d3625SFelix Fietkau struct mt76_phy *phy = &dev->phy; 45517f1de56SFelix Fietkau int ret; 45617f1de56SFelix Fietkau 45717f1de56SFelix Fietkau dev_set_drvdata(dev->dev, dev); 458c89d3625SFelix Fietkau mt76_phy_init(dev, hw); 45917f1de56SFelix Fietkau 46017f1de56SFelix Fietkau if (dev->cap.has_2ghz) { 46117f1de56SFelix Fietkau ret = mt76_init_sband_2g(dev, rates, n_rates); 46217f1de56SFelix Fietkau if (ret) 46317f1de56SFelix Fietkau return ret; 46417f1de56SFelix Fietkau } 46517f1de56SFelix Fietkau 46617f1de56SFelix Fietkau if (dev->cap.has_5ghz) { 46717f1de56SFelix Fietkau ret = mt76_init_sband_5g(dev, rates + 4, n_rates - 4, vht); 46817f1de56SFelix Fietkau if (ret) 46917f1de56SFelix Fietkau return ret; 47017f1de56SFelix Fietkau } 47117f1de56SFelix Fietkau 472c89d3625SFelix Fietkau wiphy_read_of_freq_limits(hw->wiphy); 473c89d3625SFelix Fietkau mt76_check_sband(&dev->phy, &phy->sband_2g, NL80211_BAND_2GHZ); 474c89d3625SFelix Fietkau mt76_check_sband(&dev->phy, &phy->sband_5g, NL80211_BAND_5GHZ); 47517f1de56SFelix Fietkau 476b374e868SArnd Bergmann if (IS_ENABLED(CONFIG_MT76_LEDS)) { 47717f1de56SFelix Fietkau ret = mt76_led_init(dev); 47817f1de56SFelix Fietkau if (ret) 47917f1de56SFelix Fietkau return ret; 480b374e868SArnd Bergmann } 48117f1de56SFelix Fietkau 48217f1de56SFelix Fietkau return ieee80211_register_hw(hw); 48317f1de56SFelix Fietkau } 48417f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_register_device); 48517f1de56SFelix Fietkau 48617f1de56SFelix Fietkau void mt76_unregister_device(struct mt76_dev *dev) 48717f1de56SFelix Fietkau { 48817f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 48917f1de56SFelix Fietkau 490d68f4e43SArnd Bergmann if (IS_ENABLED(CONFIG_MT76_LEDS)) 49136f7e2b2SFelix Fietkau mt76_led_cleanup(dev); 49279d1c94cSFelix Fietkau mt76_tx_status_check(dev, NULL, true); 49317f1de56SFelix Fietkau ieee80211_unregister_hw(hw); 49417f1de56SFelix Fietkau } 49517f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_unregister_device); 49617f1de56SFelix Fietkau 497def34a2fSLorenzo Bianconi void mt76_free_device(struct mt76_dev *dev) 498def34a2fSLorenzo Bianconi { 499*a86f1d01SLorenzo Bianconi if (dev->wq) { 500*a86f1d01SLorenzo Bianconi destroy_workqueue(dev->wq); 501*a86f1d01SLorenzo Bianconi dev->wq = NULL; 502*a86f1d01SLorenzo Bianconi } 503*a86f1d01SLorenzo Bianconi if (mt76_is_mmio(dev)) 504def34a2fSLorenzo Bianconi mt76_tx_free(dev); 505def34a2fSLorenzo Bianconi ieee80211_free_hw(dev->hw); 506def34a2fSLorenzo Bianconi } 507def34a2fSLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_free_device); 508def34a2fSLorenzo Bianconi 50917f1de56SFelix Fietkau void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) 51017f1de56SFelix Fietkau { 511011849e0SFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 512011849e0SFelix Fietkau struct mt76_phy *phy = mt76_dev_phy(dev, status->ext_phy); 513011849e0SFelix Fietkau 514011849e0SFelix Fietkau if (!test_bit(MT76_STATE_RUNNING, &phy->state)) { 51517f1de56SFelix Fietkau dev_kfree_skb(skb); 51617f1de56SFelix Fietkau return; 51717f1de56SFelix Fietkau } 51817f1de56SFelix Fietkau 519f0efa862SFelix Fietkau #ifdef CONFIG_NL80211_TESTMODE 520f0efa862SFelix Fietkau if (dev->test.state == MT76_TM_STATE_RX_FRAMES) { 521f0efa862SFelix Fietkau dev->test.rx_stats.packets[q]++; 522f0efa862SFelix Fietkau if (status->flag & RX_FLAG_FAILED_FCS_CRC) 523f0efa862SFelix Fietkau dev->test.rx_stats.fcs_error[q]++; 524f0efa862SFelix Fietkau } 525f0efa862SFelix Fietkau #endif 52617f1de56SFelix Fietkau __skb_queue_tail(&dev->rx_skb[q], skb); 52717f1de56SFelix Fietkau } 52817f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_rx); 52917f1de56SFelix Fietkau 5305a95ca41SFelix Fietkau bool mt76_has_tx_pending(struct mt76_phy *phy) 53126e40d4cSFelix Fietkau { 5325a95ca41SFelix Fietkau struct mt76_dev *dev = phy->dev; 533af005f26SLorenzo Bianconi struct mt76_queue *q; 5345a95ca41SFelix Fietkau int i, offset; 53526e40d4cSFelix Fietkau 5365a95ca41SFelix Fietkau offset = __MT_TXQ_MAX * (phy != &dev->phy); 5375a95ca41SFelix Fietkau 5385a95ca41SFelix Fietkau for (i = 0; i < __MT_TXQ_MAX; i++) { 5395a95ca41SFelix Fietkau q = dev->q_tx[offset + i].q; 540af005f26SLorenzo Bianconi if (q && q->queued) 54126e40d4cSFelix Fietkau return true; 54226e40d4cSFelix Fietkau } 54326e40d4cSFelix Fietkau 54426e40d4cSFelix Fietkau return false; 54526e40d4cSFelix Fietkau } 54639d501d9SStanislaw Gruszka EXPORT_SYMBOL_GPL(mt76_has_tx_pending); 54726e40d4cSFelix Fietkau 5480fd0eb54SFelix Fietkau static struct mt76_channel_state * 54996747a51SFelix Fietkau mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c) 5500fd0eb54SFelix Fietkau { 5510fd0eb54SFelix Fietkau struct mt76_sband *msband; 5520fd0eb54SFelix Fietkau int idx; 5530fd0eb54SFelix Fietkau 5540fd0eb54SFelix Fietkau if (c->band == NL80211_BAND_2GHZ) 55596747a51SFelix Fietkau msband = &phy->sband_2g; 5560fd0eb54SFelix Fietkau else 55796747a51SFelix Fietkau msband = &phy->sband_5g; 5580fd0eb54SFelix Fietkau 5590fd0eb54SFelix Fietkau idx = c - &msband->sband.channels[0]; 5600fd0eb54SFelix Fietkau return &msband->chan[idx]; 5610fd0eb54SFelix Fietkau } 5620fd0eb54SFelix Fietkau 56396747a51SFelix Fietkau static void 56496747a51SFelix Fietkau mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time) 56596747a51SFelix Fietkau { 56696747a51SFelix Fietkau struct mt76_channel_state *state = phy->chan_state; 56796747a51SFelix Fietkau 56896747a51SFelix Fietkau state->cc_active += ktime_to_us(ktime_sub(time, 56996747a51SFelix Fietkau phy->survey_time)); 57096747a51SFelix Fietkau phy->survey_time = time; 57196747a51SFelix Fietkau } 57296747a51SFelix Fietkau 5735ce09c1aSFelix Fietkau void mt76_update_survey(struct mt76_dev *dev) 5745ce09c1aSFelix Fietkau { 575aec65e48SFelix Fietkau ktime_t cur_time; 576aec65e48SFelix Fietkau 5775ce09c1aSFelix Fietkau if (dev->drv->update_survey) 5785ce09c1aSFelix Fietkau dev->drv->update_survey(dev); 5795ce09c1aSFelix Fietkau 580aec65e48SFelix Fietkau cur_time = ktime_get_boottime(); 58196747a51SFelix Fietkau mt76_update_survey_active_time(&dev->phy, cur_time); 58296747a51SFelix Fietkau if (dev->phy2) 58396747a51SFelix Fietkau mt76_update_survey_active_time(dev->phy2, cur_time); 584aec65e48SFelix Fietkau 5855ce09c1aSFelix Fietkau if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) { 58696747a51SFelix Fietkau struct mt76_channel_state *state = dev->phy.chan_state; 58796747a51SFelix Fietkau 588237312c5SLorenzo Bianconi spin_lock_bh(&dev->cc_lock); 5895ce09c1aSFelix Fietkau state->cc_bss_rx += dev->cur_cc_bss_rx; 5905ce09c1aSFelix Fietkau dev->cur_cc_bss_rx = 0; 591237312c5SLorenzo Bianconi spin_unlock_bh(&dev->cc_lock); 5925ce09c1aSFelix Fietkau } 5935ce09c1aSFelix Fietkau } 5945ce09c1aSFelix Fietkau EXPORT_SYMBOL_GPL(mt76_update_survey); 5955ce09c1aSFelix Fietkau 59696747a51SFelix Fietkau void mt76_set_channel(struct mt76_phy *phy) 59717f1de56SFelix Fietkau { 59896747a51SFelix Fietkau struct mt76_dev *dev = phy->dev; 59996747a51SFelix Fietkau struct ieee80211_hw *hw = phy->hw; 60017f1de56SFelix Fietkau struct cfg80211_chan_def *chandef = &hw->conf.chandef; 60117f1de56SFelix Fietkau bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; 60226e40d4cSFelix Fietkau int timeout = HZ / 5; 60317f1de56SFelix Fietkau 6045a95ca41SFelix Fietkau wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout); 6055ce09c1aSFelix Fietkau mt76_update_survey(dev); 60617f1de56SFelix Fietkau 60796747a51SFelix Fietkau phy->chandef = *chandef; 60896747a51SFelix Fietkau phy->chan_state = mt76_channel_state(phy, chandef->chan); 60917f1de56SFelix Fietkau 61017f1de56SFelix Fietkau if (!offchannel) 61196747a51SFelix Fietkau phy->main_chan = chandef->chan; 61217f1de56SFelix Fietkau 61396747a51SFelix Fietkau if (chandef->chan != phy->main_chan) 61496747a51SFelix Fietkau memset(phy->chan_state, 0, sizeof(*phy->chan_state)); 61517f1de56SFelix Fietkau } 61617f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_set_channel); 61717f1de56SFelix Fietkau 61817f1de56SFelix Fietkau int mt76_get_survey(struct ieee80211_hw *hw, int idx, 61917f1de56SFelix Fietkau struct survey_info *survey) 62017f1de56SFelix Fietkau { 62196747a51SFelix Fietkau struct mt76_phy *phy = hw->priv; 62296747a51SFelix Fietkau struct mt76_dev *dev = phy->dev; 62317f1de56SFelix Fietkau struct mt76_sband *sband; 62417f1de56SFelix Fietkau struct ieee80211_channel *chan; 62517f1de56SFelix Fietkau struct mt76_channel_state *state; 62617f1de56SFelix Fietkau int ret = 0; 62717f1de56SFelix Fietkau 628237312c5SLorenzo Bianconi mutex_lock(&dev->mutex); 62917f1de56SFelix Fietkau if (idx == 0 && dev->drv->update_survey) 6305ce09c1aSFelix Fietkau mt76_update_survey(dev); 63117f1de56SFelix Fietkau 63296747a51SFelix Fietkau sband = &phy->sband_2g; 63317f1de56SFelix Fietkau if (idx >= sband->sband.n_channels) { 63417f1de56SFelix Fietkau idx -= sband->sband.n_channels; 63596747a51SFelix Fietkau sband = &phy->sband_5g; 63617f1de56SFelix Fietkau } 63717f1de56SFelix Fietkau 638237312c5SLorenzo Bianconi if (idx >= sband->sband.n_channels) { 639237312c5SLorenzo Bianconi ret = -ENOENT; 640237312c5SLorenzo Bianconi goto out; 641237312c5SLorenzo Bianconi } 64217f1de56SFelix Fietkau 64317f1de56SFelix Fietkau chan = &sband->sband.channels[idx]; 64496747a51SFelix Fietkau state = mt76_channel_state(phy, chan); 64517f1de56SFelix Fietkau 64617f1de56SFelix Fietkau memset(survey, 0, sizeof(*survey)); 64717f1de56SFelix Fietkau survey->channel = chan; 64817f1de56SFelix Fietkau survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY; 649ea565833SFelix Fietkau survey->filled |= dev->drv->survey_flags; 650e5051965SFelix Fietkau if (state->noise) 651e5051965SFelix Fietkau survey->filled |= SURVEY_INFO_NOISE_DBM; 652e5051965SFelix Fietkau 65396747a51SFelix Fietkau if (chan == phy->main_chan) { 65417f1de56SFelix Fietkau survey->filled |= SURVEY_INFO_IN_USE; 65517f1de56SFelix Fietkau 6565ce09c1aSFelix Fietkau if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) 6575ce09c1aSFelix Fietkau survey->filled |= SURVEY_INFO_TIME_BSS_RX; 6585ce09c1aSFelix Fietkau } 6595ce09c1aSFelix Fietkau 66017f1de56SFelix Fietkau survey->time_busy = div_u64(state->cc_busy, 1000); 6616bfa6e38SLorenzo Bianconi survey->time_rx = div_u64(state->cc_rx, 1000); 662237312c5SLorenzo Bianconi survey->time = div_u64(state->cc_active, 1000); 663e5051965SFelix Fietkau survey->noise = state->noise; 664237312c5SLorenzo Bianconi 665237312c5SLorenzo Bianconi spin_lock_bh(&dev->cc_lock); 666237312c5SLorenzo Bianconi survey->time_bss_rx = div_u64(state->cc_bss_rx, 1000); 667ea565833SFelix Fietkau survey->time_tx = div_u64(state->cc_tx, 1000); 66817f1de56SFelix Fietkau spin_unlock_bh(&dev->cc_lock); 66917f1de56SFelix Fietkau 670237312c5SLorenzo Bianconi out: 671237312c5SLorenzo Bianconi mutex_unlock(&dev->mutex); 672237312c5SLorenzo Bianconi 67317f1de56SFelix Fietkau return ret; 67417f1de56SFelix Fietkau } 67517f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_get_survey); 67617f1de56SFelix Fietkau 67730ce7f44SFelix Fietkau void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid, 67830ce7f44SFelix Fietkau struct ieee80211_key_conf *key) 67930ce7f44SFelix Fietkau { 68030ce7f44SFelix Fietkau struct ieee80211_key_seq seq; 68130ce7f44SFelix Fietkau int i; 68230ce7f44SFelix Fietkau 68330ce7f44SFelix Fietkau wcid->rx_check_pn = false; 68430ce7f44SFelix Fietkau 68530ce7f44SFelix Fietkau if (!key) 68630ce7f44SFelix Fietkau return; 68730ce7f44SFelix Fietkau 68801cfc1b4SLorenzo Bianconi if (key->cipher != WLAN_CIPHER_SUITE_CCMP) 68901cfc1b4SLorenzo Bianconi return; 69030ce7f44SFelix Fietkau 69101cfc1b4SLorenzo Bianconi wcid->rx_check_pn = true; 69230ce7f44SFelix Fietkau for (i = 0; i < IEEE80211_NUM_TIDS; i++) { 69330ce7f44SFelix Fietkau ieee80211_get_key_rx_seq(key, i, &seq); 69430ce7f44SFelix Fietkau memcpy(wcid->rx_key_pn[i], seq.ccmp.pn, sizeof(seq.ccmp.pn)); 69530ce7f44SFelix Fietkau } 69630ce7f44SFelix Fietkau } 69730ce7f44SFelix Fietkau EXPORT_SYMBOL(mt76_wcid_key_setup); 69830ce7f44SFelix Fietkau 699bfc394ddSFelix Fietkau static void 700bfc394ddSFelix Fietkau mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, 701bfc394ddSFelix Fietkau struct ieee80211_hw **hw, 702bfc394ddSFelix Fietkau struct ieee80211_sta **sta) 7034e34249eSFelix Fietkau { 7044e34249eSFelix Fietkau struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 7054e34249eSFelix Fietkau struct mt76_rx_status mstat; 7064e34249eSFelix Fietkau 7074e34249eSFelix Fietkau mstat = *((struct mt76_rx_status *)skb->cb); 7084e34249eSFelix Fietkau memset(status, 0, sizeof(*status)); 7094e34249eSFelix Fietkau 7104e34249eSFelix Fietkau status->flag = mstat.flag; 7114e34249eSFelix Fietkau status->freq = mstat.freq; 7124e34249eSFelix Fietkau status->enc_flags = mstat.enc_flags; 7134e34249eSFelix Fietkau status->encoding = mstat.encoding; 7144e34249eSFelix Fietkau status->bw = mstat.bw; 715af4a2f2fSRyder Lee status->he_ru = mstat.he_ru; 716af4a2f2fSRyder Lee status->he_gi = mstat.he_gi; 717af4a2f2fSRyder Lee status->he_dcm = mstat.he_dcm; 7184e34249eSFelix Fietkau status->rate_idx = mstat.rate_idx; 7194e34249eSFelix Fietkau status->nss = mstat.nss; 7204e34249eSFelix Fietkau status->band = mstat.band; 7214e34249eSFelix Fietkau status->signal = mstat.signal; 7224e34249eSFelix Fietkau status->chains = mstat.chains; 723d515fdcaSFelix Fietkau status->ampdu_reference = mstat.ampdu_ref; 7244e34249eSFelix Fietkau 7254e34249eSFelix Fietkau BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb)); 72613381dcdSRyder Lee BUILD_BUG_ON(sizeof(status->chain_signal) != 72713381dcdSRyder Lee sizeof(mstat.chain_signal)); 72813381dcdSRyder Lee memcpy(status->chain_signal, mstat.chain_signal, 72913381dcdSRyder Lee sizeof(mstat.chain_signal)); 7309c68a57bSFelix Fietkau 731bfc394ddSFelix Fietkau *sta = wcid_to_sta(mstat.wcid); 732bfc394ddSFelix Fietkau *hw = mt76_phy_hw(dev, mstat.ext_phy); 7334e34249eSFelix Fietkau } 7344e34249eSFelix Fietkau 73530ce7f44SFelix Fietkau static int 73630ce7f44SFelix Fietkau mt76_check_ccmp_pn(struct sk_buff *skb) 73730ce7f44SFelix Fietkau { 73830ce7f44SFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 73930ce7f44SFelix Fietkau struct mt76_wcid *wcid = status->wcid; 74030ce7f44SFelix Fietkau struct ieee80211_hdr *hdr; 74130ce7f44SFelix Fietkau int ret; 74230ce7f44SFelix Fietkau 74330ce7f44SFelix Fietkau if (!(status->flag & RX_FLAG_DECRYPTED)) 74430ce7f44SFelix Fietkau return 0; 74530ce7f44SFelix Fietkau 74630ce7f44SFelix Fietkau if (!wcid || !wcid->rx_check_pn) 74730ce7f44SFelix Fietkau return 0; 74830ce7f44SFelix Fietkau 74930ce7f44SFelix Fietkau if (!(status->flag & RX_FLAG_IV_STRIPPED)) { 75030ce7f44SFelix Fietkau /* 75130ce7f44SFelix Fietkau * Validate the first fragment both here and in mac80211 75230ce7f44SFelix Fietkau * All further fragments will be validated by mac80211 only. 75330ce7f44SFelix Fietkau */ 75477ae1d5eSRyder Lee hdr = mt76_skb_get_hdr(skb); 75530ce7f44SFelix Fietkau if (ieee80211_is_frag(hdr) && 75630ce7f44SFelix Fietkau !ieee80211_is_first_frag(hdr->frame_control)) 75730ce7f44SFelix Fietkau return 0; 75830ce7f44SFelix Fietkau } 75930ce7f44SFelix Fietkau 76030ce7f44SFelix Fietkau BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0])); 76130ce7f44SFelix Fietkau ret = memcmp(status->iv, wcid->rx_key_pn[status->tid], 76230ce7f44SFelix Fietkau sizeof(status->iv)); 76330ce7f44SFelix Fietkau if (ret <= 0) 76430ce7f44SFelix Fietkau return -EINVAL; /* replay */ 76530ce7f44SFelix Fietkau 76630ce7f44SFelix Fietkau memcpy(wcid->rx_key_pn[status->tid], status->iv, sizeof(status->iv)); 76730ce7f44SFelix Fietkau 76830ce7f44SFelix Fietkau if (status->flag & RX_FLAG_IV_STRIPPED) 76930ce7f44SFelix Fietkau status->flag |= RX_FLAG_PN_VALIDATED; 77030ce7f44SFelix Fietkau 77130ce7f44SFelix Fietkau return 0; 77230ce7f44SFelix Fietkau } 77330ce7f44SFelix Fietkau 774d71ef286SFelix Fietkau static void 7755ce09c1aSFelix Fietkau mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status, 7765ce09c1aSFelix Fietkau int len) 7775ce09c1aSFelix Fietkau { 7785ce09c1aSFelix Fietkau struct mt76_wcid *wcid = status->wcid; 77985b7a5d0SLorenzo Bianconi struct ieee80211_rx_status info = { 78085b7a5d0SLorenzo Bianconi .enc_flags = status->enc_flags, 78185b7a5d0SLorenzo Bianconi .rate_idx = status->rate_idx, 78285b7a5d0SLorenzo Bianconi .encoding = status->encoding, 78385b7a5d0SLorenzo Bianconi .band = status->band, 78485b7a5d0SLorenzo Bianconi .nss = status->nss, 78585b7a5d0SLorenzo Bianconi .bw = status->bw, 78685b7a5d0SLorenzo Bianconi }; 7875ce09c1aSFelix Fietkau struct ieee80211_sta *sta; 7885ce09c1aSFelix Fietkau u32 airtime; 7895ce09c1aSFelix Fietkau 79085b7a5d0SLorenzo Bianconi airtime = ieee80211_calc_rx_airtime(dev->hw, &info, len); 791237312c5SLorenzo Bianconi spin_lock(&dev->cc_lock); 7925ce09c1aSFelix Fietkau dev->cur_cc_bss_rx += airtime; 793237312c5SLorenzo Bianconi spin_unlock(&dev->cc_lock); 7945ce09c1aSFelix Fietkau 7955ce09c1aSFelix Fietkau if (!wcid || !wcid->sta) 7965ce09c1aSFelix Fietkau return; 7975ce09c1aSFelix Fietkau 7985ce09c1aSFelix Fietkau sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); 7995ce09c1aSFelix Fietkau ieee80211_sta_register_airtime(sta, status->tid, 0, airtime); 8005ce09c1aSFelix Fietkau } 8015ce09c1aSFelix Fietkau 8025ce09c1aSFelix Fietkau static void 8035ce09c1aSFelix Fietkau mt76_airtime_flush_ampdu(struct mt76_dev *dev) 8045ce09c1aSFelix Fietkau { 8055ce09c1aSFelix Fietkau struct mt76_wcid *wcid; 8065ce09c1aSFelix Fietkau int wcid_idx; 8075ce09c1aSFelix Fietkau 8085ce09c1aSFelix Fietkau if (!dev->rx_ampdu_len) 8095ce09c1aSFelix Fietkau return; 8105ce09c1aSFelix Fietkau 8115ce09c1aSFelix Fietkau wcid_idx = dev->rx_ampdu_status.wcid_idx; 812bf5238b2SFelix Fietkau if (wcid_idx < ARRAY_SIZE(dev->wcid)) 8135ce09c1aSFelix Fietkau wcid = rcu_dereference(dev->wcid[wcid_idx]); 8145ce09c1aSFelix Fietkau else 8155ce09c1aSFelix Fietkau wcid = NULL; 8165ce09c1aSFelix Fietkau dev->rx_ampdu_status.wcid = wcid; 8175ce09c1aSFelix Fietkau 8185ce09c1aSFelix Fietkau mt76_airtime_report(dev, &dev->rx_ampdu_status, dev->rx_ampdu_len); 8195ce09c1aSFelix Fietkau 8205ce09c1aSFelix Fietkau dev->rx_ampdu_len = 0; 8215ce09c1aSFelix Fietkau dev->rx_ampdu_ref = 0; 8225ce09c1aSFelix Fietkau } 8235ce09c1aSFelix Fietkau 8245ce09c1aSFelix Fietkau static void 8255ce09c1aSFelix Fietkau mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb) 8265ce09c1aSFelix Fietkau { 82777ae1d5eSRyder Lee struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); 8285ce09c1aSFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 8295ce09c1aSFelix Fietkau struct mt76_wcid *wcid = status->wcid; 8305ce09c1aSFelix Fietkau 8315ce09c1aSFelix Fietkau if (!(dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME)) 8325ce09c1aSFelix Fietkau return; 8335ce09c1aSFelix Fietkau 8345ce09c1aSFelix Fietkau if (!wcid || !wcid->sta) { 8355ce09c1aSFelix Fietkau if (!ether_addr_equal(hdr->addr1, dev->macaddr)) 8365ce09c1aSFelix Fietkau return; 8375ce09c1aSFelix Fietkau 8385ce09c1aSFelix Fietkau wcid = NULL; 8395ce09c1aSFelix Fietkau } 8405ce09c1aSFelix Fietkau 8415ce09c1aSFelix Fietkau if (!(status->flag & RX_FLAG_AMPDU_DETAILS) || 8425ce09c1aSFelix Fietkau status->ampdu_ref != dev->rx_ampdu_ref) 8435ce09c1aSFelix Fietkau mt76_airtime_flush_ampdu(dev); 8445ce09c1aSFelix Fietkau 8455ce09c1aSFelix Fietkau if (status->flag & RX_FLAG_AMPDU_DETAILS) { 8465ce09c1aSFelix Fietkau if (!dev->rx_ampdu_len || 8475ce09c1aSFelix Fietkau status->ampdu_ref != dev->rx_ampdu_ref) { 8485ce09c1aSFelix Fietkau dev->rx_ampdu_status = *status; 8495ce09c1aSFelix Fietkau dev->rx_ampdu_status.wcid_idx = wcid ? wcid->idx : 0xff; 8505ce09c1aSFelix Fietkau dev->rx_ampdu_ref = status->ampdu_ref; 8515ce09c1aSFelix Fietkau } 8525ce09c1aSFelix Fietkau 8535ce09c1aSFelix Fietkau dev->rx_ampdu_len += skb->len; 8545ce09c1aSFelix Fietkau return; 8555ce09c1aSFelix Fietkau } 8565ce09c1aSFelix Fietkau 8575ce09c1aSFelix Fietkau mt76_airtime_report(dev, status, skb->len); 8585ce09c1aSFelix Fietkau } 8595ce09c1aSFelix Fietkau 8605ce09c1aSFelix Fietkau static void 861ef13edc0SFelix Fietkau mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) 862d71ef286SFelix Fietkau { 863d71ef286SFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 86477ae1d5eSRyder Lee struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); 865d71ef286SFelix Fietkau struct ieee80211_sta *sta; 866bfc394ddSFelix Fietkau struct ieee80211_hw *hw; 867d71ef286SFelix Fietkau struct mt76_wcid *wcid = status->wcid; 868d71ef286SFelix Fietkau bool ps; 86990fdc171SFelix Fietkau int i; 870d71ef286SFelix Fietkau 871bfc394ddSFelix Fietkau hw = mt76_phy_hw(dev, status->ext_phy); 87236d91096SFelix Fietkau if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) { 873bfc394ddSFelix Fietkau sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); 87436d91096SFelix Fietkau if (sta) 87536d91096SFelix Fietkau wcid = status->wcid = (struct mt76_wcid *)sta->drv_priv; 87636d91096SFelix Fietkau } 87736d91096SFelix Fietkau 8785ce09c1aSFelix Fietkau mt76_airtime_check(dev, skb); 8795ce09c1aSFelix Fietkau 880d71ef286SFelix Fietkau if (!wcid || !wcid->sta) 881d71ef286SFelix Fietkau return; 882d71ef286SFelix Fietkau 883d71ef286SFelix Fietkau sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); 884d71ef286SFelix Fietkau 88502e5a769SFelix Fietkau if (status->signal <= 0) 88602e5a769SFelix Fietkau ewma_signal_add(&wcid->rssi, -status->signal); 88702e5a769SFelix Fietkau 888ef13edc0SFelix Fietkau wcid->inactive_count = 0; 889ef13edc0SFelix Fietkau 890d71ef286SFelix Fietkau if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags)) 891d71ef286SFelix Fietkau return; 892d71ef286SFelix Fietkau 893d71ef286SFelix Fietkau if (ieee80211_is_pspoll(hdr->frame_control)) { 894d71ef286SFelix Fietkau ieee80211_sta_pspoll(sta); 895d71ef286SFelix Fietkau return; 896d71ef286SFelix Fietkau } 897d71ef286SFelix Fietkau 898d71ef286SFelix Fietkau if (ieee80211_has_morefrags(hdr->frame_control) || 899d71ef286SFelix Fietkau !(ieee80211_is_mgmt(hdr->frame_control) || 900d71ef286SFelix Fietkau ieee80211_is_data(hdr->frame_control))) 901d71ef286SFelix Fietkau return; 902d71ef286SFelix Fietkau 903d71ef286SFelix Fietkau ps = ieee80211_has_pm(hdr->frame_control); 904d71ef286SFelix Fietkau 905d71ef286SFelix Fietkau if (ps && (ieee80211_is_data_qos(hdr->frame_control) || 906d71ef286SFelix Fietkau ieee80211_is_qos_nullfunc(hdr->frame_control))) 907d71ef286SFelix Fietkau ieee80211_sta_uapsd_trigger(sta, status->tid); 908d71ef286SFelix Fietkau 909d71ef286SFelix Fietkau if (!!test_bit(MT_WCID_FLAG_PS, &wcid->flags) == ps) 910d71ef286SFelix Fietkau return; 911d71ef286SFelix Fietkau 91211b2a25fSFelix Fietkau if (ps) 913d71ef286SFelix Fietkau set_bit(MT_WCID_FLAG_PS, &wcid->flags); 91411b2a25fSFelix Fietkau else 915d71ef286SFelix Fietkau clear_bit(MT_WCID_FLAG_PS, &wcid->flags); 916d71ef286SFelix Fietkau 917d71ef286SFelix Fietkau dev->drv->sta_ps(dev, sta, ps); 9189f67c277SFelix Fietkau ieee80211_sta_ps_transition(sta, ps); 91990fdc171SFelix Fietkau 92090fdc171SFelix Fietkau if (ps) 92190fdc171SFelix Fietkau return; 92290fdc171SFelix Fietkau 92390fdc171SFelix Fietkau for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { 92490fdc171SFelix Fietkau struct mt76_txq *mtxq; 92590fdc171SFelix Fietkau 92690fdc171SFelix Fietkau if (!sta->txq[i]) 92790fdc171SFelix Fietkau continue; 92890fdc171SFelix Fietkau 92990fdc171SFelix Fietkau mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; 93090fdc171SFelix Fietkau if (!skb_queue_empty(&mtxq->retry_q)) 931bfc394ddSFelix Fietkau ieee80211_schedule_txq(hw, sta->txq[i]); 93290fdc171SFelix Fietkau } 933d71ef286SFelix Fietkau } 934d71ef286SFelix Fietkau 9359d9d738bSFelix Fietkau void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, 93681e850efSLorenzo Bianconi struct napi_struct *napi) 93717f1de56SFelix Fietkau { 9389c68a57bSFelix Fietkau struct ieee80211_sta *sta; 939bfc394ddSFelix Fietkau struct ieee80211_hw *hw; 9409d9d738bSFelix Fietkau struct sk_buff *skb; 9419d9d738bSFelix Fietkau 942c3d7c82aSFelix Fietkau spin_lock(&dev->rx_lock); 9439d9d738bSFelix Fietkau while ((skb = __skb_dequeue(frames)) != NULL) { 94430ce7f44SFelix Fietkau if (mt76_check_ccmp_pn(skb)) { 94530ce7f44SFelix Fietkau dev_kfree_skb(skb); 94630ce7f44SFelix Fietkau continue; 94730ce7f44SFelix Fietkau } 94830ce7f44SFelix Fietkau 949bfc394ddSFelix Fietkau mt76_rx_convert(dev, skb, &hw, &sta); 950bfc394ddSFelix Fietkau ieee80211_rx_napi(hw, sta, skb, napi); 9519d9d738bSFelix Fietkau } 952c3d7c82aSFelix Fietkau spin_unlock(&dev->rx_lock); 9539d9d738bSFelix Fietkau } 9549d9d738bSFelix Fietkau 95581e850efSLorenzo Bianconi void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q, 95681e850efSLorenzo Bianconi struct napi_struct *napi) 9579d9d738bSFelix Fietkau { 958aee5b8cfSFelix Fietkau struct sk_buff_head frames; 95917f1de56SFelix Fietkau struct sk_buff *skb; 96017f1de56SFelix Fietkau 961aee5b8cfSFelix Fietkau __skb_queue_head_init(&frames); 962aee5b8cfSFelix Fietkau 963d71ef286SFelix Fietkau while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) { 964ef13edc0SFelix Fietkau mt76_check_sta(dev, skb); 965aee5b8cfSFelix Fietkau mt76_rx_aggr_reorder(skb, &frames); 966d71ef286SFelix Fietkau } 967aee5b8cfSFelix Fietkau 96881e850efSLorenzo Bianconi mt76_rx_complete(dev, &frames, napi); 9694e34249eSFelix Fietkau } 97081e850efSLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_rx_poll_complete); 971723b90dcSFelix Fietkau 972e28487eaSFelix Fietkau static int 973e28487eaSFelix Fietkau mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, 974426e8e41SFelix Fietkau struct ieee80211_sta *sta, bool ext_phy) 975e28487eaSFelix Fietkau { 976e28487eaSFelix Fietkau struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; 977e28487eaSFelix Fietkau int ret; 978e28487eaSFelix Fietkau int i; 979e28487eaSFelix Fietkau 980e28487eaSFelix Fietkau mutex_lock(&dev->mutex); 981e28487eaSFelix Fietkau 982e28487eaSFelix Fietkau ret = dev->drv->sta_add(dev, vif, sta); 983e28487eaSFelix Fietkau if (ret) 984e28487eaSFelix Fietkau goto out; 985e28487eaSFelix Fietkau 986e28487eaSFelix Fietkau for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { 987e28487eaSFelix Fietkau struct mt76_txq *mtxq; 988e28487eaSFelix Fietkau 989e28487eaSFelix Fietkau if (!sta->txq[i]) 990e28487eaSFelix Fietkau continue; 991e28487eaSFelix Fietkau 992e28487eaSFelix Fietkau mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; 993e28487eaSFelix Fietkau mtxq->wcid = wcid; 994e28487eaSFelix Fietkau 995e28487eaSFelix Fietkau mt76_txq_init(dev, sta->txq[i]); 996e28487eaSFelix Fietkau } 997e28487eaSFelix Fietkau 998ef13edc0SFelix Fietkau ewma_signal_init(&wcid->rssi); 999426e8e41SFelix Fietkau if (ext_phy) 1000426e8e41SFelix Fietkau mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx); 1001c7d2d631SFelix Fietkau wcid->ext_phy = ext_phy; 1002e28487eaSFelix Fietkau rcu_assign_pointer(dev->wcid[wcid->idx], wcid); 1003e28487eaSFelix Fietkau 1004e28487eaSFelix Fietkau out: 1005e28487eaSFelix Fietkau mutex_unlock(&dev->mutex); 1006e28487eaSFelix Fietkau 1007e28487eaSFelix Fietkau return ret; 1008e28487eaSFelix Fietkau } 1009e28487eaSFelix Fietkau 101013f61dfcSLorenzo Bianconi void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, 1011723b90dcSFelix Fietkau struct ieee80211_sta *sta) 1012723b90dcSFelix Fietkau { 1013723b90dcSFelix Fietkau struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; 101413f61dfcSLorenzo Bianconi int i, idx = wcid->idx; 1015723b90dcSFelix Fietkau 101658bab0d4SFelix Fietkau for (i = 0; i < ARRAY_SIZE(wcid->aggr); i++) 101758bab0d4SFelix Fietkau mt76_rx_aggr_stop(dev, wcid, i); 101858bab0d4SFelix Fietkau 1019e28487eaSFelix Fietkau if (dev->drv->sta_remove) 1020e28487eaSFelix Fietkau dev->drv->sta_remove(dev, vif, sta); 1021e28487eaSFelix Fietkau 1022723b90dcSFelix Fietkau mt76_tx_status_check(dev, wcid, true); 1023723b90dcSFelix Fietkau for (i = 0; i < ARRAY_SIZE(sta->txq); i++) 1024723b90dcSFelix Fietkau mt76_txq_remove(dev, sta->txq[i]); 1025426e8e41SFelix Fietkau mt76_wcid_mask_clear(dev->wcid_mask, idx); 1026426e8e41SFelix Fietkau mt76_wcid_mask_clear(dev->wcid_phy_mask, idx); 102713f61dfcSLorenzo Bianconi } 102813f61dfcSLorenzo Bianconi EXPORT_SYMBOL_GPL(__mt76_sta_remove); 1029e28487eaSFelix Fietkau 103013f61dfcSLorenzo Bianconi static void 103113f61dfcSLorenzo Bianconi mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, 103213f61dfcSLorenzo Bianconi struct ieee80211_sta *sta) 103313f61dfcSLorenzo Bianconi { 103413f61dfcSLorenzo Bianconi mutex_lock(&dev->mutex); 103513f61dfcSLorenzo Bianconi __mt76_sta_remove(dev, vif, sta); 1036723b90dcSFelix Fietkau mutex_unlock(&dev->mutex); 1037723b90dcSFelix Fietkau } 1038e28487eaSFelix Fietkau 1039e28487eaSFelix Fietkau int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1040e28487eaSFelix Fietkau struct ieee80211_sta *sta, 1041e28487eaSFelix Fietkau enum ieee80211_sta_state old_state, 1042e28487eaSFelix Fietkau enum ieee80211_sta_state new_state) 1043e28487eaSFelix Fietkau { 1044426e8e41SFelix Fietkau struct mt76_phy *phy = hw->priv; 1045426e8e41SFelix Fietkau struct mt76_dev *dev = phy->dev; 1046426e8e41SFelix Fietkau bool ext_phy = phy != &dev->phy; 1047e28487eaSFelix Fietkau 1048e28487eaSFelix Fietkau if (old_state == IEEE80211_STA_NOTEXIST && 1049e28487eaSFelix Fietkau new_state == IEEE80211_STA_NONE) 1050426e8e41SFelix Fietkau return mt76_sta_add(dev, vif, sta, ext_phy); 1051e28487eaSFelix Fietkau 10529c193de5SFelix Fietkau if (old_state == IEEE80211_STA_AUTH && 10539c193de5SFelix Fietkau new_state == IEEE80211_STA_ASSOC && 10549c193de5SFelix Fietkau dev->drv->sta_assoc) 10559c193de5SFelix Fietkau dev->drv->sta_assoc(dev, vif, sta); 10569c193de5SFelix Fietkau 1057e28487eaSFelix Fietkau if (old_state == IEEE80211_STA_NONE && 1058e28487eaSFelix Fietkau new_state == IEEE80211_STA_NOTEXIST) 1059e28487eaSFelix Fietkau mt76_sta_remove(dev, vif, sta); 1060e28487eaSFelix Fietkau 1061e28487eaSFelix Fietkau return 0; 1062e28487eaSFelix Fietkau } 1063e28487eaSFelix Fietkau EXPORT_SYMBOL_GPL(mt76_sta_state); 10649313faacSFelix Fietkau 106543ba1922SFelix Fietkau void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 106643ba1922SFelix Fietkau struct ieee80211_sta *sta) 106743ba1922SFelix Fietkau { 106843ba1922SFelix Fietkau struct mt76_phy *phy = hw->priv; 106943ba1922SFelix Fietkau struct mt76_dev *dev = phy->dev; 107043ba1922SFelix Fietkau struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; 107143ba1922SFelix Fietkau 107243ba1922SFelix Fietkau mutex_lock(&dev->mutex); 107343ba1922SFelix Fietkau rcu_assign_pointer(dev->wcid[wcid->idx], NULL); 107443ba1922SFelix Fietkau mutex_unlock(&dev->mutex); 107543ba1922SFelix Fietkau } 107643ba1922SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove); 107743ba1922SFelix Fietkau 10789313faacSFelix Fietkau int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 10799313faacSFelix Fietkau int *dbm) 10809313faacSFelix Fietkau { 1081beaaeb6bSFelix Fietkau struct mt76_phy *phy = hw->priv; 1082beaaeb6bSFelix Fietkau int n_chains = hweight8(phy->antenna_mask); 108307cda406SFelix Fietkau int delta = mt76_tx_power_nss_delta(n_chains); 10849313faacSFelix Fietkau 108507cda406SFelix Fietkau *dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2); 10869313faacSFelix Fietkau 10879313faacSFelix Fietkau return 0; 10889313faacSFelix Fietkau } 10899313faacSFelix Fietkau EXPORT_SYMBOL_GPL(mt76_get_txpower); 1090e7173858SFelix Fietkau 1091e7173858SFelix Fietkau static void 1092e7173858SFelix Fietkau __mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) 1093e7173858SFelix Fietkau { 1094e7173858SFelix Fietkau if (vif->csa_active && ieee80211_csa_is_complete(vif)) 1095e7173858SFelix Fietkau ieee80211_csa_finish(vif); 1096e7173858SFelix Fietkau } 1097e7173858SFelix Fietkau 1098e7173858SFelix Fietkau void mt76_csa_finish(struct mt76_dev *dev) 1099e7173858SFelix Fietkau { 1100e7173858SFelix Fietkau if (!dev->csa_complete) 1101e7173858SFelix Fietkau return; 1102e7173858SFelix Fietkau 1103e7173858SFelix Fietkau ieee80211_iterate_active_interfaces_atomic(dev->hw, 1104e7173858SFelix Fietkau IEEE80211_IFACE_ITER_RESUME_ALL, 1105e7173858SFelix Fietkau __mt76_csa_finish, dev); 1106e7173858SFelix Fietkau 1107e7173858SFelix Fietkau dev->csa_complete = 0; 1108e7173858SFelix Fietkau } 1109e7173858SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_csa_finish); 1110e7173858SFelix Fietkau 1111e7173858SFelix Fietkau static void 1112e7173858SFelix Fietkau __mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif) 1113e7173858SFelix Fietkau { 1114e7173858SFelix Fietkau struct mt76_dev *dev = priv; 1115e7173858SFelix Fietkau 1116e7173858SFelix Fietkau if (!vif->csa_active) 1117e7173858SFelix Fietkau return; 1118e7173858SFelix Fietkau 1119e7173858SFelix Fietkau dev->csa_complete |= ieee80211_csa_is_complete(vif); 1120e7173858SFelix Fietkau } 1121e7173858SFelix Fietkau 1122e7173858SFelix Fietkau void mt76_csa_check(struct mt76_dev *dev) 1123e7173858SFelix Fietkau { 1124e7173858SFelix Fietkau ieee80211_iterate_active_interfaces_atomic(dev->hw, 1125e7173858SFelix Fietkau IEEE80211_IFACE_ITER_RESUME_ALL, 1126e7173858SFelix Fietkau __mt76_csa_check, dev); 1127e7173858SFelix Fietkau } 1128e7173858SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_csa_check); 112987d53103SStanislaw Gruszka 113087d53103SStanislaw Gruszka int 113187d53103SStanislaw Gruszka mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) 113287d53103SStanislaw Gruszka { 113387d53103SStanislaw Gruszka return 0; 113487d53103SStanislaw Gruszka } 113587d53103SStanislaw Gruszka EXPORT_SYMBOL_GPL(mt76_set_tim); 1136eadfd98fSLorenzo Bianconi 1137eadfd98fSLorenzo Bianconi void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) 1138eadfd98fSLorenzo Bianconi { 1139eadfd98fSLorenzo Bianconi struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 1140eadfd98fSLorenzo Bianconi int hdr_len = ieee80211_get_hdrlen_from_skb(skb); 1141eadfd98fSLorenzo Bianconi u8 *hdr, *pn = status->iv; 1142eadfd98fSLorenzo Bianconi 1143eadfd98fSLorenzo Bianconi __skb_push(skb, 8); 1144eadfd98fSLorenzo Bianconi memmove(skb->data, skb->data + 8, hdr_len); 1145eadfd98fSLorenzo Bianconi hdr = skb->data + hdr_len; 1146eadfd98fSLorenzo Bianconi 1147eadfd98fSLorenzo Bianconi hdr[0] = pn[5]; 1148eadfd98fSLorenzo Bianconi hdr[1] = pn[4]; 1149eadfd98fSLorenzo Bianconi hdr[2] = 0; 1150eadfd98fSLorenzo Bianconi hdr[3] = 0x20 | (key_id << 6); 1151eadfd98fSLorenzo Bianconi hdr[4] = pn[3]; 1152eadfd98fSLorenzo Bianconi hdr[5] = pn[2]; 1153eadfd98fSLorenzo Bianconi hdr[6] = pn[1]; 1154eadfd98fSLorenzo Bianconi hdr[7] = pn[0]; 1155eadfd98fSLorenzo Bianconi 1156eadfd98fSLorenzo Bianconi status->flag &= ~RX_FLAG_IV_STRIPPED; 1157eadfd98fSLorenzo Bianconi } 1158eadfd98fSLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_insert_ccmp_hdr); 1159d2679d65SLorenzo Bianconi 1160d2679d65SLorenzo Bianconi int mt76_get_rate(struct mt76_dev *dev, 1161d2679d65SLorenzo Bianconi struct ieee80211_supported_band *sband, 1162d2679d65SLorenzo Bianconi int idx, bool cck) 1163d2679d65SLorenzo Bianconi { 1164d2679d65SLorenzo Bianconi int i, offset = 0, len = sband->n_bitrates; 1165d2679d65SLorenzo Bianconi 1166d2679d65SLorenzo Bianconi if (cck) { 116796747a51SFelix Fietkau if (sband == &dev->phy.sband_5g.sband) 1168d2679d65SLorenzo Bianconi return 0; 1169d2679d65SLorenzo Bianconi 1170d2679d65SLorenzo Bianconi idx &= ~BIT(2); /* short preamble */ 117196747a51SFelix Fietkau } else if (sband == &dev->phy.sband_2g.sband) { 1172d2679d65SLorenzo Bianconi offset = 4; 1173d2679d65SLorenzo Bianconi } 1174d2679d65SLorenzo Bianconi 1175d2679d65SLorenzo Bianconi for (i = offset; i < len; i++) { 1176d2679d65SLorenzo Bianconi if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) 1177d2679d65SLorenzo Bianconi return i; 1178d2679d65SLorenzo Bianconi } 1179d2679d65SLorenzo Bianconi 1180d2679d65SLorenzo Bianconi return 0; 1181d2679d65SLorenzo Bianconi } 1182d2679d65SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_get_rate); 11838b8ab5c2SLorenzo Bianconi 11848b8ab5c2SLorenzo Bianconi void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 11858b8ab5c2SLorenzo Bianconi const u8 *mac) 11868b8ab5c2SLorenzo Bianconi { 1187011849e0SFelix Fietkau struct mt76_phy *phy = hw->priv; 11888b8ab5c2SLorenzo Bianconi 1189011849e0SFelix Fietkau set_bit(MT76_SCANNING, &phy->state); 11908b8ab5c2SLorenzo Bianconi } 11918b8ab5c2SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_sw_scan); 11928b8ab5c2SLorenzo Bianconi 11938b8ab5c2SLorenzo Bianconi void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 11948b8ab5c2SLorenzo Bianconi { 1195011849e0SFelix Fietkau struct mt76_phy *phy = hw->priv; 11968b8ab5c2SLorenzo Bianconi 1197011849e0SFelix Fietkau clear_bit(MT76_SCANNING, &phy->state); 11988b8ab5c2SLorenzo Bianconi } 11998b8ab5c2SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_sw_scan_complete); 1200e49c76d4SLorenzo Bianconi 1201e49c76d4SLorenzo Bianconi int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) 1202e49c76d4SLorenzo Bianconi { 1203beaaeb6bSFelix Fietkau struct mt76_phy *phy = hw->priv; 1204beaaeb6bSFelix Fietkau struct mt76_dev *dev = phy->dev; 1205e49c76d4SLorenzo Bianconi 1206e49c76d4SLorenzo Bianconi mutex_lock(&dev->mutex); 1207beaaeb6bSFelix Fietkau *tx_ant = phy->antenna_mask; 1208beaaeb6bSFelix Fietkau *rx_ant = phy->antenna_mask; 1209e49c76d4SLorenzo Bianconi mutex_unlock(&dev->mutex); 1210e49c76d4SLorenzo Bianconi 1211e49c76d4SLorenzo Bianconi return 0; 1212e49c76d4SLorenzo Bianconi } 1213e49c76d4SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_get_antenna); 1214