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