diff options
author | Kalle Valo <kvalo@codeaurora.org> | 2019-06-30 12:29:30 +0300 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2019-06-30 12:29:30 +0300 |
commit | 9829a0bd664da613c6b44b210d8f0ab8dba2400b (patch) | |
tree | 77e55a7ab2178a9b706cac71873407482801123a /drivers/net/wireless | |
parent | b741422218efeb76389a307b72ed3afe41671cf7 (diff) | |
parent | 676fabd1d2f089f9fb8bece3476c2ab5584b4a1a (diff) | |
download | linux-9829a0bd664da613c6b44b210d8f0ab8dba2400b.tar.bz2 |
Merge tag 'mt76-for-kvalo-2019-06-27' of https://github.com/nbd168/wireless
mt76 patches for 5.3
* use NAPI polling for tx cleanup on mt7603/mt7615
* various fixes for mt7615
* unify some code between mt7603 and mt7615
* fix locking issues on mt76x02
* add support for toggling edcca on mt7603
* fix reading target tx power with ext PA on mt7603/mt7615
* fix initalizing channel maximum power
* fix rate control / tx status reporting issues on mt76x02/mt7603
* add support for eeprom calibration data from mtd on mt7615
* support configuring tx power on mt7615
* fix external PA support on mt76x0
* per-chain signal reporting on mt7615
* rx/tx buffer fixes for USB devices
Diffstat (limited to 'drivers/net/wireless')
47 files changed, 1422 insertions, 1011 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 4381155375e1..d8f61e540bfd 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -588,6 +588,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev) { int i; + netif_napi_del(&dev->tx_napi); for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) mt76_dma_tx_cleanup(dev, i, true); diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 5b6a81ee457e..ec9efb79985f 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -766,10 +766,21 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, *dbm = DIV_ROUND_UP(dev->txpower_cur, 2); /* convert from per-chain power to combined - * output on 2x2 devices + * output power */ - if (n_chains > 1) + switch (n_chains) { + case 4: + *dbm += 6; + break; + case 3: + *dbm += 4; + break; + case 2: *dbm += 3; + break; + default: + break; + } return 0; } @@ -820,3 +831,50 @@ mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) return 0; } EXPORT_SYMBOL_GPL(mt76_set_tim); + +void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + int hdr_len = ieee80211_get_hdrlen_from_skb(skb); + u8 *hdr, *pn = status->iv; + + __skb_push(skb, 8); + memmove(skb->data, skb->data + 8, hdr_len); + hdr = skb->data + hdr_len; + + hdr[0] = pn[5]; + hdr[1] = pn[4]; + hdr[2] = 0; + hdr[3] = 0x20 | (key_id << 6); + hdr[4] = pn[3]; + hdr[5] = pn[2]; + hdr[6] = pn[1]; + hdr[7] = pn[0]; + + status->flag &= ~RX_FLAG_IV_STRIPPED; +} +EXPORT_SYMBOL_GPL(mt76_insert_ccmp_hdr); + +int mt76_get_rate(struct mt76_dev *dev, + struct ieee80211_supported_band *sband, + int idx, bool cck) +{ + int i, offset = 0, len = sband->n_bitrates; + + if (cck) { + if (sband == &dev->sband_5g.sband) + return 0; + + idx &= ~BIT(2); /* short preamble */ + } else if (sband == &dev->sband_2g.sband) { + offset = 4; + } + + for (i = offset; i < len; i++) { + if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) + return i; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_get_rate); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8ecbf81a906f..56bf93a8988e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -258,10 +258,11 @@ struct mt76_rx_tid { #define MT_TX_CB_TXS_DONE BIT(1) #define MT_TX_CB_TXS_FAILED BIT(2) -#define MT_PACKET_ID_MASK GENMASK(7, 0) +#define MT_PACKET_ID_MASK GENMASK(6, 0) #define MT_PACKET_ID_NO_ACK 0 #define MT_PACKET_ID_NO_SKB 1 #define MT_PACKET_ID_FIRST 2 +#define MT_PACKET_ID_HAS_RATE BIT(7) #define MT_TX_STATUS_SKB_TIMEOUT HZ @@ -381,7 +382,8 @@ enum mt76u_out_ep { __MT_EP_OUT_MAX, }; -#define MT_SG_MAX_SIZE 8 +#define MT_TX_SG_MAX_SIZE 8 +#define MT_RX_SG_MAX_SIZE 1 #define MT_NUM_TX_ENTRIES 256 #define MT_NUM_RX_ENTRIES 128 #define MCU_RESP_URB_SIZE 1024 @@ -393,9 +395,7 @@ struct mt76_usb { struct delayed_work stat_work; u8 out_ep[__MT_EP_OUT_MAX]; - u16 out_max_packet; u8 in_ep[__MT_EP_IN_MAX]; - u16 in_max_packet; bool sg_en; struct mt76u_mcu { @@ -452,6 +452,7 @@ struct mt76_dev { int tx_dma_idx[4]; struct tasklet_struct tx_tasklet; + struct napi_struct tx_napi; struct delayed_work mac_work; wait_queue_head_t tx_wait; @@ -483,6 +484,8 @@ struct mt76_dev { int txpower_conf; int txpower_cur; + enum nl80211_dfs_regions region; + u32 debugfs_reg; struct led_classdev led_cdev; @@ -688,6 +691,14 @@ static inline void mt76_insert_hdr_pad(struct sk_buff *skb) skb->data[len + 1] = 0; } +static inline bool mt76_is_skb_pktid(u8 pktid) +{ + if (pktid & MT_PACKET_ID_HAS_RATE) + return false; + + return pktid >= MT_PACKET_ID_FIRST; +} + void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb); @@ -749,6 +760,10 @@ void mt76_csa_check(struct mt76_dev *dev); void mt76_csa_finish(struct mt76_dev *dev); int mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); +void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id); +int mt76_get_rate(struct mt76_dev *dev, + struct ieee80211_supported_band *sband, + int idx, bool cck); /* internal */ void mt76_tx_free(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c index 37e5644b45ef..e7ee58e3379c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/core.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c @@ -35,7 +35,7 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) if (intr & MT_INT_TX_DONE_ALL) { mt7603_irq_disable(dev, MT_INT_TX_DONE_ALL); - tasklet_schedule(&dev->mt76.tx_tasklet); + napi_schedule(&dev->mt76.tx_napi); } if (intr & MT_INT_RX_DONE(0)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c index f8b3b6ab6297..a1bc3103cbe9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c @@ -40,6 +40,35 @@ mt7603_radio_read(struct seq_file *s, void *data) return 0; } +static int +mt7603_edcca_set(void *data, u64 val) +{ + struct mt7603_dev *dev = data; + + mutex_lock(&dev->mt76.mutex); + + dev->ed_monitor_enabled = !!val; + dev->ed_monitor = dev->ed_monitor_enabled && + dev->mt76.region == NL80211_DFS_ETSI; + mt7603_init_edcca(dev); + + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static int +mt7603_edcca_get(void *data, u64 *val) +{ + struct mt7603_dev *dev = data; + + *val = dev->ed_monitor_enabled; + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_edcca, mt7603_edcca_get, + mt7603_edcca_set, "%lld\n"); + void mt7603_init_debugfs(struct mt7603_dev *dev) { struct dentry *dir; @@ -48,6 +77,7 @@ void mt7603_init_debugfs(struct mt7603_dev *dev) if (!dir) return; + debugfs_create_file("edcca", 0600, dir, dev, &fops_edcca); debugfs_create_u32("reset_test", 0600, dir, &dev->reset_test); debugfs_create_devm_seqfile(dev->mt76.dev, "reset", dir, mt7603_reset_read); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 27e2d9f90553..58dc511f93c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -139,15 +139,30 @@ static void mt7603_tx_tasklet(unsigned long data) { struct mt7603_dev *dev = (struct mt7603_dev *)data; + + mt76_txq_schedule_all(&dev->mt76); +} + +static int mt7603_poll_tx(struct napi_struct *napi, int budget) +{ + struct mt7603_dev *dev; int i; + dev = container_of(napi, struct mt7603_dev, mt76.tx_napi); dev->tx_dma_check = 0; + for (i = MT_TXQ_MCU; i >= 0; i--) mt76_queue_tx_cleanup(dev, i, false); - mt76_txq_schedule_all(&dev->mt76); + if (napi_complete_done(napi, 0)) + mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); - mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); + for (i = MT_TXQ_MCU; i >= 0; i--) + mt76_queue_tx_cleanup(dev, i, false); + + tasklet_schedule(&dev->mt76.tx_tasklet); + + return 0; } int mt7603_dma_init(struct mt7603_dev *dev) @@ -216,7 +231,15 @@ int mt7603_dma_init(struct mt7603_dev *dev) return ret; mt76_wr(dev, MT_DELAY_INT_CFG, 0); - return mt76_init_queues(dev); + ret = mt76_init_queues(dev); + if (ret) + return ret; + + netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + mt7603_poll_tx, NAPI_POLL_WEIGHT); + napi_enable(&dev->mt76.tx_napi); + + return 0; } void mt7603_dma_cleanup(struct mt7603_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h index f27b99b7e359..b893facfba48 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h @@ -69,6 +69,8 @@ enum mt7603_eeprom_field { MT_EE_CP_FT_VERSION = 0x0f0, + MT_EE_TX_POWER_TSSI_OFF = 0x0f2, + MT_EE_XTAL_FREQ_OFFSET = 0x0f4, MT_EE_XTAL_TRIM_2_COMP = 0x0f5, MT_EE_XTAL_TRIM_3_COMP = 0x0f6, diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 78cdbb70e178..38834c7d0891 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -227,11 +227,19 @@ mt7603_mac_init(struct mt7603_dev *dev) mt76_rmw_field(dev, MT_LPON_BTEIR, MT_LPON_BTEIR_MBSS_MODE, 2); mt76_rmw_field(dev, MT_WF_RMACDR, MT_WF_RMACDR_MBSSID_MASK, 2); - mt76_wr(dev, MT_AGG_ARUCR, FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7)); + mt76_wr(dev, MT_AGG_ARUCR, + FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1)); + mt76_wr(dev, MT_AGG_ARDCR, - FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 0) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), - max_t(int, 0, MT7603_RATE_RETRY - 2)) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7603_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7603_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7603_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7603_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7603_RATE_RETRY - 1) | @@ -437,7 +445,9 @@ mt7603_regd_notifier(struct wiphy *wiphy, struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct mt7603_dev *dev = hw->priv; - dev->ed_monitor = request->dfs_region == NL80211_DFS_ETSI; + dev->mt76.region = request->dfs_region; + dev->ed_monitor = dev->ed_monitor_enabled && + dev->mt76.region == NL80211_DFS_ETSI; } static int @@ -463,9 +473,13 @@ mt7603_init_txpower(struct mt7603_dev *dev, u8 *eeprom = (u8 *)dev->mt76.eeprom.data; int target_power = eeprom[MT_EE_TX_POWER_0_START_2G + 2] & ~BIT(7); u8 *rate_power = &eeprom[MT_EE_TX_POWER_CCK]; + bool ext_pa = eeprom[MT_EE_NIC_CONF_0 + 1] & BIT(1); int max_offset, cur_offset; int i; + if (ext_pa && is_mt7603(dev)) + target_power = eeprom[MT_EE_TX_POWER_TSSI_OFF] & ~BIT(7); + if (target_power & BIT(6)) target_power = -(target_power & GENMASK(5, 0)); @@ -488,7 +502,7 @@ mt7603_init_txpower(struct mt7603_dev *dev, for (i = 0; i < sband->n_channels; i++) { chan = &sband->channels[i]; - chan->max_power = target_power; + chan->max_power = min_t(int, chan->max_reg_power, target_power); chan->orig_mpwr = target_power; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 6d506e34c3ee..40db1cbc832d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -370,31 +370,6 @@ void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, mt76_rmw(dev, addr + (15 * 4), tid_mask, tid_val); } -static int -mt7603_get_rate(struct mt7603_dev *dev, struct ieee80211_supported_band *sband, - int idx, bool cck) -{ - int offset = 0; - int len = sband->n_bitrates; - int i; - - if (cck) { - if (sband == &dev->mt76.sband_5g.sband) - return 0; - - idx &= ~BIT(2); /* short preamble */ - } else if (sband == &dev->mt76.sband_2g.sband) { - offset = 4; - } - - for (i = offset; i < len; i++) { - if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) - return i; - } - - return 0; -} - static struct mt76_wcid * mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast) { @@ -418,30 +393,6 @@ mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast) return &sta->vif->sta.wcid; } -static void -mt7603_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - int hdr_len = ieee80211_get_hdrlen_from_skb(skb); - u8 *pn = status->iv; - u8 *hdr; - - __skb_push(skb, 8); - memmove(skb->data, skb->data + 8, hdr_len); - hdr = skb->data + hdr_len; - - hdr[0] = pn[5]; - hdr[1] = pn[4]; - hdr[2] = 0; - hdr[3] = 0x20 | (key_id << 6); - hdr[4] = pn[3]; - hdr[5] = pn[2]; - hdr[6] = pn[1]; - hdr[7] = pn[0]; - - status->flag &= ~RX_FLAG_IV_STRIPPED; -} - int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) { @@ -532,7 +483,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - i = mt7603_get_rate(dev, sband, i, cck); + i = mt76_get_rate(&dev->mt76, sband, i, cck); break; case MT_PHY_TYPE_HT_GF: case MT_PHY_TYPE_HT: @@ -580,7 +531,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) if (insert_ccmp_hdr) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); - mt7603_insert_ccmp_hdr(skb, key_id); + mt76_insert_ccmp_hdr(skb, key_id); } hdr = (struct ieee80211_hdr *)skb->data; @@ -640,6 +591,7 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates) { + struct ieee80211_tx_rate *ref; int wcid = sta->wcid.idx; u32 addr = mt7603_wtbl2_addr(wcid); bool stbc = false; @@ -648,7 +600,8 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, u16 val[4]; u16 probe_val; u32 w9 = mt76_rr(dev, addr + 9 * 4); - int i; + bool rateset; + int i, k; if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000)) return; @@ -656,6 +609,41 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, for (i = n_rates; i < 4; i++) rates[i] = rates[n_rates - 1]; + rateset = !(sta->rate_set_tsf & BIT(0)); + memcpy(sta->rateset[rateset].rates, rates, + sizeof(sta->rateset[rateset].rates)); + if (probe_rate) { + sta->rateset[rateset].probe_rate = *probe_rate; + ref = &sta->rateset[rateset].probe_rate; + } else { + sta->rateset[rateset].probe_rate.idx = -1; + ref = &sta->rateset[rateset].rates[0]; + } + + rates = sta->rateset[rateset].rates; + for (i = 0; i < ARRAY_SIZE(sta->rateset[rateset].rates); i++) { + /* + * We don't support switching between short and long GI + * within the rate set. For accurate tx status reporting, we + * need to make sure that flags match. + * For improved performance, avoid duplicate entries by + * decrementing the MCS index if necessary + */ + if ((ref->flags ^ rates[i].flags) & IEEE80211_TX_RC_SHORT_GI) + rates[i].flags ^= IEEE80211_TX_RC_SHORT_GI; + + for (k = 0; k < i; k++) { + if (rates[i].idx != rates[k].idx) + continue; + if ((rates[i].flags ^ rates[k].flags) & + IEEE80211_TX_RC_40_MHZ_WIDTH) + continue; + + rates[i].idx--; + } + + } + w9 &= MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 | MT_WTBL2_W9_SHORT_GI_80; @@ -699,19 +687,22 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, mt76_wr(dev, MT_WTBL_RIUCR1, FIELD_PREP(MT_WTBL_RIUCR1_RATE0, probe_val) | FIELD_PREP(MT_WTBL_RIUCR1_RATE1, val[0]) | - FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[0])); + FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[1])); mt76_wr(dev, MT_WTBL_RIUCR2, - FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[0] >> 8) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[1] >> 8) | FIELD_PREP(MT_WTBL_RIUCR2_RATE3, val[1]) | - FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[1]) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[2]) | FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, val[2])); mt76_wr(dev, MT_WTBL_RIUCR3, FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, val[2] >> 4) | - FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[2]) | + FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[3]) | FIELD_PREP(MT_WTBL_RIUCR3_RATE7, val[3])); + mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + sta->rate_set_tsf = (mt76_rr(dev, MT_LPON_UTTR0) & ~BIT(0)) | rateset; + mt76_wr(dev, MT_WTBL_UPDATE, FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) | MT_WTBL_UPDATE_RATE_UPDATE | @@ -938,9 +929,9 @@ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { spin_lock_bh(&dev->mt76.lock); - msta->rate_probe = true; mt7603_wtbl_set_rates(dev, msta, &info->control.rates[0], msta->rates); + msta->rate_probe = true; spin_unlock_bh(&dev->mt76.lock); } @@ -955,10 +946,12 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, struct ieee80211_tx_info *info, __le32 *txs_data) { struct ieee80211_supported_band *sband; - int final_idx = 0; + struct mt7603_rate_set *rs; + int first_idx = 0, last_idx; + u32 rate_set_tsf; u32 final_rate; u32 final_rate_flags; - bool final_mpdu; + bool rs_idx; bool ack_timeout; bool fixed_rate; bool probe; @@ -966,7 +959,6 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, bool cck = false; int count; u32 txs; - u8 pid; int idx; int i; @@ -974,10 +966,9 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); txs = le32_to_cpu(txs_data[4]); - final_mpdu = txs & MT_TXS4_ACKED_MPDU; ampdu = !fixed_rate && (txs & MT_TXS4_AMPDU); - pid = FIELD_GET(MT_TXS4_PID, txs); count = FIELD_GET(MT_TXS4_TX_COUNT, txs); + last_idx = FIELD_GET(MT_TXS4_LAST_TX_RATE, txs); txs = le32_to_cpu(txs_data[0]); final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); @@ -999,38 +990,57 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU)) info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU; + first_idx = max_t(int, 0, last_idx - (count + 1) / MT7603_RATE_RETRY); + if (fixed_rate && !probe) { info->status.rates[0].count = count; + i = 0; goto out; } - for (i = 0, idx = 0; i < ARRAY_SIZE(info->status.rates); i++) { - int cur_count = min_t(int, count, 2 * MT7603_RATE_RETRY); + rate_set_tsf = READ_ONCE(sta->rate_set_tsf); + rs_idx = !((u32)(FIELD_GET(MT_TXS1_F0_TIMESTAMP, le32_to_cpu(txs_data[1])) - + rate_set_tsf) < 1000000); + rs_idx ^= rate_set_tsf & BIT(0); + rs = &sta->rateset[rs_idx]; - if (!i && probe) { - cur_count = 1; - } else { - info->status.rates[i] = sta->rates[idx]; - idx++; - } + if (!first_idx && rs->probe_rate.idx >= 0) { + info->status.rates[0] = rs->probe_rate; - if (i && info->status.rates[i].idx < 0) { - info->status.rates[i - 1].count += count; - break; + spin_lock_bh(&dev->mt76.lock); + if (sta->rate_probe) { + mt7603_wtbl_set_rates(dev, sta, NULL, + sta->rates); + sta->rate_probe = false; } + spin_unlock_bh(&dev->mt76.lock); + } else + info->status.rates[0] = rs->rates[first_idx / 2]; + info->status.rates[0].count = 0; - if (!count) { - info->status.rates[i].idx = -1; - break; - } + for (i = 0, idx = first_idx; count && idx <= last_idx; idx++) { + struct ieee80211_tx_rate *cur_rate; + int cur_count; - info->status.rates[i].count = cur_count; - final_idx = i; + cur_rate = &rs->rates[idx / 2]; + cur_count = min_t(int, MT7603_RATE_RETRY, count); count -= cur_count; + + if (idx && (cur_rate->idx != info->status.rates[i].idx || + cur_rate->flags != info->status.rates[i].flags)) { + i++; + if (i == ARRAY_SIZE(info->status.rates)) + break; + + info->status.rates[i] = *cur_rate; + info->status.rates[i].count = 0; + } + + info->status.rates[i].count += cur_count; } out: - final_rate_flags = info->status.rates[final_idx].flags; + final_rate_flags = info->status.rates[i].flags; switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) { case MT_PHY_TYPE_CCK: @@ -1042,7 +1052,8 @@ out: else sband = &dev->mt76.sband_2g.sband; final_rate &= GENMASK(5, 0); - final_rate = mt7603_get_rate(dev, sband, final_rate, cck); + final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, + cck); final_rate_flags = 0; break; case MT_PHY_TYPE_HT_GF: @@ -1056,8 +1067,8 @@ out: return false; } - info->status.rates[final_idx].idx = final_rate; - info->status.rates[final_idx].flags = final_rate_flags; + info->status.rates[i].idx = final_rate; + info->status.rates[i].flags = final_rate_flags; return true; } @@ -1078,16 +1089,6 @@ mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid, if (skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { - spin_lock_bh(&dev->mt76.lock); - if (sta->rate_probe) { - mt7603_wtbl_set_rates(dev, sta, NULL, - sta->rates); - sta->rate_probe = false; - } - spin_unlock_bh(&dev->mt76.lock); - } - if (!mt7603_fill_txs(dev, sta, info, txs_data)) { ieee80211_tx_info_clear_status(info); info->status.rates[0].idx = -1; @@ -1282,6 +1283,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) tasklet_disable(&dev->mt76.pre_tbtt_tasklet); napi_disable(&dev->mt76.napi[0]); napi_disable(&dev->mt76.napi[1]); + napi_disable(&dev->mt76.tx_napi); mutex_lock(&dev->mt76.mutex); @@ -1326,7 +1328,8 @@ skip_dma_reset: mutex_unlock(&dev->mt76.mutex); tasklet_enable(&dev->mt76.tx_tasklet); - tasklet_schedule(&dev->mt76.tx_tasklet); + napi_enable(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.tx_napi); tasklet_enable(&dev->mt76.pre_tbtt_tasklet); mt7603_beacon_set_timer(dev, -1, beacon_int); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 0a0334dc40d5..e5d4cb6381a8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -103,8 +103,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mutex_unlock(&dev->mt76.mutex); } -static void -mt7603_init_edcca(struct mt7603_dev *dev) +void mt7603_init_edcca(struct mt7603_dev *dev) { /* Set lower signal level to -65dBm */ mt76_rmw_field(dev, MT_RXTD(8), MT_RXTD_8_LOWER_SIGNAL, 0x23); @@ -207,8 +206,11 @@ mt7603_config(struct ieee80211_hw *hw, u32 changed) int ret = 0; if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | - IEEE80211_CONF_CHANGE_POWER)) + IEEE80211_CONF_CHANGE_POWER)) { + ieee80211_stop_queues(hw); ret = mt7603_set_channel(dev, &hw->conf.chandef); + ieee80211_wake_queues(hw); + } if (changed & IEEE80211_CONF_CHANGE_MONITOR) { mutex_lock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index 6357b5658a32..343ddc5543c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -346,7 +346,7 @@ int mt7603_mcu_set_eeprom(struct mt7603_dev *dev) }; struct req_data { - u16 addr; + __le16 addr; u8 val; u8 pad; } __packed; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index fa64bbaab0d2..2c6f7b4cf0e9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -51,6 +51,11 @@ enum mt7603_bw { MT_BW_80, }; +struct mt7603_rate_set { + struct ieee80211_tx_rate probe_rate; + struct ieee80211_tx_rate rates[4]; +}; + struct mt7603_sta { struct mt76_wcid wcid; /* must be first */ @@ -58,7 +63,11 @@ struct mt7603_sta { struct sk_buff_head psq; - struct ieee80211_tx_rate rates[8]; + struct ieee80211_tx_rate rates[4]; + + struct mt7603_rate_set rateset[2]; + u32 rate_set_tsf; + u8 rate_count; u8 n_rates; @@ -117,8 +126,9 @@ struct mt7603_dev { u8 mac_work_count; u8 mcu_running; - u8 ed_monitor; + u8 ed_monitor_enabled; + u8 ed_monitor; s8 ed_trigger; u8 ed_strict_mode; u8 ed_strong_signal; @@ -241,4 +251,5 @@ void mt7603_update_channel(struct mt76_dev *mdev); void mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val); void mt7603_cca_stats_reset(struct mt7603_dev *dev); +void mt7603_init_edcca(struct mt7603_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h index 9d257d5c309d..eb9eefe8e125 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -480,6 +480,12 @@ enum { #define MT_LPON_BASE 0x24000 #define MT_LPON(n) (MT_LPON_BASE + (n)) +#define MT_LPON_T0CR MT_LPON(0x010) +#define MT_LPON_T0CR_MODE GENMASK(1, 0) + +#define MT_LPON_UTTR0 MT_LPON(0x018) +#define MT_LPON_UTTR1 MT_LPON(0x01c) + #define MT_LPON_BTEIR MT_LPON(0x020) #define MT_LPON_BTEIR_MBSS_MODE GENMASK(31, 29) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 3ec6582afd8f..6a70273d4a69 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -93,18 +93,33 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, static void mt7615_tx_tasklet(unsigned long data) { struct mt7615_dev *dev = (struct mt7615_dev *)data; + + mt76_txq_schedule_all(&dev->mt76); +} + +static int mt7615_poll_tx(struct napi_struct *napi, int budget) +{ static const u8 queue_map[] = { MT_TXQ_MCU, MT_TXQ_BE }; + struct mt7615_dev *dev; int i; + dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); + for (i = 0; i < ARRAY_SIZE(queue_map); i++) mt76_queue_tx_cleanup(dev, queue_map[i], false); - mt76_txq_schedule_all(&dev->mt76); + if (napi_complete_done(napi, 0)) + mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL); - mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL); + for (i = 0; i < ARRAY_SIZE(queue_map); i++) + mt76_queue_tx_cleanup(dev, queue_map[i], false); + + tasklet_schedule(&dev->mt76.tx_tasklet); + + return 0; } int mt7615_dma_init(struct mt7615_dev *dev) @@ -178,6 +193,10 @@ int mt7615_dma_init(struct mt7615_dev *dev) if (ret < 0) return ret; + netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + mt7615_poll_tx, NAPI_POLL_WEIGHT); + napi_enable(&dev->mt76.tx_napi); + mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 1000); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index dd5ab46a4f66..dc94f52e6e8b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -42,13 +42,13 @@ static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base, static int mt7615_efuse_init(struct mt7615_dev *dev) { - u32 base = mt7615_reg_map(dev, MT_EFUSE_BASE); - int len = MT7615_EEPROM_SIZE; - int ret, i; + u32 val, base = mt7615_reg_map(dev, MT_EFUSE_BASE); + int i, len = MT7615_EEPROM_SIZE; void *buf; - if (mt76_rr(dev, base + MT_EFUSE_BASE_CTRL) & MT_EFUSE_BASE_CTRL_EMPTY) - return -EINVAL; + val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL); + if (val & MT_EFUSE_BASE_CTRL_EMPTY) + return 0; dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL); dev->mt76.otp.size = len; @@ -57,6 +57,8 @@ static int mt7615_efuse_init(struct mt7615_dev *dev) buf = dev->mt76.otp.data; for (i = 0; i + 16 <= len; i += 16) { + int ret; + ret = mt7615_efuse_read(dev, base, i, buf + i); if (ret) return ret; @@ -76,6 +78,82 @@ static int mt7615_eeprom_load(struct mt7615_dev *dev) return mt7615_efuse_init(dev); } +static int mt7615_check_eeprom(struct mt76_dev *dev) +{ + u16 val = get_unaligned_le16(dev->eeprom.data); + + switch (val) { + case 0x7615: + return 0; + default: + return -EINVAL; + } +} + +static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) +{ + u8 val, *eeprom = dev->mt76.eeprom.data; + + val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, + eeprom[MT_EE_WIFI_CONF]); + switch (val) { + case MT_EE_5GHZ: + dev->mt76.cap.has_5ghz = true; + break; + case MT_EE_2GHZ: + dev->mt76.cap.has_2ghz = true; + break; + default: + dev->mt76.cap.has_2ghz = true; + dev->mt76.cap.has_5ghz = true; + break; + } +} + +int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, + struct ieee80211_channel *chan, + u8 chain_idx) +{ + int index; + + if (chain_idx > 3) + return -EINVAL; + + /* TSSI disabled */ + if (mt7615_ext_pa_enabled(dev, chan->band)) { + if (chan->band == NL80211_BAND_2GHZ) + return MT_EE_EXT_PA_2G_TARGET_POWER; + else + return MT_EE_EXT_PA_5G_TARGET_POWER; + } + + /* TSSI enabled */ + if (chan->band == NL80211_BAND_2GHZ) { + index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6; + } else { + int group = mt7615_get_channel_group(chan->hw_value); + + switch (chain_idx) { + case 1: + index = MT_EE_TX1_5G_G0_TARGET_POWER; + break; + case 2: + index = MT_EE_TX2_5G_G0_TARGET_POWER; + break; + case 3: + index = MT_EE_TX3_5G_G0_TARGET_POWER; + break; + case 0: + default: + index = MT_EE_TX0_5G_G0_TARGET_POWER; + break; + } + index += 5 * group; + } + + return index; +} + int mt7615_eeprom_init(struct mt7615_dev *dev) { int ret; @@ -84,11 +162,12 @@ int mt7615_eeprom_init(struct mt7615_dev *dev) if (ret < 0) return ret; - memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, MT7615_EEPROM_SIZE); - - dev->mt76.cap.has_2ghz = true; - dev->mt76.cap.has_5ghz = true; + ret = mt7615_check_eeprom(&dev->mt76); + if (ret && dev->mt76.otp.data) + memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, + MT7615_EEPROM_SIZE); + mt7615_eeprom_parse_hw_cap(dev); memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index a4cf16688171..f4a4280768d2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -11,8 +11,69 @@ enum mt7615_eeprom_field { MT_EE_VERSION = 0x002, MT_EE_MAC_ADDR = 0x004, MT_EE_NIC_CONF_0 = 0x034, + MT_EE_NIC_CONF_1 = 0x036, + MT_EE_WIFI_CONF = 0x03e, + MT_EE_TX0_2G_TARGET_POWER = 0x058, + MT_EE_TX0_5G_G0_TARGET_POWER = 0x070, + MT_EE_TX1_5G_G0_TARGET_POWER = 0x098, + MT_EE_EXT_PA_2G_TARGET_POWER = 0x0f2, + MT_EE_EXT_PA_5G_TARGET_POWER = 0x0f3, + MT_EE_TX2_5G_G0_TARGET_POWER = 0x142, + MT_EE_TX3_5G_G0_TARGET_POWER = 0x16a, __MT_EE_MAX = 0x3bf }; +#define MT_EE_NIC_CONF_TSSI_2G BIT(5) +#define MT_EE_NIC_CONF_TSSI_5G BIT(6) + +#define MT_EE_NIC_WIFI_CONF_BAND_SEL GENMASK(5, 4) +enum mt7615_eeprom_band { + MT_EE_DUAL_BAND, + MT_EE_5GHZ, + MT_EE_2GHZ, + MT_EE_DBDC, +}; + +enum mt7615_channel_group { + MT_CH_5G_JAPAN, + MT_CH_5G_UNII_1, + MT_CH_5G_UNII_2A, + MT_CH_5G_UNII_2B, + MT_CH_5G_UNII_2E_1, + MT_CH_5G_UNII_2E_2, + MT_CH_5G_UNII_2E_3, + MT_CH_5G_UNII_3, + __MT_CH_MAX +}; + +static inline enum mt7615_channel_group +mt7615_get_channel_group(int channel) +{ + if (channel >= 184 && channel <= 196) + return MT_CH_5G_JAPAN; + if (channel <= 48) + return MT_CH_5G_UNII_1; + if (channel <= 64) + return MT_CH_5G_UNII_2A; + if (channel <= 114) + return MT_CH_5G_UNII_2E_1; + if (channel <= 144) + return MT_CH_5G_UNII_2E_2; + if (channel <= 161) + return MT_CH_5G_UNII_2E_3; + return MT_CH_5G_UNII_3; +} + +static inline bool +mt7615_ext_pa_enabled(struct mt7615_dev *dev, enum nl80211_band band) +{ + u8 *eep = dev->mt76.eeprom.data; + + if (band == NL80211_BAND_5GHZ) + return !(eep[MT_EE_NIC_CONF_1 + 1] & MT_EE_NIC_CONF_TSSI_5G); + else + return !(eep[MT_EE_NIC_CONF_1 + 1] & MT_EE_NIC_CONF_TSSI_2G); +} + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 3ab3ff553ef2..859de2454ec6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -9,6 +9,7 @@ #include <linux/etherdevice.h> #include "mt7615.h" #include "mac.h" +#include "eeprom.h" static void mt7615_phy_init(struct mt7615_dev *dev) { @@ -62,16 +63,11 @@ static void mt7615_mac_init(struct mt7615_dev *dev) MT_AGG_ARCR_RATE_DOWN_RATIO_EN | FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4))); - - dev->mt76.global_wcid.idx = MT7615_WTBL_RESERVED; - dev->mt76.global_wcid.hw_key_idx = -1; - rcu_assign_pointer(dev->mt76.wcid[MT7615_WTBL_RESERVED], - &dev->mt76.global_wcid); } static int mt7615_init_hardware(struct mt7615_dev *dev) { - int ret; + int ret, idx; mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); @@ -98,6 +94,15 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) mt7615_mcu_ctrl_pm_state(dev, 0); mt7615_mcu_del_wtbl_all(dev); + /* Beacon and mgmt frames should occupy wcid 0 */ + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1); + if (idx) + return -ENOSPC; + + dev->mt76.global_wcid.idx = idx; + dev->mt76.global_wcid.hw_key_idx = -1; + rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid); + return 0; } @@ -133,6 +138,9 @@ static const struct ieee80211_iface_limit if_limits[] = { { .max = MT7615_MAX_INTERFACES, .types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_STATION) } }; @@ -158,6 +166,48 @@ static int mt7615_init_debugfs(struct mt7615_dev *dev) return 0; } +static void +mt7615_init_txpower(struct mt7615_dev *dev, + struct ieee80211_supported_band *sband) +{ + int i, n_chains = hweight8(dev->mt76.antenna_mask), target_chains; + u8 *eep = (u8 *)dev->mt76.eeprom.data; + enum nl80211_band band = sband->band; + + target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *chan = &sband->channels[i]; + u8 target_power = 0; + int j; + + for (j = 0; j < target_chains; j++) { + int index; + + index = mt7615_eeprom_get_power_index(dev, chan, j); + target_power = max(target_power, eep[index]); + } + + target_power = DIV_ROUND_UP(target_power, 2); + switch (n_chains) { + case 4: + target_power += 6; + break; + case 3: + target_power += 4; + break; + case 2: + target_power += 3; + break; + default: + break; + } + + chan->max_power = min_t(int, chan->max_reg_power, + target_power); + chan->orig_mpwr = target_power; + } +} + int mt7615_register_device(struct mt7615_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); @@ -195,6 +245,9 @@ int mt7615_register_device(struct mt7615_dev *dev) dev->mt76.antenna_mask = 0xf; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_AP); ret = mt76_register_device(&dev->mt76, true, mt7615_rates, @@ -202,6 +255,9 @@ int mt7615_register_device(struct mt7615_dev *dev) if (ret) return ret; + mt7615_init_txpower(dev, &dev->mt76.sband_2g.sband); + mt7615_init_txpower(dev, &dev->mt76.sband_5g.sband); + hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; return mt7615_init_debugfs(dev); @@ -212,6 +268,10 @@ void mt7615_unregister_device(struct mt7615_dev *dev) struct mt76_txwi_cache *txwi; int id; + mt76_unregister_device(&dev->mt76); + mt7615_mcu_exit(dev); + mt7615_dma_cleanup(dev); + spin_lock_bh(&dev->token_lock); idr_for_each_entry(&dev->token, txwi, id) { mt7615_txp_skb_unmap(&dev->mt76, txwi); @@ -221,9 +281,6 @@ void mt7615_unregister_device(struct mt7615_dev *dev) } spin_unlock_bh(&dev->token_lock); idr_destroy(&dev->token); - mt76_unregister_device(&dev->mt76); - mt7615_mcu_exit(dev); - mt7615_dma_cleanup(dev); - ieee80211_free_hw(mt76_hw(dev)); + mt76_free_device(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index b8f48d10f27a..1eb0e9c9970c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -13,6 +13,11 @@ #include "../dma.h" #include "mac.h" +static inline s8 to_rssi(u32 field, u32 rxv) +{ + return (FIELD_GET(field, rxv) - 220) / 2; +} + static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, u8 idx, bool unicast) { @@ -36,54 +41,6 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, return &sta->vif->sta.wcid; } -static int mt7615_get_rate(struct mt7615_dev *dev, - struct ieee80211_supported_band *sband, - int idx, bool cck) -{ - int offset = 0; - int len = sband->n_bitrates; - int i; - - if (cck) { - if (sband == &dev->mt76.sband_5g.sband) - return 0; - - idx &= ~BIT(2); /* short preamble */ - } else if (sband == &dev->mt76.sband_2g.sband) { - offset = 4; - } - - for (i = offset; i < len; i++) { - if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) - return i; - } - - return 0; -} - -static void mt7615_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - int hdr_len = ieee80211_get_hdrlen_from_skb(skb); - u8 *pn = status->iv; - u8 *hdr; - - __skb_push(skb, 8); - memmove(skb->data, skb->data + 8, hdr_len); - hdr = skb->data + hdr_len; - - hdr[0] = pn[5]; - hdr[1] = pn[4]; - hdr[2] = 0; - hdr[3] = 0x20 | (key_id << 6); - hdr[4] = pn[3]; - hdr[5] = pn[2]; - hdr[6] = pn[1]; - hdr[7] = pn[0]; - - status->flag &= ~RX_FLAG_IV_STRIPPED; -} - int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; @@ -96,6 +53,9 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) bool unicast, remove_pad, insert_ccmp_hdr = false; int i, idx; + if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + return -EINVAL; + memset(status, 0, sizeof(*status)); unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; @@ -165,6 +125,7 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { u32 rxdg0 = le32_to_cpu(rxd[0]); u32 rxdg1 = le32_to_cpu(rxd[1]); + u32 rxdg3 = le32_to_cpu(rxd[3]); u8 stbc = FIELD_GET(MT_RXV1_HT_STBC, rxdg0); bool cck = false; @@ -174,7 +135,7 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - i = mt7615_get_rate(dev, sband, i, cck); + i = mt76_get_rate(&dev->mt76, sband, i, cck); break; case MT_PHY_TYPE_HT_GF: case MT_PHY_TYPE_HT: @@ -214,7 +175,21 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; - /* TODO: RSSI */ + status->chains = dev->mt76.antenna_mask; + status->chain_signal[0] = to_rssi(MT_RXV4_RCPI0, rxdg3); + status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3); + status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3); + status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3); + status->signal = status->chain_signal[0]; + + for (i = 1; i < hweight8(dev->mt76.antenna_mask); i++) { + if (!(status->chains & BIT(i))) + continue; + + status->signal = max(status->signal, + status->chain_signal[i]); + } + rxd += 6; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; @@ -225,7 +200,7 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) if (insert_ccmp_hdr) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); - mt7615_insert_ccmp_hdr(skb, key_id); + mt76_insert_ccmp_hdr(skb, key_id); } hdr = (struct ieee80211_hdr *)skb->data; @@ -549,23 +524,20 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, { struct ieee80211_supported_band *sband; int i, idx, count, final_idx = 0; - bool fixed_rate, final_mpdu, ack_timeout; + bool fixed_rate, ack_timeout; bool probe, ampdu, cck = false; u32 final_rate, final_rate_flags, final_nss, txs; - u8 pid; fixed_rate = info->status.rates[0].count; probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); txs = le32_to_cpu(txs_data[1]); - final_mpdu = txs & MT_TXS1_ACKED_MPDU; ampdu = !fixed_rate && (txs & MT_TXS1_AMPDU); txs = le32_to_cpu(txs_data[3]); count = FIELD_GET(MT_TXS3_TX_COUNT, txs); txs = le32_to_cpu(txs_data[0]); - pid = FIELD_GET(MT_TXS0_PID, txs); final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); ack_timeout = txs & MT_TXS0_ACK_TIMEOUT; @@ -628,7 +600,8 @@ out: else sband = &dev->mt76.sband_2g.sband; final_rate &= MT_TX_RATE_IDX; - final_rate = mt7615_get_rate(dev, sband, final_rate, cck); + final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, + cck); final_rate_flags = 0; break; case MT_PHY_TYPE_HT_GF: diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 18ad4b8a3807..b00ce8db58e9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -98,6 +98,11 @@ enum rx_pkt_type { #define MT_RXV2_GROUP_ID GENMASK(26, 21) #define MT_RXV2_LENGTH GENMASK(20, 0) +#define MT_RXV4_RCPI3 GENMASK(31, 24) +#define MT_RXV4_RCPI2 GENMASK(23, 16) +#define MT_RXV4_RCPI1 GENMASK(15, 8) +#define MT_RXV4_RCPI0 GENMASK(7, 0) + enum tx_header_format { MT_HDR_FORMAT_802_3, MT_HDR_FORMAT_CMD, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 80e6b211f60b..b4d6af812c54 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -37,6 +37,7 @@ static int get_omac_idx(enum nl80211_iftype type, u32 mask) switch (type) { case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: /* ap use hw bssid 0 and ext bssid */ if (~mask & BIT(HW_BSSID_0)) return HW_BSSID_0; @@ -77,11 +78,12 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, goto out; } - mvif->omac_idx = get_omac_idx(vif->type, dev->omac_mask); - if (mvif->omac_idx < 0) { + idx = get_omac_idx(vif->type, dev->omac_mask); + if (idx < 0) { ret = -ENOSPC; goto out; } + mvif->omac_idx = idx; /* TODO: DBDC support. Use band 0 and wmm 0 for now */ mvif->band_idx = 0; @@ -93,7 +95,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, dev->vif_mask |= BIT(mvif->idx); dev->omac_mask |= BIT(mvif->omac_idx); - idx = MT7615_WTBL_RESERVED - 1 - mvif->idx; + idx = MT7615_WTBL_RESERVED - mvif->idx; mvif->sta.wcid.idx = idx; mvif->sta.wcid.hw_key_idx = -1; @@ -128,8 +130,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&dev->mt76.mutex); } -static int mt7615_set_channel(struct mt7615_dev *dev, - struct cfg80211_chan_def *def) +static int mt7615_set_channel(struct mt7615_dev *dev) { int ret; @@ -190,28 +191,28 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) struct mt7615_dev *dev = hw->priv; int ret = 0; - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - mutex_lock(&dev->mt76.mutex); + mutex_lock(&dev->mt76.mutex); + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ieee80211_stop_queues(hw); - ret = mt7615_set_channel(dev, &hw->conf.chandef); + ret = mt7615_set_channel(dev); ieee80211_wake_queues(hw); - - mutex_unlock(&dev->mt76.mutex); } - if (changed & IEEE80211_CONF_CHANGE_MONITOR) { - mutex_lock(&dev->mt76.mutex); + if (changed & IEEE80211_CONF_CHANGE_POWER) + ret = mt7615_mcu_set_tx_power(dev); + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) dev->mt76.rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; else dev->mt76.rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); - - mutex_unlock(&dev->mt76.mutex); } + + mutex_unlock(&dev->mt76.mutex); + return ret; } @@ -281,26 +282,18 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&dev->mt76.mutex); - /* TODO: sta mode connect/disconnect - * BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID - */ + if (changed & BSS_CHANGED_ASSOC) + mt7615_mcu_set_bss_info(dev, vif, info->assoc); /* TODO: update beacon content * BSS_CHANGED_BEACON */ if (changed & BSS_CHANGED_BEACON_ENABLED) { - if (info->enable_beacon) { - mt7615_mcu_set_bss_info(dev, vif, 1); - mt7615_mcu_add_wtbl_bmc(dev, vif); - mt7615_mcu_set_sta_rec_bmc(dev, vif, 1); - mt7615_mcu_set_bcn(dev, vif, 1); - } else { - mt7615_mcu_set_sta_rec_bmc(dev, vif, 0); - mt7615_mcu_del_wtbl_bmc(dev, vif); - mt7615_mcu_set_bss_info(dev, vif, 0); - mt7615_mcu_set_bcn(dev, vif, 0); - } + mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon); + mt7615_mcu_wtbl_bmc(dev, vif, info->enable_beacon); + mt7615_mcu_set_sta_rec_bmc(dev, vif, info->enable_beacon); + mt7615_mcu_set_bcn(dev, vif, info->enable_beacon); } mutex_unlock(&dev->mt76.mutex); @@ -343,7 +336,7 @@ void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); mt7615_mcu_set_sta_rec(dev, vif, sta, 0); - mt7615_mcu_del_wtbl(dev, vif, sta); + mt7615_mcu_del_wtbl(dev, sta); } static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, @@ -496,4 +489,5 @@ const struct ieee80211_ops mt7615_ops = { .sw_scan_start = mt7615_sw_scan, .sw_scan_complete = mt7615_sw_scan_complete, .release_buffered_frames = mt76_release_buffered_frames, + .get_txpower = mt76_get_txpower, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index ea67c6022fe6..cdad2c8dc297 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -49,7 +49,7 @@ struct mt7615_fw_trailer { #define FW_START_WORKING_PDA_CR4 BIT(2) static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, int query, int dest, int *wait_seq) + int cmd, int *wait_seq) { struct mt7615_mcu_txd *mcu_txd; u8 seq, q_idx, pkt_fmt; @@ -57,9 +57,6 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, u32 val; __le32 *txd; - if (!skb) - return -EINVAL; - seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; if (!seq) seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; @@ -94,16 +91,15 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, mcu_txd->seq = seq; if (cmd < 0) { + mcu_txd->set_query = MCU_Q_NA; mcu_txd->cid = -cmd; } else { mcu_txd->cid = MCU_CMD_EXT_CID; + mcu_txd->set_query = MCU_Q_SET; mcu_txd->ext_cid = cmd; - if (query != MCU_Q_NA) - mcu_txd->ext_cid_ack = 1; + mcu_txd->ext_cid_ack = 1; } - - mcu_txd->set_query = query; - mcu_txd->s2d_index = dest; + mcu_txd->s2d_index = MCU_S2D_H2N; if (wait_seq) *wait_seq = seq; @@ -116,24 +112,30 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, return mt76_tx_queue_skb_raw(dev, qid, skb, 0); } -static int mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, int query, int dest, - struct sk_buff **skb_ret) +static int +mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, + int len, bool wait_resp) { + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); unsigned long expires = jiffies + 10 * HZ; struct mt7615_mcu_rxd *rxd; + struct sk_buff *skb; int ret, seq; - mutex_lock(&dev->mt76.mmio.mcu.mutex); + skb = mt7615_mcu_msg_alloc(data, len); + if (!skb) + return -ENOMEM; - ret = __mt7615_mcu_msg_send(dev, skb, cmd, query, dest, &seq); + mutex_lock(&mdev->mmio.mcu.mutex); + + ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); if (ret) goto out; - while (1) { - skb = mt76_mcu_get_response(&dev->mt76, expires); + while (wait_resp) { + skb = mt76_mcu_get_response(mdev, expires); if (!skb) { - dev_err(dev->mt76.dev, "Message %d (seq %d) timeout\n", + dev_err(mdev->dev, "Message %d (seq %d) timeout\n", cmd, seq); ret = -ETIMEDOUT; break; @@ -143,23 +145,16 @@ static int mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, if (seq != rxd->seq) continue; - if (skb_ret) { - int hdr_len = sizeof(*rxd); - - if (!test_bit(MT76_STATE_MCU_RUNNING, - &dev->mt76.state)) - hdr_len -= 4; - skb_pull(skb, hdr_len); - *skb_ret = skb; - } else { - dev_kfree_skb(skb); + if (cmd == -MCU_CMD_PATCH_SEM_CONTROL) { + skb_pull(skb, sizeof(*rxd) - 4); + ret = *skb->data; } - + dev_kfree_skb(skb); break; } out: - mutex_unlock(&dev->mt76.mmio.mcu.mutex); + mutex_unlock(&mdev->mmio.mcu.mutex); return ret; } @@ -176,28 +171,22 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, .len = cpu_to_le32(len), .mode = cpu_to_le32(mode), }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, - MCU_Q_NA, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, + &req, sizeof(req), true); } static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, int len) { - struct sk_buff *skb; - int ret = 0; + int ret = 0, cur_len; while (len > 0) { - int cur_len = min_t(int, 4096 - sizeof(struct mt7615_mcu_txd), - len); - - skb = mt7615_mcu_msg_alloc(data, cur_len); - if (!skb) - return -ENOMEM; + cur_len = min_t(int, 4096 - sizeof(struct mt7615_mcu_txd), + len); - ret = __mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER, - MCU_Q_NA, MCU_S2D_H2N, NULL); + ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, + data, cur_len, false); if (ret) break; @@ -218,47 +207,27 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, .option = cpu_to_le32(option), .addr = cpu_to_le32(addr), }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, - MCU_Q_NA, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, + &req, sizeof(req), true); } -static int mt7615_mcu_restart(struct mt7615_dev *dev) +static int mt7615_mcu_restart(struct mt76_dev *dev) { - struct sk_buff *skb = mt7615_mcu_msg_alloc(NULL, 0); - - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ, - MCU_Q_NA, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, NULL, + 0, true); } static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) { struct { - __le32 operation; + __le32 op; } req = { - .operation = cpu_to_le32(get ? PATCH_SEM_GET : - PATCH_SEM_RELEASE), + .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), }; - struct event { - u8 status; - u8 reserved[3]; - } *resp; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - struct sk_buff *skb_ret; - int ret; - ret = mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_SEM_CONTROL, - MCU_Q_NA, MCU_S2D_H2N, &skb_ret); - if (ret) - goto out; - - resp = (struct event *)(skb_ret->data); - ret = resp->status; - dev_kfree_skb(skb_ret); - -out: - return ret; + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_SEM_CONTROL, + &req, sizeof(req), true); } static int mt7615_mcu_start_patch(struct mt7615_dev *dev) @@ -269,10 +238,9 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) } req = { .check_crc = 0, }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ, - MCU_Q_NA, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_FINISH_REQ, + &req, sizeof(req), true); } static int mt7615_driver_own(struct mt7615_dev *dev) @@ -508,8 +476,14 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) int mt7615_mcu_init(struct mt7615_dev *dev) { + static const struct mt76_mcu_ops mt7615_mcu_ops = { + .mcu_send_msg = mt7615_mcu_msg_send, + .mcu_restart = mt7615_mcu_restart, + }; int ret; + dev->mt76.mcu_ops = &mt7615_mcu_ops, + ret = mt7615_driver_own(dev); if (ret) return ret; @@ -525,16 +499,13 @@ int mt7615_mcu_init(struct mt7615_dev *dev) void mt7615_mcu_exit(struct mt7615_dev *dev) { - mt7615_mcu_restart(dev); + __mt76_mcu_restart(&dev->mt76); mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN); skb_queue_purge(&dev->mt76.mmio.mcu.res_q); } int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) { - struct req_data { - u8 val; - } __packed; struct { u8 buffer_mode; u8 pad; @@ -543,23 +514,22 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) .buffer_mode = 1, .len = __MT_EE_MAX - MT_EE_NIC_CONF_0, }; - struct sk_buff *skb; - struct req_data *data; - const int size = (__MT_EE_MAX - MT_EE_NIC_CONF_0) * - sizeof(struct req_data); - u8 *eep = (u8 *)dev->mt76.eeprom.data; - u16 off; - - skb = mt7615_mcu_msg_alloc(NULL, size + sizeof(req_hdr)); - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - data = (struct req_data *)skb_put(skb, size); - memset(data, 0, size); - - for (off = MT_EE_NIC_CONF_0; off < __MT_EE_MAX; off++) - data[off - MT_EE_NIC_CONF_0].val = eep[off]; - - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + int ret, len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; + u8 *req, *eep = (u8 *)dev->mt76.eeprom.data; + + req = kzalloc(len, GFP_KERNEL); + if (!req) + return -ENOMEM; + + memcpy(req, &req_hdr, sizeof(req_hdr)); + memcpy(req + sizeof(req_hdr), eep + MT_EE_NIC_CONF_0, + __MT_EE_MAX - MT_EE_NIC_CONF_0); + + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + req, len, true); + kfree(req); + + return ret; } int mt7615_mcu_init_mac(struct mt7615_dev *dev) @@ -572,10 +542,9 @@ int mt7615_mcu_init_mac(struct mt7615_dev *dev) .enable = 1, .band = 0, }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL, - MCU_Q_SET, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, + &req, sizeof(req), true); } int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) @@ -592,10 +561,9 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) .len_thresh = cpu_to_le32(val), .pkt_thresh = cpu_to_le32(0x2), }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL, - MCU_Q_SET, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, + &req, sizeof(req), true); } int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, @@ -621,7 +589,6 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, .aifs = params->aifs, .txop = cpu_to_le16(params->txop), }; - struct sk_buff *skb; if (params->cw_min) { req.valid |= WMM_CW_MIN_SET; @@ -632,9 +599,8 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, req.cw_max = cpu_to_le16(params->cw_max); } - skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) @@ -662,300 +628,200 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, .band_idx = 0, }; - struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL, - MCU_Q_SET, MCU_S2D_H2N, NULL); -} - -static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev, - struct dev_info *dev_info) -{ - struct req_hdr { - u8 omac_idx; - u8 band_idx; - __le16 tlv_num; - u8 is_tlv_append; - u8 rsv[3]; - } __packed req_hdr = {0}; - struct req_tlv { - __le16 tag; - __le16 len; - u8 active; - u8 band_idx; - u8 omac_addr[ETH_ALEN]; - } __packed; - struct sk_buff *skb; - u16 tlv_num = 0; - - skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + - sizeof(struct req_tlv)); - skb_reserve(skb, sizeof(req_hdr)); - - if (dev_info->feature & BIT(DEV_INFO_ACTIVE)) { - struct req_tlv req_tlv = { - .tag = cpu_to_le16(DEV_INFO_ACTIVE), - .len = cpu_to_le16(sizeof(req_tlv)), - .active = dev_info->enable, - .band_idx = dev_info->band_idx, - }; - memcpy(req_tlv.omac_addr, dev_info->omac_addr, ETH_ALEN); - memcpy(skb_put(skb, sizeof(req_tlv)), &req_tlv, - sizeof(req_tlv)); - tlv_num++; - } - - req_hdr.omac_idx = dev_info->omac_idx; - req_hdr.band_idx = dev_info->band_idx; - req_hdr.tlv_num = cpu_to_le16(tlv_num); - req_hdr.is_tlv_append = tlv_num ? 1 : 0; - memcpy(skb_push(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, + &req, sizeof(req), true); } -int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en) +int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct dev_info dev_info = {0}; - - dev_info.omac_idx = mvif->omac_idx; - memcpy(dev_info.omac_addr, vif->addr, ETH_ALEN); - dev_info.band_idx = mvif->band_idx; - dev_info.enable = en; - dev_info.feature = BIT(DEV_INFO_ACTIVE); + struct { + struct req_hdr { + u8 omac_idx; + u8 band_idx; + __le16 tlv_num; + u8 is_tlv_append; + u8 rsv[3]; + } __packed hdr; + struct req_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 band_idx; + u8 omac_addr[ETH_ALEN]; + } __packed tlv; + } data = { + .hdr = { + .omac_idx = mvif->omac_idx, + .band_idx = mvif->band_idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + }, + .tlv = { + .tag = cpu_to_le16(DEV_INFO_ACTIVE), + .len = cpu_to_le16(sizeof(struct req_tlv)), + .active = enable, + .band_idx = mvif->band_idx, + }, + }; - return __mt7615_mcu_set_dev_info(dev, &dev_info); + memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, + &data, sizeof(data), true); } -static void bss_info_omac_handler (struct mt7615_dev *dev, - struct bss_info *bss_info, - struct sk_buff *skb) +static void +mt7615_mcu_bss_info_omac_header(struct mt7615_vif *mvif, u8 *data, + u32 conn_type) { - struct bss_info_omac tlv = {0}; - - tlv.tag = cpu_to_le16(BSS_INFO_OMAC); - tlv.len = cpu_to_le16(sizeof(tlv)); - tlv.hw_bss_idx = (bss_info->omac_idx > EXT_BSSID_START) ? - HW_BSSID_0 : bss_info->omac_idx; - tlv.omac_idx = bss_info->omac_idx; - tlv.band_idx = bss_info->band_idx; - tlv.conn_type = cpu_to_le32(bss_info->conn_type); - - memcpy(skb_put(skb, sizeof(tlv)), &tlv, sizeof(tlv)); + struct bss_info_omac *hdr = (struct bss_info_omac *)data; + u8 idx; + + idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; + hdr->tag = cpu_to_le16(BSS_INFO_OMAC); + hdr->len = cpu_to_le16(sizeof(struct bss_info_omac)); + hdr->hw_bss_idx = idx; + hdr->omac_idx = mvif->omac_idx; + hdr->band_idx = mvif->band_idx; + hdr->conn_type = cpu_to_le32(conn_type); } -static void bss_info_basic_handler (struct mt7615_dev *dev, - struct bss_info *bss_info, - struct sk_buff *skb) +static void +mt7615_mcu_bss_info_basic_header(struct ieee80211_vif *vif, u8 *data, + u32 net_type, u8 tx_wlan_idx, + bool enable) { - struct bss_info_basic tlv = {0}; - - tlv.tag = cpu_to_le16(BSS_INFO_BASIC); - tlv.len = cpu_to_le16(sizeof(tlv)); - tlv.network_type = cpu_to_le32(bss_info->network_type); - tlv.active = bss_info->enable; - tlv.bcn_interval = cpu_to_le16(bss_info->bcn_interval); - memcpy(tlv.bssid, bss_info->bssid, ETH_ALEN); - tlv.wmm_idx = bss_info->wmm_idx; - tlv.dtim_period = bss_info->dtim_period; - tlv.bmc_tx_wlan_idx = bss_info->bmc_tx_wlan_idx; - - memcpy(skb_put(skb, sizeof(tlv)), &tlv, sizeof(tlv)); + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct bss_info_basic *hdr = (struct bss_info_basic *)data; + + hdr->tag = cpu_to_le16(BSS_INFO_BASIC); + hdr->len = cpu_to_le16(sizeof(struct bss_info_basic)); + hdr->network_type = cpu_to_le32(net_type); + hdr->active = enable; + hdr->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + memcpy(hdr->bssid, vif->bss_conf.bssid, ETH_ALEN); + hdr->wmm_idx = mvif->wmm_idx; + hdr->dtim_period = vif->bss_conf.dtim_period; + hdr->bmc_tx_wlan_idx = tx_wlan_idx; } -static void bss_info_ext_bss_handler (struct mt7615_dev *dev, - struct bss_info *bss_info, - struct sk_buff *skb) +static void +mt7615_mcu_bss_info_ext_header(struct mt7615_vif *mvif, u8 *data) { /* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ #define BCN_TX_ESTIMATE_TIME (4096 + 20) - struct bss_info_ext_bss tlv = {0}; - int ext_bss_idx; - - ext_bss_idx = bss_info->omac_idx - EXT_BSSID_START; + struct bss_info_ext_bss *hdr = (struct bss_info_ext_bss *)data; + int ext_bss_idx, tsf_offset; + ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; if (ext_bss_idx < 0) return; - tlv.tag = cpu_to_le16(BSS_INFO_EXT_BSS); - tlv.len = cpu_to_le16(sizeof(tlv)); - tlv.mbss_tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; - - memcpy(skb_put(skb, sizeof(tlv)), &tlv, sizeof(tlv)); + hdr->tag = cpu_to_le16(BSS_INFO_EXT_BSS); + hdr->len = cpu_to_le16(sizeof(struct bss_info_ext_bss)); + tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; + hdr->mbss_tsf_offset = cpu_to_le32(tsf_offset); } -static struct bss_info_tag_handler bss_info_tag_handler[] = { - {BSS_INFO_OMAC, sizeof(struct bss_info_omac), bss_info_omac_handler}, - {BSS_INFO_BASIC, sizeof(struct bss_info_basic), bss_info_basic_handler}, - {BSS_INFO_RF_CH, sizeof(struct bss_info_rf_ch), NULL}, - {BSS_INFO_PM, 0, NULL}, - {BSS_INFO_UAPSD, 0, NULL}, - {BSS_INFO_ROAM_DETECTION, 0, NULL}, - {BSS_INFO_LQ_RM, 0, NULL}, - {BSS_INFO_EXT_BSS, sizeof(struct bss_info_ext_bss), bss_info_ext_bss_handler}, - {BSS_INFO_BMC_INFO, 0, NULL}, - {BSS_INFO_SYNC_MODE, 0, NULL}, - {BSS_INFO_RA, 0, NULL}, - {BSS_INFO_MAX_NUM, 0, NULL}, -}; - -static int __mt7615_mcu_set_bss_info(struct mt7615_dev *dev, - struct bss_info *bss_info) +int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, + struct ieee80211_vif *vif, int en) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct req_hdr { u8 bss_idx; u8 rsv0; __le16 tlv_num; u8 is_tlv_append; u8 rsv1[3]; - } __packed req_hdr = {0}; - struct sk_buff *skb; - u16 tlv_num = 0; - u32 size = 0; - int i; + } __packed; + int len = sizeof(struct req_hdr) + sizeof(struct bss_info_basic); + int ret, i, features = BIT(BSS_INFO_BASIC), ntlv = 1; + u32 conn_type = 0, net_type = NETWORK_INFRA; + u8 *buf, *data, tx_wlan_idx = 0; + struct req_hdr *hdr; - for (i = 0; i < BSS_INFO_MAX_NUM; i++) - if ((BIT(bss_info_tag_handler[i].tag) & bss_info->feature) && - bss_info_tag_handler[i].handler) { - tlv_num++; - size += bss_info_tag_handler[i].len; + if (en) { + len += sizeof(struct bss_info_omac); + features |= BIT(BSS_INFO_OMAC); + if (mvif->omac_idx > EXT_BSSID_START) { + len += sizeof(struct bss_info_ext_bss); + features |= BIT(BSS_INFO_EXT_BSS); + ntlv++; } + ntlv++; + } - skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + size); - - req_hdr.bss_idx = bss_info->bss_idx; - req_hdr.tlv_num = cpu_to_le16(tlv_num); - req_hdr.is_tlv_append = tlv_num ? 1 : 0; - - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - - for (i = 0; i < BSS_INFO_MAX_NUM; i++) - if ((BIT(bss_info_tag_handler[i].tag) & bss_info->feature) && - bss_info_tag_handler[i].handler) - bss_info_tag_handler[i].handler(dev, bss_info, skb); - - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); -} - -static void bss_info_convert_vif_type(enum nl80211_iftype type, - u32 *network_type, u32 *conn_type) -{ - switch (type) { + switch (vif->type) { case NL80211_IFTYPE_AP: - if (network_type) - *network_type = NETWORK_INFRA; - if (conn_type) - *conn_type = CONNECTION_INFRA_AP; + case NL80211_IFTYPE_MESH_POINT: + tx_wlan_idx = mvif->sta.wcid.idx; + conn_type = CONNECTION_INFRA_AP; break; - case NL80211_IFTYPE_STATION: - if (network_type) - *network_type = NETWORK_INFRA; - if (conn_type) - *conn_type = CONNECTION_INFRA_STA; + case NL80211_IFTYPE_STATION: { + /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ + if (en) { + struct ieee80211_sta *sta; + struct mt7615_sta *msta; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (!sta) { + rcu_read_unlock(); + return -EINVAL; + } + + msta = (struct mt7615_sta *)sta->drv_priv; + tx_wlan_idx = msta->wcid.idx; + rcu_read_unlock(); + } + conn_type = CONNECTION_INFRA_STA; break; + } default: WARN_ON(1); break; - }; -} - -int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct bss_info bss_info = {0}; - u8 bmc_tx_wlan_idx = 0; - u32 network_type = 0, conn_type = 0; - - if (vif->type == NL80211_IFTYPE_AP) { - bmc_tx_wlan_idx = mvif->sta.wcid.idx; - } else if (vif->type == NL80211_IFTYPE_STATION) { - /* find the unicast entry for sta mode bmc tx */ - struct ieee80211_sta *ap_sta; - struct mt7615_sta *msta; - - rcu_read_lock(); - - ap_sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); - if (!ap_sta) { - rcu_read_unlock(); - return -EINVAL; - } - - msta = (struct mt7615_sta *)ap_sta->drv_priv; - bmc_tx_wlan_idx = msta->wcid.idx; - - rcu_read_unlock(); - } else { - WARN_ON(1); } - bss_info_convert_vif_type(vif->type, &network_type, &conn_type); - - bss_info.bss_idx = mvif->idx; - memcpy(bss_info.bssid, vif->bss_conf.bssid, ETH_ALEN); - bss_info.omac_idx = mvif->omac_idx; - bss_info.band_idx = mvif->band_idx; - bss_info.bmc_tx_wlan_idx = bmc_tx_wlan_idx; - bss_info.wmm_idx = mvif->wmm_idx; - bss_info.network_type = network_type; - bss_info.conn_type = conn_type; - bss_info.bcn_interval = vif->bss_conf.beacon_int; - bss_info.dtim_period = vif->bss_conf.dtim_period; - bss_info.enable = en; - bss_info.feature = BIT(BSS_INFO_BASIC); - if (en) { - bss_info.feature |= BIT(BSS_INFO_OMAC); - if (mvif->omac_idx > EXT_BSSID_START) - bss_info.feature |= BIT(BSS_INFO_EXT_BSS); - } - - return __mt7615_mcu_set_bss_info(dev, &bss_info); -} + buf = kzalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; -static int __mt7615_mcu_set_wtbl(struct mt7615_dev *dev, int wlan_idx, - int operation, void *buf, int buf_len) -{ - struct req_hdr { - u8 wlan_idx; - u8 operation; - __le16 tlv_num; - u8 rsv[4]; - } __packed req_hdr = {0}; - struct tlv { - __le16 tag; - __le16 len; - u8 buf[0]; - } __packed; - struct sk_buff *skb; - u16 tlv_num = 0; - int offset = 0; + hdr = (struct req_hdr *)buf; + hdr->bss_idx = mvif->idx; + hdr->tlv_num = cpu_to_le16(ntlv); + hdr->is_tlv_append = 1; - while (offset < buf_len) { - struct tlv *tlv = (struct tlv *)((u8 *)buf + offset); + data = buf + sizeof(*hdr); + for (i = 0; i < BSS_INFO_MAX_NUM; i++) { + int tag = ffs(features & BIT(i)) - 1; - tlv_num++; - offset += tlv->len; + switch (tag) { + case BSS_INFO_OMAC: + mt7615_mcu_bss_info_omac_header(mvif, data, + conn_type); + data += sizeof(struct bss_info_omac); + break; + case BSS_INFO_BASIC: + mt7615_mcu_bss_info_basic_header(vif, data, net_type, + tx_wlan_idx, en); + data += sizeof(struct bss_info_basic); + break; + case BSS_INFO_EXT_BSS: + mt7615_mcu_bss_info_ext_header(mvif, data); + data += sizeof(struct bss_info_ext_bss); + break; + default: + break; + } } - skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + buf_len); - - req_hdr.wlan_idx = wlan_idx; - req_hdr.operation = operation; - req_hdr.tlv_num = cpu_to_le16(tlv_num); - - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - - if (buf && buf_len) - memcpy(skb_put(skb, buf_len), buf, buf_len); + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BSS_INFO_UPDATE, + buf, len, true); + kfree(buf); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + return ret; } static enum mt7615_cipher_type @@ -995,70 +861,90 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, struct ieee80211_key_conf *key, enum set_key_cmd cmd) { - struct wtbl_sec_key wtbl_sec_key = {0}; - int buf_len = sizeof(struct wtbl_sec_key); - u8 cipher; - - wtbl_sec_key.tag = cpu_to_le16(WTBL_SEC_KEY); - wtbl_sec_key.len = cpu_to_le16(buf_len); - wtbl_sec_key.add = cmd; + struct { + struct wtbl_req_hdr hdr; + struct wtbl_sec_key key; + } req = { + .hdr = { + .wlan_idx = wcid, + .operation = WTBL_SET, + .tlv_num = cpu_to_le16(1), + }, + .key = { + .tag = cpu_to_le16(WTBL_SEC_KEY), + .len = cpu_to_le16(sizeof(struct wtbl_sec_key)), + .add = cmd, + }, + }; if (cmd == SET_KEY) { - cipher = mt7615_get_key_info(key, wtbl_sec_key.key_material); - if (cipher == MT_CIPHER_NONE && key) + u8 cipher; + + cipher = mt7615_get_key_info(key, req.key.key_material); + if (cipher == MT_CIPHER_NONE) return -EOPNOTSUPP; - wtbl_sec_key.cipher_id = cipher; - wtbl_sec_key.key_id = key->keyidx; - wtbl_sec_key.key_len = key->keylen; + req.key.rkv = 1; + req.key.cipher_id = cipher; + req.key.key_id = key->keyidx; + req.key.key_len = key->keylen; } else { - wtbl_sec_key.key_len = sizeof(wtbl_sec_key.key_material); + req.key.key_len = sizeof(req.key.key_material); } - return __mt7615_mcu_set_wtbl(dev, wcid, WTBL_SET, &wtbl_sec_key, - buf_len); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } -int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) +static int +mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, + struct mt7615_vif *mvif) { - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct wtbl_generic *wtbl_generic; - struct wtbl_rx *wtbl_rx; - int buf_len, ret; - u8 *buf; - - buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - wtbl_generic = (struct wtbl_generic *)buf; - buf_len = sizeof(*wtbl_generic); - wtbl_generic->tag = cpu_to_le16(WTBL_GENERIC); - wtbl_generic->len = cpu_to_le16(buf_len); - eth_broadcast_addr(wtbl_generic->peer_addr); - wtbl_generic->muar_idx = 0xe; - - wtbl_rx = (struct wtbl_rx *)(buf + buf_len); - buf_len += sizeof(*wtbl_rx); - wtbl_rx->tag = cpu_to_le16(WTBL_RX); - wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); - wtbl_rx->rca1 = 1; - wtbl_rx->rca2 = 1; - wtbl_rx->rv = 1; - - ret = __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, - WTBL_RESET_AND_SET, buf, buf_len); + struct { + struct wtbl_req_hdr hdr; + struct wtbl_generic g_wtbl; + struct wtbl_rx rx_wtbl; + } req = { + .hdr = { + .wlan_idx = mvif->sta.wcid.idx, + .operation = WTBL_RESET_AND_SET, + .tlv_num = cpu_to_le16(2), + }, + .g_wtbl = { + .tag = cpu_to_le16(WTBL_GENERIC), + .len = cpu_to_le16(sizeof(struct wtbl_generic)), + .muar_idx = 0xe, + }, + .rx_wtbl = { + .tag = cpu_to_le16(WTBL_RX), + .len = cpu_to_le16(sizeof(struct wtbl_rx)), + .rca1 = 1, + .rca2 = 1, + .rv = 1, + }, + }; + eth_broadcast_addr(req.g_wtbl.peer_addr); - kfree(buf); - return ret; + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } -int mt7615_mcu_del_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) +int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - return __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, - WTBL_RESET_AND_SET, NULL, 0); + if (!enable) { + struct wtbl_req_hdr req = { + .wlan_idx = mvif->sta.wcid.idx, + .operation = WTBL_RESET_AND_SET, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); + } + + return mt7615_mcu_add_wtbl_bmc(dev, mvif); } int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -1066,175 +952,153 @@ int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct wtbl_generic *wtbl_generic; - struct wtbl_rx *wtbl_rx; - int buf_len, ret; - u8 *buf; - - buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - wtbl_generic = (struct wtbl_generic *)buf; - buf_len = sizeof(*wtbl_generic); - wtbl_generic->tag = cpu_to_le16(WTBL_GENERIC); - wtbl_generic->len = cpu_to_le16(buf_len); - memcpy(wtbl_generic->peer_addr, sta->addr, ETH_ALEN); - wtbl_generic->muar_idx = mvif->omac_idx; - wtbl_generic->qos = sta->wme; - wtbl_generic->partial_aid = cpu_to_le16(sta->aid); - - wtbl_rx = (struct wtbl_rx *)(buf + buf_len); - buf_len += sizeof(*wtbl_rx); - wtbl_rx->tag = cpu_to_le16(WTBL_RX); - wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); - wtbl_rx->rca1 = (vif->type == NL80211_IFTYPE_AP) ? 0 : 1; - wtbl_rx->rca2 = 1; - wtbl_rx->rv = 1; - - ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, - WTBL_RESET_AND_SET, buf, buf_len); + struct { + struct wtbl_req_hdr hdr; + struct wtbl_generic g_wtbl; + struct wtbl_rx rx_wtbl; + } req = { + .hdr = { + .wlan_idx = msta->wcid.idx, + .operation = WTBL_RESET_AND_SET, + .tlv_num = cpu_to_le16(2), + }, + .g_wtbl = { + .tag = cpu_to_le16(WTBL_GENERIC), + .len = cpu_to_le16(sizeof(struct wtbl_generic)), + .muar_idx = mvif->omac_idx, + .qos = sta->wme, + .partial_aid = cpu_to_le16(sta->aid), + }, + .rx_wtbl = { + .tag = cpu_to_le16(WTBL_RX), + .len = cpu_to_le16(sizeof(struct wtbl_rx)), + .rca1 = vif->type != NL80211_IFTYPE_AP, + .rca2 = 1, + .rv = 1, + }, + }; + memcpy(req.g_wtbl.peer_addr, sta->addr, ETH_ALEN); - kfree(buf); - return ret; + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, +int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_sta *sta) { struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct wtbl_req_hdr req = { + .wlan_idx = msta->wcid.idx, + .operation = WTBL_RESET_AND_SET, + }; - return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, - WTBL_RESET_AND_SET, NULL, 0); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) { - return __mt7615_mcu_set_wtbl(dev, 0, WTBL_RESET_ALL, NULL, 0); -} - -static int __mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, - int wlan_idx, int muar_idx, void *buf, - int buf_len) -{ - struct req_hdr { - u8 bss_idx; - u8 wlan_idx; - __le16 tlv_num; - u8 is_tlv_append; - u8 muar_idx; - u8 rsv[2]; - } __packed req_hdr = {0}; - struct tlv { - __le16 tag; - __le16 len; - u8 buf[0]; - } __packed; - struct sk_buff *skb; - u16 tlv_num = 0; - int offset = 0; - - while (offset < buf_len) { - struct tlv *tlv = (struct tlv *)((u8 *)buf + offset); - - tlv_num++; - offset += tlv->len; - } - - skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + buf_len); - - req_hdr.bss_idx = bss_idx; - req_hdr.wlan_idx = wlan_idx; - req_hdr.tlv_num = cpu_to_le16(tlv_num); - req_hdr.is_tlv_append = tlv_num ? 1 : 0; - req_hdr.muar_idx = muar_idx; - - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - - if (buf && buf_len) - memcpy(skb_put(skb, buf_len), buf, buf_len); + struct wtbl_req_hdr req = { + .operation = WTBL_RESET_ALL, + }; - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE, - MCU_Q_SET, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool en) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct sta_rec_basic sta_rec_basic = {0}; - int buf_len = sizeof(struct sta_rec_basic); + struct { + struct sta_req_hdr hdr; + struct sta_rec_basic basic; + } req = { + .hdr = { + .bss_idx = mvif->idx, + .wlan_idx = mvif->sta.wcid.idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + .muar_idx = mvif->omac_idx, + }, + .basic = { + .tag = cpu_to_le16(STA_REC_BASIC), + .len = cpu_to_le16(sizeof(struct sta_rec_basic)), + .conn_type = cpu_to_le32(CONNECTION_INFRA_BC), + }, + }; + eth_broadcast_addr(req.basic.peer_addr); - sta_rec_basic.tag = cpu_to_le16(STA_REC_BASIC); - sta_rec_basic.len = cpu_to_le16(buf_len); - sta_rec_basic.conn_type = cpu_to_le32(CONNECTION_INFRA_BC); - eth_broadcast_addr(sta_rec_basic.peer_addr); if (en) { - sta_rec_basic.conn_state = CONN_STATE_PORT_SECURE; - sta_rec_basic.extra_info = - cpu_to_le16(EXTRA_INFO_VER | EXTRA_INFO_NEW); + req.basic.conn_state = CONN_STATE_PORT_SECURE; + req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | + EXTRA_INFO_NEW); } else { - sta_rec_basic.conn_state = CONN_STATE_DISCONNECT; - sta_rec_basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); + req.basic.conn_state = CONN_STATE_DISCONNECT; + req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); } - return __mt7615_mcu_set_sta_rec(dev, mvif->idx, mvif->sta.wcid.idx, - mvif->omac_idx, &sta_rec_basic, - buf_len); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + &req, sizeof(req), true); } -static void sta_rec_convert_vif_type(enum nl80211_iftype type, u32 *conn_type) +int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool en) { - switch (type) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + + struct { + struct sta_req_hdr hdr; + struct sta_rec_basic basic; + } req = { + .hdr = { + .bss_idx = mvif->idx, + .wlan_idx = msta->wcid.idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + .muar_idx = mvif->omac_idx, + }, + .basic = { + .tag = cpu_to_le16(STA_REC_BASIC), + .len = cpu_to_le16(sizeof(struct sta_rec_basic)), + .qos = sta->wme, + .aid = cpu_to_le16(sta->aid), + }, + }; + memcpy(req.basic.peer_addr, sta->addr, ETH_ALEN); + + switch (vif->type) { case NL80211_IFTYPE_AP: - if (conn_type) - *conn_type = CONNECTION_INFRA_STA; + case NL80211_IFTYPE_MESH_POINT: + req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_STA); break; case NL80211_IFTYPE_STATION: - if (conn_type) - *conn_type = CONNECTION_INFRA_AP; + req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP); break; default: WARN_ON(1); break; }; -} - -int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool en) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct sta_rec_basic sta_rec_basic = {0}; - int buf_len = sizeof(struct sta_rec_basic); - u32 conn_type = 0; - - sta_rec_convert_vif_type(vif->type, &conn_type); - - sta_rec_basic.tag = cpu_to_le16(STA_REC_BASIC); - sta_rec_basic.len = cpu_to_le16(buf_len); - sta_rec_basic.conn_type = cpu_to_le32(conn_type); - sta_rec_basic.qos = sta->wme; - sta_rec_basic.aid = cpu_to_le16(sta->aid); - memcpy(sta_rec_basic.peer_addr, sta->addr, ETH_ALEN); if (en) { - sta_rec_basic.conn_state = CONN_STATE_PORT_SECURE; - sta_rec_basic.extra_info = - cpu_to_le16(EXTRA_INFO_VER | EXTRA_INFO_NEW); + req.basic.conn_state = CONN_STATE_PORT_SECURE; + req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | + EXTRA_INFO_NEW); } else { - sta_rec_basic.conn_state = CONN_STATE_DISCONNECT; - sta_rec_basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); + req.basic.conn_state = CONN_STATE_DISCONNECT; + req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); } - return __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, &sta_rec_basic, - buf_len); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + &req, sizeof(req), true); } int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, int en) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; struct req { u8 omac_idx; u8 enable; @@ -1250,14 +1114,18 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, /* bss color change */ u8 bcc_cnt; __le16 bcc_ie_pos; - } __packed req = {0}; - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt76_wcid *wcid = &dev->mt76.global_wcid; + } __packed req = { + .omac_idx = mvif->omac_idx, + .enable = en, + .wlan_idx = wcid->idx, + .band_idx = mvif->band_idx, + /* pky_type: 0 for bcn, 1 for tim */ + .pkt_type = 0, + }; struct sk_buff *skb; - u16 tim_off, tim_len; - - skb = ieee80211_beacon_get_tim(mt76_hw(dev), vif, &tim_off, &tim_len); + u16 tim_off; + skb = ieee80211_beacon_get_tim(mt76_hw(dev), vif, &tim_off, NULL); if (!skb) return -EINVAL; @@ -1270,21 +1138,79 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, 0, NULL); memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); - dev_kfree_skb(skb); - - req.omac_idx = mvif->omac_idx; - req.enable = en; - req.wlan_idx = wcid->idx; - req.band_idx = mvif->band_idx; - /* pky_type: 0 for bcn, 1 for tim */ - req.pkt_type = 0; req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + tim_off); - skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + dev_kfree_skb(skb); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, + &req, sizeof(req), true); +} + +int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) +{ + int i, ret, n_chains = hweight8(dev->mt76.antenna_mask); + struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + int freq = chandef->center_freq1, len, target_chains; + u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data; + enum nl80211_band band = chandef->chan->band; + struct ieee80211_hw *hw = mt76_hw(dev); + struct { + u8 center_chan; + u8 dbdc_idx; + u8 band; + u8 rsv; + } __packed req_hdr = { + .center_chan = ieee80211_frequency_to_channel(freq), + .band = band, + }; + s8 tx_power; + + len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; + req = kzalloc(len, GFP_KERNEL); + if (!req) + return -ENOMEM; - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD, - MCU_Q_SET, MCU_S2D_H2N, NULL); + memcpy(req, &req_hdr, sizeof(req_hdr)); + data = req + sizeof(req_hdr); + memcpy(data, eep + MT_EE_NIC_CONF_0, + __MT_EE_MAX - MT_EE_NIC_CONF_0); + + tx_power = hw->conf.power_level * 2; + switch (n_chains) { + case 4: + tx_power -= 12; + break; + case 3: + tx_power -= 8; + break; + case 2: + tx_power -= 6; + break; + default: + break; + } + tx_power = max_t(s8, tx_power, 0); + dev->mt76.txpower_cur = tx_power; + + target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; + for (i = 0; i < target_chains; i++) { + int index = -MT_EE_NIC_CONF_0; + + ret = mt7615_eeprom_get_power_index(dev, chandef->chan, i); + if (ret < 0) + goto out; + + index += ret; + data[index] = min_t(u8, data[index], tx_power); + } + + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, + req, len, true); +out: + kfree(req); + + return ret; } int mt7615_mcu_set_channel(struct mt7615_dev *dev) @@ -1309,7 +1235,6 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) u8 txpower_sku[53]; u8 rsv2[3]; } req = {0}; - struct sk_buff *skb; int ret; req.control_chan = chdef->chan->hw_value; @@ -1345,18 +1270,15 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) default: req.bw = CMD_CBW_20MHZ; } - memset(req.txpower_sku, 0x3f, 49); - skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, - MCU_Q_SET, MCU_S2D_H2N, NULL); + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, + &req, sizeof(req), true); if (ret) return ret; - skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); - return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH, - MCU_Q_SET, MCU_S2D_H2N, NULL); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RX_PATH, + &req, sizeof(req), true); } int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -1364,10 +1286,12 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, { struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct wtbl_ht *wtbl_ht; + struct wtbl_req_hdr *wtbl_hdr; + struct sta_req_hdr *sta_hdr; struct wtbl_raw *wtbl_raw; - struct sta_rec_ht *sta_rec_ht; - int buf_len, ret; + struct sta_rec_ht *sta_ht; + struct wtbl_ht *wtbl_ht; + int buf_len, ret, ntlv = 2; u32 msk, val = 0; u8 *buf; @@ -1375,15 +1299,20 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, if (!buf) return -ENOMEM; + wtbl_hdr = (struct wtbl_req_hdr *)buf; + wtbl_hdr->wlan_idx = msta->wcid.idx; + wtbl_hdr->operation = WTBL_SET; + buf_len = sizeof(*wtbl_hdr); + /* ht basic */ - buf_len = sizeof(*wtbl_ht); - wtbl_ht = (struct wtbl_ht *)buf; + wtbl_ht = (struct wtbl_ht *)(buf + buf_len); wtbl_ht->tag = cpu_to_le16(WTBL_HT); wtbl_ht->len = cpu_to_le16(sizeof(*wtbl_ht)); wtbl_ht->ht = 1; wtbl_ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; wtbl_ht->af = sta->ht_cap.ampdu_factor; wtbl_ht->mm = sta->ht_cap.ampdu_density; + buf_len += sizeof(*wtbl_ht); if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) val |= MT_WTBL_W5_SHORT_GI_20; @@ -1400,6 +1329,7 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_vht->len = cpu_to_le16(sizeof(*wtbl_vht)); wtbl_vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC; wtbl_vht->vht = 1; + ntlv++; if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) val |= MT_WTBL_W5_SHORT_GI_80; @@ -1416,6 +1346,7 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_smps->tag = cpu_to_le16(WTBL_SMPS); wtbl_smps->len = cpu_to_le16(sizeof(*wtbl_smps)); wtbl_smps->smps = 1; + ntlv++; } /* sgi */ @@ -1431,38 +1362,46 @@ int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_raw->msk = cpu_to_le32(~msk); wtbl_raw->val = cpu_to_le32(val); - ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, buf, - buf_len); - if (ret) { - kfree(buf); - return ret; - } + wtbl_hdr->tlv_num = cpu_to_le16(ntlv); + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + buf, buf_len, true); + if (ret) + goto out; memset(buf, 0, MT7615_WTBL_UPDATE_MAX_SIZE); - buf_len = sizeof(*sta_rec_ht); - sta_rec_ht = (struct sta_rec_ht *)buf; - sta_rec_ht->tag = cpu_to_le16(STA_REC_HT); - sta_rec_ht->len = cpu_to_le16(sizeof(*sta_rec_ht)); - sta_rec_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + sta_hdr = (struct sta_req_hdr *)buf; + sta_hdr->bss_idx = mvif->idx; + sta_hdr->wlan_idx = msta->wcid.idx; + sta_hdr->is_tlv_append = 1; + ntlv = sta->vht_cap.vht_supported ? 2 : 1; + sta_hdr->tlv_num = cpu_to_le16(ntlv); + sta_hdr->muar_idx = mvif->omac_idx; + buf_len = sizeof(*sta_hdr); + + sta_ht = (struct sta_rec_ht *)(buf + buf_len); + sta_ht->tag = cpu_to_le16(STA_REC_HT); + sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); + sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + buf_len += sizeof(*sta_ht); if (sta->vht_cap.vht_supported) { - struct sta_rec_vht *sta_rec_vht; - - sta_rec_vht = (struct sta_rec_vht *)(buf + buf_len); - buf_len += sizeof(*sta_rec_vht); - sta_rec_vht->tag = cpu_to_le16(STA_REC_VHT); - sta_rec_vht->len = cpu_to_le16(sizeof(*sta_rec_vht)); - sta_rec_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); - sta_rec_vht->vht_rx_mcs_map = - cpu_to_le16(sta->vht_cap.vht_mcs.rx_mcs_map); - sta_rec_vht->vht_tx_mcs_map = - cpu_to_le16(sta->vht_cap.vht_mcs.tx_mcs_map); + struct sta_rec_vht *sta_vht; + + sta_vht = (struct sta_rec_vht *)(buf + buf_len); + buf_len += sizeof(*sta_vht); + sta_vht->tag = cpu_to_le16(STA_REC_VHT); + sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); + sta_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); + sta_vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; + sta_vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; } - ret = __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, buf, buf_len); + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + buf, buf_len, true); +out: kfree(buf); + return ret; } @@ -1470,98 +1409,128 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, struct ieee80211_ampdu_params *params, bool add) { - struct ieee80211_sta *sta = params->sta; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; struct mt7615_vif *mvif = msta->vif; - u8 ba_range[8] = {4, 8, 12, 24, 36, 48, 54, 64}; - u16 tid = params->tid; - u16 ba_size = params->buf_size; - u16 ssn = params->ssn; - struct wtbl_ba wtbl_ba = {0}; - struct sta_rec_ba sta_rec_ba = {0}; - int ret, buf_len; - - buf_len = sizeof(struct wtbl_ba); - - wtbl_ba.tag = cpu_to_le16(WTBL_BA); - wtbl_ba.len = cpu_to_le16(buf_len); - wtbl_ba.tid = tid; - wtbl_ba.ba_type = MT_BA_TYPE_ORIGINATOR; + struct { + struct wtbl_req_hdr hdr; + struct wtbl_ba ba; + } wtbl_req = { + .hdr = { + .wlan_idx = msta->wcid.idx, + .operation = WTBL_SET, + .tlv_num = cpu_to_le16(1), + }, + .ba = { + .tag = cpu_to_le16(WTBL_BA), + .len = cpu_to_le16(sizeof(struct wtbl_ba)), + .tid = params->tid, + .ba_type = MT_BA_TYPE_ORIGINATOR, + .sn = add ? cpu_to_le16(params->ssn) : 0, + .ba_en = add, + }, + }; + struct { + struct sta_req_hdr hdr; + struct sta_rec_ba ba; + } sta_req = { + .hdr = { + .bss_idx = mvif->idx, + .wlan_idx = msta->wcid.idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + .muar_idx = mvif->omac_idx, + }, + .ba = { + .tag = cpu_to_le16(STA_REC_BA), + .len = cpu_to_le16(sizeof(struct sta_rec_ba)), + .tid = params->tid, + .ba_type = MT_BA_TYPE_ORIGINATOR, + .amsdu = params->amsdu, + .ba_en = add << params->tid, + .ssn = cpu_to_le16(params->ssn), + .winsize = cpu_to_le16(params->buf_size), + }, + }; + int ret; if (add) { - u8 idx; + u8 idx, ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; for (idx = 7; idx > 0; idx--) { - if (ba_size >= ba_range[idx]) + if (params->buf_size >= ba_range[idx]) break; } - wtbl_ba.sn = cpu_to_le16(ssn); - wtbl_ba.ba_en = 1; - wtbl_ba.ba_winsize_idx = idx; + wtbl_req.ba.ba_winsize_idx = idx; } - ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, &wtbl_ba, - buf_len); + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + &wtbl_req, sizeof(wtbl_req), true); if (ret) return ret; - buf_len = sizeof(struct sta_rec_ba); - - sta_rec_ba.tag = cpu_to_le16(STA_REC_BA); - sta_rec_ba.len = cpu_to_le16(buf_len); - sta_rec_ba.tid = tid; - sta_rec_ba.ba_type = MT_BA_TYPE_ORIGINATOR; - sta_rec_ba.amsdu = params->amsdu; - sta_rec_ba.ba_en = add << tid; - sta_rec_ba.ssn = cpu_to_le16(ssn); - sta_rec_ba.winsize = cpu_to_le16(ba_size); - - return __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, &sta_rec_ba, buf_len); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + &sta_req, sizeof(sta_req), true); } int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, struct ieee80211_ampdu_params *params, bool add) { - struct ieee80211_sta *sta = params->sta; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; struct mt7615_vif *mvif = msta->vif; - u16 tid = params->tid; - struct wtbl_ba wtbl_ba = {0}; - struct sta_rec_ba sta_rec_ba = {0}; - int ret, buf_len; - - buf_len = sizeof(struct sta_rec_ba); - - sta_rec_ba.tag = cpu_to_le16(STA_REC_BA); - sta_rec_ba.len = cpu_to_le16(buf_len); - sta_rec_ba.tid = tid; - sta_rec_ba.ba_type = MT_BA_TYPE_RECIPIENT; - sta_rec_ba.amsdu = params->amsdu; - sta_rec_ba.ba_en = add << tid; - sta_rec_ba.ssn = cpu_to_le16(params->ssn); - sta_rec_ba.winsize = cpu_to_le16(params->buf_size); - - ret = __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, - mvif->omac_idx, &sta_rec_ba, buf_len); - if (ret || !add) - return ret; + struct { + struct wtbl_req_hdr hdr; + struct wtbl_ba ba; + } wtbl_req = { + .hdr = { + .wlan_idx = msta->wcid.idx, + .operation = WTBL_SET, + .tlv_num = cpu_to_le16(1), + }, + .ba = { + .tag = cpu_to_le16(WTBL_BA), + .len = cpu_to_le16(sizeof(struct wtbl_ba)), + .tid = params->tid, + .ba_type = MT_BA_TYPE_RECIPIENT, + .rst_ba_tid = params->tid, + .rst_ba_sel = RST_BA_MAC_TID_MATCH, + .rst_ba_sb = 1, + }, + }; + struct { + struct sta_req_hdr hdr; + struct sta_rec_ba ba; + } sta_req = { + .hdr = { + .bss_idx = mvif->idx, + .wlan_idx = msta->wcid.idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + .muar_idx = mvif->omac_idx, + }, + .ba = { + .tag = cpu_to_le16(STA_REC_BA), + .len = cpu_to_le16(sizeof(struct sta_rec_ba)), + .tid = params->tid, + .ba_type = MT_BA_TYPE_RECIPIENT, + .amsdu = params->amsdu, + .ba_en = add << params->tid, + .ssn = cpu_to_le16(params->ssn), + .winsize = cpu_to_le16(params->buf_size), + }, + }; + int ret; - buf_len = sizeof(struct wtbl_ba); + memcpy(wtbl_req.ba.peer_addr, params->sta->addr, ETH_ALEN); - wtbl_ba.tag = cpu_to_le16(WTBL_BA); - wtbl_ba.len = cpu_to_le16(buf_len); - wtbl_ba.tid = tid; - wtbl_ba.ba_type = MT_BA_TYPE_RECIPIENT; - memcpy(wtbl_ba.peer_addr, sta->addr, ETH_ALEN); - wtbl_ba.rst_ba_tid = tid; - wtbl_ba.rst_ba_sel = RST_BA_MAC_TID_MATCH; - wtbl_ba.rst_ba_sb = 1; + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + &sta_req, sizeof(sta_req), true); + if (ret || !add) + return ret; - return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, - &wtbl_ba, buf_len); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + &wtbl_req, sizeof(wtbl_req), true); } void mt7615_mcu_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 9455f8fa475d..f8b51ad25220 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -70,6 +70,7 @@ enum { enum { MCU_EXT_CMD_PM_STATE_CTRL = 0x07, MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, + MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11, MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, MCU_EXT_CMD_STA_REC_UPDATE = 0x25, MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26, @@ -105,25 +106,19 @@ enum { #define STA_TYPE_STA BIT(0) #define STA_TYPE_AP BIT(1) #define STA_TYPE_ADHOC BIT(2) -#define STA_TYPE_TDLS BIT(3) #define STA_TYPE_WDS BIT(4) #define STA_TYPE_BC BIT(5) #define NETWORK_INFRA BIT(16) #define NETWORK_P2P BIT(17) #define NETWORK_IBSS BIT(18) -#define NETWORK_MESH BIT(19) -#define NETWORK_BOW BIT(20) #define NETWORK_WDS BIT(21) #define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA) #define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA) #define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P) #define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P) -#define CONNECTION_MESH_STA (STA_TYPE_STA | NETWORK_MESH) -#define CONNECTION_MESH_AP (STA_TYPE_AP | NETWORK_MESH) #define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS) -#define CONNECTION_TDLS (STA_TYPE_STA | NETWORK_INFRA | STA_TYPE_TDLS) #define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS) #define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA) @@ -131,41 +126,11 @@ enum { #define CONN_STATE_CONNECT 1 #define CONN_STATE_PORT_SECURE 2 -struct dev_info { - u8 omac_idx; - u8 omac_addr[ETH_ALEN]; - u8 band_idx; - u8 enable; - u32 feature; -}; - enum { DEV_INFO_ACTIVE, DEV_INFO_MAX_NUM }; -struct bss_info { - u8 bss_idx; - u8 bssid[ETH_ALEN]; - u8 omac_idx; - u8 band_idx; - u8 bmc_tx_wlan_idx; /* for bmc tx (sta mode use uc entry) */ - u8 wmm_idx; - u32 network_type; - u32 conn_type; - u16 bcn_interval; - u8 dtim_period; - u8 enable; - u32 feature; -}; - -struct bss_info_tag_handler { - u32 tag; - u32 len; - void (*handler)(struct mt7615_dev *dev, - struct bss_info *bss_info, struct sk_buff *skb); -}; - struct bss_info_omac { __le16 tag; __le16 len; @@ -231,6 +196,13 @@ enum { WTBL_RESET_ALL }; +struct wtbl_req_hdr { + u8 wlan_idx; + u8 operation; + __le16 tlv_num; + u8 rsv[4]; +} __packed; + struct wtbl_generic { __le16 tag; __le16 len; @@ -396,7 +368,8 @@ struct wtbl_raw { __le32 val; } __packed; -#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_generic) + \ +#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \ + sizeof(struct wtbl_generic) + \ sizeof(struct wtbl_rx) + \ sizeof(struct wtbl_ht) + \ sizeof(struct wtbl_vht) + \ @@ -430,6 +403,15 @@ enum { WTBL_MAX_NUM }; +struct sta_req_hdr { + u8 bss_idx; + u8 wlan_idx; + __le16 tlv_num; + u8 is_tlv_append; + u8 muar_idx; + u8 rsv[2]; +} __packed; + struct sta_rec_basic { __le16 tag; __le16 len; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 895c2904d7eb..f02ffcffe637 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -105,11 +105,14 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); int mt7615_register_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev); int mt7615_eeprom_init(struct mt7615_dev *dev); +int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, + struct ieee80211_channel *chan, + u8 chain_idx); int mt7615_dma_init(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev); int mt7615_mcu_init(struct mt7615_dev *dev); -int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en); +int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable); int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, int en); int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, @@ -118,12 +121,11 @@ int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, void mt7615_mcu_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates); -int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif); -int mt7615_mcu_del_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif); +int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool enable); int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); +int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_sta *sta); int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev); int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool en); @@ -168,6 +170,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); int mt7615_mcu_init_mac(struct mt7615_dev *dev); int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val); int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter); +int mt7615_mcu_set_tx_power(struct mt7615_dev *dev); void mt7615_mcu_exit(struct mt7615_dev *dev); int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -180,7 +183,6 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); -void mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 11122bd2d727..9e82cb53fd60 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -27,14 +27,15 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) return MT_PCIE_REMAP_BASE_2 + offset; } -void mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +static void +mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); mt7615_irq_enable(dev, MT_INT_RX_DONE(q)); } -irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) +static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) { struct mt7615_dev *dev = dev_instance; u32 intr; @@ -49,7 +50,7 @@ irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) if (intr & MT_INT_TX_DONE_ALL) { mt7615_irq_disable(dev, MT_INT_TX_DONE_ALL); - tasklet_schedule(&dev->mt76.tx_tasklet); + napi_schedule(&dev->mt76.tx_napi); } if (intr & MT_INT_RX_DONE(0)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index 71237d5cdf7f..cf7fc307322b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -271,8 +271,9 @@ mt76x0_init_txpower(struct mt76x02_dev *dev, mt76x0_get_tx_power_per_rate(dev, chan, &t); mt76x0_get_power_info(dev, chan, &tp); - chan->max_power = (mt76x02_get_max_rate_power(&t) + tp) / 2; - chan->orig_mpwr = chan->max_power; + chan->orig_mpwr = (mt76x02_get_max_rate_power(&t) + tp) / 2; + chan->max_power = min_t(int, chan->max_reg_power, + chan->orig_mpwr); } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index a7f335d6e8f8..d7bf7bc15e52 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -25,7 +25,7 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76_rr(dev, MT_CH_IDLE); mt76_rr(dev, MT_CH_BUSY); - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); if (mt76_is_mmio(dev)) { mt76x02_dfs_init_params(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index e11da6900222..1ecfc334ae79 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -422,15 +422,15 @@ mt76x0_phy_set_chan_bbp_params(struct mt76x02_dev *dev, u16 rf_bw_band) static void mt76x0_phy_ant_select(struct mt76x02_dev *dev) { u16 ee_ant = mt76x02_eeprom_get(dev, MT_EE_ANTENNA); + u16 ee_cfg1 = mt76x02_eeprom_get(dev, MT_EE_CFG1_INIT); u16 nic_conf2 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2); - u32 wlan, coex3, cmb; + u32 wlan, coex3; bool ant_div; wlan = mt76_rr(dev, MT_WLAN_FUN_CTRL); - cmb = mt76_rr(dev, MT_CMB_CTRL); coex3 = mt76_rr(dev, MT_COEXCFG3); - cmb &= ~(BIT(14) | BIT(12)); + ee_ant &= ~(BIT(14) | BIT(12)); wlan &= ~(BIT(6) | BIT(5)); coex3 &= ~GENMASK(5, 2); @@ -439,7 +439,7 @@ static void mt76x0_phy_ant_select(struct mt76x02_dev *dev) ant_div = !(nic_conf2 & MT_EE_NIC_CONF_2_ANT_OPT) && (nic_conf2 & MT_EE_NIC_CONF_2_ANT_DIV); if (ant_div) - cmb |= BIT(12); + ee_ant |= BIT(12); else coex3 |= BIT(4); coex3 |= BIT(3); @@ -456,10 +456,11 @@ static void mt76x0_phy_ant_select(struct mt76x02_dev *dev) } if (is_mt7630(dev)) - cmb |= BIT(14) | BIT(11); + ee_ant |= BIT(14) | BIT(11); mt76_wr(dev, MT_WLAN_FUN_CTRL, wlan); - mt76_wr(dev, MT_CMB_CTRL, cmb); + mt76_rmw(dev, MT_CMB_CTRL, GENMASK(15, 0), ee_ant); + mt76_rmw(dev, MT_CSR_EE_CFG1, GENMASK(15, 0), ee_cfg1); mt76_clear(dev, MT_COEXCFG0, BIT(2)); mt76_wr(dev, MT_COEXCFG3, coex3); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 2dc67e68c6a2..627ed1fc7b15 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -183,7 +183,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) /* check hw sg support in order to enable AMSDU */ if (dev->mt76.usb.sg_en) - hw->max_tx_fragments = MT_SG_MAX_SIZE; + hw->max_tx_fragments = MT_TX_SG_MAX_SIZE; else hw->max_tx_fragments = 1; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 687bd14b2d77..f7fd53a1738a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -90,7 +90,6 @@ struct mt76x02_dev { struct sk_buff *rx_head; - struct napi_struct tx_napi; struct delayed_work cal_work; struct delayed_work wdt_work; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c index e196b9c0a686..d61c686e08de 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -189,10 +189,8 @@ mt76x02_resync_beacon_timer(struct mt76x02_dev *dev) mt76_rmw_field(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_INTVAL, timer_val); - if (dev->tbtt_count >= 64) { + if (dev->tbtt_count >= 64) dev->tbtt_count = 0; - return; - } } EXPORT_SYMBOL_GPL(mt76x02_resync_beacon_timer); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c index b1d6fd4861e3..1b1e424ccbb2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c @@ -120,12 +120,16 @@ static int mt76_edcca_set(void *data, u64 val) { struct mt76x02_dev *dev = data; - enum nl80211_dfs_regions region = dev->dfs_pd.region; + enum nl80211_dfs_regions region = dev->mt76.region; + + mutex_lock(&dev->mt76.mutex); dev->ed_monitor_enabled = !!val; dev->ed_monitor = dev->ed_monitor_enabled && region == NL80211_DFS_ETSI; - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); + + mutex_unlock(&dev->mt76.mutex); return 0; } @@ -153,7 +157,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev) debugfs_create_u8("temperature", 0400, dir, &dev->cal.temp); debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc); - debugfs_create_file("edcca", 0400, dir, dev, &fops_edcca); + debugfs_create_file("edcca", 0600, dir, dev, &fops_edcca); debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); debugfs_create_file("dfs_stats", 0400, dir, dev, &fops_dfs_stat); debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 17d12d212d1b..50e9b310e496 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -283,7 +283,7 @@ static bool mt76x02_dfs_check_hw_pulse(struct mt76x02_dev *dev, if (!pulse->period || !pulse->w1) return false; - switch (dev->dfs_pd.region) { + switch (dev->mt76.region) { case NL80211_DFS_FCC: if (pulse->engine > 3) break; @@ -457,7 +457,7 @@ static int mt76x02_dfs_create_sequence(struct mt76x02_dev *dev, with_sum = event->width + cur_event->width; sw_params = &dfs_pd->sw_dpd_params; - switch (dev->dfs_pd.region) { + switch (dev->mt76.region) { case NL80211_DFS_FCC: case NL80211_DFS_JP: if (with_sum < 600) @@ -685,7 +685,7 @@ static void mt76x02_dfs_init_sw_detector(struct mt76x02_dev *dev) { struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - switch (dev->dfs_pd.region) { + switch (dev->mt76.region) { case NL80211_DFS_FCC: dfs_pd->sw_dpd_params.max_pri = MT_DFS_FCC_MAX_PRI; dfs_pd->sw_dpd_params.min_pri = MT_DFS_FCC_MIN_PRI; @@ -725,7 +725,7 @@ static void mt76x02_dfs_set_bbp_params(struct mt76x02_dev *dev) break; } - switch (dev->dfs_pd.region) { + switch (dev->mt76.region) { case NL80211_DFS_FCC: radar_specs = &fcc_radar_specs[shift]; break; @@ -836,7 +836,7 @@ void mt76x02_dfs_init_params(struct mt76x02_dev *dev) struct cfg80211_chan_def *chandef = &dev->mt76.chandef; if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && - dev->dfs_pd.region != NL80211_DFS_UNSET) { + dev->mt76.region != NL80211_DFS_UNSET) { mt76x02_dfs_init_sw_detector(dev); mt76x02_dfs_set_bbp_params(dev); /* enable debug mode */ @@ -869,7 +869,7 @@ void mt76x02_dfs_init_detector(struct mt76x02_dev *dev) INIT_LIST_HEAD(&dfs_pd->sequences); INIT_LIST_HEAD(&dfs_pd->seq_pool); - dfs_pd->region = NL80211_DFS_UNSET; + dev->mt76.region = NL80211_DFS_UNSET; dfs_pd->last_sw_check = jiffies; tasklet_init(&dfs_pd->dfs_tasklet, mt76x02_dfs_tasklet, (unsigned long)dev); @@ -882,14 +882,14 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; mutex_lock(&dev->mt76.mutex); - if (dfs_pd->region != region) { + if (dev->mt76.region != region) { tasklet_disable(&dfs_pd->dfs_tasklet); dev->ed_monitor = dev->ed_monitor_enabled && region == NL80211_DFS_ETSI; - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); - dfs_pd->region = region; + dev->mt76.region = region; mt76x02_dfs_init_params(dev); tasklet_enable(&dfs_pd->dfs_tasklet); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h index 70b394e17340..0408613b45a4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h @@ -118,8 +118,6 @@ struct mt76x02_dfs_seq_stats { }; struct mt76x02_dfs_pattern_detector { - enum nl80211_dfs_regions region; - u8 chirp_pulse_cnt; u32 chirp_pulse_ts; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h index e3442bc4e0a4..0ba536de3d6e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h @@ -26,6 +26,7 @@ enum mt76x02_eeprom_field { MT_EE_MAC_ADDR = 0x004, MT_EE_PCI_ID = 0x00A, MT_EE_ANTENNA = 0x022, + MT_EE_CFG1_INIT = 0x024, MT_EE_NIC_CONF_0 = 0x034, MT_EE_NIC_CONF_1 = 0x036, MT_EE_COUNTRY_REGION_5GHZ = 0x038, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 56510a1a843a..82bafb5ac326 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -420,30 +420,92 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, EXPORT_SYMBOL_GPL(mt76x02_mac_write_txwi); static void -mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev, +mt76x02_tx_rate_fallback(struct ieee80211_tx_rate *rates, int idx, int phy) +{ + u8 mcs, nss; + + if (!idx) + return; + + rates += idx - 1; + rates[1] = rates[0]; + switch (phy) { + case MT_PHY_TYPE_VHT: + mcs = ieee80211_rate_get_vht_mcs(rates); + nss = ieee80211_rate_get_vht_nss(rates); + + if (mcs == 0) + nss = max_t(int, nss - 1, 1); + else + mcs--; + + ieee80211_rate_set_vht(rates + 1, mcs, nss); + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + /* MCS 8 falls back to MCS 0 */ + if (rates[0].idx == 8) { + rates[1].idx = 0; + break; + } + /* fall through */ + default: + rates[1].idx = max_t(int, rates[0].idx - 1, 0); + break; + } +} + +static void +mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev, struct mt76x02_sta *msta, struct ieee80211_tx_info *info, struct mt76x02_tx_status *st, int n_frames) { struct ieee80211_tx_rate *rate = info->status.rates; - int cur_idx, last_rate; + struct ieee80211_tx_rate last_rate; + u16 first_rate; + int retry = st->retry; + int phy; int i; if (!n_frames) return; - last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1); - mt76x02_mac_process_tx_rate(&rate[last_rate], st->rate, + phy = FIELD_GET(MT_RXWI_RATE_PHY, st->rate); + + if (st->pktid & MT_PACKET_ID_HAS_RATE) { + first_rate = st->rate & ~MT_RXWI_RATE_INDEX; + first_rate |= st->pktid & MT_RXWI_RATE_INDEX; + + mt76x02_mac_process_tx_rate(&rate[0], first_rate, + dev->mt76.chandef.chan->band); + } else if (rate[0].idx < 0) { + if (!msta) + return; + + mt76x02_mac_process_tx_rate(&rate[0], msta->wcid.tx_info, + dev->mt76.chandef.chan->band); + } + + mt76x02_mac_process_tx_rate(&last_rate, st->rate, dev->mt76.chandef.chan->band); - if (last_rate < IEEE80211_TX_MAX_RATES - 1) - rate[last_rate + 1].idx = -1; - - cur_idx = rate[last_rate].idx + last_rate; - for (i = 0; i <= last_rate; i++) { - rate[i].flags = rate[last_rate].flags; - rate[i].idx = max_t(int, 0, cur_idx - i); - rate[i].count = 1; + + for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) { + retry--; + if (i + 1 == ARRAY_SIZE(info->status.rates)) { + info->status.rates[i] = last_rate; + info->status.rates[i].count = max_t(int, retry, 1); + break; + } + + mt76x02_tx_rate_fallback(info->status.rates, i, phy); + if (info->status.rates[i].idx == last_rate.idx) + break; + } + + if (i + 1 < ARRAY_SIZE(info->status.rates)) { + info->status.rates[i + 1].idx = -1; + info->status.rates[i + 1].count = 0; } - rate[last_rate].count = st->retry + 1 - last_rate; info->status.ampdu_len = n_frames; info->status.ampdu_ack_len = st->success ? n_frames : 0; @@ -489,13 +551,19 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, mt76_tx_status_lock(mdev, &list); if (wcid) { - if (stat->pktid >= MT_PACKET_ID_FIRST) + if (mt76_is_skb_pktid(stat->pktid)) status.skb = mt76_tx_status_skb_get(mdev, wcid, stat->pktid, &list); if (status.skb) status.info = IEEE80211_SKB_CB(status.skb); } + if (!status.skb && !(stat->pktid & MT_PACKET_ID_HAS_RATE)) { + mt76_tx_status_unlock(mdev, &list); + rcu_read_unlock(); + return; + } + if (msta && stat->aggr && !status.skb) { u32 stat_val, stat_cache; @@ -512,14 +580,14 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, return; } - mt76x02_mac_fill_tx_status(dev, status.info, &msta->status, - msta->n_frames); + mt76x02_mac_fill_tx_status(dev, msta, status.info, + &msta->status, msta->n_frames); msta->status = *stat; msta->n_frames = 1; *update = 0; } else { - mt76x02_mac_fill_tx_status(dev, status.info, stat, 1); + mt76x02_mac_fill_tx_status(dev, msta, status.info, stat, 1); *update = 1; } @@ -945,12 +1013,12 @@ mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable) dev->ed_tx_blocked = !enable; } -void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) +void mt76x02_edcca_init(struct mt76x02_dev *dev) { dev->ed_trigger = 0; dev->ed_silent = 0; - if (dev->ed_monitor && enable) { + if (dev->ed_monitor) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index e4a9e0d0924b..cb39da79527a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -209,5 +209,5 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, struct ieee80211_vif *vif, bool val); -void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable); +void mt76x02_edcca_init(struct mt76x02_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 7b7163bc3b62..467b28379870 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -166,7 +166,8 @@ static void mt76x02_tx_tasklet(unsigned long data) static int mt76x02_poll_tx(struct napi_struct *napi, int budget) { - struct mt76x02_dev *dev = container_of(napi, struct mt76x02_dev, tx_napi); + struct mt76x02_dev *dev = container_of(napi, struct mt76x02_dev, + mt76.tx_napi); int i; mt76x02_mac_poll_tx_status(dev, false); @@ -245,9 +246,9 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) if (ret) return ret; - netif_tx_napi_add(&dev->mt76.napi_dev, &dev->tx_napi, mt76x02_poll_tx, - NAPI_POLL_WEIGHT); - napi_enable(&dev->tx_napi); + netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + mt76x02_poll_tx, NAPI_POLL_WEIGHT); + napi_enable(&dev->mt76.tx_napi); return 0; } @@ -303,7 +304,7 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) if (intr & (MT_INT_TX_STAT | MT_INT_TX_DONE_ALL)) { mt76x02_irq_disable(dev, MT_INT_TX_DONE_ALL); - napi_schedule(&dev->tx_napi); + napi_schedule(&dev->mt76.tx_napi); } if (intr & MT_INT_GPTIMER) { @@ -334,7 +335,6 @@ static void mt76x02_dma_enable(struct mt76x02_dev *dev) void mt76x02_dma_cleanup(struct mt76x02_dev *dev) { tasklet_kill(&dev->mt76.tx_tasklet); - netif_napi_del(&dev->tx_napi); mt76_dma_cleanup(&dev->mt76); } EXPORT_SYMBOL_GPL(mt76x02_dma_cleanup); @@ -454,7 +454,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) tasklet_disable(&dev->mt76.pre_tbtt_tasklet); tasklet_disable(&dev->mt76.tx_tasklet); - napi_disable(&dev->tx_napi); + napi_disable(&dev->mt76.tx_napi); for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) napi_disable(&dev->mt76.napi[i]); @@ -508,8 +508,8 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) clear_bit(MT76_RESET, &dev->mt76.state); tasklet_enable(&dev->mt76.tx_tasklet); - napi_enable(&dev->tx_napi); - napi_schedule(&dev->tx_napi); + napi_enable(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.tx_napi); tasklet_enable(&dev->mt76.pre_tbtt_tasklet); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index 2ce05b543dff..ea7833964ec0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -66,6 +66,9 @@ #define MT_WLAN_FUN_CTRL_GPIO_OUT GENMASK(23, 16) /* MT76x0 */ #define MT_WLAN_FUN_CTRL_GPIO_OUT_EN GENMASK(31, 24) /* MT76x0 */ +/* MT76x0 */ +#define MT_CSR_EE_CFG1 0x0104 + #define MT_XO_CTRL0 0x0100 #define MT_XO_CTRL1 0x0104 #define MT_XO_CTRL2 0x0108 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index cf7abd9b7d2e..04118f08debc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -154,6 +154,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; struct mt76x02_txwi *txwi = txwi_ptr; + bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; int hdrlen, len, pid, qsel = MT_QSEL_EDCA; if (qid == MT_TXQ_PSD && wcid && wcid->idx < 128) @@ -164,9 +165,15 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, mt76x02_mac_write_txwi(dev, txwi, tx_info->skb, wcid, sta, len); pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); + + /* encode packet rate for no-skb packet id to fix up status reporting */ + if (pid == MT_PACKET_ID_NO_SKB) + pid = MT_PACKET_ID_HAS_RATE | + (le16_to_cpu(txwi->rate) & MT_RXWI_RATE_INDEX); + txwi->pktid = pid; - if (pid >= MT_PACKET_ID_FIRST) + if (mt76_is_skb_pktid(pid) && ampdu) qsel = MT_QSEL_MGMT; tx_info->info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) | diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 6b89f7eab26c..5e4f3a8c5784 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "mt76x02.h" +#include "mt76x02_usb.h" static void mt76x02u_remove_dma_hdr(struct sk_buff *skb) { @@ -79,6 +79,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); int pid, len = tx_info->skb->len, ep = q2ep(mdev->q_tx[qid].q->hw_idx); struct mt76x02_txwi *txwi; + bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; enum mt76_qsel qsel; u32 flags; @@ -89,9 +90,15 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, skb_push(tx_info->skb, sizeof(*txwi)); pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); + + /* encode packet rate for no-skb packet id to fix up status reporting */ + if (pid == MT_PACKET_ID_NO_SKB) + pid = MT_PACKET_ID_HAS_RATE | + (le16_to_cpu(txwi->rate) & MT_RXWI_RATE_INDEX); + txwi->pktid = pid; - if (pid >= MT_PACKET_ID_FIRST || ep == MT_EP_OUT_HCCA) + if ((mt76_is_skb_pktid(pid) && ampdu) || ep == MT_EP_OUT_HCCA) qsel = MT_QSEL_MGMT; else qsel = MT_QSEL_EDCA; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index c6078e90ca43..97c3543eed8a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c @@ -173,13 +173,14 @@ void mt76x2_init_txpower(struct mt76x02_dev *dev, mt76x2_get_power_info(dev, &txp, chan); mt76x2_get_rate_power(dev, &t, chan); - chan->max_power = mt76x02_get_max_rate_power(&t) + + chan->orig_mpwr = mt76x02_get_max_rate_power(&t) + txp.target_power; - chan->max_power = DIV_ROUND_UP(chan->max_power, 2); + chan->orig_mpwr = DIV_ROUND_UP(chan->orig_mpwr, 2); /* convert to combined output power on 2x2 devices */ - chan->max_power += 3; - chan->orig_mpwr = chan->max_power; + chan->orig_mpwr += 3; + chan->max_power = min_t(int, chan->max_reg_power, + chan->orig_mpwr); } } EXPORT_SYMBOL_GPL(mt76x2_init_txpower); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index e416eee6a306..3a1467326f4d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -54,14 +54,14 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) int ret; cancel_delayed_work_sync(&dev->cal_work); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); + tasklet_disable(&dev->dfs_pd.dfs_tasklet); + mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &dev->mt76.state); mt76_set_channel(&dev->mt76); - tasklet_disable(&dev->mt76.pre_tbtt_tasklet); - tasklet_disable(&dev->dfs_pd.dfs_tasklet); - mt76x2_mac_stop(dev, true); ret = mt76x2_phy_set_channel(dev, chandef); @@ -72,10 +72,12 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76x02_dfs_init_params(dev); mt76x2_mac_resume(dev); - tasklet_enable(&dev->dfs_pd.dfs_tasklet); - tasklet_enable(&dev->mt76.pre_tbtt_tasklet); clear_bit(MT76_RESET, &dev->mt76.state); + mutex_unlock(&dev->mt76.mutex); + + tasklet_enable(&dev->dfs_pd.dfs_tasklet); + tasklet_enable(&dev->mt76.pre_tbtt_tasklet); mt76_txq_schedule_all(&dev->mt76); @@ -111,14 +113,14 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed) } } + mutex_unlock(&dev->mt76.mutex); + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ieee80211_stop_queues(hw); ret = mt76x2_set_channel(dev, &hw->conf.chandef); ieee80211_wake_queues(hw); } - mutex_unlock(&dev->mt76.mutex); - return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index cc1aebcb0696..2edf1bd0c18c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -74,7 +74,7 @@ mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) mt76x2_mac_resume(dev); mt76x2_apply_gain_adj(dev); - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); dev->cal.channel_cal_done = true; } @@ -294,10 +294,16 @@ void mt76x2_phy_calibrate(struct work_struct *work) struct mt76x02_dev *dev; dev = container_of(work, struct mt76x02_dev, cal_work.work); + + mutex_lock(&dev->mt76.mutex); + mt76x2_phy_channel_calibrate(dev, false); mt76x2_phy_tssi_compensate(dev); mt76x2_phy_temp_compensate(dev); mt76x2_phy_update_channel_gain(dev); + + mutex_unlock(&dev->mt76.mutex); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, MT_CALIBRATE_INTERVAL); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index f2c57d5b87f9..94f52f98019b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -225,7 +225,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) /* check hw sg support in order to enable AMSDU */ if (dev->mt76.usb.sg_en) - hw->max_tx_fragments = MT_SG_MAX_SIZE; + hw->max_tx_fragments = MT_TX_SG_MAX_SIZE; else hw->max_tx_fragments = 1; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 97bcf6494ec1..e4dfc3bea3c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -48,22 +48,23 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, int err; cancel_delayed_work_sync(&dev->cal_work); + dev->beacon_ops->pre_tbtt_enable(dev, false); + + mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &dev->mt76.state); mt76_set_channel(&dev->mt76); - dev->beacon_ops->pre_tbtt_enable(dev, false); - mt76x2_mac_stop(dev, false); err = mt76x2u_phy_set_channel(dev, chandef); mt76x2_mac_resume(dev); - mt76x02_edcca_init(dev, true); - - dev->beacon_ops->pre_tbtt_enable(dev, true); clear_bit(MT76_RESET, &dev->mt76.state); + mutex_unlock(&dev->mt76.mutex); + + dev->beacon_ops->pre_tbtt_enable(dev, true); mt76_txq_schedule_all(&dev->mt76); return err; @@ -85,12 +86,6 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter); } - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ieee80211_stop_queues(hw); - err = mt76x2u_set_channel(dev, &hw->conf.chandef); - ieee80211_wake_queues(hw); - } - if (changed & IEEE80211_CONF_CHANGE_POWER) { dev->mt76.txpower_conf = hw->conf.power_level * 2; @@ -103,6 +98,12 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) mutex_unlock(&dev->mt76.mutex); + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + ieee80211_stop_queues(hw); + err = mt76x2u_set_channel(dev, &hw->conf.chandef); + ieee80211_wake_queues(hw); + } + return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index 07f67cb6854c..dfd54f9b0e97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -45,7 +45,7 @@ mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) if (!mac_stopped) mt76x2_mac_resume(dev); mt76x2_apply_gain_adj(dev); - mt76x02_edcca_init(dev, true); + mt76x02_edcca_init(dev); dev->cal.channel_cal_done = true; } @@ -55,10 +55,15 @@ void mt76x2u_phy_calibrate(struct work_struct *work) struct mt76x02_dev *dev; dev = container_of(work, struct mt76x02_dev, cal_work.work); + + mutex_lock(&dev->mt76.mutex); + mt76x2u_phy_channel_calibrate(dev, false); mt76x2_phy_tssi_compensate(dev); mt76x2_phy_update_channel_gain(dev); + mutex_unlock(&dev->mt76.mutex); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, MT_CALIBRATE_INTERVAL); } diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index bbaa1365bbda..61b27f3ec6e4 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -267,12 +267,10 @@ mt76u_set_endpoints(struct usb_interface *intf, if (usb_endpoint_is_bulk_in(ep_desc) && in_ep < __MT_EP_IN_MAX) { usb->in_ep[in_ep] = usb_endpoint_num(ep_desc); - usb->in_max_packet = usb_endpoint_maxp(ep_desc); in_ep++; } else if (usb_endpoint_is_bulk_out(ep_desc) && out_ep < __MT_EP_OUT_MAX) { usb->out_ep[out_ep] = usb_endpoint_num(ep_desc); - usb->out_max_packet = usb_endpoint_maxp(ep_desc); out_ep++; } } @@ -333,12 +331,13 @@ mt76u_refill_rx(struct mt76_dev *dev, struct urb *urb, int nsgs, gfp_t gfp) } static int -mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) +mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e, + int sg_max_size) { unsigned int size = sizeof(struct urb); if (dev->usb.sg_en) - size += MT_SG_MAX_SIZE * sizeof(struct scatterlist); + size += sg_max_size * sizeof(struct scatterlist); e->urb = kzalloc(size, GFP_KERNEL); if (!e->urb) @@ -357,11 +356,12 @@ mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) { int err; - err = mt76u_urb_alloc(dev, e); + err = mt76u_urb_alloc(dev, e, MT_RX_SG_MAX_SIZE); if (err) return err; - return mt76u_refill_rx(dev, e->urb, MT_SG_MAX_SIZE, GFP_KERNEL); + return mt76u_refill_rx(dev, e->urb, MT_RX_SG_MAX_SIZE, + GFP_KERNEL); } static void mt76u_urb_free(struct urb *urb) @@ -577,8 +577,9 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) if (!q->entry) return -ENOMEM; - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; q->ndesc = MT_NUM_RX_ENTRIES; + q->buf_size = PAGE_SIZE; + for (i = 0; i < q->ndesc; i++) { err = mt76u_rx_urb_alloc(dev, &q->entry[i]); if (err < 0) @@ -735,7 +736,7 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb, urb->transfer_buffer = skb->data; return 0; } else { - sg_init_table(urb->sg, MT_SG_MAX_SIZE); + sg_init_table(urb->sg, MT_TX_SG_MAX_SIZE); urb->num_sgs = skb_to_sgvec(skb, urb->sg, 0, skb->len); if (urb->num_sgs == 0) return -ENOMEM; @@ -829,7 +830,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) q->ndesc = MT_NUM_TX_ENTRIES; for (j = 0; j < q->ndesc; j++) { - err = mt76u_urb_alloc(dev, &q->entry[j]); + err = mt76u_urb_alloc(dev, &q->entry[j], + MT_TX_SG_MAX_SIZE); if (err < 0) return err; } |