introduce mt7921e support
Subsystems (3)
[email protected]
reviewerv5 cover introduce mt7921e support
From: Sean Wang <[email protected]>
Introduce support for mt7921e 802.11ax (Wi-Fi 6) 2x2:2SS chipset.
v2:
- Mark the patch as -next
v3:
- Remove sw scan support
- Get rid of dbdc code
- Run mt7921_configure_filter hodling mt76 mutex
- Correct Txp programming in Txd
- Correct fw log to host command
- Correct eeprom offset definition
- Update rate adaption info report
- Remove unused code and fields in struture
- Split the previous driver into several patches for easy review
v4:
- introduce sched scan support
- introduce 802.11 PS support in sta mode
- introduce support for hardware beacon filter
- introduce beacon_loss mcu event
- introduce PM support
- refine sta_rec_phy and add sta_rec_ra_info
- remove incorrect mt7921_mcu_tx_config member
- fix erroneous endianness conversion in mt7921_tx_complete_skb()
- fix endianness warning in mt7921_get_wtbl_info()
- fix endianness warnings in mt7921_mcu_sta_tlv()
- remove unused code in mt7921_mcu_send_message
- remove scan with random mac until fw is ready
- channel domain is added for hw scan
v5:
- fix implicit conversion from enumeration type
- remove unused function declaration
- drop zero-length packet to avoid Tx hang
- fix MT_CIPHER_BIP_CMAC_128 setkey
- reset token when mac_reset happens
- create mac.h when mac support is added
- reorder the patch of adding module support
- move mac_work in mt76_core module
- move chainmask in mt76_phy
- rebase per moving mac_work in mt76_core module
- rebase per moving chainmask in mt76_phy
Lorenzo Bianconi (2):
mt76: move mac_work in mt76_core module
mt76: move chainmask in mt76_phy
Sean Wang (13):
mt76: mt7921: add MAC support
mt76: mt7921: add MCU support
mt76: mt7921: add DMA support
mt76: mt7921: add EEPROM support
mt76: mt7921: add ieee80211_ops
mt76: mt7921: introduce mt7921e support
mt76: mt7921: add debugfs support
mt76: mt7921: add module support
mt76: mt7921: introduce schedule scan support
mt76: mt7921: introduce 802.11 PS support in sta mode
mt76: mt7921: introduce support for hardware beacon filter
mt76: mt7921: introduce beacon_loss mcu event
mt76: mt7921: introduce PM support
drivers/net/wireless/mediatek/mt76/Kconfig | 1 + drivers/net/wireless/mediatek/mt76/Makefile | 1 + drivers/net/wireless/mediatek/mt76/mt76.h | 5 +- .../net/wireless/mediatek/mt76/mt7603/init.c | 2 +- .../net/wireless/mediatek/mt76/mt7603/mac.c | 14 +- .../net/wireless/mediatek/mt76/mt7603/main.c | 10 +- .../wireless/mediatek/mt76/mt7603/mt7603.h | 2 - .../wireless/mediatek/mt76/mt7615/eeprom.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/init.c | 16 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 27 +- .../net/wireless/mediatek/mt76/mt7615/main.c | 15 +- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 4 +- .../wireless/mediatek/mt76/mt7615/mt7615.h | 5 - .../wireless/mediatek/mt76/mt7615/testmode.c | 4 +- .../net/wireless/mediatek/mt76/mt7615/usb.c | 2 +- .../net/wireless/mediatek/mt76/mt76x0/pci.c | 4 +- .../net/wireless/mediatek/mt76/mt76x0/usb.c | 4 +- drivers/net/wireless/mediatek/mt76/mt76x02.h | 2 - .../net/wireless/mediatek/mt76/mt76x02_mac.c | 10 +- .../net/wireless/mediatek/mt76/mt76x02_phy.c | 4 +- .../net/wireless/mediatek/mt76/mt76x02_util.c | 6 +- .../net/wireless/mediatek/mt76/mt76x2/mcu.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_init.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_main.c | 4 +- .../wireless/mediatek/mt76/mt76x2/usb_init.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +- .../wireless/mediatek/mt76/mt7915/eeprom.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/init.c | 17 +- .../net/wireless/mediatek/mt76/mt7915/mac.c | 31 +- .../net/wireless/mediatek/mt76/mt7915/main.c | 11 +- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 8 +- .../wireless/mediatek/mt76/mt7915/mt7915.h | 3 - .../wireless/mediatek/mt76/mt7915/testmode.c | 2 +- .../net/wireless/mediatek/mt76/mt7921/Kconfig | 10 + .../wireless/mediatek/mt76/mt7921/Makefile | 5 + .../wireless/mediatek/mt76/mt7921/debugfs.c | 178 + .../net/wireless/mediatek/mt76/mt7921/dma.c | 356 ++ .../wireless/mediatek/mt76/mt7921/eeprom.c | 101 + .../wireless/mediatek/mt76/mt7921/eeprom.h | 27 + .../net/wireless/mediatek/mt76/mt7921/init.c | 254 ++ .../net/wireless/mediatek/mt76/mt7921/mac.c | 1393 ++++++++ .../net/wireless/mediatek/mt76/mt7921/mac.h | 333 ++ .../net/wireless/mediatek/mt76/mt7921/main.c | 1051 ++++++ .../net/wireless/mediatek/mt76/mt7921/mcu.c | 2932 +++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/mcu.h | 1175 +++++++ .../wireless/mediatek/mt76/mt7921/mt7921.h | 377 +++ .../net/wireless/mediatek/mt76/mt7921/pci.c | 279 ++ .../net/wireless/mediatek/mt76/mt7921/regs.h | 413 +++ 48 files changed, 8995 insertions(+), 115 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/Kconfig create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/Makefile create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/dma.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/eeprom.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/init.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mac.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mac.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/main.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mcu.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mcu.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/pci.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/regs.h
--
2.25.1
_______________________________________________
Linux-mediatek mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 10/15 mt76: mt7921: add module support
From: Sean Wang <[email protected]>
Add mt7921 as the pci driver module.
The purpose of the patch is to check about if the following patches are able to compile properly.
--- drivers/net/wireless/mediatek/mt76/Kconfig | 1 + drivers/net/wireless/mediatek/mt76/Makefile | 1 + drivers/net/wireless/mediatek/mt76/mt7921/Kconfig | 10 ++++++++++ drivers/net/wireless/mediatek/mt76/mt7921/Makefile | 5 +++++ 4 files changed, 17 insertions(+) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/Kconfig create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/Makefile
drivers/net/wireless/mediatek/mt76/Kconfig +1 -0
@@ -29,3 +29,4 @@ source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7915/Kconfig" +source "drivers/net/wireless/mediatek/mt76/mt7921/Kconfig"
drivers/net/wireless/mediatek/mt76/Makefile +1 -0
@@ -31,3 +31,4 @@ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ obj-$(CONFIG_MT7603E) += mt7603/ obj-$(CONFIG_MT7615_COMMON) += mt7615/ obj-$(CONFIG_MT7915E) += mt7915/ +obj-$(CONFIG_MT7921E) += mt7921/
drivers/net/wireless/mediatek/mt76/mt7921/Kconfig new file +10 -0
@@ -0,0 +1,10 @@ +# SPDX-License-Identifier: ISC +config MT7921E + tristate "MediaTek MT7921E (PCIe) support" + select MT76_CORE + depends on MAC80211 + depends on PCI + help + This adds support for MT7921E 802.11ax 2x2:2SS wireless devices. + + To compile this driver as a module, choose M here.
drivers/net/wireless/mediatek/mt76/mt7921/Makefile new file +5 -0
@@ -0,0 +1,5 @@ +#SPDX-License-Identifier: ISC + +obj-$(CONFIG_MT7921E) += mt7921e.o + +mt7921e-y := pci.o mac.o mcu.o dma.o eeprom.o main.o init.o debugfs.o
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 14/15 mt76: mt7921: introduce beacon_loss mcu event
In reply to [email protected]From: Sean Wang <[email protected]>
If device has enabled beacon hw filter rx beacons are not reported to the host. Introduce beacon_loss mcu event to trigger mac80211 mlme connection state machine in this configuration. IEEE80211_VIF_BEACON_FILTER has not set in vif flags since hw beacon filter is not enabled yet
--- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 35 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/mcu.h | 6 ++++ 2 files changed, 41 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +35 -0
@@ -543,6 +543,40 @@ mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb) MT7921_HW_SCAN_TIMEOUT); } +static void +mt7921_mcu_beacon_loss_iter (void *priv,u8 *mac,struct ieee80211_vif *vif) +{ +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; +struct mt7921_beacon_loss_event *event = priv; + +if (mvif->idx != event->bss_idx) +return ; + +if (!(vif->driver_flags &IEEE80211_VIF_BEACON_FILTER )) +return ; + +ieee80211_beacon_loss (vif); +} + +static void +mt7921_mcu_beacon_loss_event (struct mt7921_dev *dev,struct sk_buff *skb) +{ +struct mt7921_beacon_loss_event *event; +struct mt76_phy *mphy; +u8 band_idx =0 ;/* DBDC support */ + +skb_pull (skb,sizeof (struct mt7921_mcu_rxd )); + event = (struct mt7921_beacon_loss_event *)skb->data; +if (band_idx && dev->mt76.phy2) + mphy = dev->mt76.phy2; +else + mphy = &dev->mt76.phy; + +ieee80211_iterate_active_interfaces_atomic (mphy->hw, +IEEE80211_IFACE_ITER_RESUME_ALL , + mt7921_mcu_beacon_loss_iter, event); +} +static void mt7921_mcu_bss_event (struct mt7921_dev *dev,struct sk_buff *skb) {
@@ -593,6 +627,7 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)switch (rxd->eid) {case MCU_EVENT_BSS_BEACON_LOSS : +mt7921_mcu_beacon_loss_event (dev, skb);break ;case MCU_EVENT_SCHED_SCAN_DONE :case MCU_EVENT_SCAN_DONE :
drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +6 -0
@@ -783,6 +783,12 @@ struct mt7921_bss_qos_tlv {u8 pad[3 ]; } __packed; +struct mt7921_beacon_loss_event { +u8 bss_idx; +u8 reason; +u8 pad[2 ]; +} __packed; +struct mt7921_mcu_scan_ssid {__le32 ssid_len;u8 ssid[IEEE80211_MAX_SSID_LEN ];
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 12/15 mt76: mt7921: introduce 802.11 PS support in sta mode
In reply to [email protected]From: Sean Wang <[email protected]>
Enable 802.11 power-save support available in mt7921 firmware
--- .../net/wireless/mediatek/mt76/mt7921/init.c | 2 ++ .../net/wireless/mediatek/mt76/mt7921/mac.c | 3 +-- .../net/wireless/mediatek/mt76/mt7921/main.c | 3 +++ .../net/wireless/mediatek/mt76/mt7921/mcu.c | 21 +++++++++++++++++++ .../wireless/mediatek/mt76/mt7921/mt7921.h | 1 + 5 files changed, 28 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/init.c +2 -0
@@ -83,6 +83,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)ieee80211_hw_set (hw,HAS_RATE_CONTROL );ieee80211_hw_set (hw,SUPPORTS_TX_ENCAP_OFFLOAD );ieee80211_hw_set (hw,WANT_MONITOR_VIF ); +ieee80211_hw_set (hw,SUPPORTS_PS ); +ieee80211_hw_set (hw,SUPPORTS_DYNAMIC_PS ); hw->max_tx_fragments =4 ; }
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +1 -2
@@ -690,8 +690,7 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, txwi[1 ] =cpu_to_le32 (val); txwi[2 ] =0 ; - val =MT_TXD3_SW_POWER_MGMT | -FIELD_PREP (MT_TXD3_REM_TX_COUNT , tx_count); + val =FIELD_PREP (MT_TXD3_REM_TX_COUNT , tx_count);if (key) val |=MT_TXD3_PROTECT_FRAME ;if (info->flags &IEEE80211_TX_CTL_NO_ACK )
drivers/net/wireless/mediatek/mt76/mt7921/main.c +3 -0
@@ -560,6 +560,9 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,if (changed & (BSS_CHANGED_QOS |BSS_CHANGED_BEACON_ENABLED ))mt7921_mcu_set_tx (dev, vif); +if (changed &BSS_CHANGED_PS ) +mt7921_mcu_set_vif_ps (dev, vif); +mutex_unlock (&dev->mt76.mutex); }
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +21 -0
@@ -2527,3 +2527,24 @@ u32 mt7921_get_wtbl_info(struct mt7921_dev *dev, u16 wlan_idx)return 0 ; } + +int mt7921_mcu_set_vif_ps (struct mt7921_dev *dev,struct ieee80211_vif *vif) +{ +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; +struct { +u8 bss_idx; +u8 ps_state;/* 0: device awake +* 1: static power save +* 2: dynamic power saving +*/ + } req = { + .bss_idx = mvif->idx, + .ps_state = vif->bss_conf.ps ?2 :0 , + }; + +if (vif->type !=NL80211_IFTYPE_STATION ) +return -EOPNOTSUPP ; + +return mt76_mcu_send_msg (&dev->mt76,MCU_CMD_SET_PS_PROFILE , &req, +sizeof (req), false); +}
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +1 -0
@@ -362,4 +362,5 @@ int mt7921_mcu_sched_scan_enable(struct mt7921_phy *phy,int mt7921_mcu_cancel_hw_scan (struct mt7921_phy *phy,struct ieee80211_vif *vif);u32 mt7921_get_wtbl_info (struct mt7921_dev *dev,u16 wlan_idx); +int mt7921_mcu_set_vif_ps (struct mt7921_dev *dev,struct ieee80211_vif *vif);#endif
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 6/15 mt76: mt7921: add EEPROM support
In reply to [email protected]From: Sean Wang <[email protected]>
Add EEPROM support to MT7921 to determine the capability the card has such as indentificaiton, MAC address, the band and antenna number the card able to support.
--- .../wireless/mediatek/mt76/mt7921/eeprom.c | 101 ++++++++++++++++++ .../wireless/mediatek/mt76/mt7921/eeprom.h | 27 +++++ 2 files changed, 128 insertions(+) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/eeprom.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h
drivers/net/wireless/mediatek/mt76/mt7921/eeprom.c new file +101 -0
@@ -0,0 +1,101 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include "mt7921.h" +#include "eeprom.h" + +static u32 mt7921_eeprom_read (struct mt7921_dev *dev,u32 offset) +{ +u8 *data = dev->mt76.eeprom.data; + +if (data[offset] ==0xff ) +mt7921_mcu_get_eeprom (dev, offset); + +return data[offset]; +} + +static int mt7921_eeprom_load (struct mt7921_dev *dev) +{ +int ret; + + ret =mt76_eeprom_init (&dev->mt76,MT7921_EEPROM_SIZE ); +if (ret <0 ) +return ret; + +memset (dev->mt76.eeprom.data,-1 ,MT7921_EEPROM_SIZE ); + +return 0 ; +} + +static int mt7921_check_eeprom (struct mt7921_dev *dev) +{ +u8 *eeprom = dev->mt76.eeprom.data; +u16 val; + +mt7921_eeprom_read (dev,MT_EE_CHIP_ID ); + val =get_unaligned_le16 (eeprom); + +switch (val) { +case 0x7961 : +return 0 ; +default : +return -EINVAL ; + } +} + +void mt7921_eeprom_parse_band_config (struct mt7921_phy *phy) +{ +struct mt7921_dev *dev = phy->dev; +u32 val; + + val =mt7921_eeprom_read (dev,MT_EE_WIFI_CONF ); + val =FIELD_GET (MT_EE_WIFI_CONF_BAND_SEL , val); + +switch (val) { +case MT_EE_5GHZ : + phy->mt76->cap.has_5ghz = true; +break ; +case MT_EE_2GHZ : + phy->mt76->cap.has_2ghz = true; +break ; +default : + phy->mt76->cap.has_2ghz = true; + phy->mt76->cap.has_5ghz = true; +break ; + } +} + +static void mt7921_eeprom_parse_hw_cap (struct mt7921_dev *dev) +{ +u8 tx_mask, *eeprom = dev->mt76.eeprom.data; + +mt7921_eeprom_parse_band_config (&dev->phy); + +/* read tx mask from eeprom (0: 1Tx, 1: 2Tx) */ + tx_mask =FIELD_GET (MT_EE_WIFI_CONF_TX_MASK , eeprom[MT_EE_WIFI_CONF ]); + tx_mask = tx_mask +1 ; + dev->chainmask =BIT (tx_mask) -1 ; + dev->mphy.antenna_mask = dev->chainmask; + dev->mphy.chainmask = dev->mphy.antenna_mask; +} + +int mt7921_eeprom_init (struct mt7921_dev *dev) +{ +int ret; + + ret =mt7921_eeprom_load (dev); +if (ret <0 ) +return ret; + + ret =mt7921_check_eeprom (dev); +if (ret) +return ret; + +mt7921_eeprom_parse_hw_cap (dev); +memcpy (dev->mphy.macaddr, dev->mt76.eeprom.data +MT_EE_MAC_ADDR , +ETH_ALEN ); + +mt76_eeprom_override (&dev->mphy); + +return 0 ; +}
drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h new file +27 -0
@@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2020 MediaTek Inc. */ + +#ifndef __MT7921_EEPROM_H +#define __MT7921_EEPROM_H + +#include "mt7921.h" + +enum mt7921_eeprom_field { +MT_EE_CHIP_ID =0x000 , +MT_EE_VERSION =0x002 , +MT_EE_MAC_ADDR =0x004 , +MT_EE_WIFI_CONF =0x07c , + __MT_EE_MAX =0x3bf +}; + +#define MT_EE_WIFI_CONF_TX_MASK BIT(0) +#define MT_EE_WIFI_CONF_BAND_SEL GENMASK(3, 2) + +enum mt7921_eeprom_band { +MT_EE_NA , +MT_EE_5GHZ , +MT_EE_2GHZ , +MT_EE_DUAL_BAND , +}; + +#endif
Signature · 1 line
2.25.1
[email protected]
reviewerPATCH v5 11/15 mt76: mt7921: introduce schedule scan support
In reply to [email protected]From: Sean Wang <[email protected]>
introduce schedule scan to control mt7921 firmware to do background scan in defined plan to see if the matched SSID is available.
--- .../net/wireless/mediatek/mt76/mt7921/init.c | 5 ++ .../net/wireless/mediatek/mt76/mt7921/main.c | 38 +++++++++ .../net/wireless/mediatek/mt76/mt7921/mcu.c | 83 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/mcu.h | 20 +++++ .../wireless/mediatek/mt76/mt7921/mt7921.h | 9 ++ 5 files changed, 155 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7921/init.c +5 -0
@@ -70,6 +70,11 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy->n_iface_combinations =ARRAY_SIZE (if_comb); wiphy->max_scan_ie_len =MT7921_SCAN_IE_LEN ; wiphy->max_scan_ssids =4 ; + wiphy->max_sched_scan_plan_interval =MT7921_MAX_SCHED_SCAN_INTERVAL ; + wiphy->max_sched_scan_ie_len =IEEE80211_MAX_DATA_LEN ; + wiphy->max_sched_scan_ssids =MT7921_MAX_SCHED_SCAN_SSID ; + wiphy->max_match_sets =MT7921_MAX_SCAN_MATCH ; + wiphy->max_sched_scan_reqs =1 ; wiphy->flags |=WIPHY_FLAG_HAS_CHANNEL_SWITCH ;wiphy_ext_feature_set (wiphy,NL80211_EXT_FEATURE_SET_SCAN_DWELL );
drivers/net/wireless/mediatek/mt76/mt7921/main.c +38 -0
@@ -865,6 +865,42 @@ mt7921_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)mutex_unlock (&dev->mt76.mutex); } +static int +mt7921_start_sched_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif, +struct cfg80211_sched_scan_request *req, +struct ieee80211_scan_ies *ies) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt76_phy *mphy = hw->priv; +int err; + +mutex_lock (&dev->mt76.mutex); + + err =mt7921_mcu_sched_scan_req (mphy->priv, vif, req); +if (err <0 ) + goto out; + + err =mt7921_mcu_sched_scan_enable (mphy->priv, vif, true); +out: +mutex_unlock (&dev->mt76.mutex); + +return err; +} + +static int +mt7921_stop_sched_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt76_phy *mphy = hw->priv; +int err; + +mutex_lock (&dev->mt76.mutex); + err =mt7921_mcu_sched_scan_enable (mphy->priv, vif, false); +mutex_unlock (&dev->mt76.mutex); + +return err; +} +static int mt7921_set_antenna (struct ieee80211_hw *hw,u32 tx_ant,u32 rx_ant) {
@@ -928,4 +964,6 @@ const struct ieee80211_ops mt7921_ops = { .set_coverage_class = mt7921_set_coverage_class, .hw_scan = mt7921_hw_scan, .cancel_hw_scan = mt7921_cancel_hw_scan, + .sched_scan_start = mt7921_start_sched_scan, + .sched_scan_stop = mt7921_stop_sched_scan, };
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +83 -0
89 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +20 -0
@@ -879,6 +879,26 @@ struct mt7921_hw_scan_done {__le32 beacon_5g_num; } __packed; +struct mt7921_sched_scan_req { +u8 version; +u8 seq_num; +u8 stop_on_match; +u8 ssids_num; +u8 match_num; +u8 pad; +__le16 ie_len; +struct mt7921_mcu_scan_ssid ssids[MT7921_MAX_SCHED_SCAN_SSID ]; +struct mt7921_mcu_scan_match match[MT7921_MAX_SCAN_MATCH ]; +u8 channel_type; +u8 channels_num; +u8 intervals_num; +u8 scan_func; +struct mt7921_mcu_scan_channel channels[64 ]; +__le16 intervals[MT7921_MAX_SCHED_SCAN_INTERVAL ]; +u8 bss_idx; +u8 pad2[64 ]; +} __packed; +struct mt7921_mcu_bss_event {u8 bss_idx;u8 is_absent;
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +9 -0
@@ -44,6 +44,9 @@#define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1)#define MT7921_SCAN_IE_LEN 600 +#define MT7921_MAX_SCHED_SCAN_INTERVAL 10 +#define MT7921_MAX_SCHED_SCAN_SSID 10 +#define MT7921_MAX_SCAN_MATCH 16struct mt7921_vif ;struct mt7921_sta ;
@@ -350,6 +353,12 @@ void mt7921_scan_work(struct work_struct *work);int mt7921_mcu_set_channel_domain (struct mt7921_phy *phy);int mt7921_mcu_hw_scan (struct mt7921_phy *phy,struct ieee80211_vif *vif,struct ieee80211_scan_request *scan_req); +int mt7921_mcu_sched_scan_req (struct mt7921_phy *phy, +struct ieee80211_vif *vif, +struct cfg80211_sched_scan_request *sreq); +int mt7921_mcu_sched_scan_enable (struct mt7921_phy *phy, +struct ieee80211_vif *vif, +bool enable);int mt7921_mcu_cancel_hw_scan (struct mt7921_phy *phy,struct ieee80211_vif *vif);u32 mt7921_get_wtbl_info (struct mt7921_dev *dev,u16 wlan_idx);
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 2/15 mt76: move chainmask in mt76_phy
In reply to [email protected]From: Lorenzo Bianconi <[email protected]>
Move chainmask from driver phy to mt76_phy since it is used by all drivers. This is a preliminary patch to create a common mcu library used by mt7615 and mt7921 drivers
--- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 12 ++++++------ drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 2 -- .../net/wireless/mediatek/mt76/mt7615/testmode.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x02.h | 2 -- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt76x02_phy.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c | 2 +- .../net/wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 13 ++++++------- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 1 - .../net/wireless/mediatek/mt76/mt7915/testmode.c | 2 +- 21 files changed, 37 insertions(+), 42 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +1 -0
@@ -579,6 +579,7 @@ struct mt76_phy {int txpower_cur;u8 antenna_mask; +u16 chainmask;#ifdef CONFIG_NL80211_TESTMODE struct mt76_testmode_data test;
drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +1 -1
@@ -161,7 +161,7 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) dev->chainmask =BIT (tx_mask) -1 ; dev->mphy.antenna_mask = dev->chainmask; - dev->phy.chainmask = dev->chainmask; + dev->mphy.chainmask = dev->chainmask; } static int mt7663_eeprom_get_target_power_index(struct mt7615_dev *dev,
drivers/net/wireless/mediatek/mt76/mt7615/init.c +6 -6
@@ -362,9 +362,9 @@ mt7615_cap_dbdc_enable(struct mt7615_dev *dev) 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; + dev->mphy.chainmask = dev->mphy.antenna_mask; + dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; + dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;mt76_set_stream_caps (&dev->mphy, true); }
@@ -375,7 +375,7 @@ mt7615_cap_dbdc_disable(struct mt7615_dev *dev)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.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);
@@ -404,8 +404,8 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) phy = mphy->priv; phy->dev = dev; phy->mt76 = mphy; - phy->chainmask = dev->chainmask & ~dev->phy.chainmask; - mphy->antenna_mask =BIT (hweight8 (phy->chainmask)) -1 ; + mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask; + mphy->antenna_mask =BIT (hweight8 (mphy->chainmask)) -1 ;mt7615_init_wiphy (mphy->hw);INIT_DELAYED_WORK (&mphy->mac_work, mt7615_mac_work);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +1 -1
@@ -326,7 +326,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)* that PHY. */ if (phy_idx <0 ) { -int first_chain =ffs (phy2->chainmask) -1 ; +int first_chain =ffs (phy2->mt76->chainmask) -1 ; phy_idx = ((rxdg5 >> (first_chain *8 )) &0xff ) ==0 ; }
drivers/net/wireless/mediatek/mt76/mt7615/main.c +1 -1
@@ -911,7 +911,7 @@ mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)else tx_ant <<=1 ; } - phy->chainmask = tx_ant; + phy->mt76->chainmask = tx_ant;mt76_set_stream_caps (phy->mt76, true);
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +2 -2
@@ -1662,7 +1662,7 @@ mt7615_mcu_uni_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif, .center_chan = ieee80211_frequency_to_channel(freq1), .center_chan2 = ieee80211_frequency_to_channel(freq2), .tx_streams = hweight8(phy->mt76->antenna_mask), - .rx_streams = phy->chainmask, + .rx_streams = phy->mt76->chainmask, .short_st = true, }, };
@@ -2880,7 +2880,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) .control_chan = chandef->chan->hw_value, .center_chan = ieee80211_frequency_to_channel(freq1), .tx_streams = hweight8(phy->mt76->antenna_mask), - .rx_streams_mask = phy->chainmask, + .rx_streams_mask = phy->mt76->chainmask, .center_chan2 = ieee80211_frequency_to_channel(freq2), };
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +0 -2
@@ -171,8 +171,6 @@ struct mt7615_phy {s8 ofdm_sensitivity;s8 cck_sensitivity; -u16 chainmask; -s16 coverage_class;u8 slottime;
drivers/net/wireless/mediatek/mt76/mt7615/testmode.c +2 -2
@@ -178,7 +178,7 @@ mt7615_tm_set_tx_antenna(struct mt7615_phy *phy, bool en)return ;if (!en) - mask = phy->chainmask; + mask = phy->mt76->chainmask;for (i =0 ; i <4 ; i++) { mt76_rmw_field(dev, MT_WF_PHY_RFINTF3_0(i),
@@ -306,7 +306,7 @@ mt7615_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb, td->state == MT76_TM_STATE_OFF)return 0 ; -if (td->tx_antenna_mask & ~phy->chainmask) +if (td->tx_antenna_mask & ~mphy->chainmask)return -EINVAL ;for (i =0 ; i <ARRAY_SIZE (tm_change_map); i++) {
drivers/net/wireless/mediatek/mt76/mt76x02.h +0 -2
@@ -82,8 +82,6 @@ struct mt76x02_dev {struct mutex phy_mutex; -u16 chainmask; -u8 txdone_seq; DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);spinlock_t txstatus_fifo_lock;
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +3 -3
@@ -345,7 +345,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,u16 txwi_flags =0 ;u8 nss;s8 txpwr_adj, max_txpwr_adj; -u8 ccmp_pn[8 ], nstreams = dev->chainmask &0xf ; +u8 ccmp_pn[8 ], nstreams = dev->mphy.chainmask &0xf ;memset (txwi,0 ,sizeof (*txwi));
@@ -685,7 +685,7 @@ mt76x02_mac_process_rate(struct mt76x02_dev *dev, status->rate_idx = idx;break ;case MT_PHY_TYPE_VHT : { -u8 n_rxstream = dev->chainmask &0xf ; +u8 n_rxstream = dev->mphy.chainmask &0xf ; status->encoding =RX_ENC_VHT ; status->rate_idx =FIELD_GET (MT_RATE_INDEX_VHT_IDX , idx);
@@ -777,7 +777,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,u16 rate =le16_to_cpu (rxwi->rate);u16 tid_sn =le16_to_cpu (rxwi->tid_sn);bool unicast = rxwi->rxinfo &cpu_to_le32 (MT_RXINFO_UNICAST ); -int pad_len =0 , nstreams = dev->chainmask &0xf ; +int pad_len =0 , nstreams = dev->mphy.chainmask &0xf ;s8 signal;u8 pn_len;u8 wcid;
drivers/net/wireless/mediatek/mt76/mt76x02_phy.c +2 -2
@@ -16,7 +16,7 @@ void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev) val =mt76_rr (dev,MT_BBP (AGC ,0 )); val &= ~BIT (4 ); -switch (dev->chainmask &0xf ) { +switch (dev->mphy.chainmask &0xf ) {case 2 : val |=BIT (3 );break ;
@@ -35,7 +35,7 @@ void mt76x02_phy_set_txdac(struct mt76x02_dev *dev) {int txpath; - txpath = (dev->chainmask >>8 ) &0xf ; + txpath = (dev->mphy.chainmask >>8 ) &0xf ;switch (txpath) {case 2 :mt76_set (dev,MT_BBP (TXBE ,5 ),0x3 );
drivers/net/wireless/mediatek/mt76/mt76x02_util.c +2 -2
@@ -197,10 +197,10 @@ void mt76x02_init_device(struct mt76x02_dev *dev)IEEE80211_HT_CAP_LDPC_CODING ; dev->mphy.sband_5g.sband.ht_cap.cap |=IEEE80211_HT_CAP_LDPC_CODING ; - dev->chainmask =0x202 ; + dev->mphy.chainmask =0x202 ; dev->mphy.antenna_mask =3 ; }else { - dev->chainmask =0x101 ; + dev->mphy.chainmask =0x101 ; dev->mphy.antenna_mask =1 ; } }
drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c +1 -1
@@ -29,7 +29,7 @@ int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, .idx = channel, .scan = scan, .bw = bw, - .chainmask = cpu_to_le16(dev->chainmask), + .chainmask = cpu_to_le16(dev->mphy.chainmask), };/* first set the channel without the extension channel info */
drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +1 -1
@@ -116,7 +116,7 @@ static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,mutex_lock (&dev->mt76.mutex); - dev->chainmask = (tx_ant ==3 ) ?0x202 :0x101 ; + dev->mphy.chainmask = (tx_ant ==3 ) ?0x202 :0x101 ; dev->mphy.antenna_mask = tx_ant;mt76_set_stream_caps (&dev->mphy, true);
drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +1 -1
@@ -89,7 +89,7 @@ static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev) dev->chainmask =BIT (nss) -1 ; dev->mphy.antenna_mask =BIT (tx_mask[0 ]) -1 ; - dev->phy.chainmask = dev->mphy.antenna_mask; + dev->mphy.chainmask = dev->mphy.antenna_mask; }int mt7915_eeprom_init (struct mt7915_dev *dev)
drivers/net/wireless/mediatek/mt76/mt7915/init.c +6 -7
@@ -235,8 +235,8 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev) phy = mphy->priv; phy->dev = dev; phy->mt76 = mphy; - phy->chainmask = dev->chainmask & ~dev->phy.chainmask; - mphy->antenna_mask =BIT (hweight8 (phy->chainmask)) -1 ; + mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask; + mphy->antenna_mask =BIT (hweight8 (mphy->chainmask)) -1 ;mt7915_init_wiphy (mphy->hw);INIT_LIST_HEAD (&phy->stats_list);
@@ -329,7 +329,7 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)void mt7915_set_stream_vht_txbf_caps (struct mt7915_phy *phy) { -int nss =hweight8 (phy->chainmask); +int nss =hweight8 (phy->mt76->chainmask);u32 *cap = &phy->mt76->sband_5g.sband.vht_cap.cap; *cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
@@ -440,8 +440,7 @@ static int mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, struct ieee80211_sband_iftype_data *data) { - int i, idx = 0; -int nss =hweight8 (phy->chainmask); + int i, idx = 0, nss = hweight8(phy->mt76->chainmask);u16 mcs_map =0 ;for (i =0 ; i <8 ; i++) {
@@ -648,8 +647,8 @@ int mt7915_register_device(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.hw->wiphy->available_antennas_rx = dev->phy.chainmask; - dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask; + dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; + dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;mt76_set_stream_caps (&dev->mphy, true);mt7915_set_stream_vht_txbf_caps (&dev->phy);
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +1 -1
@@ -1362,7 +1362,7 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx)u32 val, sum =0 , n =0 ;int nss, i; -for (nss =0 ; nss <hweight8 (phy->chainmask); nss++) { +for (nss =0 ; nss <hweight8 (phy->mt76->chainmask); nss++) {u32 reg =MT_WF_IRPI (nss + (idx << dev->dbdc_support));for (i =0 ; i <ARRAY_SIZE (nf_power); i++, reg +=4 ) {
drivers/net/wireless/mediatek/mt76/mt7915/main.c +1 -1
@@ -812,7 +812,7 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)else tx_ant <<=1 ; } - phy->chainmask = tx_ant; + phy->mt76->chainmask = tx_ant;mt76_set_stream_caps (phy->mt76, true);mt7915_set_stream_vht_txbf_caps (phy);
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +4 -4
@@ -834,9 +834,9 @@ static void mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct mt7915_phy *phy) { + int max_nss = hweight8(phy->mt76->chainmask);struct bss_info_ra *ra;struct tlv *tlv; -int max_nss =hweight8 (phy->chainmask); tlv =mt7915_mcu_add_tlv (skb,BSS_INFO_RA ,sizeof (*ra));
@@ -1771,7 +1771,7 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy, {struct ieee80211_sta_vht_cap *pc = &sta->vht_cap;struct ieee80211_sta_vht_cap *vc = &phy->mt76->sband_5g.sband.vht_cap; -u8 bfee_nr, bfer_nr, n, tx_ant =hweight8 (phy->chainmask) -1 ; +u8 bfee_nr, bfer_nr, n, tx_ant =hweight8 (phy->mt76->chainmask) -1 ;u16 mcs_map; bf->tx_mode =MT_PHY_TYPE_VHT ;
@@ -1868,9 +1868,9 @@ mt7915_mcu_sta_bfer_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif, struct mt7915_phy *phy, bool enable) { + int tx_ant = hweight8(phy->mt76->chainmask) - 1;struct sta_rec_bf *bf;struct tlv *tlv; -int tx_ant =hweight8 (phy->chainmask) -1 ; const u8 matrix[4][4] = { {0, 0, 0, 0}, {1, 1, 0, 0}, /* 2x1, 2x2, 2x3, 2x4 */
@@ -1923,9 +1923,9 @@ static void mt7915_mcu_sta_bfee_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, struct mt7915_phy *phy) { + int tx_ant = hweight8(phy->mt76->chainmask) - 1;struct sta_rec_bfee *bfee;struct tlv *tlv; -int tx_ant =hweight8 (phy->chainmask) -1 ;u8 nr =0 ; tlv =mt7915_mcu_add_tlv (skb,STA_REC_BFEE ,sizeof (*bfee));
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +0 -1
@@ -126,7 +126,6 @@ struct mt7915_phy {u64 omac_mask;u16 noise; -u16 chainmask;s16 coverage_class;u8 slottime;
drivers/net/wireless/mediatek/mt76/mt7915/testmode.c +1 -1
@@ -316,7 +316,7 @@ mt7915_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb, td->state == MT76_TM_STATE_OFF)return 0 ; -if (td->tx_antenna_mask & ~phy->chainmask) +if (td->tx_antenna_mask & ~mphy->chainmask)return -EINVAL ;for (i =0 ; i <ARRAY_SIZE (tm_change_map); i++) {
Signature · 1 line
2.25.1
[email protected]
reviewerPATCH v5 5/15 mt76: mt7921: add DMA support
In reply to [email protected]From: Sean Wang <[email protected]>
Add DMA and register access support to MT7921e driver to set up the link for the data movement between the host and MT7921 MAC, or the host and MT7921 MCU.
--- .../net/wireless/mediatek/mt76/mt7921/dma.c | 356 ++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/mac.c | 3 + 2 files changed, 359 insertions(+) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/dma.c
drivers/net/wireless/mediatek/mt76/mt7921/dma.c new file +356 -0
@@ -0,0 +1,356 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include "mt7921.h" +#include "../dma.h" +#include "mac.h" + +int mt7921_init_tx_queues (struct mt7921_phy *phy,int idx,int n_desc) +{ +int i, err; + + err =mt76_init_tx_queue (phy->mt76,0 , idx, n_desc,MT_TX_RING_BASE ); +if (err <0 ) +return err; + +for (i =0 ; i <=MT_TXQ_PSD ; i++) + phy->mt76->q_tx[i] = phy->mt76->q_tx[0 ]; + +return 0 ; +} + +void mt7921_queue_rx_skb (struct mt76_dev *mdev,enum mt76_rxq_id q, +struct sk_buff *skb) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); +__le32 *rxd = (__le32 *)skb->data; +enum rx_pkt_type type; +u16 flag; + + type =FIELD_GET (MT_RXD0_PKT_TYPE ,le32_to_cpu (rxd[0 ])); + flag =FIELD_GET (MT_RXD0_PKT_FLAG ,le32_to_cpu (rxd[0 ])); + +if (type ==PKT_TYPE_RX_EVENT && flag ==0x1 ) + type =PKT_TYPE_NORMAL_MCU ; + +switch (type) { +case PKT_TYPE_TXRX_NOTIFY : +mt7921_mac_tx_free (dev, skb); +break ; +case PKT_TYPE_RX_EVENT : +mt7921_mcu_rx_event (dev, skb); +break ; +case PKT_TYPE_NORMAL_MCU : +case PKT_TYPE_NORMAL : +if (!mt7921_mac_fill_rx (dev, skb)) { +mt76_rx (&dev->mt76, q, skb); +return ; + } + fallthrough; +default : +dev_kfree_skb (skb); +break ; + } +} + +static void +mt7921_tx_cleanup (struct mt7921_dev *dev) +{ +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 mt7921_poll_tx (struct napi_struct *napi,int budget) +{ +struct mt7921_dev *dev; + + dev = container_of(napi, struct mt7921_dev, mt76.tx_napi); + +mt7921_tx_cleanup (dev); + +if (napi_complete_done (napi,0 )) +mt7921_irq_enable (dev,MT_INT_TX_DONE_ALL ); + +return 0 ; +} + +void mt7921_dma_prefetch (struct mt7921_dev *dev) +{ +#define PREFETCH (base, depth) ((base) << 16 | (depth)) + +mt76_wr (dev,MT_WFDMA0_RX_RING0_EXT_CTRL ,PREFETCH (0x0 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_RX_RING2_EXT_CTRL ,PREFETCH (0x40 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_RX_RING3_EXT_CTRL ,PREFETCH (0x80 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_RX_RING4_EXT_CTRL ,PREFETCH (0xc0 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_RX_RING5_EXT_CTRL ,PREFETCH (0x100 ,0x4 )); + +mt76_wr (dev,MT_WFDMA0_TX_RING0_EXT_CTRL ,PREFETCH (0x140 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_TX_RING1_EXT_CTRL ,PREFETCH (0x180 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_TX_RING2_EXT_CTRL ,PREFETCH (0x1c0 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_TX_RING3_EXT_CTRL ,PREFETCH (0x200 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_TX_RING4_EXT_CTRL ,PREFETCH (0x240 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_TX_RING5_EXT_CTRL ,PREFETCH (0x280 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_TX_RING6_EXT_CTRL ,PREFETCH (0x2c0 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_TX_RING16_EXT_CTRL ,PREFETCH (0x340 ,0x4 )); +mt76_wr (dev,MT_WFDMA0_TX_RING17_EXT_CTRL ,PREFETCH (0x380 ,0x4 )); +} + +static u32 __mt7921_reg_addr (struct mt7921_dev *dev,u32 addr) +{ +static const struct { +u32 phys; +u32 mapped; +u32 size; + } fixed_map[] = { + {0x00400000 ,0x80000 ,0x10000 },/* WF_MCU_SYSRAM */ + {0x00410000 ,0x90000 ,0x10000 },/* WF_MCU_SYSRAM (configure register) */ + {0x40000000 ,0x70000 ,0x10000 },/* WF_UMAC_SYSRAM */ + {0x54000000 ,0x02000 ,0x1000 },/* WFDMA PCIE0 MCU DMA0 */ + {0x55000000 ,0x03000 ,0x1000 },/* WFDMA PCIE0 MCU DMA1 */ + {0x58000000 ,0x06000 ,0x1000 },/* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ + {0x59000000 ,0x07000 ,0x1000 },/* WFDMA PCIE1 MCU DMA1 */ + {0x7c000000 ,0xf0000 ,0x10000 },/* CONN_INFRA */ + {0x7c020000 ,0xd0000 ,0x10000 },/* CONN_INFRA, WFDMA */ + {0x7c060000 ,0xe0000 ,0x10000 },/* CONN_INFRA, conn_host_csr_top */ + {0x80020000 ,0xb0000 ,0x10000 },/* WF_TOP_MISC_OFF */ + {0x81020000 ,0xc0000 ,0x10000 },/* WF_TOP_MISC_ON */ + {0x820c0000 ,0x08000 ,0x4000 },/* WF_UMAC_TOP (PLE) */ + {0x820c8000 ,0x0c000 ,0x2000 },/* WF_UMAC_TOP (PSE) */ + {0x820cc000 ,0x0e000 ,0x2000 },/* WF_UMAC_TOP (PP) */ + {0x820ce000 ,0x21c00 ,0x0200 },/* WF_LMAC_TOP (WF_SEC) */ + {0x820cf000 ,0x22000 ,0x1000 },/* WF_LMAC_TOP (WF_PF) */ + {0x820d0000 ,0x30000 ,0x10000 },/* WF_LMAC_TOP (WF_WTBLON) */ + {0x820e0000 ,0x20000 ,0x0400 },/* WF_LMAC_TOP BN0 (WF_CFG) */ + {0x820e1000 ,0x20400 ,0x0200 },/* WF_LMAC_TOP BN0 (WF_TRB) */ + {0x820e2000 ,0x20800 ,0x0400 },/* WF_LMAC_TOP BN0 (WF_AGG) */ + {0x820e3000 ,0x20c00 ,0x0400 },/* WF_LMAC_TOP BN0 (WF_ARB) */ + {0x820e4000 ,0x21000 ,0x0400 },/* WF_LMAC_TOP BN0 (WF_TMAC) */ + {0x820e5000 ,0x21400 ,0x0800 },/* WF_LMAC_TOP BN0 (WF_RMAC) */ + {0x820e7000 ,0x21e00 ,0x0200 },/* WF_LMAC_TOP BN0 (WF_DMA) */ + {0x820e9000 ,0x23400 ,0x0200 },/* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + {0x820ea000 ,0x24000 ,0x0200 },/* WF_LMAC_TOP BN0 (WF_ETBF) */ + {0x820eb000 ,0x24200 ,0x0400 },/* WF_LMAC_TOP BN0 (WF_LPON) */ + {0x820ec000 ,0x24600 ,0x0200 },/* WF_LMAC_TOP BN0 (WF_INT) */ + {0x820ed000 ,0x24800 ,0x0800 },/* WF_LMAC_TOP BN0 (WF_MIB) */ + {0x820f0000 ,0xa0000 ,0x0400 },/* WF_LMAC_TOP BN1 (WF_CFG) */ + {0x820f1000 ,0xa0600 ,0x0200 },/* WF_LMAC_TOP BN1 (WF_TRB) */ + {0x820f2000 ,0xa0800 ,0x0400 },/* WF_LMAC_TOP BN1 (WF_AGG) */ + {0x820f3000 ,0xa0c00 ,0x0400 },/* WF_LMAC_TOP BN1 (WF_ARB) */ + {0x820f4000 ,0xa1000 ,0x0400 },/* WF_LMAC_TOP BN1 (WF_TMAC) */ + {0x820f5000 ,0xa1400 ,0x0800 },/* WF_LMAC_TOP BN1 (WF_RMAC) */ + {0x820f7000 ,0xa1e00 ,0x0200 },/* WF_LMAC_TOP BN1 (WF_DMA) */ + {0x820f9000 ,0xa3400 ,0x0200 },/* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + {0x820fa000 ,0xa4000 ,0x0200 },/* WF_LMAC_TOP BN1 (WF_ETBF) */ + {0x820fb000 ,0xa4200 ,0x0400 },/* WF_LMAC_TOP BN1 (WF_LPON) */ + {0x820fc000 ,0xa4600 ,0x0200 },/* WF_LMAC_TOP BN1 (WF_INT) */ + {0x820fd000 ,0xa4800 ,0x0800 },/* WF_LMAC_TOP BN1 (WF_MIB) */ + }; +int i; + +if (addr <0x100000 ) +return addr; + +for (i =0 ; i <ARRAY_SIZE (fixed_map); i++) { +u32 ofs; + +if (addr < fixed_map[i].phys) +continue ; + + ofs = addr - fixed_map[i].phys; +if (ofs > fixed_map[i].size) +continue ; + +return fixed_map[i].mapped + ofs; + } + +if ((addr >=0x18000000 && addr <0x18c00000 ) || + (addr >=0x70000000 && addr <0x78000000 ) || + (addr >=0x7c000000 && addr <0x7c400000 )) +return mt7921_reg_map_l1 (dev, addr); + +dev_err (dev->mt76.dev,"Access currently unsupported address %08x\n" , + addr); + +return 0 ; +} + +static u32 mt7921_rr (struct mt76_dev *mdev,u32 offset) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); +u32 addr =__mt7921_reg_addr (dev, offset); + +return dev->bus_ops->rr (mdev, addr); +} + +static void mt7921_wr (struct mt76_dev *mdev,u32 offset,u32 val) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); +u32 addr =__mt7921_reg_addr (dev, offset); + + dev->bus_ops->wr (mdev, addr, val); +} + +static u32 mt7921_rmw (struct mt76_dev *mdev,u32 offset,u32 mask,u32 val) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); +u32 addr =__mt7921_reg_addr (dev, offset); + +return dev->bus_ops->rmw (mdev, addr, mask, val); +} + +static int mt7921_dmashdl_disabled (struct mt7921_dev *dev) +{ +mt76_clear (dev,MT_WFDMA0_GLO_CFG_EXT0 ,MT_WFDMA0_CSR_TX_DMASHDL_ENABLE ); +mt76_set (dev,MT_DMASHDL_SW_CONTROL ,MT_DMASHDL_DMASHDL_BYPASS ); + +return 0 ; +} + +int mt7921_dma_init (struct mt7921_dev *dev) +{ +/* Increase buffer size to receive large VHT/HE MPDUs */ +struct mt76_bus_ops *bus_ops; +int rx_buf_size =MT_RX_BUF_SIZE *2 ; +int ret; + + dev->bus_ops = dev->mt76.bus; + bus_ops =devm_kmemdup (dev->mt76.dev, dev->bus_ops,sizeof (*bus_ops), +GFP_KERNEL ); +if (!bus_ops) +return -ENOMEM ; + + bus_ops->rr = mt7921_rr; + bus_ops->wr = mt7921_wr; + bus_ops->rmw = mt7921_rmw; + dev->mt76.bus = bus_ops; + +mt76_dma_attach (&dev->mt76); + +/* reset */ +mt76_clear (dev,MT_WFDMA0_RST , +MT_WFDMA0_RST_DMASHDL_ALL_RST | +MT_WFDMA0_RST_LOGIC_RST ); + +mt76_set (dev,MT_WFDMA0_RST , +MT_WFDMA0_RST_DMASHDL_ALL_RST | +MT_WFDMA0_RST_LOGIC_RST ); + + ret =mt7921_dmashdl_disabled (dev); +if (ret) +return ret; + +/* disable WFDMA0 */ +mt76_clear (dev,MT_WFDMA0_GLO_CFG , +MT_WFDMA0_GLO_CFG_TX_DMA_EN | +MT_WFDMA0_GLO_CFG_RX_DMA_EN | +MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | +MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | +MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | +MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 ); + +mt76_poll (dev,MT_WFDMA0_GLO_CFG , +MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | +MT_WFDMA0_GLO_CFG_RX_DMA_BUSY ,0 ,1000 ); + +/* init tx queue */ + ret =mt7921_init_tx_queues (&dev->phy,MT7921_TXQ_BAND0 , +MT7921_TX_RING_SIZE ); +if (ret) +return ret; + +mt76_wr (dev,MT_WFDMA0_TX_RING0_EXT_CTRL ,0x4 ); + +/* command to WM */ + ret =mt76_init_mcu_queue (&dev->mt76,MT_MCUQ_WM ,MT7921_TXQ_MCU_WM , +MT7921_TX_MCU_RING_SIZE ,MT_TX_RING_BASE ); +if (ret) +return ret; + +/* firmware download */ + ret =mt76_init_mcu_queue (&dev->mt76,MT_MCUQ_FWDL ,MT7921_TXQ_FWDL , +MT7921_TX_FWDL_RING_SIZE ,MT_TX_RING_BASE ); +if (ret) +return ret; + +/* event from WM before firmware download */ + ret =mt76_queue_alloc (dev, &dev->mt76.q_rx[MT_RXQ_MCU ], +MT7921_RXQ_MCU_WM , +MT7921_RX_MCU_RING_SIZE , + rx_buf_size,MT_RX_EVENT_RING_BASE ); +if (ret) +return ret; + +/* Change mcu queue after firmware download */ + ret =mt76_queue_alloc (dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA ], +MT7921_RXQ_MCU_WM , +MT7921_RX_MCU_RING_SIZE , + rx_buf_size,MT_WFDMA0 (0x540 )); +if (ret) +return ret; + +/* rx data */ + ret =mt76_queue_alloc (dev, &dev->mt76.q_rx[MT_RXQ_MAIN ], +MT7921_RXQ_BAND0 ,MT7921_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; + +netif_tx_napi_add (&dev->mt76.napi_dev, &dev->mt76.tx_napi, + mt7921_poll_tx,NAPI_POLL_WEIGHT ); +napi_enable (&dev->mt76.tx_napi); + +/* configure perfetch settings */ +mt7921_dma_prefetch (dev); + +/* reset dma idx */ +mt76_wr (dev,MT_WFDMA0_RST_DTX_PTR , ~0 ); + +/* configure delay interrupt */ +mt76_wr (dev,MT_WFDMA0_PRI_DLY_INT_CFG0 ,0 ); + +mt76_set (dev,MT_WFDMA0_GLO_CFG , +MT_WFDMA0_GLO_CFG_TX_WB_DDONE | +MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN | +MT_WFDMA0_GLO_CFG_CLK_GAT_DIS | +MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | +MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | +MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 ); + +mt76_set (dev,MT_WFDMA0_GLO_CFG , +MT_WFDMA0_GLO_CFG_TX_DMA_EN |MT_WFDMA0_GLO_CFG_RX_DMA_EN ); + +mt76_set (dev,0x54000120 ,BIT (1 )); + +/* enable interrupts for TX/RX rings */ +mt7921_irq_enable (dev,MT_INT_RX_DONE_ALL |MT_INT_TX_DONE_ALL | +MT_INT_MCU_CMD ); + +return 0 ; +} + +void mt7921_dma_cleanup (struct mt7921_dev *dev) +{ +/* disable */ +mt76_clear (dev,MT_WFDMA0_GLO_CFG , +MT_WFDMA0_GLO_CFG_TX_DMA_EN | +MT_WFDMA0_GLO_CFG_RX_DMA_EN | +MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | +MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | +MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | +MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 ); + +/* reset */ +mt76_clear (dev,MT_WFDMA0_RST , +MT_WFDMA0_RST_DMASHDL_ALL_RST | +MT_WFDMA0_RST_LOGIC_RST ); + +mt76_set (dev,MT_WFDMA0_RST , +MT_WFDMA0_RST_DMASHDL_ALL_RST | +MT_WFDMA0_RST_LOGIC_RST ); + +mt76_dma_cleanup (&dev->mt76); +}
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +3 -0
@@ -1204,6 +1204,9 @@ mt7921_dma_reset(struct mt7921_phy *phy)mt76_queue_rx_reset (dev, i); } +/* re-init prefetch settings after reset */ +mt7921_dma_prefetch (dev); +mt76_set (dev,MT_WFDMA0_GLO_CFG ,MT_WFDMA0_GLO_CFG_TX_DMA_EN |MT_WFDMA0_GLO_CFG_RX_DMA_EN ); }
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 9/15 mt76: mt7921: add debugfs support
In reply to [email protected]From: Sean Wang <[email protected]>
Add debugfs support to dump driver statistics and hardware details.
--- .../wireless/mediatek/mt76/mt7921/debugfs.c | 178 ++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/init.c | 2 +- 2 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c new file +178 -0
@@ -0,0 +1,178 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include "mt7921.h" +#include "eeprom.h" + +static int +mt7921_fw_debug_set (void *data,u64 val) +{ +struct mt7921_dev *dev = data; + + dev->fw_debug = (u8 )val; + +mt7921_mcu_fw_log_2_host (dev, dev->fw_debug); + +return 0 ; +} + +static int +mt7921_fw_debug_get (void *data,u64 *val) +{ +struct mt7921_dev *dev = data; + + *val = dev->fw_debug; + +return 0 ; +} + +DEFINE_DEBUGFS_ATTRIBUTE (fops_fw_debug, mt7921_fw_debug_get, + mt7921_fw_debug_set,"%lld\n" ); + +static void +mt7921_ampdu_stat_read_phy (struct mt7921_phy *phy, +struct seq_file *file) +{ +struct mt7921_dev *dev = file->private; +int bound[15 ], range[4 ], i; + +if (!phy) +return ; + +/* Tx ampdu stat */ +for (i =0 ; i <ARRAY_SIZE (range); i++) + range[i] =mt76_rr (dev,MT_MIB_ARNG (0 , i)); + +for (i =0 ; i <ARRAY_SIZE (bound); i++) + bound[i] =MT_MIB_ARNCR_RANGE (range[i /4 ], i) +1 ; + +seq_printf (file,"\nPhy0\n" ); + +seq_printf (file,"Length: %8d | " , bound[0 ]); +for (i =0 ; i <ARRAY_SIZE (bound) -1 ; i++) +seq_printf (file,"%3d -%3d | " , + bound[i] +1 , bound[i +1 ]); + +seq_puts (file,"\nCount: " ); +for (i =0 ; i <ARRAY_SIZE (bound); i++) +seq_printf (file,"%8d | " , dev->mt76.aggr_stats[i]); +seq_puts (file,"\n" ); + +seq_printf (file,"BA miss count: %d\n" , phy->mib.ba_miss_cnt); +} + +static int +mt7921_tx_stats_read (struct seq_file *file,void *data) +{ +struct mt7921_dev *dev = file->private; +int stat[8 ], i, n; + +mt7921_ampdu_stat_read_phy (&dev->phy, file); + +/* Tx amsdu info */ +seq_puts (file,"Tx MSDU stat:\n" ); +for (i =0 , n =0 ; i <ARRAY_SIZE (stat); i++) { + stat[i] =mt76_rr (dev,MT_PLE_AMSDU_PACK_MSDU_CNT (i)); + n += stat[i]; + } + +for (i =0 ; i <ARRAY_SIZE (stat); i++) { +seq_printf (file,"AMSDU pack count of %d MSDU in TXD: 0x%x " , + i +1 , stat[i]); +if (n !=0 ) +seq_printf (file,"(%d%%)\n" , stat[i] *100 / n); +else +seq_puts (file,"\n" ); + } + +return 0 ; +} + +static int +mt7921_tx_stats_open (struct inode *inode,struct file *f) +{ +return single_open (f, mt7921_tx_stats_read, inode->i_private); +} + +static const struct file_operations fops_tx_stats = { + .open = mt7921_tx_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner =THIS_MODULE , +}; + +static int +mt7921_queues_acq (struct seq_file *s,void *data) +{ +struct mt7921_dev *dev =dev_get_drvdata (s->private); +int i; + +for (i =0 ; i <16 ; i++) { +int j, acs = i /4 , index = i %4 ; +u32 ctrl, val, qlen =0 ; + + val =mt76_rr (dev,MT_PLE_AC_QEMPTY (acs, index)); + ctrl =BIT (31 ) |BIT (15 ) | (acs <<8 ); + +for (j =0 ; j <32 ; j++) { +if (val &BIT (j)) +continue ; + +mt76_wr (dev,MT_PLE_FL_Q0_CTRL , + ctrl | (j + (index <<5 ))); + qlen +=mt76_get_field (dev,MT_PLE_FL_Q3_CTRL , +GENMASK (11 ,0 )); + } +seq_printf (s,"AC%d%d: queued=%d\n" , acs, index, qlen); + } + +return 0 ; +} + +static int +mt7921_queues_read (struct seq_file *s,void *data) +{ +struct mt7921_dev *dev =dev_get_drvdata (s->private); +struct { +struct mt76_queue *q; +char *queue; + } queue_map[] = { + { dev->mphy.q_tx[MT_TXQ_BE ],"WFDMA0" }, + { dev->mt76.q_mcu[MT_MCUQ_WM ],"MCUWM" }, + { dev->mt76.q_mcu[MT_MCUQ_FWDL ],"MCUFWQ" }, + }; +int i; + +for (i =0 ; i <ARRAY_SIZE (queue_map); i++) { +struct mt76_queue *q = queue_map[i].q; + +if (!q) +continue ; + +seq_printf (s, +"%s: queued=%d head=%d tail=%d\n" , + queue_map[i].queue, q->queued, q->head, + q->tail); + } + +return 0 ; +} + +int mt7921_init_debugfs (struct mt7921_dev *dev) +{ +struct dentry *dir; + + dir =mt76_register_debugfs (&dev->mt76); +if (!dir) +return -ENOMEM ; + +debugfs_create_devm_seqfile (dev->mt76.dev,"queues" , dir, + mt7921_queues_read); +debugfs_create_devm_seqfile (dev->mt76.dev,"acq" , dir, + mt7921_queues_acq); +debugfs_create_file ("tx_stats" ,0400 , dir, dev, &fops_tx_stats); +debugfs_create_file ("fw_debug" ,0600 , dir, dev, &fops_fw_debug); + +return 0 ; +}
drivers/net/wireless/mediatek/mt76/mt7921/init.c +1 -1
@@ -231,7 +231,7 @@ int mt7921_register_device(struct mt7921_dev *dev)ieee80211_queue_work (mt76_hw (dev), &dev->init_work); -return 0 ; +return mt7921_init_debugfs (dev); }void mt7921_unregister_device (struct mt7921_dev *dev)
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 1/15 mt76: move mac_work in mt76_core module
In reply to [email protected]From: Lorenzo Bianconi <[email protected]>
Move mac_work delayed_work and mac_work_count in mt76_phy since it is used by all drivers. This is a preliminary patch to create a common mcu library used by mt7615 and mt7921 drivers
--- drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++- .../net/wireless/mediatek/mt76/mt7603/init.c | 2 +- .../net/wireless/mediatek/mt76/mt7603/mac.c | 14 ++++----- .../net/wireless/mediatek/mt76/mt7603/main.c | 10 +++---- .../wireless/mediatek/mt76/mt7603/mt7603.h | 2 -- .../net/wireless/mediatek/mt76/mt7615/init.c | 4 +-- .../net/wireless/mediatek/mt76/mt7615/mac.c | 25 ++++++++-------- .../net/wireless/mediatek/mt76/mt7615/main.c | 13 +++++---- .../wireless/mediatek/mt76/mt7615/mt7615.h | 3 -- .../net/wireless/mediatek/mt76/mt7615/usb.c | 2 +- .../net/wireless/mediatek/mt76/mt76x0/pci.c | 4 +-- .../net/wireless/mediatek/mt76/mt76x0/usb.c | 4 +-- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 4 +-- .../net/wireless/mediatek/mt76/mt76x02_util.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_init.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_init.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/init.c | 4 +-- .../net/wireless/mediatek/mt76/mt7915/mac.c | 29 ++++++++++--------- .../net/wireless/mediatek/mt76/mt7915/main.c | 9 +++--- .../wireless/mediatek/mt76/mt7915/mt7915.h | 2 -- 22 files changed, 72 insertions(+), 73 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +3 -1
@@ -583,6 +583,9 @@ struct mt76_phy {#ifdef CONFIG_NL80211_TESTMODE struct mt76_testmode_data test;#endif + +struct delayed_work mac_work; +u8 mac_work_count; };struct mt76_dev {
@@ -623,7 +626,6 @@ struct mt76_dev {struct mt76_worker tx_worker;struct napi_struct tx_napi; -struct delayed_work mac_work;wait_queue_head_t tx_wait;struct sk_buff_head status_list;
drivers/net/wireless/mediatek/mt76/mt7603/init.c +1 -1
@@ -532,7 +532,7 @@ int mt7603_register_device(struct mt7603_dev *dev)spin_lock_init (&dev->sta_poll_lock);spin_lock_init (&dev->ps_lock); -INIT_DELAYED_WORK (&dev->mt76.mac_work, mt7603_mac_work); +INIT_DELAYED_WORK (&dev->mphy.mac_work, mt7603_mac_work);tasklet_setup (&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet); dev->slottime =9 ;
drivers/net/wireless/mediatek/mt76/mt7603/mac.c +7 -7
@@ -1788,7 +1788,7 @@ mt7603_false_cca_check(struct mt7603_dev *dev)void mt7603_mac_work (struct work_struct *work) { struct mt7603_dev *dev = container_of(work, struct mt7603_dev, - mt76.mac_work.work); + mphy.mac_work.work);bool reset = false;int i, idx;
@@ -1796,7 +1796,7 @@ void mt7603_mac_work(struct work_struct *work)mutex_lock (&dev->mt76.mutex); - dev->mac_work_count++; + dev->mphy.mac_work_count++;mt76_update_survey (&dev->mt76);mt7603_edcca_check (dev);
@@ -1807,7 +1807,7 @@ void mt7603_mac_work(struct work_struct *work) dev->mt76.aggr_stats[idx++] += val >>16 ; } -if (dev->mac_work_count ==10 ) +if (dev->mphy.mac_work_count ==10 )mt7603_false_cca_check (dev); if (mt7603_watchdog_check(dev, &dev->rx_pse_check,
@@ -1838,17 +1838,17 @@ void mt7603_mac_work(struct work_struct *work) dev->rx_dma_idx = ~0 ;memset (dev->tx_dma_idx,0xff ,sizeof (dev->tx_dma_idx)); reset = true; - dev->mac_work_count =0 ; + dev->mphy.mac_work_count =0 ; } -if (dev->mac_work_count >=10 ) - dev->mac_work_count =0 ; +if (dev->mphy.mac_work_count >=10 ) + dev->mphy.mac_work_count =0 ;mutex_unlock (&dev->mt76.mutex);if (reset)mt7603_mac_watchdog_reset (dev); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,msecs_to_jiffies (MT7603_WATCHDOG_TIME )); }
drivers/net/wireless/mediatek/mt76/mt7603/main.c +5 -5
@@ -17,7 +17,7 @@ mt7603_start(struct ieee80211_hw *hw)mt7603_mac_start (dev); dev->mphy.survey_time =ktime_get_boottime ();set_bit (MT76_STATE_RUNNING , &dev->mphy.state); -mt7603_mac_work (&dev->mt76.mac_work.work); +mt7603_mac_work (&dev->mphy.mac_work.work);return 0 ; }
@@ -28,7 +28,7 @@ mt7603_stop(struct ieee80211_hw *hw)struct mt7603_dev *dev = hw->priv;clear_bit (MT76_STATE_RUNNING , &dev->mphy.state); -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);mt7603_mac_stop (dev); }
@@ -137,7 +137,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)u8 bw =MT_BW_20 ;bool failed = false; -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);tasklet_disable (&dev->mt76.pre_tbtt_tasklet);mutex_lock (&dev->mt76.mutex);
@@ -178,7 +178,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)mt76_txq_schedule_all (&dev->mphy); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,msecs_to_jiffies (MT7603_WATCHDOG_TIME ));/* reset channel stats */
@@ -200,7 +200,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)tasklet_enable (&dev->mt76.pre_tbtt_tasklet);if (failed) -mt7603_mac_work (&dev->mt76.mac_work.work); +mt7603_mac_work (&dev->mphy.mac_work.work);return ret; }
drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +0 -2
@@ -132,8 +132,6 @@ struct mt7603_dev {spinlock_t ps_lock; -u8 mac_work_count; -u8 mcu_running;u8 ed_monitor_enabled;
drivers/net/wireless/mediatek/mt76/mt7615/init.c +2 -2
@@ -408,7 +408,7 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) mphy->antenna_mask =BIT (hweight8 (phy->chainmask)) -1 ;mt7615_init_wiphy (mphy->hw); -INIT_DELAYED_WORK (&phy->mac_work, mt7615_mac_work); +INIT_DELAYED_WORK (&mphy->mac_work, mt7615_mac_work);INIT_DELAYED_WORK (&phy->scan_work, mt7615_scan_work);skb_queue_head_init (&phy->scan_event_list);
@@ -471,7 +471,7 @@ void mt7615_init_device(struct mt7615_dev *dev)init_completion (&dev->pm.wake_cmpl);spin_lock_init (&dev->pm.txq_lock);set_bit (MT76_STATE_PM , &dev->mphy.state); -INIT_DELAYED_WORK (&dev->phy.mac_work, mt7615_mac_work); +INIT_DELAYED_WORK (&dev->mphy.mac_work, mt7615_mac_work);INIT_DELAYED_WORK (&dev->phy.scan_work, mt7615_scan_work);skb_queue_head_init (&dev->phy.scan_event_list);INIT_LIST_HEAD (&dev->sta_poll_list);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +13 -12
@@ -1976,17 +1976,17 @@ void mt7615_pm_power_save_work(struct work_struct *work)void mt7615_mac_work (struct work_struct *work) {struct mt7615_phy *phy; -struct mt76_dev *mdev; +struct mt76_phy *mphy; - phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy, - mac_work.work); - mdev = &phy->dev->mt76; + mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, + mac_work.work); + phy = mphy->priv;mt7615_mutex_acquire (phy->dev);mt7615_update_survey (phy->dev); -if (++phy->mac_work_count ==5 ) { - phy->mac_work_count =0 ; +if (++mphy->mac_work_count ==5 ) { + mphy->mac_work_count =0 ;mt7615_mac_update_mib_stats (phy);mt7615_mac_scs_check (phy);
@@ -1994,8 +1994,8 @@ void mt7615_mac_work(struct work_struct *work)mt7615_mutex_release (phy->dev); -mt76_tx_status_check (mdev,NULL , false); -ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mac_work, +mt76_tx_status_check (mphy->dev,NULL , false); +ieee80211_queue_delayed_work (mphy->hw, &mphy->mac_work,MT7615_WATCHDOG_TIME ); }
@@ -2104,11 +2104,11 @@ void mt7615_mac_reset_work(struct work_struct *work)set_bit (MT76_RESET , &dev->mphy.state);set_bit (MT76_MCU_RESET , &dev->mphy.state);wake_up (&dev->mt76.mcu.wait); -cancel_delayed_work_sync (&dev->phy.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);del_timer_sync (&dev->phy.roc_timer);cancel_work_sync (&dev->phy.roc_work);if (phy2) { -cancel_delayed_work_sync (&phy2->mac_work); +cancel_delayed_work_sync (&phy2->mt76->mac_work);del_timer_sync (&phy2->roc_timer);cancel_work_sync (&phy2->roc_work); }
@@ -2163,10 +2163,11 @@ void mt7615_mac_reset_work(struct work_struct *work)mt7615_mutex_release (dev); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->phy.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT7615_WATCHDOG_TIME );if (phy2) -ieee80211_queue_delayed_work (ext_phy->hw, &phy2->mac_work, +ieee80211_queue_delayed_work (ext_phy->hw, + &phy2->mt76->mac_work,MT7615_WATCHDOG_TIME ); }
drivers/net/wireless/mediatek/mt76/mt7615/main.c +7 -6
@@ -70,7 +70,7 @@ static int mt7615_start(struct ieee80211_hw *hw)set_bit (MT76_STATE_RUNNING , &phy->mt76->state); -ieee80211_queue_delayed_work (hw, &phy->mac_work, +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work,MT7615_WATCHDOG_TIME );if (!running)
@@ -86,7 +86,7 @@ static void mt7615_stop(struct ieee80211_hw *hw)struct mt7615_dev *dev =mt7615_hw_dev (hw);struct mt7615_phy *phy =mt7615_hw_phy (hw); -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);del_timer_sync (&phy->roc_timer);cancel_work_sync (&phy->roc_work);
@@ -300,7 +300,7 @@ int mt7615_set_channel(struct mt7615_phy *phy)bool ext_phy = phy != &dev->phy;int ret; -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);mt7615_mutex_acquire (dev);
@@ -335,7 +335,8 @@ int mt7615_set_channel(struct mt7615_phy *phy)mt76_txq_schedule_all (phy->mt76);if (!mt76_testmode_enabled (phy->mt76)) -ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mac_work, +ieee80211_queue_delayed_work (phy->mt76->hw, + &phy->mt76->mac_work,MT7615_WATCHDOG_TIME );return ret;
@@ -1112,7 +1113,7 @@ static int mt7615_suspend(struct ieee80211_hw *hw,clear_bit (MT76_STATE_RUNNING , &phy->mt76->state);cancel_delayed_work_sync (&phy->scan_work); -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);set_bit (MT76_STATE_SUSPEND , &phy->mt76->state); ieee80211_iterate_active_interfaces(hw,
@@ -1153,7 +1154,7 @@ static int mt7615_resume(struct ieee80211_hw *hw)IEEE80211_IFACE_ITER_RESUME_ALL , mt7615_mcu_set_suspend_iter, phy); -ieee80211_queue_delayed_work (hw, &phy->mac_work, +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work,MT7615_WATCHDOG_TIME );mt7615_mutex_release (dev);
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +0 -3
@@ -185,9 +185,6 @@ struct mt7615_phy {struct mib_stats mib; -struct delayed_work mac_work; -u8 mac_work_count; -struct sk_buff_head scan_event_list;struct delayed_work scan_work;
drivers/net/wireless/mediatek/mt76/mt7615/usb.c +1 -1
@@ -29,7 +29,7 @@ static void mt7663u_stop(struct ieee80211_hw *hw)del_timer_sync (&phy->roc_timer);cancel_work_sync (&phy->roc_work);cancel_delayed_work_sync (&phy->scan_work); -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);mt76u_stop_tx (&dev->mt76); }
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +2 -2
@@ -16,7 +16,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw)mt76x02_mac_start (dev);mt76x0_phy_calibrate (dev, true); -ieee80211_queue_delayed_work (dev->mt76.hw, &dev->mt76.mac_work, +ieee80211_queue_delayed_work (dev->mt76.hw, &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL );ieee80211_queue_delayed_work (dev->mt76.hw, &dev->cal_work,MT_CALIBRATE_INTERVAL );
@@ -28,7 +28,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw) static void mt76x0e_stop_hw(struct mt76x02_dev *dev) { cancel_delayed_work_sync(&dev->cal_work); - cancel_delayed_work_sync(&dev->mt76.mac_work); + cancel_delayed_work_sync(&dev->mphy.mac_work); clear_bit(MT76_RESTART, &dev->mphy.state); if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY,
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +2 -2
@@ -82,7 +82,7 @@ static void mt76x0u_stop(struct ieee80211_hw *hw)clear_bit (MT76_STATE_RUNNING , &dev->mphy.state);cancel_delayed_work_sync (&dev->cal_work); -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);mt76u_stop_tx (&dev->mt76);mt76x02u_exit_beacon_config (dev);
@@ -108,7 +108,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw)return ret;mt76x0_phy_calibrate (dev, true); -ieee80211_queue_delayed_work (dev->mt76.hw, &dev->mt76.mac_work, +ieee80211_queue_delayed_work (dev->mt76.hw, &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL );ieee80211_queue_delayed_work (dev->mt76.hw, &dev->cal_work,MT_CALIBRATE_INTERVAL );
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +2 -2
@@ -1162,7 +1162,7 @@ static void mt76x02_edcca_check(struct mt76x02_dev *dev)void mt76x02_mac_work (struct work_struct *work) { struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, - mt76.mac_work.work); + mphy.mac_work.work);int i, idx;mutex_lock (&dev->mt76.mutex);
@@ -1185,7 +1185,7 @@ void mt76x02_mac_work(struct work_struct *work)mt76_tx_status_check (&dev->mt76,NULL , false); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL ); }
drivers/net/wireless/mediatek/mt76/mt76x02_util.c +1 -1
@@ -149,7 +149,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev)struct ieee80211_hw *hw =mt76_hw (dev);struct wiphy *wiphy = hw->wiphy; -INIT_DELAYED_WORK (&dev->mt76.mac_work, mt76x02_mac_work); +INIT_DELAYED_WORK (&dev->mphy.mac_work, mt76x02_mac_work); hw->queues =4 ; hw->max_rates =1 ;
drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +1 -1
@@ -271,7 +271,7 @@ static int mt76x2_init_hardware(struct mt76x02_dev *dev)void mt76x2_stop_hardware (struct mt76x02_dev *dev) {cancel_delayed_work_sync (&dev->cal_work); -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);cancel_delayed_work_sync (&dev->wdt_work);clear_bit (MT76_RESTART , &dev->mphy.state);mt76x02_mcu_set_radio_state (dev, false);
drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +1 -1
@@ -14,7 +14,7 @@ mt76x2_start(struct ieee80211_hw *hw)mt76x02_mac_start (dev);mt76x2_phy_start (dev); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL );ieee80211_queue_delayed_work (mt76_hw (dev), &dev->wdt_work,MT_WATCHDOG_TIME );
drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +1 -1
@@ -236,7 +236,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)void mt76x2u_stop_hw (struct mt76x02_dev *dev) {cancel_delayed_work_sync (&dev->cal_work); -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);mt76x2u_mac_stop (dev); }
drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +1 -1
@@ -15,7 +15,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw)if (ret)return ret; -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL );set_bit (MT76_STATE_RUNNING , &dev->mphy.state);
drivers/net/wireless/mediatek/mt76/mt7915/init.c +2 -2
@@ -240,7 +240,7 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)mt7915_init_wiphy (mphy->hw);INIT_LIST_HEAD (&phy->stats_list); -INIT_DELAYED_WORK (&phy->mac_work, mt7915_mac_work); +INIT_DELAYED_WORK (&mphy->mac_work, mt7915_mac_work);mt7915_eeprom_parse_band_config (phy);mt7915_set_stream_vht_txbf_caps (phy);
@@ -622,7 +622,7 @@ int mt7915_register_device(struct mt7915_dev *dev) dev->mt76.phy.priv = &dev->phy;INIT_LIST_HEAD (&dev->phy.stats_list);INIT_WORK (&dev->rc_work, mt7915_mac_sta_rc_work); -INIT_DELAYED_WORK (&dev->phy.mac_work, mt7915_mac_work); +INIT_DELAYED_WORK (&dev->mphy.mac_work, mt7915_mac_work);INIT_LIST_HEAD (&dev->sta_rc_list);INIT_LIST_HEAD (&dev->sta_poll_list);spin_lock_init (&dev->sta_poll_lock);
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +15 -14
@@ -1544,9 +1544,9 @@ void mt7915_mac_reset_work(struct work_struct *work)set_bit (MT76_RESET , &dev->mphy.state);set_bit (MT76_MCU_RESET , &dev->mphy.state);wake_up (&dev->mt76.mcu.wait); -cancel_delayed_work_sync (&dev->phy.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);if (phy2) -cancel_delayed_work_sync (&phy2->mac_work); +cancel_delayed_work_sync (&phy2->mt76->mac_work);/* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all (&dev->mphy);
@@ -1600,10 +1600,11 @@ void mt7915_mac_reset_work(struct work_struct *work)mt7915_update_beacons (dev); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->phy.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT7915_WATCHDOG_TIME );if (phy2) -ieee80211_queue_delayed_work (ext_phy->hw, &phy2->mac_work, +ieee80211_queue_delayed_work (ext_phy->hw, + &phy2->mt76->mac_work,MT7915_WATCHDOG_TIME ); }
@@ -1714,17 +1715,17 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)void mt7915_mac_work (struct work_struct *work) {struct mt7915_phy *phy; -struct mt76_dev *mdev; +struct mt76_phy *mphy; - phy = (struct mt7915_phy *)container_of(work, struct mt7915_phy, - mac_work.work); - mdev = &phy->dev->mt76; + mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, + mac_work.work); + phy = mphy->priv; -mutex_lock (&mdev->mutex); +mutex_lock (&mphy->dev->mutex); -mt76_update_survey (mdev); -if (++phy->mac_work_count ==5 ) { - phy->mac_work_count =0 ; +mt76_update_survey (mphy->dev); +if (++mphy->mac_work_count ==5 ) { + mphy->mac_work_count =0 ;mt7915_mac_update_mib_stats (phy); }
@@ -1734,9 +1735,9 @@ void mt7915_mac_work(struct work_struct *work)mt7915_mac_sta_stats_work (phy); }; -mutex_unlock (&mdev->mutex); +mutex_unlock (&mphy->dev->mutex); -ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mac_work, +ieee80211_queue_delayed_work (mphy->hw, &mphy->mac_work,MT7915_WATCHDOG_TIME ); }
drivers/net/wireless/mediatek/mt76/mt7915/main.c +5 -4
@@ -50,7 +50,7 @@ static int mt7915_start(struct ieee80211_hw *hw)set_bit (MT76_STATE_RUNNING , &phy->mt76->state);if (!mt76_testmode_enabled (phy->mt76)) -ieee80211_queue_delayed_work (hw, &phy->mac_work, +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work,MT7915_WATCHDOG_TIME );if (!running)
@@ -66,7 +66,7 @@ static void mt7915_stop(struct ieee80211_hw *hw)struct mt7915_dev *dev =mt7915_hw_dev (hw);struct mt7915_phy *phy =mt7915_hw_phy (hw); -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);mutex_lock (&dev->mt76.mutex);
@@ -273,7 +273,7 @@ int mt7915_set_channel(struct mt7915_phy *phy)struct mt7915_dev *dev = phy->dev;int ret; -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);mutex_lock (&dev->mt76.mutex);set_bit (MT76_RESET , &phy->mt76->state);
@@ -299,7 +299,8 @@ int mt7915_set_channel(struct mt7915_phy *phy)mt76_txq_schedule_all (phy->mt76);if (!mt76_testmode_enabled (phy->mt76)) -ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mac_work, +ieee80211_queue_delayed_work (phy->mt76->hw, + &phy->mt76->mac_work,MT7915_WATCHDOG_TIME );return ret;
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +0 -2
@@ -140,8 +140,6 @@ struct mt7915_phy {struct mib_stats mib;struct list_head stats_list; -struct delayed_work mac_work; -u8 mac_work_count;u8 sta_work_count;#ifdef CONFIG_NL80211_TESTMODE
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 15/15 mt76: mt7921: introduce PM support
In reply to [email protected]From: Sean Wang <[email protected]>
Introduce suspend/resume and WoW (Wake-on-WoWLAN) support to mt7921 driver to allow remote wakeu-up from the suspend state.
--- .../net/wireless/mediatek/mt76/mt7921/main.c | 79 +++++ .../net/wireless/mediatek/mt76/mt7921/mcu.c | 307 ++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/mcu.h | 99 ++++++ .../wireless/mediatek/mt76/mt7921/mt7921.h | 9 + .../net/wireless/mediatek/mt76/mt7921/pci.c | 95 ++++++ 5 files changed, 589 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +79 -0
@@ -938,6 +938,79 @@ mt7921_sta_rc_update(struct ieee80211_hw *hw, { } +#ifdef CONFIG_PM +static int mt7921_suspend (struct ieee80211_hw *hw, +struct cfg80211_wowlan *wowlan) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); +int err; + +cancel_delayed_work_sync (&phy->scan_work); +cancel_delayed_work_sync (&phy->mt76->mac_work); + +mutex_lock (&dev->mt76.mutex); + +clear_bit (MT76_STATE_RUNNING , &phy->mt76->state); + +set_bit (MT76_STATE_SUSPEND , &phy->mt76->state); +ieee80211_iterate_active_interfaces (hw, +IEEE80211_IFACE_ITER_RESUME_ALL , + mt7921_mcu_set_suspend_iter, phy); + + err =mt7921_mcu_set_hif_suspend (dev, true); + +mutex_unlock (&dev->mt76.mutex); + +return err; +} + +static int mt7921_resume (struct ieee80211_hw *hw) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); +int err; + +mutex_lock (&dev->mt76.mutex); + + err =mt7921_mcu_set_hif_suspend (dev, false); +if (err <0 ) + goto out; + +set_bit (MT76_STATE_RUNNING , &phy->mt76->state); +clear_bit (MT76_STATE_SUSPEND , &phy->mt76->state); +ieee80211_iterate_active_interfaces (hw, +IEEE80211_IFACE_ITER_RESUME_ALL , + mt7921_mcu_set_suspend_iter, phy); + +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work, +MT7921_WATCHDOG_TIME ); +out: +mutex_unlock (&dev->mt76.mutex); + +return err; +} + +static void mt7921_set_wakeup (struct ieee80211_hw *hw,bool enabled) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt76_dev *mdev = &dev->mt76; + +device_set_wakeup_enable (mdev->dev, enabled); +} + +static void mt7921_set_rekey_data (struct ieee80211_hw *hw, +struct ieee80211_vif *vif, +struct cfg80211_gtk_rekey_data *data) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); + +mutex_lock (&dev->mt76.mutex); +mt7921_mcu_update_gtk_rekey (hw, vif, data); +mutex_unlock (&dev->mt76.mutex); +} +#endif /* CONFIG_PM */ +const struct ieee80211_ops mt7921_ops = { .tx = mt7921_tx, .start = mt7921_start,
@@ -969,4 +1042,10 @@ const struct ieee80211_ops mt7921_ops = { .cancel_hw_scan = mt7921_cancel_hw_scan, .sched_scan_start = mt7921_start_sched_scan, .sched_scan_stop = mt7921_stop_sched_scan, +#ifdef CONFIG_PM + .suspend = mt7921_suspend, + .resume = mt7921_resume, + .set_wakeup = mt7921_set_wakeup, + .set_rekey_data = mt7921_set_rekey_data, +#endif /* CONFIG_PM */ };
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +307 -0
322 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +99 -0
105 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +9 -0
@@ -365,4 +365,13 @@ u32 mt7921_get_wtbl_info(struct mt7921_dev *dev, u16 wlan_idx);int mt7921_mcu_set_vif_ps (struct mt7921_dev *dev,struct ieee80211_vif *vif);int mt7921_mcu_set_bss_pm (struct mt7921_dev *dev,struct ieee80211_vif *vif,bool enable); +int mt7921_mcu_set_hif_suspend (struct mt7921_dev *dev,bool suspend); +void mt7921_mcu_set_suspend_iter (void *priv,u8 *mac, +struct ieee80211_vif *vif); +int mt7921_mcu_update_gtk_rekey (struct ieee80211_hw *hw, +struct ieee80211_vif *vif, +struct cfg80211_gtk_rekey_data *key); +int mt7921_mcu_update_arp_filter (struct ieee80211_hw *hw, +struct ieee80211_vif *vif, +struct ieee80211_bss_conf *info);#endif
drivers/net/wireless/mediatek/mt76/mt7921/pci.c +95 -0
106 lines not on this page · raw message
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 7/15 mt76: mt7921: add ieee80211_ops
In reply to [email protected]From: Sean Wang <[email protected]>
Filling ieee80211_ops with the mt7921 operations.
--- .../net/wireless/mediatek/mt76/mt7921/main.c | 931 ++++++++++++++++++ 1 file changed, 931 insertions(+) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/main.c
drivers/net/wireless/mediatek/mt76/mt7921/main.c new file +931 -0
@@ -0,0 +1,931 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include <linux/etherdevice.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/module.h> +#include "mt7921.h" +#include "mcu.h" + +static void +mt7921_gen_ppe_thresh (u8 *he_ppet,int nss) +{ +u8 i, ppet_bits, ppet_size, ru_bit_mask =0x7 ;/* HE80 */ +u8 ppet16_ppet8_ru3_ru0[] = {0x1c ,0xc7 ,0x71 }; + + 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 +mt7921_init_he_caps (struct mt7921_phy *phy,enum nl80211_band band, +struct ieee80211_sband_iftype_data *data) +{ +int i, idx =0 ; +int nss =hweight8 (phy->mt76->chainmask); +u16 mcs_map =0 ; + +for (i =0 ; i <8 ; i++) { +if (i < nss) + mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i *2 )); +else + mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i *2 )); + } + +for (i =0 ; i <NUM_NL80211_IFTYPES ; i++) { +struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap; +struct ieee80211_he_cap_elem *he_cap_elem = + &he_cap->he_cap_elem; +struct ieee80211_he_mcs_nss_supp *he_mcs = + &he_cap->he_mcs_nss_supp; + +switch (i) { +case NL80211_IFTYPE_STATION : +break ; +default : +continue ; + } + + data[idx].types_mask =BIT (i); + he_cap->has_he = true; + + he_cap_elem->mac_cap_info[0 ] = +IEEE80211_HE_MAC_CAP0_HTC_HE ; + he_cap_elem->mac_cap_info[3 ] = +IEEE80211_HE_MAC_CAP3_OMI_CONTROL | +IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_RESERVED ; + he_cap_elem->mac_cap_info[4 ] = +IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU ; + +if (band ==NL80211_BAND_2GHZ ) + he_cap_elem->phy_cap_info[0 ] = +IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G ; +else if (band ==NL80211_BAND_5GHZ ) + he_cap_elem->phy_cap_info[0 ] = +IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | +IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G ; + + he_cap_elem->phy_cap_info[1 ] = +IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD ; + he_cap_elem->phy_cap_info[2 ] = +IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | +IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ ; + +switch (i) { +case NL80211_IFTYPE_STATION : + he_cap_elem->mac_cap_info[0 ] |= +IEEE80211_HE_MAC_CAP0_TWT_REQ ; + he_cap_elem->mac_cap_info[1 ] |= +IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US ; + +if (band ==NL80211_BAND_2GHZ ) + he_cap_elem->phy_cap_info[0 ] |= +IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G ; +else if (band ==NL80211_BAND_5GHZ ) + he_cap_elem->phy_cap_info[0 ] |= +IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G ; + + he_cap_elem->phy_cap_info[1 ] |= +IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | +IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US ; + he_cap_elem->phy_cap_info[3 ] |= +IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | +IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK ; + he_cap_elem->phy_cap_info[6 ] |= +IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB | +IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | +IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT ; + he_cap_elem->phy_cap_info[7 ] |= +IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR | +IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI ; + he_cap_elem->phy_cap_info[8 ] |= +IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | +IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484 ; + he_cap_elem->phy_cap_info[9 ] |= +IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM | +IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK | +IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | +IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU | +IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | +IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB ; +break ; + } + + he_mcs->rx_mcs_80 =cpu_to_le16 (mcs_map); + he_mcs->tx_mcs_80 =cpu_to_le16 (mcs_map); + he_mcs->rx_mcs_160 =cpu_to_le16 (mcs_map); + he_mcs->tx_mcs_160 =cpu_to_le16 (mcs_map); + he_mcs->rx_mcs_80p80 =cpu_to_le16 (mcs_map); + he_mcs->tx_mcs_80p80 =cpu_to_le16 (mcs_map); + +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 ) { +mt7921_gen_ppe_thresh (he_cap->ppe_thres, nss); + }else { + he_cap_elem->phy_cap_info[9 ] |= +IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US ; + } + idx++; + } + +return idx; +} + +void mt7921_set_stream_he_caps (struct mt7921_phy *phy) +{ +struct ieee80211_sband_iftype_data *data; +struct ieee80211_supported_band *band; +int n; + +if (phy->mt76->cap.has_2ghz) { + data = phy->iftype[NL80211_BAND_2GHZ ]; + n =mt7921_init_he_caps (phy,NL80211_BAND_2GHZ , data); + + band = &phy->mt76->sband_2g.sband; + band->iftype_data = data; + band->n_iftype_data = n; + } + +if (phy->mt76->cap.has_5ghz) { + data = phy->iftype[NL80211_BAND_5GHZ ]; + n =mt7921_init_he_caps (phy,NL80211_BAND_5GHZ , data); + + band = &phy->mt76->sband_5g.sband; + band->iftype_data = data; + band->n_iftype_data = n; + } +} + +static int mt7921_start (struct ieee80211_hw *hw) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); + +mutex_lock (&dev->mt76.mutex); + +mt7921_mcu_set_mac (dev,0 , true, false); +mt7921_mcu_set_channel_domain (phy); +mt7921_mcu_set_chan_info (phy,MCU_EXT_CMD_SET_RX_PATH ); +mt7921_mac_reset_counters (phy); +set_bit (MT76_STATE_RUNNING , &phy->mt76->state); + +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work, +MT7921_WATCHDOG_TIME ); + +mutex_unlock (&dev->mt76.mutex); + +return 0 ; +} + +static void mt7921_stop (struct ieee80211_hw *hw) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); + +cancel_delayed_work_sync (&phy->mt76->mac_work); + +mutex_lock (&dev->mt76.mutex); +clear_bit (MT76_STATE_RUNNING , &phy->mt76->state); +mt7921_mcu_set_mac (dev,0 , false, false); +mutex_unlock (&dev->mt76.mutex); +} + +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_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 : +/* 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 : +WARN_ON (1 ); +break ; + } + +return -1 ; +} + +static int mt7921_add_interface (struct ieee80211_hw *hw, +struct ieee80211_vif *vif) +{ +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); +struct mt76_txq *mtxq; +int idx, ret =0 ; + +mutex_lock (&dev->mt76.mutex); + +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 >=MT7921_MAX_INTERFACES ) { + ret = -ENOSPC ; + goto out; + } + + idx =get_omac_idx (vif->type, phy->omac_mask); +if (idx <0 ) { + ret = -ENOSPC ; + goto out; + } + mvif->omac_idx = idx; + mvif->phy = phy; + mvif->band_idx =0 ; + mvif->wmm_idx = mvif->idx %MT7921_MAX_WMM_SETS ; + + ret =mt7921_mcu_uni_add_dev (dev, vif, true); +if (ret) + goto out; + + phy->mt76->vif_mask |=BIT (mvif->idx); + phy->omac_mask |=BIT_ULL (mvif->omac_idx); + + idx =MT7921_WTBL_RESERVED - mvif->idx; + +INIT_LIST_HEAD (&mvif->sta.stats_list); +INIT_LIST_HEAD (&mvif->sta.poll_list); + mvif->sta.wcid.idx = idx; + mvif->sta.wcid.ext_phy = mvif->band_idx; + mvif->sta.wcid.hw_key_idx =-1 ; + mvif->sta.wcid.tx_info |=MT_WCID_TX_INFO_SET ; +mt7921_mac_wtbl_update (dev, idx, +MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); + +rcu_assign_pointer (dev->mt76.wcid[idx], &mvif->sta.wcid); +if (vif->txq) { + mtxq = (struct mt76_txq *)vif->txq->drv_priv; + 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); + +return ret; +} + +static void mt7921_remove_interface (struct ieee80211_hw *hw, +struct ieee80211_vif *vif) +{ +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; +struct mt7921_sta *msta = &mvif->sta; +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); +int idx = msta->wcid.idx; + +if (vif == phy->monitor_vif) + phy->monitor_vif =NULL ; + +mt7921_mcu_uni_add_dev (dev, 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_ULL (mvif->omac_idx); +mutex_unlock (&dev->mt76.mutex); + +spin_lock_bh (&dev->sta_poll_lock); +if (!list_empty (&msta->poll_list)) +list_del_init (&msta->poll_list); +spin_unlock_bh (&dev->sta_poll_lock); +} + +int mt7921_set_channel (struct mt7921_phy *phy) +{ +struct mt7921_dev *dev = phy->dev; +int ret; + +cancel_delayed_work_sync (&phy->mt76->mac_work); + +mutex_lock (&dev->mt76.mutex); +set_bit (MT76_RESET , &phy->mt76->state); + +mt76_set_channel (phy->mt76); + + ret =mt7921_mcu_set_chan_info (phy,MCU_EXT_CMD_CHANNEL_SWITCH ); +if (ret) + goto out; + +mt7921_mac_set_timing (phy); + +mt7921_mac_reset_counters (phy); + phy->noise =0 ; + +out: +clear_bit (MT76_RESET , &phy->mt76->state); +mutex_unlock (&dev->mt76.mutex); + +mt76_txq_schedule_all (phy->mt76); + +ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mt76->mac_work, +MT7921_WATCHDOG_TIME ); + +return ret; +} + +static int mt7921_set_key (struct ieee80211_hw *hw,enum set_key_cmd cmd, +struct ieee80211_vif *vif,struct ieee80211_sta *sta, +struct ieee80211_key_conf *key) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; +struct mt7921_sta *msta = sta ? (struct mt7921_sta *)sta->drv_priv : + &mvif->sta; +struct mt76_wcid *wcid = &msta->wcid; +int idx = key->keyidx; + +/* The hardware does not support per-STA RX GTK, fallback +* to software mode for these. +*/ +if ((vif->type ==NL80211_IFTYPE_ADHOC || + vif->type ==NL80211_IFTYPE_MESH_POINT ) && + (key->cipher ==WLAN_CIPHER_SUITE_TKIP || + key->cipher ==WLAN_CIPHER_SUITE_CCMP ) && + !(key->flags &IEEE80211_KEY_FLAG_PAIRWISE )) +return -EOPNOTSUPP ; + +/* fall back to sw encryption for unsupported ciphers */ +switch (key->cipher) { +case WLAN_CIPHER_SUITE_AES_CMAC : + key->flags |=IEEE80211_KEY_FLAG_GENERATE_MMIE ; +break ; +case WLAN_CIPHER_SUITE_TKIP : +case WLAN_CIPHER_SUITE_CCMP : +case WLAN_CIPHER_SUITE_CCMP_256 : +case WLAN_CIPHER_SUITE_GCMP : +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 ; + } + +if (cmd ==SET_KEY ) { + key->hw_key_idx = wcid->idx; + wcid->hw_key_idx = idx; + }else if (idx == wcid->hw_key_idx) { + wcid->hw_key_idx =-1 ; + } +mt76_wcid_key_setup (&dev->mt76, wcid, + cmd ==SET_KEY ? key :NULL ); + +return mt7921_mcu_add_key (dev, vif, msta, key, cmd); +} + +static int mt7921_config (struct ieee80211_hw *hw,u32 changed) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); +bool band = phy != &dev->phy; +int ret; + +if (changed &IEEE80211_CONF_CHANGE_CHANNEL ) { +ieee80211_stop_queues (hw); + ret =mt7921_set_channel (phy); +if (ret) +return ret; +ieee80211_wake_queues (hw); + } + +mutex_lock (&dev->mt76.mutex); + +if (changed &IEEE80211_CONF_CHANGE_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_wr (dev,MT_WF_RFCR (band), phy->rxfilter); + } + +mutex_unlock (&dev->mt76.mutex); + +return 0 ; +} + +static int +mt7921_conf_tx (struct ieee80211_hw *hw,struct ieee80211_vif *vif,u16 queue, +const struct ieee80211_tx_queue_params *params) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + +/* no need to update right away, we'll get BSS_CHANGED_QOS */ + queue =mt7921_lmac_mapping (dev, queue); + mvif->queue_params[queue] = *params; + +return 0 ; +} + +static void mt7921_configure_filter (struct ieee80211_hw *hw, +unsigned int changed_flags, +unsigned int *total_flags, +u64 multicast) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); +bool band = phy != &dev->phy; +u32 ctl_flags =MT_WF_RFCR1_DROP_ACK | +MT_WF_RFCR1_DROP_BF_POLL | +MT_WF_RFCR1_DROP_BA | +MT_WF_RFCR1_DROP_CFEND | +MT_WF_RFCR1_DROP_CFACK ; +u32 flags =0 ; + +#define MT76_FILTER (_flag, _hw) do { \ + flags |= *total_flags & FIF_##_flag; \ + phy->rxfilter &= ~(_hw); \ + phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + } while (0) + +mutex_lock (&dev->mt76.mutex); + + 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 | +MT_WF_RFCR_DROP_MCAST | +MT_WF_RFCR_DROP_BCAST | +MT_WF_RFCR_DROP_DUPLICATE | +MT_WF_RFCR_DROP_A2_BSSID | +MT_WF_RFCR_DROP_UNWANTED_CTL | +MT_WF_RFCR_DROP_STBC_MULTI ); + +MT76_FILTER (OTHER_BSS ,MT_WF_RFCR_DROP_OTHER_TIM | +MT_WF_RFCR_DROP_A3_MAC | +MT_WF_RFCR_DROP_A3_BSSID ); + +MT76_FILTER (FCSFAIL ,MT_WF_RFCR_DROP_FCSFAIL ); + +MT76_FILTER (CONTROL ,MT_WF_RFCR_DROP_CTS | +MT_WF_RFCR_DROP_RTS | +MT_WF_RFCR_DROP_CTL_RSV | +MT_WF_RFCR_DROP_NDPA ); + + *total_flags = flags; +mt76_wr (dev,MT_WF_RFCR (band), phy->rxfilter); + +if (*total_flags &FIF_CONTROL ) +mt76_clear (dev,MT_WF_RFCR1 (band), ctl_flags); +else +mt76_set (dev,MT_WF_RFCR1 (band), ctl_flags); + +mutex_unlock (&dev->mt76.mutex); +} + +static void mt7921_bss_info_changed (struct ieee80211_hw *hw, +struct ieee80211_vif *vif, +struct ieee80211_bss_conf *info, +u32 changed) +{ +struct mt7921_phy *phy =mt7921_hw_phy (hw); +struct mt7921_dev *dev =mt7921_hw_dev (hw); + +mutex_lock (&dev->mt76.mutex); + +if (changed &BSS_CHANGED_ERP_SLOT ) { +int slottime = info->use_short_slot ?9 :20 ; + +if (slottime != phy->slottime) { + phy->slottime = slottime; +mt7921_mac_set_timing (phy); + } + } + +/* ensure that enable txcmd_mode after bss_info */ +if (changed & (BSS_CHANGED_QOS |BSS_CHANGED_BEACON_ENABLED )) +mt7921_mcu_set_tx (dev, vif); + +mutex_unlock (&dev->mt76.mutex); +} + +int mt7921_mac_sta_add (struct mt76_dev *mdev,struct ieee80211_vif *vif, +struct ieee80211_sta *sta) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); +struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; +int ret, idx; + + idx =mt76_wcid_alloc (dev->mt76.wcid_mask,MT7921_WTBL_STA -1 ); +if (idx <0 ) +return -ENOSPC ; + +INIT_LIST_HEAD (&msta->stats_list); +INIT_LIST_HEAD (&msta->poll_list); + msta->vif = mvif; + msta->wcid.sta =1 ; + msta->wcid.idx = idx; + msta->wcid.ext_phy = mvif->band_idx; + msta->wcid.tx_info |=MT_WCID_TX_INFO_SET ; + msta->stats.jiffies = jiffies; + +if (vif->type ==NL80211_IFTYPE_STATION && !sta->tdls) +mt7921_mcu_uni_add_bss (&dev->phy, vif, true); +mt7921_mac_wtbl_update (dev, idx, +MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); + + ret =mt7921_mcu_uni_add_sta (dev, vif, sta, true); +if (ret) +return ret; + +return 0 ; +} + +void mt7921_mac_sta_remove (struct mt76_dev *mdev,struct ieee80211_vif *vif, +struct ieee80211_sta *sta) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); +struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + +mt7921_mcu_uni_add_sta (dev, vif, sta, false); +mt7921_mac_wtbl_update (dev, msta->wcid.idx, +MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); +if (vif->type ==NL80211_IFTYPE_STATION && !sta->tdls) +mt7921_mcu_uni_add_bss (&dev->phy, vif, false); + +spin_lock_bh (&dev->sta_poll_lock); +if (!list_empty (&msta->poll_list)) +list_del_init (&msta->poll_list); +if (!list_empty (&msta->stats_list)) +list_del_init (&msta->stats_list); +spin_unlock_bh (&dev->sta_poll_lock); +} + +static void mt7921_tx (struct ieee80211_hw *hw, +struct ieee80211_tx_control *control, +struct sk_buff *skb) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt76_phy *mphy = hw->priv; +struct ieee80211_tx_info *info =IEEE80211_SKB_CB (skb); +struct ieee80211_vif *vif = info->control.vif; +struct mt76_wcid *wcid = &dev->mt76.global_wcid; + +if (control->sta) { +struct mt7921_sta *sta; + + sta = (struct mt7921_sta *)control->sta->drv_priv; + wcid = &sta->wcid; + } + +if (vif && !control->sta) { +struct mt7921_vif *mvif; + + mvif = (struct mt7921_vif *)vif->drv_priv; + wcid = &mvif->sta.wcid; + } + +mt76_tx (mphy, control->sta, wcid, skb); +} + +static int mt7921_set_rts_threshold (struct ieee80211_hw *hw,u32 val) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); + +mutex_lock (&dev->mt76.mutex); +mt7921_mcu_set_rts_thresh (phy, val); +mutex_unlock (&dev->mt76.mutex); + +return 0 ; +} + +static int +mt7921_ampdu_action (struct ieee80211_hw *hw,struct ieee80211_vif *vif, +struct ieee80211_ampdu_params *params) +{ +enum ieee80211_ampdu_mlme_action action = params->action; +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct ieee80211_sta *sta = params->sta; +struct ieee80211_txq *txq = sta->txq[params->tid]; +struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; +u16 tid = params->tid; +u16 ssn = params->ssn; +struct mt76_txq *mtxq; +int ret =0 ; + +if (!txq) +return -EINVAL ; + + mtxq = (struct mt76_txq *)txq->drv_priv; + +mutex_lock (&dev->mt76.mutex); +switch (action) { +case IEEE80211_AMPDU_RX_START : +mt76_rx_aggr_start (&dev->mt76, &msta->wcid, tid, ssn, + params->buf_size); +mt7921_mcu_uni_rx_ba (dev, params, true); +break ; +case IEEE80211_AMPDU_RX_STOP : +mt76_rx_aggr_stop (&dev->mt76, &msta->wcid, tid); +mt7921_mcu_uni_rx_ba (dev, params, false); +break ; +case IEEE80211_AMPDU_TX_OPERATIONAL : + mtxq->aggr = true; + mtxq->send_bar = false; +mt7921_mcu_uni_tx_ba (dev, params, true); +break ; +case IEEE80211_AMPDU_TX_STOP_FLUSH : +case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT : + mtxq->aggr = false; +clear_bit (tid, &msta->ampdu_state); +mt7921_mcu_uni_tx_ba (dev, params, false); +break ; +case IEEE80211_AMPDU_TX_START : +set_bit (tid, &msta->ampdu_state); + ret =IEEE80211_AMPDU_TX_START_IMMEDIATE ; +break ; +case IEEE80211_AMPDU_TX_STOP_CONT : + mtxq->aggr = false; +clear_bit (tid, &msta->ampdu_state); +mt7921_mcu_uni_tx_ba (dev, params, false); +ieee80211_stop_tx_ba_cb_irqsafe (vif, sta->addr, tid); +break ; + } +mutex_unlock (&dev->mt76.mutex); + +return ret; +} + +static int +mt7921_sta_add (struct ieee80211_hw *hw,struct ieee80211_vif *vif, +struct ieee80211_sta *sta) +{ +return mt76_sta_state (hw, vif, sta,IEEE80211_STA_NOTEXIST , +IEEE80211_STA_NONE ); +} + +static int +mt7921_sta_remove (struct ieee80211_hw *hw,struct ieee80211_vif *vif, +struct ieee80211_sta *sta) +{ +return mt76_sta_state (hw, vif, sta,IEEE80211_STA_NONE , +IEEE80211_STA_NOTEXIST ); +} + +static int +mt7921_get_stats (struct ieee80211_hw *hw, +struct ieee80211_low_level_stats *stats) +{ +struct mt7921_phy *phy =mt7921_hw_phy (hw); +struct mib_stats *mib = &phy->mib; + + stats->dot11RTSSuccessCount = mib->rts_cnt; + stats->dot11RTSFailureCount = mib->rts_retries_cnt; + stats->dot11FCSErrorCount = mib->fcs_err_cnt; + stats->dot11ACKFailureCount = mib->ack_fail_cnt; + +return 0 ; +} + +static u64 +mt7921_get_tsf (struct ieee80211_hw *hw,struct ieee80211_vif *vif) +{ +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); +bool band = phy != &dev->phy; +union { +u64 t64; +u32 t32[2 ]; + } tsf; +u16 n; + +mutex_lock (&dev->mt76.mutex); + + n = mvif->omac_idx >HW_BSSID_MAX ?HW_BSSID_0 : mvif->omac_idx; +/* TSF software read */ +mt76_set (dev,MT_LPON_TCR (band, n),MT_LPON_TCR_SW_MODE ); + tsf.t32[0 ] =mt76_rr (dev,MT_LPON_UTTR0 (band)); + tsf.t32[1 ] =mt76_rr (dev,MT_LPON_UTTR1 (band)); + +mutex_unlock (&dev->mt76.mutex); + +return tsf.t64; +} + +static void +mt7921_set_tsf (struct ieee80211_hw *hw,struct ieee80211_vif *vif, +u64 timestamp) +{ +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); +bool band = phy != &dev->phy; +union { +u64 t64; +u32 t32[2 ]; + } tsf = { .t64 = timestamp, }; +u16 n; + +mutex_lock (&dev->mt76.mutex); + + n = mvif->omac_idx >HW_BSSID_MAX ?HW_BSSID_0 : mvif->omac_idx; +mt76_wr (dev,MT_LPON_UTTR0 (band), tsf.t32[0 ]); +mt76_wr (dev,MT_LPON_UTTR1 (band), tsf.t32[1 ]); +/* TSF software overwrite */ +mt76_set (dev,MT_LPON_TCR (band, n),MT_LPON_TCR_SW_WRITE ); + +mutex_unlock (&dev->mt76.mutex); +} + +static void +mt7921_set_coverage_class (struct ieee80211_hw *hw,s16 coverage_class) +{ +struct mt7921_phy *phy =mt7921_hw_phy (hw); +struct mt7921_dev *dev = phy->dev; + +mutex_lock (&dev->mt76.mutex); + phy->coverage_class =max_t (s16, coverage_class,0 ); +mt7921_mac_set_timing (phy); +mutex_unlock (&dev->mt76.mutex); +} + +void mt7921_scan_work (struct work_struct *work) +{ +struct mt7921_phy *phy; + + phy = (struct mt7921_phy *)container_of(work, struct mt7921_phy, + scan_work.work); + +while (true) { +struct mt7921_mcu_rxd *rxd; +struct sk_buff *skb; + +spin_lock_bh (&phy->dev->mt76.lock); + skb =__skb_dequeue (&phy->scan_event_list); +spin_unlock_bh (&phy->dev->mt76.lock); + +if (!skb) +break ; + + rxd = (struct mt7921_mcu_rxd *)skb->data; +if (rxd->eid ==MCU_EVENT_SCHED_SCAN_DONE ) { +ieee80211_sched_scan_results (phy->mt76->hw); + }else if (test_and_clear_bit (MT76_HW_SCANNING , + &phy->mt76->state)) { +struct cfg80211_scan_info info = { + .aborted = false, + }; + +ieee80211_scan_completed (phy->mt76->hw, &info); + } +dev_kfree_skb (skb); + } +} + +static int +mt7921_hw_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif, +struct ieee80211_scan_request *req) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt76_phy *mphy = hw->priv; +int err; + +mutex_lock (&dev->mt76.mutex); + err =mt7921_mcu_hw_scan (mphy->priv, vif, req); +mutex_unlock (&dev->mt76.mutex); + +return err; +} + +static void +mt7921_cancel_hw_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt76_phy *mphy = hw->priv; + +mutex_lock (&dev->mt76.mutex); +mt7921_mcu_cancel_hw_scan (mphy->priv, vif); +mutex_unlock (&dev->mt76.mutex); +} + +static int +mt7921_set_antenna (struct ieee80211_hw *hw,u32 tx_ant,u32 rx_ant) +{ +struct mt7921_dev *dev =mt7921_hw_dev (hw); +struct mt7921_phy *phy =mt7921_hw_phy (hw); +int max_nss =hweight8 (hw->wiphy->available_antennas_tx); + +if (!tx_ant || tx_ant != rx_ant ||ffs (tx_ant) > max_nss) +return -EINVAL ; + +if ((BIT (hweight8 (tx_ant)) -1 ) != tx_ant) + tx_ant =BIT (ffs (tx_ant) -1 ) -1 ; + +mutex_lock (&dev->mt76.mutex); + + phy->mt76->antenna_mask = tx_ant; + phy->mt76->chainmask = tx_ant; + +mt76_set_stream_caps (phy->mt76, true); +mt7921_set_stream_he_caps (phy); + +mutex_unlock (&dev->mt76.mutex); + +return 0 ; +} + +static void +mt7921_sta_rc_update (struct ieee80211_hw *hw, +struct ieee80211_vif *vif, +struct ieee80211_sta *sta, +u32 changed) +{ +} + +const struct ieee80211_ops mt7921_ops = { + .tx = mt7921_tx, + .start = mt7921_start, + .stop = mt7921_stop, + .add_interface = mt7921_add_interface, + .remove_interface = mt7921_remove_interface, + .config = mt7921_config, + .conf_tx = mt7921_conf_tx, + .configure_filter = mt7921_configure_filter, + .bss_info_changed = mt7921_bss_info_changed, + .sta_add = mt7921_sta_add, + .sta_remove = mt7921_sta_remove, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, + .sta_rc_update = mt7921_sta_rc_update, + .set_key = mt7921_set_key, + .ampdu_action = mt7921_ampdu_action, + .set_rts_threshold = mt7921_set_rts_threshold, + .wake_tx_queue = mt76_wake_tx_queue, + .release_buffered_frames = mt76_release_buffered_frames, + .get_txpower = mt76_get_txpower, + .get_stats = mt7921_get_stats, + .get_tsf = mt7921_get_tsf, + .set_tsf = mt7921_set_tsf, + .get_survey = mt76_get_survey, + .get_antenna = mt76_get_antenna, + .set_antenna = mt7921_set_antenna, + .set_coverage_class = mt7921_set_coverage_class, + .hw_scan = mt7921_hw_scan, + .cancel_hw_scan = mt7921_cancel_hw_scan, +};
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
[email protected]
reviewerPATCH v5 4/15 mt76: mt7921: add MCU support
In reply to [email protected]From: Sean Wang <[email protected]>
MT7921 contains a microprocessor with which the host can use command/event to communicate to implement offload features such as establish connection, hardware scan and so on. The host has to download the ROM patch, RAM firmware and finally activate the MCU to complete the MT7921 initialization.
--- .../net/wireless/mediatek/mt76/mt7921/mac.c | 28 + .../net/wireless/mediatek/mt76/mt7921/mcu.c | 2446 +++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/mcu.h | 1050 +++++++ .../wireless/mediatek/mt76/mt7921/mt7921.h | 2 + 4 files changed, 3526 insertions(+) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mcu.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +28 -0
@@ -1338,6 +1338,30 @@ mt7921_mac_update_mib_stats(struct mt7921_phy *phy) } } +static void +mt7921_mac_sta_stats_work (struct mt7921_phy *phy) +{ +struct mt7921_dev *dev = phy->dev; +struct mt7921_sta *msta; +LIST_HEAD (list); + +spin_lock_bh (&dev->sta_poll_lock); +list_splice_init (&phy->stats_list, &list); + +while (!list_empty (&list)) { + msta = list_first_entry(&list, struct mt7921_sta, stats_list); +list_del_init (&msta->stats_list); +spin_unlock_bh (&dev->sta_poll_lock); + +/* query wtbl info to report tx rate for further devices */ +mt7921_get_wtbl_info (dev, msta->wcid.idx); + +spin_lock_bh (&dev->sta_poll_lock); + } + +spin_unlock_bh (&dev->sta_poll_lock); +} +void mt7921_mac_work (struct work_struct *work) {struct mt7921_phy *phy;
@@ -1355,6 +1379,10 @@ void mt7921_mac_work(struct work_struct *work)mt7921_mac_update_mib_stats (phy); } +if (++phy->sta_work_count ==10 ) { + phy->sta_work_count =0 ; +mt7921_mac_sta_stats_work (phy); + };mutex_unlock (&mphy->dev->mutex);
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c new file +2446 -0
2,446 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7921/mcu.h new file +1050 -0
514 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +2 -0
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 5 lines
2.25.1 _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
Part of the diff is not shown here. View the raw message.
[email protected]
reviewerPATCH v5 13/15 mt76: mt7921: introduce support for hardware beacon filter
In reply to [email protected]From: Sean Wang <[email protected]>
Introduce support for hw beacon filter available in the mt7921 firmware.
--- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 40 +++++++++++++++++++ .../wireless/mediatek/mt76/mt7921/mt7921.h | 2 + 2 files changed, 42 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +40 -0
@@ -2548,3 +2548,43 @@ int mt7921_mcu_set_vif_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif)return mt76_mcu_send_msg (&dev->mt76,MCU_CMD_SET_PS_PROFILE , &req,sizeof (req), false); } + +int mt7921_mcu_set_bss_pm (struct mt7921_dev *dev,struct ieee80211_vif *vif, +bool enable) +{ +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; +struct { +u8 bss_idx; +u8 dtim_period; +__le16 aid; +__le16 bcn_interval; +__le16 atim_window; +u8 uapsd; +u8 bmc_delivered_ac; +u8 bmc_triggered_ac; +u8 pad; + } req = { + .bss_idx = mvif->idx, + .aid =cpu_to_le16 (vif->bss_conf.aid), + .dtim_period = vif->bss_conf.dtim_period, + .bcn_interval =cpu_to_le16 (vif->bss_conf.beacon_int), + }; +struct { +u8 bss_idx; +u8 pad[3 ]; + } req_hdr = { + .bss_idx = mvif->idx, + }; +int err; + +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); +if (err <0 || !enable) +return err; + +return mt76_mcu_send_msg (&dev->mt76,MCU_CMD_SET_BSS_CONNECTED , &req, +sizeof (req), false); +}
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +2 -0
@@ -363,4 +363,6 @@ int mt7921_mcu_cancel_hw_scan(struct mt7921_phy *phy, struct ieee80211_vif *vif);u32 mt7921_get_wtbl_info (struct mt7921_dev *dev,u16 wlan_idx);int mt7921_mcu_set_vif_ps (struct mt7921_dev *dev,struct ieee80211_vif *vif); +int mt7921_mcu_set_bss_pm (struct mt7921_dev *dev,struct ieee80211_vif *vif, +bool enable);#endif
Signature · 1 line
2.25.1
[email protected]
reviewerPATCH v5 3/15 mt76: mt7921: add MAC support
In reply to [email protected]From: Sean Wang <[email protected]>
Add Rx packet description parsing, Tx packet description compositon, handle packet recycling and provide MAC information mt76 core needs to support mac80211.
--- .../net/wireless/mediatek/mt76/mt7921/mac.c | 1363 +++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/mac.h | 333 ++++ .../wireless/mediatek/mt76/mt7921/mt7921.h | 354 +++++ .../net/wireless/mediatek/mt76/mt7921/regs.h | 413 +++++ 4 files changed, 2463 insertions(+) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mac.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mac.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/regs.h
drivers/net/wireless/mediatek/mt76/mt7921/mac.c new file +1363 -0
@@ -0,0 +1,1363 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include <linux/etherdevice.h> +#include <linux/timekeeping.h> +#include "mt7921.h" +#include "../dma.h" +#include "mac.h" + +#define to_rssi (field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) + +#define HE_BITS (f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) +#define HE_PREP (f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ + IEEE80211_RADIOTAP_HE_##f) + +static struct mt76_wcid *mt7921_rx_get_wcid (struct mt7921_dev *dev, +u16 idx,bool unicast) +{ +struct mt7921_sta *sta; +struct mt76_wcid *wcid; + +if (idx >=ARRAY_SIZE (dev->mt76.wcid)) +return NULL ; + + wcid =rcu_dereference (dev->mt76.wcid[idx]); +if (unicast || !wcid) +return wcid; + +if (!wcid->sta) +return NULL ; + + sta = container_of(wcid, struct mt7921_sta, wcid); +if (!sta->vif) +return NULL ; + +return &sta->vif->sta.wcid; +} + +void mt7921_sta_ps (struct mt76_dev *mdev,struct ieee80211_sta *sta,bool ps) +{ +} + +bool mt7921_mac_wtbl_update (struct mt7921_dev *dev,int idx,u32 mask) +{ +mt76_rmw (dev,MT_WTBL_UPDATE ,MT_WTBL_UPDATE_WLAN_IDX , +FIELD_PREP (MT_WTBL_UPDATE_WLAN_IDX , idx) | mask); + +return mt76_poll (dev,MT_WTBL_UPDATE ,MT_WTBL_UPDATE_BUSY , +0 ,5000 ); +} + +static u32 mt7921_mac_wtbl_lmac_addr (struct mt7921_dev *dev,u16 wcid) +{ +mt76_wr (dev,MT_WTBLON_TOP_WDUCR , +FIELD_PREP (MT_WTBLON_TOP_WDUCR_GROUP , (wcid >>7 ))); + +return MT_WTBL_LMAC_OFFS (wcid,0 ); +} + +static void mt7921_mac_sta_poll (struct mt7921_dev *dev) +{ +static const u8 ac_to_tid[] = { + [IEEE80211_AC_BE ] =0 , + [IEEE80211_AC_BK ] =1 , + [IEEE80211_AC_VI ] =4 , + [IEEE80211_AC_VO ] =6 + }; +struct ieee80211_sta *sta; +struct mt7921_sta *msta; +u32 tx_time[IEEE80211_NUM_ACS ], rx_time[IEEE80211_NUM_ACS ]; +LIST_HEAD (sta_poll_list); +int i; + +spin_lock_bh (&dev->sta_poll_lock); +list_splice_init (&dev->sta_poll_list, &sta_poll_list); +spin_unlock_bh (&dev->sta_poll_lock); + +rcu_read_lock (); + +while (true) { +bool clear = false; +u32 addr; +u16 idx; + +spin_lock_bh (&dev->sta_poll_lock); +if (list_empty (&sta_poll_list)) { +spin_unlock_bh (&dev->sta_poll_lock); +break ; + } + msta =list_first_entry (&sta_poll_list, + struct mt7921_sta, poll_list); +list_del_init (&msta->poll_list); +spin_unlock_bh (&dev->sta_poll_lock); + + idx = msta->wcid.idx; + addr =mt7921_mac_wtbl_lmac_addr (dev, idx) +20 *4 ; + +for (i =0 ; i <IEEE80211_NUM_ACS ; i++) { +u32 tx_last = msta->airtime_ac[i]; +u32 rx_last = msta->airtime_ac[i +4 ]; + + msta->airtime_ac[i] =mt76_rr (dev, addr); + msta->airtime_ac[i +4 ] =mt76_rr (dev, addr +4 ); + + tx_time[i] = msta->airtime_ac[i] - tx_last; + rx_time[i] = msta->airtime_ac[i +4 ] - rx_last; + +if ((tx_last | rx_last) &BIT (30 )) + clear = true; + + addr +=8 ; + } + +if (clear) { +mt7921_mac_wtbl_update (dev, idx, +MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); +memset (msta->airtime_ac,0 ,sizeof (msta->airtime_ac)); + } + +if (!msta->wcid.sta) +continue ; + + sta = container_of((void *)msta, struct ieee80211_sta, + drv_priv); +for (i =0 ; i <IEEE80211_NUM_ACS ; i++) { +u8 q =mt7921_lmac_mapping (dev, i); +u32 tx_cur = tx_time[q]; +u32 rx_cur = rx_time[q]; +u8 tid = ac_to_tid[i]; + +if (!tx_cur && !rx_cur) +continue ; + +ieee80211_sta_register_airtime (sta, tid, tx_cur, + rx_cur); + } + } + +rcu_read_unlock (); +} + +static void +mt7921_mac_decode_he_radiotap_ru (struct mt76_rx_status *status, +struct ieee80211_radiotap_he *he, +__le32 *rxv) +{ +u32 ru_h, ru_l; +u8 ru, offs =0 ; + + ru_l =FIELD_GET (MT_PRXV_HE_RU_ALLOC_L ,le32_to_cpu (rxv[0 ])); + ru_h =FIELD_GET (MT_PRXV_HE_RU_ALLOC_H ,le32_to_cpu (rxv[1 ])); + ru = (u8)(ru_l | ru_h <<4 ); + + status->bw =RATE_INFO_BW_HE_RU ; + +switch (ru) { + case 0 ... 36: + status->he_ru =NL80211_RATE_INFO_HE_RU_ALLOC_26 ; + offs = ru; +break ; + case 37 ... 52: + status->he_ru =NL80211_RATE_INFO_HE_RU_ALLOC_52 ; + offs = ru -37 ; +break ; + case 53 ... 60: + status->he_ru =NL80211_RATE_INFO_HE_RU_ALLOC_106 ; + offs = ru -53 ; +break ; + case 61 ... 64: + status->he_ru =NL80211_RATE_INFO_HE_RU_ALLOC_242 ; + offs = ru -61 ; +break ; + case 65 ... 66: + status->he_ru =NL80211_RATE_INFO_HE_RU_ALLOC_484 ; + offs = ru -65 ; +break ; +case 67 : + status->he_ru =NL80211_RATE_INFO_HE_RU_ALLOC_996 ; +break ; +case 68 : + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; +break ; + } + + he->data1 |=HE_BITS (DATA1_BW_RU_ALLOC_KNOWN ); + he->data2 |=HE_BITS (DATA2_RU_OFFSET_KNOWN ) | +le16_encode_bits (offs, +IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET ); +} + +static void +mt7921_mac_decode_he_radiotap (struct sk_buff *skb, +struct mt76_rx_status *status, +__le32 *rxv,u32 phy) +{ +/* TODO: struct ieee80211_radiotap_he_mu */ +static const struct ieee80211_radiotap_he known = { + .data1 =HE_BITS (DATA1_DATA_MCS_KNOWN ) | +HE_BITS (DATA1_DATA_DCM_KNOWN ) | +HE_BITS (DATA1_STBC_KNOWN ) | +HE_BITS (DATA1_CODING_KNOWN ) | +HE_BITS (DATA1_LDPC_XSYMSEG_KNOWN ) | +HE_BITS (DATA1_DOPPLER_KNOWN ) | +HE_BITS (DATA1_BSS_COLOR_KNOWN ), + .data2 =HE_BITS (DATA2_GI_KNOWN ) | +HE_BITS (DATA2_TXBF_KNOWN ) | +HE_BITS (DATA2_PE_DISAMBIG_KNOWN ) | +HE_BITS (DATA2_TXOP_KNOWN ), + }; +struct ieee80211_radiotap_he *he =NULL ; +u32 ltf_size =le32_get_bits (rxv[2 ],MT_CRXV_HE_LTF_SIZE ) +1 ; + + he =skb_push (skb,sizeof (known)); +memcpy (he, &known,sizeof (known)); + + he->data3 =HE_PREP (DATA3_BSS_COLOR ,BSS_COLOR , rxv[14 ]) | +HE_PREP (DATA3_LDPC_XSYMSEG ,LDPC_EXT_SYM , rxv[2 ]); + he->data5 =HE_PREP (DATA5_PE_DISAMBIG ,PE_DISAMBIG , rxv[2 ]) | +le16_encode_bits (ltf_size, +IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE ); + he->data6 =HE_PREP (DATA6_TXOP ,TXOP_DUR , rxv[14 ]) | +HE_PREP (DATA6_DOPPLER ,DOPPLER , rxv[14 ]); + +switch (phy) { +case MT_PHY_TYPE_HE_SU : + he->data1 |=HE_BITS (DATA1_FORMAT_SU ) | +HE_BITS (DATA1_UL_DL_KNOWN ) | +HE_BITS (DATA1_BEAM_CHANGE_KNOWN ) | +HE_BITS (DATA1_SPTL_REUSE_KNOWN ); + + he->data3 |=HE_PREP (DATA3_BEAM_CHANGE ,BEAM_CHNG , rxv[14 ]) | +HE_PREP (DATA3_UL_DL ,UPLINK , rxv[2 ]); + he->data4 |=HE_PREP (DATA4_SU_MU_SPTL_REUSE ,SR_MASK , rxv[11 ]); +break ; +case MT_PHY_TYPE_HE_EXT_SU : + he->data1 |=HE_BITS (DATA1_FORMAT_EXT_SU ) | +HE_BITS (DATA1_UL_DL_KNOWN ); + + he->data3 |=HE_PREP (DATA3_UL_DL ,UPLINK , rxv[2 ]); +break ; +case MT_PHY_TYPE_HE_MU : + he->data1 |=HE_BITS (DATA1_FORMAT_MU ) | +HE_BITS (DATA1_UL_DL_KNOWN ) | +HE_BITS (DATA1_SPTL_REUSE_KNOWN ); + + he->data3 |=HE_PREP (DATA3_UL_DL ,UPLINK , rxv[2 ]); + he->data4 |=HE_PREP (DATA4_SU_MU_SPTL_REUSE ,SR_MASK , rxv[11 ]); + +mt7921_mac_decode_he_radiotap_ru (status, he, rxv); +break ; +case MT_PHY_TYPE_HE_TB : + he->data1 |=HE_BITS (DATA1_FORMAT_TRIG ) | +HE_BITS (DATA1_SPTL_REUSE_KNOWN ) | +HE_BITS (DATA1_SPTL_REUSE2_KNOWN ) | +HE_BITS (DATA1_SPTL_REUSE3_KNOWN ) | +HE_BITS (DATA1_SPTL_REUSE4_KNOWN ); + + he->data4 |=HE_PREP (DATA4_TB_SPTL_REUSE1 ,SR_MASK , rxv[11 ]) | +HE_PREP (DATA4_TB_SPTL_REUSE2 ,SR1_MASK , rxv[11 ]) | +HE_PREP (DATA4_TB_SPTL_REUSE3 ,SR2_MASK , rxv[11 ]) | +HE_PREP (DATA4_TB_SPTL_REUSE4 ,SR3_MASK , rxv[11 ]); + +mt7921_mac_decode_he_radiotap_ru (status, he, rxv); +break ; +default : +break ; + } +} + +static void +mt7921_get_status_freq_info (struct mt7921_dev *dev,struct mt76_phy *mphy, +struct mt76_rx_status *status,u8 chfreq) +{ +if (!test_bit (MT76_HW_SCANNING , &mphy->state) && + !test_bit (MT76_HW_SCHED_SCANNING , &mphy->state) && + !test_bit (MT76_STATE_ROC , &mphy->state)) { + status->freq = mphy->chandef.chan->center_freq; + status->band = mphy->chandef.chan->band; +return ; + } + + status->band = chfreq <=14 ?NL80211_BAND_2GHZ :NL80211_BAND_5GHZ ; + status->freq =ieee80211_channel_to_frequency (chfreq, status->band); +} + +int mt7921_mac_fill_rx (struct mt7921_dev *dev,struct sk_buff *skb) +{ +struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; +struct mt76_phy *mphy = &dev->mt76.phy; +struct mt7921_phy *phy = &dev->phy; +struct ieee80211_supported_band *sband; +struct ieee80211_hdr *hdr; +__le32 *rxd = (__le32 *)skb->data; +__le32 *rxv =NULL ; +u32 mode =0 ; +u32 rxd1 =le32_to_cpu (rxd[1 ]); +u32 rxd2 =le32_to_cpu (rxd[2 ]); +u32 rxd3 =le32_to_cpu (rxd[3 ]); +bool unicast, insert_ccmp_hdr = false; +u8 remove_pad; +int i, idx; +u8 chfreq; + +memset (status,0 ,sizeof (*status)); + +if (rxd1 &MT_RXD1_NORMAL_BAND_IDX ) +return -EINVAL ; + +if (!test_bit (MT76_STATE_RUNNING , &mphy->state)) +return -EINVAL ; + + chfreq =FIELD_GET (MT_RXD3_NORMAL_CH_FREQ , rxd3); + unicast =FIELD_GET (MT_RXD3_NORMAL_ADDR_TYPE , rxd3) ==MT_RXD3_NORMAL_U2M ; + idx =FIELD_GET (MT_RXD1_NORMAL_WLAN_IDX , rxd1); + status->wcid =mt7921_rx_get_wcid (dev, idx, unicast); + +if (status->wcid) { +struct mt7921_sta *msta; + + msta = container_of(status->wcid, struct mt7921_sta, wcid); +spin_lock_bh (&dev->sta_poll_lock); +if (list_empty (&msta->poll_list)) +list_add_tail (&msta->poll_list, &dev->sta_poll_list); +spin_unlock_bh (&dev->sta_poll_lock); + } + +mt7921_get_status_freq_info (dev, mphy, status, chfreq); + +if (status->band ==NL80211_BAND_5GHZ ) + sband = &mphy->sband_5g.sband; +else + sband = &mphy->sband_2g.sband; + +if (!sband->channels) +return -EINVAL ; + +if (rxd1 &MT_RXD1_NORMAL_FCS_ERR ) + status->flag |=RX_FLAG_FAILED_FCS_CRC ; + +if (rxd1 &MT_RXD1_NORMAL_TKIP_MIC_ERR ) + status->flag |=RX_FLAG_MMIC_ERROR ; + +if (FIELD_GET (MT_RXD1_NORMAL_SEC_MODE , rxd1) !=0 && + !(rxd1 & (MT_RXD1_NORMAL_CLM |MT_RXD1_NORMAL_CM ))) { + status->flag |=RX_FLAG_DECRYPTED ; + status->flag |=RX_FLAG_IV_STRIPPED ; + status->flag |=RX_FLAG_MMIC_STRIPPED |RX_FLAG_MIC_STRIPPED ; + } + +if (!(rxd2 &MT_RXD2_NORMAL_NON_AMPDU )) { + status->flag |=RX_FLAG_AMPDU_DETAILS ; + +/* all subframes of an A-MPDU have the same timestamp */ +if (phy->rx_ampdu_ts != rxd[14 ]) { +if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = rxd[14 ]; + + status->ampdu_ref = phy->ampdu_ref; + } + + remove_pad =FIELD_GET (MT_RXD2_NORMAL_HDR_OFFSET , rxd2); + +if (rxd2 &MT_RXD2_NORMAL_MAX_LEN_ERROR ) +return -EINVAL ; + + rxd +=6 ; +if (rxd1 &MT_RXD1_NORMAL_GROUP_4 ) { + rxd +=4 ; +if ((u8 *)rxd - skb->data >= skb->len) +return -EINVAL ; + } + +if (rxd1 &MT_RXD1_NORMAL_GROUP_1 ) { +u8 *data = (u8 *)rxd; + +if (status->flag &RX_FLAG_DECRYPTED ) { + status->iv[0 ] = data[5 ]; + status->iv[1 ] = data[4 ]; + status->iv[2 ] = data[3 ]; + status->iv[3 ] = data[2 ]; + status->iv[4 ] = data[1 ]; + status->iv[5 ] = data[0 ]; + + insert_ccmp_hdr =FIELD_GET (MT_RXD2_NORMAL_FRAG , rxd2); + } + rxd +=4 ; +if ((u8 *)rxd - skb->data >= skb->len) +return -EINVAL ; + } + +if (rxd1 &MT_RXD1_NORMAL_GROUP_2 ) { + rxd +=2 ; +if ((u8 *)rxd - skb->data >= skb->len) +return -EINVAL ; + } + +/* RXD Group 3 - P-RXV */ +if (rxd1 &MT_RXD1_NORMAL_GROUP_3 ) { +u32 v0, v1, v2; + + rxv = rxd; + rxd +=2 ; +if ((u8 *)rxd - skb->data >= skb->len) +return -EINVAL ; + + v0 =le32_to_cpu (rxv[0 ]); + v1 =le32_to_cpu (rxv[1 ]); + v2 =le32_to_cpu (rxv[2 ]); + +if (v0 &MT_PRXV_HT_AD_CODE ) + status->enc_flags |=RX_ENC_FLAG_LDPC ; + + status->chains = mphy->antenna_mask; + status->chain_signal[0 ] =to_rssi (MT_PRXV_RCPI0 , v1); + status->chain_signal[1 ] =to_rssi (MT_PRXV_RCPI1 , v1); + status->chain_signal[2 ] =to_rssi (MT_PRXV_RCPI2 , v1); + status->chain_signal[3 ] =to_rssi (MT_PRXV_RCPI3 , v1); + status->signal = status->chain_signal[0 ]; + +for (i =1 ; i <hweight8 (mphy->antenna_mask); i++) { +if (!(status->chains &BIT (i))) +continue ; + + status->signal =max (status->signal, + status->chain_signal[i]); + } + +/* RXD Group 5 - C-RXV */ +if (rxd1 &MT_RXD1_NORMAL_GROUP_5 ) { +u8 stbc =FIELD_GET (MT_CRXV_HT_STBC , v2); +u8 gi =FIELD_GET (MT_CRXV_HT_SHORT_GI , v2); +bool cck = false; + + rxd +=18 ; +if ((u8 *)rxd - skb->data >= skb->len) +return -EINVAL ; + + idx = i =FIELD_GET (MT_PRXV_TX_RATE , v0); + mode =FIELD_GET (MT_CRXV_TX_MODE , v2); + +switch (mode) { +case MT_PHY_TYPE_CCK : + cck = true; + fallthrough; +case MT_PHY_TYPE_OFDM : + i =mt76_get_rate (&dev->mt76, sband, i, cck); +break ; +case MT_PHY_TYPE_HT_GF : +case MT_PHY_TYPE_HT : + status->encoding =RX_ENC_HT ; +if (i >31 ) +return -EINVAL ; +break ; +case MT_PHY_TYPE_VHT : + status->nss = +FIELD_GET (MT_PRXV_NSTS , v0) +1 ; + status->encoding =RX_ENC_VHT ; +if (i >9 ) +return -EINVAL ; +break ; +case MT_PHY_TYPE_HE_MU : + status->flag |=RX_FLAG_RADIOTAP_HE_MU ; + fallthrough; +case MT_PHY_TYPE_HE_SU : +case MT_PHY_TYPE_HE_EXT_SU : +case MT_PHY_TYPE_HE_TB : + status->nss = +FIELD_GET (MT_PRXV_NSTS , v0) +1 ; + status->encoding =RX_ENC_HE ; + status->flag |=RX_FLAG_RADIOTAP_HE ; + i &=GENMASK (3 ,0 ); + +if (gi <=NL80211_RATE_INFO_HE_GI_3_2 ) + status->he_gi = gi; + + status->he_dcm = !!(idx &MT_PRXV_TX_DCM ); +break ; +default : +return -EINVAL ; + } + status->rate_idx = i; + +switch (FIELD_GET (MT_CRXV_FRAME_MODE , v2)) { +case IEEE80211_STA_RX_BW_20 : +break ; +case IEEE80211_STA_RX_BW_40 : +if (mode &MT_PHY_TYPE_HE_EXT_SU && + (idx &MT_PRXV_TX_ER_SU_106T )) { + status->bw =RATE_INFO_BW_HE_RU ; + status->he_ru = +NL80211_RATE_INFO_HE_RU_ALLOC_106 ; + }else { + status->bw =RATE_INFO_BW_40 ; + } +break ; +case IEEE80211_STA_RX_BW_80 : + status->bw =RATE_INFO_BW_80 ; +break ; +case IEEE80211_STA_RX_BW_160 : + status->bw =RATE_INFO_BW_160 ; +break ; +default : +return -EINVAL ; + } + + status->enc_flags |=RX_ENC_FLAG_STBC_MASK * stbc; +if (mode <MT_PHY_TYPE_HE_SU && gi) + status->enc_flags |=RX_ENC_FLAG_SHORT_GI ; + } + } + +skb_pull (skb, (u8 *)rxd - skb->data +2 * remove_pad); + +if (insert_ccmp_hdr) { +u8 key_id =FIELD_GET (MT_RXD1_NORMAL_KEY_ID , rxd1); + +mt76_insert_ccmp_hdr (skb, key_id); + } + +if (rxv && status->flag &RX_FLAG_RADIOTAP_HE ) +mt7921_mac_decode_he_radiotap (skb, status, rxv, mode); + + hdr =mt76_skb_get_hdr (skb); +if (!status->wcid || !ieee80211_is_data_qos (hdr->frame_control)) +return 0 ; + + status->aggr = unicast && + !ieee80211_is_qos_nullfunc (hdr->frame_control); + status->tid = *ieee80211_get_qos_ctl (hdr) &IEEE80211_QOS_CTL_TID_MASK ; + status->seqno =IEEE80211_SEQ_TO_SN (le16_to_cpu (hdr->seq_ctrl)); + +return 0 ; +} + +static void +mt7921_mac_write_txwi_8023 (struct mt7921_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 +mt7921_mac_write_txwi_80211 (struct mt7921_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 mt7921_mac_write_txwi (struct mt7921_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_vif *vif = info->control.vif; +struct mt76_phy *mphy = &dev->mphy; +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) { +struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + + omac_idx = mvif->omac_idx; + wmm_idx = mvif->wmm_idx; + } + +if (beacon) { + p_fmt =MT_TX_TYPE_FW ; + q_idx =MT_LMAC_BCN0 ; + }else if (skb_get_queue_mapping (skb) >=MT_TXQ_PSD ) { + p_fmt =MT_TX_TYPE_CT ; + q_idx =MT_LMAC_ALTX0 ; + }else { + p_fmt =MT_TX_TYPE_CT ; + q_idx = wmm_idx *MT7921_MAX_WMM_SETS + +mt7921_lmac_mapping (dev,skb_get_queue_mapping (skb)); + } + + 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); + txwi[0 ] =cpu_to_le32 (val); + + val =MT_TXD1_LONG_FORMAT | +FIELD_PREP (MT_TXD1_WLAN_IDX , wcid->idx) | +FIELD_PREP (MT_TXD1_OWN_MAC , omac_idx); + + txwi[1 ] =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 ; + + 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) +mt7921_mac_write_txwi_8023 (dev, txwi, skb, wcid); +else +mt7921_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_HTC_VLD ); + +if (mphy->chandef.chan->band ==NL80211_BAND_5GHZ ) + rate =MT7921_5G_RATE_DEFAULT ; +else + rate =MT7921_2G_RATE_DEFAULT ; + + val =MT_TXD6_FIXED_BW | +FIELD_PREP (MT_TXD6_TX_RATE , rate); + txwi[6 ] |=cpu_to_le32 (val); + txwi[3 ] |=cpu_to_le32 (MT_TXD3_BA_DISABLE ); + } +} + +static void +mt7921_write_hw_txp (struct mt7921_dev *dev,struct mt76_tx_info *tx_info, +void *txp_ptr,u32 id) +{ +struct mt7921_hw_txp *txp = txp_ptr; +struct mt7921_txp_ptr *ptr = &txp->ptr[0 ]; +int i, nbuf = tx_info->nbuf -1 ; + + tx_info->buf[0 ].len =MT_TXD_SIZE +sizeof (*txp); + tx_info->nbuf =1 ; + + txp->msdu_id[0 ] =cpu_to_le16 (id |MT_MSDU_ID_VALID ); + +for (i =0 ; i < nbuf; i++) { +u16 len = tx_info->buf[i +1 ].len &MT_TXD_LEN_MASK ; +u32 addr = tx_info->buf[i +1 ].addr; + +if (i == nbuf -1 ) + len |=MT_TXD_LEN_LAST ; + +if (i &1 ) { + ptr->buf1 =cpu_to_le32 (addr); + ptr->len1 =cpu_to_le16 (len); + ptr++; + }else { + ptr->buf0 =cpu_to_le32 (addr); + ptr->len0 =cpu_to_le16 (len); + } + } +} + +static void mt7921_set_tx_blocked (struct mt7921_dev *dev,bool blocked) +{ +struct mt76_phy *mphy = &dev->mphy; +struct mt76_queue *q; + + q = mphy->q_tx[0 ]; +if (blocked == q->blocked) +return ; + + q->blocked = blocked; +if (!blocked) +mt76_worker_schedule (&dev->mt76.tx_worker); +} + +int mt7921_tx_prepare_skb (struct mt76_dev *mdev,void *txwi_ptr, +enum mt76_txq_id qid,struct mt76_wcid *wcid, +struct ieee80211_sta *sta, +struct mt76_tx_info *tx_info) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); +struct ieee80211_tx_info *info =IEEE80211_SKB_CB (tx_info->skb); +struct ieee80211_key_conf *key = info->control.hw_key; +struct mt76_tx_cb *cb =mt76_tx_skb_cb (tx_info->skb); +struct mt76_txwi_cache *t; +struct mt7921_txp_common *txp; +int id; +u8 *txwi = (u8 *)txwi_ptr; + +if (unlikely (tx_info->skb->len <=ETH_HLEN )) +return -EINVAL ; + +if (!wcid) + wcid = &dev->mt76.global_wcid; + + cb->wcid = wcid->idx; + + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); + t->skb = tx_info->skb; + +spin_lock_bh (&dev->token_lock); + id =idr_alloc (&dev->token, t,0 ,MT7921_TOKEN_SIZE ,GFP_ATOMIC ); +if (id >=0 ) + dev->token_count++; + +if (dev->token_count >=MT7921_TOKEN_SIZE -MT7921_TOKEN_FREE_THR ) +mt7921_set_tx_blocked (dev, true); +spin_unlock_bh (&dev->token_lock); + +if (id <0 ) +return id; + +mt7921_mac_write_txwi (dev, txwi_ptr, tx_info->skb, wcid, key, + false); + + txp = (struct mt7921_txp_common *)(txwi +MT_TXD_SIZE ); +memset (txp,0 ,sizeof (struct mt7921_txp_common )); +mt7921_write_hw_txp (dev, tx_info, txp, id); + + tx_info->skb =DMA_DUMMY_DATA ; + +return 0 ; +} + +static void +mt7921_tx_check_aggr (struct ieee80211_sta *sta,__le32 *txwi) +{ +struct mt7921_sta *msta; +u16 fc, tid; +u32 val; + +if (!sta || !sta->ht_cap.ht_supported) +return ; + + tid =FIELD_GET (MT_TXD1_TID ,le32_to_cpu (txwi[1 ])); +if (tid >=6 )/* skip VO queue */ +return ; + + val =le32_to_cpu (txwi[2 ]); + fc =FIELD_GET (MT_TXD2_FRAME_TYPE , val) <<2 | +FIELD_GET (MT_TXD2_SUB_TYPE , val) <<4 ; +if (unlikely (fc != (IEEE80211_FTYPE_DATA |IEEE80211_STYPE_QOS_DATA ))) +return ; + + msta = (struct mt7921_sta *)sta->drv_priv; +if (!test_and_set_bit (tid, &msta->ampdu_state)) +ieee80211_start_tx_ba_session (sta, tid,0 ); +} + +static void +mt7921_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, + }; +struct ieee80211_hw *hw; + +if (sta) { +struct mt7921_sta *msta; + + msta = (struct mt7921_sta *)sta->drv_priv; + status.rate = &msta->stats.tx_rate; + } + + hw =mt76_tx_status_get_hw (mdev, skb); + +if (info->flags &IEEE80211_TX_CTL_AMPDU ) + info->flags |=IEEE80211_TX_STAT_AMPDU ; + +if (stat) +ieee80211_tx_info_clear_status (info); + +if (!(info->flags &IEEE80211_TX_CTL_NO_ACK )) + info->flags |=IEEE80211_TX_STAT_ACK ; + + info->status.tx_time =0 ; +ieee80211_tx_status_ext (hw, &status); +} + +void mt7921_txp_skb_unmap (struct mt76_dev *dev, +struct mt76_txwi_cache *t) +{ +struct mt7921_txp_common *txp; +int i; + + txp =mt7921_txwi_to_txp (dev, t); + +for (i =0 ; i <ARRAY_SIZE (txp->hw.ptr); i++) { +struct mt7921_txp_ptr *ptr = &txp->hw.ptr[i]; +bool last; +u16 len; + + len =le16_to_cpu (ptr->len0); + last = len &MT_TXD_LEN_LAST ; + len &=MT_TXD_LEN_MASK ; +dma_unmap_single (dev->dev,le32_to_cpu (ptr->buf0), len, +DMA_TO_DEVICE ); +if (last) +break ; + + len =le16_to_cpu (ptr->len1); + last = len &MT_TXD_LEN_LAST ; + len &=MT_TXD_LEN_MASK ; +dma_unmap_single (dev->dev,le32_to_cpu (ptr->buf1), len, +DMA_TO_DEVICE ); +if (last) +break ; + } +} + +void mt7921_mac_tx_free (struct mt7921_dev *dev,struct sk_buff *skb) +{ +struct mt7921_tx_free *free = (struct mt7921_tx_free *)skb->data; +struct mt76_dev *mdev = &dev->mt76; +struct mt76_txwi_cache *txwi; +struct ieee80211_sta *sta =NULL ; +LIST_HEAD (free_list); +struct sk_buff *tmp; +bool wake = false; +u8 i, count; + +/* clean DMA queues and unmap buffers first */ +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); + +/* TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE, +* to the time ack is received or dropped by hw (air + hw queue time). +* Should avoid accessing WTBL to get Tx airtime, and use it instead. +*/ + count =FIELD_GET (MT_TX_FREE_MSDU_CNT ,le16_to_cpu (free->ctrl)); +for (i =0 ; i < count; i++) { +u32 msdu, info =le32_to_cpu (free->info[i]); +u8 stat; + +/* 1'b1: new wcid pair. +* 1'b0: msdu_id with the same 'wcid pair' as above. +*/ +if (info &MT_TX_FREE_PAIR ) { +struct mt7921_sta *msta; +struct mt7921_phy *phy; +struct mt76_wcid *wcid; +u16 idx; + + count++; + idx =FIELD_GET (MT_TX_FREE_WLAN_ID , info); + wcid =rcu_dereference (dev->mt76.wcid[idx]); + sta =wcid_to_sta (wcid); +if (!sta) +continue ; + + msta = container_of(wcid, struct mt7921_sta, wcid); + phy = msta->vif->phy; +spin_lock_bh (&dev->sta_poll_lock); +if (list_empty (&msta->stats_list)) +list_add_tail (&msta->stats_list, &phy->stats_list); +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); + stat =FIELD_GET (MT_TX_FREE_STATUS , info); + +spin_lock_bh (&dev->token_lock); + txwi =idr_remove (&dev->token, msdu); +if (txwi) + dev->token_count--; +if (dev->token_count <MT7921_TOKEN_SIZE -MT7921_TOKEN_FREE_THR && + dev->mphy.q_tx[0 ]->blocked) + wake = true; +spin_unlock_bh (&dev->token_lock); + +if (!txwi) +continue ; + +mt7921_txp_skb_unmap (mdev, txwi); +if (txwi->skb) { +struct ieee80211_tx_info *info =IEEE80211_SKB_CB (txwi->skb); +void *txwi_ptr =mt76_get_txwi_ptr (mdev, txwi); + +if (likely (txwi->skb->protocol !=cpu_to_be16 (ETH_P_PAE ))) +mt7921_tx_check_aggr (sta, txwi_ptr); + +if (sta && !info->tx_time_est) { +struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; +int pending; + + pending =atomic_dec_return (&wcid->non_aql_packets); +if (pending <0 ) +atomic_cmpxchg (&wcid->non_aql_packets, pending,0 ); + } + +mt7921_tx_complete_status (mdev, txwi->skb, sta, stat, &free_list); + txwi->skb =NULL ; + } + +mt76_put_txwi (mdev, txwi); + } + +mt7921_mac_sta_poll (dev); + +if (wake) { +spin_lock_bh (&dev->token_lock); +mt7921_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 mt7921_tx_complete_skb (struct mt76_dev *mdev,struct mt76_queue_entry *e) +{ +struct mt7921_dev *dev; + +if (!e->txwi) { +dev_kfree_skb_any (e->skb); +return ; + } + + dev = container_of(mdev, struct mt7921_dev, mt76); + +/* error path */ +if (e->skb ==DMA_DUMMY_DATA ) { +struct mt76_txwi_cache *t; +struct mt7921_txp_common *txp; +u16 token; + + txp =mt7921_txwi_to_txp (mdev, e->txwi); + + token =le16_to_cpu (txp->hw.msdu_id[0 ]) & ~MT_MSDU_ID_VALID ; +spin_lock_bh (&dev->token_lock); + t =idr_remove (&dev->token, token); +spin_unlock_bh (&dev->token_lock); + e->skb = t ? t->skb :NULL ; + } + +if (e->skb) { +struct mt76_tx_cb *cb =mt76_tx_skb_cb (e->skb); +struct mt76_wcid *wcid; + + wcid =rcu_dereference (dev->mt76.wcid[cb->wcid]); + +mt7921_tx_complete_status (mdev, e->skb,wcid_to_sta (wcid),0 , +NULL ); + } +} + +void mt7921_mac_reset_counters (struct mt7921_phy *phy) +{ +struct mt7921_dev *dev = phy->dev; +int i; + +for (i =0 ; i <4 ; i++) { +mt76_rr (dev,MT_TX_AGG_CNT (0 , i)); +mt76_rr (dev,MT_TX_AGG_CNT2 (0 , i)); + } + + dev->mt76.phy.survey_time =ktime_get_boottime (); +memset (&dev->mt76.aggr_stats[0 ],0 ,sizeof (dev->mt76.aggr_stats) /2 ); + +/* reset airtime counters */ +mt76_rr (dev,MT_MIB_SDR9 (0 )); +mt76_rr (dev,MT_MIB_SDR36 (0 )); +mt76_rr (dev,MT_MIB_SDR37 (0 )); + +mt76_set (dev,MT_WF_RMAC_MIB_TIME0 (0 ),MT_WF_RMAC_MIB_RXTIME_CLR ); +mt76_set (dev,MT_WF_RMAC_MIB_AIRTIME0 (0 ),MT_WF_RMAC_MIB_RXTIME_CLR ); +} + +void mt7921_mac_set_timing (struct mt7921_phy *phy) +{ +s16 coverage_class = phy->coverage_class; +struct mt7921_dev *dev = phy->dev; +u32 val, reg_offset; +u32 cck =FIELD_PREP (MT_TIMEOUT_VAL_PLCP ,231 ) | +FIELD_PREP (MT_TIMEOUT_VAL_CCA ,48 ); +u32 ofdm =FIELD_PREP (MT_TIMEOUT_VAL_PLCP ,60 ) | +FIELD_PREP (MT_TIMEOUT_VAL_CCA ,28 ); +int sifs, offset; +bool is_5ghz = phy->mt76->chandef.chan->band ==NL80211_BAND_5GHZ ; + +if (!test_bit (MT76_STATE_RUNNING , &phy->mt76->state)) +return ; + +if (is_5ghz) + sifs =16 ; +else + sifs =10 ; + +mt76_set (dev,MT_ARB_SCR (0 ), +MT_ARB_SCR_TX_DISABLE |MT_ARB_SCR_RX_DISABLE ); +udelay (1 ); + + offset =3 * coverage_class; + reg_offset =FIELD_PREP (MT_TIMEOUT_VAL_PLCP , offset) | +FIELD_PREP (MT_TIMEOUT_VAL_CCA , offset); + +mt76_wr (dev,MT_TMAC_CDTR (0 ), cck + reg_offset); +mt76_wr (dev,MT_TMAC_ODTR (0 ), ofdm + reg_offset); +mt76_wr (dev,MT_TMAC_ICR0 (0 ), +FIELD_PREP (MT_IFS_EIFS ,360 ) | +FIELD_PREP (MT_IFS_RIFS ,2 ) | +FIELD_PREP (MT_IFS_SIFS , sifs) | +FIELD_PREP (MT_IFS_SLOT , phy->slottime)); + +if (phy->slottime <20 || is_5ghz) + val =MT7921_CFEND_RATE_DEFAULT ; +else + val =MT7921_CFEND_RATE_11B ; + +mt76_rmw_field (dev,MT_AGG_ACR0 (0 ),MT_AGG_ACR_CFEND_RATE , val); +mt76_clear (dev,MT_ARB_SCR (0 ), +MT_ARB_SCR_TX_DISABLE |MT_ARB_SCR_RX_DISABLE ); +} + +static u8 +mt7921_phy_get_nf (struct mt7921_phy *phy,int idx) +{ +return 0 ; +} + +static void +mt7921_phy_update_channel (struct mt76_phy *mphy,int idx) +{ + struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76); +struct mt7921_phy *phy = (struct mt7921_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 ); + tx_time =mt76_get_field (dev,MT_MIB_SDR36 (idx), +MT_MIB_SDR36_TXTIME_MASK ); + rx_time =mt76_get_field (dev,MT_MIB_SDR37 (idx), +MT_MIB_SDR37_RXTIME_MASK ); + obss_time =mt76_get_field (dev,MT_WF_RMAC_MIB_AIRTIME14 (idx), +MT_MIB_OBSSTIME_MASK ); + + nf =mt7921_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 mt7921_update_channel (struct mt76_dev *mdev) +{ + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + +mt7921_phy_update_channel (&mdev->phy,0 ); +/* reset obss airtime */ +mt76_set (dev,MT_WF_RMAC_MIB_TIME0 (0 ),MT_WF_RMAC_MIB_RXTIME_CLR ); +} + +static bool +mt7921_wait_reset_state (struct mt7921_dev *dev,u32 state) +{ +bool ret; + + ret =wait_event_timeout (dev->reset_wait, + (READ_ONCE (dev->reset_state) & state), +MT7921_RESET_TIMEOUT ); + +WARN (!ret,"Timeout waiting for MCU reset state %x\n" , state); +return ret; +} + +static void +mt7921_dma_reset (struct mt7921_phy *phy) +{ +struct mt7921_dev *dev = phy->dev; +int i; + +mt76_clear (dev,MT_WFDMA0_GLO_CFG , +MT_WFDMA0_GLO_CFG_TX_DMA_EN |MT_WFDMA0_GLO_CFG_RX_DMA_EN ); + +usleep_range (1000 ,2000 ); + +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); + +mt76_for_each_q_rx (&dev->mt76, i) { +mt76_queue_rx_reset (dev, i); + } + +mt76_set (dev,MT_WFDMA0_GLO_CFG , +MT_WFDMA0_GLO_CFG_TX_DMA_EN |MT_WFDMA0_GLO_CFG_RX_DMA_EN ); +} + +void mt7921_tx_token_put (struct mt7921_dev *dev) +{ +struct mt76_txwi_cache *txwi; +int id; + +spin_lock_bh (&dev->token_lock); +idr_for_each_entry (&dev->token, txwi, id) { +mt7921_txp_skb_unmap (&dev->mt76, txwi); +if (txwi->skb) { +struct ieee80211_hw *hw; + + hw =mt76_tx_status_get_hw (&dev->mt76, txwi->skb); +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); +} + +/* system error recovery */ +void mt7921_mac_reset_work (struct work_struct *work) +{ +struct mt7921_dev *dev; + + dev = container_of(work, struct mt7921_dev, reset_work); + +if (!(READ_ONCE (dev->reset_state) &MT_MCU_CMD_STOP_DMA )) +return ; + +ieee80211_stop_queues (mt76_hw (dev)); + +set_bit (MT76_RESET , &dev->mphy.state); +set_bit (MT76_MCU_RESET , &dev->mphy.state); +wake_up (&dev->mt76.mcu.wait); +cancel_delayed_work_sync (&dev->mphy.mac_work); + +/* lock/unlock all queues to ensure that no tx is pending */ +mt76_txq_schedule_all (&dev->mphy); + +mt76_worker_disable (&dev->mt76.tx_worker); +napi_disable (&dev->mt76.napi[0 ]); +napi_disable (&dev->mt76.napi[1 ]); +napi_disable (&dev->mt76.napi[2 ]); +napi_disable (&dev->mt76.tx_napi); + +mutex_lock (&dev->mt76.mutex); + +mt76_wr (dev,MT_MCU_INT_EVENT ,MT_MCU_INT_EVENT_DMA_STOPPED ); + +mt7921_tx_token_put (dev); +idr_init (&dev->token); + +if (mt7921_wait_reset_state (dev,MT_MCU_CMD_RESET_DONE )) { +mt7921_dma_reset (&dev->phy); + +mt76_wr (dev,MT_MCU_INT_EVENT ,MT_MCU_INT_EVENT_DMA_INIT ); +mt7921_wait_reset_state (dev,MT_MCU_CMD_RECOVERY_DONE ); + } + +clear_bit (MT76_MCU_RESET , &dev->mphy.state); +clear_bit (MT76_RESET , &dev->mphy.state); + +mt76_worker_enable (&dev->mt76.tx_worker); +napi_enable (&dev->mt76.tx_napi); +napi_schedule (&dev->mt76.tx_napi); + +napi_enable (&dev->mt76.napi[0 ]); +napi_schedule (&dev->mt76.napi[0 ]); + +napi_enable (&dev->mt76.napi[1 ]); +napi_schedule (&dev->mt76.napi[1 ]); + +napi_enable (&dev->mt76.napi[2 ]); +napi_schedule (&dev->mt76.napi[2 ]); + +ieee80211_wake_queues (mt76_hw (dev)); + +mt76_wr (dev,MT_MCU_INT_EVENT ,MT_MCU_INT_EVENT_RESET_DONE ); +mt7921_wait_reset_state (dev,MT_MCU_CMD_NORMAL_STATE ); + +mutex_unlock (&dev->mt76.mutex); + +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work, +MT7921_WATCHDOG_TIME ); +} + +static void +mt7921_mac_update_mib_stats (struct mt7921_phy *phy) +{ +struct mt7921_dev *dev = phy->dev; +struct mib_stats *mib = &phy->mib; +int i, aggr0 =0 , aggr1; + +memset (mib,0 ,sizeof (*mib)); + + mib->fcs_err_cnt =mt76_get_field (dev,MT_MIB_SDR3 (0 ), +MT_MIB_SDR3_FCS_ERR_MASK ); + +for (i =0 , aggr1 = aggr0 +4 ; i <4 ; i++) { +u32 val, val2; + + val =mt76_rr (dev,MT_MIB_MB_SDR1 (0 , i)); + + val2 =FIELD_GET (MT_MIB_ACK_FAIL_COUNT_MASK , val); +if (val2 > mib->ack_fail_cnt) + mib->ack_fail_cnt = val2; + + val2 =FIELD_GET (MT_MIB_BA_MISS_COUNT_MASK , val); +if (val2 > mib->ba_miss_cnt) + mib->ba_miss_cnt = val2; + + val =mt76_rr (dev,MT_MIB_MB_SDR0 (0 , i)); + val2 =FIELD_GET (MT_MIB_RTS_RETRIES_COUNT_MASK , val); +if (val2 > mib->rts_retries_cnt) { + mib->rts_cnt =FIELD_GET (MT_MIB_RTS_COUNT_MASK , val); + mib->rts_retries_cnt = val2; + } + + val =mt76_rr (dev,MT_TX_AGG_CNT (0 , i)); + val2 =mt76_rr (dev,MT_TX_AGG_CNT2 (0 , i)); + + dev->mt76.aggr_stats[aggr0++] += val &0xffff ; + dev->mt76.aggr_stats[aggr0++] += val >>16 ; + dev->mt76.aggr_stats[aggr1++] += val2 &0xffff ; + dev->mt76.aggr_stats[aggr1++] += val2 >>16 ; + } +} + +void mt7921_mac_work (struct work_struct *work) +{ +struct mt7921_phy *phy; +struct mt76_phy *mphy; + + mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, + mac_work.work); + phy = mphy->priv; + +mutex_lock (&mphy->dev->mutex); + +mt76_update_survey (mphy->dev); +if (++mphy->mac_work_count ==5 ) { + mphy->mac_work_count =0 ; + +mt7921_mac_update_mib_stats (phy); + } + +mutex_unlock (&mphy->dev->mutex); + +ieee80211_queue_delayed_work (mphy->hw, &mphy->mac_work, +MT7921_WATCHDOG_TIME ); +}
drivers/net/wireless/mediatek/mt76/mt7921/mac.h new file +333 -0
333 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h new file +354 -0
354 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7921/regs.h new file +413 -0
413 lines not on this page · raw message
Signature · 1 line
2.25.1
[email protected]
reviewerPATCH v5 8/15 mt76: mt7921: introduce mt7921e support
In reply to [email protected]From: Sean Wang <[email protected]>
Introduce support for mt7921e 802.11ax (Wi-Fi 6) 2x2:2SS chipset.
--- .../net/wireless/mediatek/mt76/mt7921/init.c | 247 ++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7921/pci.c | 184 +++++++++++++ 2 files changed, 431 insertions(+) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/init.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7921/pci.c
drivers/net/wireless/mediatek/mt76/mt7921/init.c new file +247 -0
@@ -0,0 +1,247 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include <linux/etherdevice.h> +#include "mt7921.h" +#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 mt7921_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 =MT7921_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 =MT7921_MAX_INTERFACES , + .num_different_channels =1 , + .beacon_int_infra_match = true, + } +}; + +static void +mt7921_init_wiphy (struct ieee80211_hw *hw) +{ +struct mt7921_phy *phy =mt7921_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 mt7921_sta ); + hw->vif_data_size =sizeof (struct mt7921_vif ); + + wiphy->iface_combinations = if_comb; + wiphy->n_iface_combinations =ARRAY_SIZE (if_comb); + wiphy->max_scan_ie_len =MT7921_SCAN_IE_LEN ; + wiphy->max_scan_ssids =4 ; + wiphy->flags |=WIPHY_FLAG_HAS_CHANNEL_SWITCH ; + +wiphy_ext_feature_set (wiphy,NL80211_EXT_FEATURE_SET_SCAN_DWELL ); + +ieee80211_hw_set (hw,SINGLE_SCAN_ON_ALL_BANDS ); +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 +mt7921_mac_init_band (struct mt7921_dev *dev,u8 band) +{ +u32 mask, set; + +mt76_rmw_field (dev,MT_TMAC_CTCR0 (band), +MT_TMAC_CTCR0_INS_DDLMT_REFTIME ,0x3f ); +mt76_set (dev,MT_TMAC_CTCR0 (band), +MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | +MT_TMAC_CTCR0_INS_DDLMT_EN ); + + mask =MT_MDP_RCFR0_MCU_RX_MGMT | +MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR | +MT_MDP_RCFR0_MCU_RX_CTL_BAR ; + set =FIELD_PREP (MT_MDP_RCFR0_MCU_RX_MGMT ,MT_MDP_TO_HIF ) | +FIELD_PREP (MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR ,MT_MDP_TO_HIF ) | +FIELD_PREP (MT_MDP_RCFR0_MCU_RX_CTL_BAR ,MT_MDP_TO_HIF ); +mt76_rmw (dev,MT_MDP_BNRCFR0 (band), mask, set); + + mask =MT_MDP_RCFR1_MCU_RX_BYPASS | +MT_MDP_RCFR1_RX_DROPPED_UCAST | +MT_MDP_RCFR1_RX_DROPPED_MCAST ; + set =FIELD_PREP (MT_MDP_RCFR1_MCU_RX_BYPASS ,MT_MDP_TO_HIF ) | +FIELD_PREP (MT_MDP_RCFR1_RX_DROPPED_UCAST ,MT_MDP_TO_HIF ) | +FIELD_PREP (MT_MDP_RCFR1_RX_DROPPED_MCAST ,MT_MDP_TO_HIF ); +mt76_rmw (dev,MT_MDP_BNRCFR1 (band), mask, set); + +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 mt7921_mac_init (struct mt7921_dev *dev) +{ +int i; + +mt76_rmw_field (dev,MT_MDP_DCR1 ,MT_MDP_DCR1_MAX_RX_LEN ,1536 ); +/* disable hardware de-agg */ +mt76_clear (dev,MT_MDP_DCR0 ,MT_MDP_DCR0_DAMSDU_EN ); + +for (i =0 ; i <MT7921_WTBL_SIZE ; i++) +mt7921_mac_wtbl_update (dev, i, +MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); +for (i =0 ; i <2 ; i++) +mt7921_mac_init_band (dev, i); + +mt7921_mcu_set_rts_thresh (&dev->phy,0x92b ); +} + +static void mt7921_init_work (struct work_struct *work) +{ + struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + init_work); + +mt7921_mcu_set_eeprom (dev); +mt7921_mac_init (dev); +} + +static int mt7921_init_hardware (struct mt7921_dev *dev) +{ +int ret, idx; + +INIT_WORK (&dev->init_work, mt7921_init_work); +spin_lock_init (&dev->token_lock); +idr_init (&dev->token); + + ret =mt7921_dma_init (dev); +if (ret) +return ret; + +set_bit (MT76_STATE_INITIALIZED , &dev->mphy.state); + +/* force firmware operation mode into normal state, +* which should be set before firmware download stage. +*/ +mt76_wr (dev,MT_SWDEF_MODE ,MT_SWDEF_NORMAL_MODE ); + + ret =mt7921_mcu_init (dev); +if (ret) +return ret; + + ret =mt7921_eeprom_init (dev); +if (ret <0 ) +return ret; + +/* Beacon and mgmt frames should occupy wcid 0 */ + idx =mt76_wcid_alloc (dev->mt76.wcid_mask,MT7921_WTBL_STA -1 ); +if (idx) +return -ENOSPC ; + + dev->mt76.global_wcid.idx = idx; + dev->mt76.global_wcid.hw_key_idx =-1 ; + dev->mt76.global_wcid.tx_info |=MT_WCID_TX_INFO_SET ; +rcu_assign_pointer (dev->mt76.wcid[idx], &dev->mt76.global_wcid); + +return 0 ; +} + +int mt7921_register_device (struct mt7921_dev *dev) +{ +struct ieee80211_hw *hw =mt76_hw (dev); +int ret; + + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; +INIT_LIST_HEAD (&dev->phy.stats_list); +INIT_DELAYED_WORK (&dev->mphy.mac_work, mt7921_mac_work); +INIT_DELAYED_WORK (&dev->phy.scan_work, mt7921_scan_work); +skb_queue_head_init (&dev->phy.scan_event_list); +INIT_LIST_HEAD (&dev->sta_poll_list); +spin_lock_init (&dev->sta_poll_lock); + +init_waitqueue_head (&dev->reset_wait); +INIT_WORK (&dev->reset_work, mt7921_mac_reset_work); + + ret =mt7921_init_hardware (dev); +if (ret) +return ret; + +mt7921_init_wiphy (hw); + dev->mphy.sband_2g.sband.ht_cap.cap |= +IEEE80211_HT_CAP_LDPC_CODING | +IEEE80211_HT_CAP_MAX_AMSDU ; + dev->mphy.sband_5g.sband.ht_cap.cap |= +IEEE80211_HT_CAP_LDPC_CODING | +IEEE80211_HT_CAP_MAX_AMSDU ; + dev->mphy.sband_5g.sband.vht_cap.cap |= +IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | +IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK ; + 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->mphy.chainmask; + dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; + +mt76_set_stream_caps (&dev->mphy, true); +mt7921_set_stream_he_caps (&dev->phy); + + ret =mt76_register_device (&dev->mt76, true, mt7921_rates, +ARRAY_SIZE (mt7921_rates)); +if (ret) +return ret; + +ieee80211_queue_work (mt76_hw (dev), &dev->init_work); + +return 0 ; +} + +void mt7921_unregister_device (struct mt7921_dev *dev) +{ +mt76_unregister_device (&dev->mt76); +mt7921_mcu_exit (dev); +mt7921_dma_cleanup (dev); + +mt7921_tx_token_put (dev); + +tasklet_disable (&dev->irq_tasklet); +mt76_free_device (&dev->mt76); +}
drivers/net/wireless/mediatek/mt76/mt7921/pci.c new file +184 -0
184 lines not on this page · raw message
Signature · 1 line
2.25.1