wireless-next patches for v5.20

Third set of patches for v5.20. MLO work continues and we have a lot
 of stack changes due to that, including driver API changes. Not much
 driver patches except on mt76.
 
 Major changes:
 
 cfg80211/mac80211
 
 * more prepartion for Wi-Fi 7 Multi-Link Operation (MLO) support,
   works with one link now
 
 * align with IEEE Draft P802.11be_D2.0
 
 * hardware timestamps for receive and transmit
 
 mt76
 
 * preparation for new chipset support
 
 * ACPI SAR support
 -----BEGIN PGP SIGNATURE-----
 
 iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmLe1k4RHGt2YWxvQGtl
 cm5lbC5vcmcACgkQbhckVSbrbZvxlQf8DrZIllhF0q/7Wry3JuG0gbNA+V2eI/lc
 OYrephsDBm/dvvyjcFWcdUzxoNk0k1+aOrx/09JijHFgCGKVwuK1+hxYVfjW2q43
 9mHxJBo4NcMk1RDDM3paVuZ8QMHuYugbv2mQOZeAEq2XloAaqEM7wVE+bb4Mgtgx
 VAKS5du2igrSt83wl8BRMFb9MPAM1EQ3Cw7Ro5T4y+1Qm/hrBm6qWizSpqh9CXYx
 pDLR3pvQxiD4Axa0Uq3rUbyF4hLwciqSFOJvr2sI3q7b9YElA7wIi6NQzMkYJH6Z
 7HW5K6UIQbblAaQkv2BLqpU1N6puTHUOAf5Md31vOAaOcGbSI5hbUA==
 =Cnxg
 -----END PGP SIGNATURE-----

Merge tag 'wireless-next-2022-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next

Kalle Valo says:

====================
wireless-next patches for v5.20

Third set of patches for v5.20. MLO work continues and we have a lot
of stack changes due to that, including driver API changes. Not much
driver patches except on mt76.

Major changes:

cfg80211/mac80211
 - more prepartion for Wi-Fi 7 Multi-Link Operation (MLO) support,
   works with one link now
 - align with IEEE Draft P802.11be_D2.0
 - hardware timestamps for receive and transmit

mt76
 - preparation for new chipset support
 - ACPI SAR support

* tag 'wireless-next-2022-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (254 commits)
  wifi: mac80211: fix link data leak
  wifi: mac80211: mlme: fix disassoc with MLO
  wifi: mac80211: add macros to loop over active links
  wifi: mac80211: remove erroneous sband/link validation
  wifi: mac80211: mlme: transmit assoc frame with address translation
  wifi: mac80211: verify link addresses are different
  wifi: mac80211: rx: track link in RX data
  wifi: mac80211: optionally implement MLO multicast TX
  wifi: mac80211: expand ieee80211_mgmt_tx() for MLO
  wifi: nl80211: add MLO link ID to the NL80211_CMD_FRAME TX API
  wifi: mac80211: report link ID to cfg80211 on mgmt RX
  wifi: cfg80211: report link ID in NL80211_CMD_FRAME
  wifi: mac80211: add hardware timestamps for RX and TX
  wifi: cfg80211: add hardware timestamps to frame RX info
  wifi: cfg80211/nl80211: move rx management data into a struct
  wifi: cfg80211: add a function for reporting TX status with hardware timestamps
  wifi: nl80211: add RX and TX timestamp attributes
  wifi: ieee80211: add helper functions for detecting TM/FTM frames
  wifi: mac80211_hwsim: handle links for wmediumd/virtio
  wifi: mac80211: sta_info: fix link_sta insertion
  ...
====================

Link: https://lore.kernel.org/r/20220725174547.EA465C341C6@smtp.kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2022-07-25 18:20:51 -07:00
commit 2baf8ba532
179 changed files with 9826 additions and 7531 deletions

View File

@ -54,6 +54,16 @@ properties:
reset-names:
const: consys
clocks:
maxItems: 2
description:
Specify the consys clocks for mt7986.
clock-names:
items:
- const: mcu
- const: ap2conn
mediatek,infracfg:
$ref: /schemas/types.yaml#/definitions/phandle
description:
@ -269,5 +279,8 @@ examples:
<0x10003000 0x1000>,
<0x11d10000 0x1000>;
interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen 50>,
<&topckgen 62>;
clock-names = "mcu", "ap2conn";
memory-region = <&wmcpu_emi>;
};

View File

@ -6252,7 +6252,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_PS) {
arvif->ps = vif->bss_conf.ps;
arvif->ps = vif->cfg.ps;
ret = ath10k_config_ps(ar);
if (ret)
@ -7814,7 +7814,8 @@ exit:
}
static int ath10k_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 ac,
struct ieee80211_vif *vif,
unsigned int link_id, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
struct ath10k *ar = hw->priv;
@ -8919,7 +8920,7 @@ unlock:
static int
ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
struct ath10k *ar = hw->priv;
@ -8999,7 +9000,7 @@ err:
static void
ath10k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
struct ath10k *ar = hw->priv;

View File

@ -1401,7 +1401,8 @@ void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
if (!vif->bss_conf.color_change_active && !arvif->bcca_zero_sent)
return;
if (vif->bss_conf.color_change_active && ieee80211_beacon_cntdwn_is_complete(vif)) {
if (vif->bss_conf.color_change_active &&
ieee80211_beacon_cntdwn_is_complete(vif)) {
arvif->bcca_zero_sent = true;
ieee80211_color_change_finish(vif);
return;
@ -3292,7 +3293,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_PS &&
ar->ab->hw_params.supports_sta_ps) {
arvif->ps = vif->bss_conf.ps;
arvif->ps = vif->cfg.ps;
ret = ath11k_mac_config_ps(ar);
if (ret)
@ -4822,7 +4823,8 @@ exit:
}
static int ath11k_mac_op_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 ac,
struct ieee80211_vif *vif,
unsigned int link_id, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
struct ath11k *ar = hw->priv;
@ -7072,7 +7074,7 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
static int
ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
struct ath11k *ar = hw->priv;
@ -7162,7 +7164,7 @@ out:
static void
ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
struct ath11k *ar = hw->priv;

View File

@ -1982,7 +1982,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
/*
* Check if the previous beacon has gone out. If
* not, don't don't try to post another: skip this
* not, don't try to post another: skip this
* period and wait for the next. Missed beacons
* indicate a problem and should not occur. If we
* miss too many consecutive beacons reset the device.

View File

@ -410,7 +410,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
/* FIF_CONTROL doc says we should only pass on control frames for this
* station. This needs testing. I believe right now this
* enables *all* control frames, which is OK.. but
* but we should see if we can improve on granularity */
* we should see if we can improve on granularity */
if (*new_flags & FIF_CONTROL)
rfilt |= AR5K_RX_FILTER_CONTROL;
@ -572,7 +572,8 @@ ath5k_get_stats(struct ieee80211_hw *hw,
static int
ath5k_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
ath5k_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct ath5k_hw *ah = hw->priv;

View File

@ -92,7 +92,7 @@ struct bus_request {
* emode - This indicates the whether the command is to be executed in a
* blocking or non-blocking fashion (HIF_SYNCHRONOUS/
* HIF_ASYNCHRONOUS). The read/write data paths in HTC have been
* implemented using the asynchronous mode allowing the the bus
* implemented using the asynchronous mode allowing the bus
* driver to indicate the completion of operation through the
* registered callback routine. The requirement primarily comes
* from the contexts these operations get called from (a driver's

View File

@ -1185,7 +1185,7 @@ static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
* Wait for first 4 bytes to be in FIFO
* If CONSERVATIVE_BMI_READ is enabled, also wait for
* a BMI command credit, which indicates that the ENTIRE
* response is available in the the FIFO
* response is available in the FIFO
*
* CASE 3: length > 128
* Wait for the first 4 bytes to be in FIFO

View File

@ -698,7 +698,7 @@ enum auth_mode {
/*
* NB: these values are ordered carefully; there are lots of
* of implications in any reordering. In particular beware
* implications in any reordering. In particular beware
* that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY.
*/
#define ATH6KL_CIPHER_WEP 0

View File

@ -1369,7 +1369,8 @@ static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw,
}
static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct ath9k_htc_priv *priv = hw->priv;

View File

@ -1712,7 +1712,8 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
}
static int ath9k_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct ath_softc *sc = hw->priv;
@ -2596,7 +2597,7 @@ static void ath9k_change_chanctx(struct ieee80211_hw *hw,
static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *conf)
{
struct ath_softc *sc = hw->priv;
@ -2628,7 +2629,7 @@ static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *conf)
{
struct ath_softc *sc = hw->priv;

View File

@ -1365,7 +1365,8 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw,
}
static int carl9170_op_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *param)
{
struct ar9170 *ar = hw->priv;

View File

@ -48,7 +48,7 @@
* the MAC address to obtain the relevant bits and compare the result with
* (frame's BSSID & mask) to see if they match.
*
* Simple example: on your card you have have two BSSes you have created with
* Simple example: on your card you have two BSSes you have created with
* BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
* There is another BSSID-03 but you are not part of it. For simplicity's sake,
* assuming only 4 bits for a mac address and for BSSIDs you can then have:

View File

@ -4142,7 +4142,7 @@ struct wcn36xx_hal_dump_cmd_rsp_msg {
/* Length of the responce message */
u32 rsp_length;
/* FIXME: Currently considering the the responce will be less than
/* FIXME: Currently considering the responce will be less than
* 100bytes */
u8 rsp_buffer[DUMPCMD_RSP_BUFFER];
} __packed;

View File

@ -385,7 +385,7 @@ static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable)
list_for_each_entry(tmp, &wcn->vif_list, list) {
vif = wcn36xx_priv_to_vif(tmp);
if (enable && !wcn->sw_scan) {
if (vif->bss_conf.ps) /* ps allowed ? */
if (vif->cfg.ps) /* ps allowed ? */
wcn36xx_pmc_enter_bmps_state(wcn, vif);
} else {
wcn36xx_pmc_exit_bmps_state(wcn, vif);

View File

@ -1012,18 +1012,12 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
u16 cmdid;
int rc, rc1;
if (cmdlen < 0)
if (cmdlen < 0 || *ppos != 0)
return -EINVAL;
wmi = kmalloc(len, GFP_KERNEL);
if (!wmi)
return -ENOMEM;
rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
if (rc < 0) {
kfree(wmi);
return rc;
}
wmi = memdup_user(buf, len);
if (IS_ERR(wmi))
return PTR_ERR(wmi);
cmd = (cmdlen > 0) ? &wmi[1] : NULL;
cmdid = le16_to_cpu(wmi->command_id);

View File

@ -356,7 +356,7 @@ struct vring_rx_mac {
* bit 10 : cmd_dma_it:1 immediate interrupt
* bit 11..15 : reserved:5
* bit 16..29 : phy_info_length:14 It is valid when the PII is set.
* When the FFM bit is set bits 29-27 are used for for
* When the FFM bit is set bits 29-27 are used for
* Flex Filter Match. Matching Index to one of the L2
* EtherType Flex Filter
* bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field

View File

@ -3353,7 +3353,7 @@ static void atmel_management_frame(struct atmel_private *priv,
priv->beacons_this_sec++;
atmel_smooth_qual(priv);
if (priv->last_beacon_timestamp) {
/* Note truncate this to 32 bits - kernel can't divide a long long */
/* Note truncate this to 32 bits - kernel can't divide a long */
u32 beacon_delay = timestamp - priv->last_beacon_timestamp;
int beacons = beacon_delay / (beacon_interval * 1000);
if (beacons > 1)

View File

@ -3783,7 +3783,8 @@ static void b43_qos_init(struct b43_wldev *dev)
}
static int b43_op_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 _queue,
struct ieee80211_vif *vif,
unsigned int link_id, u16 _queue,
const struct ieee80211_tx_queue_params *params)
{
struct b43_wl *wl = hw_to_b43_wl(hw);

View File

@ -88,7 +88,7 @@ enum b43_txpwr_result {
* initialized here.
* Must not be NULL.
* @prepare_hardware: Prepare the PHY. This is called before b43_chip_init to
* do some early early PHY hardware init.
* do some early PHY hardware init.
* Can be NULL, if not required.
* @init: Initialize the PHY.
* Must not be NULL.

View File

@ -2505,7 +2505,8 @@ static void b43legacy_op_tx(struct ieee80211_hw *hw,
}
static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
return 0;

View File

@ -89,7 +89,7 @@ struct brcmf_bus_ops {
*
* @commonrings: commonrings which are always there.
* @flowrings: commonrings which are dynamically created and destroyed for data.
* @rx_dataoffset: if set then all rx data has this this offset.
* @rx_dataoffset: if set then all rx data has this offset.
* @max_rxbufpost: maximum number of buffers to post for rx.
* @max_flowrings: maximum number of tx flow rings supported.
* @max_submissionrings: maximum number of submission rings(h2d) supported.

View File

@ -1617,7 +1617,7 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
/* Do an SDIO read for the superframe. Configurable iovar to
* read directly into the chained packet, or allocate a large
* packet and and copy into the chain.
* packet and copy into the chain.
*/
sdio_claim_host(bus->sdiodev->func1);
errcode = brcmf_sdiod_recv_chain(bus->sdiodev,

View File

@ -787,7 +787,8 @@ static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw,
}
static int
brcms_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
brcms_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct brcms_info *wl = hw->priv;

View File

@ -3800,7 +3800,7 @@ static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
}
/*
* Suspend the the MAC and update the slot timing
* Suspend the MAC and update the slot timing
* for standard 11b/g (20us slots) or shortslot 11g (9us slots).
*/
static void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)

View File

@ -2584,7 +2584,7 @@ static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit)
* through a couple of memory mapped registers.
*
* The following is a simplified implementation for pulling data out of the
* the eeprom, along with some helper functions to find information in
* eeprom, along with some helper functions to find information in
* the per device private data's copy of the eeprom.
*
* NOTE: To better understand how these functions work (i.e what is a chip

View File

@ -6690,7 +6690,7 @@ il4965_pci_remove(struct pci_dev *pdev)
sysfs_remove_group(&pdev->dev.kobj, &il_attribute_group);
/* ieee80211_unregister_hw call wil cause il_mac_stop to
* to be called and il4965_down since we are removing the device
* be called and il4965_down since we are removing the device
* we need to set S_EXIT_PENDING bit.
*/
set_bit(S_EXIT_PENDING, &il->status);

View File

@ -4480,7 +4480,8 @@ il_clear_isr_stats(struct il_priv *il)
}
int
il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct il_priv *il = hw->priv;
@ -4816,7 +4817,7 @@ il_check_stuck_queue(struct il_priv *il, int cnt)
#define IL_WD_TICK(timeout) ((timeout) / 4)
/*
* Watchdog timer callback, we check each tx queue for stuck, if if hung
* Watchdog timer callback, we check each tx queue for stuck, if hung
* we reset the firmware. If everything is fine just rearm the timer.
*/
void

View File

@ -1683,7 +1683,8 @@ struct il_cfg {
***************************/
int il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u16 queue, const struct ieee80211_tx_queue_params *params);
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params);
int il_mac_tx_last_beacon(struct ieee80211_hw *hw);
void il_set_rxon_hwcrypto(struct il_priv *il, int hw_decrypt);

View File

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2018 - 2019 Intel Corporation
* Copyright (C) 2018 - 2019, 2022 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@ -1153,7 +1153,8 @@ static int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
}
static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);

View File

@ -2397,7 +2397,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id)
struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@ -2525,20 +2525,20 @@ out_unlock:
static int iwl_mvm_start_ap(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id)
struct ieee80211_bss_conf *link_conf)
{
return iwl_mvm_start_ap_ibss(hw, vif, link_id);
return iwl_mvm_start_ap_ibss(hw, vif, link_conf);
}
static int iwl_mvm_start_ibss(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
return iwl_mvm_start_ap_ibss(hw, vif, 0);
return iwl_mvm_start_ap_ibss(hw, vif, &vif->bss_conf);
}
static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id)
struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@ -2603,15 +2603,15 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
static void iwl_mvm_stop_ap(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id)
struct ieee80211_bss_conf *link_conf)
{
iwl_mvm_stop_ap_ibss(hw, vif, link_id);
iwl_mvm_stop_ap_ibss(hw, vif, link_conf);
}
static void iwl_mvm_stop_ibss(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
iwl_mvm_stop_ap_ibss(hw, vif, 0);
iwl_mvm_stop_ap_ibss(hw, vif, &vif->bss_conf);
}
static void
@ -3349,7 +3349,8 @@ static void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw,
}
static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 ac,
struct ieee80211_vif *vif,
unsigned int link_id, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@ -4263,7 +4264,7 @@ out:
}
static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@ -4337,7 +4338,7 @@ out:
static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

View File

@ -359,7 +359,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
if (!vif->bss_conf.ps || !mvmvif->pm_enabled)
if (!vif->cfg.ps || !mvmvif->pm_enabled)
return;
if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
@ -890,7 +890,7 @@ static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled ||
mvm->ps_disabled ||
!vif->bss_conf.ps ||
!vif->cfg.ps ||
iwl_mvm_vif_low_latency(mvmvif));
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0);

View File

@ -1861,7 +1861,7 @@ static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int index = rate->index;
bool cam = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&
!vif->bss_conf.ps);
!vif->cfg.ps);
IWL_DEBUG_RATE(mvm, "cam: %d sta_ps_disabled %d\n",
cam, sta_ps_disabled);

View File

@ -173,10 +173,8 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
* keeping a extra list for uploaded keys.
*/
priv->used_rxkeys = kcalloc(BITS_TO_LONGS(priv->rx_keycache_size),
sizeof(long),
GFP_KERNEL);
priv->used_rxkeys = bitmap_zalloc(priv->rx_keycache_size,
GFP_KERNEL);
if (!priv->used_rxkeys)
return -ENOMEM;
}

View File

@ -404,7 +404,8 @@ static void p54_configure_filter(struct ieee80211_hw *dev,
}
static int p54_conf_tx(struct ieee80211_hw *dev,
struct ieee80211_vif *vif, u16 queue,
struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct p54_common *priv = dev->priv;
@ -682,7 +683,7 @@ static void p54_flush(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
* queues have already been stopped and no new frames can sneak
* up from behind.
*/
while ((total = p54_flush_count(priv) && i--)) {
while ((total = p54_flush_count(priv)) && i--) {
/* waste time */
msleep(20);
}
@ -830,7 +831,7 @@ void p54_free_common(struct ieee80211_hw *dev)
kfree(priv->output_limit);
kfree(priv->curve_data);
kfree(priv->rssi_db);
kfree(priv->used_rxkeys);
bitmap_free(priv->used_rxkeys);
kfree(priv->survey);
priv->iq_autocal = NULL;
priv->output_limit = NULL;

View File

@ -164,7 +164,7 @@ static int p54spi_request_firmware(struct ieee80211_hw *dev)
ret = p54_parse_firmware(dev, priv->firmware);
if (ret) {
release_firmware(priv->firmware);
/* the firmware is released by the caller */
return ret;
}
@ -659,6 +659,7 @@ static int p54spi_probe(struct spi_device *spi)
return 0;
err_free_common:
release_firmware(priv->firmware);
free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
err_free_gpio_irq:
gpio_free(p54spi_gpio_irq);

View File

@ -228,6 +228,7 @@ static inline void hwsim_clear_magic(struct ieee80211_vif *vif)
struct hwsim_sta_priv {
u32 magic;
unsigned int last_link;
};
#define HWSIM_STA_MAGIC 0x6d537749
@ -687,7 +688,7 @@ struct mac80211_hwsim_data {
bool ps_poll_pending;
struct dentry *debugfs;
atomic64_t pending_cookie;
atomic_t pending_cookie;
struct sk_buff_head pending; /* packets pending */
/*
* Only radios in the same group can communicate together (the
@ -1198,10 +1199,27 @@ struct mac80211_hwsim_addr_match_data {
static void mac80211_hwsim_addr_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
int i;
struct mac80211_hwsim_addr_match_data *md = data;
if (memcmp(mac, md->addr, ETH_ALEN) == 0)
if (memcmp(mac, md->addr, ETH_ALEN) == 0) {
md->ret = true;
return;
}
/* Match the link address */
for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) {
struct ieee80211_bss_conf *conf;
conf = rcu_dereference(vif->link_conf[i]);
if (!conf)
continue;
if (memcmp(conf->addr, md->addr, ETH_ALEN) == 0) {
md->ret = true;
return;
}
}
}
static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
@ -1358,7 +1376,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
int i;
struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES];
struct hwsim_tx_rate_flag tx_attempts_flags[IEEE80211_TX_MAX_RATES];
u64 cookie;
uintptr_t cookie;
if (data->ps != PS_DISABLED)
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
@ -1427,7 +1445,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
goto nla_put_failure;
/* We create a cookie to identify this skb */
cookie = (u64)atomic64_inc_return(&data->pending_cookie);
cookie = atomic_inc_return(&data->pending_cookie);
info->rate_driver_data[0] = (void *)cookie;
if (nla_put_u64_64bit(skb, HWSIM_ATTR_COOKIE, cookie, HWSIM_ATTR_PAD))
goto nla_put_failure;
@ -1474,15 +1492,26 @@ static void mac80211_hwsim_tx_iter(void *_data, u8 *addr,
struct ieee80211_vif *vif)
{
struct tx_iter_data *data = _data;
int i;
if (!vif->bss_conf.chanctx_conf)
for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) {
struct ieee80211_bss_conf *conf;
struct ieee80211_chanctx_conf *chanctx;
conf = rcu_dereference(vif->link_conf[i]);
if (!conf)
continue;
chanctx = rcu_dereference(conf->chanctx_conf);
if (!chanctx)
continue;
if (!hwsim_chans_compat(data->channel, chanctx->def.chan))
continue;
data->receive = true;
return;
if (!hwsim_chans_compat(data->channel,
rcu_dereference(vif->bss_conf.chanctx_conf)->def.chan))
return;
data->receive = true;
}
}
static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb)
@ -1672,6 +1701,51 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
return ack;
}
static struct ieee80211_bss_conf *
mac80211_hwsim_select_tx_link(struct mac80211_hwsim_data *data,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_hdr *hdr,
struct ieee80211_link_sta **link_sta)
{
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
int i;
if (!vif->valid_links)
return &vif->bss_conf;
/* FIXME: handle multicast TX properly */
if (is_multicast_ether_addr(hdr->addr1) || WARN_ON_ONCE(!sta)) {
unsigned int first_link = ffs(vif->valid_links) - 1;
return rcu_dereference(vif->link_conf[first_link]);
}
if (WARN_ON_ONCE(!sta->valid_links))
return &vif->bss_conf;
for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) {
struct ieee80211_bss_conf *bss_conf;
unsigned int link_id;
/* round-robin the available link IDs */
link_id = (sp->last_link + i + 1) % ARRAY_SIZE(vif->link_conf);
*link_sta = rcu_dereference(sta->link[link_id]);
if (!*link_sta)
continue;
bss_conf = rcu_dereference(vif->link_conf[link_id]);
if (WARN_ON_ONCE(!bss_conf))
continue;
sp->last_link = link_id;
return bss_conf;
}
return NULL;
}
static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
@ -1697,9 +1771,45 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
} else if (txi->hw_queue == 4) {
channel = data->tmp_chan;
} else {
u8 link = u32_get_bits(IEEE80211_SKB_CB(skb)->control.flags,
IEEE80211_TX_CTRL_MLO_LINK);
struct ieee80211_vif *vif = txi->control.vif;
struct ieee80211_link_sta *link_sta = NULL;
struct ieee80211_sta *sta = control->sta;
struct ieee80211_bss_conf *bss_conf;
bss_conf = &txi->control.vif->bss_conf;
if (link != IEEE80211_LINK_UNSPECIFIED) {
bss_conf = rcu_dereference(txi->control.vif->link_conf[link]);
if (sta)
link_sta = rcu_dereference(sta->link[link]);
} else {
bss_conf = mac80211_hwsim_select_tx_link(data, vif, sta,
hdr, &link_sta);
}
if (WARN_ON(!bss_conf)) {
ieee80211_free_txskb(hw, skb);
return;
}
if (sta && sta->mlo) {
if (WARN_ON(!link_sta)) {
ieee80211_free_txskb(hw, skb);
return;
}
/* address translation to link addresses on TX */
ether_addr_copy(hdr->addr1, link_sta->addr);
ether_addr_copy(hdr->addr2, bss_conf->addr);
/* translate A3 only if it's the BSSID */
if (!ieee80211_has_tods(hdr->frame_control) &&
!ieee80211_has_fromds(hdr->frame_control)) {
if (ether_addr_equal(hdr->addr3, sta->addr))
ether_addr_copy(hdr->addr3, link_sta->addr);
else if (ether_addr_equal(hdr->addr3, vif->addr))
ether_addr_copy(hdr->addr3, bss_conf->addr);
}
/* no need to look at A4, if present it's SA */
}
chanctx_conf = rcu_dereference(bss_conf->chanctx_conf);
if (chanctx_conf) {
@ -1907,7 +2017,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
{
struct mac80211_hwsim_link_data *link_data = arg;
u32 link_id = link_data->link_id;
struct ieee80211_bss_conf *link_conf = vif->link_conf[link_id];
struct ieee80211_bss_conf *link_conf;
struct mac80211_hwsim_data *data =
container_of(link_data, struct mac80211_hwsim_data,
link_data[link_id]);
@ -1921,6 +2031,10 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
hwsim_check_magic(vif);
link_conf = rcu_dereference(vif->link_conf[link_id]);
if (!link_conf)
return;
if (vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_MESH_POINT &&
vif->type != NL80211_IFTYPE_ADHOC &&
@ -2145,12 +2259,12 @@ static void mac80211_hwsim_vif_info_changed(struct ieee80211_hw *hw,
static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 link_id,
struct ieee80211_bss_conf *info,
u64 changed)
{
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct mac80211_hwsim_data *data = hw->priv;
struct ieee80211_bss_conf *info = vif->link_conf[link_id];
unsigned int link_id = info->link_id;
struct mac80211_hwsim_link_data *link_data = &data->link_data[link_id];
hwsim_check_magic(vif);
@ -2231,35 +2345,56 @@ mac80211_hwsim_sta_rc_update(struct ieee80211_hw *hw,
{
struct mac80211_hwsim_data *data = hw->priv;
u32 bw = U32_MAX;
enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT;
int link_id;
switch (sta->deflink.bandwidth) {
rcu_read_lock();
for (link_id = 0;
link_id < ARRAY_SIZE(vif->link_conf);
link_id++) {
enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT;
struct ieee80211_bss_conf *vif_conf;
struct ieee80211_link_sta *link_sta;
link_sta = rcu_dereference(sta->link[link_id]);
if (!link_sta)
continue;
switch (link_sta->bandwidth) {
#define C(_bw) case IEEE80211_STA_RX_BW_##_bw: bw = _bw; break
C(20);
C(40);
C(80);
C(160);
C(320);
C(20);
C(40);
C(80);
C(160);
C(320);
#undef C
}
if (!data->use_chanctx) {
confbw = data->bw;
} else {
struct ieee80211_chanctx_conf *chanctx_conf;
vif_conf = rcu_dereference(vif->link_conf[link_id]);
if (WARN_ON(!vif_conf))
continue;
chanctx_conf = rcu_dereference(vif_conf->chanctx_conf);
if (!WARN_ON(!chanctx_conf))
confbw = chanctx_conf->def.width;
}
WARN(bw > hwsim_get_chanwidth(confbw),
"intf %pM [link=%d]: bad STA %pM bandwidth %d MHz (%d) > channel config %d MHz (%d)\n",
vif->addr, link_id, sta->addr, bw, sta->deflink.bandwidth,
hwsim_get_chanwidth(data->bw), data->bw);
}
rcu_read_unlock();
if (!data->use_chanctx) {
confbw = data->bw;
} else {
struct ieee80211_chanctx_conf *chanctx_conf;
rcu_read_lock();
chanctx_conf = rcu_dereference(vif->bss_conf.chanctx_conf);
if (!WARN_ON(!chanctx_conf))
confbw = chanctx_conf->def.width;
rcu_read_unlock();
}
WARN(bw > hwsim_get_chanwidth(confbw),
"intf %pM: bad STA %pM bandwidth %d MHz (%d) > channel config %d MHz (%d)\n",
vif->addr, sta->addr, bw, sta->deflink.bandwidth,
hwsim_get_chanwidth(data->bw), data->bw);
}
static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
@ -2283,6 +2418,21 @@ static int mac80211_hwsim_sta_remove(struct ieee80211_hw *hw,
return 0;
}
static int mac80211_hwsim_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
{
if (new_state == IEEE80211_STA_NOTEXIST)
return mac80211_hwsim_sta_remove(hw, vif, sta);
if (old_state == IEEE80211_STA_NOTEXIST)
return mac80211_hwsim_sta_add(hw, vif, sta);
return 0;
}
static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
@ -2309,10 +2459,10 @@ static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw,
return 0;
}
static int mac80211_hwsim_conf_tx(
struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
static int mac80211_hwsim_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
wiphy_dbg(hw->wiphy,
"%s (queue=%d txop=%d cw_min=%d cw_max=%d aifs=%d)\n",
@ -2763,7 +2913,7 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
hwsim_check_magic(vif);
@ -2774,7 +2924,7 @@ static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw,
static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
hwsim_check_magic(vif);
@ -2845,6 +2995,24 @@ static int mac80211_hwsim_change_vif_links(struct ieee80211_hw *hw,
u16 old_links, u16 new_links,
struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
{
unsigned long rem = old_links & ~new_links ?: BIT(0);
unsigned long add = new_links & ~old_links;
int i;
for_each_set_bit(i, &rem, IEEE80211_MLD_MAX_NUM_LINKS)
mac80211_hwsim_config_mac_nl(hw, old[i]->addr, false);
for_each_set_bit(i, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
struct ieee80211_bss_conf *link_conf;
/* FIXME: figure out how to get the locking here */
link_conf = rcu_dereference_protected(vif->link_conf[i], 1);
if (WARN_ON(!link_conf))
continue;
mac80211_hwsim_config_mac_nl(hw, link_conf->addr, true);
}
return 0;
}
@ -2868,8 +3036,6 @@ static int mac80211_hwsim_change_sta_links(struct ieee80211_hw *hw,
.vif_cfg_changed = mac80211_hwsim_vif_info_changed, \
.link_info_changed = mac80211_hwsim_link_info_changed, \
.tx_last_beacon = mac80211_hwsim_tx_last_beacon, \
.sta_add = mac80211_hwsim_sta_add, \
.sta_remove = mac80211_hwsim_sta_remove, \
.sta_notify = mac80211_hwsim_sta_notify, \
.sta_rc_update = mac80211_hwsim_sta_rc_update, \
.conf_tx = mac80211_hwsim_conf_tx, \
@ -2882,6 +3048,8 @@ static int mac80211_hwsim_change_sta_links(struct ieee80211_hw *hw,
.get_et_strings = mac80211_hwsim_get_et_strings,
#define HWSIM_NON_MLO_OPS \
.sta_add = mac80211_hwsim_sta_add, \
.sta_remove = mac80211_hwsim_sta_remove, \
.set_tim = mac80211_hwsim_set_tim, \
.get_tsf = mac80211_hwsim_get_tsf, \
.set_tsf = mac80211_hwsim_set_tsf,
@ -2916,6 +3084,7 @@ static const struct ieee80211_ops mac80211_hwsim_mlo_ops = {
.set_rts_threshold = mac80211_hwsim_set_rts_threshold,
.change_vif_links = mac80211_hwsim_change_vif_links,
.change_sta_links = mac80211_hwsim_change_sta_links,
.sta_state = mac80211_hwsim_sta_state,
};
struct hwsim_new_radio_params {
@ -3087,7 +3256,7 @@ static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = {
.has_eht = true,
.eht_cap_elem = {
.mac_cap_info[0] =
IEEE80211_EHT_MAC_CAP0_NSEP_PRIO_ACCESS |
IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1,
.phy_cap_info[0] =
@ -3240,7 +3409,7 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = {
.has_eht = true,
.eht_cap_elem = {
.mac_cap_info[0] =
IEEE80211_EHT_MAC_CAP0_NSEP_PRIO_ACCESS |
IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1,
.phy_cap_info[0] =
@ -3422,7 +3591,7 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = {
.has_eht = true,
.eht_cap_elem = {
.mac_cap_info[0] =
IEEE80211_EHT_MAC_CAP0_NSEP_PRIO_ACCESS |
IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1,
.phy_cap_info[0] =
@ -4207,10 +4376,10 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
/* look for the skb matching the cookie passed back from user */
spin_lock_irqsave(&data2->pending.lock, flags);
skb_queue_walk_safe(&data2->pending, skb, tmp) {
u64 skb_cookie;
uintptr_t skb_cookie;
txi = IEEE80211_SKB_CB(skb);
skb_cookie = (u64)(uintptr_t)txi->rate_driver_data[0];
skb_cookie = (uintptr_t)txi->rate_driver_data[0];
if (skb_cookie == ret_skb_cookie) {
__skb_unlink(skb, &data2->pending);
@ -4327,16 +4496,28 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
/* A frame is received from user space */
memset(&rx_status, 0, sizeof(rx_status));
if (info->attrs[HWSIM_ATTR_FREQ]) {
struct tx_iter_data iter_data = {};
/* throw away off-channel packets, but allow both the temporary
* ("hw" scan/remain-on-channel) and regular channel, since the
* internal datapath also allows this
* ("hw" scan/remain-on-channel), regular channels and links,
* since the internal datapath also allows this
*/
mutex_lock(&data2->mutex);
rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]);
if (rx_status.freq != channel->center_freq) {
mutex_unlock(&data2->mutex);
iter_data.channel = ieee80211_get_channel(data2->hw->wiphy,
rx_status.freq);
if (!iter_data.channel)
goto out;
mutex_lock(&data2->mutex);
if (!hwsim_chans_compat(iter_data.channel, channel)) {
ieee80211_iterate_active_interfaces_atomic(
data2->hw, IEEE80211_IFACE_ITER_NORMAL,
mac80211_hwsim_tx_iter, &iter_data);
if (!iter_data.receive) {
mutex_unlock(&data2->mutex);
goto out;
}
}
mutex_unlock(&data2->mutex);
} else {

View File

@ -1790,29 +1790,31 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
wmm_qos_info->qos_info = 0;
config_len += sizeof(struct mwifiex_ie_types_qos_info);
if (params->ht_capa) {
if (params->link_sta_params.ht_capa) {
ht_capab = (struct mwifiex_ie_types_htcap *)(pos +
config_len);
ht_capab->header.type =
cpu_to_le16(WLAN_EID_HT_CAPABILITY);
ht_capab->header.len =
cpu_to_le16(sizeof(struct ieee80211_ht_cap));
memcpy(&ht_capab->ht_cap, params->ht_capa,
memcpy(&ht_capab->ht_cap, params->link_sta_params.ht_capa,
sizeof(struct ieee80211_ht_cap));
config_len += sizeof(struct mwifiex_ie_types_htcap);
}
if (params->supported_rates && params->supported_rates_len) {
if (params->link_sta_params.supported_rates &&
params->link_sta_params.supported_rates_len) {
tlv_rates = (struct host_cmd_tlv_rates *)(pos +
config_len);
tlv_rates->header.type =
cpu_to_le16(WLAN_EID_SUPP_RATES);
tlv_rates->header.len =
cpu_to_le16(params->supported_rates_len);
memcpy(tlv_rates->rates, params->supported_rates,
params->supported_rates_len);
cpu_to_le16(params->link_sta_params.supported_rates_len);
memcpy(tlv_rates->rates,
params->link_sta_params.supported_rates,
params->link_sta_params.supported_rates_len);
config_len += sizeof(struct host_cmd_tlv_rates) +
params->supported_rates_len;
params->link_sta_params.supported_rates_len;
}
if (params->ext_capab && params->ext_capab_len) {
@ -1826,14 +1828,14 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
config_len += sizeof(struct mwifiex_ie_types_extcap) +
params->ext_capab_len;
}
if (params->vht_capa) {
if (params->link_sta_params.vht_capa) {
vht_capab = (struct mwifiex_ie_types_vhtcap *)(pos +
config_len);
vht_capab->header.type =
cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
vht_capab->header.len =
cpu_to_le16(sizeof(struct ieee80211_vht_cap));
memcpy(&vht_capab->vht_cap, params->vht_capa,
memcpy(&vht_capab->vht_cap, params->link_sta_params.vht_capa,
sizeof(struct ieee80211_vht_cap));
config_len += sizeof(struct mwifiex_ie_types_vhtcap);
}

View File

@ -5365,7 +5365,8 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw,
}
static int mwl8k_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mwl8k_priv *priv = hw->priv;
@ -6050,7 +6051,7 @@ static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image)
goto fail;
for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) {
rc = mwl8k_conf_tx(hw, NULL, i, &priv->wmm_params[i]);
rc = mwl8k_conf_tx(hw, NULL, 0, i, &priv->wmm_params[i]);
if (rc)
goto fail;
}

View File

@ -349,8 +349,8 @@ error:
static int
mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta)
enum mt76_txq_id qid, struct sk_buff *skb,
struct mt76_wcid *wcid, struct ieee80211_sta *sta)
{
struct ieee80211_tx_status status = {
.sta = sta,
@ -406,7 +406,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
DMA_TO_DEVICE);
ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info);
ret = dev->drv->tx_prepare_skb(dev, txwi, qid, wcid, sta, &tx_info);
dma_sync_single_for_device(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
DMA_TO_DEVICE);
if (ret < 0)
@ -791,10 +791,15 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
mt76_worker_disable(&dev->tx_worker);
netif_napi_del(&dev->tx_napi);
for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) {
mt76_dma_tx_cleanup(dev, dev->phy.q_tx[i], true);
if (dev->phy2)
mt76_dma_tx_cleanup(dev, dev->phy2->q_tx[i], true);
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
struct mt76_phy *phy = dev->phys[i];
int j;
if (!phy)
continue;
for (j = 0; j < ARRAY_SIZE(phy->q_tx); j++)
mt76_dma_tx_cleanup(dev, phy->q_tx[j], true);
}
for (i = 0; i < ARRAY_SIZE(dev->q_mcu); i++)

View File

@ -162,10 +162,13 @@ mt76_find_power_limits_node(struct mt76_dev *dev)
}
if (mt76_string_prop_find(country, dev->alpha2) ||
mt76_string_prop_find(regd, region_name))
mt76_string_prop_find(regd, region_name)) {
of_node_put(np);
return cur;
}
}
of_node_put(np);
return fallback;
}

View File

@ -178,6 +178,12 @@ static const struct cfg80211_sar_freq_ranges mt76_sar_freq_ranges[] = {
{ .start_freq = 5350, .end_freq = 5470, },
{ .start_freq = 5470, .end_freq = 5725, },
{ .start_freq = 5725, .end_freq = 5950, },
{ .start_freq = 5945, .end_freq = 6165, },
{ .start_freq = 6165, .end_freq = 6405, },
{ .start_freq = 6405, .end_freq = 6525, },
{ .start_freq = 6525, .end_freq = 6705, },
{ .start_freq = 6705, .end_freq = 6865, },
{ .start_freq = 6865, .end_freq = 7125, },
};
static const struct cfg80211_sar_capa mt76_sar_capa = {
@ -210,6 +216,7 @@ static int mt76_led_init(struct mt76_dev *dev)
if (!of_property_read_u32(np, "led-sources", &led_pin))
dev->led_pin = led_pin;
dev->led_al = of_property_read_bool(np, "led-active-low");
of_node_put(np);
}
return led_classdev_register(dev->dev, &dev->led_cdev);
@ -260,6 +267,8 @@ static void mt76_init_stream_cap(struct mt76_phy *phy,
}
vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
vht_cap->vht_mcs.tx_highest |=
cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
}
void mt76_set_stream_caps(struct mt76_phy *phy, bool vht)
@ -444,7 +453,7 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
struct mt76_phy *
mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
const struct ieee80211_ops *ops)
const struct ieee80211_ops *ops, u8 band_idx)
{
struct ieee80211_hw *hw;
unsigned int phy_size;
@ -459,6 +468,7 @@ mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
phy->dev = dev;
phy->hw = hw;
phy->priv = hw->priv + phy_size;
phy->band_idx = band_idx;
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
hw->wiphy->interface_modes =
@ -511,7 +521,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht,
if (ret)
return ret;
phy->dev->phy2 = phy;
phy->dev->phys[phy->band_idx] = phy;
return 0;
}
@ -523,7 +533,7 @@ void mt76_unregister_phy(struct mt76_phy *phy)
mt76_tx_status_check(dev, true);
ieee80211_unregister_hw(phy->hw);
dev->phy2 = NULL;
dev->phys[phy->band_idx] = NULL;
}
EXPORT_SYMBOL_GPL(mt76_unregister_phy);
@ -550,6 +560,8 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
phy = &dev->phy;
phy->dev = dev;
phy->hw = hw;
phy->band_idx = MT_BAND0;
dev->phys[phy->band_idx] = phy;
spin_lock_init(&dev->rx_lock);
spin_lock_init(&dev->lock);
@ -731,7 +743,7 @@ static void mt76_rx_release_burst(struct mt76_phy *phy, enum mt76_rxq_id q,
void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_phy *phy = mt76_dev_phy(dev, status->ext_phy);
struct mt76_phy *phy = mt76_dev_phy(dev, status->phy_idx);
if (!test_bit(MT76_STATE_RUNNING, &phy->state)) {
dev_kfree_skb(skb);
@ -1007,10 +1019,10 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
sizeof(mstat.chain_signal));
*sta = wcid_to_sta(mstat.wcid);
*hw = mt76_phy_hw(dev, mstat.ext_phy);
*hw = mt76_phy_hw(dev, mstat.phy_idx);
}
static int
static void
mt76_check_ccmp_pn(struct sk_buff *skb)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
@ -1020,10 +1032,13 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
int ret;
if (!(status->flag & RX_FLAG_DECRYPTED))
return 0;
return;
if (status->flag & RX_FLAG_ONLY_MONITOR)
return;
if (!wcid || !wcid->rx_check_pn)
return 0;
return;
security_idx = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
if (status->flag & RX_FLAG_8023)
@ -1037,7 +1052,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
*/
if (ieee80211_is_frag(hdr) &&
!ieee80211_is_first_frag(hdr->frame_control))
return 0;
return;
}
/* IEEE 802.11-2020, 12.5.3.4.4 "PN and replay detection" c):
@ -1054,15 +1069,15 @@ skip_hdr_check:
BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0]));
ret = memcmp(status->iv, wcid->rx_key_pn[security_idx],
sizeof(status->iv));
if (ret <= 0)
return -EINVAL; /* replay */
if (ret <= 0) {
status->flag |= RX_FLAG_ONLY_MONITOR;
return;
}
memcpy(wcid->rx_key_pn[security_idx], status->iv, sizeof(status->iv));
if (status->flag & RX_FLAG_IV_STRIPPED)
status->flag |= RX_FLAG_PN_VALIDATED;
return 0;
}
static void
@ -1167,7 +1182,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
bool ps;
hw = mt76_phy_hw(dev, status->ext_phy);
hw = mt76_phy_hw(dev, status->phy_idx);
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid &&
!(status->flag & RX_FLAG_8023)) {
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
@ -1235,11 +1250,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
while ((skb = __skb_dequeue(frames)) != NULL) {
struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
if (mt76_check_ccmp_pn(skb)) {
dev_kfree_skb(skb);
continue;
}
mt76_check_ccmp_pn(skb);
skb_shinfo(skb)->frag_list = NULL;
mt76_rx_convert(dev, skb, &hw, &sta);
ieee80211_rx_list(hw, sta, skb, &list);
@ -1285,10 +1296,11 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
EXPORT_SYMBOL_GPL(mt76_rx_poll_complete);
static int
mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool ext_phy)
mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
struct mt76_dev *dev = phy->dev;
int ret;
int i;
@ -1309,9 +1321,9 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
}
ewma_signal_init(&wcid->rssi);
if (ext_phy)
if (phy->band_idx == MT_BAND1)
mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx);
wcid->ext_phy = ext_phy;
wcid->phy_idx = phy->band_idx;
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
mt76_packet_id_init(wcid);
@ -1356,11 +1368,10 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
{
struct mt76_phy *phy = hw->priv;
struct mt76_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE)
return mt76_sta_add(dev, vif, sta, ext_phy);
return mt76_sta_add(phy, vif, sta);
if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&

View File

@ -7,17 +7,19 @@
struct sk_buff *
__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
int data_len, gfp_t gfp)
int len, int data_len, gfp_t gfp)
{
const struct mt76_mcu_ops *ops = dev->mcu_ops;
int length = ops->headroom + data_len + ops->tailroom;
struct sk_buff *skb;
skb = alloc_skb(length, gfp);
len = max_t(int, len, data_len);
len = ops->headroom + len + ops->tailroom;
skb = alloc_skb(len, gfp);
if (!skb)
return NULL;
memset(skb->head, 0, length);
memset(skb->head, 0, len);
skb_reserve(skb, ops->headroom);
if (data && data_len)

View File

@ -99,12 +99,21 @@ enum mt76_rxq_id {
MT_RXQ_MAIN,
MT_RXQ_MCU,
MT_RXQ_MCU_WA,
MT_RXQ_EXT,
MT_RXQ_EXT_WA,
MT_RXQ_BAND1,
MT_RXQ_BAND1_WA,
MT_RXQ_MAIN_WA,
MT_RXQ_BAND2,
MT_RXQ_BAND2_WA,
__MT_RXQ_MAX
};
enum mt76_band_id {
MT_BAND0,
MT_BAND1,
MT_BAND2,
__MT_MAX_BAND
};
enum mt76_cipher_type {
MT_CIPHER_NONE,
MT_CIPHER_WEP40,
@ -185,7 +194,6 @@ struct mt76_queue {
u8 buf_offset;
u8 hw_idx;
u8 qid;
u8 flags;
u32 wed_regs;
@ -223,8 +231,8 @@ struct mt76_queue_ops {
u32 ring_base);
int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta);
enum mt76_txq_id qid, struct sk_buff *skb,
struct mt76_wcid *wcid, struct ieee80211_sta *sta);
int (*tx_queue_skb_raw)(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, u32 tx_info);
@ -254,7 +262,7 @@ enum mt76_wcid_flags {
#define MT76_N_WCIDS 544
/* stored in ieee80211_tx_info::hw_queue */
#define MT_TX_HW_QUEUE_EXT_PHY BIT(3)
#define MT_TX_HW_QUEUE_PHY GENMASK(3, 2)
DECLARE_EWMA(signal, 10, 8);
@ -279,8 +287,8 @@ struct mt76_wcid {
u8 hw_key_idx2;
u8 sta:1;
u8 ext_phy:1;
u8 amsdu:1;
u8 phy_idx:2;
u8 rx_check_pn;
u8 rx_key_pn[IEEE80211_NUM_TIDS + 1][6];
@ -573,7 +581,7 @@ struct mt76_rx_status {
u8 iv[6];
u8 ext_phy:1;
u8 phy_idx:2;
u8 aggr:1;
u8 qos_ctl;
u16 seqno;
@ -660,6 +668,7 @@ struct mt76_phy {
void *priv;
unsigned long state;
u8 band_idx;
struct mt76_queue *q_tx[__MT_TXQ_MAX];
@ -699,8 +708,7 @@ struct mt76_phy {
struct mt76_dev {
struct mt76_phy phy; /* must be first */
struct mt76_phy *phy2;
struct mt76_phy *phys[__MT_MAX_BAND];
struct ieee80211_hw *hw;
@ -885,16 +893,6 @@ extern struct ieee80211_rate mt76_rates[12];
#define mt76_hw(dev) (dev)->mphy.hw
static inline struct ieee80211_hw *
mt76_wcid_hw(struct mt76_dev *dev, u16 wcid)
{
if (wcid <= MT76_N_WCIDS &&
mt76_wcid_mask_test(dev->wcid_phy_mask, wcid))
return dev->phy2->hw;
return dev->phy.hw;
}
bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
int timeout);
@ -945,7 +943,8 @@ void mt76_free_device(struct mt76_dev *dev);
void mt76_unregister_phy(struct mt76_phy *phy);
struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
const struct ieee80211_ops *ops);
const struct ieee80211_ops *ops,
u8 band_idx);
int mt76_register_phy(struct mt76_phy *phy, bool vht,
struct ieee80211_rate *rates, int n_rates);
@ -977,7 +976,6 @@ static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx,
if (IS_ERR(q))
return PTR_ERR(q);
q->qid = qid;
phy->q_tx[qid] = q;
return 0;
@ -992,24 +990,25 @@ static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx,
if (IS_ERR(q))
return PTR_ERR(q);
q->qid = __MT_TXQ_MAX + qid;
dev->q_mcu[qid] = q;
return 0;
}
static inline struct mt76_phy *
mt76_dev_phy(struct mt76_dev *dev, bool phy_ext)
mt76_dev_phy(struct mt76_dev *dev, u8 phy_idx)
{
if (phy_ext && dev->phy2)
return dev->phy2;
if ((phy_idx == MT_BAND1 && dev->phys[phy_idx]) ||
(phy_idx == MT_BAND2 && dev->phys[phy_idx]))
return dev->phys[phy_idx];
return &dev->phy;
}
static inline struct ieee80211_hw *
mt76_phy_hw(struct mt76_dev *dev, bool phy_ext)
mt76_phy_hw(struct mt76_dev *dev, u8 phy_idx)
{
return mt76_dev_phy(dev, phy_ext)->hw;
return mt76_dev_phy(dev, phy_idx)->hw;
}
static inline u8 *
@ -1120,13 +1119,17 @@ static inline bool mt76_is_testmode_skb(struct mt76_dev *dev,
struct ieee80211_hw **hw)
{
#ifdef CONFIG_NL80211_TESTMODE
if (skb == dev->phy.test.tx_skb)
*hw = dev->phy.hw;
else if (dev->phy2 && skb == dev->phy2->test.tx_skb)
*hw = dev->phy2->hw;
else
return false;
return true;
int i;
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
struct mt76_phy *phy = dev->phys[i];
if (phy && skb == phy->test.tx_skb) {
*hw = dev->phys[i]->hw;
return true;
}
}
return false;
#else
return false;
#endif
@ -1242,12 +1245,10 @@ static inline struct ieee80211_hw *
mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hw *hw = dev->phy.hw;
u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
struct ieee80211_hw *hw = mt76_phy_hw(dev, phy_idx);
if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->phy2)
hw = dev->phy2->hw;
info->hw_queue &= ~MT_TX_HW_QUEUE_EXT_PHY;
info->hw_queue &= ~MT_TX_HW_QUEUE_PHY;
return hw;
}
@ -1346,12 +1347,12 @@ int mt76s_rd_rp(struct mt76_dev *dev, u32 base,
struct sk_buff *
__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
int data_len, gfp_t gfp);
int len, int data_len, gfp_t gfp);
static inline struct sk_buff *
mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
int data_len)
{
return __mt76_mcu_msg_alloc(dev, data, data_len, GFP_KERNEL);
return __mt76_mcu_msg_alloc(dev, data, data_len, data_len, GFP_KERNEL);
}
void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb);

View File

@ -24,8 +24,8 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
if (!skb)
return;
mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON], skb,
&mvif->sta.wcid, NULL);
mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],
MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);
spin_lock_bh(&dev->ps_lock);
mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
@ -123,7 +123,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
struct ieee80211_vif *vif = info->control.vif;
struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
mt76_tx_queue_skb(dev, q, skb, &mvif->sta.wcid, NULL);
mt76_tx_queue_skb(dev, q, MT_TXQ_CAB, skb, &mvif->sta.wcid, NULL);
}
mt76_queue_kick(dev, q);
spin_unlock(&q->lock);

View File

@ -527,7 +527,8 @@ mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
static int
mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mt7603_dev *dev = hw->priv;

View File

@ -44,7 +44,7 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
static int
mt7615_init_tx_queues(struct mt7615_dev *dev)
{
int ret, i;
int ret;
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7615_TXQ_FWDL,
MT7615_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);
@ -54,14 +54,11 @@ mt7615_init_tx_queues(struct mt7615_dev *dev)
if (!is_mt7615(&dev->mt76))
return mt7622_init_tx_queues_multi(dev);
ret = mt76_init_tx_queue(&dev->mphy, 0, 0, MT7615_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
ret = mt76_connac_init_tx_queues(&dev->mphy, 0, MT7615_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
if (ret)
return ret;
for (i = 1; i <= MT_TXQ_PSD ; i++)
dev->mphy.q_tx[i] = dev->mphy.q_tx[0];
return mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7615_TXQ_MCU,
MT7615_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
}

View File

@ -401,6 +401,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
if (is_mt7615(&phy->dev->mt76))
hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM;
@ -458,7 +459,7 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
return 0;
mt7615_cap_dbdc_enable(dev);
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops);
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops, MT_BAND1);
if (!mphy)
return -ENOMEM;
@ -508,7 +509,7 @@ EXPORT_SYMBOL_GPL(mt7615_register_ext_phy);
void mt7615_unregister_ext_phy(struct mt7615_dev *dev)
{
struct mt7615_phy *phy = mt7615_ext_phy(dev);
struct mt76_phy *mphy = dev->mt76.phy2;
struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];
if (!phy)
return;

View File

@ -109,6 +109,7 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev,
void mt7615_mac_reset_counters(struct mt7615_dev *dev)
{
struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
int i;
for (i = 0; i < 4; i++) {
@ -118,8 +119,8 @@ void mt7615_mac_reset_counters(struct mt7615_dev *dev)
memset(dev->mt76.aggr_stats, 0, sizeof(dev->mt76.aggr_stats));
dev->mt76.phy.survey_time = ktime_get_boottime();
if (dev->mt76.phy2)
dev->mt76.phy2->survey_time = ktime_get_boottime();
if (mphy_ext)
mphy_ext->survey_time = ktime_get_boottime();
/* reset airtime counters */
mt76_rr(dev, MT_MIB_SDR9(0));
@ -336,9 +337,9 @@ static int mt7615_mac_fill_rx(struct mt7615_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 mt7615_phy *phy = &dev->phy;
struct mt7615_phy *phy2 = dev->mt76.phy2 ? dev->mt76.phy2->priv : NULL;
struct ieee80211_supported_band *sband;
struct ieee80211_hdr *hdr;
struct mt7615_phy *phy2;
__le32 *rxd = (__le32 *)skb->data;
u32 rxd0 = le32_to_cpu(rxd[0]);
u32 rxd1 = le32_to_cpu(rxd[1]);
@ -355,6 +356,8 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
memset(status, 0, sizeof(*status));
chfreq = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1);
phy2 = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL;
if (!phy2)
phy_idx = 0;
else if (phy2->chfreq == phy->chfreq)
@ -498,9 +501,9 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
}
if (phy_idx == 1 && phy2) {
mphy = dev->mt76.phy2;
mphy = dev->mt76.phys[MT_BAND1];
phy = phy2;
status->ext_phy = true;
status->phy_idx = phy_idx;
}
if (!mt7615_firmware_offload(dev) && chfreq != phy->chfreq)
@ -717,13 +720,14 @@ mt7615_mac_tx_rate_val(struct mt7615_dev *dev,
int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta, int pid,
struct ieee80211_key_conf *key, bool beacon)
struct ieee80211_key_conf *key,
enum mt76_txq_id qid, bool beacon)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *rate = &info->control.rates[0];
bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY;
u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
bool multicast = is_multicast_ether_addr(hdr->addr1);
struct ieee80211_vif *vif = info->control.vif;
bool is_mmio = mt76_is_mmio(&dev->mt76);
@ -746,18 +750,18 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
tx_count = msta->rate_count;
}
if (ext_phy && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (phy_idx && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
if (beacon) {
p_fmt = MT_TX_TYPE_FW;
q_idx = ext_phy ? MT_LMAC_BCN1 : MT_LMAC_BCN0;
} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
q_idx = phy_idx ? MT_LMAC_BCN1 : MT_LMAC_BCN0;
} else if (qid >= MT_TXQ_PSD) {
p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
q_idx = ext_phy ? MT_LMAC_ALTX1 : MT_LMAC_ALTX0;
q_idx = phy_idx ? MT_LMAC_ALTX1 : MT_LMAC_ALTX0;
} else {
p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
q_idx = wmm_idx * MT7615_MAX_WMM_SETS +
@ -876,60 +880,6 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
}
EXPORT_SYMBOL_GPL(mt7615_mac_write_txwi);
static void
mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp)
{
int i;
for (i = 0; i < txp->nbuf; i++)
dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
}
static void
mt7615_txp_skb_unmap_hw(struct mt76_dev *dev, struct mt7615_hw_txp *txp)
{
u32 last_mask;
int i;
last_mask = is_mt7663(dev) ? MT_TXD_LEN_LAST : MT_TXD_LEN_MSDU_LAST;
for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) {
struct mt7615_txp_ptr *ptr = &txp->ptr[i];
bool last;
u16 len;
len = le16_to_cpu(ptr->len0);
last = len & last_mask;
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 & last_mask;
len &= MT_TXD_LEN_MASK;
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len,
DMA_TO_DEVICE);
if (last)
break;
}
}
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *t)
{
struct mt7615_txp_common *txp;
txp = mt7615_txwi_to_txp(dev, t);
if (is_mt7615(dev))
mt7615_txp_skb_unmap_fw(dev, &txp->fw);
else
mt7615_txp_skb_unmap_hw(dev, &txp->hw);
}
EXPORT_SYMBOL_GPL(mt7615_txp_skb_unmap);
bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask)
{
mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
@ -1439,8 +1389,8 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta,
if (sta->rate_probe) {
struct mt7615_phy *phy = &dev->phy;
if (sta->wcid.ext_phy && dev->mt76.phy2)
phy = dev->mt76.phy2->priv;
if (sta->wcid.phy_idx && dev->mt76.phys[MT_BAND1])
phy = dev->mt76.phys[MT_BAND1]->priv;
mt7615_mac_set_rates(phy, sta, NULL, sta->rates);
}
@ -1482,8 +1432,8 @@ out:
fallthrough;
case MT_PHY_TYPE_OFDM:
mphy = &dev->mphy;
if (sta->wcid.ext_phy && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (sta->wcid.phy_idx && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
sband = &mphy->sband_5g.sband;
@ -1590,8 +1540,8 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
if (wcidx >= MT7615_WTBL_STA || !sta)
goto out;
if (wcid->ext_phy && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (wcid->phy_idx && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
if (mt7615_fill_txs(dev, msta, &info, txs_data))
ieee80211_tx_status_noskb(mphy->hw, sta, &info);
@ -1608,7 +1558,7 @@ mt7615_txwi_free(struct mt7615_dev *dev, struct mt76_txwi_cache *txwi)
u32 val;
u8 wcid;
mt7615_txp_skb_unmap(mdev, txwi);
mt76_connac_txp_skb_unmap(mdev, txwi);
if (!txwi->skb)
goto out;
@ -1638,7 +1588,8 @@ mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token)
static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)
{
struct mt7615_tx_free *free = (struct mt7615_tx_free *)data;
struct mt76_connac_tx_free *free = data;
void *tx_token = data + sizeof(*free);
void *end = data + len;
u8 i, count;
@ -1652,7 +1603,7 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)
count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_ID_CNT);
if (is_mt7615(&dev->mt76)) {
__le16 *token = &free->token[0];
__le16 *token = tx_token;
if (WARN_ON_ONCE((void *)&token[count] > end))
return;
@ -1660,7 +1611,7 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)
for (i = 0; i < count; i++)
mt7615_mac_tx_free_token(dev, le16_to_cpu(token[i]));
} else {
__le32 *token = (__le32 *)&free->token[0];
__le32 *token = tx_token;
if (WARN_ON_ONCE((void *)&token[count] > end))
return;
@ -2007,6 +1958,7 @@ mt7615_phy_update_channel(struct mt76_phy *mphy, int idx)
static void mt7615_update_survey(struct mt7615_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
struct mt76_phy *mphy_ext = mdev->phys[MT_BAND1];
ktime_t cur_time;
/* MT7615 can only update both phys simultaneously
@ -2014,14 +1966,14 @@ static void mt7615_update_survey(struct mt7615_dev *dev)
*/
mt7615_phy_update_channel(&mdev->phy, 0);
if (mdev->phy2)
mt7615_phy_update_channel(mdev->phy2, 1);
if (mphy_ext)
mt7615_phy_update_channel(mphy_ext, 1);
cur_time = ktime_get_boottime();
mt76_update_survey_active_time(&mdev->phy, cur_time);
if (mdev->phy2)
mt76_update_survey_active_time(mdev->phy2, cur_time);
if (mphy_ext)
mt76_update_survey_active_time(mphy_ext, cur_time);
/* reset obss airtime */
mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR);
@ -2094,8 +2046,10 @@ void mt7615_pm_wake_work(struct work_struct *work)
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt76_worker_schedule(&mdev->sdio.txrx_worker);
} else {
local_bh_disable();
mt76_for_each_q_rx(mdev, i)
napi_schedule(&mdev->napi[i]);
local_bh_enable();
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt76_queue_tx_cleanup(dev, mdev->q_mcu[MT_MCUQ_WM],
false);
@ -2282,6 +2236,7 @@ mt7615_dfs_init_radar_specs(struct mt7615_phy *phy)
int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy)
{
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
struct mt7615_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
enum mt76_dfs_state dfs_state, prev_state;
@ -2292,13 +2247,13 @@ int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy)
prev_state = phy->mt76->dfs_state;
dfs_state = mt76_phy_dfs_state(phy->mt76);
if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
dfs_state < MT_DFS_STATE_CAC)
dfs_state = MT_DFS_STATE_ACTIVE;
if (prev_state == dfs_state)
return 0;
if (prev_state == MT_DFS_STATE_UNKNOWN)
mt7615_dfs_stop_radar_detector(phy);
if (dfs_state == MT_DFS_STATE_DISABLED)
goto stop;

View File

@ -165,12 +165,6 @@ enum tx_phy_bandwidth {
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
#define MT_CT_INFO_HSR2_TX BIT(4)
#define MT_TXD_SIZE (8 * 4)
#define MT_USB_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
#define MT_USB_HDR_SIZE 4
#define MT_USB_TAIL_SIZE 4
#define MT_TXD0_P_IDX BIT(31)
#define MT_TXD0_Q_IDX GENMASK(30, 26)
#define MT_TXD0_UDP_TCP_SUM BIT(24)
@ -250,56 +244,6 @@ enum tx_phy_bandwidth {
#define MT_TX_RATE_MODE GENMASK(8, 6)
#define MT_TX_RATE_IDX GENMASK(5, 0)
#define MT_TXP_MAX_BUF_NUM 6
#define MT_HW_TXP_MAX_MSDU_NUM 4
#define MT_HW_TXP_MAX_BUF_NUM 4
#define MT_MSDU_ID_VALID BIT(15)
#define MT_TXD_LEN_MASK GENMASK(11, 0)
#define MT_TXD_LEN_MSDU_LAST BIT(14)
#define MT_TXD_LEN_AMSDU_LAST BIT(15)
/* mt7663 */
#define MT_TXD_LEN_LAST BIT(15)
struct mt7615_txp_ptr {
__le32 buf0;
__le16 len0;
__le16 len1;
__le32 buf1;
} __packed __aligned(4);
struct mt7615_hw_txp {
__le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM];
struct mt7615_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2];
} __packed __aligned(4);
struct mt7615_fw_txp {
__le16 flags;
__le16 token;
u8 bss_idx;
u8 rept_wds_wcid;
u8 rsv;
u8 nbuf;
__le32 buf[MT_TXP_MAX_BUF_NUM];
__le16 len[MT_TXP_MAX_BUF_NUM];
} __packed __aligned(4);
struct mt7615_txp_common {
union {
struct mt7615_fw_txp fw;
struct mt7615_hw_txp hw;
};
};
struct mt7615_tx_free {
__le16 rx_byte_cnt;
__le16 ctrl;
u8 txd_cnt;
u8 rsv[3];
__le16 token[];
} __packed __aligned(4);
#define MT_TX_FREE_MSDU_ID_CNT GENMASK(6, 0)
#define MT_TXS0_PID GENMASK(31, 24)
@ -385,19 +329,6 @@ struct mt7615_dfs_radar_spec {
struct mt7615_dfs_pattern radar_pattern[16];
};
static inline struct mt7615_txp_common *
mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
{
u8 *txwi;
if (!t)
return NULL;
txwi = mt76_get_txwi_ptr(dev, t);
return (struct mt7615_txp_common *)(txwi + MT_TXD_SIZE);
}
static inline u32 mt7615_mac_wtbl_addr(struct mt7615_dev *dev, int wcid)
{
return MT_WTBL_BASE(dev) + wcid * MT_WTBL_ENTRY_SIZE;

View File

@ -224,7 +224,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
mvif->sta.wcid.hw_key_idx = -1;
mt76_packet_id_init(&mvif->sta.wcid);
@ -282,26 +282,6 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
}
static void mt7615_init_dfs_state(struct mt7615_phy *phy)
{
struct mt76_phy *mphy = phy->mt76;
struct ieee80211_hw *hw = mphy->hw;
struct cfg80211_chan_def *chandef = &hw->conf.chandef;
if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
return;
if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
!(mphy->chandef.chan->flags & IEEE80211_CHAN_RADAR))
return;
if (mphy->chandef.chan->center_freq == chandef->chan->center_freq &&
mphy->chandef.width == chandef->width)
return;
phy->dfs_state = -1;
}
int mt7615_set_channel(struct mt7615_phy *phy)
{
struct mt7615_dev *dev = phy->dev;
@ -314,7 +294,6 @@ int mt7615_set_channel(struct mt7615_phy *phy)
set_bit(MT76_RESET, &phy->mt76->state);
mt7615_init_dfs_state(phy);
mt76_set_channel(phy->mt76);
if (is_mt7615(&dev->mt76) && dev->flash_eeprom) {
@ -494,7 +473,8 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
}
static int
mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
@ -650,7 +630,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
msta->wcid.ext_phy = mvif->mt76.band_idx;
msta->wcid.phy_idx = mvif->mt76.band_idx;
phy = mvif->mt76.band_idx ? mt7615_ext_phy(dev) : &dev->phy;
err = mt76_connac_pm_wake(phy->mt76, &dev->pm);

View File

@ -40,18 +40,6 @@ struct mt7615_fw_trailer {
#define FW_START_DLYCAL BIT(1)
#define FW_START_WORKING_PDA_CR4 BIT(2)
struct mt7663_fw_trailer {
u8 chip_id;
u8 eco_code;
u8 n_region;
u8 format_ver;
u8 format_flag;
u8 reserv[2];
char fw_ver[10];
char build_date[15];
__le32 crc;
} __packed;
struct mt7663_fw_buf {
__le32 crc;
__le32 d_img_size;
@ -350,10 +338,11 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev)
}
mt7622_trigger_hif_int(dev, false);
pm->stats.last_doze_event = jiffies;
pm->stats.awake_time += pm->stats.last_doze_event -
pm->stats.last_wake_event;
if (!err) {
pm->stats.last_doze_event = jiffies;
pm->stats.awake_time += pm->stats.last_doze_event -
pm->stats.last_wake_event;
}
out:
mutex_unlock(&pm->mutex);
@ -380,7 +369,7 @@ mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb)
return;
if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx))
mphy = dev->mt76.phy2;
mphy = dev->mt76.phys[MT_BAND1];
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
@ -399,8 +388,11 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)
!r->constant_prf_detected && !r->staggered_prf_detected)
return;
if (r->band_idx && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (r->band_idx && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)
return;
ieee80211_radar_detected(mphy->hw);
dev->hw_pattern++;
@ -456,8 +448,8 @@ mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb)
struct mt7615_phy *phy;
struct mt76_phy *mphy;
if (*seq_num & BIT(7) && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (*seq_num & BIT(7) && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
else
mphy = &dev->mt76.phy;
@ -482,8 +474,8 @@ mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb)
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
event = (struct mt7615_roc_tlv *)skb->data;
if (event->dbdc_band && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (event->dbdc_band && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
else
mphy = &dev->mt76.phy;
@ -507,8 +499,8 @@ mt7615_mcu_beacon_loss_event(struct mt7615_dev *dev, struct sk_buff *skb)
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
event = (struct mt76_connac_beacon_loss_event *)skb->data;
if (band_idx && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (band_idx && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
else
mphy = &dev->mt76.phy;
@ -528,8 +520,8 @@ mt7615_mcu_bss_event(struct mt7615_dev *dev, struct sk_buff *skb)
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
event = (struct mt76_connac_mcu_bss_event *)skb->data;
if (band_idx && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (band_idx && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
else
mphy = &dev->mt76.phy;
@ -716,13 +708,11 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,
return -EINVAL;
}
if (mvif->mt76.band_idx) {
info = IEEE80211_SKB_CB(skb);
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
}
info = IEEE80211_SKB_CB(skb);
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mvif->mt76.band_idx);
mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL,
0, NULL, true);
0, NULL, 0, true);
memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len);
req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
@ -855,6 +845,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
struct mt7615_dev *dev = phy->dev;
struct wtbl_req_hdr *wtbl_hdr;
struct mt7615_sta *msta;
bool new_entry = true;
int cmd, err;
msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta;
@ -864,7 +855,13 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
if (IS_ERR(sskb))
return PTR_ERR(sskb);
mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, true);
if (!sta) {
if (mvif->sta_added)
new_entry = false;
else
mvif->sta_added = true;
}
mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, new_entry);
if (enable && sta)
mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0,
MT76_STA_INFO_STATE_ASSOC);
@ -1087,7 +1084,7 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
}
mt7615_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb,
wcid, NULL, 0, NULL, true);
wcid, NULL, 0, NULL, 0, true);
memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);
req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
@ -1518,7 +1515,7 @@ static int mt7615_mcu_cal_cache_apply(struct mt7615_dev *dev)
static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)
{
u32 offset = 0, override_addr = 0, flag = FW_START_DLYCAL;
const struct mt7663_fw_trailer *hdr;
const struct mt76_connac2_fw_trailer *hdr;
const struct mt7663_fw_buf *buf;
const struct firmware *fw;
const u8 *base_addr;
@ -1534,9 +1531,7 @@ static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)
goto out;
}
hdr = (const struct mt7663_fw_trailer *)(fw->data + fw->size -
FW_V3_COMMON_TAILER_SIZE);
hdr = (const void *)(fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE);
dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
dev_info(dev->mt76.dev, "Region number: 0x%x\n", hdr->n_region);
@ -2333,7 +2328,7 @@ int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy)
.bw = mt7615_mcu_chan_bw(chandef),
.band = chandef->center_freq1 > 4000,
.dbdc_en = !!dev->mt76.phy2,
.dbdc_en = !!dev->mt76.phys[MT_BAND1],
};
u16 center_freq = chandef->center_freq1;
int freq_idx;
@ -2454,7 +2449,7 @@ int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy)
.bw = mt7615_mcu_chan_bw(chandef),
.band = chandef->center_freq1 > 4000,
.dbdc_en = !!dev->mt76.phy2,
.dbdc_en = !!dev->mt76.phys[MT_BAND1],
};
u16 center_freq = chandef->center_freq1;
int freq_idx;

View File

@ -201,9 +201,6 @@ struct mt7615_mcu_rdd_report {
} hw_pulse[32];
};
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
#define MCU_PKT_ID 0xa0
enum {
MCU_ATE_SET_FREQ_OFFSET = 0xa,
MCU_ATE_SET_TX_POWER_CONTROL = 0x15,

View File

@ -186,14 +186,14 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
{
static const struct mt76_driver_ops drv_ops = {
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common),
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_txp_common),
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
.token_size = MT7615_TOKEN_SIZE,
.tx_prepare_skb = mt7615_tx_prepare_skb,
.tx_complete_skb = mt7615_tx_complete_skb,
.tx_complete_skb = mt76_connac_tx_complete_skb,
.rx_check = mt7615_rx_check,
.rx_skb = mt7615_queue_rx_skb,
.rx_poll_complete = mt7615_rx_poll_complete,

View File

@ -141,6 +141,7 @@ struct mt7615_sta {
struct mt7615_vif {
struct mt76_vif mt76; /* must be first */
struct mt7615_sta sta;
bool sta_added;
};
struct mib_stats {
@ -177,7 +178,6 @@ struct mt7615_phy {
u8 chfreq;
u8 rdd_state;
int dfs_state;
u32 rx_ampdu_ts;
u32 ampdu_ref;
@ -345,7 +345,7 @@ mt7615_hw_dev(struct ieee80211_hw *hw)
static inline struct mt7615_phy *
mt7615_ext_phy(struct mt7615_dev *dev)
{
struct mt76_phy *phy = dev->mt76.phy2;
struct mt76_phy *phy = dev->mt76.phys[MT_BAND1];
if (!phy)
return NULL;
@ -477,7 +477,8 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev);
int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta, int pid,
struct ieee80211_key_conf *key, bool beacon);
struct ieee80211_key_conf *key,
enum mt76_txq_id qid, bool beacon);
void mt7615_mac_set_timing(struct mt7615_phy *phy);
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
struct mt76_wcid *wcid,
@ -507,7 +508,6 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct mt76_tx_info *tx_info);
void mt7615_tx_worker(struct mt76_worker *w);
void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt7615_tx_token_put(struct mt7615_dev *dev);
bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len);
void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
@ -518,8 +518,6 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7615_mac_work(struct work_struct *work);
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *txwi);
int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev);
int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val);
int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,

View File

@ -14,75 +14,6 @@
#include "../dma.h"
#include "mac.h"
void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
{
if (!e->txwi) {
dev_kfree_skb_any(e->skb);
return;
}
/* error path */
if (e->skb == DMA_DUMMY_DATA) {
struct mt76_txwi_cache *t;
struct mt7615_dev *dev;
struct mt7615_txp_common *txp;
u16 token;
dev = container_of(mdev, struct mt7615_dev, mt76);
txp = mt7615_txwi_to_txp(mdev, e->txwi);
if (is_mt7615(&dev->mt76))
token = le16_to_cpu(txp->fw.token);
else
token = le16_to_cpu(txp->hw.msdu_id[0]) &
~MT_MSDU_ID_VALID;
t = mt76_token_put(mdev, token);
e->skb = t ? t->skb : NULL;
}
if (e->skb)
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
}
static void
mt7615_write_hw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
void *txp_ptr, u32 id)
{
struct mt7615_hw_txp *txp = txp_ptr;
struct mt7615_txp_ptr *ptr = &txp->ptr[0];
int i, nbuf = tx_info->nbuf - 1;
u32 last_mask;
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);
if (is_mt7663(&dev->mt76))
last_mask = MT_TXD_LEN_LAST;
else
last_mask = MT_TXD_LEN_AMSDU_LAST |
MT_TXD_LEN_MSDU_LAST;
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 |= last_mask;
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
mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
void *txp_ptr, u32 id)
@ -91,7 +22,8 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct ieee80211_vif *vif = info->control.vif;
struct mt7615_fw_txp *txp = txp_ptr;
struct mt76_connac_fw_txp *txp = txp_ptr;
u8 *rept_wds_wcid = (u8 *)&txp->rept_wds_wcid;
int nbuf = tx_info->nbuf - 1;
int i;
@ -122,7 +54,7 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
}
txp->token = cpu_to_le16(id);
txp->rept_wds_wcid = 0xff;
*rept_wds_wcid = 0xff;
}
int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
@ -145,9 +77,10 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) {
struct mt7615_phy *phy = &dev->phy;
u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2)
phy = mdev->phy2->priv;
if (phy_idx && mdev->phys[MT_BAND1])
phy = mdev->phys[MT_BAND1]->priv;
spin_lock_bh(&dev->mt76.lock);
mt7615_mac_set_rates(phy, msta, &info->control.rates[0],
@ -164,14 +97,14 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta,
pid, key, false);
pid, key, qid, false);
txp = txwi + MT_TXD_SIZE;
memset(txp, 0, sizeof(struct mt7615_txp_common));
memset(txp, 0, sizeof(struct mt76_connac_txp_common));
if (is_mt7615(&dev->mt76))
mt7615_write_fw_txp(dev, tx_info, txp, id);
else
mt7615_write_hw_txp(dev, tx_info, txp, id);
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
tx_info->skb = DMA_DUMMY_DATA;
@ -250,16 +183,18 @@ mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
static void
mt7615_update_beacons(struct mt7615_dev *dev)
{
struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
ieee80211_iterate_active_interfaces(dev->mt76.hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_update_vif_beacon, dev->mt76.hw);
if (!dev->mt76.phy2)
if (!mphy_ext)
return;
ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw,
ieee80211_iterate_active_interfaces(mphy_ext->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_update_vif_beacon, dev->mt76.phy2->hw);
mt7615_update_vif_beacon, mphy_ext->hw);
}
void mt7615_mac_reset_work(struct work_struct *work)
@ -268,9 +203,10 @@ void mt7615_mac_reset_work(struct work_struct *work)
struct mt76_phy *ext_phy;
struct mt7615_dev *dev;
unsigned long timeout;
int i;
dev = container_of(work, struct mt7615_dev, reset_work);
ext_phy = dev->mt76.phy2;
ext_phy = dev->mt76.phys[MT_BAND1];
phy2 = ext_phy ? ext_phy->priv : NULL;
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA))
@ -299,8 +235,8 @@ void mt7615_mac_reset_work(struct work_struct *work)
mt76_txq_schedule_all(ext_phy);
mt76_worker_disable(&dev->mt76.tx_worker);
napi_disable(&dev->mt76.napi[0]);
napi_disable(&dev->mt76.napi[1]);
mt76_for_each_q_rx(&dev->mt76, i)
napi_disable(&dev->mt76.napi[i]);
napi_disable(&dev->mt76.tx_napi);
mt7615_mutex_acquire(dev);
@ -330,11 +266,10 @@ void mt7615_mac_reset_work(struct work_struct *work)
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]);
mt76_for_each_q_rx(&dev->mt76, i) {
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
local_bh_enable();
ieee80211_wake_queues(mt76_hw(dev));

View File

@ -49,7 +49,7 @@ mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid,
__le32 *txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE);
memset(txwi, 0, MT_USB_TXD_SIZE);
mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, false);
mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, qid, false);
skb_push(skb, MT_USB_TXD_SIZE);
}

View File

@ -12,9 +12,28 @@
#define MT76_CONNAC_MAX_SCHED_SCAN_SSID 10
#define MT76_CONNAC_MAX_SCAN_MATCH 16
#define MT76_CONNAC_MAX_WMM_SETS 4
#define MT76_CONNAC_COREDUMP_TIMEOUT (HZ / 20)
#define MT76_CONNAC_COREDUMP_SZ (1300 * 1024)
#define MT_TXD_SIZE (8 * 4)
#define MT_USB_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
#define MT_USB_HDR_SIZE 4
#define MT_USB_TAIL_SIZE 4
#define MT_SDIO_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
#define MT_SDIO_TAIL_SIZE 8
#define MT_SDIO_HDR_SIZE 4
#define MT_MSDU_ID_VALID BIT(15)
#define MT_TXD_LEN_LAST BIT(15)
#define MT_TXD_LEN_MASK GENMASK(11, 0)
#define MT_TXD_LEN_MSDU_LAST BIT(14)
#define MT_TXD_LEN_AMSDU_LAST BIT(15)
enum {
CMD_CBW_20MHZ = IEEE80211_STA_RX_BW_20,
CMD_CBW_40MHZ = IEEE80211_STA_RX_BW_40,
@ -90,6 +109,46 @@ struct mt76_connac_sta_key_conf {
u8 key[16];
};
#define MT_TXP_MAX_BUF_NUM 6
struct mt76_connac_fw_txp {
__le16 flags;
__le16 token;
u8 bss_idx;
__le16 rept_wds_wcid;
u8 nbuf;
__le32 buf[MT_TXP_MAX_BUF_NUM];
__le16 len[MT_TXP_MAX_BUF_NUM];
} __packed __aligned(4);
#define MT_HW_TXP_MAX_MSDU_NUM 4
#define MT_HW_TXP_MAX_BUF_NUM 4
struct mt76_connac_txp_ptr {
__le32 buf0;
__le16 len0;
__le16 len1;
__le32 buf1;
} __packed __aligned(4);
struct mt76_connac_hw_txp {
__le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM];
struct mt76_connac_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2];
} __packed __aligned(4);
struct mt76_connac_txp_common {
union {
struct mt76_connac_fw_txp fw;
struct mt76_connac_hw_txp hw;
};
};
struct mt76_connac_tx_free {
__le16 rx_byte_cnt;
__le16 ctrl;
__le32 txd;
} __packed __aligned(4);
extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
static inline bool is_mt7922(struct mt76_dev *dev)
@ -145,6 +204,19 @@ static inline bool is_connac_v1(struct mt76_dev *dev)
return is_mt7615(dev) || is_mt7663(dev) || is_mt7622(dev);
}
static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
{
switch (mt76_chip(dev)) {
case 0x7961:
case 0x7922:
case 0x7663:
case 0x7622:
return false;
default:
return true;
}
}
static inline u8 mt76_connac_chan_bw(struct cfg80211_chan_def *chandef)
{
static const u8 width_to_bw[] = {
@ -170,12 +242,31 @@ static inline u8 mt76_connac_lmac_mapping(u8 ac)
return 3 - ac;
}
static inline void *
mt76_connac_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
{
u8 *txwi;
if (!t)
return NULL;
txwi = mt76_get_txwi_ptr(dev, t);
return (void *)(txwi + MT_TXD_SIZE);
}
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
void mt76_connac_power_save_sched(struct mt76_phy *phy,
struct mt76_connac_pm *pm);
void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm,
struct mt76_wcid *wcid);
static inline void mt76_connac_tx_cleanup(struct mt76_dev *dev)
{
dev->queue_ops->tx_cleanup(dev, dev->q_mcu[MT_MCUQ_WM], false);
dev->queue_ops->tx_cleanup(dev, dev->q_mcu[MT_MCUQ_WA], false);
}
static inline bool
mt76_connac_pm_ref(struct mt76_phy *phy, struct mt76_connac_pm *pm)
{
@ -238,11 +329,36 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
mutex_unlock(&dev->mutex);
}
int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
int ring_base, u32 flags);
void mt76_connac_write_hw_txp(struct mt76_dev *dev,
struct mt76_tx_info *tx_info,
void *txp_ptr, u32 id);
void mt76_connac_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *txwi);
void mt76_connac_tx_complete_skb(struct mt76_dev *mdev,
struct mt76_queue_entry *e);
void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw,
struct mt76_connac_pm *pm,
struct mt76_wcid *wcid,
struct sk_buff *skb);
void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
struct mt76_connac_pm *pm);
void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, int pid,
enum mt76_txq_id qid, u32 changed);
bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
int pid, __le32 *txs_data,
struct mt76_sta_stats *stats);
void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev,
struct sk_buff *skb,
__le32 *rxv, u32 mode);
int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif,
struct sk_buff *skb, u16 hdr_offset);
int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
struct mt76_rx_status *status,
struct ieee80211_supported_band *sband,
__le32 *rxv, u8 *mode);
#endif /* __MT76_CONNAC_H */

View File

@ -0,0 +1,323 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2022 MediaTek Inc. */
#ifndef __MT76_CONNAC2_MAC_H
#define __MT76_CONNAC2_MAC_H
enum tx_header_format {
MT_HDR_FORMAT_802_3,
MT_HDR_FORMAT_CMD,
MT_HDR_FORMAT_802_11,
MT_HDR_FORMAT_802_11_EXT,
};
enum tx_pkt_type {
MT_TX_TYPE_CT,
MT_TX_TYPE_SF,
MT_TX_TYPE_CMD,
MT_TX_TYPE_FW,
};
enum {
MT_CTX0,
MT_HIF0 = 0x0,
MT_LMAC_AC00 = 0x0,
MT_LMAC_AC01,
MT_LMAC_AC02,
MT_LMAC_AC03,
MT_LMAC_ALTX0 = 0x10,
MT_LMAC_BMC0,
MT_LMAC_BCN0,
MT_LMAC_PSMP0,
};
#define MT_TXD0_Q_IDX GENMASK(31, 25)
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
#define MT_TXD1_LONG_FORMAT BIT(31)
#define MT_TXD1_TGID BIT(30)
#define MT_TXD1_OWN_MAC GENMASK(29, 24)
#define MT_TXD1_AMSDU BIT(23)
#define MT_TXD1_TID GENMASK(22, 20)
#define MT_TXD1_HDR_PAD GENMASK(19, 18)
#define MT_TXD1_HDR_FORMAT GENMASK(17, 16)
#define MT_TXD1_HDR_INFO GENMASK(15, 11)
#define MT_TXD1_ETH_802_3 BIT(15)
#define MT_TXD1_VTA BIT(10)
#define MT_TXD1_WLAN_IDX GENMASK(9, 0)
#define MT_TXD2_FIX_RATE BIT(31)
#define MT_TXD2_FIXED_RATE BIT(30)
#define MT_TXD2_POWER_OFFSET GENMASK(29, 24)
#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16)
#define MT_TXD2_FRAG GENMASK(15, 14)
#define MT_TXD2_HTC_VLD BIT(13)
#define MT_TXD2_DURATION BIT(12)
#define MT_TXD2_BIP BIT(11)
#define MT_TXD2_MULTICAST BIT(10)
#define MT_TXD2_RTS BIT(9)
#define MT_TXD2_SOUNDING BIT(8)
#define MT_TXD2_NDPA BIT(7)
#define MT_TXD2_NDP BIT(6)
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
#define MT_TXD3_SN_VALID BIT(31)
#define MT_TXD3_PN_VALID BIT(30)
#define MT_TXD3_SW_POWER_MGMT BIT(29)
#define MT_TXD3_BA_DISABLE BIT(28)
#define MT_TXD3_SEQ GENMASK(27, 16)
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
#define MT_TXD3_TIMING_MEASURE BIT(5)
#define MT_TXD3_DAS BIT(4)
#define MT_TXD3_EEOSP BIT(3)
#define MT_TXD3_EMRD BIT(2)
#define MT_TXD3_PROTECT_FRAME BIT(1)
#define MT_TXD3_NO_ACK BIT(0)
#define MT_TXD4_PN_LOW GENMASK(31, 0)
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
#define MT_TXD5_MD BIT(15)
#define MT_TXD5_ADD_BA BIT(14)
#define MT_TXD5_TX_STATUS_HOST BIT(10)
#define MT_TXD5_TX_STATUS_MCU BIT(9)
#define MT_TXD5_TX_STATUS_FMT BIT(8)
#define MT_TXD5_PID GENMASK(7, 0)
#define MT_TXD6_TX_IBF BIT(31)
#define MT_TXD6_TX_EBF BIT(30)
#define MT_TXD6_TX_RATE GENMASK(29, 16)
#define MT_TXD6_SGI GENMASK(15, 14)
#define MT_TXD6_HELTF GENMASK(13, 12)
#define MT_TXD6_LDPC BIT(11)
#define MT_TXD6_SPE_ID_IDX BIT(10)
#define MT_TXD6_ANT_ID GENMASK(7, 4)
#define MT_TXD6_DYN_BW BIT(3)
#define MT_TXD6_FIXED_BW BIT(2)
#define MT_TXD6_BW GENMASK(1, 0)
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
#define MT_TXD7_UDP_TCP_SUM BIT(29)
#define MT_TXD7_IP_SUM BIT(28)
#define MT_TXD7_TYPE GENMASK(21, 20)
#define MT_TXD7_SUB_TYPE GENMASK(19, 16)
#define MT_TXD7_PSE_FID GENMASK(27, 16)
#define MT_TXD7_SPE_IDX GENMASK(15, 11)
#define MT_TXD7_HW_AMSDU BIT(10)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
#define MT_TXD8_L_TYPE GENMASK(5, 4)
#define MT_TXD8_L_SUB_TYPE GENMASK(3, 0)
#define MT_TX_RATE_STBC BIT(13)
#define MT_TX_RATE_NSS GENMASK(12, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
#define MT_TX_RATE_DCM BIT(4)
/* VHT/HE only use bits 0-3 */
#define MT_TX_RATE_IDX GENMASK(5, 0)
#define MT_TXS0_FIXED_RATE BIT(31)
#define MT_TXS0_BW GENMASK(30, 29)
#define MT_TXS0_TID GENMASK(28, 26)
#define MT_TXS0_AMPDU BIT(25)
#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
#define MT_TXS0_BA_ERROR BIT(22)
#define MT_TXS0_PS_FLAG BIT(21)
#define MT_TXS0_TXOP_TIMEOUT BIT(20)
#define MT_TXS0_BIP_ERROR BIT(19)
#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
#define MT_TXS0_RTS_TIMEOUT BIT(17)
#define MT_TXS0_ACK_TIMEOUT BIT(16)
#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
#define MT_TXS0_TX_STATUS_HOST BIT(15)
#define MT_TXS0_TX_STATUS_MCU BIT(14)
#define MT_TXS0_TX_RATE GENMASK(13, 0)
#define MT_TXS1_SEQNO GENMASK(31, 20)
#define MT_TXS1_RESP_RATE GENMASK(19, 16)
#define MT_TXS1_RXV_SEQNO GENMASK(15, 8)
#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0)
#define MT_TXS2_BF_STATUS GENMASK(31, 30)
#define MT_TXS2_LAST_TX_RATE GENMASK(29, 27)
#define MT_TXS2_SHARED_ANTENNA BIT(26)
#define MT_TXS2_WCID GENMASK(25, 16)
#define MT_TXS2_TX_DELAY GENMASK(15, 0)
#define MT_TXS3_PID GENMASK(31, 24)
#define MT_TXS3_ANT_ID GENMASK(23, 0)
#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
/* RXD DW1 */
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0)
#define MT_RXD1_NORMAL_GROUP_1 BIT(11)
#define MT_RXD1_NORMAL_GROUP_2 BIT(12)
#define MT_RXD1_NORMAL_GROUP_3 BIT(13)
#define MT_RXD1_NORMAL_GROUP_4 BIT(14)
#define MT_RXD1_NORMAL_GROUP_5 BIT(15)
#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16)
#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
#define MT_RXD1_NORMAL_CM BIT(23)
#define MT_RXD1_NORMAL_CLM BIT(24)
#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
#define MT_RXD1_NORMAL_FCS_ERR BIT(27)
#define MT_RXD1_NORMAL_BAND_IDX BIT(28)
#define MT_RXD1_NORMAL_SPP_EN BIT(29)
#define MT_RXD1_NORMAL_ADD_OM BIT(30)
#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
/* RXD DW2 */
#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
#define MT_RXD2_NORMAL_CO_ANT BIT(6)
#define MT_RXD2_NORMAL_BF_CQI BIT(7)
#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
#define MT_RXD2_NORMAL_HDR_TRANS BIT(13)
#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14)
#define MT_RXD2_NORMAL_TID GENMASK(19, 16)
#define MT_RXD2_NORMAL_MU_BAR BIT(21)
#define MT_RXD2_NORMAL_SW_BIT BIT(22)
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
#define MT_RXD2_NORMAL_FRAG BIT(27)
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
#define MT_RXD2_NORMAL_NDATA BIT(29)
#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
/* RXD DW4 */
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9)
#define MT_RXD4_NORMAL_CLS BIT(10)
#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11)
#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13)
#define MT_RXD4_NORMAL_WOL GENMASK(18, 14)
#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19)
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
#define MT_RXV_HDR_BAND_IDX BIT(24)
/* RXD DW3 */
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
#define MT_RXD3_NORMAL_U2M BIT(0)
#define MT_RXD3_NORMAL_HTC_VLD BIT(0)
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19)
#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
#define MT_RXD3_NORMAL_AMSDU BIT(22)
#define MT_RXD3_NORMAL_MESH BIT(23)
#define MT_RXD3_NORMAL_MHCP BIT(24)
#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25)
#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26)
#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27)
#define MT_RXD3_NORMAL_MORE BIT(28)
#define MT_RXD3_NORMAL_UNWANT BIT(29)
#define MT_RXD3_NORMAL_RX_DROP BIT(30)
#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
/* RXD GROUP4 */
#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0)
#define MT_RXD6_TA_LO GENMASK(31, 16)
#define MT_RXD7_TA_HI GENMASK(31, 0)
#define MT_RXD8_SEQ_CTRL GENMASK(15, 0)
#define MT_RXD8_QOS_CTL GENMASK(31, 16)
#define MT_RXD9_HT_CONTROL GENMASK(31, 0)
/* P-RXV DW0 */
#define MT_PRXV_TX_RATE GENMASK(6, 0)
#define MT_PRXV_TX_DCM BIT(4)
#define MT_PRXV_TX_ER_SU_106T BIT(5)
#define MT_PRXV_NSTS GENMASK(9, 7)
#define MT_PRXV_TXBF BIT(10)
#define MT_PRXV_HT_AD_CODE BIT(11)
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
#define MT_PRXV_FRAME_MODE GENMASK(14, 12)
#define MT_PRXV_HT_SGI GENMASK(16, 15)
#define MT_PRXV_HT_STBC GENMASK(23, 22)
#define MT_PRXV_TX_MODE GENMASK(27, 24)
#define MT_PRXV_DCM BIT(17)
#define MT_PRXV_NUM_RX BIT(20, 18)
/* P-RXV DW1 */
#define MT_PRXV_RCPI3 GENMASK(31, 24)
#define MT_PRXV_RCPI2 GENMASK(23, 16)
#define MT_PRXV_RCPI1 GENMASK(15, 8)
#define MT_PRXV_RCPI0 GENMASK(7, 0)
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
/* C-RXV */
#define MT_CRXV_HT_STBC GENMASK(1, 0)
#define MT_CRXV_TX_MODE GENMASK(7, 4)
#define MT_CRXV_FRAME_MODE GENMASK(10, 8)
#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13)
#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
#define MT_CRXV_HE_PE_DISAMBIG BIT(23)
#define MT_CRXV_HE_NUM_USER GENMASK(30, 24)
#define MT_CRXV_HE_UPLINK BIT(31)
#define MT_CRXV_HE_RU0 GENMASK(7, 0)
#define MT_CRXV_HE_RU1 GENMASK(15, 8)
#define MT_CRXV_HE_RU2 GENMASK(23, 16)
#define MT_CRXV_HE_RU3 GENMASK(31, 24)
#define MT_CRXV_HE_MU_AID GENMASK(30, 20)
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0)
#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6)
#define MT_CRXV_HE_BEAM_CHNG BIT(13)
#define MT_CRXV_HE_DOPPLER BIT(16)
#define MT_CRXV_SNR GENMASK(18, 13)
#define MT_CRXV_FOE_LO GENMASK(31, 19)
#define MT_CRXV_FOE_HI GENMASK(6, 0)
#define MT_CRXV_FOE_SHIFT 13
#define MT_CT_INFO_APPLY_TXD BIT(0)
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
#define MT_CT_INFO_MGMT_FRAME BIT(2)
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
#define MT_CT_INFO_HSR2_TX BIT(4)
#define MT_CT_INFO_FROM_HOST BIT(7)
enum tx_mcu_port_q_idx {
MT_TX_MCU_PORT_RX_Q0 = 0x20,
MT_TX_MCU_PORT_RX_Q1,
MT_TX_MCU_PORT_RX_Q2,
MT_TX_MCU_PORT_RX_Q3,
MT_TX_MCU_PORT_RX_FWDL = 0x3e
};
enum tx_port_idx {
MT_TX_PORT_IDX_LMAC,
MT_TX_PORT_IDX_MCU
};
#endif /* __MT76_CONNAC2_MAC_H */

View File

@ -2,6 +2,12 @@
/* Copyright (C) 2020 MediaTek Inc. */
#include "mt76_connac.h"
#include "mt76_connac2_mac.h"
#include "dma.h"
#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)
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)
{
@ -115,3 +121,917 @@ void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
mt76_worker_schedule(&phy->dev->tx_worker);
}
EXPORT_SYMBOL_GPL(mt76_connac_pm_dequeue_skbs);
void mt76_connac_tx_complete_skb(struct mt76_dev *mdev,
struct mt76_queue_entry *e)
{
if (!e->txwi) {
dev_kfree_skb_any(e->skb);
return;
}
/* error path */
if (e->skb == DMA_DUMMY_DATA) {
struct mt76_connac_txp_common *txp;
struct mt76_txwi_cache *t;
u16 token;
txp = mt76_connac_txwi_to_txp(mdev, e->txwi);
if (is_mt76_fw_txp(mdev))
token = le16_to_cpu(txp->fw.token);
else
token = le16_to_cpu(txp->hw.msdu_id[0]) &
~MT_MSDU_ID_VALID;
t = mt76_token_put(mdev, token);
e->skb = t ? t->skb : NULL;
}
if (e->skb)
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
}
EXPORT_SYMBOL_GPL(mt76_connac_tx_complete_skb);
void mt76_connac_write_hw_txp(struct mt76_dev *dev,
struct mt76_tx_info *tx_info,
void *txp_ptr, u32 id)
{
struct mt76_connac_hw_txp *txp = txp_ptr;
struct mt76_connac_txp_ptr *ptr = &txp->ptr[0];
int i, nbuf = tx_info->nbuf - 1;
u32 last_mask;
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);
if (is_mt7663(dev) || is_mt7921(dev))
last_mask = MT_TXD_LEN_LAST;
else
last_mask = MT_TXD_LEN_AMSDU_LAST |
MT_TXD_LEN_MSDU_LAST;
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 |= last_mask;
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);
}
}
}
EXPORT_SYMBOL_GPL(mt76_connac_write_hw_txp);
static void
mt76_connac_txp_skb_unmap_fw(struct mt76_dev *mdev,
struct mt76_connac_fw_txp *txp)
{
struct device *dev = is_connac_v1(mdev) ? mdev->dev : mdev->dma_dev;
int i;
for (i = 0; i < txp->nbuf; i++)
dma_unmap_single(dev, le32_to_cpu(txp->buf[i]),
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
}
static void
mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev,
struct mt76_connac_hw_txp *txp)
{
u32 last_mask;
int i;
if (is_mt7663(dev) || is_mt7921(dev))
last_mask = MT_TXD_LEN_LAST;
else
last_mask = MT_TXD_LEN_MSDU_LAST;
for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) {
struct mt76_connac_txp_ptr *ptr = &txp->ptr[i];
bool last;
u16 len;
len = le16_to_cpu(ptr->len0);
last = len & last_mask;
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 & last_mask;
len &= MT_TXD_LEN_MASK;
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len,
DMA_TO_DEVICE);
if (last)
break;
}
}
void mt76_connac_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *t)
{
struct mt76_connac_txp_common *txp;
txp = mt76_connac_txwi_to_txp(dev, t);
if (is_mt76_fw_txp(dev))
mt76_connac_txp_skb_unmap_fw(dev, &txp->fw);
else
mt76_connac_txp_skb_unmap_hw(dev, &txp->hw);
}
EXPORT_SYMBOL_GPL(mt76_connac_txp_skb_unmap);
int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
int ring_base, u32 flags)
{
int i, err;
err = mt76_init_tx_queue(phy, 0, idx, n_desc, ring_base, flags);
if (err < 0)
return err;
for (i = 1; i <= MT_TXQ_PSD; i++)
phy->q_tx[i] = phy->q_tx[0];
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues);
static u16
mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif,
bool beacon, bool mcast)
{
u8 mode = 0, band = mphy->chandef.chan->band;
int rateidx = 0, mcast_rate;
if (!vif)
goto legacy;
if (is_mt7921(mphy->dev)) {
rateidx = ffs(vif->bss_conf.basic_rates) - 1;
goto legacy;
}
if (beacon) {
struct cfg80211_bitrate_mask *mask;
mask = &vif->bss_conf.beacon_tx_rate;
if (hweight16(mask->control[band].he_mcs[0]) == 1) {
rateidx = ffs(mask->control[band].he_mcs[0]) - 1;
mode = MT_PHY_TYPE_HE_SU;
goto out;
} else if (hweight16(mask->control[band].vht_mcs[0]) == 1) {
rateidx = ffs(mask->control[band].vht_mcs[0]) - 1;
mode = MT_PHY_TYPE_VHT;
goto out;
} else if (hweight8(mask->control[band].ht_mcs[0]) == 1) {
rateidx = ffs(mask->control[band].ht_mcs[0]) - 1;
mode = MT_PHY_TYPE_HT;
goto out;
} else if (hweight32(mask->control[band].legacy) == 1) {
rateidx = ffs(mask->control[band].legacy) - 1;
goto legacy;
}
}
mcast_rate = vif->bss_conf.mcast_rate[band];
if (mcast && mcast_rate > 0)
rateidx = mcast_rate - 1;
else
rateidx = ffs(vif->bss_conf.basic_rates) - 1;
legacy:
rateidx = mt76_calculate_default_rate(mphy, rateidx);
mode = rateidx >> 8;
rateidx &= GENMASK(7, 0);
out:
return FIELD_PREP(MT_TX_RATE_IDX, rateidx) |
FIELD_PREP(MT_TX_RATE_MODE, mode);
}
static void
mt76_connac2_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb,
struct mt76_wcid *wcid)
{
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
u8 fc_type, fc_stype;
u16 ethertype;
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);
ethertype = get_unaligned_be16(&skb->data[12]);
if (ethertype >= 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
mt76_connac2_mac_write_txwi_80211(struct mt76_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 ||
info->flags & IEEE80211_TX_CTL_USE_MINRATE)
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 (!is_mt7921(dev))
txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX,
0x18));
}
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);
txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU);
}
if (mt76_is_mmio(dev)) {
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
txwi[7] |= cpu_to_le32(val);
} else {
val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) |
FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype);
txwi[8] |= cpu_to_le32(val);
}
}
void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, int pid,
enum mt76_txq_id qid, u32 changed)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
struct ieee80211_vif *vif = info->control.vif;
struct mt76_phy *mphy = &dev->phy;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0, band_idx = 0;
u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED));
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
BSS_CHANGED_FILS_DISCOVERY));
if (vif) {
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
omac_idx = mvif->omac_idx;
wmm_idx = mvif->wmm_idx;
band_idx = mvif->band_idx;
}
if (phy_idx && dev->phys[MT_BAND1])
mphy = dev->phys[MT_BAND1];
if (inband_disc) {
p_fmt = MT_TX_TYPE_FW;
q_idx = MT_LMAC_ALTX0;
} else if (beacon) {
p_fmt = MT_TX_TYPE_FW;
q_idx = MT_LMAC_BCN0;
} else if (qid >= MT_TXQ_PSD) {
p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
q_idx = MT_LMAC_ALTX0;
} else {
p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
}
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
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);
if (!is_mt7921(dev))
val |= MT_TXD1_VTA;
if (phy_idx || band_idx)
val |= MT_TXD1_TGID;
txwi[1] = cpu_to_le32(val);
txwi[2] = 0;
val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15);
if (!is_mt7921(dev))
val |= MT_TXD3_SW_POWER_MGMT;
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;
val = FIELD_PREP(MT_TXD5_PID, pid);
if (pid >= MT_PACKET_ID_FIRST)
val |= MT_TXD5_TX_STATUS_HOST;
txwi[5] = cpu_to_le32(val);
txwi[6] = 0;
txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
if (is_8023)
mt76_connac2_mac_write_txwi_8023(txwi, skb, wcid);
else
mt76_connac2_mac_write_txwi_80211(dev, txwi, skb, key);
if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) {
/* Fixed rata is available just for 802.11 txd */
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
bool multicast = is_multicast_ether_addr(hdr->addr1);
u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon,
multicast);
u32 val = MT_TXD6_FIXED_BW;
/* hardware won't add HTC for mgmt/ctrl frame */
txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD);
val |= FIELD_PREP(MT_TXD6_TX_RATE, rate);
txwi[6] |= cpu_to_le32(val);
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
}
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_write_txwi);
bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
int pid, __le32 *txs_data,
struct mt76_sta_stats *stats)
{
struct ieee80211_supported_band *sband;
struct mt76_phy *mphy;
struct ieee80211_tx_info *info;
struct sk_buff_head list;
struct rate_info rate = {};
struct sk_buff *skb;
bool cck = false;
u32 txrate, txs, mode;
mt76_tx_status_lock(dev, &list);
skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
if (!skb)
goto out;
txs = le32_to_cpu(txs_data[0]);
info = IEEE80211_SKB_CB(skb);
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.ampdu_len = 1;
info->status.ampdu_ack_len = !!(info->flags &
IEEE80211_TX_STAT_ACK);
info->status.rates[0].idx = -1;
txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
stats->tx_nss[rate.nss - 1]++;
if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
stats->tx_mcs[rate.mcs]++;
mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
switch (mode) {
case MT_PHY_TYPE_CCK:
cck = true;
fallthrough;
case MT_PHY_TYPE_OFDM:
mphy = &dev->phy;
if (wcid->phy_idx == MT_BAND1 && dev->phys[MT_BAND1])
mphy = dev->phys[MT_BAND1];
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
sband = &mphy->sband_5g.sband;
else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
sband = &mphy->sband_6g.sband;
else
sband = &mphy->sband_2g.sband;
rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck);
rate.legacy = sband->bitrates[rate.mcs].bitrate;
break;
case MT_PHY_TYPE_HT:
case MT_PHY_TYPE_HT_GF:
if (rate.mcs > 31)
goto out;
rate.flags = RATE_INFO_FLAGS_MCS;
if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
break;
case MT_PHY_TYPE_VHT:
if (rate.mcs > 9)
goto out;
rate.flags = RATE_INFO_FLAGS_VHT_MCS;
break;
case MT_PHY_TYPE_HE_SU:
case MT_PHY_TYPE_HE_EXT_SU:
case MT_PHY_TYPE_HE_TB:
case MT_PHY_TYPE_HE_MU:
if (rate.mcs > 11)
goto out;
rate.he_gi = wcid->rate.he_gi;
rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
rate.flags = RATE_INFO_FLAGS_HE_MCS;
break;
default:
goto out;
}
stats->tx_mode[mode]++;
switch (FIELD_GET(MT_TXS0_BW, txs)) {
case IEEE80211_STA_RX_BW_160:
rate.bw = RATE_INFO_BW_160;
stats->tx_bw[3]++;
break;
case IEEE80211_STA_RX_BW_80:
rate.bw = RATE_INFO_BW_80;
stats->tx_bw[2]++;
break;
case IEEE80211_STA_RX_BW_40:
rate.bw = RATE_INFO_BW_40;
stats->tx_bw[1]++;
break;
default:
rate.bw = RATE_INFO_BW_20;
stats->tx_bw[0]++;
break;
}
wcid->rate = rate;
out:
if (skb)
mt76_tx_status_skb_done(dev, skb, &list);
mt76_tx_status_unlock(dev, &list);
return !!skb;
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_add_txs_skb);
static void
mt76_connac2_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 = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
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
mt76_connac2_mac_decode_he_mu_radiotap(struct mt76_dev *dev, struct sk_buff *skb,
__le32 *rxv)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
static struct ieee80211_radiotap_he_mu mu_known = {
.flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
.flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
};
struct ieee80211_radiotap_he_mu *he_mu;
if (is_mt7921(dev)) {
mu_known.flags1 |= HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN);
mu_known.flags2 |= HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN);
}
status->flag |= RX_FLAG_RADIOTAP_HE_MU;
he_mu = skb_push(skb, sizeof(mu_known));
memcpy(he_mu, &mu_known, sizeof(mu_known));
#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
if (status->he_dcm)
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0);
if (status->bw >= RATE_INFO_BW_40) {
he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
he_mu->ru_ch2[0] =
le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
}
if (status->bw >= RATE_INFO_BW_80) {
he_mu->ru_ch1[1] =
le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
he_mu->ru_ch2[1] =
le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
}
}
void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev,
struct sk_buff *skb,
__le32 *rxv, u32 mode)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
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_SPTL_REUSE_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),
};
u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1;
struct ieee80211_radiotap_he *he;
status->flag |= RX_FLAG_RADIOTAP_HE;
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->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
le16_encode_bits(ltf_size,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
he->data5 |= HE_BITS(DATA5_TXBF);
he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
switch (mode) {
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_BW_RU_ALLOC_KNOWN);
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
break;
case MT_PHY_TYPE_HE_EXT_SU:
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
HE_BITS(DATA1_UL_DL_KNOWN) |
HE_BITS(DATA1_BW_RU_ALLOC_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->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
mt76_connac2_mac_decode_he_radiotap_ru(status, he, rxv);
mt76_connac2_mac_decode_he_mu_radiotap(dev, skb, rxv);
break;
case MT_PHY_TYPE_HE_TB:
he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
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]);
mt76_connac2_mac_decode_he_radiotap_ru(status, he, rxv);
break;
default:
break;
}
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_decode_he_radiotap);
/* The HW does not translate the mac header to 802.3 for mesh point */
int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif,
struct sk_buff *skb, u16 hdr_offset)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_offset);
__le32 *rxd = (__le32 *)skb->data;
struct ieee80211_sta *sta;
struct ieee80211_hdr hdr;
u16 frame_control;
if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
MT_RXD3_NORMAL_U2M)
return -EINVAL;
if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4))
return -EINVAL;
sta = container_of((void *)status->wcid, struct ieee80211_sta, drv_priv);
/* store the info from RXD and ethhdr to avoid being overridden */
frame_control = le32_get_bits(rxd[6], MT_RXD6_FRAME_CONTROL);
hdr.frame_control = cpu_to_le16(frame_control);
hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_SEQ_CTRL));
hdr.duration_id = 0;
ether_addr_copy(hdr.addr1, vif->addr);
ether_addr_copy(hdr.addr2, sta->addr);
switch (frame_control & (IEEE80211_FCTL_TODS |
IEEE80211_FCTL_FROMDS)) {
case 0:
ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);
break;
case IEEE80211_FCTL_FROMDS:
ether_addr_copy(hdr.addr3, eth_hdr->h_source);
break;
case IEEE80211_FCTL_TODS:
ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
break;
case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS:
ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
ether_addr_copy(hdr.addr4, eth_hdr->h_source);
break;
default:
break;
}
skb_pull(skb, hdr_offset + sizeof(struct ethhdr) - 2);
if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||
eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))
ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);
else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)
ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);
else
skb_pull(skb, 2);
if (ieee80211_has_order(hdr.frame_control))
memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[9],
IEEE80211_HT_CTL_LEN);
if (ieee80211_is_data_qos(hdr.frame_control)) {
__le16 qos_ctrl;
qos_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_QOS_CTL));
memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,
IEEE80211_QOS_CTL_LEN);
}
if (ieee80211_has_a4(hdr.frame_control))
memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
else
memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6);
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac2_reverse_frag0_hdr_trans);
int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
struct mt76_rx_status *status,
struct ieee80211_supported_band *sband,
__le32 *rxv, u8 *mode)
{
u32 v0, v2;
u8 stbc, gi, bw, dcm, nss;
int i, idx;
bool cck = false;
v0 = le32_to_cpu(rxv[0]);
v2 = le32_to_cpu(rxv[2]);
idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
if (!is_mt7915(dev)) {
stbc = FIELD_GET(MT_PRXV_HT_STBC, v0);
gi = FIELD_GET(MT_PRXV_HT_SGI, v0);
*mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
if (is_mt7921(dev))
dcm = !!(idx & MT_PRXV_TX_DCM);
else
dcm = FIELD_GET(MT_PRXV_DCM, v0);
bw = FIELD_GET(MT_PRXV_FRAME_MODE, v0);
} else {
stbc = FIELD_GET(MT_CRXV_HT_STBC, v2);
gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2);
*mode = FIELD_GET(MT_CRXV_TX_MODE, v2);
dcm = !!(idx & GENMASK(3, 0) & MT_PRXV_TX_DCM);
bw = FIELD_GET(MT_CRXV_FRAME_MODE, v2);
}
switch (*mode) {
case MT_PHY_TYPE_CCK:
cck = true;
fallthrough;
case MT_PHY_TYPE_OFDM:
i = mt76_get_rate(dev, sband, i, cck);
break;
case MT_PHY_TYPE_HT_GF:
case MT_PHY_TYPE_HT:
status->encoding = RX_ENC_HT;
if (gi)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
if (i > 31)
return -EINVAL;
break;
case MT_PHY_TYPE_VHT:
status->nss = nss;
status->encoding = RX_ENC_VHT;
if (gi)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
if (i > 11)
return -EINVAL;
break;
case MT_PHY_TYPE_HE_MU:
case MT_PHY_TYPE_HE_SU:
case MT_PHY_TYPE_HE_EXT_SU:
case MT_PHY_TYPE_HE_TB:
status->nss = nss;
status->encoding = RX_ENC_HE;
i &= GENMASK(3, 0);
if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
status->he_gi = gi;
status->he_dcm = dcm;
break;
default:
return -EINVAL;
}
status->rate_idx = i;
switch (bw) {
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;
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate);

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
#include <linux/firmware.h>
#include "mt76_connac2_mac.h"
#include "mt76_connac_mcu.h"
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
@ -193,7 +195,7 @@ int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif)
*/
} req = {
.bss_idx = mvif->idx,
.ps_state = vif->bss_conf.ps ? 2 : 0,
.ps_state = vif->cfg.ps ? 2 : 0,
};
if (vif->type != NL80211_IFTYPE_STATION)
@ -1403,6 +1405,8 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
else
conn_type = CONNECTION_INFRA_AP;
basic_req.basic.conn_type = cpu_to_le32(conn_type);
/* Fully active/deactivate BSS network in AP mode only */
basic_req.basic.active = enable;
break;
case NL80211_IFTYPE_STATION:
if (vif->p2p)
@ -2808,5 +2812,304 @@ int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_rdd_cmd);
static int
mt76_connac_mcu_send_ram_firmware(struct mt76_dev *dev,
const struct mt76_connac2_fw_trailer *hdr,
const u8 *data, bool is_wa)
{
int i, offset = 0, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
u32 override = 0, option = 0;
for (i = 0; i < hdr->n_region; i++) {
const struct mt76_connac2_fw_region *region;
u32 len, addr, mode;
int err;
region = (const void *)((const u8 *)hdr -
(hdr->n_region - i) * sizeof(*region));
mode = mt76_connac_mcu_gen_dl_mode(dev, region->feature_set,
is_wa);
len = le32_to_cpu(region->len);
addr = le32_to_cpu(region->addr);
if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR)
override = addr;
err = mt76_connac_mcu_init_download(dev, addr, len, mode);
if (err) {
dev_err(dev->dev, "Download request failed\n");
return err;
}
err = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
data + offset, len, max_len);
if (err) {
dev_err(dev->dev, "Failed to send firmware.\n");
return err;
}
offset += len;
}
if (override)
option |= FW_START_OVERRIDE;
if (is_wa)
option |= FW_START_WORKING_PDA_CR4;
return mt76_connac_mcu_start_firmware(dev, override, option);
}
int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
const char *fw_wa)
{
const struct mt76_connac2_fw_trailer *hdr;
const struct firmware *fw;
int ret;
ret = request_firmware(&fw, fw_wm, dev->dev);
if (ret)
return ret;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->dev, "Invalid firmware\n");
ret = -EINVAL;
goto out;
}
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
dev_info(dev->dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, false);
if (ret) {
dev_err(dev->dev, "Failed to start WM firmware\n");
goto out;
}
release_firmware(fw);
if (!fw_wa)
return 0;
ret = request_firmware(&fw, fw_wa, dev->dev);
if (ret)
return ret;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->dev, "Invalid firmware\n");
ret = -EINVAL;
goto out;
}
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
dev_info(dev->dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, true);
if (ret) {
dev_err(dev->dev, "Failed to start WA firmware\n");
goto out;
}
snprintf(dev->hw->wiphy->fw_version,
sizeof(dev->hw->wiphy->fw_version),
"%.10s-%.15s", hdr->fw_ver, hdr->build_date);
out:
release_firmware(fw);
return ret;
}
EXPORT_SYMBOL_GPL(mt76_connac2_load_ram);
static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)
{
u32 mode = DL_MODE_NEED_RSP;
if (!is_mt7921(dev) || info == PATCH_SEC_NOT_SUPPORT)
return mode;
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
case PATCH_SEC_ENC_TYPE_PLAIN:
break;
case PATCH_SEC_ENC_TYPE_AES:
mode |= DL_MODE_ENCRYPT;
mode |= FIELD_PREP(DL_MODE_KEY_IDX,
(info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX;
mode |= DL_MODE_RESET_SEC_IV;
break;
case PATCH_SEC_ENC_TYPE_SCRAMBLE:
mode |= DL_MODE_ENCRYPT;
mode |= DL_CONFIG_ENCRY_MODE_SEL;
mode |= DL_MODE_RESET_SEC_IV;
break;
default:
dev_err(dev->dev, "Encryption type not support!\n");
}
return mode;
}
int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)
{
int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
const struct mt76_connac2_patch_hdr *hdr;
const struct firmware *fw = NULL;
sem = mt76_connac_mcu_patch_sem_ctrl(dev, true);
switch (sem) {
case PATCH_IS_DL:
return 0;
case PATCH_NOT_DL_SEM_SUCCESS:
break;
default:
dev_err(dev->dev, "Failed to get patch semaphore\n");
return -EAGAIN;
}
ret = request_firmware(&fw, fw_name, dev->dev);
if (ret)
goto out;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->dev, "Invalid firmware\n");
ret = -EINVAL;
goto out;
}
hdr = (const void *)fw->data;
dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
struct mt76_connac2_patch_sec *sec;
u32 len, addr, mode;
const u8 *dl;
u32 sec_info;
sec = (void *)(fw->data + sizeof(*hdr) + i * sizeof(*sec));
if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
PATCH_SEC_TYPE_INFO) {
ret = -EINVAL;
goto out;
}
addr = be32_to_cpu(sec->info.addr);
len = be32_to_cpu(sec->info.len);
dl = fw->data + be32_to_cpu(sec->offs);
sec_info = be32_to_cpu(sec->info.sec_key_idx);
mode = mt76_connac2_get_data_mode(dev, sec_info);
ret = mt76_connac_mcu_init_download(dev, addr, len, mode);
if (ret) {
dev_err(dev->dev, "Download request failed\n");
goto out;
}
ret = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
dl, len, max_len);
if (ret) {
dev_err(dev->dev, "Failed to send patch\n");
goto out;
}
}
ret = mt76_connac_mcu_start_patch(dev);
if (ret)
dev_err(dev->dev, "Failed to start patch\n");
out:
sem = mt76_connac_mcu_patch_sem_ctrl(dev, false);
switch (sem) {
case PATCH_REL_SEM_SUCCESS:
break;
default:
ret = -EAGAIN;
dev_err(dev->dev, "Failed to release patch semaphore\n");
break;
}
release_firmware(fw);
return ret;
}
EXPORT_SYMBOL_GPL(mt76_connac2_load_patch);
int mt76_connac2_mcu_fill_message(struct mt76_dev *dev, struct sk_buff *skb,
int cmd, int *wait_seq)
{
int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
struct mt76_connac2_mcu_uni_txd *uni_txd;
struct mt76_connac2_mcu_txd *mcu_txd;
__le32 *txd;
u32 val;
u8 seq;
/* TODO: make dynamic based on msg type */
dev->mcu.timeout = 20 * HZ;
seq = ++dev->mcu.msg_seq & 0xf;
if (!seq)
seq = ++dev->mcu.msg_seq & 0xf;
if (cmd == MCU_CMD(FW_SCATTER))
goto exit;
txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd);
txd = (__le32 *)skb_push(skb, txd_len);
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |
FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) |
FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0);
txd[0] = cpu_to_le32(val);
val = MT_TXD1_LONG_FORMAT |
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD);
txd[1] = cpu_to_le32(val);
if (cmd & __MCU_CMD_FIELD_UNI) {
uni_txd = (struct mt76_connac2_mcu_uni_txd *)txd;
uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd));
uni_txd->option = MCU_CMD_UNI_EXT_ACK;
uni_txd->cid = cpu_to_le16(mcu_cmd);
uni_txd->s2d_index = MCU_S2D_H2N;
uni_txd->pkt_type = MCU_PKT_ID;
uni_txd->seq = seq;
goto exit;
}
mcu_txd = (struct mt76_connac2_mcu_txd *)txd;
mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd));
mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU,
MT_TX_MCU_PORT_RX_Q0));
mcu_txd->pkt_type = MCU_PKT_ID;
mcu_txd->seq = seq;
mcu_txd->cid = mcu_cmd;
mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd);
if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) {
if (cmd & __MCU_CMD_FIELD_QUERY)
mcu_txd->set_query = MCU_Q_QUERY;
else
mcu_txd->set_query = MCU_Q_SET;
mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid;
} else {
mcu_txd->set_query = MCU_Q_NA;
}
if (cmd & __MCU_CMD_FIELD_WA)
mcu_txd->s2d_index = MCU_S2D_H2C;
else
mcu_txd->s2d_index = MCU_S2D_H2N;
exit:
if (wait_seq)
*wait_seq = seq;
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac2_mcu_fill_message);
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -26,6 +26,157 @@
#define PATCH_SEC_TYPE_MASK GENMASK(15, 0)
#define PATCH_SEC_TYPE_INFO 0x2
#define PATCH_SEC_ENC_TYPE_MASK GENMASK(31, 24)
#define PATCH_SEC_ENC_TYPE_PLAIN 0x00
#define PATCH_SEC_ENC_TYPE_AES 0x01
#define PATCH_SEC_ENC_TYPE_SCRAMBLE 0x02
#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK GENMASK(15, 0)
#define PATCH_SEC_ENC_AES_KEY_MASK GENMASK(7, 0)
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
#define MCU_PKT_ID 0xa0
struct mt76_connac2_mcu_txd {
__le32 txd[8];
__le16 len;
__le16 pq_id;
u8 cid;
u8 pkt_type;
u8 set_query; /* FW don't care */
u8 seq;
u8 uc_d2b0_rev;
u8 ext_cid;
u8 s2d_index;
u8 ext_cid_ack;
u32 rsv[5];
} __packed __aligned(4);
/**
* struct mt76_connac2_mcu_uni_txd - mcu command descriptor for firmware v3
* @txd: hardware descriptor
* @len: total length not including txd
* @cid: command identifier
* @pkt_type: must be 0xa0 (cmd packet by long format)
* @frag_n: fragment number
* @seq: sequence number
* @checksum: 0 mean there is no checksum
* @s2d_index: index for command source and destination
* Definition | value | note
* CMD_S2D_IDX_H2N | 0x00 | command from HOST to WM
* CMD_S2D_IDX_C2N | 0x01 | command from WA to WM
* CMD_S2D_IDX_H2C | 0x02 | command from HOST to WA
* CMD_S2D_IDX_H2N_AND_H2C | 0x03 | command from HOST to WA and WM
*
* @option: command option
* BIT[0]: UNI_CMD_OPT_BIT_ACK
* set to 1 to request a fw reply
* if UNI_CMD_OPT_BIT_0_ACK is set and UNI_CMD_OPT_BIT_2_SET_QUERY
* is set, mcu firmware will send response event EID = 0x01
* (UNI_EVENT_ID_CMD_RESULT) to the host.
* BIT[1]: UNI_CMD_OPT_BIT_UNI_CMD
* 0: original command
* 1: unified command
* BIT[2]: UNI_CMD_OPT_BIT_SET_QUERY
* 0: QUERY command
* 1: SET command
*/
struct mt76_connac2_mcu_uni_txd {
__le32 txd[8];
/* DW1 */
__le16 len;
__le16 cid;
/* DW2 */
u8 rsv;
u8 pkt_type;
u8 frag_n;
u8 seq;
/* DW3 */
__le16 checksum;
u8 s2d_index;
u8 option;
/* DW4 */
u8 rsv1[4];
} __packed __aligned(4);
struct mt76_connac2_mcu_rxd {
__le32 rxd[6];
__le16 len;
__le16 pkt_type_id;
u8 eid;
u8 seq;
u8 rsv[2];
u8 ext_eid;
u8 rsv1[2];
u8 s2d_index;
};
struct mt76_connac2_patch_hdr {
char build_date[16];
char platform[4];
__be32 hw_sw_ver;
__be32 patch_ver;
__be16 checksum;
u16 rsv;
struct {
__be32 patch_ver;
__be32 subsys;
__be32 feature;
__be32 n_region;
__be32 crc;
u32 rsv[11];
} desc;
} __packed;
struct mt76_connac2_patch_sec {
__be32 type;
__be32 offs;
__be32 size;
union {
__be32 spec[13];
struct {
__be32 addr;
__be32 len;
__be32 sec_key_idx;
__be32 align_len;
u32 rsv[9];
} info;
};
} __packed;
struct mt76_connac2_fw_trailer {
u8 chip_id;
u8 eco_code;
u8 n_region;
u8 format_ver;
u8 format_flag;
u8 rsv[2];
char fw_ver[10];
char build_date[15];
__le32 crc;
} __packed;
struct mt76_connac2_fw_region {
__le32 decomp_crc;
__le32 decomp_len;
__le32 decomp_blk_sz;
u8 rsv[4];
__le32 addr;
__le32 len;
u8 feature_set;
u8 rsv1[15];
} __packed;
struct tlv {
__le16 tag;
__le16 len;
@ -1653,4 +1804,9 @@ int mt76_connac_mcu_set_pm(struct mt76_dev *dev, int band, int enter);
int mt76_connac_mcu_restart(struct mt76_dev *dev);
int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
u8 rx_sel, u8 val);
int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
const char *fw_wa);
int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name);
int mt76_connac2_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *wait_seq);
#endif /* __MT76_CONNAC_MCU_H */

View File

@ -156,7 +156,8 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key);
int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u16 queue, const struct ieee80211_tx_queue_params *params);
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params);
void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);

View File

@ -57,8 +57,11 @@ void mt76x02_mac_set_beacon(struct mt76x02_dev *dev,
int bcn_len = dev->beacon_ops->slot_size;
int bcn_addr = MT_BEACON_BASE + (bcn_len * dev->beacon_data_count);
if (!mt76x02_write_beacon(dev, bcn_addr, skb))
if (!mt76x02_write_beacon(dev, bcn_addr, skb)) {
if (!dev->beacon_data_count)
dev->beacon_hang_check++;
dev->beacon_data_count++;
}
dev_kfree_skb(skb);
}
EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon);
@ -74,6 +77,7 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
if (!dev->mt76.beacon_mask)
dev->tbtt_count = 0;
dev->beacon_hang_check = 0;
if (enable) {
dev->mt76.beacon_mask |= BIT(mvif->idx);
} else {

View File

@ -1044,10 +1044,9 @@ static void mt76x02_check_mac_err(struct mt76x02_dev *dev)
return;
}
if (++dev->beacon_hang_check < 10)
if (dev->beacon_hang_check < 10)
return;
dev->beacon_hang_check = 0;
} else {
u32 val = mt76_rr(dev, 0x10f4);
if (!(val & BIT(29)) || !(val & (BIT(7) | BIT(5))))
@ -1057,10 +1056,16 @@ static void mt76x02_check_mac_err(struct mt76x02_dev *dev)
dev_err(dev->mt76.dev, "MAC error detected\n");
mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
mt76x02_wait_for_txrx_idle(&dev->mt76);
if (!mt76x02_wait_for_txrx_idle(&dev->mt76)) {
dev_err(dev->mt76.dev, "MAC stop failed\n");
goto out;
}
dev->beacon_hang_check = 0;
mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
udelay(10);
out:
mt76_wr(dev, MT_MAC_SYS_CTRL,
MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
}

View File

@ -59,7 +59,8 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
struct ieee80211_vif *vif = info->control.vif;
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
mt76_tx_queue_skb(dev, q, skb, &mvif->group_wcid, NULL);
mt76_tx_queue_skb(dev, q, MT_TXQ_PSD, skb, &mvif->group_wcid,
NULL);
}
spin_unlock(&q->lock);
}

View File

@ -108,7 +108,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500,
MT_EP_OUT_INBAND_CMD);
if (ret)
return ret;
goto out;
if (wait_resp)
ret = mt76x02u_mcu_wait_resp(dev, seq);

View File

@ -487,7 +487,8 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
EXPORT_SYMBOL_GPL(mt76x02_set_key);
int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u16 queue, const struct ieee80211_tx_queue_params *params)
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mt76x02_dev *dev = hw->priv;
u8 cw_min = 5, cw_max = 10, qid;

View File

@ -976,7 +976,7 @@ mt7915_rf_regval_get(void *data, u64 *val)
if (ret)
return ret;
*val = le32_to_cpu(regval);
*val = regval;
return 0;
}
@ -985,8 +985,9 @@ static int
mt7915_rf_regval_set(void *data, u64 val)
{
struct mt7915_dev *dev = data;
u32 val32 = val;
return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, (u32 *)&val, true);
return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, &val32, true);
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7915_rf_regval_get,

View File

@ -9,29 +9,14 @@ static int
mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base)
{
struct mt7915_dev *dev = phy->dev;
int i, err;
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
ring_base = MT_WED_TX_RING_BASE;
idx -= MT_TXQ_ID(0);
}
err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base,
MT_WED_Q_TX(idx));
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;
}
static void
mt7915_tx_cleanup(struct mt7915_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);
return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc, ring_base,
MT_WED_Q_TX(idx));
}
static int mt7915_poll_tx(struct napi_struct *napi, int budget)
@ -40,8 +25,7 @@ static int mt7915_poll_tx(struct napi_struct *napi, int budget)
dev = container_of(napi, struct mt7915_dev, mt76.tx_napi);
mt7915_tx_cleanup(dev);
mt76_connac_tx_cleanup(&dev->mt76);
if (napi_complete_done(napi, 0))
mt7915_irq_enable(dev, MT_INT_TX_DONE_MCU);
@ -65,8 +49,8 @@ static void mt7915_dma_config(struct mt7915_dev *dev)
RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0, MT7915_RXQ_BAND0);
RXQ_CONFIG(MT_RXQ_MCU, WFDMA1, MT_INT_RX_DONE_WM, MT7915_RXQ_MCU_WM);
RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA1, MT_INT_RX_DONE_WA, MT7915_RXQ_MCU_WA);
RXQ_CONFIG(MT_RXQ_EXT, WFDMA0, MT_INT_RX_DONE_BAND1, MT7915_RXQ_BAND1);
RXQ_CONFIG(MT_RXQ_EXT_WA, WFDMA1, MT_INT_RX_DONE_WA_EXT, MT7915_RXQ_MCU_WA_EXT);
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7915_RXQ_BAND1);
RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA1, MT_INT_RX_DONE_WA_EXT, MT7915_RXQ_MCU_WA_EXT);
RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA1, MT_INT_RX_DONE_WA_MAIN, MT7915_RXQ_MCU_WA);
TXQ_CONFIG(0, WFDMA1, MT_INT_TX_DONE_BAND0, MT7915_TXQ_BAND0);
TXQ_CONFIG(1, WFDMA1, MT_INT_TX_DONE_BAND1, MT7915_TXQ_BAND1);
@ -77,8 +61,8 @@ static void mt7915_dma_config(struct mt7915_dev *dev)
RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0_MT7916, MT7916_RXQ_BAND0);
RXQ_CONFIG(MT_RXQ_MCU, WFDMA0, MT_INT_RX_DONE_WM, MT7916_RXQ_MCU_WM);
RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_RX_DONE_WA, MT7916_RXQ_MCU_WA);
RXQ_CONFIG(MT_RXQ_EXT, WFDMA0, MT_INT_RX_DONE_BAND1_MT7916, MT7916_RXQ_BAND1);
RXQ_CONFIG(MT_RXQ_EXT_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT_MT7916, MT7916_RXQ_MCU_WA_EXT);
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1_MT7916, MT7916_RXQ_BAND1);
RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT_MT7916, MT7916_RXQ_MCU_WA_EXT);
RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN_MT7916, MT7916_RXQ_MCU_WA_MAIN);
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7915_TXQ_BAND0);
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7915_TXQ_BAND1);
@ -100,24 +84,33 @@ static void __mt7915_dma_prefetch(struct mt7915_dev *dev, u32 ofs)
mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0xc0, 0x4));
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0x100, 0x4));
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(0x140, 0x4));
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(0x180, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU) + ofs,
PREFETCH(0x140, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU_WA) + ofs,
PREFETCH(0x180, 0x4));
if (!is_mt7915(&dev->mt76)) {
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(0x1c0, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN_WA) + ofs,
PREFETCH(0x1c0, 0x4));
base = 0x40;
}
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_EXT_WA) + ofs, PREFETCH(0x1c0 + base, 0x4));
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x200 + base, 0x4));
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_EXT) + ofs, PREFETCH(0x240 + base, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1_WA) + ofs,
PREFETCH(0x1c0 + base, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs,
PREFETCH(0x200 + base, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1) + ofs,
PREFETCH(0x240 + base, 0x4));
/* for mt7915, the ring which is next the last
* used ring must be initialized.
*/
if (is_mt7915(&dev->mt76)) {
ofs += 0x4;
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0x140, 0x0));
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_EXT_WA) + ofs, PREFETCH(0x200 + base, 0x0));
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_EXT) + ofs, PREFETCH(0x280 + base, 0x0));
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs,
PREFETCH(0x140, 0x0));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1_WA) + ofs,
PREFETCH(0x200 + base, 0x0));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND1) + ofs,
PREFETCH(0x280 + base, 0x0));
}
}
@ -455,20 +448,20 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
if (dev->dbdc_support || dev->phy.band_idx) {
/* rx data queue for band1 */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT],
MT_RXQ_ID(MT_RXQ_EXT),
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1],
MT_RXQ_ID(MT_RXQ_BAND1),
MT7915_RX_RING_SIZE,
MT_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_EXT) + hif1_ofs);
MT_RXQ_RING_BASE(MT_RXQ_BAND1) + hif1_ofs);
if (ret)
return ret;
/* tx free notify event from WA for band1 */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT_WA],
MT_RXQ_ID(MT_RXQ_EXT_WA),
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA],
MT_RXQ_ID(MT_RXQ_BAND1_WA),
MT7915_RX_MCU_RING_SIZE,
MT_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_EXT_WA) + hif1_ofs);
MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs);
if (ret)
return ret;
}

View File

@ -365,18 +365,24 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
hw->max_tx_fragments = 4;
if (phy->mt76->cap.has_2ghz)
if (phy->mt76->cap.has_2ghz) {
phy->mt76->sband_2g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_MAX_AMSDU;
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_4;
}
if (phy->mt76->cap.has_5ghz) {
phy->mt76->sband_5g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_MAX_AMSDU;
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
IEEE80211_HT_MPDU_DENSITY_4;
if (is_mt7915(&dev->mt76)) {
phy->mt76->sband_5g.sband.vht_cap.cap |=
@ -498,7 +504,7 @@ mt7915_alloc_ext_phy(struct mt7915_dev *dev)
if (!dev->dbdc_support)
return NULL;
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops);
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops, MT_BAND1);
if (!mphy)
return ERR_PTR(-ENOMEM);
@ -752,9 +758,10 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_dev *dev,
elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;
c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US;
if (!is_mt7915(&dev->mt76))
c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
elem->phy_cap_info[2] |= c;
c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
@ -978,7 +985,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_8,
cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
@ -1031,7 +1038,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
{
struct mt7915_phy *phy = mt7915_ext_phy(dev);
struct mt76_phy *mphy = dev->mt76.phy2;
struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];
if (!phy)
return;

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,8 @@
#ifndef __MT7915_MAC_H
#define __MT7915_MAC_H
#include "../mt76_connac2_mac.h"
#define MT_CT_PARSE_LEN 72
#define MT_CT_DMA_BUF_NUM 2
@ -27,289 +29,6 @@ enum rx_pkt_type {
PKT_TYPE_TXRX_NOTIFY_V0 = 0x18,
};
/* RXD DW1 */
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0)
#define MT_RXD1_NORMAL_GROUP_1 BIT(11)
#define MT_RXD1_NORMAL_GROUP_2 BIT(12)
#define MT_RXD1_NORMAL_GROUP_3 BIT(13)
#define MT_RXD1_NORMAL_GROUP_4 BIT(14)
#define MT_RXD1_NORMAL_GROUP_5 BIT(15)
#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16)
#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
#define MT_RXD1_NORMAL_CM BIT(23)
#define MT_RXD1_NORMAL_CLM BIT(24)
#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
#define MT_RXD1_NORMAL_FCS_ERR BIT(27)
#define MT_RXD1_NORMAL_BAND_IDX BIT(28)
#define MT_RXD1_NORMAL_SPP_EN BIT(29)
#define MT_RXD1_NORMAL_ADD_OM BIT(30)
#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
/* RXD DW2 */
#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
#define MT_RXD2_NORMAL_CO_ANT BIT(6)
#define MT_RXD2_NORMAL_BF_CQI BIT(7)
#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
#define MT_RXD2_NORMAL_HDR_TRANS BIT(13)
#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14)
#define MT_RXD2_NORMAL_TID GENMASK(19, 16)
#define MT_RXD2_NORMAL_MU_BAR BIT(21)
#define MT_RXD2_NORMAL_SW_BIT BIT(22)
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
#define MT_RXD2_NORMAL_FRAG BIT(27)
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
#define MT_RXD2_NORMAL_NDATA BIT(29)
#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
/* RXD DW3 */
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
#define MT_RXD3_NORMAL_U2M BIT(0)
#define MT_RXD3_NORMAL_HTC_VLD BIT(0)
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19)
#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
#define MT_RXD3_NORMAL_AMSDU BIT(22)
#define MT_RXD3_NORMAL_MESH BIT(23)
#define MT_RXD3_NORMAL_MHCP BIT(24)
#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25)
#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26)
#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27)
#define MT_RXD3_NORMAL_MORE BIT(28)
#define MT_RXD3_NORMAL_UNWANT BIT(29)
#define MT_RXD3_NORMAL_RX_DROP BIT(30)
#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
/* RXD DW4 */
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9)
#define MT_RXD4_NORMAL_CLS BIT(10)
#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11)
#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13)
#define MT_RXD4_NORMAL_WOL GENMASK(18, 14)
#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19)
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
#define MT_RXV_HDR_BAND_IDX BIT(24)
/* RXD GROUP4 */
#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0)
#define MT_RXD6_TA_LO GENMASK(31, 16)
#define MT_RXD7_TA_HI GENMASK(31, 0)
#define MT_RXD8_SEQ_CTRL GENMASK(15, 0)
#define MT_RXD8_QOS_CTL GENMASK(31, 16)
#define MT_RXD9_HT_CONTROL GENMASK(31, 0)
/* P-RXV */
#define MT_PRXV_TX_RATE GENMASK(6, 0)
#define MT_PRXV_TX_DCM BIT(4)
#define MT_PRXV_TX_ER_SU_106T BIT(5)
#define MT_PRXV_NSTS GENMASK(9, 7)
#define MT_PRXV_TXBF BIT(10)
#define MT_PRXV_HT_AD_CODE BIT(11)
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
#define MT_PRXV_RCPI3 GENMASK(31, 24)
#define MT_PRXV_RCPI2 GENMASK(23, 16)
#define MT_PRXV_RCPI1 GENMASK(15, 8)
#define MT_PRXV_RCPI0 GENMASK(7, 0)
#define MT_PRXV_HT_SHORT_GI GENMASK(16, 15)
#define MT_PRXV_HT_STBC GENMASK(23, 22)
#define MT_PRXV_TX_MODE GENMASK(27, 24)
#define MT_PRXV_FRAME_MODE GENMASK(14, 12)
#define MT_PRXV_DCM BIT(17)
#define MT_PRXV_NUM_RX BIT(20, 18)
/* C-RXV */
#define MT_CRXV_HT_STBC GENMASK(1, 0)
#define MT_CRXV_TX_MODE GENMASK(7, 4)
#define MT_CRXV_FRAME_MODE GENMASK(10, 8)
#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13)
#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
#define MT_CRXV_HE_PE_DISAMBIG BIT(23)
#define MT_CRXV_HE_NUM_USER GENMASK(30, 24)
#define MT_CRXV_HE_UPLINK BIT(31)
#define MT_CRXV_HE_RU0 GENMASK(7, 0)
#define MT_CRXV_HE_RU1 GENMASK(15, 8)
#define MT_CRXV_HE_RU2 GENMASK(23, 16)
#define MT_CRXV_HE_RU3 GENMASK(31, 24)
#define MT_CRXV_HE_MU_AID GENMASK(30, 20)
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0)
#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6)
#define MT_CRXV_HE_BEAM_CHNG BIT(13)
#define MT_CRXV_HE_DOPPLER BIT(16)
#define MT_CRXV_SNR GENMASK(18, 13)
#define MT_CRXV_FOE_LO GENMASK(31, 19)
#define MT_CRXV_FOE_HI GENMASK(6, 0)
#define MT_CRXV_FOE_SHIFT 13
enum tx_header_format {
MT_HDR_FORMAT_802_3,
MT_HDR_FORMAT_CMD,
MT_HDR_FORMAT_802_11,
MT_HDR_FORMAT_802_11_EXT,
};
enum tx_pkt_type {
MT_TX_TYPE_CT,
MT_TX_TYPE_SF,
MT_TX_TYPE_CMD,
MT_TX_TYPE_FW,
};
enum tx_port_idx {
MT_TX_PORT_IDX_LMAC,
MT_TX_PORT_IDX_MCU
};
enum tx_mcu_port_q_idx {
MT_TX_MCU_PORT_RX_Q0 = 0x20,
MT_TX_MCU_PORT_RX_Q1,
MT_TX_MCU_PORT_RX_Q2,
MT_TX_MCU_PORT_RX_Q3,
MT_TX_MCU_PORT_RX_FWDL = 0x3e
};
#define MT_CT_INFO_APPLY_TXD BIT(0)
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
#define MT_CT_INFO_MGMT_FRAME BIT(2)
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
#define MT_CT_INFO_HSR2_TX BIT(4)
#define MT_CT_INFO_FROM_HOST BIT(7)
#define MT_TXD_SIZE (8 * 4)
#define MT_TXD0_Q_IDX GENMASK(31, 25)
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
#define MT_TXD1_LONG_FORMAT BIT(31)
#define MT_TXD1_TGID BIT(30)
#define MT_TXD1_OWN_MAC GENMASK(29, 24)
#define MT_TXD1_AMSDU BIT(23)
#define MT_TXD1_TID GENMASK(22, 20)
#define MT_TXD1_HDR_PAD GENMASK(19, 18)
#define MT_TXD1_HDR_FORMAT GENMASK(17, 16)
#define MT_TXD1_HDR_INFO GENMASK(15, 11)
#define MT_TXD1_ETH_802_3 BIT(15)
#define MT_TXD1_VTA BIT(10)
#define MT_TXD1_WLAN_IDX GENMASK(9, 0)
#define MT_TXD2_FIX_RATE BIT(31)
#define MT_TXD2_FIXED_RATE BIT(30)
#define MT_TXD2_POWER_OFFSET GENMASK(29, 24)
#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16)
#define MT_TXD2_FRAG GENMASK(15, 14)
#define MT_TXD2_HTC_VLD BIT(13)
#define MT_TXD2_DURATION BIT(12)
#define MT_TXD2_BIP BIT(11)
#define MT_TXD2_MULTICAST BIT(10)
#define MT_TXD2_RTS BIT(9)
#define MT_TXD2_SOUNDING BIT(8)
#define MT_TXD2_NDPA BIT(7)
#define MT_TXD2_NDP BIT(6)
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
#define MT_TXD3_SN_VALID BIT(31)
#define MT_TXD3_PN_VALID BIT(30)
#define MT_TXD3_SW_POWER_MGMT BIT(29)
#define MT_TXD3_BA_DISABLE BIT(28)
#define MT_TXD3_SEQ GENMASK(27, 16)
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
#define MT_TXD3_TIMING_MEASURE BIT(5)
#define MT_TXD3_DAS BIT(4)
#define MT_TXD3_EEOSP BIT(3)
#define MT_TXD3_EMRD BIT(2)
#define MT_TXD3_PROTECT_FRAME BIT(1)
#define MT_TXD3_NO_ACK BIT(0)
#define MT_TXD4_PN_LOW GENMASK(31, 0)
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
#define MT_TXD5_MD BIT(15)
#define MT_TXD5_ADD_BA BIT(14)
#define MT_TXD5_TX_STATUS_HOST BIT(10)
#define MT_TXD5_TX_STATUS_MCU BIT(9)
#define MT_TXD5_TX_STATUS_FMT BIT(8)
#define MT_TXD5_PID GENMASK(7, 0)
#define MT_TXD6_TX_IBF BIT(31)
#define MT_TXD6_TX_EBF BIT(30)
#define MT_TXD6_TX_RATE GENMASK(29, 16)
#define MT_TXD6_SGI GENMASK(15, 14)
#define MT_TXD6_HELTF GENMASK(13, 12)
#define MT_TXD6_LDPC BIT(11)
#define MT_TXD6_SPE_ID_IDX BIT(10)
#define MT_TXD6_ANT_ID GENMASK(7, 4)
#define MT_TXD6_DYN_BW BIT(3)
#define MT_TXD6_FIXED_BW BIT(2)
#define MT_TXD6_BW GENMASK(1, 0)
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
#define MT_TXD7_UDP_TCP_SUM BIT(29)
#define MT_TXD7_IP_SUM BIT(28)
#define MT_TXD7_TYPE GENMASK(21, 20)
#define MT_TXD7_SUB_TYPE GENMASK(19, 16)
#define MT_TXD7_PSE_FID GENMASK(27, 16)
#define MT_TXD7_SPE_IDX GENMASK(15, 11)
#define MT_TXD7_HW_AMSDU BIT(10)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
#define MT_TX_RATE_STBC BIT(13)
#define MT_TX_RATE_NSS GENMASK(12, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
#define MT_TX_RATE_DCM BIT(4)
/* VHT/HE only use bits 0-3 */
#define MT_TX_RATE_IDX GENMASK(5, 0)
#define MT_TXP_MAX_BUF_NUM 6
struct mt7915_txp {
__le16 flags;
__le16 token;
u8 bss_idx;
__le16 rept_wds_wcid;
u8 nbuf;
__le32 buf[MT_TXP_MAX_BUF_NUM];
__le16 len[MT_TXP_MAX_BUF_NUM];
} __packed __aligned(4);
struct mt7915_tx_free {
__le16 rx_byte_cnt;
__le16 ctrl;
__le32 txd;
__le32 info[];
} __packed __aligned(4);
#define MT_TX_FREE_VER GENMASK(18, 16)
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0)
@ -324,41 +43,6 @@ struct mt7915_tx_free {
/* will support this field in further revision */
#define MT_TX_FREE_RATE GENMASK(13, 0)
#define MT_TXS0_FIXED_RATE BIT(31)
#define MT_TXS0_BW GENMASK(30, 29)
#define MT_TXS0_TID GENMASK(28, 26)
#define MT_TXS0_AMPDU BIT(25)
#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
#define MT_TXS0_BA_ERROR BIT(22)
#define MT_TXS0_PS_FLAG BIT(21)
#define MT_TXS0_TXOP_TIMEOUT BIT(20)
#define MT_TXS0_BIP_ERROR BIT(19)
#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
#define MT_TXS0_RTS_TIMEOUT BIT(17)
#define MT_TXS0_ACK_TIMEOUT BIT(16)
#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
#define MT_TXS0_TX_STATUS_HOST BIT(15)
#define MT_TXS0_TX_STATUS_MCU BIT(14)
#define MT_TXS0_TX_RATE GENMASK(13, 0)
#define MT_TXS1_SEQNO GENMASK(31, 20)
#define MT_TXS1_RESP_RATE GENMASK(19, 16)
#define MT_TXS1_RXV_SEQNO GENMASK(15, 8)
#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0)
#define MT_TXS2_BF_STATUS GENMASK(31, 30)
#define MT_TXS2_LAST_TX_RATE GENMASK(29, 27)
#define MT_TXS2_SHARED_ANTENNA BIT(26)
#define MT_TXS2_WCID GENMASK(25, 16)
#define MT_TXS2_TX_DELAY GENMASK(15, 0)
#define MT_TXS3_PID GENMASK(31, 24)
#define MT_TXS3_ANT_ID GENMASK(23, 0)
#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
#define MT_TXS5_F0_FINAL_MPDU BIT(31)
#define MT_TXS5_F0_QOS BIT(30)
#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
@ -414,17 +98,4 @@ struct mt7915_dfs_radar_spec {
struct mt7915_dfs_pattern radar_pattern[16];
};
static inline struct mt7915_txp *
mt7915_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
{
u8 *txwi;
if (!t)
return NULL;
txwi = mt76_get_txwi_ptr(dev, t);
return (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
}
#endif

View File

@ -227,7 +227,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
INIT_LIST_HEAD(&mvif->sta.rc_list);
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.ext_phy = ext_phy;
mvif->sta.wcid.phy_idx = ext_phy;
mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
mt76_packet_id_init(&mvif->sta.wcid);
@ -235,7 +235,6 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
mt7915_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 = idx;
@ -251,6 +250,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
mt7915_mcu_add_bss_info(phy, vif, true);
mt7915_mcu_add_sta(dev, vif, NULL, true);
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
out:
mutex_unlock(&dev->mt76.mutex);
@ -478,7 +478,8 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
}
static int
mt7915_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
mt7915_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
@ -660,7 +661,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
msta->wcid.ext_phy = ext_phy;
msta->wcid.phy_idx = ext_phy;
msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
msta->jiffies = jiffies;
@ -1146,8 +1147,15 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
"rx_fifo_full_cnt",
"rx_mpdu_cnt",
"channel_idle_cnt",
"primary_cca_busy_time",
"secondary_cca_busy_time",
"primary_energy_detect_time",
"cck_mdrdy_time",
"ofdm_mdrdy_time",
"green_mdrdy_time",
"rx_vector_mismatch_cnt",
"rx_delimiter_fail_cnt",
"rx_mrdy_cnt",
"rx_len_mismatch_cnt",
"rx_ampdu_cnt",
"rx_ampdu_bytes_cnt",
@ -1287,8 +1295,15 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
data[ei++] = mib->rx_fifo_full_cnt;
data[ei++] = mib->rx_mpdu_cnt;
data[ei++] = mib->channel_idle_cnt;
data[ei++] = mib->primary_cca_busy_time;
data[ei++] = mib->secondary_cca_busy_time;
data[ei++] = mib->primary_energy_detect_time;
data[ei++] = mib->cck_mdrdy_time;
data[ei++] = mib->ofdm_mdrdy_time;
data[ei++] = mib->green_mdrdy_time;
data[ei++] = mib->rx_vector_mismatch_cnt;
data[ei++] = mib->rx_delimiter_fail_cnt;
data[ei++] = mib->rx_mrdy_cnt;
data[ei++] = mib->rx_len_mismatch_cnt;
data[ei++] = mib->rx_ampdu_cnt;
data[ei++] = mib->rx_ampdu_bytes_cnt;

View File

@ -1,69 +1,12 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
#include <linux/firmware.h>
#include <linux/fs.h>
#include "mt7915.h"
#include "mcu.h"
#include "mac.h"
#include "eeprom.h"
struct mt7915_patch_hdr {
char build_date[16];
char platform[4];
__be32 hw_sw_ver;
__be32 patch_ver;
__be16 checksum;
u16 reserved;
struct {
__be32 patch_ver;
__be32 subsys;
__be32 feature;
__be32 n_region;
__be32 crc;
u32 reserved[11];
} desc;
} __packed;
struct mt7915_patch_sec {
__be32 type;
__be32 offs;
__be32 size;
union {
__be32 spec[13];
struct {
__be32 addr;
__be32 len;
__be32 sec_key_idx;
__be32 align_len;
u32 reserved[9];
} info;
};
} __packed;
struct mt7915_fw_trailer {
u8 chip_id;
u8 eco_code;
u8 n_region;
u8 format_ver;
u8 format_flag;
u8 reserved[2];
char fw_ver[10];
char build_date[15];
u32 crc;
} __packed;
struct mt7915_fw_region {
__le32 decomp_crc;
__le32 decomp_len;
__le32 decomp_blk_sz;
u8 reserved[4];
__le32 addr;
__le32 len;
u8 feature_set;
u8 reserved1[15];
} __packed;
#define fw_name(_dev, name, ...) ({ \
char *_fw; \
switch (mt76_chip(&(_dev)->mt76)) { \
@ -207,7 +150,7 @@ static int
mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
struct sk_buff *skb, int seq)
{
struct mt7915_mcu_rxd *rxd;
struct mt76_connac2_mcu_rxd *rxd;
int ret = 0;
if (!skb) {
@ -216,7 +159,7 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
return -ETIMEDOUT;
}
rxd = (struct mt7915_mcu_rxd *)skb->data;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
if (seq != rxd->seq)
return -EAGAIN;
@ -227,7 +170,7 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
skb_pull(skb, sizeof(*rxd) + 4);
ret = le32_to_cpu(*(__le32 *)skb->data);
} else {
skb_pull(skb, sizeof(struct mt7915_mcu_rxd));
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
}
return ret;
@ -238,69 +181,20 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *wait_seq)
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
struct mt7915_mcu_txd *mcu_txd;
enum mt76_mcuq_id qid;
__le32 *txd;
u32 val;
u8 seq;
int ret;
/* TODO: make dynamic based on msg type */
mdev->mcu.timeout = 20 * HZ;
ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, wait_seq);
if (ret)
return ret;
seq = ++dev->mt76.mcu.msg_seq & 0xf;
if (!seq)
seq = ++dev->mt76.mcu.msg_seq & 0xf;
if (cmd == MCU_CMD(FW_SCATTER)) {
if (cmd == MCU_CMD(FW_SCATTER))
qid = MT_MCUQ_FWDL;
goto exit;
}
mcu_txd = (struct mt7915_mcu_txd *)skb_push(skb, sizeof(*mcu_txd));
if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
else if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
qid = MT_MCUQ_WA;
else
qid = MT_MCUQ_WM;
txd = mcu_txd->txd;
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |
FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) |
FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0);
txd[0] = cpu_to_le32(val);
val = MT_TXD1_LONG_FORMAT |
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD);
txd[1] = cpu_to_le32(val);
mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd));
mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU,
MT_TX_MCU_PORT_RX_Q0));
mcu_txd->pkt_type = MCU_PKT_ID;
mcu_txd->seq = seq;
mcu_txd->cid = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
mcu_txd->set_query = MCU_Q_NA;
mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd);
if (mcu_txd->ext_cid) {
mcu_txd->ext_cid_ack = 1;
/* do not use Q_SET for efuse */
if (cmd & __MCU_CMD_FIELD_QUERY)
mcu_txd->set_query = MCU_Q_QUERY;
else
mcu_txd->set_query = MCU_Q_SET;
}
if (cmd & __MCU_CMD_FIELD_WA)
mcu_txd->s2d_index = MCU_S2D_H2C;
else
mcu_txd->s2d_index = MCU_S2D_H2N;
exit:
if (wait_seq)
*wait_seq = seq;
return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[qid], skb, 0);
}
@ -334,8 +228,8 @@ mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb)
c = (struct mt7915_mcu_csa_notify *)skb->data;
if ((c->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if ((c->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
@ -353,8 +247,8 @@ mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb)
if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE)
return;
if ((t->ctrl.band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if ((t->ctrl.band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
phy = (struct mt7915_phy *)mphy->priv;
phy->throttle_state = t->ctrl.duty.duty_cycle;
@ -368,8 +262,8 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
r = (struct mt7915_mcu_rdd_report *)skb->data;
if ((r->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if ((r->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
if (r->band_idx == MT_RX_SEL2)
cfg80211_background_radar_event(mphy->hw->wiphy,
@ -383,10 +277,12 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
static void
mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb)
{
struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
const char *data = (char *)&rxd[1];
const char *type;
struct mt76_connac2_mcu_rxd *rxd;
int len = skb->len - sizeof(*rxd);
const char *data, *type;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
data = (char *)&rxd[1];
switch (rxd->s2d_index) {
case 0:
@ -423,8 +319,8 @@ mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb)
b = (struct mt7915_mcu_bcc_notify *)skb->data;
if ((b->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if ((b->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
@ -434,8 +330,9 @@ mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb)
static void
mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
{
struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
struct mt76_connac2_mcu_rxd *rxd;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
switch (rxd->ext_eid) {
case MCU_EXT_EVENT_THERMAL_PROTECT:
mt7915_mcu_rx_thermal_notify(dev, skb);
@ -460,8 +357,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
static void
mt7915_mcu_rx_unsolicited_event(struct mt7915_dev *dev, struct sk_buff *skb)
{
struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
struct mt76_connac2_mcu_rxd *rxd;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
switch (rxd->eid) {
case MCU_EVENT_EXT:
mt7915_mcu_rx_ext_event(dev, skb);
@ -474,8 +372,9 @@ mt7915_mcu_rx_unsolicited_event(struct mt7915_dev *dev, struct sk_buff *skb)
void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
{
struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
struct mt76_connac2_mcu_rxd *rxd;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
@ -927,8 +826,8 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
}
static void
mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
struct ieee80211_sta *sta, struct ieee80211_vif *vif)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
@ -946,7 +845,8 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||
mvif->cap.vht_mu_ebfer ||
mvif->cap.vht_mu_ebfee;
muru->cfg.mimo_ul_en = true;
if (!is_mt7915(&dev->mt76))
muru->cfg.mimo_ul_en = true;
muru->cfg.ofdma_dl_en = true;
if (sta->deflink.vht_cap.vht_supported)
@ -1720,7 +1620,8 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
return PTR_ERR(skb);
/* starec basic */
mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable, true);
mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable,
!rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
if (!enable)
goto out;
@ -1748,7 +1649,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
/* starec he */
mt7915_mcu_sta_he_tlv(skb, sta, vif);
/* starec muru */
mt7915_mcu_sta_muru_tlv(skb, sta, vif);
mt7915_mcu_sta_muru_tlv(dev, skb, sta, vif);
/* starec bfee */
mt7915_mcu_sta_bfee_tlv(dev, skb, vif, sta);
}
@ -1910,8 +1811,8 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
}
buf = (u8 *)tlv + sizeof(*cont);
mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
BSS_CHANGED_BEACON);
mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,
0, BSS_CHANGED_BEACON);
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
}
@ -2031,12 +1932,17 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
info->control.vif = vif;
info->band = band;
if (ext_phy)
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
len = (len & 0x3) ? ((len | 0x3) + 1) : len;
if (len > (MT7915_MAX_BSS_OFFLOAD_SIZE - rskb->len)) {
dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
dev_kfree_skb(skb);
return;
}
tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
len, &bcn->sub_ntlv, &bcn->len);
discov = (struct bss_info_inband_discovery *)tlv;
@ -2049,8 +1955,8 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
buf = (u8 *)tlv + sizeof(*discov);
mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
changed);
mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,
0, changed);
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
dev_kfree_skb(skb);
@ -2059,7 +1965,6 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int en, u32 changed)
{
#define MAX_BEACON_SIZE 512
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
@ -2068,7 +1973,7 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct sk_buff *skb, *rskb;
struct tlv *tlv;
struct bss_info_bcn *bcn;
int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE;
int len = MT7915_MAX_BSS_OFFLOAD_SIZE;
bool ext_phy = phy != &dev->phy;
if (vif->bss_conf.nontransmitted)
@ -2090,16 +1995,14 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (!skb)
return -EINVAL;
if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) {
if (skb->len > MT7915_MAX_BEACON_SIZE - MT_TXD_SIZE) {
dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
dev_kfree_skb(skb);
return -EINVAL;
}
if (ext_phy) {
info = IEEE80211_SKB_CB(skb);
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
}
info = IEEE80211_SKB_CB(skb);
info->hw_queue = FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
mt7915_mcu_beacon_check_caps(phy, vif, skb);
@ -2134,203 +2037,6 @@ static int mt7915_driver_own(struct mt7915_dev *dev, u8 band)
return 0;
}
static int mt7915_load_patch(struct mt7915_dev *dev)
{
const struct mt7915_patch_hdr *hdr;
const struct firmware *fw = NULL;
int i, ret, sem;
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, 1);
switch (sem) {
case PATCH_IS_DL:
return 0;
case PATCH_NOT_DL_SEM_SUCCESS:
break;
default:
dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");
return -EAGAIN;
}
ret = request_firmware(&fw, fw_name_var(dev, ROM_PATCH),
dev->mt76.dev);
if (ret)
goto out;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->mt76.dev, "Invalid firmware\n");
ret = -EINVAL;
goto out;
}
hdr = (const struct mt7915_patch_hdr *)(fw->data);
dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
struct mt7915_patch_sec *sec;
const u8 *dl;
u32 len, addr;
sec = (struct mt7915_patch_sec *)(fw->data + sizeof(*hdr) +
i * sizeof(*sec));
if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
PATCH_SEC_TYPE_INFO) {
ret = -EINVAL;
goto out;
}
addr = be32_to_cpu(sec->info.addr);
len = be32_to_cpu(sec->info.len);
dl = fw->data + be32_to_cpu(sec->offs);
ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
DL_MODE_NEED_RSP);
if (ret) {
dev_err(dev->mt76.dev, "Download request failed\n");
goto out;
}
ret = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
dl, len, 4096);
if (ret) {
dev_err(dev->mt76.dev, "Failed to send patch\n");
goto out;
}
}
ret = mt76_connac_mcu_start_patch(&dev->mt76);
if (ret)
dev_err(dev->mt76.dev, "Failed to start patch\n");
out:
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, 0);
switch (sem) {
case PATCH_REL_SEM_SUCCESS:
break;
default:
ret = -EAGAIN;
dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");
break;
}
release_firmware(fw);
return ret;
}
static int
mt7915_mcu_send_ram_firmware(struct mt7915_dev *dev,
const struct mt7915_fw_trailer *hdr,
const u8 *data, bool is_wa)
{
int i, offset = 0;
u32 override = 0, option = 0;
for (i = 0; i < hdr->n_region; i++) {
const struct mt7915_fw_region *region;
int err;
u32 len, addr, mode;
region = (const struct mt7915_fw_region *)((const u8 *)hdr -
(hdr->n_region - i) * sizeof(*region));
mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
region->feature_set, is_wa);
len = le32_to_cpu(region->len);
addr = le32_to_cpu(region->addr);
if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR)
override = addr;
err = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
mode);
if (err) {
dev_err(dev->mt76.dev, "Download request failed\n");
return err;
}
err = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
data + offset, len, 4096);
if (err) {
dev_err(dev->mt76.dev, "Failed to send firmware.\n");
return err;
}
offset += len;
}
if (override)
option |= FW_START_OVERRIDE;
if (is_wa)
option |= FW_START_WORKING_PDA_CR4;
return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
}
static int mt7915_load_ram(struct mt7915_dev *dev)
{
const struct mt7915_fw_trailer *hdr;
const struct firmware *fw;
int ret;
ret = request_firmware(&fw, fw_name_var(dev, FIRMWARE_WM),
dev->mt76.dev);
if (ret)
return ret;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->mt76.dev, "Invalid firmware\n");
ret = -EINVAL;
goto out;
}
hdr = (const struct mt7915_fw_trailer *)(fw->data + fw->size -
sizeof(*hdr));
dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
ret = mt7915_mcu_send_ram_firmware(dev, hdr, fw->data, false);
if (ret) {
dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
goto out;
}
release_firmware(fw);
ret = request_firmware(&fw, fw_name(dev, FIRMWARE_WA),
dev->mt76.dev);
if (ret)
return ret;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->mt76.dev, "Invalid firmware\n");
ret = -EINVAL;
goto out;
}
hdr = (const struct mt7915_fw_trailer *)(fw->data + fw->size -
sizeof(*hdr));
dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
ret = mt7915_mcu_send_ram_firmware(dev, hdr, fw->data, true);
if (ret) {
dev_err(dev->mt76.dev, "Failed to start WA firmware\n");
goto out;
}
snprintf(dev->mt76.hw->wiphy->fw_version,
sizeof(dev->mt76.hw->wiphy->fw_version),
"%.10s-%.15s", hdr->fw_ver, hdr->build_date);
out:
release_firmware(fw);
return ret;
}
static int
mt7915_firmware_state(struct mt7915_dev *dev, bool wa)
{
@ -2361,11 +2067,12 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)
}
}
ret = mt7915_load_patch(dev);
ret = mt76_connac2_load_patch(&dev->mt76, fw_name_var(dev, ROM_PATCH));
if (ret)
return ret;
ret = mt7915_load_ram(dev);
ret = mt76_connac2_load_ram(&dev->mt76, fw_name_var(dev, FIRMWARE_WM),
fw_name(dev, FIRMWARE_WA));
if (ret)
return ret;
@ -2528,7 +2235,7 @@ mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)
int mt7915_mcu_init(struct mt7915_dev *dev)
{
static const struct mt76_mcu_ops mt7915_mcu_ops = {
.headroom = sizeof(struct mt7915_mcu_txd),
.headroom = sizeof(struct mt76_connac2_mcu_txd),
.mcu_skb_send_msg = mt7915_mcu_send_message,
.mcu_parse_response = mt7915_mcu_parse_response,
.mcu_restart = mt76_connac_mcu_restart,
@ -2685,7 +2392,7 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif)
struct edca *e = &req.edca[ac];
e->set = WMM_PARAM_SET;
e->queue = ac + mvif->mt76.wmm_idx * MT7915_MAX_WMM_SETS;
e->queue = ac + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
e->aifs = q->aifs;
e->txop = cpu_to_le16(q->txop);

View File

@ -6,25 +6,6 @@
#include "../mt76_connac_mcu.h"
struct mt7915_mcu_txd {
__le32 txd[8];
__le16 len;
__le16 pq_id;
u8 cid;
u8 pkt_type;
u8 set_query; /* FW don't care */
u8 seq;
u8 uc_d2b0_rev;
u8 ext_cid;
u8 s2d_index;
u8 ext_cid_ack;
u32 reserved[5];
} __packed __aligned(4);
enum {
MCU_ATE_SET_TRX = 0x1,
MCU_ATE_SET_FREQ_OFFSET = 0xa,
@ -32,21 +13,6 @@ enum {
MCU_ATE_CLEAN_TXQUEUE = 0x1c,
};
struct mt7915_mcu_rxd {
__le32 rxd[6];
__le16 len;
__le16 pkt_type_id;
u8 eid;
u8 seq;
__le16 __rsv;
u8 ext_eid;
u8 __rsv1[2];
u8 s2d_index;
};
struct mt7915_mcu_thermal_ctrl {
u8 ctrl_id;
u8 band_idx;
@ -63,7 +29,7 @@ struct mt7915_mcu_thermal_ctrl {
} __packed;
struct mt7915_mcu_thermal_notify {
struct mt7915_mcu_rxd rxd;
struct mt76_connac2_mcu_rxd rxd;
struct mt7915_mcu_thermal_ctrl ctrl;
__le32 temperature;
@ -71,7 +37,7 @@ struct mt7915_mcu_thermal_notify {
} __packed;
struct mt7915_mcu_csa_notify {
struct mt7915_mcu_rxd rxd;
struct mt76_connac2_mcu_rxd rxd;
u8 omac_idx;
u8 csa_count;
@ -80,7 +46,7 @@ struct mt7915_mcu_csa_notify {
} __packed;
struct mt7915_mcu_bcc_notify {
struct mt7915_mcu_rxd rxd;
struct mt76_connac2_mcu_rxd rxd;
u8 band_idx;
u8 omac_idx;
@ -89,7 +55,7 @@ struct mt7915_mcu_bcc_notify {
} __packed;
struct mt7915_mcu_rdd_report {
struct mt7915_mcu_rxd rxd;
struct mt76_connac2_mcu_rxd rxd;
u8 band_idx;
u8 long_detected;
@ -267,9 +233,6 @@ struct mt7915_mcu_muru_stats {
#define WMM_TXOP_SET BIT(3)
#define WMM_PARAM_SET GENMASK(3, 0)
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
#define MCU_PKT_ID 0xa0
enum {
MCU_FW_LOG_WM,
MCU_FW_LOG_WA,
@ -489,6 +452,12 @@ enum {
SER_RECOVER
};
#define MT7915_MAX_BEACON_SIZE 512
#define MT7915_MAX_INBAND_FRAME_SIZE 256
#define MT7915_MAX_BSS_OFFLOAD_SIZE (MT7915_MAX_BEACON_SIZE + \
MT7915_MAX_INBAND_FRAME_SIZE + \
MT7915_BEACON_UPDATE_SIZE)
#define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct bss_info_omac) + \
sizeof(struct bss_info_basic) +\

View File

@ -591,8 +591,8 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
if (intr & MT_INT_RX(MT_RXQ_MAIN))
napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]);
if (intr & MT_INT_RX(MT_RXQ_EXT))
napi_schedule(&dev->mt76.napi[MT_RXQ_EXT]);
if (intr & MT_INT_RX(MT_RXQ_BAND1))
napi_schedule(&dev->mt76.napi[MT_RXQ_BAND1]);
if (intr & MT_INT_RX(MT_RXQ_MCU))
napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]);
@ -604,8 +604,8 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
(intr & MT_INT_RX(MT_RXQ_MAIN_WA)))
napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN_WA]);
if (intr & MT_INT_RX(MT_RXQ_EXT_WA))
napi_schedule(&dev->mt76.napi[MT_RXQ_EXT_WA]);
if (intr & MT_INT_RX(MT_RXQ_BAND1_WA))
napi_schedule(&dev->mt76.napi[MT_RXQ_BAND1_WA]);
if (intr & MT_INT_MCU_CMD) {
u32 val = mt76_rr(dev, MT_MCU_CMD);
@ -645,14 +645,14 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
{
static const struct mt76_driver_ops drv_ops = {
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7915_txp),
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
.token_size = MT7915_TOKEN_SIZE,
.tx_prepare_skb = mt7915_tx_prepare_skb,
.tx_complete_skb = mt7915_tx_complete_skb,
.tx_complete_skb = mt76_connac_tx_complete_skb,
.rx_skb = mt7915_queue_rx_skb,
.rx_check = mt7915_rx_check,
.rx_poll_complete = mt7915_rx_poll_complete,
@ -661,16 +661,11 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
.sta_remove = mt7915_mac_sta_remove,
.update_survey = mt7915_update_channel,
};
struct ieee80211_ops *ops;
struct mt7915_dev *dev;
struct mt76_dev *mdev;
int ret;
ops = devm_kmemdup(pdev, &mt7915_ops, sizeof(mt7915_ops), GFP_KERNEL);
if (!ops)
return ERR_PTR(-ENOMEM);
mdev = mt76_alloc_device(pdev, sizeof(*dev), ops, &drv_ops);
mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt7915_ops, &drv_ops);
if (!mdev)
return ERR_PTR(-ENOMEM);

View File

@ -10,7 +10,6 @@
#include "regs.h"
#define MT7915_MAX_INTERFACES 19
#define MT7915_MAX_WMM_SETS 4
#define MT7915_WTBL_SIZE 288
#define MT7916_WTBL_SIZE 544
#define MT7915_WTBL_RESERVED (mt7915_wtbl_size(dev) - 1)
@ -67,7 +66,7 @@
#define MT7915_MAX_TWT_AGRT 16
#define MT7915_MAX_STA_TWT_AGRT 8
#define MT7915_MIN_TWT_DUR 64
#define MT7915_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 2)
#define MT7915_MAX_QUEUE (MT_RXQ_BAND2 + __MT_MCUQ_MAX + 2)
struct mt7915_vif;
struct mt7915_sta;
@ -200,8 +199,15 @@ struct mib_stats {
/* rx stats */
u32 rx_fifo_full_cnt;
u32 channel_idle_cnt;
u32 primary_cca_busy_time;
u32 secondary_cca_busy_time;
u32 primary_energy_detect_time;
u32 cck_mdrdy_time;
u32 ofdm_mdrdy_time;
u32 green_mdrdy_time;
u32 rx_vector_mismatch_cnt;
u32 rx_delimiter_fail_cnt;
u32 rx_mrdy_cnt;
u32 rx_len_mismatch_cnt;
u32 rx_mpdu_cnt;
u32 rx_ampdu_cnt;
@ -341,20 +347,6 @@ enum {
__MT_WFDMA_MAX,
};
enum {
MT_CTX0,
MT_HIF0 = 0x0,
MT_LMAC_AC00 = 0x0,
MT_LMAC_AC01,
MT_LMAC_AC02,
MT_LMAC_AC03,
MT_LMAC_ALTX0 = 0x10,
MT_LMAC_BMC0,
MT_LMAC_BCN0,
MT_LMAC_PSMP0,
};
enum {
MT_RX_SEL0,
MT_RX_SEL1,
@ -396,7 +388,7 @@ mt7915_hw_dev(struct ieee80211_hw *hw)
static inline struct mt7915_phy *
mt7915_ext_phy(struct mt7915_dev *dev)
{
struct mt76_phy *phy = dev->mt76.phy2;
struct mt76_phy *phy = dev->mt76.phys[MT_BAND1];
if (!phy)
return NULL;
@ -557,9 +549,10 @@ bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask);
void mt7915_mac_reset_counters(struct mt7915_phy *phy);
void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy);
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
void mt7915_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
struct ieee80211_key_conf *key, u32 changed);
struct ieee80211_key_conf *key,
enum mt76_txq_id qid, u32 changed);
void mt7915_mac_set_timing(struct mt7915_phy *phy);
int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
@ -579,7 +572,6 @@ int mt7915_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);
void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt7915_tx_token_put(struct mt7915_dev *dev);
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);

View File

@ -305,7 +305,7 @@ enum offs_rev {
#define MT_MIB_SDR9_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR9))
#define MT_MIB_SDR9_CCA_BUSY_TIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR10_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR10))
#define MT_MIB_SDR10(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR10))
#define MT_MIB_SDR10_MRDY_COUNT_MASK GENMASK(25, 0)
#define MT_MIB_SDR10_MRDY_COUNT_MASK_MT7916 GENMASK(31, 0)
@ -329,24 +329,24 @@ enum offs_rev {
#define MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK_MT7916 GENMASK(31, 0)
/* in units of 'us' */
#define MT_MIB_SDR16_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR16))
#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR16))
#define MT_MIB_SDR16_PRIMARY_CCA_BUSY_TIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR17_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR17))
#define MT_MIB_SDR17(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR17))
#define MT_MIB_SDR17_SECONDARY_CCA_BUSY_TIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR18(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR18))
#define MT_MIB_SDR18_PRIMARY_ENERGY_DETECT_TIME_MASK GENMASK(23, 0)
/* units are us */
#define MT_MIB_SDR19_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR19))
#define MT_MIB_SDR19(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR19))
#define MT_MIB_SDR19_CCK_MDRDY_TIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR20_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR20))
#define MT_MIB_SDR20(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR20))
#define MT_MIB_SDR20_OFDM_VHT_MDRDY_TIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR21_DNR(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR21))
#define MT_MIB_SDR20_GREEN_MDRDY_TIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR21(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR21))
#define MT_MIB_SDR21_GREEN_MDRDY_TIME_MASK GENMASK(23, 0)
/* rx ampdu count, 32-bit */
#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR22))
@ -623,7 +623,7 @@ enum offs_rev {
/* WFDMA COMMON */
#define __RXQ(q) ((q) + __MT_MCUQ_MAX)
#define __TXQ(q) (__RXQ(q) + __MT_RXQ_MAX)
#define __TXQ(q) (__RXQ(q) + MT_RXQ_BAND2)
#define MT_Q_ID(q) (dev->q_id[(q)])
#define MT_Q_BASE(q) ((dev->wfdma_mask >> (q)) & 0x1 ? \
@ -639,7 +639,7 @@ enum offs_rev {
#define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \
MT_MCUQ_ID(q)* 0x4)
#define MT_RXQ_EXT_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \
#define MT_RXQ_BAND1_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \
MT_RXQ_ID(q)* 0x4)
#define MT_TXQ_EXT_CTRL(q) (MT_Q_BASE(__TXQ(q)) + 0x600 + \
MT_TXQ_ID(q)* 0x4)
@ -671,8 +671,8 @@ enum offs_rev {
#define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \
MT_INT_RX(MT_RXQ_MAIN_WA))
#define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_EXT) | \
MT_INT_RX(MT_RXQ_EXT_WA) | \
#define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \
MT_INT_RX(MT_RXQ_BAND1_WA) | \
MT_INT_RX(MT_RXQ_MAIN_WA))
#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \
@ -940,7 +940,7 @@ enum offs_rev {
#define MT_ADIE_TYPE_MASK BIT(1)
/* FW MODE SYNC */
#define MT_FW_EXCEPTION __REG(FW_EXCEPTION_ADDR)
#define MT_FW_EXCEPTION __REG(FW_EXCEPTION_ADDR)
#define MT_SWDEF_BASE __REG(SWDEF_BASE_ADDR)

View File

@ -168,13 +168,14 @@ mt7915_tm_set_tam_arb(struct mt7915_phy *phy, bool enable, bool mu)
}
static int
mt7915_tm_set_wmm_qid(struct mt7915_dev *dev, u8 qid, u8 aifs, u8 cw_min,
mt7915_tm_set_wmm_qid(struct mt7915_phy *phy, u8 qid, u8 aifs, u8 cw_min,
u16 cw_max, u16 txop)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)phy->monitor_vif->drv_priv;
struct mt7915_mcu_tx req = { .total = 1 };
struct edca *e = &req.edca[0];
e->queue = qid;
e->queue = qid + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
e->set = WMM_PARAM_SET;
e->aifs = aifs;
@ -182,7 +183,7 @@ mt7915_tm_set_wmm_qid(struct mt7915_dev *dev, u8 qid, u8 aifs, u8 cw_min,
e->cw_max = cpu_to_le16(cw_max);
e->txop = cpu_to_le16(txop);
return mt7915_mcu_update_edca(dev, &req);
return mt7915_mcu_update_edca(phy->dev, &req);
}
static int
@ -244,7 +245,7 @@ done:
mt7915_tm_set_slot_time(phy, slot_time, sifs);
return mt7915_tm_set_wmm_qid(dev,
return mt7915_tm_set_wmm_qid(phy,
mt76_connac_lmac_mapping(IEEE80211_AC_BE),
aifsn, cw, cw, 0);
}
@ -774,7 +775,7 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
fcs_err = is_mt7915(&dev->mt76) ? FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK, cnt) :
FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK_MT7916, cnt);
q = phy->band_idx ? MT_RXQ_EXT : MT_RXQ_MAIN;
q = phy->band_idx ? MT_RXQ_BAND1 : MT_RXQ_MAIN;
mphy->test.rx_stats.packets[q] += fcs_err;
mphy->test.rx_stats.fcs_error[q] += fcs_err;

View File

@ -9,6 +9,7 @@ CFLAGS_trace.o := -I$(src)
mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o trace.o
mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
mt7921-common-$(CONFIG_ACPI) += acpi_sar.o
mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o
mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o
mt7921u-y := usb.o usb_mac.o

View File

@ -0,0 +1,279 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2022 MediaTek Inc. */
#include <linux/acpi.h>
#include "mt7921.h"
static int
mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len)
{
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *sar_root, *sar_unit;
struct mt76_dev *mdev = &dev->mt76;
acpi_handle root, handle;
acpi_status status;
u32 i = 0;
root = ACPI_HANDLE(mdev->dev);
if (!root)
return -EOPNOTSUPP;
status = acpi_get_handle(root, method, &handle);
if (ACPI_FAILURE(status))
return -EIO;
status = acpi_evaluate_object(handle, NULL, NULL, &buf);
if (ACPI_FAILURE(status))
return -EIO;
sar_root = buf.pointer;
if (sar_root->type != ACPI_TYPE_PACKAGE ||
sar_root->package.count < 4 ||
sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) {
dev_err(mdev->dev, "sar cnt = %d\n",
sar_root->package.count);
goto free;
}
if (!*tbl) {
*tbl = devm_kzalloc(mdev->dev, sar_root->package.count,
GFP_KERNEL);
if (!*tbl)
goto free;
}
if (len)
*len = sar_root->package.count;
for (i = 0; i < sar_root->package.count; i++) {
sar_unit = &sar_root->package.elements[i];
if (sar_unit->type != ACPI_TYPE_INTEGER)
break;
*(*tbl + i) = (u8)sar_unit->integer.value;
}
free:
kfree(sar_root);
return (i == sar_root->package.count) ? 0 : -EINVAL;
}
/* MTCL : Country List Table for 6G band */
static int
mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version)
{
*version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0)
? 1 : 2;
return 0;
}
/* MTDS : Dynamic SAR Power Table */
static int
mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version)
{
int len, ret, sarlen, prelen, tblcnt;
bool enable;
ret = mt7921_acpi_read(dev, MT7921_ACPI_MTDS, table, &len);
if (ret)
return ret;
/* Table content validation */
switch (version) {
case 1:
enable = ((struct mt7921_asar_dyn *)*table)->enable;
sarlen = sizeof(struct mt7921_asar_dyn_limit);
prelen = sizeof(struct mt7921_asar_dyn);
break;
case 2:
enable = ((struct mt7921_asar_dyn_v2 *)*table)->enable;
sarlen = sizeof(struct mt7921_asar_dyn_limit_v2);
prelen = sizeof(struct mt7921_asar_dyn_v2);
break;
default:
return -EINVAL;
}
tblcnt = (len - prelen) / sarlen;
if (!enable ||
tblcnt > MT7921_ASAR_MAX_DYN || tblcnt < MT7921_ASAR_MIN_DYN)
ret = -EINVAL;
return ret;
}
/* MTGS : Geo SAR Power Table */
static int
mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version)
{
int len, ret = 0, sarlen, prelen, tblcnt;
ret = mt7921_acpi_read(dev, MT7921_ACPI_MTGS, table, &len);
if (ret)
return ret;
/* Table content validation */
switch (version) {
case 1:
sarlen = sizeof(struct mt7921_asar_geo_limit);
prelen = sizeof(struct mt7921_asar_geo);
break;
case 2:
sarlen = sizeof(struct mt7921_asar_geo_limit_v2);
prelen = sizeof(struct mt7921_asar_geo_v2);
break;
default:
return -EINVAL;
}
tblcnt = (len - prelen) / sarlen;
if (tblcnt > MT7921_ASAR_MAX_GEO || tblcnt < MT7921_ASAR_MIN_GEO)
ret = -EINVAL;
return ret;
}
int mt7921_init_acpi_sar(struct mt7921_dev *dev)
{
struct mt7921_acpi_sar *asar;
int ret;
asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL);
if (!asar)
return -ENOMEM;
mt7921_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
/* MTDS is mandatory. Return error if table is invalid */
ret = mt7921_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
if (ret) {
devm_kfree(dev->mt76.dev, asar->dyn);
devm_kfree(dev->mt76.dev, asar->countrylist);
devm_kfree(dev->mt76.dev, asar);
return ret;
}
/* MTGS is optional */
ret = mt7921_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
if (ret) {
devm_kfree(dev->mt76.dev, asar->geo);
asar->geo = NULL;
}
dev->phy.acpisar = asar;
return 0;
}
static s8
mt7921_asar_get_geo_pwr(struct mt7921_phy *phy,
enum nl80211_band band, s8 dyn_power)
{
struct mt7921_acpi_sar *asar = phy->acpisar;
struct mt7921_asar_geo_band *band_pwr;
s8 geo_power;
u8 idx, max;
if (!asar->geo)
return dyn_power;
switch (phy->mt76->dev->region) {
case NL80211_DFS_FCC:
idx = 0;
break;
case NL80211_DFS_ETSI:
idx = 1;
break;
default: /* WW */
idx = 2;
break;
}
if (asar->ver == 1) {
band_pwr = &asar->geo->tbl[idx].band[0];
max = ARRAY_SIZE(asar->geo->tbl[idx].band);
} else {
band_pwr = &asar->geo_v2->tbl[idx].band[0];
max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band);
}
switch (band) {
case NL80211_BAND_2GHZ:
idx = 0;
break;
case NL80211_BAND_5GHZ:
idx = 1;
break;
case NL80211_BAND_6GHZ:
idx = 2;
break;
default:
return dyn_power;
}
if (idx >= max)
return dyn_power;
geo_power = (band_pwr + idx)->pwr;
dyn_power += (band_pwr + idx)->offset;
return min(geo_power, dyn_power);
}
static s8
mt7921_asar_range_pwr(struct mt7921_phy *phy,
const struct cfg80211_sar_freq_ranges *range,
u8 idx)
{
const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
struct mt7921_acpi_sar *asar = phy->acpisar;
u8 *limit, band, max;
if (!capa)
return 127;
if (asar->ver == 1) {
limit = &asar->dyn->tbl[0].frp[0];
max = ARRAY_SIZE(asar->dyn->tbl[0].frp);
} else {
limit = &asar->dyn_v2->tbl[0].frp[0];
max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp);
}
if (idx >= max)
return 127;
if (range->start_freq >= 5945)
band = NL80211_BAND_6GHZ;
else if (range->start_freq >= 5150)
band = NL80211_BAND_5GHZ;
else
band = NL80211_BAND_2GHZ;
return mt7921_asar_get_geo_pwr(phy, band, limit[idx]);
}
int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
{
const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
int i;
if (!phy->acpisar)
return 0;
/* When ACPI SAR enabled in HW, we should apply rules for .frp
* 1. w/o .sar_specs : set ACPI SAR power as the defatul value
* 2. w/ .sar_specs : set power with min(.sar_specs, ACPI_SAR)
*/
for (i = 0; i < capa->num_freq_ranges; i++) {
struct mt76_freq_range_power *frp = &phy->mt76->frp[i];
frp->range = set_default ? &capa->freq_ranges[i] : frp->range;
if (!frp->range)
continue;
frp->power = min_t(s8, set_default ? 127 : frp->power,
mt7921_asar_range_pwr(phy, frp->range, i));
}
return 0;
}

View File

@ -0,0 +1,93 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2022 MediaTek Inc. */
#ifndef __MT7921_ACPI_SAR_H
#define __MT7921_ACPI_SAR_H
#define MT7921_ASAR_MIN_DYN 1
#define MT7921_ASAR_MAX_DYN 8
#define MT7921_ASAR_MIN_GEO 3
#define MT7921_ASAR_MAX_GEO 8
#define MT7921_ACPI_MTCL "MTCL"
#define MT7921_ACPI_MTDS "MTDS"
#define MT7921_ACPI_MTGS "MTGS"
struct mt7921_asar_dyn_limit {
u8 idx;
u8 frp[5];
} __packed;
struct mt7921_asar_dyn {
u8 names[4];
u8 enable;
u8 nr_tbl;
struct mt7921_asar_dyn_limit tbl[0];
} __packed;
struct mt7921_asar_dyn_limit_v2 {
u8 idx;
u8 frp[11];
} __packed;
struct mt7921_asar_dyn_v2 {
u8 names[4];
u8 enable;
u8 rsvd;
u8 nr_tbl;
struct mt7921_asar_dyn_limit_v2 tbl[0];
} __packed;
struct mt7921_asar_geo_band {
u8 pwr;
u8 offset;
} __packed;
struct mt7921_asar_geo_limit {
u8 idx;
/* 0:2G, 1:5G */
struct mt7921_asar_geo_band band[2];
} __packed;
struct mt7921_asar_geo {
u8 names[4];
u8 version;
u8 nr_tbl;
struct mt7921_asar_geo_limit tbl[0];
} __packed;
struct mt7921_asar_geo_limit_v2 {
u8 idx;
/* 0:2G, 1:5G, 2:6G */
struct mt7921_asar_geo_band band[3];
} __packed;
struct mt7921_asar_geo_v2 {
u8 names[4];
u8 version;
u8 rsvd;
u8 nr_tbl;
struct mt7921_asar_geo_limit_v2 tbl[0];
} __packed;
struct mt7921_asar_cl {
u8 names[4];
u8 version;
u8 mode_6g;
u8 cl6g[6];
} __packed;
struct mt7921_acpi_sar {
u8 ver;
union {
struct mt7921_asar_dyn *dyn;
struct mt7921_asar_dyn_v2 *dyn_v2;
};
union {
struct mt7921_asar_geo *geo;
struct mt7921_asar_geo_v2 *geo_v2;
};
struct mt7921_asar_cl *countrylist;
};
#endif

View File

@ -5,20 +5,6 @@
#include "../dma.h"
#include "mac.h"
static 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, 0);
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;
}
static int mt7921_poll_tx(struct napi_struct *napi, int budget)
{
struct mt7921_dev *dev;
@ -31,7 +17,7 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget)
return 0;
}
mt7921_mcu_tx_cleanup(dev);
mt76_connac_tx_cleanup(&dev->mt76);
if (napi_complete(napi))
mt7921_irq_enable(dev, MT_INT_TX_DONE_ALL);
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
@ -250,8 +236,9 @@ int mt7921_dma_init(struct mt7921_dev *dev)
return ret;
/* init tx queue */
ret = mt7921_init_tx_queues(&dev->phy, MT7921_TXQ_BAND0,
MT7921_TX_RING_SIZE);
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
MT7921_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
if (ret)
return ret;

View File

@ -34,14 +34,13 @@ mt7921_regd_notifier(struct wiphy *wiphy,
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct mt7921_dev *dev = mt7921_hw_dev(hw);
struct mt7921_phy *phy = mt7921_hw_phy(hw);
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
dev->mt76.region = request->dfs_region;
mt7921_mutex_acquire(dev);
mt76_connac_mcu_set_channel_domain(hw->priv);
mt76_connac_mcu_set_rate_txpower(phy->mt76);
mt7921_set_tx_sar_pwr(hw, NULL);
mt7921_mutex_release(dev);
}
@ -53,8 +52,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
struct wiphy *wiphy = hw->wiphy;
hw->queues = 4;
hw->max_rx_aggregation_subframes = 64;
hw->max_tx_aggregation_subframes = 128;
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
hw->netdev_features = NETIF_F_RXCSUM;
hw->radiotap_timestamp.units_pos =
@ -97,6 +96,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
ieee80211_hw_set(hw, CONNECTION_MONITOR);
if (dev->pm.enable)
ieee80211_hw_set(hw, CONNECTION_MONITOR);
@ -289,6 +290,8 @@ int mt7921_register_device(struct mt7921_dev *dev)
if (!mt76_is_mmio(&dev->mt76))
hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
mt7921_init_acpi_sar(dev);
ret = mt7921_init_wcid(dev);
if (ret)
return ret;
@ -304,7 +307,7 @@ int mt7921_register_device(struct mt7921_dev *dev)
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_MPDU_LENGTH_11454 |
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |

View File

@ -9,10 +9,6 @@
#include "mac.h"
#include "mcu.h"
#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)
{
@ -168,183 +164,6 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev)
}
EXPORT_SYMBOL_GPL(mt7921_mac_sta_poll);
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 = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
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_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
static const struct ieee80211_radiotap_he_mu mu_known = {
.flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN) |
HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN),
.flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN) |
HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN),
};
struct ieee80211_radiotap_he_mu *he_mu;
status->flag |= RX_FLAG_RADIOTAP_HE_MU;
he_mu = skb_push(skb, sizeof(mu_known));
memcpy(he_mu, &mu_known, sizeof(mu_known));
#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
if (status->he_dcm)
he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0);
if (status->bw >= RATE_INFO_BW_40) {
he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
he_mu->ru_ch2[0] =
le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
}
if (status->bw >= RATE_INFO_BW_80) {
he_mu->ru_ch1[1] =
le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
he_mu->ru_ch2[1] =
le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
}
}
static void
mt7921_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
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_SPTL_REUSE_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;
status->flag |= RX_FLAG_RADIOTAP_HE;
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->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
le16_encode_bits(ltf_size,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
he->data5 |= HE_BITS(DATA5_TXBF);
he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
switch (mode) {
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_BW_RU_ALLOC_KNOWN);
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
break;
case MT_PHY_TYPE_HE_EXT_SU:
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
HE_BITS(DATA1_UL_DL_KNOWN) |
HE_BITS(DATA1_BW_RU_ALLOC_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->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
mt7921_mac_decode_he_radiotap_ru(status, he, rxv);
mt7921_mac_decode_he_mu_radiotap(skb, rxv);
break;
case MT_PHY_TYPE_HE_TB:
he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
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)
@ -399,86 +218,6 @@ mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mac_rssi_iter, skb);
}
/* The HW does not translate the mac header to 802.3 for mesh point */
static int mt7921_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap);
struct mt7921_sta *msta = (struct mt7921_sta *)status->wcid;
__le32 *rxd = (__le32 *)skb->data;
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
struct ieee80211_hdr hdr;
u16 frame_control;
if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
MT_RXD3_NORMAL_U2M)
return -EINVAL;
if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4))
return -EINVAL;
if (!msta || !msta->vif)
return -EINVAL;
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
/* store the info from RXD and ethhdr to avoid being overridden */
frame_control = le32_get_bits(rxd[6], MT_RXD6_FRAME_CONTROL);
hdr.frame_control = cpu_to_le16(frame_control);
hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_SEQ_CTRL));
hdr.duration_id = 0;
ether_addr_copy(hdr.addr1, vif->addr);
ether_addr_copy(hdr.addr2, sta->addr);
switch (frame_control & (IEEE80211_FCTL_TODS |
IEEE80211_FCTL_FROMDS)) {
case 0:
ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);
break;
case IEEE80211_FCTL_FROMDS:
ether_addr_copy(hdr.addr3, eth_hdr->h_source);
break;
case IEEE80211_FCTL_TODS:
ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
break;
case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS:
ether_addr_copy(hdr.addr3, eth_hdr->h_dest);
ether_addr_copy(hdr.addr4, eth_hdr->h_source);
break;
default:
break;
}
skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2);
if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||
eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))
ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);
else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)
ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);
else
skb_pull(skb, 2);
if (ieee80211_has_order(hdr.frame_control))
memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[9],
IEEE80211_HT_CTL_LEN);
if (ieee80211_is_data_qos(hdr.frame_control)) {
__le16 qos_ctrl;
qos_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_QOS_CTL));
memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,
IEEE80211_QOS_CTL_LEN);
}
if (ieee80211_has_a4(hdr.frame_control))
memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
else
memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6);
return 0;
}
static int
mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
{
@ -496,9 +235,10 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
u32 rxd2 = le32_to_cpu(rxd[2]);
u32 rxd3 = le32_to_cpu(rxd[3]);
u32 rxd4 = le32_to_cpu(rxd[4]);
struct mt7921_sta *msta;
u16 seq_ctrl = 0;
__le16 fc = 0;
u32 mode = 0;
u8 mode = 0;
int i, idx;
memset(status, 0, sizeof(*status));
@ -526,8 +266,6 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
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))
@ -642,9 +380,8 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
/* RXD Group 3 - P-RXV */
if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
u8 stbc, gi;
u32 v0, v1;
bool cck;
int ret;
rxv = rxd;
rxd += 2;
@ -672,79 +409,10 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
status->chain_signal[i]);
}
stbc = FIELD_GET(MT_PRXV_STBC, v0);
gi = FIELD_GET(MT_PRXV_SGI, v0);
cck = false;
idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
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 > 11)
return -EINVAL;
break;
case MT_PHY_TYPE_HE_MU:
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;
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_PRXV_FRAME_MODE, v0)) {
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;
ret = mt76_connac2_mac_fill_rx_rate(&dev->mt76, status, sband,
rxv, &mode);
if (ret < 0)
return ret;
if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
rxd += 18;
@ -762,8 +430,18 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad;
if (hdr_trans && ieee80211_has_morefrags(fc)) {
if (mt7921_reverse_frag0_hdr_trans(skb, hdr_gap))
struct ieee80211_vif *vif;
int err;
if (!msta || !msta->vif)
return -EINVAL;
vif = container_of((void *)msta->vif, struct ieee80211_vif,
drv_priv);
err = mt76_connac2_reverse_frag0_hdr_trans(vif, skb, hdr_gap);
if (err)
return err;
hdr_trans = false;
} else {
skb_pull(skb, hdr_gap);
@ -796,7 +474,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
mt7921_mac_assoc_rssi(dev, skb);
if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
mt7921_mac_decode_he_radiotap(skb, rxv, mode);
mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv, mode);
if (!status->wcid || !ieee80211_is_data_qos(fc))
return 0;
@ -808,217 +486,6 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
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;
u16 ethertype;
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);
ethertype = get_unaligned_be16(&skb->data[12]);
if (ethertype >= 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 ||
info->flags & IEEE80211_TX_CTL_USE_MINRATE)
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);
txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU);
}
if (mt76_is_mmio(&dev->mt76)) {
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
txwi[7] |= cpu_to_le32(val);
} else {
val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) |
FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype);
txwi[8] |= 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, int pid,
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_mmio = mt76_is_mmio(&dev->mt76);
u32 sz_txd = is_mmio ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
u16 tx_count = 15;
u32 val;
if (vif) {
struct mt76_vif *mvif = (struct mt76_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 = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
q_idx = MT_LMAC_ALTX0;
} else {
p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
q_idx = wmm_idx * MT7921_MAX_WMM_SETS +
mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
}
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
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 = 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;
val = FIELD_PREP(MT_TXD5_PID, pid);
if (pid >= MT_PACKET_ID_FIRST)
val |= MT_TXD5_TX_STATUS_HOST;
txwi[5] = cpu_to_le32(val);
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)) {
int rateidx = vif ? ffs(vif->bss_conf.basic_rates) - 1 : 0;
u16 rate, mode;
/* hardware won't add HTC for mgmt/ctrl frame */
txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD);
rate = mt76_calculate_default_rate(mphy, rateidx);
mode = rate >> 8;
rate &= GENMASK(7, 0);
rate |= FIELD_PREP(MT_TX_RATE_MODE, mode);
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);
}
}
EXPORT_SYMBOL_GPL(mt7921_mac_write_txwi);
void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
{
struct mt7921_sta *msta;
@ -1044,123 +511,6 @@ void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
}
EXPORT_SYMBOL_GPL(mt7921_tx_check_aggr);
static bool
mt7921_mac_add_txs_skb(struct mt7921_dev *dev, struct mt76_wcid *wcid, int pid,
__le32 *txs_data)
{
struct mt7921_sta *msta = container_of(wcid, struct mt7921_sta, wcid);
struct mt76_sta_stats *stats = &msta->stats;
struct ieee80211_supported_band *sband;
struct mt76_dev *mdev = &dev->mt76;
struct ieee80211_tx_info *info;
struct rate_info rate = {};
struct sk_buff_head list;
u32 txrate, txs, mode;
struct sk_buff *skb;
bool cck = false;
mt76_tx_status_lock(mdev, &list);
skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
if (!skb)
goto out;
info = IEEE80211_SKB_CB(skb);
txs = le32_to_cpu(txs_data[0]);
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.ampdu_len = 1;
info->status.ampdu_ack_len = !!(info->flags &
IEEE80211_TX_STAT_ACK);
info->status.rates[0].idx = -1;
if (!wcid->sta)
goto out;
txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
stats->tx_nss[rate.nss - 1]++;
if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
stats->tx_mcs[rate.mcs]++;
mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
switch (mode) {
case MT_PHY_TYPE_CCK:
cck = true;
fallthrough;
case MT_PHY_TYPE_OFDM:
if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ)
sband = &dev->mphy.sband_5g.sband;
else
sband = &dev->mphy.sband_2g.sband;
rate.mcs = mt76_get_rate(dev->mphy.dev, sband, rate.mcs, cck);
rate.legacy = sband->bitrates[rate.mcs].bitrate;
break;
case MT_PHY_TYPE_HT:
case MT_PHY_TYPE_HT_GF:
if (rate.mcs > 31)
goto out;
rate.flags = RATE_INFO_FLAGS_MCS;
if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
break;
case MT_PHY_TYPE_VHT:
if (rate.mcs > 9)
goto out;
rate.flags = RATE_INFO_FLAGS_VHT_MCS;
break;
case MT_PHY_TYPE_HE_SU:
case MT_PHY_TYPE_HE_EXT_SU:
case MT_PHY_TYPE_HE_TB:
case MT_PHY_TYPE_HE_MU:
if (rate.mcs > 11)
goto out;
rate.he_gi = wcid->rate.he_gi;
rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
rate.flags = RATE_INFO_FLAGS_HE_MCS;
break;
default:
goto out;
}
stats->tx_mode[mode]++;
switch (FIELD_GET(MT_TXS0_BW, txs)) {
case IEEE80211_STA_RX_BW_160:
rate.bw = RATE_INFO_BW_160;
stats->tx_bw[3]++;
break;
case IEEE80211_STA_RX_BW_80:
rate.bw = RATE_INFO_BW_80;
stats->tx_bw[2]++;
break;
case IEEE80211_STA_RX_BW_40:
rate.bw = RATE_INFO_BW_40;
stats->tx_bw[1]++;
break;
default:
rate.bw = RATE_INFO_BW_20;
stats->tx_bw[0]++;
break;
}
wcid->rate = rate;
out:
if (skb)
mt76_tx_status_skb_done(mdev, skb, &list);
mt76_tx_status_unlock(mdev, &list);
return !!skb;
}
void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
{
struct mt7921_sta *msta = NULL;
@ -1187,12 +537,13 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
if (!wcid)
goto out;
mt7921_mac_add_txs_skb(dev, wcid, pid, txs_data);
msta = container_of(wcid, struct mt7921_sta, wcid);
mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data,
&msta->stats);
if (!wcid->sta)
goto out;
msta = container_of(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);
@ -1387,9 +738,9 @@ void mt7921_mac_reset_work(struct work_struct *work)
reset_work);
struct ieee80211_hw *hw = mt76_hw(dev);
struct mt76_connac_pm *pm = &dev->pm;
int i;
int i, ret;
dev_err(dev->mt76.dev, "chip reset\n");
dev_dbg(dev->mt76.dev, "chip reset\n");
dev->hw_full_reset = true;
ieee80211_stop_queues(hw);
@ -1397,11 +748,14 @@ void mt7921_mac_reset_work(struct work_struct *work)
cancel_delayed_work_sync(&pm->ps_work);
cancel_work_sync(&pm->wake_work);
mutex_lock(&dev->mt76.mutex);
for (i = 0; i < 10; i++)
if (!mt7921_dev_reset(dev))
for (i = 0; i < 10; i++) {
mutex_lock(&dev->mt76.mutex);
ret = mt7921_dev_reset(dev);
mutex_unlock(&dev->mt76.mutex);
if (!ret)
break;
mutex_unlock(&dev->mt76.mutex);
}
if (i == 10)
dev_err(dev->mt76.dev, "chip reset failed\n");
@ -1538,10 +892,12 @@ void mt7921_pm_wake_work(struct work_struct *work)
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt76_worker_schedule(&mdev->sdio.txrx_worker);
} else {
local_bh_disable();
mt76_for_each_q_rx(mdev, i)
napi_schedule(&mdev->napi[i]);
local_bh_enable();
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt7921_mcu_tx_cleanup(dev);
mt76_connac_tx_cleanup(mdev);
}
if (test_bit(MT76_STATE_RUNNING, &mphy->state))
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
@ -1617,7 +973,7 @@ void mt7921_coredump_work(struct work_struct *work)
if (!skb)
break;
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
dev_kfree_skb(skb);
continue;
@ -1646,7 +1002,7 @@ mt7921_usb_sdio_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid,
__le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE);
memset(txwi, 0, MT_SDIO_TXD_SIZE);
mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false);
mt76_connac2_mac_write_txwi(&dev->mt76, txwi, skb, wcid, key, pid, qid, 0);
skb_push(skb, MT_SDIO_TXD_SIZE);
}

View File

@ -4,6 +4,8 @@
#ifndef __MT7921_MAC_H
#define __MT7921_MAC_H
#include "../mt76_connac2_mac.h"
#define MT_CT_PARSE_LEN 72
#define MT_CT_DMA_BUF_NUM 2
@ -27,294 +29,6 @@ enum rx_pkt_type {
PKT_TYPE_NORMAL_MCU,
};
/* RXD DW1 */
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0)
#define MT_RXD1_NORMAL_GROUP_1 BIT(11)
#define MT_RXD1_NORMAL_GROUP_2 BIT(12)
#define MT_RXD1_NORMAL_GROUP_3 BIT(13)
#define MT_RXD1_NORMAL_GROUP_4 BIT(14)
#define MT_RXD1_NORMAL_GROUP_5 BIT(15)
#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16)
#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
#define MT_RXD1_NORMAL_CM BIT(23)
#define MT_RXD1_NORMAL_CLM BIT(24)
#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
#define MT_RXD1_NORMAL_FCS_ERR BIT(27)
#define MT_RXD1_NORMAL_BAND_IDX BIT(28)
#define MT_RXD1_NORMAL_SPP_EN BIT(29)
#define MT_RXD1_NORMAL_ADD_OM BIT(30)
#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
/* RXD DW2 */
#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
#define MT_RXD2_NORMAL_CO_ANT BIT(6)
#define MT_RXD2_NORMAL_BF_CQI BIT(7)
#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
#define MT_RXD2_NORMAL_HDR_TRANS BIT(13)
#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14)
#define MT_RXD2_NORMAL_TID GENMASK(19, 16)
#define MT_RXD2_NORMAL_MU_BAR BIT(21)
#define MT_RXD2_NORMAL_SW_BIT BIT(22)
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
#define MT_RXD2_NORMAL_FRAG BIT(27)
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
#define MT_RXD2_NORMAL_NDATA BIT(29)
#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
/* RXD DW3 */
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
#define MT_RXD3_NORMAL_U2M BIT(0)
#define MT_RXD3_NORMAL_HTC_VLD BIT(0)
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19)
#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
#define MT_RXD3_NORMAL_AMSDU BIT(22)
#define MT_RXD3_NORMAL_MESH BIT(23)
#define MT_RXD3_NORMAL_MHCP BIT(24)
#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25)
#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26)
#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27)
#define MT_RXD3_NORMAL_MORE BIT(28)
#define MT_RXD3_NORMAL_UNWANT BIT(29)
#define MT_RXD3_NORMAL_RX_DROP BIT(30)
#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
/* RXD DW4 */
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9)
#define MT_RXD4_NORMAL_CLS BIT(10)
#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11)
#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13)
#define MT_RXD4_NORMAL_WOL GENMASK(18, 14)
#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19)
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
/* RXD GROUP4 */
#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0)
#define MT_RXD6_TA_LO GENMASK(31, 16)
#define MT_RXD7_TA_HI GENMASK(31, 0)
#define MT_RXD8_SEQ_CTRL GENMASK(15, 0)
#define MT_RXD8_QOS_CTL GENMASK(31, 16)
#define MT_RXD9_HT_CONTROL GENMASK(31, 0)
/* P-RXV DW0 */
#define MT_PRXV_TX_RATE GENMASK(6, 0)
#define MT_PRXV_TX_DCM BIT(4)
#define MT_PRXV_TX_ER_SU_106T BIT(5)
#define MT_PRXV_NSTS GENMASK(9, 7)
#define MT_PRXV_TXBF BIT(10)
#define MT_PRXV_HT_AD_CODE BIT(11)
#define MT_PRXV_FRAME_MODE GENMASK(14, 12)
#define MT_PRXV_SGI GENMASK(16, 15)
#define MT_PRXV_STBC GENMASK(23, 22)
#define MT_PRXV_TX_MODE GENMASK(27, 24)
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
/* P-RXV DW1 */
#define MT_PRXV_RCPI3 GENMASK(31, 24)
#define MT_PRXV_RCPI2 GENMASK(23, 16)
#define MT_PRXV_RCPI1 GENMASK(15, 8)
#define MT_PRXV_RCPI0 GENMASK(7, 0)
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
/* C-RXV */
#define MT_CRXV_HT_STBC GENMASK(1, 0)
#define MT_CRXV_TX_MODE GENMASK(7, 4)
#define MT_CRXV_FRAME_MODE GENMASK(10, 8)
#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13)
#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
#define MT_CRXV_HE_PE_DISAMBIG BIT(23)
#define MT_CRXV_HE_NUM_USER GENMASK(30, 24)
#define MT_CRXV_HE_UPLINK BIT(31)
#define MT_CRXV_HE_RU0 GENMASK(7, 0)
#define MT_CRXV_HE_RU1 GENMASK(15, 8)
#define MT_CRXV_HE_RU2 GENMASK(23, 16)
#define MT_CRXV_HE_RU3 GENMASK(31, 24)
#define MT_CRXV_HE_MU_AID GENMASK(30, 20)
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0)
#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6)
#define MT_CRXV_HE_BEAM_CHNG BIT(13)
#define MT_CRXV_HE_DOPPLER BIT(16)
#define MT_CRXV_SNR GENMASK(18, 13)
#define MT_CRXV_FOE_LO GENMASK(31, 19)
#define MT_CRXV_FOE_HI GENMASK(6, 0)
#define MT_CRXV_FOE_SHIFT 13
enum tx_header_format {
MT_HDR_FORMAT_802_3,
MT_HDR_FORMAT_CMD,
MT_HDR_FORMAT_802_11,
MT_HDR_FORMAT_802_11_EXT,
};
enum tx_pkt_type {
MT_TX_TYPE_CT,
MT_TX_TYPE_SF,
MT_TX_TYPE_CMD,
MT_TX_TYPE_FW,
};
enum tx_port_idx {
MT_TX_PORT_IDX_LMAC,
MT_TX_PORT_IDX_MCU
};
enum tx_mcu_port_q_idx {
MT_TX_MCU_PORT_RX_Q0 = 0x20,
MT_TX_MCU_PORT_RX_Q1,
MT_TX_MCU_PORT_RX_Q2,
MT_TX_MCU_PORT_RX_Q3,
MT_TX_MCU_PORT_RX_FWDL = 0x3e
};
#define MT_CT_INFO_APPLY_TXD BIT(0)
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
#define MT_CT_INFO_MGMT_FRAME BIT(2)
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
#define MT_CT_INFO_HSR2_TX BIT(4)
#define MT_CT_INFO_FROM_HOST BIT(7)
#define MT_TXD_SIZE (8 * 4)
#define MT_SDIO_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
#define MT_SDIO_TAIL_SIZE 8
#define MT_SDIO_HDR_SIZE 4
#define MT_USB_TAIL_SIZE 4
#define MT_TXD0_Q_IDX GENMASK(31, 25)
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
#define MT_TXD1_LONG_FORMAT BIT(31)
#define MT_TXD1_TGID BIT(30)
#define MT_TXD1_OWN_MAC GENMASK(29, 24)
#define MT_TXD1_AMSDU BIT(23)
#define MT_TXD1_TID GENMASK(22, 20)
#define MT_TXD1_HDR_PAD GENMASK(19, 18)
#define MT_TXD1_HDR_FORMAT GENMASK(17, 16)
#define MT_TXD1_HDR_INFO GENMASK(15, 11)
#define MT_TXD1_ETH_802_3 BIT(15)
#define MT_TXD1_VTA BIT(10)
#define MT_TXD1_WLAN_IDX GENMASK(9, 0)
#define MT_TXD2_FIX_RATE BIT(31)
#define MT_TXD2_FIXED_RATE BIT(30)
#define MT_TXD2_POWER_OFFSET GENMASK(29, 24)
#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16)
#define MT_TXD2_FRAG GENMASK(15, 14)
#define MT_TXD2_HTC_VLD BIT(13)
#define MT_TXD2_DURATION BIT(12)
#define MT_TXD2_BIP BIT(11)
#define MT_TXD2_MULTICAST BIT(10)
#define MT_TXD2_RTS BIT(9)
#define MT_TXD2_SOUNDING BIT(8)
#define MT_TXD2_NDPA BIT(7)
#define MT_TXD2_NDP BIT(6)
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
#define MT_TXD3_SN_VALID BIT(31)
#define MT_TXD3_PN_VALID BIT(30)
#define MT_TXD3_SW_POWER_MGMT BIT(29)
#define MT_TXD3_BA_DISABLE BIT(28)
#define MT_TXD3_SEQ GENMASK(27, 16)
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
#define MT_TXD3_TIMING_MEASURE BIT(5)
#define MT_TXD3_DAS BIT(4)
#define MT_TXD3_EEOSP BIT(3)
#define MT_TXD3_EMRD BIT(2)
#define MT_TXD3_PROTECT_FRAME BIT(1)
#define MT_TXD3_NO_ACK BIT(0)
#define MT_TXD4_PN_LOW GENMASK(31, 0)
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
#define MT_TXD5_MD BIT(15)
#define MT_TXD5_ADD_BA BIT(14)
#define MT_TXD5_TX_STATUS_HOST BIT(10)
#define MT_TXD5_TX_STATUS_MCU BIT(9)
#define MT_TXD5_TX_STATUS_FMT BIT(8)
#define MT_TXD5_PID GENMASK(7, 0)
#define MT_TXD6_TX_IBF BIT(31)
#define MT_TXD6_TX_EBF BIT(30)
#define MT_TXD6_TX_RATE GENMASK(29, 16)
#define MT_TXD6_SGI GENMASK(15, 14)
#define MT_TXD6_HELTF GENMASK(13, 12)
#define MT_TXD6_LDPC BIT(11)
#define MT_TXD6_SPE_ID_IDX BIT(10)
#define MT_TXD6_ANT_ID GENMASK(7, 4)
#define MT_TXD6_DYN_BW BIT(3)
#define MT_TXD6_FIXED_BW BIT(2)
#define MT_TXD6_BW GENMASK(1, 0)
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
#define MT_TXD7_UDP_TCP_SUM BIT(29)
#define MT_TXD7_IP_SUM BIT(28)
#define MT_TXD7_TYPE GENMASK(21, 20)
#define MT_TXD7_SUB_TYPE GENMASK(19, 16)
#define MT_TXD7_PSE_FID GENMASK(27, 16)
#define MT_TXD7_SPE_IDX GENMASK(15, 11)
#define MT_TXD7_HW_AMSDU BIT(10)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
#define MT_TXD8_L_TYPE GENMASK(5, 4)
#define MT_TXD8_L_SUB_TYPE GENMASK(3, 0)
#define MT_TX_RATE_STBC BIT(13)
#define MT_TX_RATE_NSS GENMASK(12, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
#define MT_TX_RATE_DCM BIT(4)
#define MT_TX_RATE_IDX GENMASK(3, 0)
#define MT_TXP_MAX_BUF_NUM 6
struct mt7921_txp {
__le16 flags;
__le16 token;
u8 bss_idx;
__le16 rept_wds_wcid;
u8 nbuf;
__le32 buf[MT_TXP_MAX_BUF_NUM];
__le16 len[MT_TXP_MAX_BUF_NUM];
} __packed __aligned(4);
struct mt7921_tx_free {
__le16 rx_byte_cnt;
__le16 ctrl;
u8 txd_cnt;
u8 rsv[3];
__le32 info[];
} __packed __aligned(4);
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
@ -325,56 +39,6 @@ struct mt7921_tx_free {
/* will support this field in further revision */
#define MT_TX_FREE_RATE GENMASK(13, 0)
#define MT_TXS0_BW GENMASK(30, 29)
#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
#define MT_TXS0_TX_RATE GENMASK(13, 0)
#define MT_TXS2_WCID GENMASK(25, 16)
#define MT_TXS3_PID GENMASK(31, 24)
static inline struct mt7921_txp_common *
mt7921_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
{
u8 *txwi;
if (!t)
return NULL;
txwi = mt76_get_txwi_ptr(dev, t);
return (struct mt7921_txp_common *)(txwi + MT_TXD_SIZE);
}
#define MT_HW_TXP_MAX_MSDU_NUM 4
#define MT_HW_TXP_MAX_BUF_NUM 4
#define MT_MSDU_ID_VALID BIT(15)
#define MT_TXD_LEN_MASK GENMASK(11, 0)
#define MT_TXD_LEN_MSDU_LAST BIT(14)
#define MT_TXD_LEN_AMSDU_LAST BIT(15)
#define MT_TXD_LEN_LAST BIT(15)
struct mt7921_txp_ptr {
__le32 buf0;
__le16 len0;
__le16 len1;
__le32 buf1;
} __packed __aligned(4);
struct mt7921_hw_txp {
__le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM];
struct mt7921_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2];
} __packed __aligned(4);
struct mt7921_txp_common {
union {
struct mt7921_hw_txp hw;
};
};
#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7
#define MT_WTBL_TXRX_RATE_G2_HE 24
#define MT_WTBL_TXRX_RATE_G2 12

View File

@ -257,7 +257,7 @@ int __mt7921_start(struct mt7921_phy *phy)
if (err)
return err;
err = mt76_connac_mcu_set_rate_txpower(phy->mt76);
err = mt7921_set_tx_sar_pwr(mphy->hw, NULL);
if (err)
return err;
@ -322,7 +322,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
mvif->mt76.omac_idx = mvif->mt76.idx;
mvif->phy = phy;
mvif->mt76.band_idx = 0;
mvif->mt76.wmm_idx = mvif->mt76.idx % MT7921_MAX_WMM_SETS;
mvif->mt76.wmm_idx = mvif->mt76.idx % MT76_CONNAC_MAX_WMM_SETS;
ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid,
true);
@ -336,7 +336,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
mt76_packet_id_init(&mvif->sta.wcid);
@ -352,6 +352,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
mtxq->wcid = idx;
}
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
out:
mt7921_mutex_release(dev);
@ -495,8 +496,21 @@ static void
mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct mt7921_dev *dev = priv;
struct ieee80211_hw *hw = mt76_hw(dev);
bool pm_enable = dev->pm.enable;
int err;
mt7921_mcu_set_beacon_filter(dev, vif, dev->pm.enable);
err = mt7921_mcu_set_beacon_filter(dev, vif, pm_enable);
if (err < 0)
return;
if (pm_enable) {
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
ieee80211_hw_set(hw, CONNECTION_MONITOR);
} else {
vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
__clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags);
}
}
static void
@ -548,7 +562,7 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
mt7921_mutex_acquire(dev);
if (changed & IEEE80211_CONF_CHANGE_POWER) {
ret = mt76_connac_mcu_set_rate_txpower(phy->mt76);
ret = mt7921_set_tx_sar_pwr(hw, NULL);
if (ret)
goto out;
}
@ -567,7 +581,8 @@ out:
}
static int
mt7921_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
mt7921_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
@ -653,15 +668,6 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
}
}
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
true);
mt7921_mcu_sta_update(dev, NULL, vif, true,
MT76_STA_INFO_STATE_NONE);
}
if (changed & (BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED))
mt7921_mcu_uni_add_beacon_offload(dev, hw, vif,
@ -677,8 +683,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ASSOC) {
mt7921_mcu_sta_update(dev, NULL, vif, true,
MT76_STA_INFO_STATE_ASSOC);
if (dev->pm.enable)
mt7921_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
mt7921_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
}
if (changed & BSS_CHANGED_ARP_FILTER) {
@ -707,7 +712,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
msta->wcid.ext_phy = mvif->mt76.band_idx;
msta->wcid.phy_idx = mvif->mt76.band_idx;
msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
msta->last_txs = jiffies;
@ -1177,7 +1182,7 @@ void mt7921_scan_work(struct work_struct *work)
scan_work.work);
while (true) {
struct mt7921_mcu_rxd *rxd;
struct mt76_connac2_mcu_rxd *rxd;
struct sk_buff *skb;
spin_lock_bh(&phy->dev->mt76.lock);
@ -1187,7 +1192,7 @@ void mt7921_scan_work(struct work_struct *work)
if (!skb)
break;
rxd = (struct mt7921_mcu_rxd *)skb->data;
rxd = (struct mt76_connac2_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,
@ -1450,15 +1455,14 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw,
if (!idx)
return;
skb = __mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) +
idx * sizeof(struct in6_addr), GFP_ATOMIC);
if (!skb)
return;
req_hdr.arpns.ips_num = idx;
req_hdr.arpns.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)
+ idx * sizeof(struct in6_addr));
skb_put_data(skb, &req_hdr, sizeof(req_hdr));
skb = __mt76_mcu_msg_alloc(&dev->mt76, &req_hdr,
sizeof(req_hdr) + idx * sizeof(struct in6_addr),
sizeof(req_hdr), GFP_ATOMIC);
if (!skb)
return;
for (i = 0; i < idx; i++)
skb_put_data(skb, &ns_addrs[i].in6_u, sizeof(struct in6_addr));
@ -1469,20 +1473,33 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw,
}
#endif
int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar)
{
struct mt76_phy *mphy = hw->priv;
int err;
if (sar) {
err = mt76_init_sar_power(hw, sar);
if (err)
return err;
}
mt7921_init_acpi_sar_power(mt7921_hw_phy(hw), !sar);
err = mt76_connac_mcu_set_rate_txpower(mphy);
return err;
}
static int mt7921_set_sar_specs(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar)
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);
struct mt76_phy *mphy = hw->priv;
int err;
mt7921_mutex_acquire(dev);
err = mt76_init_sar_power(hw, sar);
if (err)
goto out;
err = mt76_connac_mcu_set_rate_txpower(mphy);
out:
err = mt7921_set_tx_sar_pwr(hw, sar);
mt7921_mutex_release(dev);
return err;
@ -1500,6 +1517,44 @@ mt7921_channel_switch_beacon(struct ieee80211_hw *hw,
mt7921_mutex_release(dev);
}
static int
mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt7921_phy *phy = mt7921_hw_phy(hw);
struct mt7921_dev *dev = mt7921_hw_dev(hw);
int err;
err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
true);
if (err)
return err;
err = mt7921_mcu_set_bss_pm(dev, vif, true);
if (err)
return err;
return mt7921_mcu_sta_update(dev, NULL, vif, true,
MT76_STA_INFO_STATE_NONE);
}
static void
mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt7921_phy *phy = mt7921_hw_phy(hw);
struct mt7921_dev *dev = mt7921_hw_dev(hw);
int err;
err = mt7921_mcu_set_bss_pm(dev, vif, false);
if (err)
return;
mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false);
}
const struct ieee80211_ops mt7921_ops = {
.tx = mt7921_tx,
.start = mt7921_start,
@ -1510,6 +1565,8 @@ const struct ieee80211_ops mt7921_ops = {
.conf_tx = mt7921_conf_tx,
.configure_filter = mt7921_configure_filter,
.bss_info_changed = mt7921_bss_info_changed,
.start_ap = mt7921_start_ap,
.stop_ap = mt7921_stop_ap,
.sta_state = mt7921_sta_state,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
.set_key = mt7921_set_key,

View File

@ -1,79 +1,15 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
#include <linux/firmware.h>
#include <linux/fs.h>
#include "mt7921.h"
#include "mt7921_trace.h"
#include "mcu.h"
#include "mac.h"
struct mt7921_patch_hdr {
char build_date[16];
char platform[4];
__be32 hw_sw_ver;
__be32 patch_ver;
__be16 checksum;
u16 reserved;
struct {
__be32 patch_ver;
__be32 subsys;
__be32 feature;
__be32 n_region;
__be32 crc;
u32 reserved[11];
} desc;
} __packed;
struct mt7921_patch_sec {
__be32 type;
__be32 offs;
__be32 size;
union {
__be32 spec[13];
struct {
__be32 addr;
__be32 len;
__be32 sec_key_idx;
__be32 align_len;
u32 reserved[9];
} info;
};
} __packed;
struct mt7921_fw_trailer {
u8 chip_id;
u8 eco_code;
u8 n_region;
u8 format_ver;
u8 format_flag;
u8 reserved[2];
char fw_ver[10];
char build_date[15];
u32 crc;
} __packed;
struct mt7921_fw_region {
__le32 decomp_crc;
__le32 decomp_len;
__le32 decomp_blk_sz;
u8 reserved[4];
__le32 addr;
__le32 len;
u8 feature_set;
u8 reserved1[15];
} __packed;
#define MT_STA_BFER BIT(0)
#define MT_STA_BFEE BIT(1)
#define PATCH_SEC_ENC_TYPE_MASK GENMASK(31, 24)
#define PATCH_SEC_ENC_TYPE_PLAIN 0x00
#define PATCH_SEC_ENC_TYPE_AES 0x01
#define PATCH_SEC_ENC_TYPE_SCRAMBLE 0x02
#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK GENMASK(15, 0)
#define PATCH_SEC_ENC_AES_KEY_MASK GENMASK(7, 0)
static int
mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb)
{
@ -83,7 +19,7 @@ mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb)
if (!skb)
return -EINVAL;
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
res = (struct mt7921_mcu_eeprom_info *)skb->data;
buf = dev->eeprom.data + le32_to_cpu(res->addr);
@ -96,7 +32,7 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
struct sk_buff *skb, int seq)
{
int mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
struct mt7921_mcu_rxd *rxd;
struct mt76_connac2_mcu_rxd *rxd;
int ret = 0;
if (!skb) {
@ -107,11 +43,12 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
return -ETIMEDOUT;
}
rxd = (struct mt7921_mcu_rxd *)skb->data;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
if (seq != rxd->seq)
return -EAGAIN;
if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {
if (cmd == MCU_CMD(PATCH_SEM_CONTROL) ||
cmd == MCU_CMD(PATCH_FINISH_REQ)) {
skb_pull(skb, sizeof(*rxd) - 4);
ret = *skb->data;
} else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {
@ -140,90 +77,13 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
event = (struct mt7921_mcu_reg_event *)skb->data;
ret = (int)le32_to_cpu(event->val);
} else {
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
}
return ret;
}
EXPORT_SYMBOL_GPL(mt7921_mcu_parse_response);
int mt7921_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *wait_seq)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
struct mt7921_uni_txd *uni_txd;
struct mt7921_mcu_txd *mcu_txd;
__le32 *txd;
u32 val;
u8 seq;
if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
cmd == MCU_UNI_CMD(SUSPEND) ||
cmd == MCU_UNI_CMD(OFFLOAD))
mdev->mcu.timeout = HZ;
else
mdev->mcu.timeout = 3 * HZ;
seq = ++dev->mt76.mcu.msg_seq & 0xf;
if (!seq)
seq = ++dev->mt76.mcu.msg_seq & 0xf;
if (cmd == MCU_CMD(FW_SCATTER))
goto exit;
txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd);
txd = (__le32 *)skb_push(skb, txd_len);
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |
FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) |
FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0);
txd[0] = cpu_to_le32(val);
val = MT_TXD1_LONG_FORMAT |
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD);
txd[1] = cpu_to_le32(val);
if (cmd & __MCU_CMD_FIELD_UNI) {
uni_txd = (struct mt7921_uni_txd *)txd;
uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd));
uni_txd->option = MCU_CMD_UNI_EXT_ACK;
uni_txd->cid = cpu_to_le16(mcu_cmd);
uni_txd->s2d_index = MCU_S2D_H2N;
uni_txd->pkt_type = MCU_PKT_ID;
uni_txd->seq = seq;
goto exit;
}
mcu_txd = (struct mt7921_mcu_txd *)txd;
mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd));
mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU,
MT_TX_MCU_PORT_RX_Q0));
mcu_txd->pkt_type = MCU_PKT_ID;
mcu_txd->seq = seq;
mcu_txd->cid = mcu_cmd;
mcu_txd->s2d_index = MCU_S2D_H2N;
mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd);
if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) {
if (cmd & __MCU_CMD_FIELD_QUERY)
mcu_txd->set_query = MCU_Q_QUERY;
else
mcu_txd->set_query = MCU_Q_SET;
mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid;
} else {
mcu_txd->set_query = MCU_Q_NA;
}
exit:
if (wait_seq)
*wait_seq = seq;
return 0;
}
EXPORT_SYMBOL_GPL(mt7921_mcu_fill_message);
#ifdef CONFIG_PM
static int
@ -304,7 +164,7 @@ mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb)
struct mt76_connac_beacon_loss_event *event;
struct mt76_phy *mphy = &dev->mt76.phy;
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
event = (struct mt76_connac_beacon_loss_event *)skb->data;
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
@ -318,7 +178,7 @@ mt7921_mcu_bss_event(struct mt7921_dev *dev, struct sk_buff *skb)
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_mcu_bss_event *event;
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
event = (struct mt76_connac_mcu_bss_event *)skb->data;
if (event->is_absent)
ieee80211_stop_queues(mphy->hw);
@ -338,7 +198,7 @@ mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb)
u8 content[512];
} __packed * msg;
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
msg = (struct mt7921_debug_msg *)skb->data;
if (msg->type == 3) { /* fw log */
@ -361,7 +221,7 @@ mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb)
u8 reserved[3];
} __packed * event;
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
event = (struct mt7921_mcu_lp_event *)skb->data;
trace_lp_event(dev, event->state);
@ -372,7 +232,7 @@ mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb)
{
struct mt7921_mcu_tx_done_event *event;
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
event = (struct mt7921_mcu_tx_done_event *)skb->data;
mt7921_mac_add_txs(dev, event->txs);
@ -381,8 +241,9 @@ mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb)
static void
mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
{
struct mt7921_mcu_rxd *rxd = (struct mt7921_mcu_rxd *)skb->data;
struct mt76_connac2_mcu_rxd *rxd;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
switch (rxd->eid) {
case MCU_EVENT_BSS_BEACON_LOSS:
mt7921_mcu_connection_loss_event(dev, skb);
@ -416,12 +277,12 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
{
struct mt7921_mcu_rxd *rxd;
struct mt76_connac2_mcu_rxd *rxd;
if (skb_linearize(skb))
return;
rxd = (struct mt7921_mcu_rxd *)skb->data;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
if (rxd->eid == 0x6) {
mt76_mcu_rx_event(&dev->mt76, skb);
@ -469,34 +330,6 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
enable, false);
}
static u32 mt7921_get_data_mode(struct mt7921_dev *dev, u32 info)
{
u32 mode = DL_MODE_NEED_RSP;
if (info == PATCH_SEC_NOT_SUPPORT)
return mode;
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
case PATCH_SEC_ENC_TYPE_PLAIN:
break;
case PATCH_SEC_ENC_TYPE_AES:
mode |= DL_MODE_ENCRYPT;
mode |= FIELD_PREP(DL_MODE_KEY_IDX,
(info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX;
mode |= DL_MODE_RESET_SEC_IV;
break;
case PATCH_SEC_ENC_TYPE_SCRAMBLE:
mode |= DL_MODE_ENCRYPT;
mode |= DL_CONFIG_ENCRY_MODE_SEL;
mode |= DL_MODE_RESET_SEC_IV;
break;
default:
dev_err(dev->mt76.dev, "Encryption type not support!\n");
}
return mode;
}
static char *mt7921_patch_name(struct mt7921_dev *dev)
{
char *ret;
@ -509,152 +342,6 @@ static char *mt7921_patch_name(struct mt7921_dev *dev)
return ret;
}
static int mt7921_load_patch(struct mt7921_dev *dev)
{
const struct mt7921_patch_hdr *hdr;
const struct firmware *fw = NULL;
int i, ret, sem, max_len;
max_len = mt76_is_sdio(&dev->mt76) ? 2048 : 4096;
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, true);
switch (sem) {
case PATCH_IS_DL:
return 0;
case PATCH_NOT_DL_SEM_SUCCESS:
break;
default:
dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");
return -EAGAIN;
}
ret = request_firmware(&fw, mt7921_patch_name(dev), dev->mt76.dev);
if (ret)
goto out;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->mt76.dev, "Invalid firmware\n");
ret = -EINVAL;
goto out;
}
hdr = (const struct mt7921_patch_hdr *)(fw->data);
dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
struct mt7921_patch_sec *sec;
const u8 *dl;
u32 len, addr, mode;
u32 sec_info = 0;
sec = (struct mt7921_patch_sec *)(fw->data + sizeof(*hdr) +
i * sizeof(*sec));
if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
PATCH_SEC_TYPE_INFO) {
ret = -EINVAL;
goto out;
}
addr = be32_to_cpu(sec->info.addr);
len = be32_to_cpu(sec->info.len);
dl = fw->data + be32_to_cpu(sec->offs);
sec_info = be32_to_cpu(sec->info.sec_key_idx);
mode = mt7921_get_data_mode(dev, sec_info);
ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
mode);
if (ret) {
dev_err(dev->mt76.dev, "Download request failed\n");
goto out;
}
ret = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
dl, len, max_len);
if (ret) {
dev_err(dev->mt76.dev, "Failed to send patch\n");
goto out;
}
}
ret = mt76_connac_mcu_start_patch(&dev->mt76);
if (ret)
dev_err(dev->mt76.dev, "Failed to start patch\n");
if (mt76_is_sdio(&dev->mt76)) {
/* activate again */
ret = __mt7921_mcu_fw_pmctrl(dev);
if (!ret)
ret = __mt7921_mcu_drv_pmctrl(dev);
}
out:
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);
switch (sem) {
case PATCH_REL_SEM_SUCCESS:
break;
default:
ret = -EAGAIN;
dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");
break;
}
release_firmware(fw);
return ret;
}
static int
mt7921_mcu_send_ram_firmware(struct mt7921_dev *dev,
const struct mt7921_fw_trailer *hdr,
const u8 *data, bool is_wa)
{
int i, offset = 0, max_len;
u32 override = 0, option = 0;
max_len = mt76_is_sdio(&dev->mt76) ? 2048 : 4096;
for (i = 0; i < hdr->n_region; i++) {
const struct mt7921_fw_region *region;
int err;
u32 len, addr, mode;
region = (const struct mt7921_fw_region *)((const u8 *)hdr -
(hdr->n_region - i) * sizeof(*region));
mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
region->feature_set, is_wa);
len = le32_to_cpu(region->len);
addr = le32_to_cpu(region->addr);
if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR)
override = addr;
err = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
mode);
if (err) {
dev_err(dev->mt76.dev, "Download request failed\n");
return err;
}
err = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
data + offset, len, max_len);
if (err) {
dev_err(dev->mt76.dev, "Failed to send firmware.\n");
return err;
}
offset += len;
}
if (override)
option |= FW_START_OVERRIDE;
if (is_wa)
option |= FW_START_WORKING_PDA_CR4;
return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
}
static char *mt7921_ram_name(struct mt7921_dev *dev)
{
char *ret;
@ -667,44 +354,6 @@ static char *mt7921_ram_name(struct mt7921_dev *dev)
return ret;
}
static int mt7921_load_ram(struct mt7921_dev *dev)
{
const struct mt7921_fw_trailer *hdr;
const struct firmware *fw;
int ret;
ret = request_firmware(&fw, mt7921_ram_name(dev), dev->mt76.dev);
if (ret)
return ret;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->mt76.dev, "Invalid firmware\n");
ret = -EINVAL;
goto out;
}
hdr = (const struct mt7921_fw_trailer *)(fw->data + fw->size -
sizeof(*hdr));
dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
ret = mt7921_mcu_send_ram_firmware(dev, hdr, fw->data, false);
if (ret) {
dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
goto out;
}
snprintf(dev->mt76.hw->wiphy->fw_version,
sizeof(dev->mt76.hw->wiphy->fw_version),
"%.10s-%.15s", hdr->fw_ver, hdr->build_date);
out:
release_firmware(fw);
return ret;
}
static int mt7921_load_firmware(struct mt7921_dev *dev)
{
int ret;
@ -715,11 +364,18 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
goto fw_loaded;
}
ret = mt7921_load_patch(dev);
ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev));
if (ret)
return ret;
ret = mt7921_load_ram(dev);
if (mt76_is_sdio(&dev->mt76)) {
/* activate again */
ret = __mt7921_mcu_fw_pmctrl(dev);
if (!ret)
ret = __mt7921_mcu_drv_pmctrl(dev);
}
ret = mt76_connac2_load_ram(&dev->mt76, mt7921_ram_name(dev), NULL);
if (ret)
return ret;
@ -771,12 +427,6 @@ int mt7921_run_firmware(struct mt7921_dev *dev)
}
EXPORT_SYMBOL_GPL(mt7921_run_firmware);
void mt7921_mcu_exit(struct mt7921_dev *dev)
{
skb_queue_purge(&dev->mt76.mcu.res_q);
}
EXPORT_SYMBOL_GPL(mt7921_mcu_exit);
int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
@ -972,7 +622,7 @@ int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif)
.ps = {
.tag = cpu_to_le16(UNI_BSS_INFO_PS),
.len = cpu_to_le16(sizeof(struct ps_tlv)),
.ps_state = vif->bss_conf.ps ? 2 : 0,
.ps_state = vif->cfg.ps ? 2 : 0,
},
};
@ -1019,7 +669,7 @@ mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif,
&bcnft_req, sizeof(bcnft_req), true);
}
static int
int
mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
bool enable)
{
@ -1048,9 +698,6 @@ mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
};
int err;
if (vif->type != NL80211_IFTYPE_STATION)
return 0;
err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT),
&req_hdr, sizeof(req_hdr), false);
if (err < 0 || !enable)
@ -1132,7 +779,6 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
struct ieee80211_vif *vif,
bool enable)
{
struct ieee80211_hw *hw = mt76_hw(dev);
int err;
if (enable) {
@ -1140,8 +786,6 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
if (err)
return err;
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
ieee80211_hw_set(hw, CONNECTION_MONITOR);
mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
return 0;
@ -1151,8 +795,6 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
if (err)
return err;
vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
__clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags);
mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
return 0;
@ -1255,8 +897,11 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
};
struct sk_buff *skb;
/* support enable/update process only
* disable flow would be handled in bss stop handler automatically
*/
if (!enable)
goto out;
return -EOPNOTSUPP;
skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0);
if (!skb)
@ -1268,8 +913,8 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
return -EINVAL;
}
mt7921_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb,
wcid, NULL, 0, true);
mt76_connac2_mac_write_txwi(&dev->mt76, (__le32 *)(req.beacon_tlv.pkt),
skb, wcid, NULL, 0, 0, BSS_CHANGED_BEACON);
memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);
req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
@ -1282,7 +927,6 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
}
dev_kfree_skb(skb);
out:
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),
&req, sizeof(req), true);
}

View File

@ -6,76 +6,6 @@
#include "../mt76_connac_mcu.h"
struct mt7921_mcu_txd {
__le32 txd[8];
__le16 len;
__le16 pq_id;
u8 cid;
u8 pkt_type;
u8 set_query; /* FW don't care */
u8 seq;
u8 uc_d2b0_rev;
u8 ext_cid;
u8 s2d_index;
u8 ext_cid_ack;
u32 reserved[5];
} __packed __aligned(4);
/**
* struct mt7921_uni_txd - mcu command descriptor for firmware v3
* @txd: hardware descriptor
* @len: total length not including txd
* @cid: command identifier
* @pkt_type: must be 0xa0 (cmd packet by long format)
* @frag_n: fragment number
* @seq: sequence number
* @checksum: 0 mean there is no checksum
* @s2d_index: index for command source and destination
* Definition | value | note
* CMD_S2D_IDX_H2N | 0x00 | command from HOST to WM
* CMD_S2D_IDX_C2N | 0x01 | command from WA to WM
* CMD_S2D_IDX_H2C | 0x02 | command from HOST to WA
* CMD_S2D_IDX_H2N_AND_H2C | 0x03 | command from HOST to WA and WM
*
* @option: command option
* BIT[0]: UNI_CMD_OPT_BIT_ACK
* set to 1 to request a fw reply
* if UNI_CMD_OPT_BIT_0_ACK is set and UNI_CMD_OPT_BIT_2_SET_QUERY
* is set, mcu firmware will send response event EID = 0x01
* (UNI_EVENT_ID_CMD_RESULT) to the host.
* BIT[1]: UNI_CMD_OPT_BIT_UNI_CMD
* 0: original command
* 1: unified command
* BIT[2]: UNI_CMD_OPT_BIT_SET_QUERY
* 0: QUERY command
* 1: SET command
*/
struct mt7921_uni_txd {
__le32 txd[8];
/* DW1 */
__le16 len;
__le16 cid;
/* DW2 */
u8 reserved;
u8 pkt_type;
u8 frag_n;
u8 seq;
/* DW3 */
__le16 checksum;
u8 s2d_index;
u8 option;
/* DW4 */
u8 reserved2[4];
} __packed __aligned(4);
struct mt7921_mcu_tx_done_event {
u8 pid;
u8 status;
@ -108,21 +38,6 @@ enum {
MCU_EXT_EVENT_RATE_REPORT = 0x87,
};
struct mt7921_mcu_rxd {
__le32 rxd[6];
__le16 len;
__le16 pkt_type_id;
u8 eid;
u8 seq;
__le16 __rsv;
u8 ext_eid;
u8 __rsv1[2];
u8 s2d_index;
};
struct mt7921_mcu_eeprom_info {
__le32 addr;
__le32 valid;
@ -135,9 +50,6 @@ struct mt7921_mcu_eeprom_info {
#define MT_RA_RATE_DCM_EN BIT(4)
#define MT_RA_RATE_BW GENMASK(14, 13)
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
#define MCU_PKT_ID 0xa0
struct mt7921_mcu_uni_event {
u8 cid;
u8 pad[3];

View File

@ -8,9 +8,9 @@
#include <linux/ktime.h>
#include "../mt76_connac_mcu.h"
#include "regs.h"
#include "acpi_sar.h"
#define MT7921_MAX_INTERFACES 4
#define MT7921_MAX_WMM_SETS 4
#define MT7921_WTBL_SIZE 20
#define MT7921_WTBL_RESERVED (MT7921_WTBL_SIZE - 1)
#define MT7921_WTBL_STA (MT7921_WTBL_RESERVED - \
@ -171,6 +171,9 @@ struct mt7921_phy {
struct sk_buff_head scan_event_list;
struct delayed_work scan_work;
#ifdef CONFIG_ACPI
struct mt7921_acpi_sar *acpisar;
#endif
};
#define mt7921_init_reset(dev) ((dev)->hif_ops->init_reset(dev))
@ -247,16 +250,6 @@ struct mt7921_txpwr {
} data[TXPWR_MAX_NUM];
};
enum {
MT_LMAC_AC00,
MT_LMAC_AC01,
MT_LMAC_AC02,
MT_LMAC_AC03,
MT_LMAC_ALTX0 = 0x10,
MT_LMAC_BMC0,
MT_LMAC_BCN0,
};
static inline struct mt7921_phy *
mt7921_hw_phy(struct ieee80211_hw *hw)
{
@ -279,7 +272,6 @@ mt7921_hw_dev(struct ieee80211_hw *hw)
mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
extern const struct ieee80211_ops mt7921_ops;
extern struct pci_driver mt7921_pci_driver;
u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr);
@ -291,6 +283,8 @@ int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force);
int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev);
void mt7921_dma_cleanup(struct mt7921_dev *dev);
int mt7921_run_firmware(struct mt7921_dev *dev);
int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
struct ieee80211_vif *vif, bool enable,
enum mt76_sta_info_state state);
@ -301,7 +295,6 @@ int mt7921_mcu_get_rx_rate(struct mt7921_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct rate_info *rate);
int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl);
void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb);
void mt7921_mcu_exit(struct mt7921_dev *dev);
static inline void mt7921_irq_enable(struct mt7921_dev *dev, u32 mask)
{
@ -352,12 +345,6 @@ static inline bool mt7921_dma_need_reinit(struct mt7921_dev *dev)
return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
}
static inline void mt7921_mcu_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 inline void
mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb,
int type)
@ -392,7 +379,6 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct mt76_tx_info *tx_info);
void mt7921_tx_worker(struct mt76_worker *w);
void mt7921e_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt7921_tx_token_put(struct mt7921_dev *dev);
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);
@ -424,14 +410,8 @@ int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len);
int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
struct netlink_callback *cb, void *data, int len);
void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, int pid,
bool beacon);
void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi);
void mt7921_mac_sta_poll(struct mt7921_dev *dev);
int mt7921_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, int *wait_seq);
int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
struct sk_buff *skb, int seq);
@ -481,4 +461,22 @@ int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
bool enable);
#ifdef CONFIG_ACPI
int mt7921_init_acpi_sar(struct mt7921_dev *dev);
int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default);
#else
static inline int
mt7921_init_acpi_sar(struct mt7921_dev *dev)
{
return 0;
}
static inline int
mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
{
return 0;
}
#endif
int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar);
#endif

View File

@ -116,7 +116,7 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
mt7921_mcu_drv_pmctrl(dev);
mt7921_dma_cleanup(dev);
mt7921_wfsys_reset(dev);
mt7921_mcu_exit(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
tasklet_disable(&dev->irq_tasklet);
}
@ -230,14 +230,14 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
{
static const struct mt76_driver_ops drv_ops = {
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7921_txp_common),
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_hw_txp),
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
.token_size = MT7921_TOKEN_SIZE,
.tx_prepare_skb = mt7921e_tx_prepare_skb,
.tx_complete_skb = mt7921e_tx_complete_skb,
.tx_complete_skb = mt76_connac_tx_complete_skb,
.rx_check = mt7921e_rx_check,
.rx_skb = mt7921e_queue_rx_skb,
.rx_poll_complete = mt7921_rx_poll_complete,
@ -247,7 +247,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
.sta_remove = mt7921_mac_sta_remove,
.update_survey = mt7921_update_channel,
};
static const struct mt7921_hif_ops mt7921_pcie_ops = {
.init_reset = mt7921e_init_reset,
.reset = mt7921e_mac_reset,
@ -359,9 +358,9 @@ static void mt7921_pci_remove(struct pci_dev *pdev)
pci_free_irq_vectors(pdev);
}
#ifdef CONFIG_PM
static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
static int mt7921_pci_suspend(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt76_connac_pm *pm = &dev->pm;
@ -391,8 +390,6 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
napi_disable(&mdev->napi[i]);
}
pci_enable_wake(pdev, pci_choose_state(pdev, state), true);
/* wait until dma is idle */
mt76_poll(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
@ -412,8 +409,6 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
if (err)
goto restore_napi;
pci_save_state(pdev);
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
if (err)
goto restore_napi;
@ -436,19 +431,14 @@ restore_suspend:
return err;
}
static int mt7921_pci_resume(struct pci_dev *pdev)
static int mt7921_pci_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct mt76_connac_pm *pm = &dev->pm;
int i, err;
err = pci_set_power_state(pdev, PCI_D0);
if (err)
return err;
pci_restore_state(pdev);
err = mt7921_mcu_drv_pmctrl(dev);
if (err < 0)
return err;
@ -488,17 +478,15 @@ static int mt7921_pci_resume(struct pci_dev *pdev)
return err;
}
#endif /* CONFIG_PM */
struct pci_driver mt7921_pci_driver = {
static DEFINE_SIMPLE_DEV_PM_OPS(mt7921_pm_ops, mt7921_pci_suspend, mt7921_pci_resume);
static struct pci_driver mt7921_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = mt7921_pci_device_table,
.probe = mt7921_pci_probe,
.remove = mt7921_pci_remove,
#ifdef CONFIG_PM
.suspend = mt7921_pci_suspend,
.resume = mt7921_pci_resume,
#endif /* CONFIG_PM */
.driver.pm = pm_sleep_ptr(&mt7921_pm_ops),
};
module_pci_driver(mt7921_pci_driver);

View File

@ -5,37 +5,6 @@
#include "../dma.h"
#include "mac.h"
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);
}
}
}
int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
@ -44,8 +13,8 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
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_connac_hw_txp *txp;
struct mt76_txwi_cache *t;
struct mt7921_txp_common *txp;
int id, pid;
u8 *txwi = (u8 *)txwi_ptr;
@ -72,49 +41,18 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
}
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
mt7921_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
pid, false);
mt76_connac2_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, key,
pid, qid, 0);
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);
txp = (struct mt76_connac_hw_txp *)(txwi + MT_TXD_SIZE);
memset(txp, 0, sizeof(struct mt76_connac_hw_txp));
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
tx_info->skb = DMA_DUMMY_DATA;
return 0;
}
static 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;
}
}
static void
mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta, bool clear_status,
@ -124,7 +62,7 @@ mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
__le32 *txwi;
u16 wcid_idx;
mt7921_txp_skb_unmap(mdev, t);
mt76_connac_txp_skb_unmap(mdev, t);
if (!t->skb)
goto out;
@ -150,7 +88,8 @@ out:
static void
mt7921e_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
{
struct mt7921_tx_free *free = (struct mt7921_tx_free *)data;
struct mt76_connac_tx_free *free = data;
__le32 *tx_info = (__le32 *)(data + sizeof(*free));
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
@ -165,11 +104,11 @@ mt7921e_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
if (WARN_ON_ONCE((void *)&free->info[count] > end))
if (WARN_ON_ONCE((void *)&tx_info[count] > end))
return;
for (i = 0; i < count; i++) {
u32 msdu, info = le32_to_cpu(free->info[i]);
u32 msdu, info = le32_to_cpu(tx_info[i]);
u8 stat;
/* 1'b1: new wcid pair.
@ -262,29 +201,6 @@ void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
}
}
void mt7921e_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
{
if (!e->txwi) {
dev_kfree_skb_any(e->skb);
return;
}
/* 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;
t = mt76_token_put(mdev, token);
e->skb = t ? t->skb : NULL;
}
if (e->skb)
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
}
void mt7921_tx_token_put(struct mt7921_dev *dev)
{
struct mt76_txwi_cache *txwi;

View File

@ -26,10 +26,17 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
enum mt76_mcuq_id txq = MT_MCUQ_WM;
int ret;
ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq);
ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
if (ret)
return ret;
if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
cmd == MCU_UNI_CMD(SUSPEND) ||
cmd == MCU_UNI_CMD(OFFLOAD))
mdev->mcu.timeout = HZ;
else
mdev->mcu.timeout = 3 * HZ;
if (cmd == MCU_CMD(FW_SCATTER))
txq = MT_MCUQ_FWDL;
@ -39,7 +46,7 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int mt7921e_mcu_init(struct mt7921_dev *dev)
{
static const struct mt76_mcu_ops mt7921_mcu_ops = {
.headroom = sizeof(struct mt7921_mcu_txd),
.headroom = sizeof(struct mt76_connac2_mcu_txd),
.mcu_skb_send_msg = mt7921_mcu_send_message,
.mcu_parse_response = mt7921_mcu_parse_response,
.mcu_restart = mt76_connac_mcu_restart,
@ -102,7 +109,7 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int i, err = 0;
int i;
for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN);
@ -114,12 +121,12 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev)
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "firmware own failed\n");
clear_bit(MT76_STATE_PM, &mphy->state);
err = -EIO;
return -EIO;
}
pm->stats.last_doze_event = jiffies;
pm->stats.awake_time += pm->stats.last_doze_event -
pm->stats.last_wake_event;
return err;
return 0;
}

View File

@ -48,7 +48,7 @@ static void mt7921s_unregister_device(struct mt7921_dev *dev)
mt76s_deinit(&dev->mt76);
mt7921s_wfsys_reset(dev);
mt7921_mcu_exit(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76_free_device(&dev->mt76);
}

View File

@ -29,10 +29,17 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
if (dev->fw_assert)
return -EBUSY;
ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq);
ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
if (ret)
return ret;
if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
cmd == MCU_UNI_CMD(SUSPEND) ||
cmd == MCU_UNI_CMD(OFFLOAD))
mdev->mcu.timeout = HZ;
else
mdev->mcu.timeout = 3 * HZ;
if (cmd == MCU_CMD(FW_SCATTER))
type = MT7921_SDIO_FWDL;
@ -72,7 +79,8 @@ static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev)
int mt7921s_mcu_init(struct mt7921_dev *dev)
{
static const struct mt76_mcu_ops mt7921s_mcu_ops = {
.headroom = MT_SDIO_HDR_SIZE + sizeof(struct mt7921_mcu_txd),
.headroom = MT_SDIO_HDR_SIZE +
sizeof(struct mt76_connac2_mcu_txd),
.tailroom = MT_SDIO_TAIL_SIZE,
.mcu_skb_send_msg = mt7921s_mcu_send_message,
.mcu_parse_response = mt7921_mcu_parse_response,
@ -99,8 +107,8 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev)
struct sdio_func *func = dev->mt76.sdio.func;
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int err = 0;
u32 status;
int err;
sdio_claim_host(func);
@ -118,8 +126,7 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev)
if (err < 0) {
dev_err(dev->mt76.dev, "driver own failed\n");
err = -EIO;
goto out;
return -EIO;
}
clear_bit(MT76_STATE_PM, &mphy->state);
@ -127,8 +134,8 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev)
pm->stats.last_wake_event = jiffies;
pm->stats.doze_time += pm->stats.last_wake_event -
pm->stats.last_doze_event;
out:
return err;
return 0;
}
int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
@ -136,8 +143,8 @@ int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
struct sdio_func *func = dev->mt76.sdio.func;
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt76_connac_pm *pm = &dev->pm;
int err = 0;
u32 status;
int err;
sdio_claim_host(func);
@ -148,7 +155,7 @@ int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
2000, 1000000);
if (err < 0) {
dev_err(dev->mt76.dev, "mailbox ACK not cleared\n");
goto err;
goto out;
}
}
@ -156,18 +163,18 @@ int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
!(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000);
out:
sdio_release_host(func);
err:
if (err < 0) {
dev_err(dev->mt76.dev, "firmware own failed\n");
clear_bit(MT76_STATE_PM, &mphy->state);
err = -EIO;
return -EIO;
}
pm->stats.last_doze_event = jiffies;
pm->stats.awake_time += pm->stats.last_doze_event -
pm->stats.last_wake_event;
return err;
return 0;
}

View File

@ -102,10 +102,17 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
u32 pad, ep;
int ret;
ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq);
ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
if (ret)
return ret;
if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
cmd == MCU_UNI_CMD(SUSPEND) ||
cmd == MCU_UNI_CMD(OFFLOAD))
mdev->mcu.timeout = HZ;
else
mdev->mcu.timeout = 3 * HZ;
if (cmd != MCU_CMD(FW_SCATTER))
ep = MT_EP_OUT_INBAND_CMD;
else
@ -125,7 +132,8 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
static int mt7921u_mcu_init(struct mt7921_dev *dev)
{
static const struct mt76_mcu_ops mcu_ops = {
.headroom = MT_SDIO_HDR_SIZE + sizeof(struct mt7921_mcu_txd),
.headroom = MT_SDIO_HDR_SIZE +
sizeof(struct mt76_connac2_mcu_txd),
.tailroom = MT_USB_TAIL_SIZE,
.mcu_skb_send_msg = mt7921u_mcu_send_message,
.mcu_parse_response = mt7921_mcu_parse_response,
@ -158,7 +166,7 @@ static void mt7921u_cleanup(struct mt7921_dev *dev)
{
clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
mt7921u_wfsys_reset(dev);
mt7921_mcu_exit(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_queues_deinit(&dev->mt76);
}

View File

@ -185,7 +185,7 @@ int mt7921u_init_reset(struct mt7921_dev *dev)
set_bit(MT76_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
mt7921_mcu_exit(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
@ -208,7 +208,7 @@ int mt7921u_mac_reset(struct mt7921_dev *dev)
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
mt7921_mcu_exit(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);

View File

@ -350,7 +350,6 @@ int mt76s_alloc_tx(struct mt76_dev *dev)
if (IS_ERR(q))
return PTR_ERR(q);
q->qid = i;
dev->phy.q_tx[i] = q;
}
@ -358,7 +357,6 @@ int mt76s_alloc_tx(struct mt76_dev *dev)
if (IS_ERR(q))
return PTR_ERR(q);
q->qid = MT_MCUQ_WM;
dev->q_mcu[MT_MCUQ_WM] = q;
return 0;
@ -517,8 +515,8 @@ static void mt76s_tx_status_data(struct work_struct *work)
static int
mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta)
enum mt76_txq_id qid, struct sk_buff *skb,
struct mt76_wcid *wcid, struct ieee80211_sta *sta)
{
struct mt76_tx_info tx_info = {
.skb = skb,
@ -530,7 +528,7 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
return -ENOSPC;
skb->prev = skb->next = NULL;
err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info);
err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info);
if (err < 0)
return err;

View File

@ -50,8 +50,8 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
q->queued < q->ndesc / 2) {
int ret;
ret = dev->queue_ops->tx_queue_skb(dev, q, skb_get(skb), wcid,
NULL);
ret = dev->queue_ops->tx_queue_skb(dev, q, qid, skb_get(skb),
wcid, NULL);
if (ret < 0)
break;
@ -101,7 +101,6 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
u16 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
IEEE80211_FCTL_FROMDS;
struct mt76_testmode_data *td = &phy->test;
bool ext_phy = phy != &phy->dev->phy;
struct sk_buff **frag_tail, *head;
struct ieee80211_tx_info *info;
struct ieee80211_hdr *hdr;
@ -136,9 +135,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
IEEE80211_TX_CTL_NO_ACK |
IEEE80211_TX_CTL_NO_PS_BUFFER;
if (ext_phy)
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
frag_tail = &skb_shinfo(head)->frag_list;
for (i = 0; i < nfrags; i++) {

View File

@ -284,7 +284,7 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
int idx;
non_aql = !info->tx_time_est;
idx = dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta);
idx = dev->queue_ops->tx_queue_skb(dev, q, qid, skb, wcid, sta);
if (idx < 0 || !sta)
return idx;
@ -310,7 +310,6 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct mt76_queue *q;
int qid = skb_get_queue_mapping(skb);
bool ext_phy = phy != &dev->phy;
if (mt76_testmode_enabled(phy)) {
ieee80211_free_txskb(phy->hw, skb);
@ -327,16 +326,13 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
!ieee80211_is_data(hdr->frame_control) &&
!ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
qid = MT_TXQ_PSD;
skb_set_queue_mapping(skb, qid);
}
if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET))
ieee80211_get_tx_rates(info->control.vif, sta, skb,
info->control.rates, 1);
if (ext_phy)
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
q = phy->q_tx[qid];
spin_lock_bh(&q->lock);
@ -351,7 +347,6 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq)
{
struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
struct ieee80211_tx_info *info;
bool ext_phy = phy != &phy->dev->phy;
struct sk_buff *skb;
skb = ieee80211_tx_dequeue(phy->hw, txq);
@ -359,8 +354,7 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq)
return NULL;
info = IEEE80211_SKB_CB(skb);
if (ext_phy)
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
return skb;
}
@ -586,15 +580,25 @@ EXPORT_SYMBOL_GPL(mt76_txq_schedule_all);
void mt76_tx_worker_run(struct mt76_dev *dev)
{
mt76_txq_schedule_all(&dev->phy);
if (dev->phy2)
mt76_txq_schedule_all(dev->phy2);
struct mt76_phy *phy;
int i;
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
phy = dev->phys[i];
if (!phy)
continue;
mt76_txq_schedule_all(phy);
}
#ifdef CONFIG_NL80211_TESTMODE
if (dev->phy.test.tx_pending)
mt76_testmode_tx_pending(&dev->phy);
if (dev->phy2 && dev->phy2->test.tx_pending)
mt76_testmode_tx_pending(dev->phy2);
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
phy = dev->phys[i];
if (!phy || !phy->test.tx_pending)
continue;
mt76_testmode_tx_pending(phy);
}
#endif
}
EXPORT_SYMBOL_GPL(mt76_tx_worker_run);
@ -697,17 +701,23 @@ EXPORT_SYMBOL_GPL(mt76_queue_tx_complete);
void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
{
struct mt76_phy *phy = &dev->phy, *phy2 = dev->phy2;
struct mt76_queue *q, *q2 = NULL;
struct mt76_phy *phy = &dev->phy;
struct mt76_queue *q = phy->q_tx[0];
q = phy->q_tx[0];
if (blocked == q->blocked)
return;
q->blocked = blocked;
if (phy2) {
q2 = phy2->q_tx[0];
q2->blocked = blocked;
phy = dev->phys[MT_BAND1];
if (phy) {
q = phy->q_tx[0];
q->blocked = blocked;
}
phy = dev->phys[MT_BAND2];
if (phy) {
q = phy->q_tx[0];
q->blocked = blocked;
}
if (!blocked)

Some files were not shown because too many files have changed in this diff Show More