diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-16 00:22:29 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-16 00:22:29 +0300 |
commit | d635a69dd4981cc51f90293f5f64268620ed1565 (patch) | |
tree | 5e0a758b402ea7d624c25c3a343545dd29e80f31 /drivers/net/wireless/mediatek/mt76 | |
parent | ac73e3dc8acd0a3be292755db30388c3580f5674 (diff) | |
parent | efd5a1584537698220578227e6467638307c2a0b (diff) | |
download | linux-d635a69dd4981cc51f90293f5f64268620ed1565.tar.xz |
Merge tag 'net-next-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Jakub Kicinski:
"Core:
- support "prefer busy polling" NAPI operation mode, where we defer
softirq for some time expecting applications to periodically busy
poll
- AF_XDP: improve efficiency by more batching and hindering the
adjacency cache prefetcher
- af_packet: make packet_fanout.arr size configurable up to 64K
- tcp: optimize TCP zero copy receive in presence of partial or
unaligned reads making zero copy a performance win for much smaller
messages
- XDP: add bulk APIs for returning / freeing frames
- sched: support fragmenting IP packets as they come out of conntrack
- net: allow virtual netdevs to forward UDP L4 and fraglist GSO skbs
BPF:
- BPF switch from crude rlimit-based to memcg-based memory accounting
- BPF type format information for kernel modules and related tracing
enhancements
- BPF implement task local storage for BPF LSM
- allow the FENTRY/FEXIT/RAW_TP tracing programs to use
bpf_sk_storage
Protocols:
- mptcp: improve multiple xmit streams support, memory accounting and
many smaller improvements
- TLS: support CHACHA20-POLY1305 cipher
- seg6: add support for SRv6 End.DT4/DT6 behavior
- sctp: Implement RFC 6951: UDP Encapsulation of SCTP
- ppp_generic: add ability to bridge channels directly
- bridge: Connectivity Fault Management (CFM) support as is defined
in IEEE 802.1Q section 12.14.
Drivers:
- mlx5: make use of the new auxiliary bus to organize the driver
internals
- mlx5: more accurate port TX timestamping support
- mlxsw:
- improve the efficiency of offloaded next hop updates by using
the new nexthop object API
- support blackhole nexthops
- support IEEE 802.1ad (Q-in-Q) bridging
- rtw88: major bluetooth co-existance improvements
- iwlwifi: support new 6 GHz frequency band
- ath11k: Fast Initial Link Setup (FILS)
- mt7915: dual band concurrent (DBDC) support
- net: ipa: add basic support for IPA v4.5
Refactor:
- a few pieces of in_interrupt() cleanup work from Sebastian Andrzej
Siewior
- phy: add support for shared interrupts; get rid of multiple driver
APIs and have the drivers write a full IRQ handler, slight growth
of driver code should be compensated by the simpler API which also
allows shared IRQs
- add common code for handling netdev per-cpu counters
- move TX packet re-allocation from Ethernet switch tag drivers to a
central place
- improve efficiency and rename nla_strlcpy
- number of W=1 warning cleanups as we now catch those in a patchwork
build bot
Old code removal:
- wan: delete the DLCI / SDLA drivers
- wimax: move to staging
- wifi: remove old WDS wifi bridging support"
* tag 'net-next-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1922 commits)
net: hns3: fix expression that is currently always true
net: fix proc_fs init handling in af_packet and tls
nfc: pn533: convert comma to semicolon
af_vsock: Assign the vsock transport considering the vsock address flags
af_vsock: Set VMADDR_FLAG_TO_HOST flag on the receive path
vsock_addr: Check for supported flag values
vm_sockets: Add VMADDR_FLAG_TO_HOST vsock flag
vm_sockets: Add flags field in the vsock address data structure
net: Disable NETIF_F_HW_TLS_TX when HW_CSUM is disabled
tcp: Add logic to check for SYN w/ data in tcp_simple_retransmit
net: mscc: ocelot: install MAC addresses in .ndo_set_rx_mode from process context
nfc: s3fwrn5: Release the nfc firmware
net: vxget: clean up sparse warnings
mlxsw: spectrum_router: Use eXtended mezzanine to offload IPv4 router
mlxsw: spectrum: Set KVH XLT cache mode for Spectrum2/3
mlxsw: spectrum_router_xm: Introduce basic XM cache flushing
mlxsw: reg: Add Router LPM Cache Enable Register
mlxsw: reg: Add Router LPM Cache ML Delete Register
mlxsw: spectrum_router_xm: Implement L-value tracking for M-index
mlxsw: reg: Add XM Router M Table Register
...
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76')
76 files changed, 3446 insertions, 2156 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index 52f583cb1418..d4a6b8108971 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -30,8 +30,8 @@ int mt76_queues_read(struct seq_file *s, void *data) struct mt76_dev *dev = dev_get_drvdata(s->private); int i; - for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) { - struct mt76_queue *q = dev->q_tx[i]; + for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) { + struct mt76_queue *q = dev->phy.q_tx[i]; if (!q) continue; diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 214fc95b8a33..73eeb00d5aa6 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -72,9 +72,11 @@ mt76_free_pending_txwi(struct mt76_dev *dev) { struct mt76_txwi_cache *t; + local_bh_disable(); while ((t = __mt76_get_txwi(dev)) != NULL) dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); + local_bh_enable(); } static int @@ -86,6 +88,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, int i; spin_lock_init(&q->lock); + spin_lock_init(&q->cleanup_lock); q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE; q->ndesc = n_desc; @@ -215,16 +218,15 @@ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) } static void -mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) +mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush) { - struct mt76_queue *q = dev->q_tx[qid]; struct mt76_queue_entry entry; - bool wake = false; int last; if (!q) return; + spin_lock_bh(&q->cleanup_lock); if (flush) last = -1; else @@ -237,13 +239,13 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) if (entry.txwi) { if (!(dev->drv->drv_flags & MT_DRV_TXWI_NO_FREE)) mt76_put_txwi(dev, entry.txwi); - wake = !flush; } if (!flush && q->tail == last) last = readl(&q->regs->dma_idx); } + spin_unlock_bh(&q->cleanup_lock); if (flush) { spin_lock_bh(&q->lock); @@ -252,16 +254,8 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) spin_unlock_bh(&q->lock); } - wake = wake && q->stopped && - qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; - if (wake) - q->stopped = false; - if (!q->queued) wake_up(&dev->tx_wait); - - if (wake) - ieee80211_wake_queue(dev->hw, qid); } static void * @@ -312,10 +306,9 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, } static int -mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, u32 tx_info) { - struct mt76_queue *q = dev->q_tx[qid]; struct mt76_queue_buf buf; dma_addr_t addr; @@ -343,11 +336,10 @@ error: } static int -mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { - struct mt76_queue *q = dev->q_tx[qid]; struct mt76_tx_info tx_info = { .skb = skb, }; @@ -397,7 +389,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); - ret = dev->drv->tx_prepare_skb(dev, txwi, qid, wcid, sta, &tx_info); + ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info); dma_sync_single_for_device(dev->dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); if (ret < 0) @@ -661,8 +653,15 @@ void mt76_dma_cleanup(struct mt76_dev *dev) mt76_worker_disable(&dev->tx_worker); netif_napi_del(&dev->tx_napi); - for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) - mt76_dma_tx_cleanup(dev, i, true); + + for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) { + mt76_dma_tx_cleanup(dev, dev->phy.q_tx[i], true); + if (dev->phy2) + mt76_dma_tx_cleanup(dev, dev->phy2->q_tx[i], true); + } + + for (i = 0; i < ARRAY_SIZE(dev->q_mcu); i++) + mt76_dma_tx_cleanup(dev, dev->q_mcu[i], true); mt76_for_each_q_rx(dev, i) { netif_napi_del(&dev->napi[i]); diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 3044e0069991..90278aeb6721 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -88,8 +88,10 @@ out_put_node: } void -mt76_eeprom_override(struct mt76_dev *dev) +mt76_eeprom_override(struct mt76_phy *phy) { + struct mt76_dev *dev = phy->dev; + #ifdef CONFIG_OF struct device_node *np = dev->dev->of_node; const u8 *mac = NULL; @@ -97,14 +99,14 @@ mt76_eeprom_override(struct mt76_dev *dev) if (np) mac = of_get_mac_address(np); if (!IS_ERR_OR_NULL(mac)) - ether_addr_copy(dev->macaddr, mac); + ether_addr_copy(phy->macaddr, mac); #endif - if (!is_valid_ether_addr(dev->macaddr)) { - eth_random_addr(dev->macaddr); + if (!is_valid_ether_addr(phy->macaddr)) { + eth_random_addr(phy->macaddr); dev_info(dev->dev, "Invalid MAC address, using random address %pM\n", - dev->macaddr); + phy->macaddr); } } EXPORT_SYMBOL_GPL(mt76_eeprom_override); diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 4befe7f937a9..a840396f2c74 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -159,21 +159,22 @@ static void mt76_init_stream_cap(struct mt76_phy *phy, void mt76_set_stream_caps(struct mt76_phy *phy, bool vht) { - if (phy->dev->cap.has_2ghz) + if (phy->cap.has_2ghz) mt76_init_stream_cap(phy, &phy->sband_2g.sband, false); - if (phy->dev->cap.has_5ghz) + if (phy->cap.has_5ghz) mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht); } EXPORT_SYMBOL_GPL(mt76_set_stream_caps); static int -mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, +mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband, const struct ieee80211_channel *chan, int n_chan, struct ieee80211_rate *rates, int n_rates, bool vht) { struct ieee80211_supported_band *sband = &msband->sband; - struct ieee80211_sta_ht_cap *ht_cap; struct ieee80211_sta_vht_cap *vht_cap; + struct ieee80211_sta_ht_cap *ht_cap; + struct mt76_dev *dev = phy->dev; void *chanlist; int size; @@ -203,7 +204,7 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - mt76_init_stream_cap(&dev->phy, sband, vht); + mt76_init_stream_cap(phy, sband, vht); if (!vht) return 0; @@ -221,27 +222,25 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, } static int -mt76_init_sband_2g(struct mt76_dev *dev, struct ieee80211_rate *rates, +mt76_init_sband_2g(struct mt76_phy *phy, struct ieee80211_rate *rates, int n_rates) { - dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->phy.sband_2g.sband; + phy->hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; - return mt76_init_sband(dev, &dev->phy.sband_2g, - mt76_channels_2ghz, - ARRAY_SIZE(mt76_channels_2ghz), - rates, n_rates, false); + return mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz, + ARRAY_SIZE(mt76_channels_2ghz), rates, + n_rates, false); } static int -mt76_init_sband_5g(struct mt76_dev *dev, struct ieee80211_rate *rates, +mt76_init_sband_5g(struct mt76_phy *phy, struct ieee80211_rate *rates, int n_rates, bool vht) { - dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->phy.sband_5g.sband; + phy->hw->wiphy->bands[NL80211_BAND_5GHZ] = &phy->sband_5g.sband; - return mt76_init_sband(dev, &dev->phy.sband_5g, - mt76_channels_5ghz, - ARRAY_SIZE(mt76_channels_5ghz), - rates, n_rates, vht); + return mt76_init_sband(phy, &phy->sband_5g, mt76_channels_5ghz, + ARRAY_SIZE(mt76_channels_5ghz), rates, + n_rates, vht); } static void @@ -274,12 +273,13 @@ mt76_check_sband(struct mt76_phy *phy, struct mt76_sband *msband, } static void -mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) +mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) { + struct mt76_dev *dev = phy->dev; struct wiphy *wiphy = hw->wiphy; SET_IEEE80211_DEV(hw, dev->dev); - SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); + SET_IEEE80211_PERM_ADDR(hw, phy->macaddr); wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH | @@ -305,6 +305,7 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); + ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) { ieee80211_hw_set(hw, TX_AMSDU); @@ -314,7 +315,6 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) ieee80211_hw_set(hw, MFP_CAPABLE); ieee80211_hw_set(hw, AP_LINK_PS); ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); - ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); wiphy->flags |= WIPHY_FLAG_IBSS_RSN; wiphy->interface_modes = @@ -333,65 +333,57 @@ mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, const struct ieee80211_ops *ops) { struct ieee80211_hw *hw; + unsigned int phy_size; struct mt76_phy *phy; - unsigned int phy_size, chan_size; - unsigned int size_2g, size_5g; - void *priv; phy_size = ALIGN(sizeof(*phy), 8); - chan_size = sizeof(dev->phy.sband_2g.chan[0]); - size_2g = ALIGN(ARRAY_SIZE(mt76_channels_2ghz) * chan_size, 8); - size_5g = ALIGN(ARRAY_SIZE(mt76_channels_5ghz) * chan_size, 8); - - size += phy_size + size_2g + size_5g; - hw = ieee80211_alloc_hw(size, ops); + hw = ieee80211_alloc_hw(size + phy_size, ops); if (!hw) return NULL; phy = hw->priv; phy->dev = dev; phy->hw = hw; + phy->priv = hw->priv + phy_size; - mt76_phy_init(dev, hw); - - priv = hw->priv + phy_size; + return phy; +} +EXPORT_SYMBOL_GPL(mt76_alloc_phy); - phy->sband_2g = dev->phy.sband_2g; - phy->sband_2g.chan = priv; - priv += size_2g; +int mt76_register_phy(struct mt76_phy *phy, bool vht, + struct ieee80211_rate *rates, int n_rates) +{ + int ret; - phy->sband_5g = dev->phy.sband_5g; - phy->sband_5g.chan = priv; - priv += size_5g; + mt76_phy_init(phy, phy->hw); - phy->priv = priv; + if (phy->cap.has_2ghz) { + ret = mt76_init_sband_2g(phy, rates, n_rates); + if (ret) + return ret; + } - hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; - hw->wiphy->bands[NL80211_BAND_5GHZ] = &phy->sband_5g.sband; + if (phy->cap.has_5ghz) { + ret = mt76_init_sband_5g(phy, rates + 4, n_rates - 4, vht); + if (ret) + return ret; + } + wiphy_read_of_freq_limits(phy->hw->wiphy); mt76_check_sband(phy, &phy->sband_2g, NL80211_BAND_2GHZ); mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ); - return phy; -} -EXPORT_SYMBOL_GPL(mt76_alloc_phy); - -int -mt76_register_phy(struct mt76_phy *phy) -{ - int ret; - ret = ieee80211_register_hw(phy->hw); if (ret) return ret; phy->dev->phy2 = phy; + return 0; } EXPORT_SYMBOL_GPL(mt76_register_phy); -void -mt76_unregister_phy(struct mt76_phy *phy) +void mt76_unregister_phy(struct mt76_phy *phy) { struct mt76_dev *dev = phy->dev; @@ -459,16 +451,16 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, int ret; dev_set_drvdata(dev->dev, dev); - mt76_phy_init(dev, hw); + mt76_phy_init(phy, hw); - if (dev->cap.has_2ghz) { - ret = mt76_init_sband_2g(dev, rates, n_rates); + if (phy->cap.has_2ghz) { + ret = mt76_init_sband_2g(phy, rates, n_rates); if (ret) return ret; } - if (dev->cap.has_5ghz) { - ret = mt76_init_sband_5g(dev, rates + 4, n_rates - 4, vht); + if (phy->cap.has_5ghz) { + ret = mt76_init_sband_5g(phy, rates + 4, n_rates - 4, vht); if (ret) return ret; } @@ -539,14 +531,11 @@ EXPORT_SYMBOL_GPL(mt76_rx); bool mt76_has_tx_pending(struct mt76_phy *phy) { - struct mt76_dev *dev = phy->dev; struct mt76_queue *q; - int i, offset; - - offset = __MT_TXQ_MAX * (phy != &dev->phy); + int i; for (i = 0; i < __MT_TXQ_MAX; i++) { - q = dev->q_tx[offset + i]; + q = phy->q_tx[i]; if (q && q->queued) return true; } @@ -842,7 +831,7 @@ mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb) return; if (!wcid || !wcid->sta) { - if (!ether_addr_equal(hdr->addr1, dev->macaddr)) + if (!ether_addr_equal(hdr->addr1, dev->phy.macaddr)) return; wcid = NULL; @@ -932,7 +921,8 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, { struct ieee80211_sta *sta; struct ieee80211_hw *hw; - struct sk_buff *skb; + struct sk_buff *skb, *tmp; + LIST_HEAD(list); spin_lock(&dev->rx_lock); while ((skb = __skb_dequeue(frames)) != NULL) { @@ -942,9 +932,19 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, } mt76_rx_convert(dev, skb, &hw, &sta); - ieee80211_rx_napi(hw, sta, skb, napi); + ieee80211_rx_list(hw, sta, skb, &list); } spin_unlock(&dev->rx_lock); + + if (!napi) { + netif_receive_skb_list(&list); + return; + } + + list_for_each_entry_safe(skb, tmp, &list, list) { + skb_list_del_init(skb); + napi_gro_receive(napi, skb); + } } void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q, @@ -1202,3 +1202,22 @@ int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) return 0; } EXPORT_SYMBOL_GPL(mt76_get_antenna); + +struct mt76_queue * +mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, + int ring_base) +{ + struct mt76_queue *hwq; + int err; + + hwq = devm_kzalloc(dev->dev, sizeof(*hwq), GFP_KERNEL); + if (!hwq) + return ERR_PTR(-ENOMEM); + + err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base); + if (err < 0) + return ERR_PTR(err); + + return hwq; +} +EXPORT_SYMBOL_GPL(mt76_init_queue); diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index ade61a5334c6..d3a5e2c4f12a 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -50,3 +50,83 @@ void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb) wake_up(&dev->mcu.wait); } EXPORT_SYMBOL_GPL(mt76_mcu_rx_event); + +int mt76_mcu_send_and_get_msg(struct mt76_dev *dev, int cmd, const void *data, + int len, bool wait_resp, struct sk_buff **ret_skb) +{ + struct sk_buff *skb; + + if (dev->mcu_ops->mcu_send_msg) + return dev->mcu_ops->mcu_send_msg(dev, cmd, data, len, wait_resp); + + skb = mt76_mcu_msg_alloc(dev, data, len); + if (!skb) + return -ENOMEM; + + return mt76_mcu_skb_send_and_get_msg(dev, skb, cmd, wait_resp, ret_skb); +} +EXPORT_SYMBOL_GPL(mt76_mcu_send_and_get_msg); + +int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, + int cmd, bool wait_resp, + struct sk_buff **ret_skb) +{ + unsigned long expires; + int ret, seq; + + if (ret_skb) + *ret_skb = NULL; + + mutex_lock(&dev->mcu.mutex); + + ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq); + if (ret < 0) + goto out; + + if (!wait_resp) { + ret = 0; + goto out; + } + + expires = jiffies + dev->mcu.timeout; + + do { + skb = mt76_mcu_get_response(dev, expires); + ret = dev->mcu_ops->mcu_parse_response(dev, cmd, skb, seq); + if (!ret && ret_skb) + *ret_skb = skb; + else + dev_kfree_skb(skb); + } while (ret == -EAGAIN); + +out: + mutex_unlock(&dev->mcu.mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(mt76_mcu_skb_send_and_get_msg); + +int mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data, + int len) +{ + int err, cur_len; + + while (len > 0) { + cur_len = min_t(int, 4096 - dev->mcu_ops->headroom, len); + + err = mt76_mcu_send_msg(dev, cmd, data, cur_len, false); + if (err) + return err; + + data += cur_len; + len -= cur_len; + + if (dev->queue_ops->tx_cleanup) + dev->queue_ops->tx_cleanup(dev, + dev->q_mcu[MT_MCUQ_FWDL], + false); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_mcu_send_firmware); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index a5be66de1cff..3e496a188bf0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -64,18 +64,23 @@ enum mt76_txq_id { MT_TXQ_BE = IEEE80211_AC_BE, MT_TXQ_BK = IEEE80211_AC_BK, MT_TXQ_PSD, - MT_TXQ_MCU, - MT_TXQ_MCU_WA, MT_TXQ_BEACON, MT_TXQ_CAB, - MT_TXQ_FWDL, __MT_TXQ_MAX }; +enum mt76_mcuq_id { + MT_MCUQ_WM, + MT_MCUQ_WA, + MT_MCUQ_FWDL, + __MT_MCUQ_MAX +}; + enum mt76_rxq_id { MT_RXQ_MAIN, MT_RXQ_MCU, MT_RXQ_MCU_WA, + MT_RXQ_EXT, __MT_RXQ_MAX }; @@ -121,6 +126,7 @@ struct mt76_queue { struct mt76_queue_regs __iomem *regs; spinlock_t lock; + spinlock_t cleanup_lock; struct mt76_queue_entry *entry; struct mt76_desc *desc; @@ -131,9 +137,11 @@ struct mt76_queue { int queued; int buf_size; bool stopped; + bool blocked; u8 buf_offset; u8 hw_idx; + u8 qid; dma_addr_t desc_dma; struct sk_buff *rx_head; @@ -147,7 +155,9 @@ struct mt76_mcu_ops { int (*mcu_send_msg)(struct mt76_dev *dev, int cmd, const void *data, int len, bool wait_resp); int (*mcu_skb_send_msg)(struct mt76_dev *dev, struct sk_buff *skb, - int cmd, bool wait_resp); + int cmd, int *seq); + int (*mcu_parse_response)(struct mt76_dev *dev, int cmd, + struct sk_buff *skb, int seq); u32 (*mcu_rr)(struct mt76_dev *dev, u32 offset); void (*mcu_wr)(struct mt76_dev *dev, u32 offset, u32 val); int (*mcu_wr_rp)(struct mt76_dev *dev, u32 base, @@ -164,11 +174,11 @@ struct mt76_queue_ops { int idx, int n_desc, int bufsize, u32 ring_base); - int (*tx_queue_skb)(struct mt76_dev *dev, enum mt76_txq_id qid, + int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta); - int (*tx_queue_skb_raw)(struct mt76_dev *dev, enum mt76_txq_id qid, + int (*tx_queue_skb_raw)(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, u32 tx_info); void *(*dequeue)(struct mt76_dev *dev, struct mt76_queue *q, bool flush, @@ -176,7 +186,7 @@ struct mt76_queue_ops { void (*rx_reset)(struct mt76_dev *dev, enum mt76_rxq_id qid); - void (*tx_cleanup)(struct mt76_dev *dev, enum mt76_txq_id qid, + void (*tx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q, bool flush); void (*kick)(struct mt76_dev *dev, struct mt76_queue *q); @@ -185,6 +195,7 @@ struct mt76_queue_ops { enum mt76_wcid_flags { MT_WCID_FLAG_CHECK_PS, MT_WCID_FLAG_PS, + MT_WCID_FLAG_4ADDR, }; #define MT76_N_WCIDS 288 @@ -411,6 +422,7 @@ enum mt76u_out_ep { struct mt76_mcu { struct mutex mutex; u32 msg_seq; + int timeout; struct sk_buff_head res_q; wait_queue_head_t wait; @@ -426,7 +438,9 @@ struct mt76_usb { u8 *data; u16 data_len; - struct tasklet_struct rx_tasklet; + struct mt76_worker status_worker; + struct mt76_worker rx_worker; + struct work_struct stat_work; u8 out_ep[__MT_EP_OUT_MAX]; @@ -445,25 +459,18 @@ struct mt76_usb { #define MT76S_XMIT_BUF_SZ (16 * PAGE_SIZE) struct mt76_sdio { - struct workqueue_struct *txrx_wq; - struct { - struct work_struct xmit_work; - struct work_struct status_work; - } tx; - struct { - struct work_struct recv_work; - struct work_struct net_work; - } rx; + struct mt76_worker txrx_worker; + struct mt76_worker status_worker; + struct mt76_worker net_worker; struct work_struct stat_work; - u8 *xmit_buf[MT_TXQ_MCU_WA]; + u8 *xmit_buf[IEEE80211_NUM_ACS + 2]; struct sdio_func *func; void *intr_data; struct { - struct mutex lock; int pse_data_quota; int ple_data_quota; int pse_mcu_quota; @@ -528,6 +535,8 @@ struct mt76_testmode_data { u8 tx_rate_nss; u8 tx_rate_sgi; u8 tx_rate_ldpc; + u8 tx_rate_stbc; + u8 tx_ltf; u8 tx_antenna_mask; @@ -555,15 +564,20 @@ struct mt76_phy { unsigned long state; + struct mt76_queue *q_tx[__MT_TXQ_MAX]; + struct cfg80211_chan_def chandef; struct ieee80211_channel *main_chan; struct mt76_channel_state *chan_state; ktime_t survey_time; + struct mt76_hw_cap cap; struct mt76_sband sband_2g; struct mt76_sband sband_5g; + u8 macaddr[ETH_ALEN]; + u32 vif_mask; int txpower_cur; @@ -601,7 +615,7 @@ struct mt76_dev { struct sk_buff_head rx_skb[__MT_RXQ_MAX]; struct list_head txwi_cache; - struct mt76_queue *q_tx[2 * __MT_TXQ_MAX]; + struct mt76_queue *q_mcu[__MT_MCUQ_MAX]; struct mt76_queue q_rx[__MT_RXQ_MAX]; const struct mt76_queue_ops *queue_ops; int tx_dma_idx[4]; @@ -619,7 +633,6 @@ struct mt76_dev { struct mt76_wcid global_wcid; struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; - u8 macaddr[ETH_ALEN]; u32 rev; u32 aggr_stats[32]; @@ -630,7 +643,6 @@ struct mt76_dev { struct debugfs_blob_wrapper eeprom; struct debugfs_blob_wrapper otp; - struct mt76_hw_cap cap; struct mt76_rate_power rate_power; @@ -690,10 +702,7 @@ enum mt76_phy_type { #define mt76_wr_rp(dev, ...) (dev)->mt76.bus->wr_rp(&((dev)->mt76), __VA_ARGS__) #define mt76_rd_rp(dev, ...) (dev)->mt76.bus->rd_rp(&((dev)->mt76), __VA_ARGS__) -#define mt76_mcu_send_msg(dev, ...) (dev)->mt76.mcu_ops->mcu_send_msg(&((dev)->mt76), __VA_ARGS__) -#define __mt76_mcu_send_msg(dev, ...) (dev)->mcu_ops->mcu_send_msg((dev), __VA_ARGS__) -#define __mt76_mcu_skb_send_msg(dev, ...) (dev)->mcu_ops->mcu_skb_send_msg((dev), __VA_ARGS__) #define mt76_mcu_restart(dev, ...) (dev)->mt76.mcu_ops->mcu_restart(&((dev)->mt76)) #define __mt76_mcu_restart(dev, ...) (dev)->mcu_ops->mcu_restart((dev)) @@ -752,7 +761,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__) #define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) -#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) +#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) #define mt76_for_each_q_rx(dev, i) \ @@ -770,7 +779,8 @@ void mt76_unregister_phy(struct mt76_phy *phy); struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, const struct ieee80211_ops *ops); -int mt76_register_phy(struct mt76_phy *phy); +int mt76_register_phy(struct mt76_phy *phy, bool vht, + struct ieee80211_rate *rates, int n_rates); struct dentry *mt76_register_debugfs(struct mt76_dev *dev); int mt76_queues_read(struct seq_file *s, void *data); @@ -778,7 +788,40 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str, s8 *val, int len); int mt76_eeprom_init(struct mt76_dev *dev, int len); -void mt76_eeprom_override(struct mt76_dev *dev); +void mt76_eeprom_override(struct mt76_phy *phy); + +struct mt76_queue * +mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, + int ring_base); +static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx, + int n_desc, int ring_base) +{ + struct mt76_queue *q; + + q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base); + if (IS_ERR(q)) + return PTR_ERR(q); + + q->qid = qid; + phy->q_tx[qid] = q; + + return 0; +} + +static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx, + int n_desc, int ring_base) +{ + struct mt76_queue *q; + + q = mt76_init_queue(dev, qid, idx, n_desc, ring_base); + if (IS_ERR(q)) + return PTR_ERR(q); + + q->qid = __MT_TXQ_MAX + qid; + dev->q_mcu[qid] = q; + + return 0; +} static inline struct mt76_phy * mt76_dev_phy(struct mt76_dev *dev, bool phy_ext) @@ -901,7 +944,7 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); void mt76_tx(struct mt76_phy *dev, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb); void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq); -void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, +void mt76_stop_tx_queues(struct mt76_phy *phy, struct ieee80211_sta *sta, bool send_bar); void mt76_tx_check_agg_ssn(struct ieee80211_sta *sta, struct sk_buff *skb); void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid); @@ -1064,7 +1107,6 @@ void mt76u_queues_deinit(struct mt76_dev *dev); int mt76s_init(struct mt76_dev *dev, struct sdio_func *func, const struct mt76_bus_ops *bus_ops); int mt76s_alloc_queues(struct mt76_dev *dev); -void mt76s_stop_txrx(struct mt76_dev *dev); void mt76s_deinit(struct mt76_dev *dev); struct sk_buff * @@ -1073,6 +1115,25 @@ mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb); struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires); +int mt76_mcu_send_and_get_msg(struct mt76_dev *dev, int cmd, const void *data, + int len, bool wait_resp, struct sk_buff **ret); +int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, + int cmd, bool wait_resp, struct sk_buff **ret); +int mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data, + int len); +static inline int +mt76_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, int len, + bool wait_resp) +{ + return mt76_mcu_send_and_get_msg(dev, cmd, data, len, wait_resp, NULL); +} + +static inline int +mt76_mcu_skb_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd, + bool wait_resp) +{ + return mt76_mcu_skb_send_and_get_msg(dev, skb, cmd, wait_resp, NULL); +} void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index d728c5e43783..5d4522f440b7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -13,23 +13,25 @@ static void mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt7603_dev *dev = (struct mt7603_dev *)priv; + struct mt76_dev *mdev = &dev->mt76; struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; struct sk_buff *skb = NULL; - if (!(dev->mt76.beacon_mask & BIT(mvif->idx))) + if (!(mdev->beacon_mask & BIT(mvif->idx))) return; skb = ieee80211_beacon_get(mt76_hw(dev), vif); if (!skb) return; - mt76_tx_queue_skb(dev, MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL); + mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON], skb, + &mvif->sta.wcid, NULL); spin_lock_bh(&dev->ps_lock); mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) | FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, - dev->mt76.q_tx[MT_TXQ_CAB]->hw_idx) | + dev->mphy.q_tx[MT_TXQ_CAB]->hw_idx) | FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) | FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8)); @@ -64,9 +66,10 @@ mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) data->count[mvif->idx]++; } -void mt7603_pre_tbtt_tasklet(unsigned long arg) +void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) { - struct mt7603_dev *dev = (struct mt7603_dev *)arg; + struct mt7603_dev *dev = from_tasklet(dev, t, mt76.pre_tbtt_tasklet); + struct mt76_dev *mdev = &dev->mt76; struct mt76_queue *q; struct beacon_bc_data data = {}; struct sk_buff *skb; @@ -78,7 +81,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg) data.dev = dev; __skb_queue_head_init(&data.q); - q = dev->mt76.q_tx[MT_TXQ_BEACON]; + q = dev->mphy.q_tx[MT_TXQ_BEACON]; spin_lock_bh(&q->lock); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, @@ -89,13 +92,13 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg) /* Flush all previous CAB queue packets */ mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0)); - mt76_queue_tx_cleanup(dev, MT_TXQ_CAB, false); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false); - mt76_csa_check(&dev->mt76); - if (dev->mt76.csa_complete) + mt76_csa_check(mdev); + if (mdev->csa_complete) goto out; - q = dev->mt76.q_tx[MT_TXQ_CAB]; + q = dev->mphy.q_tx[MT_TXQ_CAB]; do { nframes = skb_queue_len(&data.q); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), @@ -120,7 +123,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg) struct ieee80211_vif *vif = info->control.vif; struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; - mt76_tx_queue_skb(dev, MT_TXQ_CAB, skb, &mvif->sta.wcid, NULL); + mt76_tx_queue_skb(dev, q, skb, &mvif->sta.wcid, NULL); } mt76_queue_kick(dev, q); spin_unlock_bh(&q->lock); @@ -135,9 +138,8 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg) ((1 << (MT7603_MAX_INTERFACES - 1)) - 1))); out: - mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false); - if (dev->mt76.q_tx[MT_TXQ_BEACON]->queued > - hweight8(dev->mt76.beacon_mask)) + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false); + if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > hweight8(mdev->beacon_mask)) dev->beacon_check++; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index d60d00f6f6a0..0086f18cb79a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -4,27 +4,6 @@ #include "mac.h" #include "../dma.h" -static int -mt7603_init_tx_queue(struct mt7603_dev *dev, int qid, int idx, int n_desc) -{ - struct mt76_queue *hwq; - int err; - - hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); - if (!hwq) - return -ENOMEM; - - err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); - if (err < 0) - return err; - - dev->mt76.q_tx[qid] = hwq; - - mt7603_irq_enable(dev, MT_INT_TX_DONE(idx)); - - return 0; -} - static void mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) { @@ -152,14 +131,16 @@ static int mt7603_poll_tx(struct napi_struct *napi, int budget) 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_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); + for (i = MT_TXQ_PSD; i >= 0; i--) + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false); if (napi_complete_done(napi, 0)) mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); - for (i = MT_TXQ_MCU; i >= 0; i--) - mt76_queue_tx_cleanup(dev, i, false); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); + for (i = MT_TXQ_PSD; i >= 0; i--) + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false); mt7603_mac_sta_poll(dev); @@ -191,32 +172,42 @@ int mt7603_dma_init(struct mt7603_dev *dev) mt7603_pse_client_reset(dev); for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { - ret = mt7603_init_tx_queue(dev, i, wmm_queue_map[i], - MT7603_TX_RING_SIZE); + ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], + MT7603_TX_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; } - ret = mt7603_init_tx_queue(dev, MT_TXQ_PSD, - MT_TX_HW_QUEUE_MGMT, MT7603_PSD_RING_SIZE); + ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, + MT7603_PSD_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; - ret = mt7603_init_tx_queue(dev, MT_TXQ_MCU, - MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE); + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT_TX_HW_QUEUE_MCU, + MT_MCU_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; - ret = mt7603_init_tx_queue(dev, MT_TXQ_BEACON, - MT_TX_HW_QUEUE_BCN, MT_MCU_RING_SIZE); + ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN, + MT_MCU_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; - ret = mt7603_init_tx_queue(dev, MT_TXQ_CAB, - MT_TX_HW_QUEUE_BMC, MT_MCU_RING_SIZE); + ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC, + MT_MCU_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; + mt7603_irq_enable(dev, + MT_INT_TX_DONE(IEEE80211_AC_VO) | + MT_INT_TX_DONE(IEEE80211_AC_VI) | + MT_INT_TX_DONE(IEEE80211_AC_BE) | + MT_INT_TX_DONE(IEEE80211_AC_BK) | + MT_INT_TX_DONE(MT_TX_HW_QUEUE_MGMT) | + MT_INT_TX_DONE(MT_TX_HW_QUEUE_MCU) | + MT_INT_TX_DONE(MT_TX_HW_QUEUE_BCN) | + MT_INT_TX_DONE(MT_TX_HW_QUEUE_BMC)); + ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1, MT7603_MCU_RX_RING_SIZE, MT_RX_BUF_SIZE); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c index 01f1e0da5ee1..d951cb81df83 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c @@ -141,6 +141,7 @@ static int mt7603_check_eeprom(struct mt76_dev *dev) switch (val) { case 0x7628: case 0x7603: + case 0x7600: return 0; default: return -EINVAL; @@ -170,8 +171,8 @@ int mt7603_eeprom_init(struct mt7603_dev *dev) } eeprom = (u8 *)dev->mt76.eeprom.data; - dev->mt76.cap.has_2ghz = true; - memcpy(dev->mt76.macaddr, eeprom + MT_EE_MAC_ADDR, ETH_ALEN); + dev->mphy.cap.has_2ghz = true; + memcpy(dev->mphy.macaddr, eeprom + MT_EE_MAC_ADDR, ETH_ALEN); /* Check for 1SS devices */ dev->mphy.antenna_mask = 3; @@ -180,7 +181,7 @@ int mt7603_eeprom_init(struct mt7603_dev *dev) is_mt7688(dev)) dev->mphy.antenna_mask = 1; - mt76_eeprom_override(&dev->mt76); + mt76_eeprom_override(&dev->mphy); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index c4848fafd270..b14e08046e20 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -533,8 +533,7 @@ int mt7603_register_device(struct mt7603_dev *dev) spin_lock_init(&dev->ps_lock); INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7603_mac_work); - tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet, - (unsigned long)dev); + tasklet_setup(&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet); dev->slottime = 9; dev->sensitivity_limit = 28; @@ -557,6 +556,7 @@ int mt7603_register_device(struct mt7603_dev *dev) ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index f665a1c95eed..55095e66f2ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -445,7 +445,7 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev) sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); for (i = 0; i < 4; i++) { - struct mt76_queue *q = dev->mt76.q_tx[i]; + struct mt76_queue *q = dev->mphy.q_tx[i]; u8 qidx = q->hw_idx; u8 tid = ac_to_tid[i]; u32 txtime = airtime[qidx]; @@ -896,7 +896,7 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; struct ieee80211_vif *vif = info->control.vif; - struct mt76_queue *q = dev->mt76.q_tx[qid]; + struct mt76_queue *q = dev->mphy.q_tx[qid]; struct mt7603_vif *mvif; int wlan_idx; int hdr_len = ieee80211_get_hdrlen_from_skb(skb); @@ -1434,8 +1434,9 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) mt7603_pse_client_reset(dev); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true); for (i = 0; i < __MT_TXQ_MAX; i++) - mt76_queue_tx_cleanup(dev, i, true); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); @@ -1514,7 +1515,7 @@ static bool mt7603_tx_hang(struct mt7603_dev *dev) int i; for (i = 0; i < 4; i++) { - q = dev->mt76.q_tx[i]; + q = dev->mphy.q_tx[i]; if (!q->queued) continue; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index c9226dceb510..6d47b57cbc39 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -380,9 +380,11 @@ mt7603_ps_tx_list(struct mt7603_dev *dev, struct sk_buff_head *list) { struct sk_buff *skb; - while ((skb = __skb_dequeue(list)) != NULL) - mt76_tx_queue_skb_raw(dev, skb_get_queue_mapping(skb), - skb, 0); + while ((skb = __skb_dequeue(list)) != NULL) { + int qid = skb_get_queue_mapping(skb); + + mt76_tx_queue_skb_raw(dev, dev->mphy.q_tx[qid], skb, 0); + } } void @@ -392,7 +394,7 @@ mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; struct sk_buff_head list; - mt76_stop_tx_queues(&dev->mt76, sta, true); + mt76_stop_tx_queues(&dev->mphy, sta, true); mt7603_wtbl_set_ps(dev, msta, ps); if (ps) return; @@ -512,7 +514,7 @@ mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, u16 cw_max = (1 << 10) - 1; u32 val; - queue = dev->mt76.q_tx[queue]->hw_idx; + queue = dev->mphy.q_tx[queue]->hw_idx; if (params->cw_min) cw_min = params->cw_min; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index a47a3a644ecc..96b6c8916730 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -14,14 +14,38 @@ struct mt7603_fw_trailer { } __packed; static int -__mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, - int cmd, int *wait_seq) +mt7603_mcu_parse_response(struct mt76_dev *mdev, int cmd, + struct sk_buff *skb, int seq) { + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + struct mt7603_mcu_rxd *rxd; + + if (!skb) { + dev_err(mdev->dev, + "MCU message %d (seq %d) timed out\n", + cmd, seq); + dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT; + return -ETIMEDOUT; + } + + rxd = (struct mt7603_mcu_rxd *)skb->data; + if (seq != rxd->seq) + return -EAGAIN; + + return 0; +} + +static int +mt7603_mcu_skb_send_msg(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, int *wait_seq) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); int hdrlen = dev->mcu_running ? sizeof(struct mt7603_mcu_txd) : 12; - struct mt76_dev *mdev = &dev->mt76; struct mt7603_mcu_txd *txd; u8 seq; + mdev->mcu.timeout = 3 * HZ; + seq = ++mdev->mcu.msg_seq & 0xf; if (!seq) seq = ++mdev->mcu.msg_seq & 0xf; @@ -49,56 +73,7 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, if (wait_seq) *wait_seq = seq; - return mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0); -} - -static int -mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, - int len, bool wait_resp) -{ - struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); - unsigned long expires = jiffies + 3 * HZ; - struct mt7603_mcu_rxd *rxd; - struct sk_buff *skb; - int ret, seq; - - skb = mt76_mcu_msg_alloc(mdev, data, len); - if (!skb) - return -ENOMEM; - - mutex_lock(&mdev->mcu.mutex); - - ret = __mt7603_mcu_msg_send(dev, skb, cmd, &seq); - if (ret) - goto out; - - while (wait_resp) { - bool check_seq = false; - - skb = mt76_mcu_get_response(&dev->mt76, expires); - if (!skb) { - dev_err(mdev->dev, - "MCU message %d (seq %d) timed out\n", - cmd, seq); - dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT; - ret = -ETIMEDOUT; - break; - } - - rxd = (struct mt7603_mcu_rxd *)skb->data; - if (seq == rxd->seq) - check_seq = true; - - dev_kfree_skb(skb); - - if (check_seq) - break; - } - -out: - mutex_unlock(&mdev->mcu.mutex); - - return ret; + return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[MT_MCUQ_WM], skb, 0); } static int @@ -114,29 +89,8 @@ mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len) .mode = cpu_to_le32(BIT(31)), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, - &req, sizeof(req), true); -} - -static int -mt7603_mcu_send_firmware(struct mt7603_dev *dev, const void *data, int len) -{ - int cur_len, ret = 0; - - while (len > 0) { - cur_len = min_t(int, 4096 - sizeof(struct mt7603_mcu_txd), - len); - - ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, - data, cur_len, false); - if (ret) - break; - - data += cur_len; - len -= cur_len; - } - - return ret; + return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, + &req, sizeof(req), true); } static int @@ -150,15 +104,14 @@ mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr) .addr = cpu_to_le32(addr), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, &req, + sizeof(req), true); } static int mt7603_mcu_restart(struct mt76_dev *dev) { - return __mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, - NULL, 0, true); + return mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, NULL, 0, true); } static int mt7603_load_firmware(struct mt7603_dev *dev) @@ -226,7 +179,8 @@ static int mt7603_load_firmware(struct mt7603_dev *dev) goto out; } - ret = mt7603_mcu_send_firmware(dev, fw->data, dl_len); + ret = mt76_mcu_send_firmware(&dev->mt76, -MCU_CMD_FW_SCATTER, + fw->data, dl_len); if (ret) { dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); goto out; @@ -266,7 +220,8 @@ int mt7603_mcu_init(struct mt7603_dev *dev) { static const struct mt76_mcu_ops mt7603_mcu_ops = { .headroom = sizeof(struct mt7603_mcu_txd), - .mcu_send_msg = mt7603_mcu_msg_send, + .mcu_skb_send_msg = mt7603_mcu_skb_send_msg, + .mcu_parse_response = mt7603_mcu_parse_response, .mcu_restart = mt7603_mcu_restart, }; @@ -377,8 +332,8 @@ int mt7603_mcu_set_eeprom(struct mt7603_dev *dev) data[i].val = eep[req_fields[i]]; } - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, - req, len, true); + ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + req, len, true); kfree(req); return ret; @@ -424,8 +379,8 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) memcpy(req.temp_comp_power, eep + MT_EE_STEP_NUM_NEG_6_7, sizeof(req.temp_comp_power)); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, + &req, sizeof(req), true); } int mt7603_mcu_set_channel(struct mt7603_dev *dev) @@ -470,8 +425,8 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) for (i = 0; i < ARRAY_SIZE(req.txpower); i++) req.txpower[i] = tx_power; - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, - &req, sizeof(req), true); + ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, &req, + sizeof(req), true); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 2a6e4332ad06..6e0a92a28b1c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -256,7 +256,7 @@ void mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, void mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -void mt7603_pre_tbtt_tasklet(unsigned long arg); +void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t); void mt7603_update_channel(struct mt76_dev *mdev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/pci.c b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c index a5845da3547a..06fa28f645f2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c @@ -57,7 +57,8 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; error: - ieee80211_free_hw(mt76_hw(dev)); + mt76_free_device(&dev->mt76); + return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index 00ba550fc48f..4d5e3f8b2a62 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -55,11 +55,26 @@ static int mt7615_pm_set(void *data, u64 val) { struct mt7615_dev *dev = data; + int ret = 0; if (!mt7615_wait_for_mcu_init(dev)) return 0; - return mt7615_pm_set_enable(dev, val); + if (!mt7615_firmware_offload(dev) || !mt76_is_mmio(&dev->mt76)) + return -EOPNOTSUPP; + + mt7615_mutex_acquire(dev); + + if (dev->phy.n_beacon_vif) { + ret = -EBUSY; + goto out; + } + + dev->pm.enable = val; +out: + mt7615_mutex_release(dev); + + return ret; } static int @@ -172,7 +187,7 @@ mt7615_reset_test_set(void *data, u64 val) skb_put(skb, 1); mt7615_mutex_acquire(dev); - mt76_tx_queue_skb_raw(dev, 0, skb, 0); + mt76_tx_queue_skb_raw(dev, dev->mphy.q_tx[0], skb, 0); mt7615_mutex_release(dev); return 0; @@ -317,21 +332,18 @@ static int mt7615_queues_read(struct seq_file *s, void *data) { struct mt7615_dev *dev = dev_get_drvdata(s->private); - static const struct { + struct { + struct mt76_queue *q; char *queue; - int id; } queue_map[] = { - { "PDMA0", MT_TXQ_BE }, - { "MCUQ", MT_TXQ_MCU }, - { "MCUFWQ", MT_TXQ_FWDL }, + { dev->mphy.q_tx[MT_TXQ_BE], "PDMA0" }, + { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUQ" }, + { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" }, }; int i; for (i = 0; i < ARRAY_SIZE(queue_map); i++) { - struct mt76_queue *q = dev->mt76.q_tx[queue_map[i].id]; - - if (!q) - continue; + struct mt76_queue *q = queue_map[i].q; seq_printf(s, "%s: queued=%d head=%d tail=%d\n", @@ -365,6 +377,107 @@ mt7615_rf_reg_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_reg, mt7615_rf_reg_get, mt7615_rf_reg_set, "0x%08llx\n"); +static ssize_t +mt7615_ext_mac_addr_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct mt7615_dev *dev = file->private_data; + char buf[32 * ((ETH_ALEN * 3) + 4) + 1]; + u8 addr[ETH_ALEN]; + int ofs = 0; + int i; + + for (i = 0; i < 32; i++) { + if (!(dev->muar_mask & BIT(i))) + continue; + + mt76_wr(dev, MT_WF_RMAC_MAR1, + FIELD_PREP(MT_WF_RMAC_MAR1_IDX, i * 2) | + MT_WF_RMAC_MAR1_START); + put_unaligned_le32(mt76_rr(dev, MT_WF_RMAC_MAR0), addr); + put_unaligned_le16((mt76_rr(dev, MT_WF_RMAC_MAR1) & + MT_WF_RMAC_MAR1_ADDR), addr + 4); + ofs += snprintf(buf + ofs, sizeof(buf) - ofs, "%d=%pM\n", i, addr); + } + + return simple_read_from_buffer(userbuf, count, ppos, buf, ofs); +} + +static ssize_t +mt7615_ext_mac_addr_write(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct mt7615_dev *dev = file->private_data; + unsigned long idx = 0; + u8 addr[ETH_ALEN]; + char buf[32]; + char *p; + + if (count > sizeof(buf)) + return -EINVAL; + + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[sizeof(buf) - 1] = '\0'; + + p = strchr(buf, '='); + if (p) { + *p = 0; + p++; + + if (kstrtoul(buf, 0, &idx) || idx > 31) + return -EINVAL; + } else { + idx = 0; + p = buf; + } + + if (!mac_pton(p, addr)) + return -EINVAL; + + if (is_valid_ether_addr(addr)) { + dev->muar_mask |= BIT(idx); + } else { + memset(addr, 0, sizeof(addr)); + dev->muar_mask &= ~BIT(idx); + } + + mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, 1); + mt76_wr(dev, MT_WF_RMAC_MAR0, get_unaligned_le32(addr)); + mt76_wr(dev, MT_WF_RMAC_MAR1, + get_unaligned_le16(addr + 4) | + FIELD_PREP(MT_WF_RMAC_MAR1_IDX, idx * 2) | + MT_WF_RMAC_MAR1_START | + MT_WF_RMAC_MAR1_WRITE); + + mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, !!dev->muar_mask); + + return count; +} + +static const struct file_operations fops_ext_mac_addr = { + .open = simple_open, + .llseek = generic_file_llseek, + .read = mt7615_ext_mac_addr_read, + .write = mt7615_ext_mac_addr_write, + .owner = THIS_MODULE, +}; + +static int +mt7663s_sched_quota_read(struct seq_file *s, void *data) +{ + struct mt7615_dev *dev = dev_get_drvdata(s->private); + struct mt76_sdio *sdio = &dev->mt76.sdio; + + seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota); + seq_printf(s, "ple_data_quota\t%d\n", sdio->sched.ple_data_quota); + seq_printf(s, "pse_mcu_quota\t%d\n", sdio->sched.pse_mcu_quota); + seq_printf(s, "sched_deficit\t%d\n", sdio->sched.deficit); + + return 0; +} + int mt7615_init_debugfs(struct mt7615_dev *dev) { struct dentry *dir; @@ -406,11 +519,15 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) &fops_reset_test); debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir, mt7615_read_temperature); + debugfs_create_file("ext_mac_addr", 0600, dir, dev, &fops_ext_mac_addr); debugfs_create_u32("rf_wfidx", 0600, dir, &dev->debugfs_rf_wf); debugfs_create_u32("rf_regidx", 0600, dir, &dev->debugfs_rf_reg); debugfs_create_file_unsafe("rf_regval", 0600, dir, dev, &fops_rf_reg); + if (mt76_is_sdio(&dev->mt76)) + debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir, + mt7663s_sched_quota_read); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index bf8ae14121db..25e3069cf2b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -12,25 +12,6 @@ #include "mac.h" static int -mt7615_init_tx_queue(struct mt7615_dev *dev, int qid, int idx, int n_desc) -{ - struct mt76_queue *hwq; - int err; - - hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); - if (!hwq) - return -ENOMEM; - - err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); - if (err < 0) - return err; - - dev->mt76.q_tx[qid] = hwq; - - return 0; -} - -static int mt7622_init_tx_queues_multi(struct mt7615_dev *dev) { static const u8 wmm_queue_map[] = { @@ -43,20 +24,21 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev) int i; for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { - ret = mt7615_init_tx_queue(dev, i, wmm_queue_map[i], - MT7615_TX_RING_SIZE / 2); + ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], + MT7615_TX_RING_SIZE / 2, + MT_TX_RING_BASE); if (ret) return ret; } - ret = mt7615_init_tx_queue(dev, MT_TXQ_PSD, - MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE); + ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT7622_TXQ_MGMT, + MT7615_TX_MGMT_RING_SIZE, + MT_TX_RING_BASE); if (ret) return ret; - ret = mt7615_init_tx_queue(dev, MT_TXQ_MCU, - MT7622_TXQ_MCU, MT7615_TX_MCU_RING_SIZE); - return ret; + return mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7622_TXQ_MCU, + MT7615_TX_MCU_RING_SIZE, MT_TX_RING_BASE); } static int @@ -64,25 +46,24 @@ mt7615_init_tx_queues(struct mt7615_dev *dev) { int ret, i; - ret = mt7615_init_tx_queue(dev, MT_TXQ_FWDL, - MT7615_TXQ_FWDL, - MT7615_TX_FWDL_RING_SIZE); + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7615_TXQ_FWDL, + MT7615_TX_FWDL_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; if (!is_mt7615(&dev->mt76)) return mt7622_init_tx_queues_multi(dev); - ret = mt7615_init_tx_queue(dev, 0, 0, MT7615_TX_RING_SIZE); + ret = mt76_init_tx_queue(&dev->mphy, 0, 0, MT7615_TX_RING_SIZE, + MT_TX_RING_BASE); if (ret) return ret; - for (i = 1; i < MT_TXQ_MCU; i++) - dev->mt76.q_tx[i] = dev->mt76.q_tx[0]; + for (i = 1; i <= MT_TXQ_PSD ; i++) + dev->mphy.q_tx[i] = dev->mphy.q_tx[0]; - ret = mt7615_init_tx_queue(dev, MT_TXQ_MCU, MT7615_TXQ_MCU, - MT7615_TX_MCU_RING_SIZE); - return 0; + return mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7615_TXQ_MCU, + MT7615_TX_MCU_RING_SIZE, MT_TX_RING_BASE); } static int mt7615_poll_tx(struct napi_struct *napi, int budget) @@ -91,7 +72,7 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget) dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); - mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); if (napi_complete_done(napi, 0)) mt7615_irq_enable(dev, mt7615_tx_mcu_int_mask(dev)); @@ -202,7 +183,7 @@ int mt7615_dma_init(struct mt7615_dev *dev) int ret; /* Increase buffer size to receive large VHT MPDUs */ - if (dev->mt76.cap.has_5ghz) + if (dev->mphy.cap.has_5ghz) rx_buf_size *= 2; mt76_dma_attach(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index f4756bb946c3..3232ebd5eda6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -99,20 +99,20 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) if (is_mt7663(&dev->mt76)) { /* dual band */ - dev->mt76.cap.has_2ghz = true; - dev->mt76.cap.has_5ghz = true; + dev->mphy.cap.has_2ghz = true; + dev->mphy.cap.has_5ghz = true; return; } if (is_mt7622(&dev->mt76)) { /* 2GHz only */ - dev->mt76.cap.has_2ghz = true; + dev->mphy.cap.has_2ghz = true; return; } if (is_mt7611(&dev->mt76)) { /* 5GHz only */ - dev->mt76.cap.has_5ghz = true; + dev->mphy.cap.has_5ghz = true; return; } @@ -120,17 +120,17 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) eeprom[MT_EE_WIFI_CONF]); switch (val) { case MT_EE_5GHZ: - dev->mt76.cap.has_5ghz = true; + dev->mphy.cap.has_5ghz = true; break; case MT_EE_2GHZ: - dev->mt76.cap.has_2ghz = true; + dev->mphy.cap.has_2ghz = true; break; case MT_EE_DBDC: dev->dbdc_support = true; - /* fall through */ + fallthrough; default: - dev->mt76.cap.has_2ghz = true; - dev->mt76.cap.has_5ghz = true; + dev->mphy.cap.has_2ghz = true; + dev->mphy.cap.has_5ghz = true; break; } } @@ -342,10 +342,10 @@ int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr) } mt7615_eeprom_parse_hw_cap(dev); - memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, + memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN); - mt76_eeprom_override(&dev->mt76); + mt76_eeprom_override(&dev->mphy); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index e194259c84e9..a73b76e57c7f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -221,7 +221,7 @@ static const struct ieee80211_iface_combination if_comb_radar[] = { { .limits = if_limits, .n_limits = ARRAY_SIZE(if_limits), - .max_interfaces = 4, + .max_interfaces = MT7615_MAX_INTERFACES, .num_different_channels = 1, .beacon_int_infra_match = true, .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | @@ -237,7 +237,7 @@ static const struct ieee80211_iface_combination if_comb[] = { { .limits = if_limits, .n_limits = ARRAY_SIZE(if_limits), - .max_interfaces = 4, + .max_interfaces = MT7615_MAX_INTERFACES, .num_different_channels = 1, .beacon_int_infra_match = true, } @@ -385,7 +385,7 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) { struct mt7615_phy *phy = mt7615_ext_phy(dev); struct mt76_phy *mphy; - int ret; + int i, ret; if (!is_mt7615(&dev->mt76)) return -EOPNOTSUPP; @@ -422,14 +422,21 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) * Make the secondary PHY MAC address local without overlapping with * the usual MAC address allocation scheme on multiple virtual interfaces */ - mphy->hw->wiphy->perm_addr[0] |= 2; - mphy->hw->wiphy->perm_addr[0] ^= BIT(7); + memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, + ETH_ALEN); + mphy->macaddr[0] |= 2; + mphy->macaddr[0] ^= BIT(7); + mt76_eeprom_override(mphy); /* second phy can only handle 5 GHz */ - mphy->sband_2g.sband.n_channels = 0; - mphy->hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; + mphy->cap.has_5ghz = true; - ret = mt76_register_phy(mphy); + /* mt7615 second phy shares the same hw queues with the primary one */ + for (i = 0; i <= MT_TXQ_PSD ; i++) + mphy->q_tx[i] = dev->mphy.q_tx[i]; + + ret = mt76_register_phy(mphy, true, mt7615_rates, + ARRAY_SIZE(mt7615_rates)); if (ret) ieee80211_free_hw(mphy->hw); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 8dc645e398fd..0f360be0b885 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -215,8 +215,8 @@ static void mt7615_mac_fill_tm_rx(struct mt7615_dev *dev, __le32 *rxv) dev->test.last_rcpi[1] = FIELD_GET(MT_RXV4_RCPI1, rxv4); dev->test.last_rcpi[2] = FIELD_GET(MT_RXV4_RCPI2, rxv4); dev->test.last_rcpi[3] = FIELD_GET(MT_RXV4_RCPI3, rxv4); - dev->test.last_ib_rssi = FIELD_GET(MT_RXV3_IB_RSSI, rxv3); - dev->test.last_wb_rssi = FIELD_GET(MT_RXV3_WB_RSSI, rxv3); + dev->test.last_ib_rssi[0] = FIELD_GET(MT_RXV3_IB_RSSI, rxv3); + dev->test.last_wb_rssi[0] = FIELD_GET(MT_RXV3_WB_RSSI, rxv3); #endif } @@ -915,22 +915,20 @@ mt7615_mac_queue_rate_update(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *rates) { struct mt7615_dev *dev = phy->dev; - struct mt7615_wtbl_desc *wd; + struct mt7615_wtbl_rate_desc *wrd; - if (work_pending(&dev->wtbl_work)) + if (work_pending(&dev->rate_work)) return -EBUSY; - wd = kzalloc(sizeof(*wd), GFP_ATOMIC); - if (!wd) + wrd = kzalloc(sizeof(*wrd), GFP_ATOMIC); + if (!wrd) return -ENOMEM; - wd->type = MT7615_WTBL_RATE_DESC; - wd->sta = sta; - + wrd->sta = sta; mt7615_mac_update_rate_desc(phy, sta, probe_rate, rates, - &wd->rate); - list_add_tail(&wd->node, &dev->wd_head); - queue_work(dev->mt76.wq, &dev->wtbl_work); + &wrd->rate); + list_add_tail(&wrd->node, &dev->wrd_head); + queue_work(dev->mt76.wq, &dev->rate_work); return 0; } @@ -1030,31 +1028,33 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, } EXPORT_SYMBOL_GPL(mt7615_mac_set_rates); -int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, - struct mt76_wcid *wcid, - u8 *key, u8 keylen, - enum mt7615_cipher_type cipher, - enum set_key_cmd cmd) +static int +mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, + enum mt7615_cipher_type cipher, + enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; u8 data[32] = {}; - if (keylen > sizeof(data)) + if (key->keylen > sizeof(data)) return -EINVAL; mt76_rr_copy(dev, addr, data, sizeof(data)); if (cmd == SET_KEY) { if (cipher == MT_CIPHER_TKIP) { /* Rx/Tx MIC keys are swapped */ - memcpy(data + 16, key + 24, 8); - memcpy(data + 24, key + 16, 8); + memcpy(data, key->key, 16); + memcpy(data + 16, key->key + 24, 8); + memcpy(data + 24, key->key + 16, 8); + } else { + if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher) + memmove(data + 16, data, 16); + if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) + memcpy(data, key->key, key->keylen); + else if (cipher == MT_CIPHER_BIP_CMAC_128) + memcpy(data + 16, key->key, 16); } - if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher) - memmove(data + 16, data, 16); - if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) - memcpy(data, key, keylen); - else if (cipher == MT_CIPHER_BIP_CMAC_128) - memcpy(data + 16, key, 16); } else { if (wcid->cipher & ~BIT(cipher)) { if (cipher != MT_CIPHER_BIP_CMAC_128) @@ -1068,12 +1068,11 @@ int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, return 0; } -EXPORT_SYMBOL_GPL(mt7615_mac_wtbl_update_key); -int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, - struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, - int keyidx, enum set_key_cmd cmd) +static int +mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, + enum mt7615_cipher_type cipher, + int keyidx, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; @@ -1105,12 +1104,11 @@ int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, return 0; } -EXPORT_SYMBOL_GPL(mt7615_mac_wtbl_update_pk); -void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, - struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, - enum set_key_cmd cmd) +static void +mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, + enum mt7615_cipher_type cipher, + enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); @@ -1128,12 +1126,11 @@ void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); } } -EXPORT_SYMBOL_GPL(mt7615_mac_wtbl_update_cipher); -int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, - struct mt76_wcid *wcid, - struct ieee80211_key_conf *key, - enum set_key_cmd cmd) +int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, + struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd) { enum mt7615_cipher_type cipher; int err; @@ -1142,25 +1139,32 @@ int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, if (cipher == MT_CIPHER_NONE) return -EOPNOTSUPP; - spin_lock_bh(&dev->mt76.lock); - mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd); - err = mt7615_mac_wtbl_update_key(dev, wcid, key->key, key->keylen, - cipher, cmd); + err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd); if (err < 0) - goto out; + return err; - err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, - cmd); + err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd); if (err < 0) - goto out; + return err; if (cmd == SET_KEY) wcid->cipher |= BIT(cipher); else wcid->cipher &= ~BIT(cipher); -out: + return 0; +} + +int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, + struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd) +{ + int err; + + spin_lock_bh(&dev->mt76.lock); + err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); spin_unlock_bh(&dev->mt76.lock); return err; @@ -1431,12 +1435,12 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data; u8 i, count; - mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); if (is_mt7615(&dev->mt76)) { - mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); } else { for (i = 0; i < IEEE80211_NUM_ACS; i++) - mt76_queue_tx_cleanup(dev, i, false); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false); } count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl)); @@ -1969,49 +1973,6 @@ out: queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta); } -static void -mt7615_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ - struct mt7615_phy *phy = priv; - struct mt7615_dev *dev = phy->dev; - bool ext_phy = phy != &dev->phy; - - if (mt7615_mcu_set_bss_pm(dev, vif, dev->pm.enable)) - return; - - if (dev->pm.enable) { - vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; - mt76_set(dev, MT_WF_RFCR(ext_phy), - MT_WF_RFCR_DROP_OTHER_BEACON); - } else { - vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; - mt76_clear(dev, MT_WF_RFCR(ext_phy), - MT_WF_RFCR_DROP_OTHER_BEACON); - } -} - -int mt7615_pm_set_enable(struct mt7615_dev *dev, bool enable) -{ - struct mt76_phy *mphy = dev->phy.mt76; - - if (!mt7615_firmware_offload(dev) || !mt76_is_mmio(&dev->mt76)) - return -EOPNOTSUPP; - - mt7615_mutex_acquire(dev); - - if (dev->pm.enable == enable) - goto out; - - dev->pm.enable = enable; - ieee80211_iterate_active_interfaces(mphy->hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7615_pm_interface_iter, mphy->priv); -out: - mt7615_mutex_release(dev); - - return 0; -} - void mt7615_mac_work(struct work_struct *work) { struct mt7615_phy *phy; @@ -2083,8 +2044,9 @@ void mt7615_dma_reset(struct mt7615_dev *dev) MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); usleep_range(1000, 2000); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true); for (i = 0; i < __MT_TXQ_MAX; i++) - mt76_queue_tx_cleanup(dev, i, true); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); @@ -2314,3 +2276,46 @@ stop: mt7615_dfs_stop_radar_detector(phy); return 0; } + +int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy, + struct ieee80211_vif *vif, + bool enable) +{ + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + int err; + + if (!mt7615_firmware_offload(dev)) + return -EOPNOTSUPP; + + switch (vif->type) { + case NL80211_IFTYPE_MONITOR: + return 0; + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + if (enable) + phy->n_beacon_vif++; + else + phy->n_beacon_vif--; + fallthrough; + default: + break; + } + + err = mt7615_mcu_set_bss_pm(dev, vif, !phy->n_beacon_vif); + if (err) + return err; + + if (phy->n_beacon_vif) { + vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; + mt76_clear(dev, MT_WF_RFCR(ext_phy), + MT_WF_RFCR_DROP_OTHER_BEACON); + } else { + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; + mt76_set(dev, MT_WF_RFCR(ext_phy), + MT_WF_RFCR_DROP_OTHER_BEACON); + } + + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 3186b7b2ca48..56dd0b4e4460 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -115,29 +115,50 @@ static void mt7615_stop(struct ieee80211_hw *hw) mt7615_mutex_release(dev); } -static int get_omac_idx(enum nl80211_iftype type, u32 mask) +static inline int get_free_idx(u32 mask, u8 start, u8 end) +{ + return ffs(~mask & GENMASK(end, start)); +} + +static int get_omac_idx(enum nl80211_iftype type, u64 mask) { int i; switch (type) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: - /* ap use hw bssid 0 and ext bssid */ + case NL80211_IFTYPE_STATION: + /* prefer hw bssid slot 1-3 */ + i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3); + if (i) + return i - 1; + + if (type != NL80211_IFTYPE_STATION) + break; + + /* next, try to find a free repeater entry for the sta */ + i = get_free_idx(mask >> REPEATER_BSSID_START, 0, + REPEATER_BSSID_MAX - REPEATER_BSSID_START); + if (i) + return i + 32 - 1; + + i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); + if (i) + return i - 1; + if (~mask & BIT(HW_BSSID_0)) return HW_BSSID_0; - for (i = EXT_BSSID_1; i < EXT_BSSID_END; i++) - if (~mask & BIT(i)) - return i; - break; - case NL80211_IFTYPE_STATION: - /* sta use hw bssid other than 0 */ - for (i = HW_BSSID_1; i < HW_BSSID_MAX; i++) - if (~mask & BIT(i)) - return i; + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_AP: + /* ap uses hw bssid 0 and ext bssid */ + if (~mask & BIT(HW_BSSID_0)) + return HW_BSSID_0; + + i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); + if (i) + return i - 1; break; default: @@ -187,8 +208,8 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS; dev->mphy.vif_mask |= BIT(mvif->idx); - dev->omac_mask |= BIT(mvif->omac_idx); - phy->omac_mask |= BIT(mvif->omac_idx); + dev->omac_mask |= BIT_ULL(mvif->omac_idx); + phy->omac_mask |= BIT_ULL(mvif->omac_idx); mt7615_mcu_set_dbdc(dev); @@ -211,15 +232,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, if (ret) goto out; - if (dev->pm.enable) { - ret = mt7615_mcu_set_bss_pm(dev, vif, true); - if (ret) - goto out; - - vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; - mt76_set(dev, MT_WF_RFCR(ext_phy), - MT_WF_RFCR_DROP_OTHER_BEACON); - } + mt7615_mac_set_beacon_filter(phy, vif, true); out: mt7615_mutex_release(dev); @@ -245,20 +258,14 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mt7615_free_pending_tx_skbs(dev, msta); - if (dev->pm.enable) { - bool ext_phy = phy != &dev->phy; - - mt7615_mcu_set_bss_pm(dev, vif, false); - mt76_clear(dev, MT_WF_RFCR(ext_phy), - MT_WF_RFCR_DROP_OTHER_BEACON); - } + mt7615_mac_set_beacon_filter(phy, vif, false); mt7615_mcu_add_dev_info(dev, vif, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); dev->mphy.vif_mask &= ~BIT(mvif->idx); - dev->omac_mask &= ~BIT(mvif->omac_idx); - phy->omac_mask &= ~BIT(mvif->omac_idx); + dev->omac_mask &= ~BIT_ULL(mvif->omac_idx); + phy->omac_mask &= ~BIT_ULL(mvif->omac_idx); mt7615_mutex_release(dev); @@ -334,39 +341,6 @@ out: return ret; } -static int -mt7615_queue_key_update(struct mt7615_dev *dev, enum set_key_cmd cmd, - struct mt7615_sta *msta, - struct ieee80211_key_conf *key) -{ - struct mt7615_wtbl_desc *wd; - - wd = kzalloc(sizeof(*wd), GFP_KERNEL); - if (!wd) - return -ENOMEM; - - wd->type = MT7615_WTBL_KEY_DESC; - wd->sta = msta; - - wd->key.key = kmemdup(key->key, key->keylen, GFP_KERNEL); - if (!wd->key.key) { - kfree(wd); - return -ENOMEM; - } - wd->key.cipher = key->cipher; - wd->key.keyidx = key->keyidx; - wd->key.keylen = key->keylen; - wd->key.cmd = cmd; - - spin_lock_bh(&dev->mt76.lock); - list_add_tail(&wd->node, &dev->wd_head); - spin_unlock_bh(&dev->mt76.lock); - - queue_work(dev->mt76.wq, &dev->wtbl_work); - - return 0; -} - static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) @@ -393,8 +367,6 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case WLAN_CIPHER_SUITE_AES_CMAC: key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; break; - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP_256: @@ -402,6 +374,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_SMS4: break; + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: default: return -EOPNOTSUPP; } @@ -420,7 +394,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (mt76_is_mmio(&dev->mt76)) err = mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); else - err = mt7615_queue_key_update(dev, cmd, msta, key); + err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); mt7615_mutex_release(dev); @@ -511,7 +485,6 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, } while (0) phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | - MT_WF_RFCR_DROP_OTHER_BEACON | MT_WF_RFCR_DROP_FRAME_REPORT | MT_WF_RFCR_DROP_PROBEREQ | MT_WF_RFCR_DROP_MCAST_FILTERED | @@ -522,6 +495,9 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, MT_WF_RFCR_DROP_UNWANTED_CTL | MT_WF_RFCR_DROP_STBC_MULTI); + if (phy->n_beacon_vif || !mt7615_firmware_offload(dev)) + phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_BEACON; + MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | MT_WF_RFCR_DROP_A3_MAC | MT_WF_RFCR_DROP_A3_BSSID); @@ -1127,7 +1103,6 @@ static int mt7615_suspend(struct ieee80211_hw *hw, { struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_phy *phy = mt7615_hw_phy(hw); - bool ext_phy = phy != &dev->phy; int err = 0; cancel_delayed_work_sync(&dev->pm.ps_work); @@ -1139,8 +1114,6 @@ static int mt7615_suspend(struct ieee80211_hw *hw, cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->mac_work); - mt76_set(dev, MT_WF_RFCR(ext_phy), MT_WF_RFCR_DROP_OTHER_BEACON); - set_bit(MT76_STATE_SUSPEND, &phy->mt76->state); ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, @@ -1158,7 +1131,7 @@ static int mt7615_resume(struct ieee80211_hw *hw) { struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_phy *phy = mt7615_hw_phy(hw); - bool running, ext_phy = phy != &dev->phy; + bool running; mt7615_mutex_acquire(dev); @@ -1182,7 +1155,6 @@ static int mt7615_resume(struct ieee80211_hw *hw) ieee80211_queue_delayed_work(hw, &phy->mac_work, MT7615_WATCHDOG_TIME); - mt76_clear(dev, MT_WF_RFCR(ext_phy), MT_WF_RFCR_DROP_OTHER_BEACON); mt7615_mutex_release(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 31b40fb83f6c..a44b7766dec6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -94,6 +94,9 @@ void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb, __le32 *txd; u32 val; + /* TODO: make dynamic based on msg type */ + dev->mt76.mcu.timeout = 20 * HZ; + seq = ++dev->mt76.mcu.msg_seq & 0xf; if (!seq) seq = ++dev->mt76.mcu.msg_seq & 0xf; @@ -165,32 +168,22 @@ void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb, } EXPORT_SYMBOL_GPL(mt7615_mcu_fill_msg); -static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, int *wait_seq) +int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd, + struct sk_buff *skb, int seq) { - enum mt76_txq_id qid; - - mt7615_mcu_fill_msg(dev, skb, cmd, wait_seq); - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) - qid = MT_TXQ_MCU; - else - qid = MT_TXQ_FWDL; - - return mt76_tx_queue_skb_raw(dev, qid, skb, 0); -} - -static int -mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd, - struct sk_buff *skb, int seq) -{ - struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data; + struct mt7615_mcu_rxd *rxd; int ret = 0; - if (seq != rxd->seq) { - ret = -EAGAIN; - goto out; + if (!skb) { + dev_err(mdev->dev, "Message %ld (seq %d) timeout\n", + cmd & MCU_CMD_MASK, seq); + return -ETIMEDOUT; } + rxd = (struct mt7615_mcu_rxd *)skb->data; + if (seq != rxd->seq) + return -EAGAIN; + switch (cmd) { case MCU_CMD_PATCH_SEM_CONTROL: skb_pull(skb, sizeof(*rxd) - 4); @@ -228,69 +221,26 @@ mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd, default: break; } -out: - dev_kfree_skb(skb); - - return ret; -} - -int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq) -{ - unsigned long expires = jiffies + 20 * HZ; - struct sk_buff *skb; - int ret = 0; - - while (true) { - skb = mt76_mcu_get_response(&dev->mt76, expires); - if (!skb) { - dev_err(dev->mt76.dev, "Message %ld (seq %d) timeout\n", - cmd & MCU_CMD_MASK, seq); - return -ETIMEDOUT; - } - - ret = mt7615_mcu_parse_response(dev, cmd, skb, seq); - if (ret != -EAGAIN) - break; - } return ret; } -EXPORT_SYMBOL_GPL(mt7615_mcu_wait_response); +EXPORT_SYMBOL_GPL(mt7615_mcu_parse_response); static int mt7615_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, - int cmd, bool wait_resp) + int cmd, int *seq) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - int ret, seq; - - mutex_lock(&mdev->mcu.mutex); - - ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); - if (ret) - goto out; - - if (wait_resp) - ret = mt7615_mcu_wait_response(dev, cmd, seq); - -out: - mutex_unlock(&mdev->mcu.mutex); - - return ret; -} - -int mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, - int len, bool wait_resp) -{ - struct sk_buff *skb; + enum mt76_txq_id qid; - skb = mt76_mcu_msg_alloc(mdev, data, len); - if (!skb) - return -ENOMEM; + mt7615_mcu_fill_msg(dev, skb, cmd, seq); + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) + qid = MT_MCUQ_WM; + else + qid = MT_MCUQ_FWDL; - return __mt76_mcu_skb_send_msg(mdev, skb, cmd, wait_resp); + return mt76_tx_queue_skb_raw(dev, dev->mt76.q_mcu[qid], skb, 0); } -EXPORT_SYMBOL_GPL(mt7615_mcu_msg_send); u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg) { @@ -303,9 +253,9 @@ u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg) .address = cpu_to_le32(reg), }; - return __mt76_mcu_send_msg(&dev->mt76, - MCU_EXT_CMD_RF_REG_ACCESS | MCU_QUERY_PREFIX, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD_RF_REG_ACCESS | MCU_QUERY_PREFIX, + &req, sizeof(req), true); } int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val) @@ -320,8 +270,8 @@ int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val) .data = cpu_to_le32(val), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RF_REG_ACCESS, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RF_REG_ACCESS, &req, + sizeof(req), false); } static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) @@ -645,8 +595,44 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, .mode = cpu_to_le32(mode), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_TARGET_ADDRESS_LEN_REQ, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_TARGET_ADDRESS_LEN_REQ, + &req, sizeof(req), true); +} + +static int +mt7615_mcu_muar_config(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool bssid, bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + u32 idx = mvif->omac_idx - REPEATER_BSSID_START; + u32 mask = dev->omac_mask >> 32 & ~BIT(idx); + const u8 *addr = vif->addr; + struct { + u8 mode; + u8 force_clear; + u8 clear_bitmap[8]; + u8 entry_count; + u8 write; + + u8 index; + u8 bssid; + u8 addr[ETH_ALEN]; + } __packed req = { + .mode = !!mask || enable, + .entry_count = 1, + .write = 1, + + .index = idx * 2 + bssid, + }; + + if (bssid) + addr = vif->bss_conf.bssid; + + if (enable) + ether_addr_copy(req.addr, addr); + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MUAR_UPDATE, &req, + sizeof(req), true); } static int @@ -684,9 +670,12 @@ mt7615_mcu_add_dev(struct mt7615_dev *dev, struct ieee80211_vif *vif, }, }; + if (mvif->omac_idx >= REPEATER_BSSID_START) + return mt7615_mcu_muar_config(dev, vif, false, enable); + 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); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, + &data, sizeof(data), true); } static int @@ -750,8 +739,8 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, } dev_kfree_skb(skb); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, &req, + sizeof(req), true); } static int @@ -781,8 +770,8 @@ mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) .band_idx = band, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, &req, + sizeof(req), true); } static struct sk_buff * @@ -1266,6 +1255,9 @@ mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif, struct mt7615_dev *dev = phy->dev; struct sk_buff *skb; + if (mvif->omac_idx >= REPEATER_BSSID_START) + mt7615_mcu_muar_config(dev, vif, true, enable); + skb = mt7615_mcu_alloc_sta_req(dev, mvif, NULL); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -1275,11 +1267,12 @@ mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif, mt7615_mcu_bss_basic_tlv(skb, vif, sta, enable); - if (enable && mvif->omac_idx > EXT_BSSID_START) + if (enable && mvif->omac_idx >= EXT_BSSID_START && + mvif->omac_idx < REPEATER_BSSID_START) mt7615_mcu_bss_ext_tlv(skb, mvif); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_BSS_INFO_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_BSS_INFO_UPDATE, true); } static int @@ -1299,8 +1292,8 @@ mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev, mt7615_mcu_wtbl_ba_tlv(skb, params, enable, true, NULL, wtbl_hdr); - err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_WTBL_UPDATE, true); + err = mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, + true); if (err < 0) return err; @@ -1310,8 +1303,8 @@ mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev, mt7615_mcu_sta_ba_tlv(skb, params, enable, true); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); } static int @@ -1331,8 +1324,8 @@ mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev, mt7615_mcu_sta_ba_tlv(skb, params, enable, false); - err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + err = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); if (err < 0 || !enable) return err; @@ -1343,8 +1336,8 @@ mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev, mt7615_mcu_wtbl_ba_tlv(skb, params, enable, false, NULL, wtbl_hdr); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_WTBL_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, + true); } static int @@ -1383,7 +1376,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_dev *dev, struct ieee80211_vif *vif, cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE; skb = enable ? wskb : sskb; - err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); + err = mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); if (err < 0) { skb = enable ? sskb : wskb; dev_kfree_skb(skb); @@ -1394,7 +1387,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_dev *dev, struct ieee80211_vif *vif, cmd = enable ? MCU_EXT_CMD_STA_REC_UPDATE : MCU_EXT_CMD_WTBL_UPDATE; skb = enable ? sskb : wskb; - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); } static const struct mt7615_mcu_ops wtbl_update_ops = { @@ -1432,8 +1425,8 @@ mt7615_mcu_sta_ba(struct mt7615_dev *dev, &skb); mt7615_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); } static int @@ -1484,7 +1477,7 @@ mt7615_mcu_add_sta_cmd(struct mt7615_dev *dev, struct ieee80211_vif *vif, mt7615_mcu_wtbl_ht_tlv(skb, sta, sta_wtbl, wtbl_hdr); } - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); } static int @@ -1586,7 +1579,7 @@ mt7615_mcu_uni_add_dev(struct mt7615_dev *dev, data = enable ? (void *)&dev_req : (void *)&basic_req; len = enable ? sizeof(dev_req) : sizeof(basic_req); - err = __mt76_mcu_send_msg(&dev->mt76, cmd, data, len, true); + err = mt76_mcu_send_msg(&dev->mt76, cmd, data, len, true); if (err < 0) return err; @@ -1594,7 +1587,7 @@ mt7615_mcu_uni_add_dev(struct mt7615_dev *dev, data = enable ? (void *)&basic_req : (void *)&dev_req; len = enable ? sizeof(basic_req) : sizeof(dev_req); - return __mt76_mcu_send_msg(&dev->mt76, cmd, data, len, true); + return mt76_mcu_send_msg(&dev->mt76, cmd, data, len, true); } static int @@ -1708,8 +1701,8 @@ mt7615_mcu_uni_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif, basic_req.basic.sta_idx = cpu_to_le16(mvif->sta.wcid.idx); basic_req.basic.conn_state = !enable; - err = __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, - &basic_req, sizeof(basic_req), true); + err = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, + &basic_req, sizeof(basic_req), true); if (err < 0) return err; @@ -1744,8 +1737,8 @@ mt7615_mcu_uni_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif, else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan) rlm_req.rlm.sco = 3; /* SCB */ - return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, - &rlm_req, sizeof(rlm_req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, + &rlm_req, sizeof(rlm_req), true); } static int @@ -1816,8 +1809,8 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, } dev_kfree_skb(skb); - return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, + &req, sizeof(req), true); } static int @@ -1846,8 +1839,8 @@ mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev, mt7615_mcu_wtbl_ba_tlv(skb, params, enable, true, sta_wtbl, wtbl_hdr); - err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_STA_REC_UPDATE, true); + err = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); if (err < 0) return err; @@ -1857,8 +1850,8 @@ mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev, mt7615_mcu_sta_ba_tlv(skb, params, enable, true); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); } static int @@ -1879,8 +1872,8 @@ mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev, mt7615_mcu_sta_ba_tlv(skb, params, enable, false); - err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_STA_REC_UPDATE, true); + err = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); if (err < 0 || !enable) return err; @@ -1898,8 +1891,8 @@ mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev, mt7615_mcu_wtbl_ba_tlv(skb, params, enable, false, sta_wtbl, wtbl_hdr); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); } static int @@ -1922,29 +1915,6 @@ static const struct mt7615_mcu_ops uni_update_ops = { .set_fw_ctrl = mt7615_mcu_fw_pmctrl, }; -static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, - int len) -{ - int ret = 0, cur_len; - - while (len > 0) { - cur_len = min_t(int, 4096 - dev->mt76.mcu_ops->headroom, len); - - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_SCATTER, - data, cur_len, false); - if (ret) - break; - - data += cur_len; - len -= cur_len; - - if (mt76_is_mmio(&dev->mt76)) - mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); - } - - return ret; -} - static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, u32 option) { @@ -1956,14 +1926,13 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, .addr = cpu_to_le32(addr), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_START_REQ, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_START_REQ, &req, + sizeof(req), true); } int mt7615_mcu_restart(struct mt76_dev *dev) { - return __mt76_mcu_send_msg(dev, MCU_CMD_RESTART_DL_REQ, NULL, - 0, true); + return mt76_mcu_send_msg(dev, MCU_CMD_RESTART_DL_REQ, NULL, 0, true); } EXPORT_SYMBOL_GPL(mt7615_mcu_restart); @@ -1975,8 +1944,8 @@ static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_SEM_CONTROL, - &req, sizeof(req), true); + 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) @@ -1988,8 +1957,8 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) .check_crc = 0, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_FINISH_REQ, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_FINISH_REQ, &req, + sizeof(req), true); } static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) @@ -2032,7 +2001,8 @@ static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) goto out; } - ret = mt7615_mcu_send_firmware(dev, fw->data + sizeof(*hdr), len); + ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, + fw->data + sizeof(*hdr), len); if (ret) { dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); goto out; @@ -2092,7 +2062,8 @@ mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev, return err; } - err = mt7615_mcu_send_firmware(dev, data + offset, len); + err = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, + data + offset, len); if (err) { dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); return err; @@ -2285,8 +2256,8 @@ int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl) .ctrl_val = ctrl }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, - &data, sizeof(data), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, &data, + sizeof(data), true); } static int mt7663_load_n9(struct mt7615_dev *dev, const char *name) @@ -2333,7 +2304,8 @@ static int mt7663_load_n9(struct mt7615_dev *dev, const char *name) goto out; } - ret = mt7615_mcu_send_firmware(dev, fw->data + offset, len); + ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, + fw->data + offset, len); if (ret) { dev_err(dev->mt76.dev, "Failed to send firmware\n"); goto out; @@ -2467,7 +2439,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev) static const struct mt76_mcu_ops mt7615_mcu_ops = { .headroom = sizeof(struct mt7615_mcu_txd), .mcu_skb_send_msg = mt7615_mcu_send_message, - .mcu_send_msg = mt7615_mcu_msg_send, + .mcu_parse_response = mt7615_mcu_parse_response, .mcu_restart = mt7615_mcu_restart, }; int ret; @@ -2492,7 +2464,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev) if (ret) return ret; - mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false); dev_dbg(dev->mt76.dev, "Firmware init done\n"); set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); mt7615_mcu_fw_log_2_host(dev, 0); @@ -2547,8 +2519,8 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) skb_put_data(skb, &req_hdr, sizeof(req_hdr)); skb_put_data(skb, eep + offset, eep_len); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_EFUSE_BUFFER_MODE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_EFUSE_BUFFER_MODE, true); } EXPORT_SYMBOL_GPL(mt7615_mcu_set_eeprom); @@ -2563,8 +2535,8 @@ int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable) .band = band, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, - &req, sizeof(req), true); + 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_phy *phy, u32 val) @@ -2583,8 +2555,8 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val) .pkt_thresh = cpu_to_le32(0x2), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, - &req, sizeof(req), true); + 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, @@ -2620,8 +2592,8 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, if (params->cw_max) req.cw_max = cpu_to_le16(fls(params->cw_max)); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, &req, + sizeof(req), true); } int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) @@ -2654,13 +2626,13 @@ int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) } while (0) for (i = 0; i < 4; i++) { - bool band = !!(ext_phy->omac_mask & BIT(i)); + bool band = !!(ext_phy->omac_mask & BIT_ULL(i)); ADD_DBDC_ENTRY(DBDC_TYPE_BSS, i, band); } for (i = 0; i < 14; i++) { - bool band = !!(ext_phy->omac_mask & BIT(0x11 + i)); + bool band = !!(ext_phy->omac_mask & BIT_ULL(0x11 + i)); ADD_DBDC_ENTRY(DBDC_TYPE_MBSS, i, band); } @@ -2679,8 +2651,8 @@ int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 1, 1); out: - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DBDC_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DBDC_CTRL, &req, + sizeof(req), true); } int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) @@ -2689,8 +2661,8 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) .operation = WTBL_RESET_ALL, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &req, + sizeof(req), true); } EXPORT_SYMBOL_GPL(mt7615_mcu_del_wtbl_all); @@ -2711,56 +2683,98 @@ int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, .val = val, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, &req, + sizeof(req), true); } int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val) { struct { - u16 tag; - u16 min_lpn; + __le16 tag; + __le16 min_lpn; } req = { - .tag = 0x1, - .min_lpn = val, + .tag = cpu_to_le16(0x1), + .min_lpn = cpu_to_le16(val), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, + sizeof(req), true); } int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, const struct mt7615_dfs_pulse *pulse) { struct { - u16 tag; - struct mt7615_dfs_pulse pulse; + __le16 tag; + __le32 max_width; /* us */ + __le32 max_pwr; /* dbm */ + __le32 min_pwr; /* dbm */ + __le32 min_stgr_pri; /* us */ + __le32 max_stgr_pri; /* us */ + __le32 min_cr_pri; /* us */ + __le32 max_cr_pri; /* us */ } req = { - .tag = 0x3, + .tag = cpu_to_le16(0x3), +#define __req_field(field) .field = cpu_to_le32(pulse->field) + __req_field(max_width), + __req_field(max_pwr), + __req_field(min_pwr), + __req_field(min_stgr_pri), + __req_field(max_stgr_pri), + __req_field(min_cr_pri), + __req_field(max_cr_pri), +#undef __req_field }; - memcpy(&req.pulse, pulse, sizeof(*pulse)); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, + sizeof(req), true); } int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, const struct mt7615_dfs_pattern *pattern) { struct { - u16 tag; - u16 radar_type; - struct mt7615_dfs_pattern pattern; + __le16 tag; + __le16 radar_type; + u8 enb; + u8 stgr; + u8 min_crpn; + u8 max_crpn; + u8 min_crpr; + u8 min_pw; + u8 max_pw; + __le32 min_pri; + __le32 max_pri; + u8 min_crbn; + u8 max_crbn; + u8 min_stgpn; + u8 max_stgpn; + u8 min_stgpr; } req = { - .tag = 0x2, - .radar_type = index, + .tag = cpu_to_le16(0x2), + .radar_type = cpu_to_le16(index), +#define __req_field_u8(field) .field = pattern->field +#define __req_field_u32(field) .field = cpu_to_le32(pattern->field) + __req_field_u8(enb), + __req_field_u8(stgr), + __req_field_u8(min_crpn), + __req_field_u8(max_crpn), + __req_field_u8(min_crpr), + __req_field_u8(min_pw), + __req_field_u8(max_pw), + __req_field_u32(min_pri), + __req_field_u32(max_pri), + __req_field_u8(min_crbn), + __req_field_u8(max_crbn), + __req_field_u8(min_stgpn), + __req_field_u8(max_stgpn), + __req_field_u8(min_stgpr), +#undef __req_field_u8 +#undef __req_field_u32 }; - memcpy(&req.pattern, pattern, sizeof(*pattern)); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, + sizeof(req), true); } int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) @@ -2769,9 +2783,9 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) u8 pulse_num; u8 rsv[3]; struct { - u32 start_time; - u16 width; - s16 power; + __le32 start_time; + __le16 width; + __le16 power; } pattern[32]; } req = { .pulse_num = dev->radar_pattern.n_pulses, @@ -2784,14 +2798,15 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) /* TODO: add some noise here */ for (i = 0; i < dev->radar_pattern.n_pulses; i++) { - req.pattern[i].width = dev->radar_pattern.width; - req.pattern[i].power = dev->radar_pattern.power; - req.pattern[i].start_time = start_time + - i * dev->radar_pattern.period; + u32 ts = start_time + i * dev->radar_pattern.period; + + req.pattern[i].width = cpu_to_le16(dev->radar_pattern.width); + req.pattern[i].power = cpu_to_le16(dev->radar_pattern.power); + req.pattern[i].start_time = cpu_to_le32(ts); } - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_PATTERN, - &req, sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_PATTERN, + &req, sizeof(req), false); } static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) @@ -2885,7 +2900,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) else mt7615_mcu_set_txpower_sku(phy, req.txpower_sku); - return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) @@ -2897,8 +2912,8 @@ int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) .action = index, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req, + sizeof(req), true); } int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode, @@ -2918,8 +2933,8 @@ int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode, .value = cpu_to_le32(val), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, + sizeof(req), false); } int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) @@ -2936,8 +2951,9 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) .sku_enable = enable, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, + sizeof(req), true); } int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif) @@ -2957,8 +2973,8 @@ int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif) if (vif->type != NL80211_IFTYPE_STATION) return -ENOTSUPP; - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_PS_PROFILE, - &req, sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_PS_PROFILE, &req, + sizeof(req), false); } int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy) @@ -3018,8 +3034,8 @@ int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy) skb_put_data(skb, &channel, sizeof(channel)); } - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_CMD_SET_CHAN_DOMAIN, false); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_CMD_SET_CHAN_DOMAIN, + false); } #define MT7615_SCAN_CHANNEL_TIME 60 @@ -3101,8 +3117,8 @@ int mt7615_mcu_hw_scan(struct mt7615_phy *phy, struct ieee80211_vif *vif, req->scan_func = 1; } - err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_CMD_START_HW_SCAN, - false); + err = mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_CMD_START_HW_SCAN, + false); if (err < 0) clear_bit(MT76_HW_SCANNING, &phy->mt76->state); @@ -3130,8 +3146,8 @@ int mt7615_mcu_cancel_hw_scan(struct mt7615_phy *phy, ieee80211_scan_completed(phy->mt76->hw, &info); } - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_CANCEL_HW_SCAN, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_CANCEL_HW_SCAN, &req, + sizeof(req), false); } int mt7615_mcu_sched_scan_req(struct mt7615_phy *phy, @@ -3202,8 +3218,8 @@ int mt7615_mcu_sched_scan_req(struct mt7615_phy *phy, memcpy(skb_put(skb, sreq->ie_len), sreq->ie, sreq->ie_len); } - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_CMD_SCHED_SCAN_REQ, false); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_CMD_SCHED_SCAN_REQ, + false); } int mt7615_mcu_sched_scan_enable(struct mt7615_phy *phy, @@ -3226,8 +3242,8 @@ int mt7615_mcu_sched_scan_enable(struct mt7615_phy *phy, else clear_bit(MT76_HW_SCHED_SCANNING, &phy->mt76->state); - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SCHED_SCAN_ENABLE, - &req, sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SCHED_SCAN_ENABLE, &req, + sizeof(req), false); } static int mt7615_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur) @@ -3366,8 +3382,8 @@ again: out: req.center_freq = cpu_to_le16(center_freq); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RXDCOC_CAL, &req, - sizeof(req), true); + ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RXDCOC_CAL, &req, + sizeof(req), true); if ((chandef->width == NL80211_CHAN_WIDTH_80P80 || chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) { @@ -3487,8 +3503,8 @@ again: out: req.center_freq = cpu_to_le16(center_freq); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXDPD_CAL, &req, - sizeof(req), true); + ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXDPD_CAL, &req, + sizeof(req), true); if ((chandef->width == NL80211_CHAN_WIDTH_80P80 || chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) { @@ -3528,17 +3544,16 @@ int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif, }; int err; - if (vif->type != NL80211_IFTYPE_STATION || - !mt7615_firmware_offload(dev)) - return -ENOTSUPP; + if (vif->type != NL80211_IFTYPE_STATION) + return 0; - err = __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_ABORT, - &req_hdr, sizeof(req_hdr), false); + err = mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_ABORT, &req_hdr, + sizeof(req_hdr), false); if (err < 0 || !enable) return err; - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_CONNECTED, - &req, sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_CONNECTED, &req, + sizeof(req), false); } #ifdef CONFIG_PM @@ -3569,9 +3584,11 @@ int mt7615_mcu_set_hif_suspend(struct mt7615_dev *dev, bool suspend) req.hdr.hif_type = 2; else if (mt76_is_usb(&dev->mt76)) req.hdr.hif_type = 1; + else if (mt76_is_sdio(&dev->mt76)) + req.hdr.hif_type = 0; - return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_HIF_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_HIF_CTRL, &req, + sizeof(req), true); } EXPORT_SYMBOL_GPL(mt7615_mcu_set_hif_suspend); @@ -3587,6 +3604,7 @@ mt7615_mcu_set_wow_ctrl(struct mt7615_phy *phy, struct ieee80211_vif *vif, u8 pad[3]; } __packed hdr; struct mt7615_wow_ctrl_tlv wow_ctrl_tlv; + struct mt7615_wow_gpio_param_tlv gpio_tlv; } req = { .hdr = { .bss_idx = mvif->idx, @@ -3596,6 +3614,11 @@ mt7615_mcu_set_wow_ctrl(struct mt7615_phy *phy, struct ieee80211_vif *vif, .len = cpu_to_le16(sizeof(struct mt7615_wow_ctrl_tlv)), .cmd = suspend ? 1 : 2, }, + .gpio_tlv = { + .tag = cpu_to_le16(UNI_SUSPEND_WOW_GPIO_PARAM), + .len = cpu_to_le16(sizeof(struct mt7615_wow_gpio_param_tlv)), + .gpio_pin = 0xff, /* follow fw about GPIO pin */ + }, }; if (wowlan->magic_pkt) @@ -3609,12 +3632,14 @@ mt7615_mcu_set_wow_ctrl(struct mt7615_phy *phy, struct ieee80211_vif *vif, } if (mt76_is_mmio(&dev->mt76)) - req.wow_ctrl_tlv.wakeup_hif = 2; + req.wow_ctrl_tlv.wakeup_hif = WOW_PCIE; else if (mt76_is_usb(&dev->mt76)) - req.wow_ctrl_tlv.wakeup_hif = 1; + req.wow_ctrl_tlv.wakeup_hif = WOW_USB; + else if (mt76_is_sdio(&dev->mt76)) + req.wow_ctrl_tlv.wakeup_hif = WOW_GPIO; - return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_SUSPEND, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_SUSPEND, &req, + sizeof(req), true); } static int @@ -3649,8 +3674,8 @@ mt7615_mcu_set_wow_pattern(struct mt7615_dev *dev, memcpy(ptlv->pattern, pattern->pattern, pattern->pattern_len); memcpy(ptlv->mask, pattern->mask, pattern->pattern_len / 8); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_SUSPEND, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_SUSPEND, + true); } static int @@ -3678,8 +3703,8 @@ mt7615_mcu_set_suspend_mode(struct mt7615_dev *dev, }, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_SUSPEND, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_SUSPEND, &req, + sizeof(req), true); } static int @@ -3705,8 +3730,8 @@ mt7615_mcu_set_gtk_rekey(struct mt7615_dev *dev, }, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_OFFLOAD, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_OFFLOAD, &req, + sizeof(req), true); } static int @@ -3731,8 +3756,8 @@ mt7615_mcu_set_arp_filter(struct mt7615_dev *dev, struct ieee80211_vif *vif, }, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_OFFLOAD, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_OFFLOAD, &req, + sizeof(req), true); } void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac, @@ -3744,8 +3769,6 @@ void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac, struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; int i; - mt7615_mcu_set_bss_pm(phy->dev, vif, suspend); - mt7615_mcu_set_gtk_rekey(phy->dev, vif, suspend); mt7615_mcu_set_arp_filter(phy->dev, vif, suspend); @@ -3822,8 +3845,8 @@ int mt7615_mcu_update_gtk_rekey(struct ieee80211_hw *hw, memcpy(gtk_tlv->kck, key->kck, NL80211_KCK_LEN); memcpy(gtk_tlv->replay_ctr, key->replay_ctr, NL80211_REPLAY_CTR_LEN); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_OFFLOAD, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD, + true); } #endif /* CONFIG_PM */ @@ -3843,8 +3866,8 @@ int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, phy->roc_grant = false; - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req, + sizeof(req), false); } int mt7615_mcu_update_arp_filter(struct ieee80211_hw *hw, @@ -3890,8 +3913,8 @@ int mt7615_mcu_update_arp_filter(struct ieee80211_hw *hw, memcpy(addr, &info->arp_addr_list[i], sizeof(__be32)); } - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_UNI_CMD_OFFLOAD, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD, + true); } int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, @@ -3912,8 +3935,8 @@ int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, if (!mt7615_firmware_offload(dev)) return -ENOTSUPP; - return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_P2P_OPPPS, - &req, sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_P2P_OPPPS, &req, + sizeof(req), false); } u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset) @@ -3925,8 +3948,8 @@ u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset) .addr = cpu_to_le32(offset), }; - return __mt76_mcu_send_msg(dev, MCU_CMD_REG_READ, - &req, sizeof(req), true); + return mt76_mcu_send_msg(dev, MCU_CMD_REG_READ, &req, sizeof(req), + true); } EXPORT_SYMBOL_GPL(mt7615_mcu_reg_rr); @@ -3940,7 +3963,6 @@ void mt7615_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val) .val = cpu_to_le32(val), }; - __mt76_mcu_send_msg(dev, MCU_CMD_REG_WRITE, - &req, sizeof(req), false); + mt76_mcu_send_msg(dev, MCU_CMD_REG_WRITE, &req, sizeof(req), false); } EXPORT_SYMBOL_GPL(mt7615_mcu_reg_wr); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 7b856e9eee1e..6ef5670211d1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -275,6 +275,7 @@ enum { MCU_EXT_CMD_PROTECT_CTRL = 0x3e, MCU_EXT_CMD_DBDC_CTRL = 0x45, MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, + MCU_EXT_CMD_MUAR_UPDATE = 0x48, MCU_EXT_CMD_BCN_OFFLOAD = 0x49, MCU_EXT_CMD_SET_RX_PATH = 0x4e, MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, @@ -477,6 +478,12 @@ struct mt7615_bss_qos_tlv { u8 pad[3]; } __packed; +enum { + WOW_USB = 1, + WOW_PCIE = 2, + WOW_GPIO = 3, +}; + struct mt7615_wow_ctrl_tlv { __le16 tag; __le16 len; @@ -501,6 +508,16 @@ struct mt7615_wow_ctrl_tlv { u8 rsv[4]; } __packed; +struct mt7615_wow_gpio_param_tlv { + __le16 tag; + __le16 len; + u8 gpio_pin; + u8 trigger_lvl; + u8 pad[2]; + __le32 gpio_interval; + u8 rsv[4]; +} __packed; + #define MT7615_WOW_MASK_MAX_LEN 16 #define MT7615_WOW_PATTEN_MAX_LEN 128 struct mt7615_wow_pattern_tlv { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index 6de492a4cf02..a7f92fa0488f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -98,9 +98,9 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) return IRQ_HANDLED; } -static void mt7615_irq_tasklet(unsigned long data) +static void mt7615_irq_tasklet(struct tasklet_struct *t) { - struct mt7615_dev *dev = (struct mt7615_dev *)data; + struct mt7615_dev *dev = from_tasklet(dev, t, irq_tasklet); u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev); mt76_wr(dev, MT_INT_MASK_CSR, 0); @@ -203,7 +203,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, dev = container_of(mdev, struct mt7615_dev, mt76); mt76_mmio_init(&dev->mt76, mem_base); - tasklet_init(&dev->irq_tasklet, mt7615_irq_tasklet, (unsigned long)dev); + tasklet_setup(&dev->irq_tasklet, mt7615_irq_tasklet); dev->reg_map = map; dev->ops = ops; @@ -240,7 +240,8 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, return 0; error: - ieee80211_free_hw(mt76_hw(dev)); + mt76_free_device(&dev->mt76); + return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 6a9f9187f76a..99b8abdbb08f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -11,7 +11,7 @@ #include "../mt76.h" #include "regs.h" -#define MT7615_MAX_INTERFACES 4 +#define MT7615_MAX_INTERFACES 16 #define MT7615_MAX_WMM_SETS 4 #define MT7663_WTBL_SIZE 32 #define MT7615_WTBL_SIZE 128 @@ -106,29 +106,11 @@ struct mt7615_rate_desc { u8 bw; }; -enum mt7615_wtbl_desc_type { - MT7615_WTBL_RATE_DESC, - MT7615_WTBL_KEY_DESC -}; - -struct mt7615_key_desc { - enum set_key_cmd cmd; - u32 cipher; - s8 keyidx; - u8 keylen; - u8 *key; -}; - -struct mt7615_wtbl_desc { +struct mt7615_wtbl_rate_desc { struct list_head node; - enum mt7615_wtbl_desc_type type; + struct mt7615_rate_desc rate; struct mt7615_sta *sta; - - union { - struct mt7615_rate_desc rate; - struct mt7615_key_desc key; - }; }; struct mt7615_sta { @@ -175,8 +157,10 @@ struct mt7615_phy { struct ieee80211_vif *monitor_vif; + u8 n_beacon_vif; + u32 rxfilter; - u32 omac_mask; + u64 omac_mask; u16 noise; @@ -254,7 +238,7 @@ struct mt7615_dev { struct tasklet_struct irq_tasklet; struct mt7615_phy phy; - u32 omac_mask; + u64 omac_mask; u16 chainmask; @@ -289,20 +273,22 @@ struct mt7615_dev { u8 fw_ver; - struct work_struct wtbl_work; - struct list_head wd_head; + struct work_struct rate_work; + struct list_head wrd_head; u32 debugfs_rf_wf; u32 debugfs_rf_reg; + u32 muar_mask; + #ifdef CONFIG_NL80211_TESTMODE struct { u32 *reg_backup; s16 last_freq_offset; u8 last_rcpi[4]; - s8 last_ib_rssi; - s8 last_wb_rssi; + s8 last_ib_rssi[4]; + s8 last_wb_rssi[4]; } test; #endif @@ -344,24 +330,13 @@ enum { HW_BSSID_1, HW_BSSID_2, HW_BSSID_3, - HW_BSSID_MAX, + HW_BSSID_MAX = HW_BSSID_3, EXT_BSSID_START = 0x10, EXT_BSSID_1, - EXT_BSSID_2, - EXT_BSSID_3, - EXT_BSSID_4, - EXT_BSSID_5, - EXT_BSSID_6, - EXT_BSSID_7, - EXT_BSSID_8, - EXT_BSSID_9, - EXT_BSSID_10, - EXT_BSSID_11, - EXT_BSSID_12, - EXT_BSSID_13, - EXT_BSSID_14, - EXT_BSSID_15, - EXT_BSSID_END + EXT_BSSID_15 = 0x1f, + EXT_BSSID_MAX = EXT_BSSID_15, + REPEATER_BSSID_START = 0x20, + REPEATER_BSSID_MAX = 0x3f, }; enum { @@ -452,7 +427,6 @@ bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev); void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates); -int mt7615_pm_set_enable(struct mt7615_dev *dev, bool enable); void mt7615_pm_wake_work(struct work_struct *work); int mt7615_pm_wake(struct mt7615_dev *dev); void mt7615_pm_power_save_sched(struct mt7615_dev *dev); @@ -542,7 +516,7 @@ static inline u8 mt7615_lmac_mapping(struct mt7615_dev *dev, u8 ac) static inline u32 mt7615_tx_mcu_int_mask(struct mt7615_dev *dev) { - return MT_INT_TX_DONE(dev->mt76.q_tx[MT_TXQ_MCU]->hw_idx); + return MT_INT_TX_DONE(dev->mt76.q_mcu[MT_MCUQ_WM]->hw_idx); } void mt7615_dma_reset(struct mt7615_dev *dev); @@ -568,28 +542,18 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct ieee80211_sta *sta, int pid, struct ieee80211_key_conf *key, bool beacon); void mt7615_mac_set_timing(struct mt7615_phy *phy); +int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, + struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd); int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, enum set_key_cmd cmd); -int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, - struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, - int keyidx, enum set_key_cmd cmd); -void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, - struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, - enum set_key_cmd cmd); -int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, - struct mt76_wcid *wcid, - u8 *key, u8 keylen, - enum mt7615_cipher_type cipher, - enum set_key_cmd cmd); void mt7615_mac_reset_work(struct work_struct *work); u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid); -int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq); -int mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, - int len, bool wait_resp); +int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd, + struct sk_buff *skb, int seq); u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg); int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val); int mt7615_mcu_set_dbdc(struct mt7615_dev *dev); @@ -651,6 +615,9 @@ int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, int mt7615_init_debugfs(struct mt7615_dev *dev); int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq); +int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy, + struct ieee80211_vif *vif, + bool enable); int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7615_mcu_set_hif_suspend(struct mt7615_dev *dev, bool suspend); @@ -674,14 +641,13 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, bool mt7663_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update); void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); -void mt7663_usb_sdio_wtbl_work(struct work_struct *work); int mt7663_usb_sdio_register_device(struct mt7615_dev *dev); int mt7663u_mcu_init(struct mt7615_dev *dev); /* sdio */ u32 mt7663s_read_pcr(struct mt7615_dev *dev); int mt7663s_mcu_init(struct mt7615_dev *dev); -void mt7663s_tx_work(struct work_struct *work); +void mt7663s_txrx_worker(struct mt76_worker *w); void mt7663s_rx_work(struct work_struct *work); void mt7663s_sdio_irq(struct sdio_func *func); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c index 06a0f8f7bc89..27fcb1374685 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c @@ -16,8 +16,15 @@ static void mt7615_init_work(struct work_struct *work) { struct mt7615_dev *dev = container_of(work, struct mt7615_dev, mcu_work); + int i, ret; - if (mt7615_mcu_init(dev)) + ret = mt7615_mcu_init(dev); + for (i = 0; (ret == -EAGAIN) && (i < 10); i++) { + msleep(200); + ret = mt7615_mcu_init(dev); + } + + if (ret) return; mt7615_mcu_set_eeprom(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 61623f480806..6e5db015b32c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -333,6 +333,9 @@ enum mt7615_reg_base { #define MT_WF_RFCR_DROP_NDPA BIT(20) #define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) +#define MT_WF_RMAC_MORE(_band) MT_WF_RMAC((_band) ? 0x124 : 0x024) +#define MT_WF_RMAC_MORE_MUAR_MODE GENMASK(31, 30) + #define MT_WF_RFCR1(_band) MT_WF_RMAC((_band) ? 0x104 : 0x004) #define MT_WF_RFCR1_DROP_ACK BIT(4) #define MT_WF_RFCR1_DROP_BF_POLL BIT(5) @@ -342,6 +345,14 @@ enum mt7615_reg_base { #define MT_CHFREQ(_band) MT_WF_RMAC((_band) ? 0x130 : 0x030) +#define MT_WF_RMAC_MAR0 MT_WF_RMAC(0x025c) +#define MT_WF_RMAC_MAR1 MT_WF_RMAC(0x0260) +#define MT_WF_RMAC_MAR1_ADDR GENMASK(15, 0) +#define MT_WF_RMAC_MAR1_START BIT(16) +#define MT_WF_RMAC_MAR1_WRITE BIT(17) +#define MT_WF_RMAC_MAR1_IDX GENMASK(29, 24) +#define MT_WF_RMAC_MAR1_GROUP GENMASK(31, 30) + #define MT_WF_RMAC_MIB_TIME0 MT_WF_RMAC(0x03c4) #define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) #define MT_WF_RMAC_MIB_RXTIME_EN BIT(30) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c index 874c929d8552..347975eaba86 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c @@ -294,30 +294,6 @@ release: return ret; } -static int mt7663s_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - struct mt76_sdio *sdio = &mdev->sdio; - u32 pse, ple; - int err; - - err = mt7615_mac_sta_add(mdev, vif, sta); - if (err < 0) - return err; - - /* init sched data quota */ - pse = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); - ple = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); - - mutex_lock(&sdio->sched.lock); - sdio->sched.pse_data_quota = pse; - sdio->sched.ple_data_quota = ple; - mutex_unlock(&sdio->sched.lock); - - return 0; -} - static int mt7663s_probe(struct sdio_func *func, const struct sdio_device_id *id) { @@ -329,7 +305,7 @@ static int mt7663s_probe(struct sdio_func *func, .tx_status_data = mt7663_usb_sdio_tx_status_data, .rx_skb = mt7615_queue_rx_skb, .sta_ps = mt7615_sta_ps, - .sta_add = mt7663s_sta_add, + .sta_add = mt7615_mac_sta_add, .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, }; @@ -366,14 +342,11 @@ static int mt7663s_probe(struct sdio_func *func, ret = mt76s_init(mdev, func, &mt7663s_ops); if (ret < 0) - goto err_free; - - INIT_WORK(&mdev->sdio.tx.xmit_work, mt7663s_tx_work); - INIT_WORK(&mdev->sdio.rx.recv_work, mt7663s_rx_work); + goto error; ret = mt7663s_hw_init(dev, func); if (ret) - goto err_deinit; + goto error; mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | (mt76_rr(dev, MT_HW_REV) & 0xff); @@ -384,7 +357,7 @@ static int mt7663s_probe(struct sdio_func *func, GFP_KERNEL); if (!mdev->sdio.intr_data) { ret = -ENOMEM; - goto err_deinit; + goto error; } for (i = 0; i < ARRAY_SIZE(mdev->sdio.xmit_buf); i++) { @@ -393,23 +366,29 @@ static int mt7663s_probe(struct sdio_func *func, GFP_KERNEL); if (!mdev->sdio.xmit_buf[i]) { ret = -ENOMEM; - goto err_deinit; + goto error; } } ret = mt76s_alloc_queues(&dev->mt76); if (ret) - goto err_deinit; + goto error; + + ret = mt76_worker_setup(mt76_hw(dev), &mdev->sdio.txrx_worker, + mt7663s_txrx_worker, "sdio-txrx"); + if (ret) + goto error; + + sched_set_fifo_low(mdev->sdio.txrx_worker.task); ret = mt7663_usb_sdio_register_device(dev); if (ret) - goto err_deinit; + goto error; return 0; -err_deinit: +error: mt76s_deinit(&dev->mt76); -err_free: mt76_free_device(&dev->mt76); return ret; @@ -432,6 +411,7 @@ static int mt7663s_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct mt7615_dev *mdev = sdio_get_drvdata(func); + int err; if (!test_bit(MT76_STATE_SUSPEND, &mdev->mphy.state) && mt7615_firmware_offload(mdev)) { @@ -444,9 +424,20 @@ static int mt7663s_suspend(struct device *dev) sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); - mt76s_stop_txrx(&mdev->mt76); + err = mt7615_mcu_set_fw_ctrl(mdev); + if (err) + return err; - return mt7615_mcu_set_fw_ctrl(mdev); + mt76_worker_disable(&mdev->mt76.sdio.txrx_worker); + mt76_worker_disable(&mdev->mt76.sdio.status_worker); + mt76_worker_disable(&mdev->mt76.sdio.net_worker); + + cancel_work_sync(&mdev->mt76.sdio.stat_work); + clear_bit(MT76_READING_STATS, &mdev->mphy.state); + + mt76_tx_status_check(&mdev->mt76, NULL, true); + + return 0; } static int mt7663s_resume(struct device *dev) @@ -455,6 +446,10 @@ static int mt7663s_resume(struct device *dev) struct mt7615_dev *mdev = sdio_get_drvdata(func); int err; + mt76_worker_enable(&mdev->mt76.sdio.txrx_worker); + mt76_worker_enable(&mdev->mt76.sdio.status_worker); + mt76_worker_enable(&mdev->mt76.sdio.net_worker); + err = mt7615_mcu_set_drv_ctrl(mdev); if (err) return err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c index 38670c00380c..17fe4187d1de 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c @@ -19,46 +19,34 @@ static int mt7663s_mcu_init_sched(struct mt7615_dev *dev) { struct mt76_sdio *sdio = &dev->mt76.sdio; - u32 pse0, ple, pse1, txdwcnt; - - pse0 = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); - pse1 = mt76_get_field(dev, MT_PSE_PG_HIF1_GROUP, MT_HIF1_MIN_QUOTA); - ple = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); + u32 txdwcnt; + + sdio->sched.pse_data_quota = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP, + MT_HIF0_MIN_QUOTA); + sdio->sched.pse_mcu_quota = mt76_get_field(dev, MT_PSE_PG_HIF1_GROUP, + MT_HIF1_MIN_QUOTA); + sdio->sched.ple_data_quota = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP, + MT_HIF0_MIN_QUOTA); txdwcnt = mt76_get_field(dev, MT_PP_TXDWCNT, MT_PP_TXDWCNT_TX1_ADD_DW_CNT); - - mutex_lock(&sdio->sched.lock); - - sdio->sched.pse_data_quota = pse0; - sdio->sched.ple_data_quota = ple; - sdio->sched.pse_mcu_quota = pse1; sdio->sched.deficit = txdwcnt << 2; - mutex_unlock(&sdio->sched.lock); - return 0; } static int mt7663s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, - int cmd, bool wait_resp) + int cmd, int *seq) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - int ret, seq; - - mutex_lock(&mdev->mcu.mutex); + int ret; - mt7615_mcu_fill_msg(dev, skb, cmd, &seq); - ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0); + mt7615_mcu_fill_msg(dev, skb, cmd, seq); + ret = mt76_tx_queue_skb_raw(dev, mdev->q_mcu[MT_MCUQ_WM], skb, 0); if (ret) - goto out; - - mt76_queue_kick(dev, mdev->q_tx[MT_TXQ_MCU]); - if (wait_resp) - ret = mt7615_mcu_wait_response(dev, cmd, seq); + return ret; -out: - mutex_unlock(&mdev->mcu.mutex); + mt76_queue_kick(dev, mdev->q_mcu[MT_MCUQ_WM]); return ret; } @@ -127,7 +115,7 @@ int mt7663s_mcu_init(struct mt7615_dev *dev) .headroom = sizeof(struct mt7615_mcu_txd), .tailroom = MT_USB_TAIL_SIZE, .mcu_skb_send_msg = mt7663s_mcu_send_message, - .mcu_send_msg = mt7615_mcu_msg_send, + .mcu_parse_response = mt7615_mcu_parse_response, .mcu_restart = mt7615_mcu_restart, .mcu_rr = mt7615_mcu_reg_rr, .mcu_wr = mt7615_mcu_reg_wr, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c index 2486cda3243b..13d77f8fca86 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c @@ -46,11 +46,9 @@ static int mt7663s_refill_sched_quota(struct mt76_dev *dev, u32 *data) if (!pse_data_quota && !ple_data_quota && !pse_mcu_quota) return 0; - mutex_lock(&sdio->sched.lock); sdio->sched.pse_mcu_quota += pse_mcu_quota; sdio->sched.pse_data_quota += pse_data_quota; sdio->sched.ple_data_quota += ple_data_quota; - mutex_unlock(&sdio->sched.lock); return pse_data_quota + ple_data_quota + pse_mcu_quota; } @@ -105,10 +103,7 @@ static int mt7663s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid, buf = page_address(page); - sdio_claim_host(sdio->func); err = sdio_readsb(sdio->func, buf, MCR_WRDR(qid), len); - sdio_release_host(sdio->func); - if (err < 0) { dev_err(dev->dev, "sdio read data failed:%d\n", err); __free_pages(page, order); @@ -138,19 +133,52 @@ static int mt7663s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid, return i; } -static int mt7663s_tx_pick_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid, - int buf_sz, int *pse_size, int *ple_size) +static int mt7663s_rx_handler(struct mt76_dev *dev) +{ + struct mt76_sdio *sdio = &dev->sdio; + struct mt76s_intr *intr = sdio->intr_data; + int nframes = 0, ret; + + ret = sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(*intr)); + if (ret < 0) + return ret; + + trace_dev_irq(dev, intr->isr, 0); + + if (intr->isr & WHIER_RX0_DONE_INT_EN) { + ret = mt7663s_rx_run_queue(dev, 0, intr); + if (ret > 0) { + mt76_worker_schedule(&sdio->net_worker); + nframes += ret; + } + } + + if (intr->isr & WHIER_RX1_DONE_INT_EN) { + ret = mt7663s_rx_run_queue(dev, 1, intr); + if (ret > 0) { + mt76_worker_schedule(&sdio->net_worker); + nframes += ret; + } + } + + nframes += !!mt7663s_refill_sched_quota(dev, intr->tx.wtqcr); + + return nframes; +} + +static int mt7663s_tx_pick_quota(struct mt76_sdio *sdio, bool mcu, int buf_sz, + int *pse_size, int *ple_size) { int pse_sz; pse_sz = DIV_ROUND_UP(buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ); - if (qid == MT_TXQ_MCU) { + if (mcu) { if (sdio->sched.pse_mcu_quota < *pse_size + pse_sz) return -EBUSY; } else { if (sdio->sched.pse_data_quota < *pse_size + pse_sz || - sdio->sched.ple_data_quota < *ple_size) + sdio->sched.ple_data_quota < *ple_size + 1) return -EBUSY; *ple_size = *ple_size + 1; @@ -160,17 +188,15 @@ static int mt7663s_tx_pick_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid, return 0; } -static void mt7663s_tx_update_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid, +static void mt7663s_tx_update_quota(struct mt76_sdio *sdio, bool mcu, int pse_size, int ple_size) { - mutex_lock(&sdio->sched.lock); - if (qid == MT_TXQ_MCU) { + if (mcu) { sdio->sched.pse_mcu_quota -= pse_size; } else { sdio->sched.pse_data_quota -= pse_size; sdio->sched.ple_data_quota -= ple_size; } - mutex_unlock(&sdio->sched.lock); } static int __mt7663s_xmit_queue(struct mt76_dev *dev, u8 *data, int len) @@ -181,22 +207,20 @@ static int __mt7663s_xmit_queue(struct mt76_dev *dev, u8 *data, int len) if (len > sdio->func->cur_blksize) len = roundup(len, sdio->func->cur_blksize); - sdio_claim_host(sdio->func); err = sdio_writesb(sdio->func, MCR_WTDR1, data, len); - sdio_release_host(sdio->func); - if (err) dev_err(dev->dev, "sdio write failed: %d\n", err); return err; } -static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid) +static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) { - int err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0; - struct mt76_queue *q = dev->q_tx[qid]; + int qid, err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0; + bool mcu = q == dev->q_mcu[MT_MCUQ_WM]; struct mt76_sdio *sdio = &dev->sdio; + qid = mcu ? ARRAY_SIZE(sdio->xmit_buf) - 1 : q->qid; while (q->first != q->head) { struct mt76_queue_entry *e = &q->entry[q->first]; struct sk_buff *iter; @@ -214,7 +238,7 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid) if (len + e->skb->len + 4 > MT76S_XMIT_BUF_SZ) break; - if (mt7663s_tx_pick_quota(sdio, qid, e->buf_sz, &pse_sz, + if (mt7663s_tx_pick_quota(sdio, mcu, e->buf_sz, &pse_sz, &ple_sz)) break; @@ -240,78 +264,44 @@ next: if (err) return err; } - mt7663s_tx_update_quota(sdio, qid, pse_sz, ple_sz); + mt7663s_tx_update_quota(sdio, mcu, pse_sz, ple_sz); - return nframes; -} - -void mt7663s_tx_work(struct work_struct *work) -{ - struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, - tx.xmit_work); - struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); - int i, nframes = 0; + mt76_worker_schedule(&sdio->status_worker); - for (i = 0; i < MT_TXQ_MCU_WA; i++) { - int ret; - - ret = mt7663s_tx_run_queue(dev, i); - if (ret < 0) - break; - - nframes += ret; - } - if (nframes) - queue_work(sdio->txrx_wq, &sdio->tx.xmit_work); - - queue_work(sdio->txrx_wq, &sdio->tx.status_work); + return nframes; } -void mt7663s_rx_work(struct work_struct *work) +void mt7663s_txrx_worker(struct mt76_worker *w) { - struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, - rx.recv_work); + struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, + txrx_worker); struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); - struct mt76s_intr *intr = sdio->intr_data; - int nframes = 0, ret; + int i, nframes, ret; /* disable interrupt */ sdio_claim_host(sdio->func); sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL); - ret = sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(*intr)); - sdio_release_host(sdio->func); - - if (ret < 0) - goto out; - trace_dev_irq(dev, intr->isr, 0); + do { + nframes = 0; - if (intr->isr & WHIER_RX0_DONE_INT_EN) { - ret = mt7663s_rx_run_queue(dev, 0, intr); - if (ret > 0) { - queue_work(sdio->txrx_wq, &sdio->rx.net_work); - nframes += ret; + /* tx */ + for (i = 0; i <= MT_TXQ_PSD; i++) { + ret = mt7663s_tx_run_queue(dev, dev->phy.q_tx[i]); + if (ret > 0) + nframes += ret; } - } - - if (intr->isr & WHIER_RX1_DONE_INT_EN) { - ret = mt7663s_rx_run_queue(dev, 1, intr); - if (ret > 0) { - queue_work(sdio->txrx_wq, &sdio->rx.net_work); + ret = mt7663s_tx_run_queue(dev, dev->q_mcu[MT_MCUQ_WM]); + if (ret > 0) nframes += ret; - } - } - if (mt7663s_refill_sched_quota(dev, intr->tx.wtqcr)) - queue_work(sdio->txrx_wq, &sdio->tx.xmit_work); + /* rx */ + ret = mt7663s_rx_handler(dev); + if (ret > 0) + nframes += ret; + } while (nframes > 0); - if (nframes) { - queue_work(sdio->txrx_wq, &sdio->rx.recv_work); - return; - } -out: /* enable interrupt */ - sdio_claim_host(sdio->func); sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL); sdio_release_host(sdio->func); } @@ -324,5 +314,5 @@ void mt7663s_sdio_irq(struct sdio_func *func) if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.phy.state)) return; - queue_work(sdio->txrx_wq, &sdio->rx.recv_work); + mt76_worker_schedule(&sdio->txrx_worker); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c index e4dc62314bae..8fc97a52411a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c @@ -90,8 +90,8 @@ mt7615_tm_set_tx_power(struct mt7615_phy *phy) data[ret - MT_EE_NIC_CONF_0] = tx_power[i]; } - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_SET_TX_POWER_CTRL, false); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_SET_TX_POWER_CTRL, false); } static void @@ -335,9 +335,7 @@ mt7615_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg) if (!rx) return -ENOMEM; - if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, dev->test.last_freq_offset) || - nla_put_s32(msg, MT76_TM_RX_ATTR_IB_RSSI, dev->test.last_ib_rssi) || - nla_put_s32(msg, MT76_TM_RX_ATTR_WB_RSSI, dev->test.last_wb_rssi)) + if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, dev->test.last_freq_offset)) return -ENOMEM; rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RCPI); @@ -350,6 +348,26 @@ mt7615_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg) nla_nest_end(msg, rssi); + rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_IB_RSSI); + if (!rssi) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(dev->test.last_ib_rssi); i++) + if (nla_put_s8(msg, i, dev->test.last_ib_rssi[i])) + return -ENOMEM; + + nla_nest_end(msg, rssi); + + rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_WB_RSSI); + if (!rssi) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(dev->test.last_wb_rssi); i++) + if (nla_put_s8(msg, i, dev->test.last_wb_rssi[i])) + return -ENOMEM; + + nla_nest_end(msg, rssi); + nla_nest_end(msg, rx); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index f0ad83af9e00..a60cfa345521 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -126,21 +126,20 @@ static int mt7663u_probe(struct usb_interface *usb_intf, alloc_queues: ret = mt76u_alloc_mcu_queue(&dev->mt76); if (ret) - goto error_free_q; + goto error; ret = mt76u_alloc_queues(&dev->mt76); if (ret) - goto error_free_q; + goto error; ret = mt7663_usb_sdio_register_device(dev); if (ret) - goto error_free_q; + goto error; return 0; -error_free_q: - mt76u_queues_deinit(&dev->mt76); error: + mt76u_queues_deinit(&dev->mt76); usb_set_intfdata(usb_intf, NULL); usb_put_dev(interface_to_usbdev(usb_intf)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c index 4d8be366af31..c55698f9c49a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c @@ -15,14 +15,12 @@ static int mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, - int cmd, bool wait_resp) + int cmd, int *seq) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - int ret, seq, ep, len, pad; + int ret, ep, len, pad; - mutex_lock(&mdev->mcu.mutex); - - mt7615_mcu_fill_msg(dev, skb, cmd, &seq); + mt7615_mcu_fill_msg(dev, skb, cmd, seq); if (cmd != MCU_CMD_FW_SCATTER) ep = MT_EP_OUT_INBAND_CMD; else @@ -37,14 +35,8 @@ mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL, 1000, ep); - if (ret < 0) - goto out; - - if (wait_resp) - ret = mt7615_mcu_wait_response(dev, cmd, seq); out: - mutex_unlock(&mdev->mcu.mutex); dev_kfree_skb(skb); return ret; @@ -56,7 +48,7 @@ int mt7663u_mcu_init(struct mt7615_dev *dev) .headroom = MT_USB_HDR_SIZE + sizeof(struct mt7615_mcu_txd), .tailroom = MT_USB_TAIL_SIZE, .mcu_skb_send_msg = mt7663u_mcu_send_message, - .mcu_send_msg = mt7615_mcu_msg_send, + .mcu_parse_response = mt7615_mcu_parse_response, .mcu_restart = mt7615_mcu_restart, }; int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c index 3b29a6d3dc64..203256862dfd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c @@ -61,12 +61,11 @@ mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid, skb_push(skb, MT_USB_TXD_SIZE); } -static int -mt7663_usb_sdio_set_rates(struct mt7615_dev *dev, - struct mt7615_wtbl_desc *wd) +static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev, + struct mt7615_wtbl_rate_desc *wrd) { - struct mt7615_rate_desc *rate = &wd->rate; - struct mt7615_sta *sta = wd->sta; + struct mt7615_rate_desc *rate = &wrd->rate; + struct mt7615_sta *sta = wrd->sta; u32 w5, w27, addr, val; lockdep_assert_held(&dev->mt76.mutex); @@ -132,86 +131,30 @@ mt7663_usb_sdio_set_rates(struct mt7615_dev *dev, return 0; } -static int -mt7663_usb_sdio_set_key(struct mt7615_dev *dev, - struct mt7615_wtbl_desc *wd) +static void mt7663_usb_sdio_rate_work(struct work_struct *work) { - struct mt7615_key_desc *key = &wd->key; - struct mt7615_sta *sta = wd->sta; - enum mt7615_cipher_type cipher; - struct mt76_wcid *wcid; - int err; - - lockdep_assert_held(&dev->mt76.mutex); - - if (!sta) { - err = -EINVAL; - goto out; - } - - cipher = mt7615_mac_get_cipher(key->cipher); - if (cipher == MT_CIPHER_NONE) { - err = -EOPNOTSUPP; - goto out; - } - - wcid = &wd->sta->wcid; - - mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, key->cmd); - err = mt7615_mac_wtbl_update_key(dev, wcid, key->key, key->keylen, - cipher, key->cmd); - if (err < 0) - goto out; - - err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, - key->cmd); - if (err < 0) - goto out; - - if (key->cmd == SET_KEY) - wcid->cipher |= BIT(cipher); - else - wcid->cipher &= ~BIT(cipher); -out: - kfree(key->key); - - return err; -} - -void mt7663_usb_sdio_wtbl_work(struct work_struct *work) -{ - struct mt7615_wtbl_desc *wd, *wd_next; - struct list_head wd_list; + struct mt7615_wtbl_rate_desc *wrd, *wrd_next; + struct list_head wrd_list; struct mt7615_dev *dev; dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev, - wtbl_work); + rate_work); - INIT_LIST_HEAD(&wd_list); + INIT_LIST_HEAD(&wrd_list); spin_lock_bh(&dev->mt76.lock); - list_splice_init(&dev->wd_head, &wd_list); + list_splice_init(&dev->wrd_head, &wrd_list); spin_unlock_bh(&dev->mt76.lock); - list_for_each_entry_safe(wd, wd_next, &wd_list, node) { - list_del(&wd->node); + list_for_each_entry_safe(wrd, wrd_next, &wrd_list, node) { + list_del(&wrd->node); mt7615_mutex_acquire(dev); - - switch (wd->type) { - case MT7615_WTBL_RATE_DESC: - mt7663_usb_sdio_set_rates(dev, wd); - break; - case MT7615_WTBL_KEY_DESC: - mt7663_usb_sdio_set_key(dev, wd); - break; - } - + mt7663_usb_sdio_set_rates(dev, wrd); mt7615_mutex_release(dev); - kfree(wd); + kfree(wrd); } } -EXPORT_SYMBOL_GPL(mt7663_usb_sdio_wtbl_work); bool mt7663_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update) { @@ -357,8 +300,8 @@ int mt7663_usb_sdio_register_device(struct mt7615_dev *dev) struct ieee80211_hw *hw = mt76_hw(dev); int err; - INIT_WORK(&dev->wtbl_work, mt7663_usb_sdio_wtbl_work); - INIT_LIST_HEAD(&dev->wd_head); + INIT_WORK(&dev->rate_work, mt7663_usb_sdio_rate_work); + INIT_LIST_HEAD(&dev->wrd_head); mt7615_init_device(dev); err = mt7663_usb_sdio_init_hardware(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index 9087607b621e..dd66fd12a2e6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -52,15 +52,15 @@ static void mt76x0_set_chip_cap(struct mt76x02_dev *dev) mt76x02_eeprom_parse_hw_cap(dev); dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n", - dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz); + dev->mphy.cap.has_2ghz, dev->mphy.cap.has_5ghz); if (dev->no_2ghz) { - dev->mt76.cap.has_2ghz = false; + dev->mphy.cap.has_2ghz = false; dev_dbg(dev->mt76.dev, "mask out 2GHz support\n"); } if (is_mt7630(dev)) { - dev->mt76.cap.has_5ghz = false; + dev->mphy.cap.has_5ghz = false; dev_dbg(dev->mt76.dev, "mask out 5GHz support\n"); } @@ -342,10 +342,10 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev) dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n", version, fae); - memcpy(dev->mt76.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR, + memcpy(dev->mphy.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN); - mt76_eeprom_override(&dev->mt76); - mt76x02_mac_setaddr(dev, dev->mt76.macaddr); + mt76_eeprom_override(&dev->mphy); + mt76x02_mac_setaddr(dev, dev->mphy.macaddr); mt76x0_set_chip_cap(dev); mt76x0_set_freq_offset(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index d78866bf41ba..0bac39bf3b66 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -245,7 +245,7 @@ int mt76x0_register_device(struct mt76x02_dev *dev) if (ret) return ret; - if (dev->mt76.cap.has_5ghz) { + if (dev->mphy.cap.has_5ghz) { struct ieee80211_supported_band *sband; sband = &dev->mphy.sband_5g.sband; @@ -253,7 +253,7 @@ int mt76x0_register_device(struct mt76x02_dev *dev) mt76x0_init_txpower(dev, sband); } - if (dev->mt76.cap.has_2ghz) + if (dev->mphy.cap.has_2ghz) mt76x0_init_txpower(dev, &dev->mphy.sband_2g.sband); mt76x02_init_debugfs(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index dda11c704aba..b87d8e136cb9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -194,7 +194,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; error: - ieee80211_free_hw(mt76_hw(dev)); + mt76_free_device(&dev->mt76); + return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c index 007c762c6db1..f0962507f72f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c @@ -117,6 +117,7 @@ int mt76x0e_mcu_init(struct mt76x02_dev *dev) { static const struct mt76_mcu_ops mt76x0e_mcu_ops = { .mcu_send_msg = mt76x02_mcu_msg_send, + .mcu_parse_response = mt76x02_mcu_parse_response, }; int err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 3de33aadf794..e91c314cdfac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -447,11 +447,11 @@ static void mt76x0_phy_ant_select(struct mt76x02_dev *dev) else coex3 |= BIT(4); coex3 |= BIT(3); - if (dev->mt76.cap.has_2ghz) + if (dev->mphy.cap.has_2ghz) wlan |= BIT(6); } else { /* sigle antenna mode */ - if (dev->mt76.cap.has_5ghz) { + if (dev->mphy.cap.has_5ghz) { coex3 |= BIT(3) | BIT(4); } else { wlan |= BIT(6); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index ce6b286a8152..b12cb17cb43d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -277,6 +277,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, err: usb_set_intfdata(usb_intf, NULL); usb_put_dev(interface_to_usbdev(usb_intf)); + mt76u_queues_deinit(&dev->mt76); mt76_free_device(&dev->mt76); return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index b29cd39dc176..a601350531cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -609,10 +609,11 @@ static void mt76x02_dfs_check_event_window(struct mt76x02_dev *dev) } } -static void mt76x02_dfs_tasklet(unsigned long arg) +static void mt76x02_dfs_tasklet(struct tasklet_struct *t) { - struct mt76x02_dev *dev = (struct mt76x02_dev *)arg; - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_pattern_detector *dfs_pd = from_tasklet(dfs_pd, t, + dfs_tasklet); + struct mt76x02_dev *dev = container_of(dfs_pd, typeof(*dev), dfs_pd); u32 engine_mask; int i; @@ -860,8 +861,7 @@ void mt76x02_dfs_init_detector(struct mt76x02_dev *dev) INIT_LIST_HEAD(&dfs_pd->seq_pool); dev->mt76.region = NL80211_DFS_UNSET; dfs_pd->last_sw_check = jiffies; - tasklet_init(&dfs_pd->dfs_tasklet, mt76x02_dfs_tasklet, - (unsigned long)dev); + tasklet_setup(&dfs_pd->dfs_tasklet, mt76x02_dfs_tasklet); } static void diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c index c54c50fd639a..0acabba2d1a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c @@ -75,14 +75,14 @@ void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev) switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) { case BOARD_TYPE_5GHZ: - dev->mt76.cap.has_5ghz = true; + dev->mphy.cap.has_5ghz = true; break; case BOARD_TYPE_2GHZ: - dev->mt76.cap.has_2ghz = true; + dev->mphy.cap.has_2ghz = true; break; default: - dev->mt76.cap.has_2ghz = true; - dev->mt76.cap.has_5ghz = true; + dev->mphy.cap.has_2ghz = true; + dev->mphy.cap.has_5ghz = true; break; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index da6d3f51f6d4..16b40a73fd1f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -727,24 +727,24 @@ void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr) static const u8 null_addr[ETH_ALEN] = {}; int i; - ether_addr_copy(dev->mt76.macaddr, addr); + ether_addr_copy(dev->mphy.macaddr, addr); - if (!is_valid_ether_addr(dev->mt76.macaddr)) { - eth_random_addr(dev->mt76.macaddr); + if (!is_valid_ether_addr(dev->mphy.macaddr)) { + eth_random_addr(dev->mphy.macaddr); dev_info(dev->mt76.dev, "Invalid MAC address, using random address %pM\n", - dev->mt76.macaddr); + dev->mphy.macaddr); } - mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->mt76.macaddr)); + mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->mphy.macaddr)); mt76_wr(dev, MT_MAC_ADDR_DW1, - get_unaligned_le16(dev->mt76.macaddr + 4) | + get_unaligned_le16(dev->mphy.macaddr + 4) | FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff)); mt76_wr(dev, MT_MAC_BSSID_DW0, - get_unaligned_le32(dev->mt76.macaddr)); + get_unaligned_le32(dev->mphy.macaddr)); mt76_wr(dev, MT_MAC_BSSID_DW1, - get_unaligned_le16(dev->mt76.macaddr + 4) | + get_unaligned_le16(dev->mphy.macaddr + 4) | FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 APs + 8 STAs */ MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT); /* enable 7 additional beacon slots and control them with bypass mask */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index 267058086a90..4aa5c36afeaf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -10,6 +10,28 @@ #include "mt76x02_mcu.h" +int mt76x02_mcu_parse_response(struct mt76_dev *mdev, int cmd, + struct sk_buff *skb, int seq) +{ + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); + u32 *rxfce; + + if (!skb) { + dev_err(mdev->dev, + "MCU message %d (seq %d) timed out\n", cmd, + seq); + dev->mcu_timeout = 1; + return -ETIMEDOUT; + } + + rxfce = (u32 *)skb->cb; + if (seq != FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, *rxfce)) + return -EAGAIN; + + return 0; +} +EXPORT_SYMBOL_GPL(mt76x02_mcu_parse_response); + int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int len, bool wait_resp) { @@ -39,31 +61,15 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | FIELD_PREP(MT_MCU_MSG_LEN, skb->len); - ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, tx_info); + ret = mt76_tx_queue_skb_raw(dev, mdev->q_mcu[MT_MCUQ_WM], skb, tx_info); if (ret) goto out; while (wait_resp) { - u32 *rxfce; - bool check_seq = false; - skb = mt76_mcu_get_response(&dev->mt76, expires); - if (!skb) { - dev_err(mdev->dev, - "MCU message %d (seq %d) timed out\n", cmd, - seq); - ret = -ETIMEDOUT; - dev->mcu_timeout = 1; - break; - } - - rxfce = (u32 *)skb->cb; - - if (seq == FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, *rxfce)) - check_seq = true; - + ret = mt76x02_mcu_parse_response(mdev, cmd, skb, seq); dev_kfree_skb(skb); - if (check_seq) + if (ret != -EAGAIN) break; } @@ -89,7 +95,8 @@ int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func, if (func != Q_SELECT) wait = true; - return mt76_mcu_send_msg(dev, CMD_FUN_SET_OP, &msg, sizeof(msg), wait); + return mt76_mcu_send_msg(&dev->mt76, CMD_FUN_SET_OP, &msg, + sizeof(msg), wait); } EXPORT_SYMBOL_GPL(mt76x02_mcu_function_select); @@ -103,8 +110,8 @@ int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on) .level = cpu_to_le32(0), }; - return mt76_mcu_send_msg(dev, CMD_POWER_SAVING_OP, &msg, sizeof(msg), - false); + return mt76_mcu_send_msg(&dev->mt76, CMD_POWER_SAVING_OP, &msg, + sizeof(msg), false); } EXPORT_SYMBOL_GPL(mt76x02_mcu_set_radio_state); @@ -123,8 +130,8 @@ int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param) if (is_mt76x2e) mt76_rmw(dev, MT_MCU_COM_REG0, BIT(31), 0); - ret = mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg), - true); + ret = mt76_mcu_send_msg(&dev->mt76, CMD_CALIBRATION_OP, &msg, + sizeof(msg), true); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h index 5fba1266c648..e187ed52968e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h @@ -89,6 +89,8 @@ int mt76x02_mcu_cleanup(struct mt76x02_dev *dev); int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param); int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int len, bool wait_resp); +int mt76x02_mcu_parse_response(struct mt76_dev *mdev, int cmd, + struct sk_buff *skb, int seq); int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func, u32 val); int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index cf68731bd094..e7e87311d355 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -11,10 +11,11 @@ #include "mt76x02_mcu.h" #include "trace.h" -static void mt76x02_pre_tbtt_tasklet(unsigned long arg) +static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t) { - struct mt76x02_dev *dev = (struct mt76x02_dev *)arg; - struct mt76_queue *q = dev->mt76.q_tx[MT_TXQ_PSD]; + struct mt76x02_dev *dev = from_tasklet(dev, t, mt76.pre_tbtt_tasklet); + struct mt76_dev *mdev = &dev->mt76; + struct mt76_queue *q = dev->mphy.q_tx[MT_TXQ_PSD]; struct beacon_bc_data data = {}; struct sk_buff *skb; int i; @@ -35,9 +36,9 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg) mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~(0xff00 >> dev->beacon_data_count)); - mt76_csa_check(&dev->mt76); + mt76_csa_check(mdev); - if (dev->mt76.csa_complete) + if (mdev->csa_complete) return; mt76x02_enqueue_buffered_bc(dev, &data, 8); @@ -58,8 +59,7 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg) struct ieee80211_vif *vif = info->control.vif; struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; - mt76_tx_queue_skb(dev, MT_TXQ_PSD, skb, &mvif->group_wcid, - NULL); + mt76_tx_queue_skb(dev, q, skb, &mvif->group_wcid, NULL); } spin_unlock_bh(&q->lock); } @@ -104,27 +104,6 @@ void mt76x02e_init_beacon_config(struct mt76x02_dev *dev) EXPORT_SYMBOL_GPL(mt76x02e_init_beacon_config); static int -mt76x02_init_tx_queue(struct mt76x02_dev *dev, int qid, int idx, int n_desc) -{ - struct mt76_queue *hwq; - int err; - - hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); - if (!hwq) - return -ENOMEM; - - err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); - if (err < 0) - return err; - - dev->mt76.q_tx[qid] = hwq; - - mt76x02_irq_enable(dev, MT_INT_TX_DONE(idx)); - - return 0; -} - -static int mt76x02_init_rx_queue(struct mt76x02_dev *dev, struct mt76_queue *q, int idx, int n_desc, int bufsize) { @@ -169,14 +148,16 @@ static int mt76x02_poll_tx(struct napi_struct *napi, int budget) mt76x02_mac_poll_tx_status(dev, false); - for (i = MT_TXQ_MCU; i >= 0; i--) - mt76_queue_tx_cleanup(dev, i, false); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); + for (i = MT_TXQ_PSD; i >= 0; i--) + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false); if (napi_complete_done(napi, 0)) mt76x02_irq_enable(dev, MT_INT_TX_DONE_ALL); - for (i = MT_TXQ_MCU; i >= 0; i--) - mt76_queue_tx_cleanup(dev, i, false); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); + for (i = MT_TXQ_PSD; i >= 0; i--) + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false); mt76_worker_schedule(&dev->mt76.tx_worker); @@ -198,8 +179,7 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) return -ENOMEM; dev->mt76.tx_worker.fn = mt76x02_tx_worker; - tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet, - (unsigned long)dev); + tasklet_setup(&dev->mt76.pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet); spin_lock_init(&dev->txstatus_fifo_lock); kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size); @@ -209,22 +189,31 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); for (i = 0; i < IEEE80211_NUM_ACS; i++) { - ret = mt76x02_init_tx_queue(dev, i, mt76_ac_to_hwq(i), - MT76x02_TX_RING_SIZE); + ret = mt76_init_tx_queue(&dev->mphy, i, mt76_ac_to_hwq(i), + MT76x02_TX_RING_SIZE, + MT_TX_RING_BASE); if (ret) return ret; } - ret = mt76x02_init_tx_queue(dev, MT_TXQ_PSD, - MT_TX_HW_QUEUE_MGMT, MT76x02_PSD_RING_SIZE); + ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, + MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; - ret = mt76x02_init_tx_queue(dev, MT_TXQ_MCU, - MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE); + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT_TX_HW_QUEUE_MCU, + MT_MCU_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; + mt76x02_irq_enable(dev, + MT_INT_TX_DONE(IEEE80211_AC_VO) | + MT_INT_TX_DONE(IEEE80211_AC_VI) | + MT_INT_TX_DONE(IEEE80211_AC_BE) | + MT_INT_TX_DONE(IEEE80211_AC_BK) | + MT_INT_TX_DONE(MT_TX_HW_QUEUE_MGMT) | + MT_INT_TX_DONE(MT_TX_HW_QUEUE_MCU)); + ret = mt76x02_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1, MT_MCU_RING_SIZE, MT_RX_BUF_SIZE); if (ret) @@ -292,7 +281,7 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) if (dev->mt76.csa_complete) mt76_csa_finish(&dev->mt76); else - mt76_queue_kick(dev, dev->mt76.q_tx[MT_TXQ_PSD]); + mt76_queue_kick(dev, dev->mphy.q_tx[MT_TXQ_PSD]); } if (intr & MT_INT_TX_STAT) @@ -357,7 +346,7 @@ static bool mt76x02_tx_hang(struct mt76x02_dev *dev) int i; for (i = 0; i < 4; i++) { - q = dev->mt76.q_tx[i]; + q = dev->mphy.q_tx[i]; if (!q->queued) continue; @@ -475,8 +464,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) if (restart) mt76_mcu_restart(dev); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true); for (i = 0; i < __MT_TXQ_MAX; i++) - mt76_queue_tx_cleanup(dev, i, true); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 2c2f56112b57..efd70ddc2fd1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -67,7 +67,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, struct mt76_tx_info *tx_info) { struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); - int pid, len = tx_info->skb->len, ep = q2ep(mdev->q_tx[qid]->hw_idx); + int pid, len = tx_info->skb->len, ep = q2ep(dev->mphy.q_tx[qid]->hw_idx); struct mt76x02_txwi *txwi; bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; enum mt76_qsel qsel; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index e43d13d7c988..2953df7d8388 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -297,6 +297,7 @@ void mt76x02u_init_mcu(struct mt76_dev *dev) .headroom = MT_CMD_HDR_LEN, .tailroom = 8, .mcu_send_msg = mt76x02u_mcu_send_msg, + .mcu_parse_response = mt76x02_mcu_parse_response, .mcu_wr_rp = mt76x02u_mcu_wr_rp, .mcu_rd_rp = mt76x02u_mcu_rd_rp, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 11b769af2f8f..7ac20d3c16d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -186,6 +186,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev) ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); dev->mt76.global_wcid.idx = 255; dev->mt76.global_wcid.hw_key_idx = -1; @@ -304,12 +305,12 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) /* Allow to change address in HW if we create first interface. */ if (!dev->mphy.vif_mask && - (((vif->addr[0] ^ dev->mt76.macaddr[0]) & ~GENMASK(4, 1)) || - memcmp(vif->addr + 1, dev->mt76.macaddr + 1, ETH_ALEN - 1))) + (((vif->addr[0] ^ dev->mphy.macaddr[0]) & ~GENMASK(4, 1)) || + memcmp(vif->addr + 1, dev->mphy.macaddr + 1, ETH_ALEN - 1))) mt76x02_mac_setaddr(dev, vif->addr); if (vif->addr[0] & BIT(1)) - idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7); + idx = 1 + (((dev->mphy.macaddr[0] ^ vif->addr[0]) >> 2) & 7); /* * Client mode typically only has one configurable BSSID register, @@ -487,7 +488,7 @@ int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 cw_min = 5, cw_max = 10, qid; u32 val; - qid = dev->mt76.q_tx[queue]->hw_idx; + qid = dev->mphy.q_tx[queue]->hw_idx; if (params->cw_min) cw_min = fls(params->cw_min); @@ -621,7 +622,7 @@ void mt76x02_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, struct mt76x02_sta *msta = (struct mt76x02_sta *)sta->drv_priv; int idx = msta->wcid.idx; - mt76_stop_tx_queues(&dev->mt76, sta, true); + mt76_stop_tx_queues(&dev->mphy, sta, true); if (mt76_is_mmio(mdev)) mt76x02_mac_wcid_set_drop(dev, idx, ps); } @@ -677,7 +678,7 @@ void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev) for (i = 0; i < ARRAY_SIZE(dev->macaddr_list); i++) { u8 *addr = dev->macaddr_list[i].addr; - memcpy(addr, dev->mt76.macaddr, ETH_ALEN); + memcpy(addr, dev->mphy.macaddr, ETH_ALEN); if (!i) continue; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c index 410ffce3baff..c57e05a5c65e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c @@ -16,7 +16,7 @@ mt76x2_eeprom_get_macaddr(struct mt76x02_dev *dev) { void *src = dev->mt76.eeprom.data + MT_EE_MAC_ADDR; - memcpy(dev->mt76.macaddr, src, ETH_ALEN); + memcpy(dev->mphy.macaddr, src, ETH_ALEN); return 0; } @@ -502,8 +502,8 @@ int mt76x2_eeprom_init(struct mt76x02_dev *dev) mt76x02_eeprom_parse_hw_cap(dev); mt76x2_eeprom_get_macaddr(dev); - mt76_eeprom_override(&dev->mt76); - dev->mt76.macaddr[0] &= ~BIT(1); + mt76_eeprom_override(&dev->mphy); + dev->mphy.macaddr[0] &= ~BIT(1); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c index 9635c04ce032..3c2738903d7d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c @@ -33,13 +33,14 @@ int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, }; /* first set the channel without the extension channel info */ - mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), true); + mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg, + sizeof(msg), true); usleep_range(5000, 10000); msg.ext_chan = 0xe0 + bw_index; - return mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), - true); + return mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg, + sizeof(msg), true); } EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel); @@ -66,7 +67,8 @@ int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, msg.cfg = cpu_to_le32(val); /* first set the channel without the extension channel info */ - return mt76_mcu_send_msg(dev, CMD_LOAD_CR, &msg, sizeof(msg), true); + return mt76_mcu_send_msg(&dev->mt76, CMD_LOAD_CR, &msg, sizeof(msg), + true); } EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr); @@ -84,8 +86,8 @@ int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain, if (force) msg.channel |= cpu_to_le32(BIT(31)); - return mt76_mcu_send_msg(dev, CMD_INIT_GAIN_OP, &msg, sizeof(msg), - true); + return mt76_mcu_send_msg(&dev->mt76, CMD_INIT_GAIN_OP, &msg, + sizeof(msg), true); } EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain); @@ -100,7 +102,7 @@ int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev, .data = *tssi_data, }; - return mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg), - true); + return mt76_mcu_send_msg(&dev->mt76, CMD_CALIBRATION_OP, &msg, + sizeof(msg), true); } EXPORT_SYMBOL_GPL(mt76x2_mcu_tssi_comp); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index 4d50dad29ddf..ecaf85b483ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -90,7 +90,8 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; error: - ieee80211_free_hw(mt76_hw(dev)); + mt76_free_device(&dev->mt76); + return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 48a3ebc9892a..620484390418 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -69,7 +69,7 @@ mt76x2_fixup_xtal(struct mt76x02_dev *dev) int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) { - const u8 *macaddr = dev->mt76.macaddr; + const u8 *macaddr = dev->mphy.macaddr; u32 val; int i, k; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c index ca6f968411ac..e5b6282d1a6c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c @@ -179,6 +179,7 @@ int mt76x2_mcu_init(struct mt76x02_dev *dev) static const struct mt76_mcu_ops mt76x2_mcu_ops = { .mcu_restart = mt76pci_mcu_restart, .mcu_send_msg = mt76x02_mcu_msg_send, + .mcu_parse_response = mt76x02_mcu_parse_response, }; int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index 4e003c7b62cf..2575369e44e2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -75,6 +75,7 @@ static int mt76x2u_probe(struct usb_interface *intf, return 0; err: + mt76u_queues_deinit(&dev->mt76); mt76_free_device(&dev->mt76); usb_set_intfdata(intf, NULL); usb_put_dev(udev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile index 57fe726cc38b..cc2054dffa98 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile @@ -4,3 +4,5 @@ obj-$(CONFIG_MT7915E) += mt7915e.o mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ debugfs.o + +mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index 1049927faf24..7d810fbf2862 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -48,32 +48,6 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL, mt7915_radar_trigger, "%lld\n"); static int -mt7915_dbdc_set(void *data, u64 val) -{ - struct mt7915_dev *dev = data; - - if (val) - mt7915_register_ext_phy(dev); - else - mt7915_unregister_ext_phy(dev); - - return 0; -} - -static int -mt7915_dbdc_get(void *data, u64 *val) -{ - struct mt7915_dev *dev = data; - - *val = !!mt7915_ext_phy(dev); - - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7915_dbdc_get, - mt7915_dbdc_set, "%lld\n"); - -static int mt7915_fw_debug_set(void *data, u64 val) { struct mt7915_dev *dev = data; @@ -233,6 +207,7 @@ static const struct file_operations fops_tx_stats = { .read = seq_read, .llseek = seq_lseek, .release = single_release, + .owner = THIS_MODULE, }; static int mt7915_read_temperature(struct seq_file *s, void *data) @@ -279,19 +254,23 @@ static int mt7915_queues_read(struct seq_file *s, void *data) { struct mt7915_dev *dev = dev_get_drvdata(s->private); - static const struct { + struct mt76_phy *mphy_ext = dev->mt76.phy2; + struct mt76_queue *ext_q = mphy_ext ? mphy_ext->q_tx[MT_TXQ_BE] : NULL; + struct { + struct mt76_queue *q; char *queue; - int id; } queue_map[] = { - { "WFDMA0", MT_TXQ_BE }, - { "MCUWM", MT_TXQ_MCU }, - { "MCUWA", MT_TXQ_MCU_WA }, - { "MCUFWQ", MT_TXQ_FWDL }, + { dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" }, + { ext_q, "WFDMA1" }, + { dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" }, + { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" }, + { dev->mt76.q_mcu[MT_MCUQ_WA], "MCUWA" }, + { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" }, }; int i; for (i = 0; i < ARRAY_SIZE(queue_map); i++) { - struct mt76_queue *q = dev->mt76.q_tx[queue_map[i].id]; + struct mt76_queue *q = queue_map[i].q; if (!q) continue; @@ -375,7 +354,6 @@ int mt7915_init_debugfs(struct mt7915_dev *dev) debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, mt7915_queues_acq); debugfs_create_file("tx_stats", 0400, dir, dev, &fops_tx_stats); - debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc); debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); /* test knobs */ @@ -460,6 +438,7 @@ static const struct file_operations fops_sta_stats = { .read = seq_read, .llseek = seq_lseek, .release = single_release, + .owner = THIS_MODULE, }; void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index cfa12c4c671f..8c1f9c77b14f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -5,42 +5,16 @@ #include "../dma.h" #include "mac.h" -static int -mt7915_init_tx_queues(struct mt7915_dev *dev, int n_desc) +int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc) { - struct mt76_queue *hwq; - int err, i; + int i, err; - hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); - if (!hwq) - return -ENOMEM; - - err = mt76_queue_alloc(dev, hwq, MT7915_TXQ_BAND0, n_desc, 0, - MT_TX_RING_BASE); - if (err < 0) - return err; - - for (i = 0; i < MT_TXQ_MCU; i++) - dev->mt76.q_tx[i] = hwq; - - return 0; -} - -static int -mt7915_init_mcu_queue(struct mt7915_dev *dev, int qid, int idx, int n_desc) -{ - struct mt76_queue *hwq; - int err; - - hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); - if (!hwq) - return -ENOMEM; - - err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); + err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE); if (err < 0) return err; - dev->mt76.q_tx[qid] = hwq; + for (i = 0; i <= MT_TXQ_PSD; i++) + phy->mt76->q_tx[i] = phy->mt76->q_tx[0]; return 0; } @@ -61,6 +35,11 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, case PKT_TYPE_RX_EVENT: mt7915_mcu_rx_event(dev, skb); break; +#ifdef CONFIG_NL80211_TESTMODE + case PKT_TYPE_TXRXV: + mt7915_mac_fill_rx_vector(dev, skb); + break; +#endif case PKT_TYPE_NORMAL: if (!mt7915_mac_fill_rx(dev, skb)) { mt76_rx(&dev->mt76, q, skb); @@ -76,8 +55,8 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, static void mt7915_tx_cleanup(struct mt7915_dev *dev) { - mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false); - mt76_queue_tx_cleanup(dev, MT_TXQ_MCU_WA, false); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false); } static int mt7915_poll_tx(struct napi_struct *napi, int budget) @@ -257,25 +236,26 @@ int mt7915_dma_init(struct mt7915_dev *dev) mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0, 0); /* init tx queue */ - ret = mt7915_init_tx_queues(dev, MT7915_TX_RING_SIZE); + ret = mt7915_init_tx_queues(&dev->phy, MT7915_TXQ_BAND0, + MT7915_TX_RING_SIZE); if (ret) return ret; /* command to WM */ - ret = mt7915_init_mcu_queue(dev, MT_TXQ_MCU, MT7915_TXQ_MCU_WM, - MT7915_TX_MCU_RING_SIZE); + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7915_TXQ_MCU_WM, + MT7915_TX_MCU_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; /* command to WA */ - ret = mt7915_init_mcu_queue(dev, MT_TXQ_MCU_WA, MT7915_TXQ_MCU_WA, - MT7915_TX_MCU_RING_SIZE); + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WA, MT7915_TXQ_MCU_WA, + MT7915_TX_MCU_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; /* firmware download */ - ret = mt7915_init_mcu_queue(dev, MT_TXQ_FWDL, MT7915_TXQ_FWDL, - MT7915_TX_FWDL_RING_SIZE); + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7915_TXQ_FWDL, + MT7915_TX_FWDL_RING_SIZE, MT_TX_RING_BASE); if (ret) return ret; @@ -293,13 +273,21 @@ int mt7915_dma_init(struct mt7915_dev *dev) if (ret) return ret; - /* rx data */ - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, - MT7915_RX_RING_SIZE, rx_buf_size, - MT_RX_DATA_RING_BASE); + /* rx data queue */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], + MT7915_RXQ_BAND0, MT7915_RX_RING_SIZE, + rx_buf_size, MT_RX_DATA_RING_BASE); if (ret) return ret; + if (dev->dbdc_support) { + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT], + MT7915_RXQ_BAND1, MT7915_RX_RING_SIZE, + rx_buf_size, MT_RX_DATA_RING_BASE); + if (ret) + return ret; + } + ret = mt76_init_queues(dev); if (ret < 0) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 7deba7ebd68a..7a2be3f61398 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -4,16 +4,11 @@ #include "mt7915.h" #include "eeprom.h" -static inline bool mt7915_efuse_valid(u8 val) -{ - return !(val == 0xff); -} - -u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset) +static u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset) { u8 *data = dev->mt76.eeprom.data; - if (!mt7915_efuse_valid(data[offset])) + if (data[offset] == 0xff) mt7915_mcu_get_eeprom(dev, offset); return data[offset]; @@ -34,10 +29,10 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) static int mt7915_check_eeprom(struct mt7915_dev *dev) { - u16 val; u8 *eeprom = dev->mt76.eeprom.data; + u16 val; - mt7915_eeprom_read(dev, 0); + mt7915_eeprom_read(dev, MT_EE_CHIP_ID); val = get_unaligned_le16(eeprom); switch (val) { @@ -48,35 +43,50 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev) } } -static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev) +void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) { - u8 *eeprom = dev->mt76.eeprom.data; - u8 tx_mask, max_nss = 4; - u32 val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF); + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 val; + val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF + ext_phy); val = FIELD_GET(MT_EE_WIFI_CONF_BAND_SEL, val); switch (val) { case MT_EE_5GHZ: - dev->mt76.cap.has_5ghz = true; + phy->mt76->cap.has_5ghz = true; break; case MT_EE_2GHZ: - dev->mt76.cap.has_2ghz = true; + phy->mt76->cap.has_2ghz = true; break; default: - dev->mt76.cap.has_2ghz = true; - dev->mt76.cap.has_5ghz = true; + phy->mt76->cap.has_2ghz = true; + phy->mt76->cap.has_5ghz = true; break; } +} + +static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev) +{ + u8 nss, tx_mask[2] = {}, *eeprom = dev->mt76.eeprom.data; + + mt7915_eeprom_parse_band_config(&dev->phy); /* read tx mask from eeprom */ - tx_mask = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK, - eeprom[MT_EE_WIFI_CONF]); - if (!tx_mask || tx_mask > max_nss) - tx_mask = max_nss; - - dev->chainmask = BIT(tx_mask) - 1; - dev->mphy.antenna_mask = dev->chainmask; - dev->phy.chainmask = dev->chainmask; + tx_mask[0] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK, + eeprom[MT_EE_WIFI_CONF]); + if (dev->dbdc_support) + tx_mask[1] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK, + eeprom[MT_EE_WIFI_CONF + 1]); + + nss = tx_mask[0] + tx_mask[1]; + if (!nss || nss > 4) { + tx_mask[0] = 4; + nss = 4; + } + + dev->chainmask = BIT(nss) - 1; + dev->mphy.antenna_mask = BIT(tx_mask[0]) - 1; + dev->phy.chainmask = dev->mphy.antenna_mask; } int mt7915_eeprom_init(struct mt7915_dev *dev) @@ -92,10 +102,10 @@ int mt7915_eeprom_init(struct mt7915_dev *dev) return ret; mt7915_eeprom_parse_hw_cap(dev); - memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, + memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN); - mt76_eeprom_override(&dev->mt76); + mt76_eeprom_override(&dev->mphy); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h index 4e31d6ab4fa6..6712032b40df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h @@ -15,6 +15,7 @@ enum mt7915_eeprom_field { MT_EE_CHIP_ID = 0x000, MT_EE_VERSION = 0x002, MT_EE_MAC_ADDR = 0x004, + MT_EE_MAC_ADDR2 = 0x00a, MT_EE_DDIE_FT_VERSION = 0x050, MT_EE_WIFI_CONF = 0x190, MT_EE_TX0_POWER_2G = 0x2fc, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 0232b66acb4f..ed4635bd151a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -6,6 +6,113 @@ #include "mac.h" #include "eeprom.h" +#define CCK_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ + .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)), \ +} + +#define OFDM_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ +} + +static struct ieee80211_rate mt7915_rates[] = { + CCK_RATE(0, 10), + CCK_RATE(1, 20), + CCK_RATE(2, 55), + CCK_RATE(3, 110), + OFDM_RATE(11, 60), + OFDM_RATE(15, 90), + OFDM_RATE(10, 120), + OFDM_RATE(14, 180), + OFDM_RATE(9, 240), + OFDM_RATE(13, 360), + OFDM_RATE(8, 480), + OFDM_RATE(12, 540), +}; + +static const struct ieee80211_iface_limit if_limits[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_ADHOC) + }, { + .max = 16, + .types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) +#endif + }, { + .max = MT7915_MAX_INTERFACES, + .types = BIT(NL80211_IFTYPE_STATION) + } +}; + +static const struct ieee80211_iface_combination if_comb[] = { + { + .limits = if_limits, + .n_limits = ARRAY_SIZE(if_limits), + .max_interfaces = MT7915_MAX_INTERFACES, + .num_different_channels = 1, + .beacon_int_infra_match = true, + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80) | + BIT(NL80211_CHAN_WIDTH_160) | + BIT(NL80211_CHAN_WIDTH_80P80), + } +}; + +static void +mt7915_regd_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + struct mt7915_phy *phy = mphy->priv; + struct cfg80211_chan_def *chandef = &mphy->chandef; + + dev->mt76.region = request->dfs_region; + + if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) + return; + + mt7915_dfs_init_radar_detector(phy); +} + +static void +mt7915_init_wiphy(struct ieee80211_hw *hw) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct wiphy *wiphy = hw->wiphy; + + hw->queues = 4; + hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + + phy->slottime = 9; + + hw->sta_data_size = sizeof(struct mt7915_sta); + hw->vif_data_size = sizeof(struct mt7915_vif); + + wiphy->iface_combinations = if_comb; + wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); + wiphy->reg_notifier = mt7915_regd_notifier; + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + + ieee80211_hw_set(hw, HAS_RATE_CONTROL); + ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); + ieee80211_hw_set(hw, WANT_MONITOR_VIF); + + hw->max_tx_fragments = 4; +} + static void mt7915_mac_init_band(struct mt7915_dev *dev, u8 band) { @@ -35,25 +142,26 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band) mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); + + mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536); + /* disable rx rate report by default due to hw issues */ + mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); } static void mt7915_mac_init(struct mt7915_dev *dev) { int i; - mt76_rmw_field(dev, MT_DMA_DCR0, MT_DMA_DCR0_MAX_RX_LEN, 1536); mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536); - /* enable rx rate report */ - mt76_set(dev, MT_DMA_DCR0, MT_DMA_DCR0_RXD_G5_EN); /* disable hardware de-agg */ mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); for (i = 0; i < MT7915_WTBL_SIZE; i++) mt7915_mac_wtbl_update(dev, i, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + for (i = 0; i < 2; i++) + mt7915_mac_init_band(dev, i); - mt7915_mac_init_band(dev, 0); - mt7915_mac_init_band(dev, 1); mt7915_mcu_set_rts_thresh(&dev->phy, 0x92b); } @@ -108,6 +216,60 @@ static void mt7915_init_txpower(struct mt7915_dev *dev) mt7915_eeprom_init_sku(dev); } +static int mt7915_register_ext_phy(struct mt7915_dev *dev) +{ + struct mt7915_phy *phy = mt7915_ext_phy(dev); + struct mt76_phy *mphy; + int ret; + + if (!dev->dbdc_support) + return 0; + + if (phy) + return 0; + + mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); + if (!mphy) + return -ENOMEM; + + phy = mphy->priv; + phy->dev = dev; + phy->mt76 = mphy; + phy->chainmask = dev->chainmask & ~dev->phy.chainmask; + mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; + mt7915_init_wiphy(mphy->hw); + + INIT_LIST_HEAD(&phy->stats_list); + INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work); + + mt7915_eeprom_parse_band_config(phy); + mt7915_set_stream_vht_txbf_caps(phy); + mt7915_set_stream_he_caps(phy); + + memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR2, + ETH_ALEN); + mt76_eeprom_override(mphy); + + /* The second interface does not get any packets unless it has a vif */ + ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF); + + ret = mt7915_init_tx_queues(phy, MT7915_TXQ_BAND1, + MT7915_TX_RING_SIZE); + if (ret) + goto error; + + ret = mt76_register_phy(mphy, true, mt7915_rates, + ARRAY_SIZE(mt7915_rates)); + if (ret) + goto error; + + return 0; + +error: + ieee80211_free_hw(mphy->hw); + return ret; +} + static void mt7915_init_work(struct work_struct *work) { struct mt7915_dev *dev = container_of(work, struct mt7915_dev, @@ -117,6 +279,7 @@ static void mt7915_init_work(struct work_struct *work) mt7915_mac_init(dev); mt7915_init_txpower(dev); mt7915_txbf_init(dev); + mt7915_register_ext_phy(dev); } static int mt7915_init_hardware(struct mt7915_dev *dev) @@ -129,6 +292,8 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) spin_lock_init(&dev->token_lock); idr_init(&dev->token); + dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5)); + ret = mt7915_dma_init(dev); if (ret) return ret; @@ -162,109 +327,6 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) return 0; } -#define CCK_RATE(_idx, _rate) { \ - .bitrate = _rate, \ - .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ - .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \ - .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)), \ -} - -#define OFDM_RATE(_idx, _rate) { \ - .bitrate = _rate, \ - .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ - .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ -} - -static struct ieee80211_rate mt7915_rates[] = { - CCK_RATE(0, 10), - CCK_RATE(1, 20), - CCK_RATE(2, 55), - CCK_RATE(3, 110), - OFDM_RATE(11, 60), - OFDM_RATE(15, 90), - OFDM_RATE(10, 120), - OFDM_RATE(14, 180), - OFDM_RATE(9, 240), - OFDM_RATE(13, 360), - OFDM_RATE(8, 480), - OFDM_RATE(12, 540), -}; - -static const struct ieee80211_iface_limit if_limits[] = { - { - .max = 1, - .types = BIT(NL80211_IFTYPE_ADHOC) - }, { - .max = MT7915_MAX_INTERFACES, - .types = BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_STATION) - } -}; - -static const struct ieee80211_iface_combination if_comb[] = { - { - .limits = if_limits, - .n_limits = ARRAY_SIZE(if_limits), - .max_interfaces = 4, - .num_different_channels = 1, - .beacon_int_infra_match = true, - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | - BIT(NL80211_CHAN_WIDTH_20) | - BIT(NL80211_CHAN_WIDTH_40) | - BIT(NL80211_CHAN_WIDTH_80) | - BIT(NL80211_CHAN_WIDTH_160) | - BIT(NL80211_CHAN_WIDTH_80P80), - } -}; - -static void -mt7915_regd_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct mt7915_dev *dev = mt7915_hw_dev(hw); - struct mt76_phy *mphy = hw->priv; - struct mt7915_phy *phy = mphy->priv; - struct cfg80211_chan_def *chandef = &mphy->chandef; - - dev->mt76.region = request->dfs_region; - - if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) - return; - - mt7915_dfs_init_radar_detector(phy); -} - -static void -mt7915_init_wiphy(struct ieee80211_hw *hw) -{ - struct mt7915_phy *phy = mt7915_hw_phy(hw); - struct wiphy *wiphy = hw->wiphy; - - hw->queues = 4; - hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; - hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; - - phy->slottime = 9; - - hw->sta_data_size = sizeof(struct mt7915_sta); - hw->vif_data_size = sizeof(struct mt7915_vif); - - wiphy->iface_combinations = if_comb; - wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); - wiphy->reg_notifier = mt7915_regd_notifier; - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; - - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); - - ieee80211_hw_set(hw, HAS_RATE_CONTROL); - - hw->max_tx_fragments = 4; -} - void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy) { int nss = hweight8(phy->chainmask); @@ -342,7 +404,7 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER; /* num_snd_dim */ - c = (nss - 1) | (max_t(int, mcs->tx_mcs_160, 1) << 3); + c = (nss - 1) | (max_t(int, le16_to_cpu(mcs->tx_mcs_160), 1) << 3); elem->phy_cap_info[5] |= c; c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | @@ -354,35 +416,24 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, } static void -mt7915_gen_ppe_thresh(u8 *he_ppet) +mt7915_gen_ppe_thresh(u8 *he_ppet, int nss) { - int ru, nss, max_nss = 1, max_ru = 3; - u8 bit = 7, ru_bit_mask = 0x7; + u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; - he_ppet[0] = max_nss & IEEE80211_PPE_THRES_NSS_MASK; - he_ppet[0] |= (ru_bit_mask << - IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) & - IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK; - - for (nss = 0; nss <= max_nss; nss++) { - for (ru = 0; ru < max_ru; ru++) { - u8 val; - int i; - - if (!(ru_bit_mask & BIT(ru))) - continue; - - val = (ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) & - 0x3f; - val = ((val >> 3) & 0x7) | ((val & 0x7) << 3); - for (i = 5; i >= 0; i--) { - he_ppet[bit / 8] |= - ((val >> i) & 0x1) << ((bit % 8)); - bit++; - } - } - } + he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | + FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, + ru_bit_mask); + + ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE * + nss * hweight8(ru_bit_mask) * 2; + ppet_size = DIV_ROUND_UP(ppet_bits, 8); + + for (i = 0; i < ppet_size - 1; i++) + he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3]; + + he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] & + (0xff >> (8 - (ppet_bits - 1) % 8)); } static int @@ -513,7 +564,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { - mt7915_gen_ppe_thresh(he_cap->ppe_thres); + mt7915_gen_ppe_thresh(he_cap->ppe_thres, nss); } else { he_cap_elem->phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US; @@ -528,10 +579,9 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy) { struct ieee80211_sband_iftype_data *data; struct ieee80211_supported_band *band; - struct mt76_dev *mdev = &phy->dev->mt76; int n; - if (mdev->cap.has_2ghz) { + if (phy->mt76->cap.has_2ghz) { data = phy->iftype[NL80211_BAND_2GHZ]; n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data); @@ -540,7 +590,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy) band->n_iftype_data = n; } - if (mdev->cap.has_5ghz) { + if (phy->mt76->cap.has_5ghz) { data = phy->iftype[NL80211_BAND_5GHZ]; n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data); @@ -550,95 +600,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy) } } -static void -mt7915_cap_dbdc_enable(struct mt7915_dev *dev) -{ - dev->mphy.sband_5g.sband.vht_cap.cap &= - ~(IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); - - if (dev->chainmask == 0xf) - dev->mphy.antenna_mask = dev->chainmask >> 2; - else - dev->mphy.antenna_mask = dev->chainmask >> 1; - - dev->phy.chainmask = dev->mphy.antenna_mask; - dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask; - dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask; - - mt76_set_stream_caps(&dev->mphy, true); - mt7915_set_stream_vht_txbf_caps(&dev->phy); - mt7915_set_stream_he_caps(&dev->phy); -} - -static void -mt7915_cap_dbdc_disable(struct mt7915_dev *dev) -{ - dev->mphy.sband_5g.sband.vht_cap.cap |= - IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; - - dev->mphy.antenna_mask = dev->chainmask; - dev->phy.chainmask = dev->chainmask; - dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask; - dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask; - - mt76_set_stream_caps(&dev->mphy, true); - mt7915_set_stream_vht_txbf_caps(&dev->phy); - mt7915_set_stream_he_caps(&dev->phy); -} - -int mt7915_register_ext_phy(struct mt7915_dev *dev) -{ - struct mt7915_phy *phy = mt7915_ext_phy(dev); - struct mt76_phy *mphy; - int ret; - bool bound; - - /* TODO: enble DBDC */ - bound = mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5); - if (!bound) - return -EINVAL; - - if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) - return -EINVAL; - - if (phy) - return 0; - - mt7915_cap_dbdc_enable(dev); - mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); - if (!mphy) - return -ENOMEM; - - phy = mphy->priv; - phy->dev = dev; - phy->mt76 = mphy; - phy->chainmask = dev->chainmask & ~dev->phy.chainmask; - mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; - mt7915_init_wiphy(mphy->hw); - - INIT_LIST_HEAD(&phy->stats_list); - INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work); - - /* - * Make the secondary PHY MAC address local without overlapping with - * the usual MAC address allocation scheme on multiple virtual interfaces - */ - mphy->hw->wiphy->perm_addr[0] |= 2; - mphy->hw->wiphy->perm_addr[0] ^= BIT(7); - - /* The second interface does not get any packets unless it has a vif */ - ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF); - - ret = mt76_register_phy(mphy); - if (ret) - ieee80211_free_hw(mphy->hw); - - return ret; -} - -void mt7915_unregister_ext_phy(struct mt7915_dev *dev) +static void mt7915_unregister_ext_phy(struct mt7915_dev *dev) { struct mt7915_phy *phy = mt7915_ext_phy(dev); struct mt76_phy *mphy = dev->mt76.phy2; @@ -646,7 +608,6 @@ void mt7915_unregister_ext_phy(struct mt7915_dev *dev) if (!phy) return; - mt7915_cap_dbdc_disable(dev); mt76_unregister_phy(mphy); ieee80211_free_hw(mphy->hw); } @@ -683,9 +644,22 @@ int mt7915_register_device(struct mt7915_dev *dev) dev->mphy.sband_5g.sband.vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; - mt7915_cap_dbdc_disable(dev); + if (!dev->dbdc_support) + dev->mphy.sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask; + dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask; + + mt76_set_stream_caps(&dev->mphy, true); + mt7915_set_stream_vht_txbf_caps(&dev->phy); + mt7915_set_stream_he_caps(&dev->phy); dev->phy.dfs_state = -1; +#ifdef CONFIG_NL80211_TESTMODE + dev->mt76.test_ops = &mt7915_testmode_ops; +#endif + ret = mt76_register_device(&dev->mt76, true, mt7915_rates, ARRAY_SIZE(mt7915_rates)); if (ret) @@ -716,6 +690,7 @@ void mt7915_unregister_device(struct mt7915_dev *dev) ieee80211_free_txskb(hw, txwi->skb); } mt76_put_txwi(&dev->mt76, txwi); + dev->token_count--; } spin_unlock_bh(&dev->token_lock); idr_destroy(&dev->token); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 6f159d99a596..f504eeb221f9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -562,21 +562,271 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) return 0; } +#ifdef CONFIG_NL80211_TESTMODE +void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb) +{ + __le32 *rxd = (__le32 *)skb->data; + __le32 *rxv = rxd + 4; + u32 rcpi, ib_rssi, wb_rssi, v20, v21; + s32 foe; + u8 snr; + int i; + + rcpi = le32_to_cpu(rxv[6]); + ib_rssi = le32_to_cpu(rxv[7]); + wb_rssi = le32_to_cpu(rxv[8]) >> 5; + + for (i = 0; i < 4; i++, rcpi >>= 8, ib_rssi >>= 8, wb_rssi >>= 9) { + if (i == 3) + wb_rssi = le32_to_cpu(rxv[9]); + + dev->test.last_rcpi[i] = rcpi & 0xff; + dev->test.last_ib_rssi[i] = ib_rssi & 0xff; + dev->test.last_wb_rssi[i] = wb_rssi & 0xff; + } + + v20 = le32_to_cpu(rxv[20]); + v21 = le32_to_cpu(rxv[21]); + + foe = FIELD_GET(MT_CRXV_FOE_LO, v20) | + (FIELD_GET(MT_CRXV_FOE_HI, v21) << MT_CRXV_FOE_SHIFT); + + snr = FIELD_GET(MT_CRXV_SNR, v20) - 16; + + dev->test.last_freq_offset = foe; + dev->test.last_snr = snr; + + dev_kfree_skb(skb); +} +#endif + +static void +mt7915_mac_write_txwi_tm(struct mt7915_dev *dev, struct mt76_phy *mphy, + __le32 *txwi, struct sk_buff *skb) +{ +#ifdef CONFIG_NL80211_TESTMODE + struct mt76_testmode_data *td = &dev->mt76.test; + u8 rate_idx = td->tx_rate_idx; + u8 nss = td->tx_rate_nss; + u8 bw, mode; + u16 rateval = 0; + u32 val; + + if (skb != dev->mt76.test.tx_skb) + return; + + switch (td->tx_rate_mode) { + case MT76_TM_TX_MODE_CCK: + mode = MT_PHY_TYPE_CCK; + break; + case MT76_TM_TX_MODE_HT: + nss = 1 + (rate_idx >> 3); + mode = MT_PHY_TYPE_HT; + break; + case MT76_TM_TX_MODE_VHT: + mode = MT_PHY_TYPE_VHT; + break; + case MT76_TM_TX_MODE_HE_SU: + mode = MT_PHY_TYPE_HE_SU; + break; + case MT76_TM_TX_MODE_HE_EXT_SU: + mode = MT_PHY_TYPE_HE_EXT_SU; + break; + case MT76_TM_TX_MODE_HE_TB: + mode = MT_PHY_TYPE_HE_TB; + break; + case MT76_TM_TX_MODE_HE_MU: + mode = MT_PHY_TYPE_HE_MU; + break; + case MT76_TM_TX_MODE_OFDM: + default: + mode = MT_PHY_TYPE_OFDM; + break; + } + + switch (mphy->chandef.width) { + case NL80211_CHAN_WIDTH_40: + bw = 1; + break; + case NL80211_CHAN_WIDTH_80: + bw = 2; + break; + case NL80211_CHAN_WIDTH_80P80: + case NL80211_CHAN_WIDTH_160: + bw = 3; + break; + default: + bw = 0; + break; + } + + if (td->tx_rate_stbc && nss == 1) { + nss++; + rateval |= MT_TX_RATE_STBC; + } + + rateval |= FIELD_PREP(MT_TX_RATE_IDX, rate_idx) | + FIELD_PREP(MT_TX_RATE_MODE, mode) | + FIELD_PREP(MT_TX_RATE_NSS, nss - 1); + + txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); + + le32p_replace_bits(&txwi[3], 1, MT_TXD3_REM_TX_COUNT); + if (td->tx_rate_mode < MT76_TM_TX_MODE_HT) + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); + + val = MT_TXD6_FIXED_BW | + FIELD_PREP(MT_TXD6_BW, bw) | + FIELD_PREP(MT_TXD6_TX_RATE, rateval) | + FIELD_PREP(MT_TXD6_SGI, td->tx_rate_sgi); + + /* for HE_SU/HE_EXT_SU PPDU + * - 1x, 2x, 4x LTF + 0.8us GI + * - 2x LTF + 1.6us GI, 4x LTF + 3.2us GI + * for HE_MU PPDU + * - 2x, 4x LTF + 0.8us GI + * - 2x LTF + 1.6us GI, 4x LTF + 3.2us GI + * for HE_TB PPDU + * - 1x, 2x LTF + 1.6us GI + * - 4x LTF + 3.2us GI + */ + if (mode >= MT_PHY_TYPE_HE_SU) + val |= FIELD_PREP(MT_TXD6_HELTF, td->tx_ltf); + + if (td->tx_rate_ldpc) + val |= MT_TXD6_LDPC; + + txwi[6] |= cpu_to_le32(val); + txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, + dev->test.spe_idx)); +#endif +} + +static void +mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid) +{ + + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + u8 fc_type, fc_stype; + bool wmm = false; + u32 val; + + if (wcid->sta) { + struct ieee80211_sta *sta; + + sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); + wmm = sta->wme; + } + + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | + FIELD_PREP(MT_TXD1_TID, tid); + + if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN) + val |= MT_TXD1_ETH_802_3; + + txwi[1] |= cpu_to_le32(val); + + fc_type = IEEE80211_FTYPE_DATA >> 2; + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; + + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); + + txwi[2] |= cpu_to_le32(val); + + val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | + FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); + txwi[7] |= cpu_to_le32(val); +} + +static void +mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct ieee80211_key_conf *key) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + bool multicast = is_multicast_ether_addr(hdr->addr1); + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + __le16 fc = hdr->frame_control; + u8 fc_type, fc_stype; + u32 val; + + if (ieee80211_is_action(fc) && + mgmt->u.action.category == WLAN_CATEGORY_BACK && + mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { + u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); + + txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA); + tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK; + } else if (ieee80211_is_back_req(hdr->frame_control)) { + struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr; + u16 control = le16_to_cpu(bar->control); + + tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control); + } + + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | + FIELD_PREP(MT_TXD1_HDR_INFO, + ieee80211_get_hdrlen_from_skb(skb) / 2) | + FIELD_PREP(MT_TXD1_TID, tid); + txwi[1] |= cpu_to_le32(val); + + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; + + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | + FIELD_PREP(MT_TXD2_MULTICAST, multicast); + + if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { + val |= MT_TXD2_BIP; + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); + } + + if (!ieee80211_is_data(fc) || multicast) + val |= MT_TXD2_FIX_RATE; + + txwi[2] |= cpu_to_le32(val); + + if (ieee80211_is_beacon(fc)) { + txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); + } + + if (info->flags & IEEE80211_TX_CTL_INJECTED) { + u16 seqno = le16_to_cpu(hdr->seq_ctrl); + + if (ieee80211_is_back_req(hdr->frame_control)) { + struct ieee80211_bar *bar; + + bar = (struct ieee80211_bar *)skb->data; + seqno = le16_to_cpu(bar->start_seq_num); + } + + val = MT_TXD3_SN_VALID | + FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); + txwi[3] |= cpu_to_le32(val); + } + + val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | + FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); + txwi[7] |= cpu_to_le32(val); +} + void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, bool beacon) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - bool multicast = is_multicast_ether_addr(hdr->addr1); struct ieee80211_vif *vif = info->control.vif; struct mt76_phy *mphy = &dev->mphy; bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY; - u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; - __le16 fc = hdr->frame_control; - u16 tx_count = 15, seqno = 0; - u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; + u16 tx_count = 15; u32 val; if (vif) { @@ -589,13 +839,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, if (ext_phy && dev->mt76.phy2) mphy = dev->mt76.phy2; - fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; - fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; - - txwi[4] = 0; - txwi[5] = 0; - txwi[6] = 0; - if (beacon) { p_fmt = MT_TX_TYPE_FW; q_idx = MT_LMAC_BCN0; @@ -608,20 +851,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, mt7915_lmac_mapping(dev, skb_get_queue_mapping(skb)); } - if (ieee80211_is_action(fc) && - mgmt->u.action.category == WLAN_CATEGORY_BACK && - mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { - u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); - - txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA); - tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK; - } else if (ieee80211_is_back_req(hdr->frame_control)) { - struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr; - u16 control = le16_to_cpu(bar->control); - - tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control); - } - val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | FIELD_PREP(MT_TXD0_Q_IDX, q_idx); @@ -629,10 +858,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, val = MT_TXD1_LONG_FORMAT | FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | - FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | - FIELD_PREP(MT_TXD1_HDR_INFO, - ieee80211_get_hdrlen_from_skb(skb) / 2) | - FIELD_PREP(MT_TXD1_TID, tid) | FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) @@ -640,27 +865,31 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, txwi[1] = cpu_to_le32(val); - val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | - FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | - FIELD_PREP(MT_TXD2_MULTICAST, multicast); - if (key) { - if (multicast && ieee80211_is_robust_mgmt_frame(skb) && - key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { - val |= MT_TXD2_BIP; - txwi[3] = 0; - } else { - txwi[3] = cpu_to_le32(MT_TXD3_PROTECT_FRAME); - } - } else { - txwi[3] = 0; - } - txwi[2] = cpu_to_le32(val); + txwi[2] = 0; + + val = MT_TXD3_SW_POWER_MGMT | + FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); + if (key) + val |= MT_TXD3_PROTECT_FRAME; + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + val |= MT_TXD3_NO_ACK; - if (!ieee80211_is_data(fc) || multicast) { + txwi[3] = cpu_to_le32(val); + txwi[4] = 0; + txwi[5] = 0; + txwi[6] = 0; + txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; + + if (is_8023) + mt7915_mac_write_txwi_8023(dev, txwi, skb, wcid); + else + mt7915_mac_write_txwi_80211(dev, txwi, skb, key); + + if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) { u16 rate; /* hardware won't add HTC for mgmt/ctrl frame */ - txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE | MT_TXD2_HTC_VLD); + txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD); if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) rate = MT7915_5G_RATE_DEFAULT; @@ -673,35 +902,28 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); } - if (!ieee80211_is_beacon(fc)) - txwi[3] |= cpu_to_le32(MT_TXD3_SW_POWER_MGMT); - else - tx_count = 0x1f; - - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - txwi[3] |= cpu_to_le32(MT_TXD3_NO_ACK); - - val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | - FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); - if (wcid->amsdu) - val |= MT_TXD7_HW_AMSDU; - txwi[7] = cpu_to_le32(val); - - val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); - if (info->flags & IEEE80211_TX_CTL_INJECTED) { - seqno = le16_to_cpu(hdr->seq_ctrl); + if (mt76_testmode_enabled(&dev->mt76)) + mt7915_mac_write_txwi_tm(dev, mphy, txwi, skb); +} - if (ieee80211_is_back_req(hdr->frame_control)) { - struct ieee80211_bar *bar; +static void +mt7915_set_tx_blocked(struct mt7915_dev *dev, bool blocked) +{ + struct mt76_phy *mphy = &dev->mphy, *mphy2 = dev->mt76.phy2; + struct mt76_queue *q, *q2 = NULL; - bar = (struct ieee80211_bar *)skb->data; - seqno = le16_to_cpu(bar->start_seq_num); - } + q = mphy->q_tx[0]; + if (blocked == q->blocked) + return; - val |= MT_TXD3_SN_VALID | - FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); + q->blocked = blocked; + if (mphy2) { + q2 = mphy2->q_tx[0]; + q2->blocked = blocked; } - txwi[3] |= cpu_to_le32(val); + + if (!blocked) + mt76_worker_schedule(&dev->mt76.tx_worker); } int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -723,11 +945,11 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (!wcid) wcid = &dev->mt76.global_wcid; - cb->wcid = wcid->idx; - mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, false); + cb->wcid = wcid->idx; + txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE); for (i = 0; i < nbuf; i++) { txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); @@ -740,12 +962,13 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, tx_info->buf[1].skip_unmap = true; tx_info->nbuf = MT_CT_DMA_BUF_NUM; - txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD); + txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD | MT_CT_INFO_FROM_HOST); if (!key) txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); - if (ieee80211_is_mgmt(hdr->frame_control)) + if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && + ieee80211_is_mgmt(hdr->frame_control)) txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); if (vif) { @@ -759,12 +982,21 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, spin_lock_bh(&dev->token_lock); id = idr_alloc(&dev->token, t, 0, MT7915_TOKEN_SIZE, GFP_ATOMIC); + if (id >= 0) + dev->token_count++; + + if (dev->token_count >= MT7915_TOKEN_SIZE - MT7915_TOKEN_FREE_THR) + mt7915_set_tx_blocked(dev, true); spin_unlock_bh(&dev->token_lock); + if (id < 0) return id; txp->token = cpu_to_le16(id); - txp->rept_wds_wcid = 0xff; + if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) + txp->rept_wds_wcid = cpu_to_le16(wcid->idx); + else + txp->rept_wds_wcid = cpu_to_le16(0x3ff); tx_info->skb = DMA_DUMMY_DATA; return 0; @@ -795,17 +1027,19 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) ieee80211_start_tx_ba_session(sta, tid, 0); } -static inline void -mt7915_tx_status(struct ieee80211_sta *sta, struct ieee80211_hw *hw, - struct ieee80211_tx_info *info, struct sk_buff *skb) +static void +mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb, + struct ieee80211_sta *sta, u8 stat, + struct list_head *free_list) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_status status = { .sta = sta, .info = info, + .skb = skb, + .free_list = free_list, }; - - if (skb) - status.skb = skb; + struct ieee80211_hw *hw; if (sta) { struct mt7915_sta *msta; @@ -814,18 +1048,19 @@ mt7915_tx_status(struct ieee80211_sta *sta, struct ieee80211_hw *hw, status.rate = &msta->stats.tx_rate; } - /* use status_ext to report HE rate */ - ieee80211_tx_status_ext(hw, &status); -} + hw = mt76_tx_status_get_hw(mdev, skb); -static void -mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb, - struct ieee80211_sta *sta, u8 stat) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hw *hw; +#ifdef CONFIG_NL80211_TESTMODE + if (skb == mdev->test.tx_skb) { + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct ieee80211_vif *vif = phy->monitor_vif; + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - hw = mt76_tx_status_get_hw(mdev, skb); + mt76_tx_complete_skb(mdev, mvif->sta.wcid.idx, skb); + + return; + } +#endif if (info->flags & IEEE80211_TX_CTL_AMPDU) info->flags |= IEEE80211_TX_STAT_AMPDU; @@ -837,16 +1072,7 @@ mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb, info->flags |= IEEE80211_TX_STAT_ACK; info->status.tx_time = 0; - - if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { - mt7915_tx_status(sta, hw, info, skb); - return; - } - - if (sta || !(info->flags & IEEE80211_TX_CTL_NO_ACK)) - mt7915_tx_status(sta, hw, info, NULL); - - ieee80211_free_txskb(hw, skb); + ieee80211_tx_status_ext(hw, &status); } void mt7915_txp_skb_unmap(struct mt76_dev *dev, @@ -865,13 +1091,21 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) { struct mt7915_tx_free *free = (struct mt7915_tx_free *)skb->data; struct mt76_dev *mdev = &dev->mt76; + struct mt76_phy *mphy_ext = mdev->phy2; struct mt76_txwi_cache *txwi; struct ieee80211_sta *sta = NULL; + LIST_HEAD(free_list); + struct sk_buff *tmp; u8 i, count; + bool wake = false; /* clean DMA queues and unmap buffers first */ - mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false); - mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); + if (mphy_ext) { + mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false); + mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false); + } /* * TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE, @@ -908,6 +1142,7 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) if (list_empty(&msta->poll_list)) list_add_tail(&msta->poll_list, &dev->sta_poll_list); spin_unlock_bh(&dev->sta_poll_lock); + continue; } msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); @@ -915,6 +1150,11 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) spin_lock_bh(&dev->token_lock); txwi = idr_remove(&dev->token, msdu); + if (txwi) + dev->token_count--; + if (dev->token_count < MT7915_TOKEN_SIZE - MT7915_TOKEN_FREE_THR && + dev->mphy.q_tx[0]->blocked) + wake = true; spin_unlock_bh(&dev->token_lock); if (!txwi) @@ -937,16 +1177,29 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) atomic_cmpxchg(&wcid->non_aql_packets, pending, 0); } - mt7915_tx_complete_status(mdev, txwi->skb, sta, stat); + mt7915_tx_complete_status(mdev, txwi->skb, sta, stat, &free_list); txwi->skb = NULL; } mt76_put_txwi(mdev, txwi); } - dev_kfree_skb(skb); mt7915_mac_sta_poll(dev); + + if (wake) { + spin_lock_bh(&dev->token_lock); + mt7915_set_tx_blocked(dev, false); + spin_unlock_bh(&dev->token_lock); + } + mt76_worker_schedule(&dev->mt76.tx_worker); + + napi_consume_skb(skb, 1); + + list_for_each_entry_safe(skb, tmp, &free_list, list) { + skb_list_del_init(skb); + napi_consume_skb(skb, 1); + } } void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) @@ -979,7 +1232,8 @@ void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) wcid = rcu_dereference(dev->mt76.wcid[cb->wcid]); - mt7915_tx_complete_status(mdev, e->skb, wcid_to_sta(wcid), 0); + mt7915_tx_complete_status(mdev, e->skb, wcid_to_sta(wcid), 0, + NULL); } } @@ -1081,17 +1335,48 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); } -/* - * TODO: mib counters are read-clear and there're many HE functionalities need - * such info, hence firmware prepares a task to read the fields out to a shared - * structure. User should switch to use event format to avoid race condition. - */ +void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy) +{ + mt7915_l2_set(dev, MT_WF_PHY_RXTD12(ext_phy), + MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY | + MT_WF_PHY_RXTD12_IRPI_SW_CLR); + + mt7915_l2_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy), + FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5)); +} + +static u8 +mt7915_phy_get_nf(struct mt7915_phy *phy, int idx) +{ + static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 }; + struct mt7915_dev *dev = phy->dev; + u32 val, sum = 0, n = 0; + int nss, i; + + for (nss = 0; nss < hweight8(phy->chainmask); nss++) { + u32 reg = MT_WF_IRPI(nss + (idx << dev->dbdc_support)); + + for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { + val = mt7915_l2_rr(dev, reg); + sum += val * nf_power[i]; + n += val; + } + } + + if (!n) + return 0; + + return sum / n; +} + static void mt7915_phy_update_channel(struct mt76_phy *mphy, int idx) { struct mt7915_dev *dev = container_of(mphy->dev, struct mt7915_dev, mt76); + struct mt7915_phy *phy = (struct mt7915_phy *)mphy->priv; struct mt76_channel_state *state; u64 busy_time, tx_time, rx_time, obss_time; + int nf; busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), MT_MIB_SDR9_BUSY_MASK); @@ -1102,12 +1387,18 @@ mt7915_phy_update_channel(struct mt76_phy *mphy, int idx) obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx), MT_MIB_OBSSTIME_MASK); - /* TODO: state->noise */ + nf = mt7915_phy_get_nf(phy, idx); + if (!phy->noise) + phy->noise = nf << 4; + else if (nf) + phy->noise += nf - (phy->noise >> 4); + state = mphy->chan_state; state->cc_busy += busy_time; state->cc_tx += tx_time; state->cc_rx += rx_time + obss_time; state->cc_bss_rx += rx_time; + state->noise = -(phy->noise >> 4); } void mt7915_update_channel(struct mt76_dev *mdev) @@ -1162,8 +1453,10 @@ mt7915_update_beacons(struct mt7915_dev *dev) } static void -mt7915_dma_reset(struct mt7915_dev *dev) +mt7915_dma_reset(struct mt7915_phy *phy) { + struct mt7915_dev *dev = phy->dev; + struct mt76_phy *mphy_ext = dev->mt76.phy2; int i; mt76_clear(dev, MT_WFDMA0_GLO_CFG, @@ -1172,8 +1465,12 @@ mt7915_dma_reset(struct mt7915_dev *dev) MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN); usleep_range(1000, 2000); - for (i = 0; i < __MT_TXQ_MAX; i++) - mt76_queue_tx_cleanup(dev, i, true); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true); + for (i = 0; i < __MT_TXQ_MAX; i++) { + mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true); + if (mphy_ext) + mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true); + } mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); @@ -1229,7 +1526,7 @@ void mt7915_mac_reset_work(struct work_struct *work) mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { - mt7915_dma_reset(dev); + mt7915_dma_reset(&dev->phy); mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); @@ -1329,7 +1626,7 @@ mt7915_mac_sta_stats_work(struct mt7915_phy *phy) spin_unlock_bh(&dev->sta_poll_lock); /* use MT_TX_FREE_RATE to report Tx rate for further devices */ - mt7915_mcu_get_rate_info(dev, RATE_CTRL_RU_INFO, msta->wcid.idx); + mt7915_mcu_get_tx_rate(dev, RATE_CTRL_RU_INFO, msta->wcid.idx); spin_lock_bh(&dev->sta_poll_lock); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index c8bb5ea96c60..d420392b952d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -128,6 +128,11 @@ enum rx_pkt_type { #define MT_CRXV_HE_BEAM_CHNG BIT(13) #define MT_CRXV_HE_DOPPLER BIT(16) +#define MT_CRXV_SNR GENMASK(18, 13) +#define MT_CRXV_FOE_LO GENMASK(31, 19) +#define MT_CRXV_FOE_HI GENMASK(6, 0) +#define MT_CRXV_FOE_SHIFT 13 + enum tx_header_format { MT_HDR_FORMAT_802_3, MT_HDR_FORMAT_CMD, @@ -160,6 +165,7 @@ enum tx_mcu_port_q_idx { #define MT_CT_INFO_MGMT_FRAME BIT(2) #define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) #define MT_CT_INFO_HSR2_TX BIT(4) +#define MT_CT_INFO_FROM_HOST BIT(7) #define MT_TXD_SIZE (8 * 4) @@ -176,6 +182,7 @@ enum tx_mcu_port_q_idx { #define MT_TXD1_HDR_PAD GENMASK(19, 18) #define MT_TXD1_HDR_FORMAT GENMASK(17, 16) #define MT_TXD1_HDR_INFO GENMASK(15, 11) +#define MT_TXD1_ETH_802_3 BIT(15) #define MT_TXD1_VTA BIT(10) #define MT_TXD1_WLAN_IDX GENMASK(9, 0) @@ -229,7 +236,7 @@ enum tx_mcu_port_q_idx { #define MT_TXD6_ANT_ID GENMASK(7, 4) #define MT_TXD6_DYN_BW BIT(3) #define MT_TXD6_FIXED_BW BIT(2) -#define MT_TXD6_BW GENMASK(2, 0) +#define MT_TXD6_BW GENMASK(1, 0) #define MT_TXD7_TXD_LEN GENMASK(31, 30) #define MT_TXD7_UDP_TCP_SUM BIT(29) @@ -246,7 +253,9 @@ enum tx_mcu_port_q_idx { #define MT_TX_RATE_STBC BIT(13) #define MT_TX_RATE_NSS GENMASK(12, 10) #define MT_TX_RATE_MODE GENMASK(9, 6) -#define MT_TX_RATE_IDX GENMASK(5, 0) +#define MT_TX_RATE_SU_EXT_TONE BIT(5) +#define MT_TX_RATE_DCM BIT(4) +#define MT_TX_RATE_IDX GENMASK(3, 0) #define MT_TXP_MAX_BUF_NUM 6 @@ -254,8 +263,7 @@ struct mt7915_txp { __le16 flags; __le16 token; u8 bss_idx; - u8 rept_wds_wcid; - u8 rsv; + __le16 rept_wds_wcid; u8 nbuf; __le32 buf[MT_TXP_MAX_BUF_NUM]; __le16 len[MT_TXP_MAX_BUF_NUM]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index c48158392057..0c82aa2ef219 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -34,21 +34,24 @@ static int mt7915_start(struct ieee80211_hw *hw) mt7915_mcu_set_pm(dev, 0, 0); mt7915_mcu_set_mac(dev, 0, true, false); mt7915_mcu_set_scs(dev, 0, true); + mt7915_mac_enable_nf(dev, 0); } if (phy != &dev->phy) { mt7915_mcu_set_pm(dev, 1, 0); mt7915_mcu_set_mac(dev, 1, true, false); mt7915_mcu_set_scs(dev, 1, true); + mt7915_mac_enable_nf(dev, 1); } - mt7915_mcu_set_sku_en(phy, true); + mt7915_mcu_set_sku_en(phy, !mt76_testmode_enabled(&dev->mt76)); mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); set_bit(MT76_STATE_RUNNING, &phy->mt76->state); - ieee80211_queue_delayed_work(hw, &phy->mac_work, - MT7915_WATCHDOG_TIME); + if (!mt76_testmode_enabled(&dev->mt76)) + ieee80211_queue_delayed_work(hw, &phy->mac_work, + MT7915_WATCHDOG_TIME); if (!running) mt7915_mac_reset_counters(phy); @@ -67,6 +70,8 @@ static void mt7915_stop(struct ieee80211_hw *hw) mutex_lock(&dev->mt76.mutex); + mt76_testmode_reset(&dev->mt76, true); + clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); if (phy != &dev->phy) { @@ -82,28 +87,51 @@ static void mt7915_stop(struct ieee80211_hw *hw) mutex_unlock(&dev->mt76.mutex); } -static int get_omac_idx(enum nl80211_iftype type, u32 mask) +static inline int get_free_idx(u32 mask, u8 start, u8 end) +{ + return ffs(~mask & GENMASK(end, start)); +} + +static int get_omac_idx(enum nl80211_iftype type, u64 mask) { int i; switch (type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + /* prefer hw bssid slot 1-3 */ + i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3); + if (i) + return i - 1; + + if (type != NL80211_IFTYPE_STATION) + break; + + /* next, try to find a free repeater entry for the sta */ + i = get_free_idx(mask >> REPEATER_BSSID_START, 0, + REPEATER_BSSID_MAX - REPEATER_BSSID_START); + if (i) + return i + 32 - 1; + + i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); + if (i) + return i - 1; + + if (~mask & BIT(HW_BSSID_0)) + return HW_BSSID_0; + + break; case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP: /* ap uses hw bssid 0 and ext bssid */ if (~mask & BIT(HW_BSSID_0)) return HW_BSSID_0; - for (i = EXT_BSSID_1; i < EXT_BSSID_END; i++) - if (~mask & BIT(i)) - return i; - break; - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - /* station uses hw bssid other than 0 */ - for (i = HW_BSSID_1; i < HW_BSSID_MAX; i++) - if (~mask & BIT(i)) - return i; + i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); + if (i) + return i - 1; + break; default: WARN_ON(1); @@ -125,6 +153,12 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, mutex_lock(&dev->mt76.mutex); + mt76_testmode_reset(&dev->mt76, true); + + if (vif->type == NL80211_IFTYPE_MONITOR && + is_zero_ether_addr(vif->addr)) + phy->monitor_vif = vif; + mvif->idx = ffs(~phy->mt76->vif_mask) - 1; if (mvif->idx >= MT7915_MAX_INTERFACES) { ret = -ENOSPC; @@ -146,12 +180,12 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, else mvif->wmm_idx = mvif->idx % MT7915_MAX_WMM_SETS; - ret = mt7915_mcu_add_dev_info(dev, vif, true); + ret = mt7915_mcu_add_dev_info(phy, vif, true); if (ret) goto out; phy->mt76->vif_mask |= BIT(mvif->idx); - phy->omac_mask |= BIT(mvif->omac_idx); + phy->omac_mask |= BIT_ULL(mvif->omac_idx); idx = MT7915_WTBL_RESERVED - mvif->idx; @@ -171,6 +205,11 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, mtxq->wcid = &mvif->sta.wcid; } + if (vif->type != NL80211_IFTYPE_AP && + (!mvif->omac_idx || mvif->omac_idx > 3)) + vif->offload_flags = 0; + vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; + out: mutex_unlock(&dev->mt76.mutex); @@ -188,13 +227,20 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, /* TODO: disable beacon for the bss */ - mt7915_mcu_add_dev_info(dev, vif, false); + mutex_lock(&dev->mt76.mutex); + mt76_testmode_reset(&dev->mt76, true); + mutex_unlock(&dev->mt76.mutex); + + if (vif == phy->monitor_vif) + phy->monitor_vif = NULL; + + mt7915_mcu_add_dev_info(phy, vif, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); mutex_lock(&dev->mt76.mutex); phy->mt76->vif_mask &= ~BIT(mvif->idx); - phy->omac_mask &= ~BIT(mvif->omac_idx); + phy->omac_mask &= ~BIT_ULL(mvif->omac_idx); mutex_unlock(&dev->mt76.mutex); spin_lock_bh(&dev->sta_poll_lock); @@ -222,7 +268,7 @@ static void mt7915_init_dfs_state(struct mt7915_phy *phy) phy->dfs_state = -1; } -static int mt7915_set_channel(struct mt7915_phy *phy) +int mt7915_set_channel(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; int ret; @@ -251,8 +297,10 @@ out: mutex_unlock(&dev->mt76.mutex); mt76_txq_schedule_all(phy->mt76); - ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work, - MT7915_WATCHDOG_TIME); + + if (!mt76_testmode_enabled(&dev->mt76)) + ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work, + MT7915_WATCHDOG_TIME); return ret; } @@ -283,8 +331,6 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case WLAN_CIPHER_SUITE_AES_CMAC: key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; break; - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP_256: @@ -292,6 +338,8 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_SMS4: break; + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: default: return -EOPNOTSUPP; } @@ -316,6 +364,13 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed) int ret; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { +#ifdef CONFIG_NL80211_TESTMODE + if (dev->mt76.test.state != MT76_TM_STATE_OFF) { + mutex_lock(&dev->mt76.mutex); + mt76_testmode_reset(&dev->mt76, false); + mutex_unlock(&dev->mt76.mutex); + } +#endif ieee80211_stop_queues(hw); ret = mt7915_set_channel(phy); if (ret) @@ -332,11 +387,16 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&dev->mt76.mutex); if (changed & IEEE80211_CONF_CHANGE_MONITOR) { - if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) + bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); + + if (!enabled) phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; else phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN, + enabled); + mt76_testmode_reset(&dev->mt76, true); mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); } @@ -764,9 +824,13 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct station_info *sinfo) { + struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_sta_stats *stats = &msta->stats; + if (mt7915_mcu_get_rx_rate(phy, vif, sta, &sinfo->rxrate) == 0) + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); + if (!stats->tx_rate.legacy && !stats->tx_rate.flags) return; @@ -802,6 +866,22 @@ mt7915_sta_rc_update(struct ieee80211_hw *hw, ieee80211_queue_work(hw, &dev->rc_work); } +static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + bool enabled) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + + if (enabled) + set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); + else + clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); + + mt7915_mcu_sta_update_hdr_trans(dev, vif, sta); +} + const struct ieee80211_ops mt7915_ops = { .tx = mt7915_tx, .start = mt7915_start, @@ -833,6 +913,9 @@ const struct ieee80211_ops mt7915_ops = { .set_antenna = mt7915_set_antenna, .set_coverage_class = mt7915_set_coverage_class, .sta_statistics = mt7915_sta_statistics, + .sta_set_4addr = mt7915_sta_set_4addr, + CFG80211_TESTMODE_CMD(mt76_testmode_cmd) + CFG80211_TESTMODE_DUMP(mt76_testmode_dump) #ifdef CONFIG_MAC80211_DEBUGFS .sta_add_debugfs = mt7915_sta_add_debugfs, #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index a3ccc1785661..5fdd1a6d32ee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -215,32 +215,71 @@ mt7915_mcu_get_sta_nss(u16 mcs_map) return nss - 1; } -static int __mt7915_mcu_msg_send(struct mt7915_dev *dev, struct sk_buff *skb, - int cmd, int *wait_seq) +static int +mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd, + struct sk_buff *skb, int seq) { + struct mt7915_mcu_rxd *rxd; + int ret = 0; + + if (!skb) { + dev_err(mdev->dev, "Message %d (seq %d) timeout\n", + cmd, seq); + return -ETIMEDOUT; + } + + rxd = (struct mt7915_mcu_rxd *)skb->data; + if (seq != rxd->seq) + return -EAGAIN; + + switch (cmd) { + case -MCU_CMD_PATCH_SEM_CONTROL: + skb_pull(skb, sizeof(*rxd) - 4); + ret = *skb->data; + break; + case MCU_EXT_CMD_THERMAL_CTRL: + skb_pull(skb, sizeof(*rxd) + 4); + ret = le32_to_cpu(*(__le32 *)skb->data); + break; + default: + skb_pull(skb, sizeof(struct mt7915_mcu_rxd)); + break; + } + + return ret; +} + +static int +mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, int *wait_seq) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); struct mt7915_mcu_txd *mcu_txd; u8 seq, pkt_fmt, qidx; enum mt76_txq_id txq; __le32 *txd; u32 val; + /* TODO: make dynamic based on msg type */ + mdev->mcu.timeout = 20 * HZ; + seq = ++dev->mt76.mcu.msg_seq & 0xf; if (!seq) seq = ++dev->mt76.mcu.msg_seq & 0xf; if (cmd == -MCU_CMD_FW_SCATTER) { - txq = MT_TXQ_FWDL; + txq = MT_MCUQ_FWDL; goto exit; } mcu_txd = (struct mt7915_mcu_txd *)skb_push(skb, sizeof(*mcu_txd)); if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) { - txq = MT_TXQ_MCU_WA; + txq = MT_MCUQ_WA; qidx = MT_TX_MCU_PORT_RX_Q0; pkt_fmt = MT_TX_TYPE_CMD; } else { - txq = MT_TXQ_MCU; + txq = MT_MCUQ_WM; qidx = MT_TX_MCU_PORT_RX_Q0; pkt_fmt = MT_TX_TYPE_CMD; } @@ -276,7 +315,10 @@ static int __mt7915_mcu_msg_send(struct mt7915_dev *dev, struct sk_buff *skb, mcu_txd->set_query = MCU_Q_SET; } - mcu_txd->s2d_index = MCU_S2D_H2N; + if (cmd == MCU_EXT_CMD_MWDS_SUPPORT) + mcu_txd->s2d_index = MCU_S2D_H2C; + else + mcu_txd->s2d_index = MCU_S2D_H2N; WARN_ON(cmd == MCU_EXT_CMD_EFUSE_ACCESS && mcu_txd->set_query != MCU_Q_QUERY); @@ -284,116 +326,7 @@ exit: if (wait_seq) *wait_seq = seq; - return mt76_tx_queue_skb_raw(dev, txq, skb, 0); -} - -static int -mt7915_mcu_parse_eeprom(struct mt7915_dev *dev, struct sk_buff *skb) -{ - struct mt7915_mcu_eeprom_info *res; - u8 *buf; - - if (!skb) - return -EINVAL; - - skb_pull(skb, sizeof(struct mt7915_mcu_rxd)); - - res = (struct mt7915_mcu_eeprom_info *)skb->data; - buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); - memcpy(buf, res->data, 16); - - return 0; -} - -static int -mt7915_mcu_parse_response(struct mt7915_dev *dev, int cmd, - struct sk_buff *skb, int seq) -{ - struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; - int ret = 0; - - if (seq != rxd->seq) { - ret = -EAGAIN; - goto out; - } - - switch (cmd) { - case -MCU_CMD_PATCH_SEM_CONTROL: - skb_pull(skb, sizeof(*rxd) - 4); - ret = *skb->data; - break; - case MCU_EXT_CMD_THERMAL_CTRL: - skb_pull(skb, sizeof(*rxd) + 4); - ret = le32_to_cpu(*(__le32 *)skb->data); - break; - case MCU_EXT_CMD_EFUSE_ACCESS: - ret = mt7915_mcu_parse_eeprom(dev, skb); - break; - default: - break; - } -out: - dev_kfree_skb(skb); - - return ret; -} - -static int -mt7915_mcu_wait_response(struct mt7915_dev *dev, int cmd, int seq) -{ - unsigned long expires = jiffies + 20 * HZ; - struct sk_buff *skb; - int ret = 0; - - while (true) { - skb = mt76_mcu_get_response(&dev->mt76, expires); - if (!skb) { - dev_err(dev->mt76.dev, "Message %d (seq %d) timeout\n", - cmd, seq); - return -ETIMEDOUT; - } - - ret = mt7915_mcu_parse_response(dev, cmd, skb, seq); - if (ret != -EAGAIN) - break; - } - - return ret; -} - -static int -mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, - int cmd, bool wait_resp) -{ - struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); - int ret, seq; - - mutex_lock(&mdev->mcu.mutex); - - ret = __mt7915_mcu_msg_send(dev, skb, cmd, &seq); - if (ret) - goto out; - - if (wait_resp) - ret = mt7915_mcu_wait_response(dev, cmd, seq); - -out: - mutex_unlock(&mdev->mcu.mutex); - - return ret; -} - -static int -mt7915_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, - int len, bool wait_resp) -{ - struct sk_buff *skb; - - skb = mt76_mcu_msg_alloc(mdev, data, len); - if (!skb) - return -ENOMEM; - - return __mt76_mcu_skb_send_msg(mdev, skb, cmd, wait_resp); + return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0); } static void @@ -419,8 +352,8 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) } static void -mt7915_mcu_tx_rate_cal(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra, - struct rate_info *rate, u16 r) +mt7915_mcu_tx_rate_parse(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra, + struct rate_info *rate, u16 r) { struct ieee80211_supported_band *sband; u16 ru_idx = le16_to_cpu(ra->ru_idx); @@ -532,11 +465,11 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb) mphy = dev->mt76.phy2; /* current rate */ - mt7915_mcu_tx_rate_cal(mphy, ra, &rate, curr); + mt7915_mcu_tx_rate_parse(mphy, ra, &rate, curr); stats->tx_rate = rate; /* probing rate */ - mt7915_mcu_tx_rate_cal(mphy, ra, &prob_rate, probe); + mt7915_mcu_tx_rate_parse(mphy, ra, &prob_rate, probe); stats->prob_rate = prob_rate; if (attempts) { @@ -1005,18 +938,42 @@ mt7915_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7915_phy *phy) } } -static void -mt7915_mcu_bss_sync_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +static int +mt7915_mcu_muar_config(struct mt7915_phy *phy, struct ieee80211_vif *vif, + bool bssid, bool enable) { - struct bss_info_sync_mode *sync; - struct tlv *tlv; + struct mt7915_dev *dev = phy->dev; + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + u32 idx = mvif->omac_idx - REPEATER_BSSID_START; + u32 mask = phy->omac_mask >> 32 & ~BIT(idx); + const u8 *addr = vif->addr; + struct { + u8 mode; + u8 force_clear; + u8 clear_bitmap[8]; + u8 entry_count; + u8 write; + u8 band; - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_SYNC_MODE, sizeof(*sync)); + u8 index; + u8 bssid; + u8 addr[ETH_ALEN]; + } __packed req = { + .mode = !!mask || enable, + .entry_count = 1, + .write = 1, + .band = phy != &dev->phy, + .index = idx * 2 + bssid, + }; - sync = (struct bss_info_sync_mode *)tlv; - sync->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); - sync->dtim_period = vif->bss_conf.dtim_period; - sync->enable = true; + if (bssid) + addr = vif->bss_conf.bssid; + + if (enable) + ether_addr_copy(req.addr, addr); + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MUAR_UPDATE, &req, + sizeof(req), true); } int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, @@ -1025,6 +982,9 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct sk_buff *skb; + if (mvif->omac_idx >= REPEATER_BSSID_START) + mt7915_mcu_muar_config(phy, vif, true, enable); + skb = mt7915_mcu_alloc_sta_req(phy->dev, mvif, NULL, MT7915_BSS_UPDATE_MAX_SIZE); if (IS_ERR(skb)) @@ -1045,14 +1005,13 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, if (vif->bss_conf.he_support) mt7915_mcu_bss_he_tlv(skb, vif, phy); - if (mvif->omac_idx > HW_BSSID_MAX) + if (mvif->omac_idx >= EXT_BSSID_START && + mvif->omac_idx < REPEATER_BSSID_START) mt7915_mcu_bss_ext_tlv(skb, mvif); - else - mt7915_mcu_bss_sync_tlv(skb, vif); } - return __mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, - MCU_EXT_CMD_BSS_INFO_UPDATE, true); + return mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, + MCU_EXT_CMD_BSS_INFO_UPDATE, true); } /** starec & wtbl **/ @@ -1133,8 +1092,8 @@ int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif, if (ret) return ret; - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); } static void @@ -1213,8 +1172,8 @@ mt7915_mcu_sta_ba(struct mt7915_dev *dev, &skb); mt7915_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); - ret = __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); if (ret) return ret; @@ -1225,8 +1184,8 @@ mt7915_mcu_sta_ba(struct mt7915_dev *dev, mt7915_mcu_sta_ba_tlv(skb, params, enable, tx); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); } int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, @@ -1508,9 +1467,7 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) muru = (struct sta_rec_muru *)tlv; muru->cfg.ofdma_dl_en = true; - muru->cfg.ofdma_ul_en = true; muru->cfg.mimo_dl_en = true; - muru->cfg.mimo_ul_en = true; muru->ofdma_dl.punc_pream_rx = HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]); @@ -1563,8 +1520,8 @@ mt7915_mcu_add_mu(struct mt7915_dev *dev, struct ieee80211_vif *vif, /* starec muru */ mt7915_mcu_sta_muru_tlv(skb, sta); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); } static void @@ -1662,7 +1619,7 @@ mt7915_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), wtbl_tlv, sta_wtbl); ht = (struct wtbl_ht *)tlv; - ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; + ht->ldpc = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING); ht->af = sta->ht_cap.ampdu_factor; ht->mm = sta->ht_cap.ampdu_density; ht->ht = true; @@ -1676,7 +1633,7 @@ mt7915_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_VHT, sizeof(*vht), wtbl_tlv, sta_wtbl); vht = (struct wtbl_vht *)tlv; - vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC, + vht->ldpc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); vht->vht = true; af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, @@ -1688,6 +1645,53 @@ mt7915_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_tlv); } +static void +mt7915_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + void *sta_wtbl, void *wtbl_tlv) +{ + struct mt7915_sta *msta; + struct wtbl_hdr_trans *htr = NULL; + struct tlv *tlv; + + tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_HDR_TRANS, sizeof(*htr), + wtbl_tlv, sta_wtbl); + htr = (struct wtbl_hdr_trans *)tlv; + htr->no_rx_trans = true; + if (vif->type == NL80211_IFTYPE_STATION) + htr->to_ds = true; + else + htr->from_ds = true; + + if (!sta) + return; + + msta = (struct mt7915_sta *)sta->drv_priv; + if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags)) { + htr->to_ds = true; + htr->from_ds = true; + } +} + +int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct wtbl_req_hdr *wtbl_hdr; + struct sk_buff *skb; + + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, MT7915_WTBL_UPDATE_MAX_SIZE); + if (!skb) + return -ENOMEM; + + wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, NULL, &skb); + mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, + true); +} + int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { @@ -1708,8 +1712,8 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, &skb); mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); } static void @@ -2010,8 +2014,8 @@ mt7915_mcu_add_txbf(struct mt7915_dev *dev, struct ieee80211_vif *vif, mt7915_mcu_sta_bfer_tlv(skb, sta, vif, phy, enable); - r = __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + r = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); if (r) return r; } @@ -2026,8 +2030,8 @@ mt7915_mcu_add_txbf(struct mt7915_dev *dev, struct ieee80211_vif *vif, mt7915_mcu_sta_bfee_tlv(skb, sta, phy); - r = __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + r = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); if (r) return r; } @@ -2194,8 +2198,8 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta); - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); } static int @@ -2217,11 +2221,11 @@ mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif, .action = cpu_to_le32(MT_STA_BSS_GROUP), .wlan_idx_lo = to_wcid_lo(msta->wcid.idx), .wlan_idx_hi = to_wcid_hi(msta->wcid.idx), - .val = cpu_to_le32(mvif->idx), + .val = cpu_to_le32(mvif->idx % 16), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_DRR_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_DRR_CTRL, &req, + sizeof(req), true); } int mt7915_mcu_add_sta_adv(struct mt7915_dev *dev, struct ieee80211_vif *vif, @@ -2277,12 +2281,13 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, sta_wtbl, &skb); if (enable) { mt7915_mcu_wtbl_generic_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); + mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); if (sta) mt7915_mcu_wtbl_ht_tlv(skb, sta, sta_wtbl, wtbl_hdr); } - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); } int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev, @@ -2327,13 +2332,14 @@ int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev, ra->phy.sgi = ra->phy.mcs * 15; out: - return __mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD_STA_REC_UPDATE, true); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); } -int mt7915_mcu_add_dev_info(struct mt7915_dev *dev, +int mt7915_mcu_add_dev_info(struct mt7915_phy *phy, struct ieee80211_vif *vif, bool enable) { + struct mt7915_dev *dev = phy->dev; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct { struct req_hdr { @@ -2365,9 +2371,12 @@ int mt7915_mcu_add_dev_info(struct mt7915_dev *dev, }, }; + if (mvif->omac_idx >= REPEATER_BSSID_START) + return mt7915_mcu_muar_config(phy, vif, false, enable); + 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); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, + &data, sizeof(data), true); } static void @@ -2458,30 +2467,8 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, mt7915_mcu_beacon_cont(dev, rskb, skb, bcn, &offs); dev_kfree_skb(skb); - return __mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, - MCU_EXT_CMD_BSS_INFO_UPDATE, true); -} - -static int mt7915_mcu_send_firmware(struct mt7915_dev *dev, const void *data, - int len) -{ - int ret = 0, cur_len; - - while (len > 0) { - cur_len = min_t(int, 4096 - sizeof(struct mt7915_mcu_txd), - len); - - ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, - data, cur_len, false); - if (ret) - break; - - data += cur_len; - len -= cur_len; - mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); - } - - return ret; + return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, + MCU_EXT_CMD_BSS_INFO_UPDATE, true); } static int mt7915_mcu_start_firmware(struct mt7915_dev *dev, u32 addr, @@ -2495,8 +2482,8 @@ static int mt7915_mcu_start_firmware(struct mt7915_dev *dev, u32 addr, .addr = cpu_to_le32(addr), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, &req, + sizeof(req), true); } static int mt7915_mcu_restart(struct mt76_dev *dev) @@ -2508,8 +2495,8 @@ static int mt7915_mcu_restart(struct mt76_dev *dev) .power_mode = 1, }; - return __mt76_mcu_send_msg(dev, -MCU_CMD_NIC_POWER_CTRL, &req, - sizeof(req), false); + return mt76_mcu_send_msg(dev, -MCU_CMD_NIC_POWER_CTRL, &req, + sizeof(req), false); } static int mt7915_mcu_patch_sem_ctrl(struct mt7915_dev *dev, bool get) @@ -2520,8 +2507,8 @@ static int mt7915_mcu_patch_sem_ctrl(struct mt7915_dev *dev, bool get) .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_SEM_CONTROL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_SEM_CONTROL, &req, + sizeof(req), true); } static int mt7915_mcu_start_patch(struct mt7915_dev *dev) @@ -2533,8 +2520,8 @@ static int mt7915_mcu_start_patch(struct mt7915_dev *dev) .check_crc = 0, }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_FINISH_REQ, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_FINISH_REQ, &req, + sizeof(req), true); } static int mt7915_driver_own(struct mt7915_dev *dev) @@ -2570,7 +2557,7 @@ static int mt7915_mcu_init_download(struct mt7915_dev *dev, u32 addr, else attr = -MCU_CMD_TARGET_ADDRESS_LEN_REQ; - return __mt76_mcu_send_msg(&dev->mt76, attr, &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, attr, &req, sizeof(req), true); } static int mt7915_load_patch(struct mt7915_dev *dev) @@ -2629,7 +2616,8 @@ static int mt7915_load_patch(struct mt7915_dev *dev) goto out; } - ret = mt7915_mcu_send_firmware(dev, dl, len); + ret = mt76_mcu_send_firmware(&dev->mt76, -MCU_CMD_FW_SCATTER, + dl, len); if (ret) { dev_err(dev->mt76.dev, "Failed to send patch\n"); goto out; @@ -2697,7 +2685,8 @@ mt7915_mcu_send_ram_firmware(struct mt7915_dev *dev, return err; } - err = mt7915_mcu_send_firmware(dev, data + offset, len); + err = mt76_mcu_send_firmware(&dev->mt76, -MCU_CMD_FW_SCATTER, + data + offset, len); if (err) { dev_err(dev->mt76.dev, "Failed to send firmware.\n"); return err; @@ -2810,7 +2799,7 @@ static int mt7915_load_firmware(struct mt7915_dev *dev) return -EIO; } - mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false); dev_dbg(dev->mt76.dev, "Firmware init done\n"); @@ -2826,8 +2815,8 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl) .ctrl_val = ctrl }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, - &data, sizeof(data), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, &data, + sizeof(data), true); } int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level) @@ -2835,7 +2824,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level) struct { u8 ver; u8 pad; - u16 len; + __le16 len; u8 level; u8 rsv[3]; __le32 module_idx; @@ -2844,8 +2833,21 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level) .level = level, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_DBG_CTRL, - &data, sizeof(data), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_DBG_CTRL, &data, + sizeof(data), false); +} + +static int mt7915_mcu_set_mwds(struct mt7915_dev *dev, bool enabled) +{ + struct { + u8 enable; + u8 _rsv[3]; + } __packed req = { + .enable = enabled + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MWDS_SUPPORT, &req, + sizeof(req), false); } int mt7915_mcu_init(struct mt7915_dev *dev) @@ -2853,12 +2855,12 @@ int mt7915_mcu_init(struct mt7915_dev *dev) static const struct mt76_mcu_ops mt7915_mcu_ops = { .headroom = sizeof(struct mt7915_mcu_txd), .mcu_skb_send_msg = mt7915_mcu_send_message, - .mcu_send_msg = mt7915_mcu_msg_send, + .mcu_parse_response = mt7915_mcu_parse_response, .mcu_restart = mt7915_mcu_restart, }; int ret; - dev->mt76.mcu_ops = &mt7915_mcu_ops, + dev->mt76.mcu_ops = &mt7915_mcu_ops; ret = mt7915_driver_own(dev); if (ret) @@ -2870,6 +2872,7 @@ int mt7915_mcu_init(struct mt7915_dev *dev) set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); mt7915_mcu_fw_log_2_host(dev, 0); + mt7915_mcu_set_mwds(dev, 1); return 0; } @@ -2916,13 +2919,13 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, }; int ret; - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS, - &req_trans, sizeof(req_trans), false); + ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS, + &req_trans, sizeof(req_trans), false); if (ret) return ret; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, - &req_mac, sizeof(req_mac), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, + &req_mac, sizeof(req_mac), true); } int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable) @@ -2937,8 +2940,8 @@ int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable) .enable = enable + 1, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SCS_CTRL, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SCS_CTRL, &req, + sizeof(req), false); } int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val) @@ -2957,8 +2960,8 @@ int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val) .pkt_thresh = cpu_to_le32(0x2), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, &req, + sizeof(req), true); } int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif) @@ -3011,8 +3014,8 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif) else e->cw_max = cpu_to_le16(10); } - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, &req, + sizeof(req), true); } int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter) @@ -3042,8 +3045,8 @@ int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter) .band_idx = band, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, &req, + sizeof(req), true); } int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, @@ -3063,57 +3066,106 @@ int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, .val = val, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, &req, + sizeof(req), true); } int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val) { struct { - u32 tag; - u16 min_lpn; + __le32 tag; + __le16 min_lpn; u8 rsv[2]; } __packed req = { - .tag = 0x1, - .min_lpn = val, + .tag = cpu_to_le32(0x1), + .min_lpn = cpu_to_le16(val), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, + sizeof(req), true); } int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev, const struct mt7915_dfs_pulse *pulse) { struct { - u32 tag; - struct mt7915_dfs_pulse pulse; + __le32 tag; + + __le32 max_width; /* us */ + __le32 max_pwr; /* dbm */ + __le32 min_pwr; /* dbm */ + __le32 min_stgr_pri; /* us */ + __le32 max_stgr_pri; /* us */ + __le32 min_cr_pri; /* us */ + __le32 max_cr_pri; /* us */ } __packed req = { - .tag = 0x3, + .tag = cpu_to_le32(0x3), + +#define __req_field(field) .field = cpu_to_le32(pulse->field) + __req_field(max_width), + __req_field(max_pwr), + __req_field(min_pwr), + __req_field(min_stgr_pri), + __req_field(max_stgr_pri), + __req_field(min_cr_pri), + __req_field(max_cr_pri), +#undef __req_field }; - memcpy(&req.pulse, pulse, sizeof(*pulse)); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, + sizeof(req), true); } int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index, const struct mt7915_dfs_pattern *pattern) { struct { - u32 tag; - u16 radar_type; - struct mt7915_dfs_pattern pattern; + __le32 tag; + __le16 radar_type; + + u8 enb; + u8 stgr; + u8 min_crpn; + u8 max_crpn; + u8 min_crpr; + u8 min_pw; + u32 min_pri; + u32 max_pri; + u8 max_pw; + u8 min_crbn; + u8 max_crbn; + u8 min_stgpn; + u8 max_stgpn; + u8 min_stgpr; + u8 rsv[2]; + u32 min_stgpr_diff; } __packed req = { - .tag = 0x2, - .radar_type = index, + .tag = cpu_to_le32(0x2), + .radar_type = cpu_to_le16(index), + +#define __req_field_u8(field) .field = pattern->field +#define __req_field_u32(field) .field = cpu_to_le32(pattern->field) + __req_field_u8(enb), + __req_field_u8(stgr), + __req_field_u8(min_crpn), + __req_field_u8(max_crpn), + __req_field_u8(min_crpr), + __req_field_u8(min_pw), + __req_field_u32(min_pri), + __req_field_u32(max_pri), + __req_field_u8(max_pw), + __req_field_u8(min_crbn), + __req_field_u8(max_crbn), + __req_field_u8(min_stgpn), + __req_field_u8(max_stgpn), + __req_field_u8(min_stgpr), + __req_field_u32(min_stgpr_diff), +#undef __req_field_u8 +#undef __req_field_u32 }; - memcpy(&req.pattern, pattern, sizeof(*pattern)); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, + sizeof(req), true); } int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) @@ -3143,11 +3195,20 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) .center_ch = ieee80211_frequency_to_channel(freq1), .bw = mt7915_mcu_chan_bw(chandef), .tx_streams_num = hweight8(phy->mt76->antenna_mask), - .rx_streams = phy->chainmask, + .rx_streams = phy->mt76->antenna_mask, .band_idx = phy != &dev->phy, .channel_band = chandef->chan->band, }; +#ifdef CONFIG_NL80211_TESTMODE + if (dev->mt76.test.tx_antenna_mask && + (dev->mt76.test.state == MT76_TM_STATE_TX_FRAMES || + dev->mt76.test.state == MT76_TM_STATE_RX_FRAMES)) { + req.tx_streams_num = fls(dev->mt76.test.tx_antenna_mask); + req.rx_streams = dev->mt76.test.tx_antenna_mask; + } +#endif + if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && @@ -3165,7 +3226,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) req.center_ch2 = ieee80211_frequency_to_channel(freq2); } - return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } int mt7915_mcu_set_eeprom(struct mt7915_dev *dev) @@ -3179,8 +3240,8 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev) .format = EE_FORMAT_WHOLE, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + &req, sizeof(req), true); } int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset) @@ -3188,9 +3249,22 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset) struct mt7915_mcu_eeprom_info req = { .addr = cpu_to_le32(round_down(offset, 16)), }; + struct mt7915_mcu_eeprom_info *res; + struct sk_buff *skb; + int ret; + u8 *buf; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_ACCESS, &req, + sizeof(req), true, &skb); + if (ret) + return ret; + + res = (struct mt7915_mcu_eeprom_info *)skb->data; + buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); + memcpy(buf, res->data, 16); + dev_kfree_skb(skb); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_ACCESS, &req, - sizeof(req), true); + return 0; } int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index) @@ -3205,11 +3279,11 @@ int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index) .action = index, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_THERMAL_CTRL, &req, - sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_THERMAL_CTRL, &req, + sizeof(req), true); } -int mt7915_mcu_get_rate_info(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx) +int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx) { struct { __le32 cmd; @@ -3223,8 +3297,8 @@ int mt7915_mcu_get_rate_info(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx) .dump_group = cpu_to_le16(1), }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RATE_CTRL, &req, - sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RATE_CTRL, &req, + sizeof(req), false); } int mt7915_mcu_set_sku(struct mt7915_phy *phy) @@ -3251,9 +3325,31 @@ int mt7915_mcu_set_sku(struct mt7915_phy *phy) for (i = 0; i < MT7915_SKU_RATE_NUM; i++) req.val[i] = hw->conf.power_level * 2 + delta[i]; - return __mt76_mcu_send_msg(&dev->mt76, - MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, + sizeof(req), true); +} + +int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, + u8 en) +{ + struct { + u8 test_mode_en; + u8 param_idx; + u8 _rsv[2]; + + u8 enable; + u8 _rsv2[3]; + + u8 pad[8]; + } __packed req = { + .test_mode_en = test_mode, + .param_idx = param, + .enable = en, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, + sizeof(req), false); } int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable) @@ -3270,9 +3366,9 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable) .sku_enable = enable, }; - return __mt76_mcu_send_msg(&dev->mt76, - MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, + sizeof(req), true); } int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band) @@ -3288,8 +3384,8 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band) .band = band, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SER_TRIGGER, - &req, sizeof(req), false); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SER_TRIGGER, + &req, sizeof(req), false); } int mt7915_mcu_set_txbf_type(struct mt7915_dev *dev) @@ -3306,8 +3402,8 @@ int mt7915_mcu_set_txbf_type(struct mt7915_dev *dev) .ibf = false, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, &req, + sizeof(req), true); } int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev) @@ -3325,8 +3421,8 @@ int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev) .snd_mode = MT_BF_PROCESSING, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, - &req, sizeof(req), true); + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, &req, + sizeof(req), true); } int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, @@ -3342,14 +3438,112 @@ int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, u8 drop_tx_idx; u8 sta_idx; /* 256 sta */ u8 rsv[2]; - u32 val; + __le32 val; } __packed req = { .action = MT_SPR_ENABLE, .arg_num = 1, .band_idx = mvif->band_idx, - .val = enable, + .val = cpu_to_le32(enable), + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR, &req, + sizeof(req), true); +} + +int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct rate_info *rate) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt7915_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; + struct { + u8 category; + u8 band; + __le16 wcid; + } __packed req = { + .category = MCU_PHY_STATE_CONTENTION_RX_RATE, + .band = mvif->band_idx, + .wcid = cpu_to_le16(msta->wcid.idx), }; + struct ieee80211_supported_band *sband; + struct mt7915_mcu_phy_rx_info *res; + struct sk_buff *skb; + u16 flags = 0; + int ret; + int i; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD_PHY_STAT_INFO, + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + res = (struct mt7915_mcu_phy_rx_info *)skb->data; + + rate->mcs = res->rate; + rate->nss = res->nsts + 1; + + switch (res->mode) { + case MT_PHY_TYPE_CCK: + case MT_PHY_TYPE_OFDM: + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else + sband = &mphy->sband_2g.sband; + + for (i = 0; i < sband->n_bitrates; i++) { + if (rate->mcs != (sband->bitrates[i].hw_value & 0xf)) + continue; + + rate->legacy = sband->bitrates[i].bitrate; + break; + } + break; + case MT_PHY_TYPE_HT: + case MT_PHY_TYPE_HT_GF: + if (rate->mcs > 31) + return -EINVAL; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR, - &req, sizeof(req), true); + flags |= RATE_INFO_FLAGS_MCS; + + if (res->gi) + flags |= RATE_INFO_FLAGS_SHORT_GI; + break; + case MT_PHY_TYPE_VHT: + flags |= RATE_INFO_FLAGS_VHT_MCS; + + if (res->gi) + flags |= RATE_INFO_FLAGS_SHORT_GI; + break; + case MT_PHY_TYPE_HE_SU: + case MT_PHY_TYPE_HE_EXT_SU: + case MT_PHY_TYPE_HE_TB: + case MT_PHY_TYPE_HE_MU: + rate->he_gi = res->gi; + + flags |= RATE_INFO_FLAGS_HE_MCS; + break; + default: + break; + } + rate->flags = flags; + + switch (res->bw) { + case IEEE80211_STA_RX_BW_160: + rate->bw = RATE_INFO_BW_160; + break; + case IEEE80211_STA_RX_BW_80: + rate->bw = RATE_INFO_BW_80; + break; + case IEEE80211_STA_RX_BW_40: + rate->bw = RATE_INFO_BW_40; + break; + default: + rate->bw = RATE_INFO_BW_20; + break; + } + + dev_kfree_skb(skb); + + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index c656d66385c4..cd1a4256c843 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -46,6 +46,11 @@ enum { MCU_EXT_EVENT_RATE_REPORT = 0x87, }; +enum { + MCU_ATE_SET_TRX = 0x1, + MCU_ATE_SET_FREQ_OFFSET = 0xa, +}; + struct mt7915_mcu_rxd { __le32 rxd[6]; @@ -153,6 +158,18 @@ struct mt7915_mcu_ra_info { u8 prob_down_pending; } __packed; + +struct mt7915_mcu_phy_rx_info { + u8 category; + u8 rate; + u8 mode; + u8 nsts; + u8 gi; + u8 coding; + u8 stbc; + u8 bw; +}; + #define MT_RA_RATE_NSS GENMASK(8, 6) #define MT_RA_RATE_MCS GENMASK(3, 0) #define MT_RA_RATE_TX_MODE GENMASK(12, 9) @@ -201,19 +218,24 @@ enum { MCU_EXT_CMD_EDCA_UPDATE = 0x27, MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A, MCU_EXT_CMD_THERMAL_CTRL = 0x2c, + MCU_EXT_CMD_WTBL_UPDATE = 0x32, MCU_EXT_CMD_SET_DRR_CTRL = 0x36, MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, + MCU_EXT_CMD_ATE_CTRL = 0x3d, MCU_EXT_CMD_PROTECT_CTRL = 0x3e, MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, MCU_EXT_CMD_RX_HDR_TRANS = 0x47, + MCU_EXT_CMD_MUAR_UPDATE = 0x48, MCU_EXT_CMD_SET_RX_PATH = 0x4e, MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, + MCU_EXT_CMD_MWDS_SUPPORT = 0x80, MCU_EXT_CMD_SET_SER_TRIGGER = 0x81, MCU_EXT_CMD_SCS_CTRL = 0x82, MCU_EXT_CMD_RATE_CTRL = 0x87, MCU_EXT_CMD_FW_DBG_CTRL = 0x95, MCU_EXT_CMD_SET_RDD_TH = 0x9d, MCU_EXT_CMD_SET_SPR = 0xa8, + MCU_EXT_CMD_PHY_STAT_INFO = 0xad, }; enum { @@ -247,6 +269,14 @@ enum { EE_FORMAT_MULTIPLE, }; +enum { + MCU_PHY_STATE_TX_RATE, + MCU_PHY_STATE_RX_RATE, + MCU_PHY_STATE_RSSI, + MCU_PHY_STATE_CONTENTION_RX_RATE, + MCU_PHY_STATE_OFDMLQ_CNINFO, +}; + #define STA_TYPE_STA BIT(0) #define STA_TYPE_AP BIT(1) #define STA_TYPE_ADHOC BIT(2) @@ -354,15 +384,6 @@ struct bss_info_ext_bss { u8 rsv[8]; } __packed; -struct bss_info_sync_mode { - __le16 tag; - __le16 len; - __le16 bcn_interval; - u8 enable; - u8 dtim_period; - u8 rsv[8]; -} __packed; - struct bss_info_bmc_rate { __le16 tag; __le16 len; @@ -480,7 +501,7 @@ enum { BSS_INFO_LQ_RM, /* obsoleted */ BSS_INFO_EXT_BSS, BSS_INFO_BMC_RATE, /* for bmc rate control in CR4 */ - BSS_INFO_SYNC_MODE, + BSS_INFO_SYNC_MODE, /* obsoleted */ BSS_INFO_RA, BSS_INFO_HW_AMSDU, BSS_INFO_BSS_COLOR, @@ -551,6 +572,15 @@ struct wtbl_vht { u8 rsv[4]; } __packed; +struct wtbl_hdr_trans { + __le16 tag; + __le16 len; + u8 to_ds; + u8 from_ds; + u8 no_rx_trans; + u8 _rsv; +}; + enum { MT_BA_TYPE_INVALID, MT_BA_TYPE_ORIGINATOR, @@ -972,6 +1002,7 @@ enum { sizeof(struct wtbl_rx) + \ sizeof(struct wtbl_ht) + \ sizeof(struct wtbl_vht) + \ + sizeof(struct wtbl_hdr_trans) +\ sizeof(struct wtbl_ba) + \ sizeof(struct wtbl_smps)) @@ -997,8 +1028,7 @@ enum { sizeof(struct bss_info_hw_amsdu) +\ sizeof(struct bss_info_he) + \ sizeof(struct bss_info_bmc_rate) +\ - sizeof(struct bss_info_ext_bss) +\ - sizeof(struct bss_info_sync_mode)) + sizeof(struct bss_info_ext_bss)) #define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \ sizeof(struct bss_info_bcn_csa) + \ diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 4b8908fa7eda..0339abf360d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -9,7 +9,7 @@ #include "../mt76.h" #include "regs.h" -#define MT7915_MAX_INTERFACES 4 +#define MT7915_MAX_INTERFACES 32 #define MT7915_MAX_WMM_SETS 4 #define MT7915_WTBL_SIZE 288 #define MT7915_WTBL_RESERVED (MT7915_WTBL_SIZE - 1) @@ -32,6 +32,7 @@ #define MT7915_EEPROM_SIZE 3584 #define MT7915_TOKEN_SIZE 8192 +#define MT7915_TOKEN_FREE_THR 64 #define MT7915_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ #define MT7915_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ @@ -112,8 +113,10 @@ struct mt7915_phy { struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES]; + struct ieee80211_vif *monitor_vif; + u32 rxfilter; - u32 omac_mask; + u64 omac_mask; u16 noise; u16 chainmask; @@ -159,11 +162,27 @@ struct mt7915_dev { u32 hw_pattern; spinlock_t token_lock; + int token_count; struct idr token; s8 **rate_power; /* TODO: use mt76_rate_power */ + bool dbdc_support; bool fw_debug; + +#ifdef CONFIG_NL80211_TESTMODE + struct { + u32 *reg_backup; + + s32 last_freq_offset; + u8 last_rcpi[4]; + s8 last_ib_rssi[4]; + s8 last_wb_rssi[4]; + u8 last_snr; + + u8 spe_idx; + } test; +#endif }; enum { @@ -171,24 +190,13 @@ enum { HW_BSSID_1, HW_BSSID_2, HW_BSSID_3, - HW_BSSID_MAX, + HW_BSSID_MAX = HW_BSSID_3, EXT_BSSID_START = 0x10, EXT_BSSID_1, - EXT_BSSID_2, - EXT_BSSID_3, - EXT_BSSID_4, - EXT_BSSID_5, - EXT_BSSID_6, - EXT_BSSID_7, - EXT_BSSID_8, - EXT_BSSID_9, - EXT_BSSID_10, - EXT_BSSID_11, - EXT_BSSID_12, - EXT_BSSID_13, - EXT_BSSID_14, - EXT_BSSID_15, - EXT_BSSID_END + EXT_BSSID_15 = 0x1f, + EXT_BSSID_MAX = EXT_BSSID_15, + REPEATER_BSSID_START = 0x20, + REPEATER_BSSID_MAX = 0x3f, }; enum { @@ -264,15 +272,14 @@ static inline u8 mt7915_lmac_mapping(struct mt7915_dev *dev, u8 ac) extern const struct ieee80211_ops mt7915_ops; extern struct pci_driver mt7915_pci_driver; +extern const struct mt76_testmode_ops mt7915_testmode_ops; u32 mt7915_reg_map(struct mt7915_dev *dev, u32 addr); int mt7915_register_device(struct mt7915_dev *dev); void mt7915_unregister_device(struct mt7915_dev *dev); -int mt7915_register_ext_phy(struct mt7915_dev *dev); -void mt7915_unregister_ext_phy(struct mt7915_dev *dev); int mt7915_eeprom_init(struct mt7915_dev *dev); -u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset); +void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy); int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, struct ieee80211_channel *chan, u8 chain_idx); @@ -281,7 +288,7 @@ int mt7915_dma_init(struct mt7915_dev *dev); void mt7915_dma_prefetch(struct mt7915_dev *dev); void mt7915_dma_cleanup(struct mt7915_dev *dev); int mt7915_mcu_init(struct mt7915_dev *dev); -int mt7915_mcu_add_dev_info(struct mt7915_dev *dev, +int mt7915_mcu_add_dev_info(struct mt7915_phy *phy, struct ieee80211_vif *vif, bool enable); int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, struct ieee80211_vif *vif, int enable); @@ -289,6 +296,9 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable); int mt7915_mcu_add_sta_adv(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable); +int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, struct ieee80211_ampdu_params *params, bool add); @@ -306,6 +316,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); +int mt7915_set_channel(struct mt7915_phy *phy); int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd); int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif); int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev, @@ -314,6 +325,8 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev); int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset); int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, bool hdr_trans); +int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, + u8 en); int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable); int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band); int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val); @@ -327,8 +340,10 @@ int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev, const struct mt7915_dfs_pulse *pulse); int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index, const struct mt7915_dfs_pattern *pattern); -int mt7915_mcu_get_rate_info(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx); int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index); +int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx); +int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct rate_info *rate); int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, enum mt7915_rdd_cmd cmd, u8 index, u8 rx_sel, u8 val); int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl); @@ -428,11 +443,13 @@ mt7915_l2_rmw(struct mt7915_dev *dev, u32 addr, u32 mask, u32 val) bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask); void mt7915_mac_reset_counters(struct mt7915_phy *phy); void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy); +void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy); void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, bool beacon); void mt7915_mac_set_timing(struct mt7915_phy *phy); int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb); +void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb); void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb); int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -446,6 +463,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); +int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc); void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c index fe62b4d853e4..aeb86fbea41c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -21,8 +21,14 @@ static void mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + static const u32 rx_irq_mask[] = { + [MT_RXQ_MAIN] = MT_INT_RX_DONE_DATA0, + [MT_RXQ_EXT] = MT_INT_RX_DONE_DATA1, + [MT_RXQ_MCU] = MT_INT_RX_DONE_WM, + [MT_RXQ_MCU_WA] = MT_INT_RX_DONE_WA, + }; - mt7915_irq_enable(dev, MT_INT_RX_DONE(q)); + mt7915_irq_enable(dev, rx_irq_mask[q]); } /* TODO: support 2/4/6/8 MSI-X vectors */ @@ -49,14 +55,17 @@ static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance) if (intr & MT_INT_TX_DONE_MCU) napi_schedule(&dev->mt76.tx_napi); - if (intr & MT_INT_RX_DONE_DATA) - napi_schedule(&dev->mt76.napi[0]); + if (intr & MT_INT_RX_DONE_DATA0) + napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); + + if (intr & MT_INT_RX_DONE_DATA1) + napi_schedule(&dev->mt76.napi[MT_RXQ_EXT]); if (intr & MT_INT_RX_DONE_WM) - napi_schedule(&dev->mt76.napi[1]); + napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]); if (intr & MT_INT_RX_DONE_WA) - napi_schedule(&dev->mt76.napi[2]); + napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]); if (intr & MT_INT_MCU_CMD) { u32 val = mt76_rr(dev, MT_MCU_CMD); @@ -140,7 +149,7 @@ static int mt7915_pci_probe(struct pci_dev *pdev, dev = container_of(mdev, struct mt7915_dev, mt76); ret = mt7915_alloc_device(pdev, dev); if (ret) - return ret; + goto error; mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); mdev->rev = (mt7915_l1_rr(dev, MT_HW_CHIPID) << 16) | @@ -163,7 +172,8 @@ static int mt7915_pci_probe(struct pci_dev *pdev, return 0; error: - ieee80211_free_hw(mt76_hw(dev)); + mt76_free_device(&dev->mt76); + return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index 64327153b7fa..848703e6eb7c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -51,6 +51,9 @@ #define MT_WF_TMAC_BASE(_band) ((_band) ? 0xa1000 : 0x21000) #define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs)) +#define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0) +#define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25) + #define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090) #define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094) #define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) @@ -67,11 +70,13 @@ #define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) #define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) -/* DMA Band 0 */ -#define MT_WF_DMA_BASE 0x21e00 -#define MT_WF_DMA(ofs) (MT_WF_DMA_BASE + (ofs)) +#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c) +#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0) + +#define MT_WF_DMA_BASE(_band) ((_band) ? 0xa1e00 : 0x21e00) +#define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs)) -#define MT_DMA_DCR0 MT_WF_DMA(0x000) +#define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000) #define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3) #define MT_DMA_DCR0_RXD_G5_EN BIT(23) @@ -166,10 +171,33 @@ #define MT_WF_AGG_BASE(_band) ((_band) ? 0xa0800 : 0x20800) #define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs)) +#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, 0x05c + (_n) * 4) +#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, 0x06c + (_n) * 4) +#define MT_AGG_PCR0_MM_PROT BIT(0) +#define MT_AGG_PCR0_GF_PROT BIT(1) +#define MT_AGG_PCR0_BW20_PROT BIT(2) +#define MT_AGG_PCR0_BW40_PROT BIT(4) +#define MT_AGG_PCR0_BW80_PROT BIT(6) +#define MT_AGG_PCR0_ERP_PROT GENMASK(12, 8) +#define MT_AGG_PCR0_VHT_PROT BIT(13) +#define MT_AGG_PCR0_PTA_WIN_DIS BIT(15) + +#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23) +#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0) + #define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084) #define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) #define MT_AGG_ACR_BAR_RATE GENMASK(29, 16) +#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, 0x098) +#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12) +#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6) +#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7) +#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24) + +#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, 0x0f0) +#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, 0x0f4) + /* ARB: band 0(0x20c00), band 1(0xa0c00) */ #define MT_WF_ARB_BASE(_band) ((_band) ? 0xa0c00 : 0x20c00) #define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs)) @@ -178,6 +206,8 @@ #define MT_ARB_SCR_TX_DISABLE BIT(8) #define MT_ARB_SCR_RX_DISABLE BIT(9) +#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, 0x194 + (_n) * 4) + /* RMAC: band 0(0x21400), band 1(0xa1400) */ #define MT_WF_RMAC_BASE(_band) ((_band) ? 0xa1400 : 0x21400) #define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs)) @@ -308,11 +338,11 @@ #define MT_INT_SOURCE_CSR MT_WFDMA_EXT_CSR(0x10) #define MT_INT_MASK_CSR MT_WFDMA_EXT_CSR(0x14) -#define MT_INT_RX_DONE_DATA BIT(16) +#define MT_INT_RX_DONE_DATA0 BIT(16) +#define MT_INT_RX_DONE_DATA1 BIT(17) #define MT_INT_RX_DONE_WM BIT(0) #define MT_INT_RX_DONE_WA BIT(1) -#define MT_INT_RX_DONE(_n) ((_n) ? BIT((_n) - 1) : BIT(16)) -#define MT_INT_RX_DONE_ALL (BIT(0) | BIT(1) | BIT(16)) +#define MT_INT_RX_DONE_ALL (BIT(0) | BIT(1) | GENMASK(17, 16)) #define MT_INT_TX_DONE_MCU_WA BIT(15) #define MT_INT_TX_DONE_FWDL BIT(26) #define MT_INT_TX_DONE_MCU_WM BIT(27) @@ -385,11 +415,19 @@ #define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) #define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) +#define MT_WF_IRPI_BASE 0x83006000 +#define MT_WF_IRPI(ofs) (MT_WF_IRPI_BASE + ((ofs) << 16)) + /* PHY: band 0(0x83080000), band 1(0x83090000) */ #define MT_WF_PHY_BASE 0x83080000 #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) #define MT_WF_PHY_RX_CTRL1(_phy) MT_WF_PHY(0x2004 + ((_phy) << 16)) +#define MT_WF_PHY_RX_CTRL1_IPI_EN GENMASK(2, 0) #define MT_WF_PHY_RX_CTRL1_STSCNT_EN GENMASK(11, 9) +#define MT_WF_PHY_RXTD12(_phy) MT_WF_PHY(0x8230 + ((_phy) << 16)) +#define MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY BIT(18) +#define MT_WF_PHY_RXTD12_IRPI_SW_CLR BIT(29) + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c new file mode 100644 index 000000000000..9ee82e2d262c --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include "mt7915.h" +#include "mac.h" +#include "mcu.h" +#include "testmode.h" + +enum { + TM_CHANGED_TXPOWER, + TM_CHANGED_FREQ_OFFSET, + + /* must be last */ + NUM_TM_CHANGED +}; + +static const u8 tm_change_map[] = { + [TM_CHANGED_TXPOWER] = MT76_TM_ATTR_TX_POWER, + [TM_CHANGED_FREQ_OFFSET] = MT76_TM_ATTR_FREQ_OFFSET, +}; + +struct reg_band { + u32 band[2]; +}; + +#define REG_BAND(_reg) \ + { .band[0] = MT_##_reg(0), .band[1] = MT_##_reg(1) } +#define REG_BAND_IDX(_reg, _idx) \ + { .band[0] = MT_##_reg(0, _idx), .band[1] = MT_##_reg(1, _idx) } + +static const struct reg_band reg_backup_list[] = { + REG_BAND_IDX(AGG_PCR0, 0), + REG_BAND_IDX(AGG_PCR0, 1), + REG_BAND_IDX(AGG_AWSCR0, 0), + REG_BAND_IDX(AGG_AWSCR0, 1), + REG_BAND_IDX(AGG_AWSCR0, 2), + REG_BAND_IDX(AGG_AWSCR0, 3), + REG_BAND(AGG_MRCR), + REG_BAND(TMAC_TFCR0), + REG_BAND(TMAC_TCR0), + REG_BAND(AGG_ATCR1), + REG_BAND(AGG_ATCR3), + REG_BAND(TMAC_TRCR0), + REG_BAND(TMAC_ICR0), + REG_BAND_IDX(ARB_DRNGR0, 0), + REG_BAND_IDX(ARB_DRNGR0, 1), + REG_BAND(WF_RFCR), + REG_BAND(WF_RFCR1), +}; + +static int +mt7915_tm_set_tx_power(struct mt7915_phy *phy) +{ + struct mt7915_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; + struct cfg80211_chan_def *chandef = &mphy->chandef; + int freq = chandef->center_freq1; + int ret; + struct { + u8 format_id; + u8 dbdc_idx; + s8 tx_power; + u8 ant_idx; /* Only 0 is valid */ + u8 center_chan; + u8 rsv[3]; + } __packed req = { + .format_id = 0xf, + .dbdc_idx = phy != &dev->phy, + .center_chan = ieee80211_frequency_to_channel(freq), + }; + u8 *tx_power = NULL; + + if (dev->mt76.test.state != MT76_TM_STATE_OFF) + tx_power = dev->mt76.test.tx_power; + + /* Tx power of the other antennas are the same as antenna 0 */ + if (tx_power && tx_power[0]) + req.tx_power = tx_power[0]; + + ret = mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, + &req, sizeof(req), false); + + return ret; +} + +static int +mt7915_tm_set_freq_offset(struct mt7915_dev *dev, bool en, u32 val) +{ + struct mt7915_tm_cmd req = { + .testmode_en = en, + .param_idx = MCU_ATE_SET_FREQ_OFFSET, + .param.freq.freq_offset = cpu_to_le32(val), + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, + sizeof(req), false); +} + +static int +mt7915_tm_mode_ctrl(struct mt7915_dev *dev, bool enable) +{ + struct { + u8 format_id; + bool enable; + u8 rsv[2]; + } __packed req = { + .format_id = 0x6, + .enable = enable, + }; + + return mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, + &req, sizeof(req), false); +} + +static int +mt7915_tm_set_trx(struct mt7915_dev *dev, struct mt7915_phy *phy, + int type, bool en) +{ + struct mt7915_tm_cmd req = { + .testmode_en = 1, + .param_idx = MCU_ATE_SET_TRX, + .param.trx.type = type, + .param.trx.enable = en, + .param.trx.band = phy != &dev->phy, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, + sizeof(req), false); +} + +static void +mt7915_tm_reg_backup_restore(struct mt7915_dev *dev, struct mt7915_phy *phy) +{ + int n_regs = ARRAY_SIZE(reg_backup_list); + bool ext_phy = phy != &dev->phy; + u32 *b = dev->test.reg_backup; + int i; + + if (dev->mt76.test.state == MT76_TM_STATE_OFF) { + for (i = 0; i < n_regs; i++) + mt76_wr(dev, reg_backup_list[i].band[ext_phy], b[i]); + return; + } + + if (b) + return; + + b = devm_kzalloc(dev->mt76.dev, 4 * n_regs, GFP_KERNEL); + if (!b) + return; + + dev->test.reg_backup = b; + for (i = 0; i < n_regs; i++) + b[i] = mt76_rr(dev, reg_backup_list[i].band[ext_phy]); + + mt76_clear(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_MM_PROT | + MT_AGG_PCR0_GF_PROT | MT_AGG_PCR0_ERP_PROT | + MT_AGG_PCR0_VHT_PROT | MT_AGG_PCR0_BW20_PROT | + MT_AGG_PCR0_BW40_PROT | MT_AGG_PCR0_BW80_PROT); + mt76_set(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_PTA_WIN_DIS); + + mt76_wr(dev, MT_AGG_PCR0(ext_phy, 1), MT_AGG_PCR1_RTS0_NUM_THRES | + MT_AGG_PCR1_RTS0_LEN_THRES); + + mt76_clear(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_BAR_CNT_LIMIT | + MT_AGG_MRCR_LAST_RTS_CTS_RN | MT_AGG_MRCR_RTS_FAIL_LIMIT | + MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT); + + mt76_rmw(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_RTS_FAIL_LIMIT | + MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT, + FIELD_PREP(MT_AGG_MRCR_RTS_FAIL_LIMIT, 1) | + FIELD_PREP(MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT, 1)); + + mt76_wr(dev, MT_TMAC_TFCR0(ext_phy), 0); + mt76_clear(dev, MT_TMAC_TCR0(ext_phy), MT_TMAC_TCR0_TBTT_STOP_CTRL); + + /* config rx filter for testmode rx */ + mt76_wr(dev, MT_WF_RFCR(ext_phy), 0xcf70a); + mt76_wr(dev, MT_WF_RFCR1(ext_phy), 0); +} + +static void +mt7915_tm_init(struct mt7915_dev *dev) +{ + bool en = !(dev->mt76.test.state == MT76_TM_STATE_OFF); + + if (!test_bit(MT76_STATE_RUNNING, &dev->phy.mt76->state)) + return; + + mt7915_tm_mode_ctrl(dev, en); + mt7915_tm_reg_backup_restore(dev, &dev->phy); + mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_TXRX, !en); +} + +static void +mt7915_tm_set_tx_frames(struct mt7915_dev *dev, bool en) +{ + static const u8 spe_idx_map[] = {0, 0, 1, 0, 3, 2, 4, 0, + 9, 8, 6, 10, 16, 12, 18, 0}; + struct sk_buff *skb = dev->mt76.test.tx_skb; + struct ieee80211_tx_info *info; + + mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_RX_RXV, false); + + if (en) { + u8 tx_ant = dev->mt76.test.tx_antenna_mask; + + mutex_unlock(&dev->mt76.mutex); + mt7915_set_channel(&dev->phy); + mutex_lock(&dev->mt76.mutex); + + mt7915_mcu_set_chan_info(&dev->phy, MCU_EXT_CMD_SET_RX_PATH); + dev->test.spe_idx = spe_idx_map[tx_ant]; + } + + mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_TX, en); + + if (!en || !skb) + return; + + info = IEEE80211_SKB_CB(skb); + info->control.vif = dev->phy.monitor_vif; +} + +static void +mt7915_tm_set_rx_frames(struct mt7915_dev *dev, bool en) +{ + if (en) { + mutex_unlock(&dev->mt76.mutex); + mt7915_set_channel(&dev->phy); + mutex_lock(&dev->mt76.mutex); + + mt7915_mcu_set_chan_info(&dev->phy, MCU_EXT_CMD_SET_RX_PATH); + } + + mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_RX_RXV, en); +} + +static void +mt7915_tm_update_params(struct mt7915_dev *dev, u32 changed) +{ + struct mt76_testmode_data *td = &dev->mt76.test; + bool en = dev->mt76.test.state != MT76_TM_STATE_OFF; + + if (changed & BIT(TM_CHANGED_FREQ_OFFSET)) + mt7915_tm_set_freq_offset(dev, en, en ? td->freq_offset : 0); + if (changed & BIT(TM_CHANGED_TXPOWER)) + mt7915_tm_set_tx_power(&dev->phy); +} + +static int +mt7915_tm_set_state(struct mt76_dev *mdev, enum mt76_testmode_state state) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct mt76_testmode_data *td = &mdev->test; + enum mt76_testmode_state prev_state = td->state; + + mdev->test.state = state; + + if (prev_state == MT76_TM_STATE_TX_FRAMES) + mt7915_tm_set_tx_frames(dev, false); + else if (state == MT76_TM_STATE_TX_FRAMES) + mt7915_tm_set_tx_frames(dev, true); + else if (prev_state == MT76_TM_STATE_RX_FRAMES) + mt7915_tm_set_rx_frames(dev, false); + else if (state == MT76_TM_STATE_RX_FRAMES) + mt7915_tm_set_rx_frames(dev, true); + else if (prev_state == MT76_TM_STATE_OFF || state == MT76_TM_STATE_OFF) + mt7915_tm_init(dev); + + if ((state == MT76_TM_STATE_IDLE && + prev_state == MT76_TM_STATE_OFF) || + (state == MT76_TM_STATE_OFF && + prev_state == MT76_TM_STATE_IDLE)) { + u32 changed = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) { + u16 cur = tm_change_map[i]; + + if (td->param_set[cur / 32] & BIT(cur % 32)) + changed |= BIT(i); + } + + mt7915_tm_update_params(dev, changed); + } + + return 0; +} + +static int +mt7915_tm_set_params(struct mt76_dev *mdev, struct nlattr **tb, + enum mt76_testmode_state new_state) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct mt76_testmode_data *td = &dev->mt76.test; + u32 changed = 0; + int i; + + BUILD_BUG_ON(NUM_TM_CHANGED >= 32); + + if (new_state == MT76_TM_STATE_OFF || + td->state == MT76_TM_STATE_OFF) + return 0; + + if (td->tx_antenna_mask & ~dev->phy.chainmask) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) { + if (tb[tm_change_map[i]]) + changed |= BIT(i); + } + + mt7915_tm_update_params(dev, changed); + + return 0; +} + +static int +mt7915_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + void *rx, *rssi; + int i; + + rx = nla_nest_start(msg, MT76_TM_STATS_ATTR_LAST_RX); + if (!rx) + return -ENOMEM; + + if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, dev->test.last_freq_offset)) + return -ENOMEM; + + rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RCPI); + if (!rssi) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(dev->test.last_rcpi); i++) + if (nla_put_u8(msg, i, dev->test.last_rcpi[i])) + return -ENOMEM; + + nla_nest_end(msg, rssi); + + rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_IB_RSSI); + if (!rssi) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(dev->test.last_ib_rssi); i++) + if (nla_put_s8(msg, i, dev->test.last_ib_rssi[i])) + return -ENOMEM; + + nla_nest_end(msg, rssi); + + rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_WB_RSSI); + if (!rssi) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(dev->test.last_wb_rssi); i++) + if (nla_put_s8(msg, i, dev->test.last_wb_rssi[i])) + return -ENOMEM; + + nla_nest_end(msg, rssi); + + if (nla_put_u8(msg, MT76_TM_RX_ATTR_SNR, dev->test.last_snr)) + return -ENOMEM; + + nla_nest_end(msg, rx); + + return 0; +} + +const struct mt76_testmode_ops mt7915_testmode_ops = { + .set_state = mt7915_tm_set_state, + .set_params = mt7915_tm_set_params, + .dump_stats = mt7915_tm_dump_stats, +}; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h new file mode 100644 index 000000000000..964f2d7fde3a --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#ifndef __MT7915_TESTMODE_H +#define __MT7915_TESTMODE_H + +struct mt7915_tm_trx { + u8 type; + u8 enable; + u8 band; + u8 rsv; +}; + +struct mt7915_tm_freq_offset { + u8 band; + __le32 freq_offset; +}; + +struct mt7915_tm_cmd { + u8 testmode_en; + u8 param_idx; + u8 _rsv[2]; + union { + __le32 data; + struct mt7915_tm_trx trx; + struct mt7915_tm_freq_offset freq; + u8 test[72]; + } param; +} __packed; + +enum { + TM_MAC_TX = 1, + TM_MAC_RX, + TM_MAC_TXRX, + TM_MAC_TXRX_RXV, + TM_MAC_RXV, + TM_MAC_RX_RXV, +}; + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c index 9a4d95a2a707..62b5b912818f 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/sdio.c @@ -36,46 +36,49 @@ mt76s_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid) return 0; } -static int mt76s_alloc_tx(struct mt76_dev *dev) +static struct mt76_queue *mt76s_alloc_tx_queue(struct mt76_dev *dev) { struct mt76_queue *q; - int i; - - for (i = 0; i < MT_TXQ_MCU_WA; i++) { - q = devm_kzalloc(dev->dev, sizeof(*q), GFP_KERNEL); - if (!q) - return -ENOMEM; - spin_lock_init(&q->lock); - q->hw_idx = i; - dev->q_tx[i] = q; + q = devm_kzalloc(dev->dev, sizeof(*q), GFP_KERNEL); + if (!q) + return ERR_PTR(-ENOMEM); - q->entry = devm_kcalloc(dev->dev, - MT_NUM_TX_ENTRIES, sizeof(*q->entry), - GFP_KERNEL); - if (!q->entry) - return -ENOMEM; + spin_lock_init(&q->lock); + q->entry = devm_kcalloc(dev->dev, + MT_NUM_TX_ENTRIES, sizeof(*q->entry), + GFP_KERNEL); + if (!q->entry) + return ERR_PTR(-ENOMEM); - q->ndesc = MT_NUM_TX_ENTRIES; - } + q->ndesc = MT_NUM_TX_ENTRIES; - return 0; + return q; } -void mt76s_stop_txrx(struct mt76_dev *dev) +static int mt76s_alloc_tx(struct mt76_dev *dev) { - struct mt76_sdio *sdio = &dev->sdio; + struct mt76_queue *q; + int i; - cancel_work_sync(&sdio->tx.xmit_work); - cancel_work_sync(&sdio->tx.status_work); - cancel_work_sync(&sdio->rx.recv_work); - cancel_work_sync(&sdio->rx.net_work); - cancel_work_sync(&sdio->stat_work); - clear_bit(MT76_READING_STATS, &dev->phy.state); + for (i = 0; i <= MT_TXQ_PSD; i++) { + q = mt76s_alloc_tx_queue(dev); + if (IS_ERR(q)) + return PTR_ERR(q); - mt76_tx_status_check(dev, NULL, true); + q->qid = i; + dev->phy.q_tx[i] = q; + } + + q = mt76s_alloc_tx_queue(dev); + if (IS_ERR(q)) + return PTR_ERR(q); + + q->qid = MT_MCUQ_WM; + dev->q_mcu[MT_MCUQ_WM] = q; + + return 0; } -EXPORT_SYMBOL_GPL(mt76s_stop_txrx); int mt76s_alloc_queues(struct mt76_dev *dev) { @@ -131,11 +134,32 @@ mt76s_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) return nframes; } -static void mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid) +static void mt76s_net_worker(struct mt76_worker *w) +{ + struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, + net_worker); + struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); + int i, nframes; + + do { + nframes = 0; + + local_bh_disable(); + rcu_read_lock(); + + mt76_for_each_q_rx(dev, i) + nframes += mt76s_process_rx_queue(dev, &dev->q_rx[i]); + + rcu_read_unlock(); + local_bh_enable(); + } while (nframes > 0); +} + +static int mt76s_process_tx_queue(struct mt76_dev *dev, struct mt76_queue *q) { - struct mt76_queue *q = dev->q_tx[qid]; + bool wake, mcu = q == dev->q_mcu[MT_MCUQ_WM]; struct mt76_queue_entry entry; - bool wake; + int nframes = 0; while (q->queued > 0) { if (!q->entry[q->tail].done) @@ -144,12 +168,13 @@ static void mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid) entry = q->entry[q->tail]; q->entry[q->tail].done = false; - if (qid == MT_TXQ_MCU) { + if (mcu) { dev_kfree_skb(entry.skb); entry.skb = NULL; } mt76_queue_tx_complete(dev, q, &entry); + nframes++; } wake = q->stopped && q->queued < q->ndesc - 8; @@ -159,13 +184,35 @@ static void mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid) if (!q->queued) wake_up(&dev->tx_wait); - if (qid == MT_TXQ_MCU) - return; + if (mcu) + goto out; - mt76_txq_schedule(&dev->phy, qid); + mt76_txq_schedule(&dev->phy, q->qid); if (wake) - ieee80211_wake_queue(dev->hw, qid); + ieee80211_wake_queue(dev->hw, q->qid); +out: + return nframes; +} + +static void mt76s_status_worker(struct mt76_worker *w) +{ + struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, + status_worker); + struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); + int i, nframes; + + do { + nframes = mt76s_process_tx_queue(dev, dev->q_mcu[MT_MCUQ_WM]); + + for (i = 0; i <= MT_TXQ_PSD; i++) + nframes += mt76s_process_tx_queue(dev, + dev->phy.q_tx[i]); + + if (dev->drv->tx_status_data && + !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) + queue_work(dev->wq, &dev->sdio.stat_work); + } while (nframes > 0); } static void mt76s_tx_status_data(struct work_struct *work) @@ -194,11 +241,10 @@ static void mt76s_tx_status_data(struct work_struct *work) } static int -mt76s_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { - struct mt76_queue *q = dev->q_tx[qid]; struct mt76_tx_info tx_info = { .skb = skb, }; @@ -209,7 +255,7 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, return -ENOSPC; skb->prev = skb->next = NULL; - err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info); + err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info); if (err < 0) return err; @@ -222,10 +268,9 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, } static int -mt76s_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76s_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, u32 tx_info) { - struct mt76_queue *q = dev->q_tx[qid]; int ret = -ENOSPC, len = skb->len, pad; if (q->queued == q->ndesc) @@ -257,7 +302,7 @@ static void mt76s_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) { struct mt76_sdio *sdio = &dev->sdio; - queue_work(sdio->txrx_wq, &sdio->tx.xmit_work); + mt76_worker_schedule(&sdio->txrx_worker); } static const struct mt76_queue_ops sdio_queue_ops = { @@ -266,49 +311,19 @@ static const struct mt76_queue_ops sdio_queue_ops = { .tx_queue_skb_raw = mt76s_tx_queue_skb_raw, }; -static void mt76s_tx_work(struct work_struct *work) -{ - struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, - tx.status_work); - struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); - int i; - - for (i = 0; i < MT_TXQ_MCU_WA; i++) - mt76s_process_tx_queue(dev, i); - - if (dev->drv->tx_status_data && - !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) - queue_work(dev->wq, &dev->sdio.stat_work); -} - -static void mt76s_rx_work(struct work_struct *work) -{ - struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, - rx.net_work); - struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); - int i; - - /* rx processing */ - local_bh_disable(); - rcu_read_lock(); - - mt76_for_each_q_rx(dev, i) - mt76s_process_rx_queue(dev, &dev->q_rx[i]); - - rcu_read_unlock(); - local_bh_enable(); -} - void mt76s_deinit(struct mt76_dev *dev) { struct mt76_sdio *sdio = &dev->sdio; int i; - mt76s_stop_txrx(dev); - if (sdio->txrx_wq) { - destroy_workqueue(sdio->txrx_wq); - sdio->txrx_wq = NULL; - } + mt76_worker_teardown(&sdio->txrx_worker); + mt76_worker_teardown(&sdio->status_worker); + mt76_worker_teardown(&sdio->net_worker); + + cancel_work_sync(&sdio->stat_work); + clear_bit(MT76_READING_STATS, &dev->phy.state); + + mt76_tx_status_check(dev, NULL, true); sdio_claim_host(sdio->func); sdio_release_irq(sdio->func); @@ -335,18 +350,23 @@ int mt76s_init(struct mt76_dev *dev, struct sdio_func *func, const struct mt76_bus_ops *bus_ops) { struct mt76_sdio *sdio = &dev->sdio; + int err; - sdio->txrx_wq = alloc_workqueue("mt76s_txrx_wq", - WQ_UNBOUND | WQ_HIGHPRI, - WQ_UNBOUND_MAX_ACTIVE); - if (!sdio->txrx_wq) - return -ENOMEM; + err = mt76_worker_setup(dev->hw, &sdio->status_worker, + mt76s_status_worker, "sdio-status"); + if (err) + return err; + + err = mt76_worker_setup(dev->hw, &sdio->net_worker, mt76s_net_worker, + "sdio-net"); + if (err) + return err; + + sched_set_fifo_low(sdio->status_worker.task); + sched_set_fifo_low(sdio->net_worker.task); INIT_WORK(&sdio->stat_work, mt76s_tx_status_data); - INIT_WORK(&sdio->tx.status_work, mt76s_tx_work); - INIT_WORK(&sdio->rx.net_work, mt76s_rx_work); - mutex_init(&sdio->sched.lock); dev->queue_ops = &sdio_queue_ops; dev->bus = bus_ops; dev->sdio.func = func; diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c index 883f59c7a7e4..581eb56dc4be 100644 --- a/drivers/net/wireless/mediatek/mt76/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/testmode.c @@ -11,6 +11,8 @@ static const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = { [MT76_TM_ATTR_TX_RATE_IDX] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_RATE_SGI] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_RATE_LDPC] = { .type = NLA_U8 }, + [MT76_TM_ATTR_TX_RATE_STBC] = { .type = NLA_U8 }, + [MT76_TM_ATTR_TX_LTF] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_ANTENNA] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_POWER_CONTROL] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_POWER] = { .type = NLA_NESTED }, @@ -21,6 +23,7 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev) { struct mt76_testmode_data *td = &dev->test; struct mt76_wcid *wcid = &dev->global_wcid; + struct mt76_phy *phy = &dev->phy; struct sk_buff *skb = td->tx_skb; struct mt76_queue *q; int qid; @@ -29,7 +32,7 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev) return; qid = skb_get_queue_mapping(skb); - q = dev->q_tx[qid]; + q = phy->q_tx[qid]; spin_lock_bh(&q->lock); @@ -37,7 +40,8 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev) q->queued < q->ndesc / 2) { int ret; - ret = dev->queue_ops->tx_queue_skb(dev, qid, skb_get(skb), wcid, NULL); + ret = dev->queue_ops->tx_queue_skb(dev, q, skb_get(skb), wcid, + NULL); if (ret < 0) break; @@ -55,13 +59,14 @@ static int mt76_testmode_tx_init(struct mt76_dev *dev) { struct mt76_testmode_data *td = &dev->test; + struct mt76_phy *phy = &dev->phy; struct ieee80211_tx_info *info; struct ieee80211_hdr *hdr; struct sk_buff *skb; u16 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_FROMDS; struct ieee80211_tx_rate *rate; - u8 max_nss = hweight8(dev->phy.antenna_mask); + u8 max_nss = hweight8(phy->antenna_mask); if (td->tx_antenna_mask) max_nss = min_t(u8, max_nss, hweight8(td->tx_antenna_mask)); @@ -74,28 +79,32 @@ mt76_testmode_tx_init(struct mt76_dev *dev) td->tx_skb = skb; hdr = __skb_put_zero(skb, td->tx_msdu_len); hdr->frame_control = cpu_to_le16(fc); - memcpy(hdr->addr1, dev->macaddr, sizeof(dev->macaddr)); - memcpy(hdr->addr2, dev->macaddr, sizeof(dev->macaddr)); - memcpy(hdr->addr3, dev->macaddr, sizeof(dev->macaddr)); + memcpy(hdr->addr1, phy->macaddr, sizeof(phy->macaddr)); + memcpy(hdr->addr2, phy->macaddr, sizeof(phy->macaddr)); + memcpy(hdr->addr3, phy->macaddr, sizeof(phy->macaddr)); info = IEEE80211_SKB_CB(skb); info->flags = IEEE80211_TX_CTL_INJECTED | IEEE80211_TX_CTL_NO_ACK | IEEE80211_TX_CTL_NO_PS_BUFFER; + + if (td->tx_rate_mode > MT76_TM_TX_MODE_VHT) + goto out; + rate = &info->control.rates[0]; rate->count = 1; rate->idx = td->tx_rate_idx; switch (td->tx_rate_mode) { case MT76_TM_TX_MODE_CCK: - if (dev->phy.chandef.chan->band != NL80211_BAND_2GHZ) + if (phy->chandef.chan->band != NL80211_BAND_2GHZ) return -EINVAL; if (rate->idx > 4) return -EINVAL; break; case MT76_TM_TX_MODE_OFDM: - if (dev->phy.chandef.chan->band != NL80211_BAND_2GHZ) + if (phy->chandef.chan->band != NL80211_BAND_2GHZ) break; if (rate->idx > 8) @@ -106,7 +115,7 @@ mt76_testmode_tx_init(struct mt76_dev *dev) case MT76_TM_TX_MODE_HT: if (rate->idx > 8 * max_nss && !(rate->idx == 32 && - dev->phy.chandef.width >= NL80211_CHAN_WIDTH_40)) + phy->chandef.width >= NL80211_CHAN_WIDTH_40)) return -EINVAL; rate->flags |= IEEE80211_TX_RC_MCS; @@ -131,8 +140,11 @@ mt76_testmode_tx_init(struct mt76_dev *dev) if (td->tx_rate_ldpc) info->flags |= IEEE80211_TX_CTL_LDPC; + if (td->tx_rate_stbc) + info->flags |= IEEE80211_TX_CTL_STBC; + if (td->tx_rate_mode >= MT76_TM_TX_MODE_HT) { - switch (dev->phy.chandef.width) { + switch (phy->chandef.width) { case NL80211_CHAN_WIDTH_40: rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; break; @@ -147,7 +159,7 @@ mt76_testmode_tx_init(struct mt76_dev *dev) break; } } - +out: skb_set_queue_mapping(skb, IEEE80211_AC_BE); return 0; @@ -334,8 +346,10 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 0, MT76_TM_TX_MODE_MAX) || mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_NSS], &td->tx_rate_nss, 1, hweight8(phy->antenna_mask)) || - mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_SGI], &td->tx_rate_sgi, 0, 1) || + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_SGI], &td->tx_rate_sgi, 0, 2) || mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_LDPC], &td->tx_rate_ldpc, 0, 1) || + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_STBC], &td->tx_rate_stbc, 0, 1) || + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_LTF], &td->tx_ltf, 0, 2) || mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], &td->tx_antenna_mask, 1, phy->antenna_mask) || mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL], @@ -472,6 +486,9 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, td->tx_rate_idx) || nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_SGI, td->tx_rate_sgi) || nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, td->tx_rate_ldpc) || + nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) || + (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) && + nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) || (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) && nla_put_u8(msg, MT76_TM_ATTR_TX_ANTENNA, td->tx_antenna_mask)) || (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER_CONTROL) && diff --git a/drivers/net/wireless/mediatek/mt76/testmode.h b/drivers/net/wireless/mediatek/mt76/testmode.h index 691fe5773244..7efad685a17c 100644 --- a/drivers/net/wireless/mediatek/mt76/testmode.h +++ b/drivers/net/wireless/mediatek/mt76/testmode.h @@ -25,6 +25,8 @@ * @MT76_TM_ATTR_TX_RATE_IDX: packet tx rate/MCS index (u8) * @MT76_TM_ATTR_TX_RATE_SGI: packet tx use short guard interval (u8) * @MT76_TM_ATTR_TX_RATE_LDPC: packet tx enable LDPC (u8) + * @MT76_TM_ATTR_TX_RATE_STBC: packet tx enable STBC (u8) + * @MT76_TM_ATTR_TX_LTF: packet tx LTF, set 0 to 2 for 1x, 2x, and 4x LTF (u8) * * @MT76_TM_ATTR_TX_ANTENNA: tx antenna mask (u8) * @MT76_TM_ATTR_TX_POWER_CONTROL: enable tx power control (u8) @@ -50,6 +52,8 @@ enum mt76_testmode_attr { MT76_TM_ATTR_TX_RATE_IDX, MT76_TM_ATTR_TX_RATE_SGI, MT76_TM_ATTR_TX_RATE_LDPC, + MT76_TM_ATTR_TX_RATE_STBC, + MT76_TM_ATTR_TX_LTF, MT76_TM_ATTR_TX_ANTENNA, MT76_TM_ATTR_TX_POWER_CONTROL, @@ -99,8 +103,9 @@ enum mt76_testmode_stats_attr { * * @MT76_TM_RX_ATTR_FREQ_OFFSET: frequency offset (s32) * @MT76_TM_RX_ATTR_RCPI: received channel power indicator (array, u8) - * @MT76_TM_RX_ATTR_IB_RSSI: internal inband RSSI (s8) - * @MT76_TM_RX_ATTR_WB_RSSI: internal wideband RSSI (s8) + * @MT76_TM_RX_ATTR_IB_RSSI: internal inband RSSI (array, s8) + * @MT76_TM_RX_ATTR_WB_RSSI: internal wideband RSSI (array, s8) + * @MT76_TM_RX_ATTR_SNR: signal-to-noise ratio (u8) */ enum mt76_testmode_rx_attr { MT76_TM_RX_ATTR_UNSPEC, @@ -109,6 +114,7 @@ enum mt76_testmode_rx_attr { MT76_TM_RX_ATTR_RCPI, MT76_TM_RX_ATTR_IB_RSSI, MT76_TM_RX_ATTR_WB_RSSI, + MT76_TM_RX_ATTR_SNR, /* keep last */ NUM_MT76_TM_RX_ATTRS, @@ -141,12 +147,20 @@ enum mt76_testmode_state { * @MT76_TM_TX_MODE_OFDM: legacy OFDM mode * @MT76_TM_TX_MODE_HT: 802.11n MCS * @MT76_TM_TX_MODE_VHT: 802.11ac MCS + * @MT76_TM_TX_MODE_HE_SU: 802.11ax single-user MIMO + * @MT76_TM_TX_MODE_HE_EXT_SU: 802.11ax extended-range SU + * @MT76_TM_TX_MODE_HE_TB: 802.11ax trigger-based + * @MT76_TM_TX_MODE_HE_MU: 802.11ax multi-user MIMO */ enum mt76_testmode_tx_mode { MT76_TM_TX_MODE_CCK, MT76_TM_TX_MODE_OFDM, MT76_TM_TX_MODE_HT, MT76_TM_TX_MODE_VHT, + MT76_TM_TX_MODE_HE_SU, + MT76_TM_TX_MODE_HE_EXT_SU, + MT76_TM_TX_MODE_HE_TB, + MT76_TM_TX_MODE_HE_MU, /* keep last */ NUM_MT76_TM_TX_MODES, diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 44ef4bc7a46e..25627e70bdad 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -225,23 +225,23 @@ void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *sk EXPORT_SYMBOL_GPL(mt76_tx_complete_skb); static int -__mt76_tx_queue_skb(struct mt76_dev *dev, int qid, struct sk_buff *skb, +__mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, bool *stop) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct mt76_queue *q; + struct mt76_queue *q = phy->q_tx[qid]; + struct mt76_dev *dev = phy->dev; bool non_aql; int pending; int idx; non_aql = !info->tx_time_est; - idx = dev->queue_ops->tx_queue_skb(dev, qid, skb, wcid, sta); + idx = dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta); if (idx < 0 || !sta || !non_aql) return idx; wcid = (struct mt76_wcid *)sta->drv_priv; - q = dev->q_tx[qid]; q->entry[idx].wcid = wcid->idx; pending = atomic_inc_return(&wcid->non_aql_packets); if (stop && pending >= MT_MAX_NON_AQL_PKT) @@ -272,6 +272,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, } if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) && + !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && !ieee80211_is_data(hdr->frame_control) && !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { qid = MT_TXQ_PSD; @@ -285,17 +286,11 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, if (ext_phy) info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; - q = dev->q_tx[qid]; + q = phy->q_tx[qid]; spin_lock_bh(&q->lock); - __mt76_tx_queue_skb(dev, qid, skb, wcid, sta, NULL); + __mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL); dev->queue_ops->kick(dev, q); - - if (q->queued > q->ndesc - 8 && !q->stopped) { - ieee80211_stop_queue(phy->hw, skb_get_queue_mapping(skb)); - q->stopped = true; - } - spin_unlock_bh(&q->lock); } EXPORT_SYMBOL_GPL(mt76_tx); @@ -320,7 +315,7 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq) } static void -mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta, +mt76_queue_ps_skb(struct mt76_phy *phy, struct ieee80211_sta *sta, struct sk_buff *skb, bool last) { struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; @@ -332,7 +327,7 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta, IEEE80211_TX_CTL_REQ_TX_STATUS; mt76_skb_set_moredata(skb, !last); - __mt76_tx_queue_skb(dev, MT_TXQ_PSD, skb, wcid, sta, NULL); + __mt76_tx_queue_skb(phy, MT_TXQ_PSD, skb, wcid, sta, NULL); } void @@ -344,7 +339,7 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct mt76_phy *phy = hw->priv; struct mt76_dev *dev = phy->dev; struct sk_buff *last_skb = NULL; - struct mt76_queue *hwq = dev->q_tx[MT_TXQ_PSD]; + struct mt76_queue *hwq = phy->q_tx[MT_TXQ_PSD]; int i; spin_lock_bh(&hwq->lock); @@ -363,14 +358,14 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, nframes--; if (last_skb) - mt76_queue_ps_skb(dev, sta, last_skb, false); + mt76_queue_ps_skb(phy, sta, last_skb, false); last_skb = skb; } while (nframes); } if (last_skb) { - mt76_queue_ps_skb(dev, sta, last_skb, true); + mt76_queue_ps_skb(phy, sta, last_skb, true); dev->queue_ops->kick(dev, hwq); } else { ieee80211_sta_eosp(sta); @@ -380,6 +375,13 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, } EXPORT_SYMBOL_GPL(mt76_release_buffered_frames); +static bool +mt76_txq_stopped(struct mt76_queue *q) +{ + return q->stopped || q->blocked || + q->queued + MT_TXQ_FREE_THR >= q->ndesc; +} + static int mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, struct mt76_txq *mtxq) @@ -409,7 +411,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, ieee80211_get_tx_rates(txq->vif, txq->sta, skb, info->control.rates, 1); - idx = __mt76_tx_queue_skb(dev, qid, skb, wcid, txq->sta, &stop); + idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop); if (idx < 0) return idx; @@ -418,10 +420,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, test_bit(MT76_RESET, &phy->state)) return -EBUSY; - if (stop) - break; - - if (q->queued + MT_TXQ_FREE_THR >= q->ndesc) + if (stop || mt76_txq_stopped(q)) break; skb = mt76_txq_dequeue(phy, mtxq); @@ -433,7 +432,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, ieee80211_get_tx_rates(txq->vif, txq->sta, skb, info->control.rates, 1); - idx = __mt76_tx_queue_skb(dev, qid, skb, wcid, txq->sta, &stop); + idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop); if (idx < 0) break; @@ -448,8 +447,8 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, static int mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) { + struct mt76_queue *q = phy->q_tx[qid]; struct mt76_dev *dev = phy->dev; - struct mt76_queue *q = dev->q_tx[qid]; struct ieee80211_txq *txq; struct mt76_txq *mtxq; struct mt76_wcid *wcid; @@ -463,7 +462,14 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) break; } - if (q->queued + MT_TXQ_FREE_THR >= q->ndesc) + if (dev->queue_ops->tx_cleanup && + q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) { + spin_unlock_bh(&q->lock); + dev->queue_ops->tx_cleanup(dev, q, false); + spin_lock_bh(&q->lock); + } + + if (mt76_txq_stopped(q)) break; txq = ieee80211_next_txq(phy->hw, qid); @@ -538,7 +544,7 @@ void mt76_tx_worker(struct mt76_worker *w) #endif } -void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, +void mt76_stop_tx_queues(struct mt76_phy *phy, struct ieee80211_sta *sta, bool send_bar) { int i; @@ -551,7 +557,7 @@ void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, if (!txq) continue; - hwq = dev->q_tx[mt76_txq_get_qid(txq)]; + hwq = phy->q_tx[mt76_txq_get_qid(txq)]; mtxq = (struct mt76_txq *)txq->drv_priv; spin_lock_bh(&hwq->lock); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index f1ae9ff835b2..dc850109de22 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -627,7 +627,7 @@ static void mt76u_complete_rx(struct urb *urb) q->head = (q->head + 1) % q->ndesc; q->queued++; - tasklet_schedule(&dev->usb.rx_tasklet); + mt76_worker_schedule(&dev->usb.rx_worker); out: spin_unlock_irqrestore(&q->lock, flags); } @@ -665,13 +665,17 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) } mt76u_submit_rx_buf(dev, qid, urb); } - if (qid == MT_RXQ_MAIN) + if (qid == MT_RXQ_MAIN) { + local_bh_disable(); mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL); + local_bh_enable(); + } } -static void mt76u_rx_tasklet(unsigned long data) +static void mt76u_rx_worker(struct mt76_worker *w) { - struct mt76_dev *dev = (struct mt76_dev *)data; + struct mt76_usb *usb = container_of(w, struct mt76_usb, rx_worker); + struct mt76_dev *dev = container_of(usb, struct mt76_dev, usb); int i; rcu_read_lock(); @@ -737,8 +741,13 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) struct page *page; int i; - for (i = 0; i < q->ndesc; i++) + for (i = 0; i < q->ndesc; i++) { + if (!q->entry[i].urb) + continue; + mt76u_urb_free(q->entry[i].urb); + q->entry[i].urb = NULL; + } if (!q->rx_page.va) return; @@ -752,6 +761,8 @@ static void mt76u_free_rx(struct mt76_dev *dev) { int i; + mt76_worker_teardown(&dev->usb.rx_worker); + mt76_for_each_q_rx(dev, i) mt76u_free_rx_queue(dev, &dev->q_rx[i]); } @@ -760,6 +771,8 @@ void mt76u_stop_rx(struct mt76_dev *dev) { int i; + mt76_worker_disable(&dev->usb.rx_worker); + mt76_for_each_q_rx(dev, i) { struct mt76_queue *q = &dev->q_rx[i]; int j; @@ -767,8 +780,6 @@ void mt76u_stop_rx(struct mt76_dev *dev) for (j = 0; j < q->ndesc; j++) usb_poison_urb(q->entry[j].urb); } - - tasklet_kill(&dev->usb.rx_tasklet); } EXPORT_SYMBOL_GPL(mt76u_stop_rx); @@ -788,20 +799,23 @@ int mt76u_resume_rx(struct mt76_dev *dev) return err; } + mt76_worker_enable(&dev->usb.rx_worker); + return 0; } EXPORT_SYMBOL_GPL(mt76u_resume_rx); -static void mt76u_tx_worker(struct mt76_worker *w) +static void mt76u_status_worker(struct mt76_worker *w) { - struct mt76_dev *dev = container_of(w, struct mt76_dev, tx_worker); + struct mt76_usb *usb = container_of(w, struct mt76_usb, status_worker); + struct mt76_dev *dev = container_of(usb, struct mt76_dev, usb); struct mt76_queue_entry entry; struct mt76_queue *q; bool wake; int i; for (i = 0; i < IEEE80211_NUM_ACS; i++) { - q = dev->q_tx[i]; + q = dev->phy.q_tx[i]; while (q->queued > 0) { if (!q->entry[q->tail].done) @@ -820,7 +834,7 @@ static void mt76u_tx_worker(struct mt76_worker *w) if (!q->queued) wake_up(&dev->tx_wait); - mt76_txq_schedule(&dev->phy, i); + mt76_worker_schedule(&dev->tx_worker); if (dev->drv->tx_status_data && !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) @@ -864,7 +878,7 @@ static void mt76u_complete_tx(struct urb *urb) dev_err(dev->dev, "tx urb failed: %d\n", urb->status); e->done = true; - mt76_worker_schedule(&dev->tx_worker); + mt76_worker_schedule(&dev->usb.status_worker); } static int @@ -887,11 +901,10 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb, } static int -mt76u_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { - struct mt76_queue *q = dev->q_tx[qid]; struct mt76_tx_info tx_info = { .skb = skb, }; @@ -902,7 +915,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, return -ENOSPC; skb->prev = skb->next = NULL; - err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info); + err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info); if (err < 0) return err; @@ -970,7 +983,7 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) for (i = 0; i <= MT_TXQ_PSD; i++) { if (i >= IEEE80211_NUM_ACS) { - dev->q_tx[i] = dev->q_tx[0]; + dev->phy.q_tx[i] = dev->phy.q_tx[0]; continue; } @@ -980,7 +993,9 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) spin_lock_init(&q->lock); q->hw_idx = mt76u_ac_to_hwq(dev, i); - dev->q_tx[i] = q; + q->qid = i; + + dev->phy.q_tx[i] = q; q->entry = devm_kcalloc(dev->dev, MT_NUM_TX_ENTRIES, sizeof(*q->entry), @@ -1003,16 +1018,20 @@ static void mt76u_free_tx(struct mt76_dev *dev) { int i; + mt76_worker_teardown(&dev->usb.status_worker); + for (i = 0; i < IEEE80211_NUM_ACS; i++) { struct mt76_queue *q; int j; - q = dev->q_tx[i]; + q = dev->phy.q_tx[i]; if (!q) continue; - for (j = 0; j < q->ndesc; j++) + for (j = 0; j < q->ndesc; j++) { usb_free_urb(q->entry[j].urb); + q->entry[j].urb = NULL; + } } } @@ -1020,6 +1039,8 @@ void mt76u_stop_tx(struct mt76_dev *dev) { int ret; + mt76_worker_disable(&dev->usb.status_worker); + ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(&dev->phy), HZ / 5); if (!ret) { @@ -1030,7 +1051,7 @@ void mt76u_stop_tx(struct mt76_dev *dev) dev_err(dev->dev, "timed out waiting for pending tx\n"); for (i = 0; i < IEEE80211_NUM_ACS; i++) { - q = dev->q_tx[i]; + q = dev->phy.q_tx[i]; if (!q) continue; @@ -1044,7 +1065,7 @@ void mt76u_stop_tx(struct mt76_dev *dev) * will fail to submit urb, cleanup those skb's manually. */ for (i = 0; i < IEEE80211_NUM_ACS; i++) { - q = dev->q_tx[i]; + q = dev->phy.q_tx[i]; if (!q) continue; @@ -1061,6 +1082,8 @@ void mt76u_stop_tx(struct mt76_dev *dev) cancel_work_sync(&dev->usb.stat_work); clear_bit(MT76_READING_STATS, &dev->phy.state); + mt76_worker_enable(&dev->usb.status_worker); + mt76_tx_status_check(dev, NULL, true); } EXPORT_SYMBOL_GPL(mt76u_stop_tx); @@ -1103,15 +1126,13 @@ int mt76u_init(struct mt76_dev *dev, }; struct usb_device *udev = interface_to_usbdev(intf); struct mt76_usb *usb = &dev->usb; - int err = -ENOMEM; + int err; mt76u_ops.rr = ext ? mt76u_rr_ext : mt76u_rr; mt76u_ops.wr = ext ? mt76u_wr_ext : mt76u_wr; mt76u_ops.rmw = ext ? mt76u_rmw_ext : mt76u_rmw; mt76u_ops.write_copy = ext ? mt76u_copy_ext : mt76u_copy; - dev->tx_worker.fn = mt76u_tx_worker; - tasklet_init(&usb->rx_tasklet, mt76u_rx_tasklet, (unsigned long)dev); INIT_WORK(&usb->stat_work, mt76u_tx_status_data); usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1); @@ -1120,7 +1141,7 @@ int mt76u_init(struct mt76_dev *dev, usb->data = devm_kmalloc(dev->dev, usb->data_len, GFP_KERNEL); if (!usb->data) - goto error; + return -ENOMEM; mutex_init(&usb->usb_ctrl_mtx); dev->bus = &mt76u_ops; @@ -1132,14 +1153,22 @@ int mt76u_init(struct mt76_dev *dev, err = mt76u_set_endpoints(intf, usb); if (err < 0) - goto error; + return err; - return 0; + err = mt76_worker_setup(dev->hw, &usb->rx_worker, mt76u_rx_worker, + "usb-rx"); + if (err) + return err; + + err = mt76_worker_setup(dev->hw, &usb->status_worker, + mt76u_status_worker, "usb-status"); + if (err) + return err; -error: - destroy_workqueue(dev->wq); + sched_set_fifo_low(usb->rx_worker.task); + sched_set_fifo_low(usb->status_worker.task); - return err; + return 0; } EXPORT_SYMBOL_GPL(mt76u_init); |