1c8846e10SFelix Fietkau /* SPDX-License-Identifier: ISC */ 2c8846e10SFelix Fietkau 3c8846e10SFelix Fietkau #include <linux/etherdevice.h> 4c8846e10SFelix Fietkau #include <linux/platform_device.h> 5c8846e10SFelix Fietkau #include <linux/pci.h> 6c8846e10SFelix Fietkau #include <linux/module.h> 7c8846e10SFelix Fietkau #include "mt7603.h" 8c8846e10SFelix Fietkau #include "eeprom.h" 9c8846e10SFelix Fietkau 10c8846e10SFelix Fietkau static int 11c8846e10SFelix Fietkau mt7603_start(struct ieee80211_hw *hw) 12c8846e10SFelix Fietkau { 13c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 14c8846e10SFelix Fietkau 15c8846e10SFelix Fietkau mt7603_mac_start(dev); 16c8846e10SFelix Fietkau dev->survey_time = ktime_get_boottime(); 17c8846e10SFelix Fietkau set_bit(MT76_STATE_RUNNING, &dev->mt76.state); 18c8846e10SFelix Fietkau mt7603_mac_work(&dev->mac_work.work); 19c8846e10SFelix Fietkau 20c8846e10SFelix Fietkau return 0; 21c8846e10SFelix Fietkau } 22c8846e10SFelix Fietkau 23c8846e10SFelix Fietkau static void 24c8846e10SFelix Fietkau mt7603_stop(struct ieee80211_hw *hw) 25c8846e10SFelix Fietkau { 26c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 27c8846e10SFelix Fietkau 28c8846e10SFelix Fietkau clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); 29c8846e10SFelix Fietkau cancel_delayed_work_sync(&dev->mac_work); 30c8846e10SFelix Fietkau mt7603_mac_stop(dev); 31c8846e10SFelix Fietkau } 32c8846e10SFelix Fietkau 33c8846e10SFelix Fietkau static int 34c8846e10SFelix Fietkau mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 35c8846e10SFelix Fietkau { 36c8846e10SFelix Fietkau struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; 37c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 38c8846e10SFelix Fietkau struct mt76_txq *mtxq; 39c8846e10SFelix Fietkau u8 bc_addr[ETH_ALEN]; 40c8846e10SFelix Fietkau int idx; 41c8846e10SFelix Fietkau int ret = 0; 42c8846e10SFelix Fietkau 43c8846e10SFelix Fietkau mutex_lock(&dev->mt76.mutex); 44c8846e10SFelix Fietkau 45c8846e10SFelix Fietkau mvif->idx = ffs(~dev->vif_mask) - 1; 46c8846e10SFelix Fietkau if (mvif->idx >= MT7603_MAX_INTERFACES) { 47c8846e10SFelix Fietkau ret = -ENOSPC; 48c8846e10SFelix Fietkau goto out; 49c8846e10SFelix Fietkau } 50c8846e10SFelix Fietkau 51c8846e10SFelix Fietkau mt76_wr(dev, MT_MAC_ADDR0(mvif->idx), 52c8846e10SFelix Fietkau get_unaligned_le32(vif->addr)); 53c8846e10SFelix Fietkau mt76_wr(dev, MT_MAC_ADDR1(mvif->idx), 54c8846e10SFelix Fietkau (get_unaligned_le16(vif->addr + 4) | 55c8846e10SFelix Fietkau MT_MAC_ADDR1_VALID)); 56c8846e10SFelix Fietkau 57c8846e10SFelix Fietkau if (vif->type == NL80211_IFTYPE_AP) { 58c8846e10SFelix Fietkau mt76_wr(dev, MT_BSSID0(mvif->idx), 59c8846e10SFelix Fietkau get_unaligned_le32(vif->addr)); 60c8846e10SFelix Fietkau mt76_wr(dev, MT_BSSID1(mvif->idx), 61c8846e10SFelix Fietkau (get_unaligned_le16(vif->addr + 4) | 62c8846e10SFelix Fietkau MT_BSSID1_VALID)); 63c8846e10SFelix Fietkau } 64c8846e10SFelix Fietkau 65c8846e10SFelix Fietkau idx = MT7603_WTBL_RESERVED - 1 - mvif->idx; 66c8846e10SFelix Fietkau dev->vif_mask |= BIT(mvif->idx); 67c8846e10SFelix Fietkau mvif->sta.wcid.idx = idx; 68c8846e10SFelix Fietkau mvif->sta.wcid.hw_key_idx = -1; 69c8846e10SFelix Fietkau 70c8846e10SFelix Fietkau eth_broadcast_addr(bc_addr); 71c8846e10SFelix Fietkau mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr); 72c8846e10SFelix Fietkau 73c8846e10SFelix Fietkau mtxq = (struct mt76_txq *)vif->txq->drv_priv; 74c8846e10SFelix Fietkau mtxq->wcid = &mvif->sta.wcid; 75c8846e10SFelix Fietkau mt76_txq_init(&dev->mt76, vif->txq); 76c8846e10SFelix Fietkau rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); 77c8846e10SFelix Fietkau 78c8846e10SFelix Fietkau out: 79c8846e10SFelix Fietkau mutex_unlock(&dev->mt76.mutex); 80c8846e10SFelix Fietkau 81c8846e10SFelix Fietkau return ret; 82c8846e10SFelix Fietkau } 83c8846e10SFelix Fietkau 84c8846e10SFelix Fietkau static void 85c8846e10SFelix Fietkau mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 86c8846e10SFelix Fietkau { 87c8846e10SFelix Fietkau struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; 88c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 89c8846e10SFelix Fietkau int idx = mvif->sta.wcid.idx; 90c8846e10SFelix Fietkau 91c8846e10SFelix Fietkau mt76_wr(dev, MT_MAC_ADDR0(mvif->idx), 0); 92c8846e10SFelix Fietkau mt76_wr(dev, MT_MAC_ADDR1(mvif->idx), 0); 93c8846e10SFelix Fietkau mt76_wr(dev, MT_BSSID0(mvif->idx), 0); 94c8846e10SFelix Fietkau mt76_wr(dev, MT_BSSID1(mvif->idx), 0); 95c8846e10SFelix Fietkau mt7603_beacon_set_timer(dev, mvif->idx, 0); 96c8846e10SFelix Fietkau 97c8846e10SFelix Fietkau rcu_assign_pointer(dev->mt76.wcid[idx], NULL); 98c8846e10SFelix Fietkau mt76_txq_remove(&dev->mt76, vif->txq); 99c8846e10SFelix Fietkau 100c8846e10SFelix Fietkau mutex_lock(&dev->mt76.mutex); 101c8846e10SFelix Fietkau dev->vif_mask &= ~BIT(mvif->idx); 102c8846e10SFelix Fietkau mutex_unlock(&dev->mt76.mutex); 103c8846e10SFelix Fietkau } 104c8846e10SFelix Fietkau 105c8846e10SFelix Fietkau static void 106c8846e10SFelix Fietkau mt7603_init_edcca(struct mt7603_dev *dev) 107c8846e10SFelix Fietkau { 108c8846e10SFelix Fietkau /* Set lower signal level to -65dBm */ 109c8846e10SFelix Fietkau mt76_rmw_field(dev, MT_RXTD(8), MT_RXTD_8_LOWER_SIGNAL, 0x23); 110c8846e10SFelix Fietkau 111c8846e10SFelix Fietkau /* clear previous energy detect monitor results */ 112c8846e10SFelix Fietkau mt76_rr(dev, MT_MIB_STAT_ED); 113c8846e10SFelix Fietkau 114c8846e10SFelix Fietkau if (dev->ed_monitor) 115c8846e10SFelix Fietkau mt76_set(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME); 116c8846e10SFelix Fietkau else 117c8846e10SFelix Fietkau mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME); 118c8846e10SFelix Fietkau 119c8846e10SFelix Fietkau dev->ed_strict_mode = 0xff; 120c8846e10SFelix Fietkau dev->ed_strong_signal = 0; 121c8846e10SFelix Fietkau dev->ed_time = ktime_get_boottime(); 122c8846e10SFelix Fietkau 123c8846e10SFelix Fietkau mt7603_edcca_set_strict(dev, false); 124c8846e10SFelix Fietkau } 125c8846e10SFelix Fietkau 126c8846e10SFelix Fietkau static int 127c8846e10SFelix Fietkau mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) 128c8846e10SFelix Fietkau { 129c8846e10SFelix Fietkau u8 *rssi_data = (u8 *)dev->mt76.eeprom.data; 130c8846e10SFelix Fietkau int idx, ret; 131c8846e10SFelix Fietkau u8 bw = MT_BW_20; 132c8846e10SFelix Fietkau bool failed = false; 133c8846e10SFelix Fietkau 134c8846e10SFelix Fietkau cancel_delayed_work_sync(&dev->mac_work); 135c8846e10SFelix Fietkau 136c8846e10SFelix Fietkau mutex_lock(&dev->mt76.mutex); 137c8846e10SFelix Fietkau set_bit(MT76_RESET, &dev->mt76.state); 138c8846e10SFelix Fietkau 139c8846e10SFelix Fietkau mt76_set_channel(&dev->mt76); 140c8846e10SFelix Fietkau mt7603_mac_stop(dev); 141c8846e10SFelix Fietkau 142c8846e10SFelix Fietkau if (def->width == NL80211_CHAN_WIDTH_40) 143c8846e10SFelix Fietkau bw = MT_BW_40; 144c8846e10SFelix Fietkau 145c8846e10SFelix Fietkau dev->mt76.chandef = *def; 146c8846e10SFelix Fietkau mt76_rmw_field(dev, MT_AGG_BWCR, MT_AGG_BWCR_BW, bw); 147c8846e10SFelix Fietkau ret = mt7603_mcu_set_channel(dev); 148c8846e10SFelix Fietkau if (ret) { 149c8846e10SFelix Fietkau failed = true; 150c8846e10SFelix Fietkau goto out; 151c8846e10SFelix Fietkau } 152c8846e10SFelix Fietkau 153c8846e10SFelix Fietkau if (def->chan->band == NL80211_BAND_5GHZ) { 154c8846e10SFelix Fietkau idx = 1; 155c8846e10SFelix Fietkau rssi_data += MT_EE_RSSI_OFFSET_5G; 156c8846e10SFelix Fietkau } else { 157c8846e10SFelix Fietkau idx = 0; 158c8846e10SFelix Fietkau rssi_data += MT_EE_RSSI_OFFSET_2G; 159c8846e10SFelix Fietkau } 160c8846e10SFelix Fietkau 161c8846e10SFelix Fietkau memcpy(dev->rssi_offset, rssi_data, sizeof(dev->rssi_offset)); 162c8846e10SFelix Fietkau 163c8846e10SFelix Fietkau idx |= (def->chan - 164c8846e10SFelix Fietkau mt76_hw(dev)->wiphy->bands[def->chan->band]->channels) << 1; 165c8846e10SFelix Fietkau mt76_wr(dev, MT_WF_RMAC_CH_FREQ, idx); 166c8846e10SFelix Fietkau mt7603_mac_set_timing(dev); 167c8846e10SFelix Fietkau mt7603_mac_start(dev); 168c8846e10SFelix Fietkau 169c8846e10SFelix Fietkau clear_bit(MT76_RESET, &dev->mt76.state); 170c8846e10SFelix Fietkau 171c8846e10SFelix Fietkau mt76_txq_schedule_all(&dev->mt76); 172c8846e10SFelix Fietkau 173c8846e10SFelix Fietkau ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, 174c8846e10SFelix Fietkau MT7603_WATCHDOG_TIME); 175c8846e10SFelix Fietkau 176c8846e10SFelix Fietkau /* reset channel stats */ 177c8846e10SFelix Fietkau mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_READ_CLR_DIS); 178c8846e10SFelix Fietkau mt76_set(dev, MT_MIB_CTL, 179c8846e10SFelix Fietkau MT_MIB_CTL_CCA_NAV_TX | MT_MIB_CTL_PSCCA_TIME); 180c8846e10SFelix Fietkau mt76_rr(dev, MT_MIB_STAT_PSCCA); 181c8846e10SFelix Fietkau mt7603_cca_stats_reset(dev); 182c8846e10SFelix Fietkau 183c8846e10SFelix Fietkau dev->survey_time = ktime_get_boottime(); 184c8846e10SFelix Fietkau 185c8846e10SFelix Fietkau mt7603_init_edcca(dev); 186c8846e10SFelix Fietkau 187c8846e10SFelix Fietkau out: 188c8846e10SFelix Fietkau mutex_unlock(&dev->mt76.mutex); 189c8846e10SFelix Fietkau 190c8846e10SFelix Fietkau if (failed) 191c8846e10SFelix Fietkau mt7603_mac_work(&dev->mac_work.work); 192c8846e10SFelix Fietkau 193c8846e10SFelix Fietkau return ret; 194c8846e10SFelix Fietkau } 195c8846e10SFelix Fietkau 196c8846e10SFelix Fietkau static int 197c8846e10SFelix Fietkau mt7603_config(struct ieee80211_hw *hw, u32 changed) 198c8846e10SFelix Fietkau { 199c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 200c8846e10SFelix Fietkau int ret = 0; 201c8846e10SFelix Fietkau 202c8846e10SFelix Fietkau if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | 203c8846e10SFelix Fietkau IEEE80211_CONF_CHANGE_POWER)) 204c8846e10SFelix Fietkau ret = mt7603_set_channel(dev, &hw->conf.chandef); 205c8846e10SFelix Fietkau 206c8846e10SFelix Fietkau if (changed & IEEE80211_CONF_CHANGE_MONITOR) { 207c8846e10SFelix Fietkau mutex_lock(&dev->mt76.mutex); 208c8846e10SFelix Fietkau 209c8846e10SFelix Fietkau if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) 210c8846e10SFelix Fietkau dev->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; 211c8846e10SFelix Fietkau else 212c8846e10SFelix Fietkau dev->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; 213c8846e10SFelix Fietkau 214c8846e10SFelix Fietkau mt76_wr(dev, MT_WF_RFCR, dev->rxfilter); 215c8846e10SFelix Fietkau 216c8846e10SFelix Fietkau mutex_unlock(&dev->mt76.mutex); 217c8846e10SFelix Fietkau } 218c8846e10SFelix Fietkau 219c8846e10SFelix Fietkau return ret; 220c8846e10SFelix Fietkau } 221c8846e10SFelix Fietkau 222c8846e10SFelix Fietkau static void 223c8846e10SFelix Fietkau mt7603_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, 224c8846e10SFelix Fietkau unsigned int *total_flags, u64 multicast) 225c8846e10SFelix Fietkau { 226c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 227c8846e10SFelix Fietkau u32 flags = 0; 228c8846e10SFelix Fietkau 229c8846e10SFelix Fietkau #define MT76_FILTER(_flag, _hw) do { \ 230c8846e10SFelix Fietkau flags |= *total_flags & FIF_##_flag; \ 231c8846e10SFelix Fietkau dev->rxfilter &= ~(_hw); \ 232c8846e10SFelix Fietkau dev->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ 233c8846e10SFelix Fietkau } while (0) 234c8846e10SFelix Fietkau 235c8846e10SFelix Fietkau dev->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | 236c8846e10SFelix Fietkau MT_WF_RFCR_DROP_OTHER_BEACON | 237c8846e10SFelix Fietkau MT_WF_RFCR_DROP_FRAME_REPORT | 238c8846e10SFelix Fietkau MT_WF_RFCR_DROP_PROBEREQ | 239c8846e10SFelix Fietkau MT_WF_RFCR_DROP_MCAST_FILTERED | 240c8846e10SFelix Fietkau MT_WF_RFCR_DROP_MCAST | 241c8846e10SFelix Fietkau MT_WF_RFCR_DROP_BCAST | 242c8846e10SFelix Fietkau MT_WF_RFCR_DROP_DUPLICATE | 243c8846e10SFelix Fietkau MT_WF_RFCR_DROP_A2_BSSID | 244c8846e10SFelix Fietkau MT_WF_RFCR_DROP_UNWANTED_CTL | 245c8846e10SFelix Fietkau MT_WF_RFCR_DROP_STBC_MULTI); 246c8846e10SFelix Fietkau 247c8846e10SFelix Fietkau MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | 248c8846e10SFelix Fietkau MT_WF_RFCR_DROP_A3_MAC | 249c8846e10SFelix Fietkau MT_WF_RFCR_DROP_A3_BSSID); 250c8846e10SFelix Fietkau 251c8846e10SFelix Fietkau MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL); 252c8846e10SFelix Fietkau 253c8846e10SFelix Fietkau MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | 254c8846e10SFelix Fietkau MT_WF_RFCR_DROP_RTS | 255c8846e10SFelix Fietkau MT_WF_RFCR_DROP_CTL_RSV | 256c8846e10SFelix Fietkau MT_WF_RFCR_DROP_NDPA); 257c8846e10SFelix Fietkau 258c8846e10SFelix Fietkau *total_flags = flags; 259c8846e10SFelix Fietkau mt76_wr(dev, MT_WF_RFCR, dev->rxfilter); 260c8846e10SFelix Fietkau } 261c8846e10SFelix Fietkau 262c8846e10SFelix Fietkau static void 263c8846e10SFelix Fietkau mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 264c8846e10SFelix Fietkau struct ieee80211_bss_conf *info, u32 changed) 265c8846e10SFelix Fietkau { 266c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 267c8846e10SFelix Fietkau struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; 268c8846e10SFelix Fietkau 269c8846e10SFelix Fietkau mutex_lock(&dev->mt76.mutex); 270c8846e10SFelix Fietkau 271c8846e10SFelix Fietkau if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID)) { 272c8846e10SFelix Fietkau if (info->assoc || info->ibss_joined) { 273c8846e10SFelix Fietkau mt76_wr(dev, MT_BSSID0(mvif->idx), 274c8846e10SFelix Fietkau get_unaligned_le32(info->bssid)); 275c8846e10SFelix Fietkau mt76_wr(dev, MT_BSSID1(mvif->idx), 276c8846e10SFelix Fietkau (get_unaligned_le16(info->bssid + 4) | 277c8846e10SFelix Fietkau MT_BSSID1_VALID)); 278c8846e10SFelix Fietkau } else { 279c8846e10SFelix Fietkau mt76_wr(dev, MT_BSSID0(mvif->idx), 0); 280c8846e10SFelix Fietkau mt76_wr(dev, MT_BSSID1(mvif->idx), 0); 281c8846e10SFelix Fietkau } 282c8846e10SFelix Fietkau } 283c8846e10SFelix Fietkau 284c8846e10SFelix Fietkau if (changed & BSS_CHANGED_ERP_SLOT) { 285c8846e10SFelix Fietkau int slottime = info->use_short_slot ? 9 : 20; 286c8846e10SFelix Fietkau 287c8846e10SFelix Fietkau if (slottime != dev->slottime) { 288c8846e10SFelix Fietkau dev->slottime = slottime; 289c8846e10SFelix Fietkau mt7603_mac_set_timing(dev); 290c8846e10SFelix Fietkau } 291c8846e10SFelix Fietkau } 292c8846e10SFelix Fietkau 293c8846e10SFelix Fietkau if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT)) { 294c8846e10SFelix Fietkau int beacon_int = !!info->enable_beacon * info->beacon_int; 295c8846e10SFelix Fietkau 296c8846e10SFelix Fietkau tasklet_disable(&dev->pre_tbtt_tasklet); 297c8846e10SFelix Fietkau mt7603_beacon_set_timer(dev, mvif->idx, beacon_int); 298c8846e10SFelix Fietkau tasklet_enable(&dev->pre_tbtt_tasklet); 299c8846e10SFelix Fietkau } 300c8846e10SFelix Fietkau 301c8846e10SFelix Fietkau mutex_unlock(&dev->mt76.mutex); 302c8846e10SFelix Fietkau } 303c8846e10SFelix Fietkau 304c8846e10SFelix Fietkau int 305c8846e10SFelix Fietkau mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, 306c8846e10SFelix Fietkau struct ieee80211_sta *sta) 307c8846e10SFelix Fietkau { 308c8846e10SFelix Fietkau struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 309c8846e10SFelix Fietkau struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; 310c8846e10SFelix Fietkau struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; 311c8846e10SFelix Fietkau int idx; 312c8846e10SFelix Fietkau int ret = 0; 313c8846e10SFelix Fietkau 314c8846e10SFelix Fietkau idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7603_WTBL_STA - 1); 315c8846e10SFelix Fietkau if (idx < 0) 316c8846e10SFelix Fietkau return -ENOSPC; 317c8846e10SFelix Fietkau 318c8846e10SFelix Fietkau __skb_queue_head_init(&msta->psq); 319c8846e10SFelix Fietkau msta->ps = ~0; 320c8846e10SFelix Fietkau msta->smps = ~0; 321c8846e10SFelix Fietkau msta->wcid.sta = 1; 322c8846e10SFelix Fietkau msta->wcid.idx = idx; 323c8846e10SFelix Fietkau mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr); 324c8846e10SFelix Fietkau mt7603_wtbl_set_ps(dev, msta, false); 325c8846e10SFelix Fietkau 326c8846e10SFelix Fietkau if (vif->type == NL80211_IFTYPE_AP) 327c8846e10SFelix Fietkau set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags); 328c8846e10SFelix Fietkau 329c8846e10SFelix Fietkau return ret; 330c8846e10SFelix Fietkau } 331c8846e10SFelix Fietkau 332c8846e10SFelix Fietkau void 333c8846e10SFelix Fietkau mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, 334c8846e10SFelix Fietkau struct ieee80211_sta *sta) 335c8846e10SFelix Fietkau { 336c8846e10SFelix Fietkau struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 337c8846e10SFelix Fietkau 338c8846e10SFelix Fietkau mt7603_wtbl_update_cap(dev, sta); 339c8846e10SFelix Fietkau } 340c8846e10SFelix Fietkau 341c8846e10SFelix Fietkau void 342c8846e10SFelix Fietkau mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, 343c8846e10SFelix Fietkau struct ieee80211_sta *sta) 344c8846e10SFelix Fietkau { 345c8846e10SFelix Fietkau struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 346c8846e10SFelix Fietkau struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; 347c8846e10SFelix Fietkau struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; 348c8846e10SFelix Fietkau 349c8846e10SFelix Fietkau spin_lock_bh(&dev->ps_lock); 350c8846e10SFelix Fietkau __skb_queue_purge(&msta->psq); 351c8846e10SFelix Fietkau mt7603_filter_tx(dev, wcid->idx, true); 352c8846e10SFelix Fietkau spin_unlock_bh(&dev->ps_lock); 353c8846e10SFelix Fietkau 354c8846e10SFelix Fietkau mt7603_wtbl_clear(dev, wcid->idx); 355c8846e10SFelix Fietkau } 356c8846e10SFelix Fietkau 357c8846e10SFelix Fietkau static void 358c8846e10SFelix Fietkau mt7603_ps_tx_list(struct mt7603_dev *dev, struct sk_buff_head *list) 359c8846e10SFelix Fietkau { 360c8846e10SFelix Fietkau struct sk_buff *skb; 361c8846e10SFelix Fietkau 362c8846e10SFelix Fietkau while ((skb = __skb_dequeue(list)) != NULL) 363c8846e10SFelix Fietkau mt76_tx_queue_skb_raw(dev, skb_get_queue_mapping(skb), 364c8846e10SFelix Fietkau skb, 0); 365c8846e10SFelix Fietkau } 366c8846e10SFelix Fietkau 367c8846e10SFelix Fietkau void 368c8846e10SFelix Fietkau mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) 369c8846e10SFelix Fietkau { 370c8846e10SFelix Fietkau struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 371c8846e10SFelix Fietkau struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; 372c8846e10SFelix Fietkau struct sk_buff_head list; 373c8846e10SFelix Fietkau 374c8846e10SFelix Fietkau mt76_stop_tx_queues(&dev->mt76, sta, false); 375c8846e10SFelix Fietkau mt7603_wtbl_set_ps(dev, msta, ps); 376c8846e10SFelix Fietkau if (ps) 377c8846e10SFelix Fietkau return; 378c8846e10SFelix Fietkau 379c8846e10SFelix Fietkau __skb_queue_head_init(&list); 380c8846e10SFelix Fietkau 381c8846e10SFelix Fietkau spin_lock_bh(&dev->ps_lock); 382c8846e10SFelix Fietkau skb_queue_splice_tail_init(&msta->psq, &list); 383c8846e10SFelix Fietkau spin_unlock_bh(&dev->ps_lock); 384c8846e10SFelix Fietkau 385c8846e10SFelix Fietkau mt7603_ps_tx_list(dev, &list); 386c8846e10SFelix Fietkau } 387c8846e10SFelix Fietkau 388c8846e10SFelix Fietkau static void 389c8846e10SFelix Fietkau mt7603_release_buffered_frames(struct ieee80211_hw *hw, 390c8846e10SFelix Fietkau struct ieee80211_sta *sta, 391c8846e10SFelix Fietkau u16 tids, int nframes, 392c8846e10SFelix Fietkau enum ieee80211_frame_release_type reason, 393c8846e10SFelix Fietkau bool more_data) 394c8846e10SFelix Fietkau { 395c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 396c8846e10SFelix Fietkau struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; 397c8846e10SFelix Fietkau struct sk_buff_head list; 398c8846e10SFelix Fietkau struct sk_buff *skb, *tmp; 399c8846e10SFelix Fietkau 400c8846e10SFelix Fietkau __skb_queue_head_init(&list); 401c8846e10SFelix Fietkau 402c8846e10SFelix Fietkau spin_lock_bh(&dev->ps_lock); 403c8846e10SFelix Fietkau skb_queue_walk_safe(&msta->psq, skb, tmp) { 404c8846e10SFelix Fietkau if (!nframes) 405c8846e10SFelix Fietkau break; 406c8846e10SFelix Fietkau 407c8846e10SFelix Fietkau if (!(tids & BIT(skb->priority))) 408c8846e10SFelix Fietkau continue; 409c8846e10SFelix Fietkau 410c8846e10SFelix Fietkau skb_set_queue_mapping(skb, MT_TXQ_PSD); 411c8846e10SFelix Fietkau __skb_unlink(skb, &msta->psq); 412c8846e10SFelix Fietkau __skb_queue_tail(&list, skb); 413c8846e10SFelix Fietkau nframes--; 414c8846e10SFelix Fietkau } 415c8846e10SFelix Fietkau spin_unlock_bh(&dev->ps_lock); 416c8846e10SFelix Fietkau 417c8846e10SFelix Fietkau mt7603_ps_tx_list(dev, &list); 418c8846e10SFelix Fietkau 419c8846e10SFelix Fietkau if (nframes) 420c8846e10SFelix Fietkau mt76_release_buffered_frames(hw, sta, tids, nframes, reason, 421c8846e10SFelix Fietkau more_data); 422c8846e10SFelix Fietkau } 423c8846e10SFelix Fietkau 424c8846e10SFelix Fietkau static int 425c8846e10SFelix Fietkau mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 426c8846e10SFelix Fietkau struct ieee80211_vif *vif, struct ieee80211_sta *sta, 427c8846e10SFelix Fietkau struct ieee80211_key_conf *key) 428c8846e10SFelix Fietkau { 429c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 430c8846e10SFelix Fietkau struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; 431c8846e10SFelix Fietkau struct mt7603_sta *msta = sta ? (struct mt7603_sta *)sta->drv_priv : 432c8846e10SFelix Fietkau &mvif->sta; 433c8846e10SFelix Fietkau struct mt76_wcid *wcid = &msta->wcid; 434c8846e10SFelix Fietkau int idx = key->keyidx; 435c8846e10SFelix Fietkau 436c8846e10SFelix Fietkau /* fall back to sw encryption for unsupported ciphers */ 437c8846e10SFelix Fietkau switch (key->cipher) { 438c8846e10SFelix Fietkau case WLAN_CIPHER_SUITE_TKIP: 439c8846e10SFelix Fietkau case WLAN_CIPHER_SUITE_CCMP: 440c8846e10SFelix Fietkau break; 441c8846e10SFelix Fietkau default: 442c8846e10SFelix Fietkau return -EOPNOTSUPP; 443c8846e10SFelix Fietkau } 444c8846e10SFelix Fietkau 445c8846e10SFelix Fietkau /* 446c8846e10SFelix Fietkau * The hardware does not support per-STA RX GTK, fall back 447c8846e10SFelix Fietkau * to software mode for these. 448c8846e10SFelix Fietkau */ 449c8846e10SFelix Fietkau if ((vif->type == NL80211_IFTYPE_ADHOC || 450c8846e10SFelix Fietkau vif->type == NL80211_IFTYPE_MESH_POINT) && 451c8846e10SFelix Fietkau (key->cipher == WLAN_CIPHER_SUITE_TKIP || 452c8846e10SFelix Fietkau key->cipher == WLAN_CIPHER_SUITE_CCMP) && 453c8846e10SFelix Fietkau !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) 454c8846e10SFelix Fietkau return -EOPNOTSUPP; 455c8846e10SFelix Fietkau 456c8846e10SFelix Fietkau if (cmd == SET_KEY) { 457c8846e10SFelix Fietkau key->hw_key_idx = wcid->idx; 458c8846e10SFelix Fietkau wcid->hw_key_idx = idx; 459c8846e10SFelix Fietkau } else { 460c8846e10SFelix Fietkau if (idx == wcid->hw_key_idx) 461c8846e10SFelix Fietkau wcid->hw_key_idx = -1; 462c8846e10SFelix Fietkau 463c8846e10SFelix Fietkau key = NULL; 464c8846e10SFelix Fietkau } 465c8846e10SFelix Fietkau mt76_wcid_key_setup(&dev->mt76, wcid, key); 466c8846e10SFelix Fietkau 467c8846e10SFelix Fietkau return mt7603_wtbl_set_key(dev, wcid->idx, key); 468c8846e10SFelix Fietkau } 469c8846e10SFelix Fietkau 470c8846e10SFelix Fietkau static int 471c8846e10SFelix Fietkau mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, 472c8846e10SFelix Fietkau const struct ieee80211_tx_queue_params *params) 473c8846e10SFelix Fietkau { 474c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 475c8846e10SFelix Fietkau u16 cw_min = (1 << 5) - 1; 476c8846e10SFelix Fietkau u16 cw_max = (1 << 10) - 1; 477c8846e10SFelix Fietkau u32 val; 478c8846e10SFelix Fietkau 479c8846e10SFelix Fietkau queue = dev->mt76.q_tx[queue].hw_idx; 480c8846e10SFelix Fietkau 481c8846e10SFelix Fietkau if (params->cw_min) 482c8846e10SFelix Fietkau cw_min = params->cw_min; 483c8846e10SFelix Fietkau if (params->cw_max) 484c8846e10SFelix Fietkau cw_max = params->cw_max; 485c8846e10SFelix Fietkau 486c8846e10SFelix Fietkau mutex_lock(&dev->mt76.mutex); 487c8846e10SFelix Fietkau mt7603_mac_stop(dev); 488c8846e10SFelix Fietkau 489c8846e10SFelix Fietkau val = mt76_rr(dev, MT_WMM_TXOP(queue)); 490c8846e10SFelix Fietkau val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(queue)); 491c8846e10SFelix Fietkau val |= params->txop << MT_WMM_TXOP_SHIFT(queue); 492c8846e10SFelix Fietkau mt76_wr(dev, MT_WMM_TXOP(queue), val); 493c8846e10SFelix Fietkau 494c8846e10SFelix Fietkau val = mt76_rr(dev, MT_WMM_AIFSN); 495c8846e10SFelix Fietkau val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(queue)); 496c8846e10SFelix Fietkau val |= params->aifs << MT_WMM_AIFSN_SHIFT(queue); 497c8846e10SFelix Fietkau mt76_wr(dev, MT_WMM_AIFSN, val); 498c8846e10SFelix Fietkau 499c8846e10SFelix Fietkau val = mt76_rr(dev, MT_WMM_CWMIN); 500c8846e10SFelix Fietkau val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(queue)); 501c8846e10SFelix Fietkau val |= cw_min << MT_WMM_CWMIN_SHIFT(queue); 502c8846e10SFelix Fietkau mt76_wr(dev, MT_WMM_CWMIN, val); 503c8846e10SFelix Fietkau 504c8846e10SFelix Fietkau val = mt76_rr(dev, MT_WMM_CWMAX(queue)); 505c8846e10SFelix Fietkau val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(queue)); 506c8846e10SFelix Fietkau val |= cw_max << MT_WMM_CWMAX_SHIFT(queue); 507c8846e10SFelix Fietkau mt76_wr(dev, MT_WMM_CWMAX(queue), val); 508c8846e10SFelix Fietkau 509c8846e10SFelix Fietkau mt7603_mac_start(dev); 510c8846e10SFelix Fietkau mutex_unlock(&dev->mt76.mutex); 511c8846e10SFelix Fietkau 512c8846e10SFelix Fietkau return 0; 513c8846e10SFelix Fietkau } 514c8846e10SFelix Fietkau 515c8846e10SFelix Fietkau static void 516c8846e10SFelix Fietkau mt7603_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 517c8846e10SFelix Fietkau const u8 *mac) 518c8846e10SFelix Fietkau { 519c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 520c8846e10SFelix Fietkau 521c8846e10SFelix Fietkau set_bit(MT76_SCANNING, &dev->mt76.state); 522c8846e10SFelix Fietkau mt7603_beacon_set_timer(dev, -1, 0); 523c8846e10SFelix Fietkau } 524c8846e10SFelix Fietkau 525c8846e10SFelix Fietkau static void 526c8846e10SFelix Fietkau mt7603_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 527c8846e10SFelix Fietkau { 528c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 529c8846e10SFelix Fietkau 530c8846e10SFelix Fietkau clear_bit(MT76_SCANNING, &dev->mt76.state); 531c8846e10SFelix Fietkau mt7603_beacon_set_timer(dev, -1, dev->beacon_int); 532c8846e10SFelix Fietkau } 533c8846e10SFelix Fietkau 534c8846e10SFelix Fietkau static void 535c8846e10SFelix Fietkau mt7603_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 536c8846e10SFelix Fietkau u32 queues, bool drop) 537c8846e10SFelix Fietkau { 538c8846e10SFelix Fietkau } 539c8846e10SFelix Fietkau 540c8846e10SFelix Fietkau static int 541c8846e10SFelix Fietkau mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 542c8846e10SFelix Fietkau struct ieee80211_ampdu_params *params) 543c8846e10SFelix Fietkau { 544c8846e10SFelix Fietkau enum ieee80211_ampdu_mlme_action action = params->action; 545c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 546c8846e10SFelix Fietkau struct ieee80211_sta *sta = params->sta; 547c8846e10SFelix Fietkau struct ieee80211_txq *txq = sta->txq[params->tid]; 548c8846e10SFelix Fietkau struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; 549c8846e10SFelix Fietkau u16 tid = params->tid; 550c8846e10SFelix Fietkau u16 *ssn = ¶ms->ssn; 551c8846e10SFelix Fietkau u8 ba_size = params->buf_size; 552c8846e10SFelix Fietkau struct mt76_txq *mtxq; 553c8846e10SFelix Fietkau 554c8846e10SFelix Fietkau if (!txq) 555c8846e10SFelix Fietkau return -EINVAL; 556c8846e10SFelix Fietkau 557c8846e10SFelix Fietkau mtxq = (struct mt76_txq *)txq->drv_priv; 558c8846e10SFelix Fietkau 559c8846e10SFelix Fietkau switch (action) { 560c8846e10SFelix Fietkau case IEEE80211_AMPDU_RX_START: 561c8846e10SFelix Fietkau mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, *ssn, 562c8846e10SFelix Fietkau params->buf_size); 563c8846e10SFelix Fietkau mt7603_mac_rx_ba_reset(dev, sta->addr, tid); 564c8846e10SFelix Fietkau break; 565c8846e10SFelix Fietkau case IEEE80211_AMPDU_RX_STOP: 566c8846e10SFelix Fietkau mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); 567c8846e10SFelix Fietkau break; 568c8846e10SFelix Fietkau case IEEE80211_AMPDU_TX_OPERATIONAL: 569c8846e10SFelix Fietkau mtxq->aggr = true; 570c8846e10SFelix Fietkau mtxq->send_bar = false; 571c8846e10SFelix Fietkau mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, ba_size); 572c8846e10SFelix Fietkau break; 573c8846e10SFelix Fietkau case IEEE80211_AMPDU_TX_STOP_FLUSH: 574c8846e10SFelix Fietkau case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 575c8846e10SFelix Fietkau mtxq->aggr = false; 576c8846e10SFelix Fietkau ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn); 577c8846e10SFelix Fietkau mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); 578c8846e10SFelix Fietkau break; 579c8846e10SFelix Fietkau case IEEE80211_AMPDU_TX_START: 580c8846e10SFelix Fietkau mtxq->agg_ssn = *ssn << 4; 581c8846e10SFelix Fietkau ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 582c8846e10SFelix Fietkau break; 583c8846e10SFelix Fietkau case IEEE80211_AMPDU_TX_STOP_CONT: 584c8846e10SFelix Fietkau mtxq->aggr = false; 585c8846e10SFelix Fietkau mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); 586c8846e10SFelix Fietkau ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 587c8846e10SFelix Fietkau break; 588c8846e10SFelix Fietkau } 589c8846e10SFelix Fietkau 590c8846e10SFelix Fietkau return 0; 591c8846e10SFelix Fietkau } 592c8846e10SFelix Fietkau 593c8846e10SFelix Fietkau static void 594c8846e10SFelix Fietkau mt7603_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 595c8846e10SFelix Fietkau struct ieee80211_sta *sta) 596c8846e10SFelix Fietkau { 597c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 598c8846e10SFelix Fietkau struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; 599c8846e10SFelix Fietkau struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates); 600c8846e10SFelix Fietkau int i; 601c8846e10SFelix Fietkau 602c8846e10SFelix Fietkau spin_lock_bh(&dev->mt76.lock); 603c8846e10SFelix Fietkau for (i = 0; i < ARRAY_SIZE(msta->rates); i++) { 604c8846e10SFelix Fietkau msta->rates[i].idx = sta_rates->rate[i].idx; 605c8846e10SFelix Fietkau msta->rates[i].count = sta_rates->rate[i].count; 606c8846e10SFelix Fietkau msta->rates[i].flags = sta_rates->rate[i].flags; 607c8846e10SFelix Fietkau 608c8846e10SFelix Fietkau if (msta->rates[i].idx < 0 || !msta->rates[i].count) 609c8846e10SFelix Fietkau break; 610c8846e10SFelix Fietkau } 611c8846e10SFelix Fietkau msta->n_rates = i; 612c8846e10SFelix Fietkau mt7603_wtbl_set_rates(dev, msta, NULL, msta->rates); 613c8846e10SFelix Fietkau msta->rate_probe = false; 614c8846e10SFelix Fietkau mt7603_wtbl_set_smps(dev, msta, 615c8846e10SFelix Fietkau sta->smps_mode == IEEE80211_SMPS_DYNAMIC); 616c8846e10SFelix Fietkau spin_unlock_bh(&dev->mt76.lock); 617c8846e10SFelix Fietkau } 618c8846e10SFelix Fietkau 619c8846e10SFelix Fietkau static void 620c8846e10SFelix Fietkau mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) 621c8846e10SFelix Fietkau { 622c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 623c8846e10SFelix Fietkau 624c8846e10SFelix Fietkau dev->coverage_class = coverage_class; 625c8846e10SFelix Fietkau mt7603_mac_set_timing(dev); 626c8846e10SFelix Fietkau } 627c8846e10SFelix Fietkau 628c8846e10SFelix Fietkau static void mt7603_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, 629c8846e10SFelix Fietkau struct sk_buff *skb) 630c8846e10SFelix Fietkau { 631c8846e10SFelix Fietkau struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 632c8846e10SFelix Fietkau struct ieee80211_vif *vif = info->control.vif; 633c8846e10SFelix Fietkau struct mt7603_dev *dev = hw->priv; 634c8846e10SFelix Fietkau struct mt76_wcid *wcid = &dev->global_sta.wcid; 635c8846e10SFelix Fietkau 636c8846e10SFelix Fietkau if (control->sta) { 637c8846e10SFelix Fietkau struct mt7603_sta *msta; 638c8846e10SFelix Fietkau 639c8846e10SFelix Fietkau msta = (struct mt7603_sta *)control->sta->drv_priv; 640c8846e10SFelix Fietkau wcid = &msta->wcid; 641c8846e10SFelix Fietkau } else if (vif) { 642c8846e10SFelix Fietkau struct mt7603_vif *mvif; 643c8846e10SFelix Fietkau 644c8846e10SFelix Fietkau mvif = (struct mt7603_vif *)vif->drv_priv; 645c8846e10SFelix Fietkau wcid = &mvif->sta.wcid; 646c8846e10SFelix Fietkau } 647c8846e10SFelix Fietkau 648c8846e10SFelix Fietkau mt76_tx(&dev->mt76, control->sta, wcid, skb); 649c8846e10SFelix Fietkau } 650c8846e10SFelix Fietkau 651c8846e10SFelix Fietkau static int 652c8846e10SFelix Fietkau mt7603_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) 653c8846e10SFelix Fietkau { 654c8846e10SFelix Fietkau return 0; 655c8846e10SFelix Fietkau } 656c8846e10SFelix Fietkau 657c8846e10SFelix Fietkau const struct ieee80211_ops mt7603_ops = { 658c8846e10SFelix Fietkau .tx = mt7603_tx, 659c8846e10SFelix Fietkau .start = mt7603_start, 660c8846e10SFelix Fietkau .stop = mt7603_stop, 661c8846e10SFelix Fietkau .add_interface = mt7603_add_interface, 662c8846e10SFelix Fietkau .remove_interface = mt7603_remove_interface, 663c8846e10SFelix Fietkau .config = mt7603_config, 664c8846e10SFelix Fietkau .configure_filter = mt7603_configure_filter, 665c8846e10SFelix Fietkau .bss_info_changed = mt7603_bss_info_changed, 666c8846e10SFelix Fietkau .sta_state = mt76_sta_state, 667c8846e10SFelix Fietkau .set_key = mt7603_set_key, 668c8846e10SFelix Fietkau .conf_tx = mt7603_conf_tx, 669c8846e10SFelix Fietkau .sw_scan_start = mt7603_sw_scan, 670c8846e10SFelix Fietkau .sw_scan_complete = mt7603_sw_scan_complete, 671c8846e10SFelix Fietkau .flush = mt7603_flush, 672c8846e10SFelix Fietkau .ampdu_action = mt7603_ampdu_action, 673c8846e10SFelix Fietkau .get_txpower = mt76_get_txpower, 674c8846e10SFelix Fietkau .wake_tx_queue = mt76_wake_tx_queue, 675c8846e10SFelix Fietkau .sta_rate_tbl_update = mt7603_sta_rate_tbl_update, 676c8846e10SFelix Fietkau .release_buffered_frames = mt7603_release_buffered_frames, 677c8846e10SFelix Fietkau .set_coverage_class = mt7603_set_coverage_class, 678c8846e10SFelix Fietkau .set_tim = mt7603_set_tim, 679c8846e10SFelix Fietkau .get_survey = mt76_get_survey, 680c8846e10SFelix Fietkau }; 681c8846e10SFelix Fietkau 682c8846e10SFelix Fietkau MODULE_LICENSE("Dual BSD/GPL"); 683c8846e10SFelix Fietkau 684c8846e10SFelix Fietkau static int __init mt7603_init(void) 685c8846e10SFelix Fietkau { 686c8846e10SFelix Fietkau int ret; 687c8846e10SFelix Fietkau 688c8846e10SFelix Fietkau ret = platform_driver_register(&mt76_wmac_driver); 689c8846e10SFelix Fietkau if (ret) 690c8846e10SFelix Fietkau return ret; 691c8846e10SFelix Fietkau 692c8846e10SFelix Fietkau #ifdef CONFIG_PCI 693c8846e10SFelix Fietkau ret = pci_register_driver(&mt7603_pci_driver); 694c8846e10SFelix Fietkau if (ret) 695c8846e10SFelix Fietkau platform_driver_unregister(&mt76_wmac_driver); 696c8846e10SFelix Fietkau #endif 697c8846e10SFelix Fietkau return ret; 698c8846e10SFelix Fietkau } 699c8846e10SFelix Fietkau 700c8846e10SFelix Fietkau static void __exit mt7603_exit(void) 701c8846e10SFelix Fietkau { 702c8846e10SFelix Fietkau #ifdef CONFIG_PCI 703c8846e10SFelix Fietkau pci_unregister_driver(&mt7603_pci_driver); 704c8846e10SFelix Fietkau #endif 705c8846e10SFelix Fietkau platform_driver_unregister(&mt76_wmac_driver); 706c8846e10SFelix Fietkau } 707c8846e10SFelix Fietkau 708c8846e10SFelix Fietkau module_init(mt7603_init); 709c8846e10SFelix Fietkau module_exit(mt7603_exit); 710