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