117f1de56SFelix Fietkau /* 217f1de56SFelix Fietkau * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 317f1de56SFelix Fietkau * 417f1de56SFelix Fietkau * Permission to use, copy, modify, and/or distribute this software for any 517f1de56SFelix Fietkau * purpose with or without fee is hereby granted, provided that the above 617f1de56SFelix Fietkau * copyright notice and this permission notice appear in all copies. 717f1de56SFelix Fietkau * 817f1de56SFelix Fietkau * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 917f1de56SFelix Fietkau * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1017f1de56SFelix Fietkau * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1117f1de56SFelix Fietkau * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1217f1de56SFelix Fietkau * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1317f1de56SFelix Fietkau * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1417f1de56SFelix Fietkau * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1517f1de56SFelix Fietkau */ 1617f1de56SFelix Fietkau #include <linux/of.h> 1717f1de56SFelix Fietkau #include "mt76.h" 1817f1de56SFelix Fietkau 1917f1de56SFelix Fietkau #define CHAN2G(_idx, _freq) { \ 2017f1de56SFelix Fietkau .band = NL80211_BAND_2GHZ, \ 2117f1de56SFelix Fietkau .center_freq = (_freq), \ 2217f1de56SFelix Fietkau .hw_value = (_idx), \ 2317f1de56SFelix Fietkau .max_power = 30, \ 2417f1de56SFelix Fietkau } 2517f1de56SFelix Fietkau 2617f1de56SFelix Fietkau #define CHAN5G(_idx, _freq) { \ 2717f1de56SFelix Fietkau .band = NL80211_BAND_5GHZ, \ 2817f1de56SFelix Fietkau .center_freq = (_freq), \ 2917f1de56SFelix Fietkau .hw_value = (_idx), \ 3017f1de56SFelix Fietkau .max_power = 30, \ 3117f1de56SFelix Fietkau } 3217f1de56SFelix Fietkau 3317f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_2ghz[] = { 3417f1de56SFelix Fietkau CHAN2G(1, 2412), 3517f1de56SFelix Fietkau CHAN2G(2, 2417), 3617f1de56SFelix Fietkau CHAN2G(3, 2422), 3717f1de56SFelix Fietkau CHAN2G(4, 2427), 3817f1de56SFelix Fietkau CHAN2G(5, 2432), 3917f1de56SFelix Fietkau CHAN2G(6, 2437), 4017f1de56SFelix Fietkau CHAN2G(7, 2442), 4117f1de56SFelix Fietkau CHAN2G(8, 2447), 4217f1de56SFelix Fietkau CHAN2G(9, 2452), 4317f1de56SFelix Fietkau CHAN2G(10, 2457), 4417f1de56SFelix Fietkau CHAN2G(11, 2462), 4517f1de56SFelix Fietkau CHAN2G(12, 2467), 4617f1de56SFelix Fietkau CHAN2G(13, 2472), 4717f1de56SFelix Fietkau CHAN2G(14, 2484), 4817f1de56SFelix Fietkau }; 4917f1de56SFelix Fietkau 5017f1de56SFelix Fietkau static const struct ieee80211_channel mt76_channels_5ghz[] = { 5117f1de56SFelix Fietkau CHAN5G(36, 5180), 5217f1de56SFelix Fietkau CHAN5G(40, 5200), 5317f1de56SFelix Fietkau CHAN5G(44, 5220), 5417f1de56SFelix Fietkau CHAN5G(48, 5240), 5517f1de56SFelix Fietkau 5617f1de56SFelix Fietkau CHAN5G(52, 5260), 5717f1de56SFelix Fietkau CHAN5G(56, 5280), 5817f1de56SFelix Fietkau CHAN5G(60, 5300), 5917f1de56SFelix Fietkau CHAN5G(64, 5320), 6017f1de56SFelix Fietkau 6117f1de56SFelix Fietkau CHAN5G(100, 5500), 6217f1de56SFelix Fietkau CHAN5G(104, 5520), 6317f1de56SFelix Fietkau CHAN5G(108, 5540), 6417f1de56SFelix Fietkau CHAN5G(112, 5560), 6517f1de56SFelix Fietkau CHAN5G(116, 5580), 6617f1de56SFelix Fietkau CHAN5G(120, 5600), 6717f1de56SFelix Fietkau CHAN5G(124, 5620), 6817f1de56SFelix Fietkau CHAN5G(128, 5640), 6917f1de56SFelix Fietkau CHAN5G(132, 5660), 7017f1de56SFelix Fietkau CHAN5G(136, 5680), 7117f1de56SFelix Fietkau CHAN5G(140, 5700), 7217f1de56SFelix Fietkau 7317f1de56SFelix Fietkau CHAN5G(149, 5745), 7417f1de56SFelix Fietkau CHAN5G(153, 5765), 7517f1de56SFelix Fietkau CHAN5G(157, 5785), 7617f1de56SFelix Fietkau CHAN5G(161, 5805), 7717f1de56SFelix Fietkau CHAN5G(165, 5825), 7817f1de56SFelix Fietkau }; 7917f1de56SFelix Fietkau 8017f1de56SFelix Fietkau static const struct ieee80211_tpt_blink mt76_tpt_blink[] = { 8117f1de56SFelix Fietkau { .throughput = 0 * 1024, .blink_time = 334 }, 8217f1de56SFelix Fietkau { .throughput = 1 * 1024, .blink_time = 260 }, 8317f1de56SFelix Fietkau { .throughput = 5 * 1024, .blink_time = 220 }, 8417f1de56SFelix Fietkau { .throughput = 10 * 1024, .blink_time = 190 }, 8517f1de56SFelix Fietkau { .throughput = 20 * 1024, .blink_time = 170 }, 8617f1de56SFelix Fietkau { .throughput = 50 * 1024, .blink_time = 150 }, 8717f1de56SFelix Fietkau { .throughput = 70 * 1024, .blink_time = 130 }, 8817f1de56SFelix Fietkau { .throughput = 100 * 1024, .blink_time = 110 }, 8917f1de56SFelix Fietkau { .throughput = 200 * 1024, .blink_time = 80 }, 9017f1de56SFelix Fietkau { .throughput = 300 * 1024, .blink_time = 50 }, 9117f1de56SFelix Fietkau }; 9217f1de56SFelix Fietkau 9317f1de56SFelix Fietkau static int mt76_led_init(struct mt76_dev *dev) 9417f1de56SFelix Fietkau { 9517f1de56SFelix Fietkau struct device_node *np = dev->dev->of_node; 9617f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 9717f1de56SFelix Fietkau int led_pin; 9817f1de56SFelix Fietkau 9917f1de56SFelix Fietkau if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set) 10017f1de56SFelix Fietkau return 0; 10117f1de56SFelix Fietkau 10217f1de56SFelix Fietkau snprintf(dev->led_name, sizeof(dev->led_name), 10317f1de56SFelix Fietkau "mt76-%s", wiphy_name(hw->wiphy)); 10417f1de56SFelix Fietkau 10517f1de56SFelix Fietkau dev->led_cdev.name = dev->led_name; 10617f1de56SFelix Fietkau dev->led_cdev.default_trigger = 10717f1de56SFelix Fietkau ieee80211_create_tpt_led_trigger(hw, 10817f1de56SFelix Fietkau IEEE80211_TPT_LEDTRIG_FL_RADIO, 10917f1de56SFelix Fietkau mt76_tpt_blink, 11017f1de56SFelix Fietkau ARRAY_SIZE(mt76_tpt_blink)); 11117f1de56SFelix Fietkau 11217f1de56SFelix Fietkau np = of_get_child_by_name(np, "led"); 11317f1de56SFelix Fietkau if (np) { 11417f1de56SFelix Fietkau if (!of_property_read_u32(np, "led-sources", &led_pin)) 11517f1de56SFelix Fietkau dev->led_pin = led_pin; 11617f1de56SFelix Fietkau dev->led_al = of_property_read_bool(np, "led-active-low"); 11717f1de56SFelix Fietkau } 11817f1de56SFelix Fietkau 11917f1de56SFelix Fietkau return devm_led_classdev_register(dev->dev, &dev->led_cdev); 12017f1de56SFelix Fietkau } 12117f1de56SFelix Fietkau 12217f1de56SFelix Fietkau static int 12317f1de56SFelix Fietkau mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, 12417f1de56SFelix Fietkau const struct ieee80211_channel *chan, int n_chan, 12517f1de56SFelix Fietkau struct ieee80211_rate *rates, int n_rates, bool vht) 12617f1de56SFelix Fietkau { 12717f1de56SFelix Fietkau struct ieee80211_supported_band *sband = &msband->sband; 12817f1de56SFelix Fietkau struct ieee80211_sta_ht_cap *ht_cap; 12917f1de56SFelix Fietkau struct ieee80211_sta_vht_cap *vht_cap; 13017f1de56SFelix Fietkau void *chanlist; 13117f1de56SFelix Fietkau u16 mcs_map; 13217f1de56SFelix Fietkau int size; 13317f1de56SFelix Fietkau 13417f1de56SFelix Fietkau size = n_chan * sizeof(*chan); 13517f1de56SFelix Fietkau chanlist = devm_kmemdup(dev->dev, chan, size, GFP_KERNEL); 13617f1de56SFelix Fietkau if (!chanlist) 13717f1de56SFelix Fietkau return -ENOMEM; 13817f1de56SFelix Fietkau 13917f1de56SFelix Fietkau msband->chan = devm_kzalloc(dev->dev, n_chan * sizeof(*msband->chan), 14017f1de56SFelix Fietkau GFP_KERNEL); 14117f1de56SFelix Fietkau if (!msband->chan) 14217f1de56SFelix Fietkau return -ENOMEM; 14317f1de56SFelix Fietkau 14417f1de56SFelix Fietkau sband->channels = chanlist; 14517f1de56SFelix Fietkau sband->n_channels = n_chan; 14617f1de56SFelix Fietkau sband->bitrates = rates; 14717f1de56SFelix Fietkau sband->n_bitrates = n_rates; 14817f1de56SFelix Fietkau dev->chandef.chan = &sband->channels[0]; 14917f1de56SFelix Fietkau 15017f1de56SFelix Fietkau ht_cap = &sband->ht_cap; 15117f1de56SFelix Fietkau ht_cap->ht_supported = true; 15217f1de56SFelix Fietkau ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 15317f1de56SFelix Fietkau IEEE80211_HT_CAP_GRN_FLD | 15417f1de56SFelix Fietkau IEEE80211_HT_CAP_SGI_20 | 15517f1de56SFelix Fietkau IEEE80211_HT_CAP_SGI_40 | 15617f1de56SFelix Fietkau IEEE80211_HT_CAP_TX_STBC | 15717f1de56SFelix Fietkau (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 15817f1de56SFelix Fietkau 15917f1de56SFelix Fietkau ht_cap->mcs.rx_mask[0] = 0xff; 16017f1de56SFelix Fietkau ht_cap->mcs.rx_mask[1] = 0xff; 16117f1de56SFelix Fietkau ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 16217f1de56SFelix Fietkau ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 16317f1de56SFelix Fietkau ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; 16417f1de56SFelix Fietkau 16517f1de56SFelix Fietkau if (!vht) 16617f1de56SFelix Fietkau return 0; 16717f1de56SFelix Fietkau 16817f1de56SFelix Fietkau vht_cap = &sband->vht_cap; 16917f1de56SFelix Fietkau vht_cap->vht_supported = true; 17017f1de56SFelix Fietkau 17117f1de56SFelix Fietkau mcs_map = (IEEE80211_VHT_MCS_SUPPORT_0_9 << (0 * 2)) | 17217f1de56SFelix Fietkau (IEEE80211_VHT_MCS_SUPPORT_0_9 << (1 * 2)) | 17317f1de56SFelix Fietkau (IEEE80211_VHT_MCS_NOT_SUPPORTED << (2 * 2)) | 17417f1de56SFelix Fietkau (IEEE80211_VHT_MCS_NOT_SUPPORTED << (3 * 2)) | 17517f1de56SFelix Fietkau (IEEE80211_VHT_MCS_NOT_SUPPORTED << (4 * 2)) | 17617f1de56SFelix Fietkau (IEEE80211_VHT_MCS_NOT_SUPPORTED << (5 * 2)) | 17717f1de56SFelix Fietkau (IEEE80211_VHT_MCS_NOT_SUPPORTED << (6 * 2)) | 17817f1de56SFelix Fietkau (IEEE80211_VHT_MCS_NOT_SUPPORTED << (7 * 2)); 17917f1de56SFelix Fietkau 18017f1de56SFelix Fietkau vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); 18117f1de56SFelix Fietkau vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); 18217f1de56SFelix Fietkau vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC | 18317f1de56SFelix Fietkau IEEE80211_VHT_CAP_TXSTBC | 18417f1de56SFelix Fietkau IEEE80211_VHT_CAP_RXSTBC_1 | 18517f1de56SFelix Fietkau IEEE80211_VHT_CAP_SHORT_GI_80; 18617f1de56SFelix Fietkau 18717f1de56SFelix Fietkau return 0; 18817f1de56SFelix Fietkau } 18917f1de56SFelix Fietkau 19017f1de56SFelix Fietkau static int 19117f1de56SFelix Fietkau mt76_init_sband_2g(struct mt76_dev *dev, struct ieee80211_rate *rates, 19217f1de56SFelix Fietkau int n_rates) 19317f1de56SFelix Fietkau { 19417f1de56SFelix Fietkau dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->sband_2g.sband; 19517f1de56SFelix Fietkau 19617f1de56SFelix Fietkau return mt76_init_sband(dev, &dev->sband_2g, 19717f1de56SFelix Fietkau mt76_channels_2ghz, 19817f1de56SFelix Fietkau ARRAY_SIZE(mt76_channels_2ghz), 19917f1de56SFelix Fietkau rates, n_rates, false); 20017f1de56SFelix Fietkau } 20117f1de56SFelix Fietkau 20217f1de56SFelix Fietkau static int 20317f1de56SFelix Fietkau mt76_init_sband_5g(struct mt76_dev *dev, struct ieee80211_rate *rates, 20417f1de56SFelix Fietkau int n_rates, bool vht) 20517f1de56SFelix Fietkau { 20617f1de56SFelix Fietkau dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->sband_5g.sband; 20717f1de56SFelix Fietkau 20817f1de56SFelix Fietkau return mt76_init_sband(dev, &dev->sband_5g, 20917f1de56SFelix Fietkau mt76_channels_5ghz, 21017f1de56SFelix Fietkau ARRAY_SIZE(mt76_channels_5ghz), 21117f1de56SFelix Fietkau rates, n_rates, vht); 21217f1de56SFelix Fietkau } 21317f1de56SFelix Fietkau 21417f1de56SFelix Fietkau static void 21517f1de56SFelix Fietkau mt76_check_sband(struct mt76_dev *dev, int band) 21617f1de56SFelix Fietkau { 21717f1de56SFelix Fietkau struct ieee80211_supported_band *sband = dev->hw->wiphy->bands[band]; 21817f1de56SFelix Fietkau bool found = false; 21917f1de56SFelix Fietkau int i; 22017f1de56SFelix Fietkau 22117f1de56SFelix Fietkau if (!sband) 22217f1de56SFelix Fietkau return; 22317f1de56SFelix Fietkau 22417f1de56SFelix Fietkau for (i = 0; i < sband->n_channels; i++) { 22517f1de56SFelix Fietkau if (sband->channels[i].flags & IEEE80211_CHAN_DISABLED) 22617f1de56SFelix Fietkau continue; 22717f1de56SFelix Fietkau 22817f1de56SFelix Fietkau found = true; 22917f1de56SFelix Fietkau break; 23017f1de56SFelix Fietkau } 23117f1de56SFelix Fietkau 23217f1de56SFelix Fietkau if (found) 23317f1de56SFelix Fietkau return; 23417f1de56SFelix Fietkau 23517f1de56SFelix Fietkau sband->n_channels = 0; 23617f1de56SFelix Fietkau dev->hw->wiphy->bands[band] = NULL; 23717f1de56SFelix Fietkau } 23817f1de56SFelix Fietkau 23917f1de56SFelix Fietkau int mt76_register_device(struct mt76_dev *dev, bool vht, 24017f1de56SFelix Fietkau struct ieee80211_rate *rates, int n_rates) 24117f1de56SFelix Fietkau { 24217f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 24317f1de56SFelix Fietkau struct wiphy *wiphy = hw->wiphy; 24417f1de56SFelix Fietkau int ret; 24517f1de56SFelix Fietkau 24617f1de56SFelix Fietkau dev_set_drvdata(dev->dev, dev); 24717f1de56SFelix Fietkau 24817f1de56SFelix Fietkau spin_lock_init(&dev->lock); 24917f1de56SFelix Fietkau spin_lock_init(&dev->cc_lock); 25017f1de56SFelix Fietkau INIT_LIST_HEAD(&dev->txwi_cache); 25117f1de56SFelix Fietkau 25217f1de56SFelix Fietkau SET_IEEE80211_DEV(hw, dev->dev); 25317f1de56SFelix Fietkau SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); 25417f1de56SFelix Fietkau 25517f1de56SFelix Fietkau wiphy->interface_modes = 25617f1de56SFelix Fietkau BIT(NL80211_IFTYPE_STATION) | 25717f1de56SFelix Fietkau BIT(NL80211_IFTYPE_AP) | 25817f1de56SFelix Fietkau #ifdef CONFIG_MAC80211_MESH 25917f1de56SFelix Fietkau BIT(NL80211_IFTYPE_MESH_POINT) | 26017f1de56SFelix Fietkau #endif 26117f1de56SFelix Fietkau BIT(NL80211_IFTYPE_ADHOC); 26217f1de56SFelix Fietkau 26317f1de56SFelix Fietkau wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; 26417f1de56SFelix Fietkau 26517f1de56SFelix Fietkau hw->txq_data_size = sizeof(struct mt76_txq); 26617f1de56SFelix Fietkau hw->max_tx_fragments = 16; 26717f1de56SFelix Fietkau 26817f1de56SFelix Fietkau ieee80211_hw_set(hw, SIGNAL_DBM); 26917f1de56SFelix Fietkau ieee80211_hw_set(hw, PS_NULLFUNC_STACK); 27017f1de56SFelix Fietkau ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); 27117f1de56SFelix Fietkau ieee80211_hw_set(hw, AMPDU_AGGREGATION); 27217f1de56SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); 27317f1de56SFelix Fietkau ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); 27417f1de56SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); 27517f1de56SFelix Fietkau ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); 27617f1de56SFelix Fietkau ieee80211_hw_set(hw, TX_AMSDU); 27717f1de56SFelix Fietkau ieee80211_hw_set(hw, TX_FRAG_LIST); 27817f1de56SFelix Fietkau ieee80211_hw_set(hw, MFP_CAPABLE); 27917f1de56SFelix Fietkau 28017f1de56SFelix Fietkau wiphy->flags |= WIPHY_FLAG_IBSS_RSN; 28117f1de56SFelix Fietkau 28217f1de56SFelix Fietkau if (dev->cap.has_2ghz) { 28317f1de56SFelix Fietkau ret = mt76_init_sband_2g(dev, rates, n_rates); 28417f1de56SFelix Fietkau if (ret) 28517f1de56SFelix Fietkau return ret; 28617f1de56SFelix Fietkau } 28717f1de56SFelix Fietkau 28817f1de56SFelix Fietkau if (dev->cap.has_5ghz) { 28917f1de56SFelix Fietkau ret = mt76_init_sband_5g(dev, rates + 4, n_rates - 4, vht); 29017f1de56SFelix Fietkau if (ret) 29117f1de56SFelix Fietkau return ret; 29217f1de56SFelix Fietkau } 29317f1de56SFelix Fietkau 29417f1de56SFelix Fietkau wiphy_read_of_freq_limits(dev->hw->wiphy); 29517f1de56SFelix Fietkau mt76_check_sband(dev, NL80211_BAND_2GHZ); 29617f1de56SFelix Fietkau mt76_check_sband(dev, NL80211_BAND_5GHZ); 29717f1de56SFelix Fietkau 29817f1de56SFelix Fietkau ret = mt76_led_init(dev); 29917f1de56SFelix Fietkau if (ret) 30017f1de56SFelix Fietkau return ret; 30117f1de56SFelix Fietkau 30217f1de56SFelix Fietkau return ieee80211_register_hw(hw); 30317f1de56SFelix Fietkau } 30417f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_register_device); 30517f1de56SFelix Fietkau 30617f1de56SFelix Fietkau void mt76_unregister_device(struct mt76_dev *dev) 30717f1de56SFelix Fietkau { 30817f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 30917f1de56SFelix Fietkau 31017f1de56SFelix Fietkau ieee80211_unregister_hw(hw); 31117f1de56SFelix Fietkau mt76_tx_free(dev); 31217f1de56SFelix Fietkau } 31317f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_unregister_device); 31417f1de56SFelix Fietkau 31517f1de56SFelix Fietkau void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) 31617f1de56SFelix Fietkau { 31717f1de56SFelix Fietkau if (!test_bit(MT76_STATE_RUNNING, &dev->state)) { 31817f1de56SFelix Fietkau dev_kfree_skb(skb); 31917f1de56SFelix Fietkau return; 32017f1de56SFelix Fietkau } 32117f1de56SFelix Fietkau 32217f1de56SFelix Fietkau __skb_queue_tail(&dev->rx_skb[q], skb); 32317f1de56SFelix Fietkau } 32417f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_rx); 32517f1de56SFelix Fietkau 32617f1de56SFelix Fietkau void mt76_set_channel(struct mt76_dev *dev) 32717f1de56SFelix Fietkau { 32817f1de56SFelix Fietkau struct ieee80211_hw *hw = dev->hw; 32917f1de56SFelix Fietkau struct cfg80211_chan_def *chandef = &hw->conf.chandef; 33017f1de56SFelix Fietkau struct mt76_channel_state *state; 33117f1de56SFelix Fietkau bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; 33217f1de56SFelix Fietkau 33317f1de56SFelix Fietkau if (dev->drv->update_survey) 33417f1de56SFelix Fietkau dev->drv->update_survey(dev); 33517f1de56SFelix Fietkau 33617f1de56SFelix Fietkau dev->chandef = *chandef; 33717f1de56SFelix Fietkau 33817f1de56SFelix Fietkau if (!offchannel) 33917f1de56SFelix Fietkau dev->main_chan = chandef->chan; 34017f1de56SFelix Fietkau 34117f1de56SFelix Fietkau if (chandef->chan != dev->main_chan) { 34217f1de56SFelix Fietkau state = mt76_channel_state(dev, chandef->chan); 34317f1de56SFelix Fietkau memset(state, 0, sizeof(*state)); 34417f1de56SFelix Fietkau } 34517f1de56SFelix Fietkau } 34617f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_set_channel); 34717f1de56SFelix Fietkau 34817f1de56SFelix Fietkau int mt76_get_survey(struct ieee80211_hw *hw, int idx, 34917f1de56SFelix Fietkau struct survey_info *survey) 35017f1de56SFelix Fietkau { 35117f1de56SFelix Fietkau struct mt76_dev *dev = hw->priv; 35217f1de56SFelix Fietkau struct mt76_sband *sband; 35317f1de56SFelix Fietkau struct ieee80211_channel *chan; 35417f1de56SFelix Fietkau struct mt76_channel_state *state; 35517f1de56SFelix Fietkau int ret = 0; 35617f1de56SFelix Fietkau 35717f1de56SFelix Fietkau if (idx == 0 && dev->drv->update_survey) 35817f1de56SFelix Fietkau dev->drv->update_survey(dev); 35917f1de56SFelix Fietkau 36017f1de56SFelix Fietkau sband = &dev->sband_2g; 36117f1de56SFelix Fietkau if (idx >= sband->sband.n_channels) { 36217f1de56SFelix Fietkau idx -= sband->sband.n_channels; 36317f1de56SFelix Fietkau sband = &dev->sband_5g; 36417f1de56SFelix Fietkau } 36517f1de56SFelix Fietkau 36617f1de56SFelix Fietkau if (idx >= sband->sband.n_channels) 36717f1de56SFelix Fietkau return -ENOENT; 36817f1de56SFelix Fietkau 36917f1de56SFelix Fietkau chan = &sband->sband.channels[idx]; 37017f1de56SFelix Fietkau state = mt76_channel_state(dev, chan); 37117f1de56SFelix Fietkau 37217f1de56SFelix Fietkau memset(survey, 0, sizeof(*survey)); 37317f1de56SFelix Fietkau survey->channel = chan; 37417f1de56SFelix Fietkau survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY; 37517f1de56SFelix Fietkau if (chan == dev->main_chan) 37617f1de56SFelix Fietkau survey->filled |= SURVEY_INFO_IN_USE; 37717f1de56SFelix Fietkau 37817f1de56SFelix Fietkau spin_lock_bh(&dev->cc_lock); 37917f1de56SFelix Fietkau survey->time = div_u64(state->cc_active, 1000); 38017f1de56SFelix Fietkau survey->time_busy = div_u64(state->cc_busy, 1000); 38117f1de56SFelix Fietkau spin_unlock_bh(&dev->cc_lock); 38217f1de56SFelix Fietkau 38317f1de56SFelix Fietkau return ret; 38417f1de56SFelix Fietkau } 38517f1de56SFelix Fietkau EXPORT_SYMBOL_GPL(mt76_get_survey); 38617f1de56SFelix Fietkau 387*4e34249eSFelix Fietkau static void 388*4e34249eSFelix Fietkau mt76_rx_convert(struct sk_buff *skb) 389*4e34249eSFelix Fietkau { 390*4e34249eSFelix Fietkau struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 391*4e34249eSFelix Fietkau struct mt76_rx_status mstat; 392*4e34249eSFelix Fietkau 393*4e34249eSFelix Fietkau mstat = *((struct mt76_rx_status *) skb->cb); 394*4e34249eSFelix Fietkau memset(status, 0, sizeof(*status)); 395*4e34249eSFelix Fietkau 396*4e34249eSFelix Fietkau status->flag = mstat.flag; 397*4e34249eSFelix Fietkau status->freq = mstat.freq; 398*4e34249eSFelix Fietkau status->enc_flags = mstat.enc_flags; 399*4e34249eSFelix Fietkau status->encoding = mstat.encoding; 400*4e34249eSFelix Fietkau status->bw = mstat.bw; 401*4e34249eSFelix Fietkau status->rate_idx = mstat.rate_idx; 402*4e34249eSFelix Fietkau status->nss = mstat.nss; 403*4e34249eSFelix Fietkau status->band = mstat.band; 404*4e34249eSFelix Fietkau status->signal = mstat.signal; 405*4e34249eSFelix Fietkau status->chains = mstat.chains; 406*4e34249eSFelix Fietkau 407*4e34249eSFelix Fietkau BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb)); 408*4e34249eSFelix Fietkau BUILD_BUG_ON(sizeof(status->chain_signal) != sizeof(mstat.chain_signal)); 409*4e34249eSFelix Fietkau memcpy(status->chain_signal, mstat.chain_signal, sizeof(mstat.chain_signal)); 410*4e34249eSFelix Fietkau } 411*4e34249eSFelix Fietkau 41217f1de56SFelix Fietkau void mt76_rx_complete(struct mt76_dev *dev, enum mt76_rxq_id q) 41317f1de56SFelix Fietkau { 41417f1de56SFelix Fietkau struct sk_buff *skb; 41517f1de56SFelix Fietkau 416*4e34249eSFelix Fietkau while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) { 417*4e34249eSFelix Fietkau mt76_rx_convert(skb); 41817f1de56SFelix Fietkau ieee80211_rx_napi(dev->hw, NULL, skb, &dev->napi[q]); 41917f1de56SFelix Fietkau } 420*4e34249eSFelix Fietkau } 421