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