wireless-drivers-next patches for v5.16

Second set of patches for v5.16 and this time we have a big one. We
 have the new Realtek driver rtw89 with over 90 kLOC and also over 150
 patches for mt76. ath9k also got few new small features. And the usual
 cleanups and fixes all over.
 
 Major changes:
 
 rtw89
 
 * new Realtek 802.11ax driver
 
 * supports Realtek 8852AE 802.11ax 2x2 chip
 
 ath9k
 
 * add option to reset the wifi chip via debugfs
 
 * convert Device Tree bindings to the json-schema
 
 * support Device Tree ieee80211-freq-limit property to limit channels
 
 mt76
 
 * mt7921 aspm support
 
 * mt7921 testmode support
 
 * mt7915 LED support
 
 * mt7921 6GHz band support
 
 * support for eeprom data in DT
 
 * mt7915 TWT support
 
 * mt7921s SDIO support
 -----BEGIN PGP SIGNATURE-----
 
 iQFJBAABCgAzFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmFybvwVHGt2YWxvQGNv
 ZGVhdXJvcmEub3JnAAoJEG4XJFUm622b8VoH/ikpKrYdhCwEHwaRHEiieejhD1w+
 kvUhiQP/oL7q/4WVUzEnzv5BWQm1D7gHMmVvSdfjfdPuw7F085p6rQDCs99RlMo6
 pUv6VllvuZa8XpIrQzdWbXbWv041cQA97wS5QNeEfiIvlwzw48Sfj2ANgPHRJy5a
 z93ZhOeS5VL1h+1ki6uuGS0MoOaNhzPazb3kH7U2QkuuiP5BTvUw8nW9sQIaBEEg
 UzdEzLjwhbZJtmIFs4dAkOKX2+ANrS09Zl0c9530ShwZB4RXTESv+OybQrcYNBUw
 2RlGT0g8LYX7QJq/hJpJuylH7s/WrMZVDo07NBbfyOc2R/bi7R54S8zBInI=
 =tjnh
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-next-2021-10-22' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for v5.16

Second set of patches for v5.16 and this time we have a big one. We
have the new Realtek driver rtw89 with over 90 kLOC and also over 150
patches for mt76. ath9k also got few new small features. And the usual
cleanups and fixes all over.

Major changes:

rtw89
 * new Realtek 802.11ax driver
 * supports Realtek 8852AE 802.11ax 2x2 chip

ath9k
 * add option to reset the wifi chip via debugfs
 * convert Device Tree bindings to the json-schema
 * support Device Tree ieee80211-freq-limit property to limit channels

mt76
 * mt7921 aspm support
 * mt7921 testmode support
 * mt7915 LED support
 * mt7921 6GHz band support
 * support for eeprom data in DT
 * mt7915 TWT support
 * mt7921s SDIO support

* tag 'wireless-drivers-next-2021-10-22' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next: (213 commits)
  zd1201: use eth_hw_addr_set()
  wl3501_cs: use eth_hw_addr_set()
  ray_cs: use eth_hw_addr_set()
  ...
====================

Link: https://lore.kernel.org/r/20211022075845.0E679C4360D@smtp.codeaurora.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2021-10-22 10:22:05 -07:00
commit d1a3f40951
187 changed files with 97765 additions and 2798 deletions

View File

@ -47,6 +47,11 @@ properties:
ieee80211-freq-limit: true
mediatek,eeprom-data:
$ref: /schemas/types.yaml#/definitions/uint32-array
description:
EEPROM data embedded as array.
mediatek,mtd-eeprom:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:

View File

@ -1,48 +0,0 @@
* Qualcomm Atheros ath9k wireless devices
This node provides properties for configuring the ath9k wireless device. The
node is expected to be specified as a child node of the PCI controller to
which the wireless chip is connected.
Required properties:
- compatible: For PCI and PCIe devices this should be an identifier following
the format as defined in "PCI Bus Binding to Open Firmware"
Revision 2.1. One of the possible formats is "pciVVVV,DDDD"
where VVVV is the PCI vendor ID and DDDD is PCI device ID.
Typically QCA's PCI vendor ID 168c is used while the PCI device
ID depends on the chipset - see the following (possibly
incomplete) list:
- 0023 for AR5416
- 0024 for AR5418
- 0027 for AR9160
- 0029 for AR9220 and AR9223
- 002a for AR9280 and AR9283
- 002b for AR9285
- 002c for AR2427
- 002d for AR9227
- 002e for AR9287
- 0030 for AR9380, AR9381 and AR9382
- 0032 for AR9485
- 0033 for AR9580 and AR9590
- 0034 for AR9462
- 0036 for AR9565
- 0037 for AR9485
- reg: Address and length of the register set for the device.
Optional properties:
- qca,no-eeprom: Indicates that there is no physical EEPROM connected to the
ath9k wireless chip (in this case the calibration /
EEPROM data will be loaded from userspace using the
kernel firmware loader).
The MAC address will be determined using the optional properties defined in
net/ethernet.txt.
In this example, the node is defined as child node of the PCI controller:
&pci0 {
wifi@168c,002d {
compatible = "pci168c,002d";
reg = <0x7000 0 0 0 0x1000>;
qca,no-eeprom;
};
};

View File

@ -0,0 +1,90 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/wireless/qca,ath9k.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Atheros ath9k wireless devices Generic Binding
maintainers:
- Kalle Valo <kvalo@codeaurora.org>
description: |
This node provides properties for configuring the ath9k wireless device.
The node is expected to be specified as a child node of the PCI controller
to which the wireless chip is connected.
allOf:
- $ref: ieee80211.yaml#
properties:
compatible:
enum:
- pci168c,0023 # AR5416
- pci168c,0024 # AR5418
- pci168c,0027 # AR9160
- pci168c,0029 # AR9220 and AR9223
- pci168c,002a # AR9280 and AR9283
- pci168c,002b # AR9285
- pci168c,002c # AR2427 - 802.11n bonded out
- pci168c,002d # AR9227
- pci168c,002e # AR9287
- pci168c,0030 # AR9380, AR9381 and AR9382
- pci168c,0032 # AR9485
- pci168c,0033 # AR9580 and AR9590
- pci168c,0034 # AR9462
- pci168c,0036 # AR9565
- pci168c,0037 # AR1111 and AR9485
reg:
maxItems: 1
interrupts:
maxItems: 1
ieee80211-freq-limit: true
qca,no-eeprom:
$ref: /schemas/types.yaml#/definitions/flag
description:
Indicates that there is no physical EEPROM connected
nvmem-cells:
items:
- description: Reference to an nvmem node for the MAC address
- description: Reference to an nvmem node for calibration data
nvmem-cell-names:
items:
- const: mac-address
- const: calibration
required:
- compatible
- reg
additionalProperties: false
examples:
- |
pcie0 {
#address-cells = <3>;
#size-cells = <2>;
wifi@0,0 {
compatible = "pci168c,002d";
reg = <0 0 0 0 0>;
interrupts = <3>;
qca,no-eeprom;
};
};
- |
pci0 {
#address-cells = <3>;
#size-cells = <2>;
wifi@0,11 {
compatible = "pci168c,0029";
reg = <0x8800 0 0 0 0>;
nvmem-cells = <&macaddr_art_c>, <&cal_art_1000>;
nvmem-cell-names = "mac-address", "calibration";
};
};

View File

@ -11830,7 +11830,9 @@ F: drivers/mmc/host/mtk-sd.c
MEDIATEK MT76 WIRELESS LAN DRIVER
M: Felix Fietkau <nbd@nbd.name>
M: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
R: Ryder Lee <ryder.lee@mediatek.com>
M: Ryder Lee <ryder.lee@mediatek.com>
R: Shayne Chen <shayne.chen@mediatek.com>
R: Sean Wang <sean.wang@mediatek.com>
L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/net/wireless/mediatek/mt76/
@ -15469,6 +15471,7 @@ M: ath9k-devel@qca.qualcomm.com
L: linux-wireless@vger.kernel.org
S: Supported
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath9k
F: Documentation/devicetree/bindings/net/wireless/qca,ath9k.yaml
F: drivers/net/wireless/ath/ath9k/
QUALCOMM CAMERA SUBSYSTEM DRIVER
@ -15890,6 +15893,12 @@ L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/net/wireless/realtek/rtw88/
REALTEK WIRELESS DRIVER (rtw89)
M: Ping-Ke Shih <pkshih@realtek.com>
L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/net/wireless/realtek/rtw89/
REDPINE WIRELESS DRIVER
M: Amitkumar Karwar <amitkarwar@gmail.com>
M: Siva Rebbagondla <siva8118@gmail.com>

View File

@ -3520,13 +3520,10 @@ EXPORT_SYMBOL(ath10k_core_create);
void ath10k_core_destroy(struct ath10k *ar)
{
flush_workqueue(ar->workqueue);
destroy_workqueue(ar->workqueue);
flush_workqueue(ar->workqueue_aux);
destroy_workqueue(ar->workqueue_aux);
flush_workqueue(ar->workqueue_tx_complete);
destroy_workqueue(ar->workqueue_tx_complete);
ath10k_debug_destroy(ar);

View File

@ -1052,7 +1052,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
arg.channel.min_power = 0;
arg.channel.max_power = channel->max_power * 2;
arg.channel.max_reg_power = channel->max_reg_power * 2;
arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
arg.channel.max_antenna_gain = channel->max_antenna_gain;
reinit_completion(&ar->vdev_setup_done);
reinit_completion(&ar->vdev_delete_done);
@ -1498,7 +1498,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif,
arg.channel.min_power = 0;
arg.channel.max_power = chandef->chan->max_power * 2;
arg.channel.max_reg_power = chandef->chan->max_reg_power * 2;
arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2;
arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain;
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
arg.ssid = arvif->u.ap.ssid;
@ -3426,7 +3426,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
ch->min_power = 0;
ch->max_power = channel->max_power * 2;
ch->max_reg_power = channel->max_reg_power * 2;
ch->max_antenna_gain = channel->max_antenna_gain * 2;
ch->max_antenna_gain = channel->max_antenna_gain;
ch->reg_class_id = 0; /* FIXME */
/* FIXME: why use only legacy modes, why not any

View File

@ -864,7 +864,8 @@ static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi)
ath10k_qmi_remove_msa_permission(qmi);
ath10k_core_free_board_files(ar);
if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags))
if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags) &&
!test_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags))
ath10k_snoc_fw_crashed_dump(ar);
ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND);

View File

@ -2650,7 +2650,6 @@ static void ath10k_sdio_remove(struct sdio_func *func)
ath10k_core_destroy(ar);
flush_workqueue(ar_sdio->workqueue);
destroy_workqueue(ar_sdio->workqueue);
}

View File

@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/remoteproc/qcom_rproc.h>
#include <linux/of_address.h>
#include <linux/iommu.h>
@ -1477,6 +1478,74 @@ void ath10k_snoc_fw_crashed_dump(struct ath10k *ar)
mutex_unlock(&ar->dump_mutex);
}
static int ath10k_snoc_modem_notify(struct notifier_block *nb, unsigned long action,
void *data)
{
struct ath10k_snoc *ar_snoc = container_of(nb, struct ath10k_snoc, nb);
struct ath10k *ar = ar_snoc->ar;
struct qcom_ssr_notify_data *notify_data = data;
switch (action) {
case QCOM_SSR_BEFORE_POWERUP:
ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem starting event\n");
clear_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags);
break;
case QCOM_SSR_AFTER_POWERUP:
ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem running event\n");
break;
case QCOM_SSR_BEFORE_SHUTDOWN:
ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem %s event\n",
notify_data->crashed ? "crashed" : "stopping");
if (!notify_data->crashed)
set_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags);
else
clear_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags);
break;
case QCOM_SSR_AFTER_SHUTDOWN:
ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem offline event\n");
break;
default:
ath10k_err(ar, "received unrecognized event %lu\n", action);
break;
}
return NOTIFY_OK;
}
static int ath10k_modem_init(struct ath10k *ar)
{
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
void *notifier;
int ret;
ar_snoc->nb.notifier_call = ath10k_snoc_modem_notify;
notifier = qcom_register_ssr_notifier("mpss", &ar_snoc->nb);
if (IS_ERR(notifier)) {
ret = PTR_ERR(notifier);
ath10k_err(ar, "failed to initialize modem notifier: %d\n", ret);
return ret;
}
ar_snoc->notifier = notifier;
return 0;
}
static void ath10k_modem_deinit(struct ath10k *ar)
{
int ret;
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
ret = qcom_unregister_ssr_notifier(ar_snoc->notifier, &ar_snoc->nb);
if (ret)
ath10k_err(ar, "error %d unregistering notifier\n", ret);
}
static int ath10k_setup_msa_resources(struct ath10k *ar, u32 msa_size)
{
struct device *dev = ar->dev;
@ -1740,10 +1809,17 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
goto err_fw_deinit;
}
ret = ath10k_modem_init(ar);
if (ret)
goto err_qmi_deinit;
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n");
return 0;
err_qmi_deinit:
ath10k_qmi_deinit(ar);
err_fw_deinit:
ath10k_fw_deinit(ar);
@ -1771,6 +1847,7 @@ static int ath10k_snoc_free_resources(struct ath10k *ar)
ath10k_fw_deinit(ar);
ath10k_snoc_free_irq(ar);
ath10k_snoc_release_resource(ar);
ath10k_modem_deinit(ar);
ath10k_qmi_deinit(ar);
ath10k_core_destroy(ar);

View File

@ -6,6 +6,8 @@
#ifndef _SNOC_H_
#define _SNOC_H_
#include <linux/notifier.h>
#include "hw.h"
#include "ce.h"
#include "qmi.h"
@ -45,6 +47,7 @@ struct ath10k_snoc_ce_irq {
enum ath10k_snoc_flags {
ATH10K_SNOC_FLAG_REGISTERED,
ATH10K_SNOC_FLAG_UNREGISTERING,
ATH10K_SNOC_FLAG_MODEM_STOPPED,
ATH10K_SNOC_FLAG_RECOVERY,
ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
};
@ -75,6 +78,8 @@ struct ath10k_snoc {
struct clk_bulk_data *clks;
size_t num_clks;
struct ath10k_qmi *qmi;
struct notifier_block nb;
void *notifier;
unsigned long flags;
bool xo_cal_supported;
u32 xo_cal_data;

View File

@ -2066,7 +2066,9 @@ struct wmi_channel {
union {
__le32 reginfo1;
struct {
/* note: power unit is 1 dBm */
u8 antenna_max;
/* note: power unit is 0.5 dBm */
u8 max_tx_power;
} __packed;
} __packed;
@ -2086,6 +2088,7 @@ struct wmi_channel_arg {
u32 min_power;
u32 max_power;
u32 max_reg_power;
/* note: power unit is 1 dBm */
u32 max_antenna_gain;
u32 reg_class_id;
enum wmi_phy_mode mode;

View File

@ -58,7 +58,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.rx_mac_buf_ring = false,
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
.spectral = {
.fft_sz = 2,
@ -81,6 +80,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_suspend = false,
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
.fix_l1ss = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
@ -109,7 +109,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.rx_mac_buf_ring = false,
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
.spectral = {
.fft_sz = 4,
@ -129,6 +128,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_suspend = false,
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
.fix_l1ss = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX,
},
{
.name = "qca6390 hw2.0",
@ -157,7 +157,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.rx_mac_buf_ring = true,
.vdev_start_delay = true,
.htt_peer_map_v2 = false,
.tcl_0_only = true,
.spectral = {
.fft_sz = 0,
@ -176,6 +175,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_suspend = true,
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
.fix_l1ss = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
},
{
.name = "qcn9074 hw1.0",
@ -203,7 +203,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.rx_mac_buf_ring = false,
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
.spectral = {
.fft_sz = 2,
@ -223,6 +222,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_suspend = false,
.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
.fix_l1ss = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX,
},
{
.name = "wcn6855 hw2.0",
@ -251,7 +251,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.rx_mac_buf_ring = true,
.vdev_start_delay = true,
.htt_peer_map_v2 = false,
.tcl_0_only = true,
.spectral = {
.fft_sz = 0,
@ -270,6 +269,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_suspend = true,
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
.fix_l1ss = false,
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
},
};

View File

@ -806,7 +806,7 @@ static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
for (i = 0; i < ab->hw_params.max_tx_ring; i++)
len += scnprintf(buf + len, size - len, "ring%d: %u\n",
i, soc_stats->tx_err.desc_na[i]);

View File

@ -311,7 +311,7 @@ void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)
if (!ab->hw_params.supports_shadow_regs)
return;
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
for (i = 0; i < ab->hw_params.max_tx_ring; i++)
ath11k_dp_shadow_stop_timer(ab, &ab->dp.tx_ring_timer[i]);
ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer);
@ -326,7 +326,7 @@ static void ath11k_dp_srng_common_cleanup(struct ath11k_base *ab)
ath11k_dp_srng_cleanup(ab, &dp->wbm_desc_rel_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_cmd_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_status_ring);
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_data_ring);
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_comp_ring);
}
@ -366,7 +366,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
goto err;
}
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
ret = ath11k_dp_srng_setup(ab, &dp->tx_ring[i].tcl_data_ring,
HAL_TCL_DATA, i, 0,
DP_TCL_DATA_RING_SIZE);
@ -996,7 +996,7 @@ void ath11k_dp_free(struct ath11k_base *ab)
ath11k_dp_reo_cmd_list_cleanup(ab);
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
spin_lock_bh(&dp->tx_ring[i].tx_idr_lock);
idr_for_each(&dp->tx_ring[i].txbuf_idr,
ath11k_dp_tx_pending_cleanup, ab);
@ -1046,7 +1046,7 @@ int ath11k_dp_alloc(struct ath11k_base *ab)
size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE;
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
idr_init(&dp->tx_ring[i].txbuf_idr);
spin_lock_init(&dp->tx_ring[i].tx_idr_lock);
dp->tx_ring[i].tcl_data_ring_id = i;

View File

@ -170,6 +170,7 @@ struct ath11k_pdev_dp {
#define DP_BA_WIN_SZ_MAX 256
#define DP_TCL_NUM_RING_MAX 3
#define DP_TCL_NUM_RING_MAX_QCA6390 1
#define DP_IDLE_SCATTER_BUFS_MAX 16

View File

@ -4828,7 +4828,7 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar,
struct ieee80211_rx_status *rxs)
{
struct ath11k_base *ab = ar->ab;
struct sk_buff *msdu, *mpdu_buf, *prev_buf;
struct sk_buff *msdu, *prev_buf;
u32 wifi_hdr_len;
struct hal_rx_desc *rx_desc;
char *hdr_desc;
@ -4836,8 +4836,6 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar,
struct ieee80211_hdr_3addr *wh;
struct rx_attention *rx_attention;
mpdu_buf = NULL;
if (!head_msdu)
goto err_merge_fail;
@ -4920,12 +4918,6 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar,
return head_msdu;
err_merge_fail:
if (mpdu_buf && decap_format != DP_RX_DECAP_TYPE_RAW) {
ath11k_dbg(ab, ATH11K_DBG_DATA,
"err_merge_fail mpdu_buf %pK", mpdu_buf);
/* Free the head buffer */
dev_kfree_skb_any(mpdu_buf);
}
return NULL;
}

View File

@ -115,11 +115,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
tcl_ring_sel:
tcl_ring_retry = false;
/* For some chip, it can only use tcl0 to tx */
if (ar->ab->hw_params.tcl_0_only)
ti.ring_id = 0;
else
ti.ring_id = ring_selector % DP_TCL_NUM_RING_MAX;
ti.ring_id = ring_selector % ab->hw_params.max_tx_ring;
ring_map |= BIT(ti.ring_id);
@ -131,7 +128,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
spin_unlock_bh(&tx_ring->tx_idr_lock);
if (ret < 0) {
if (ring_map == (BIT(DP_TCL_NUM_RING_MAX) - 1)) {
if (ring_map == (BIT(ab->hw_params.max_tx_ring) - 1)) {
atomic_inc(&ab->soc_stats.tx_err.misc_fail);
return -ENOSPC;
}
@ -248,8 +245,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
* checking this ring earlier for each pkt tx.
* Restart ring selection if some rings are not checked yet.
*/
if (ring_map != (BIT(DP_TCL_NUM_RING_MAX) - 1) &&
!ar->ab->hw_params.tcl_0_only) {
if (ring_map != (BIT(ab->hw_params.max_tx_ring) - 1) &&
ab->hw_params.max_tx_ring > 1) {
tcl_ring_retry = true;
ring_selector++;
}

View File

@ -152,7 +152,6 @@ struct ath11k_hw_params {
bool rx_mac_buf_ring;
bool vdev_start_delay;
bool htt_peer_map_v2;
bool tcl_0_only;
struct {
u8 fft_sz;
@ -170,6 +169,7 @@ struct ath11k_hw_params {
bool supports_suspend;
u32 hal_desc_sz;
bool fix_l1ss;
u8 max_tx_ring;
};
struct ath11k_hw_ops {

View File

@ -5797,7 +5797,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
idr_for_each(&ar->txmgmt_idr,
ath11k_mac_vif_txmgmt_idr_remove, vif);
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
idr_for_each(&ab->dp.tx_ring[i].txbuf_idr,
ath11k_mac_vif_unref, vif);
@ -7081,7 +7081,7 @@ ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
if (!ath11k_mac_validate_vht_he_fixed_rate_settings(ar, band, mask))
ath11k_warn(ar->ab,
"could not update fixed rate settings to all peers due to mcs/nss incompaitiblity\n");
"could not update fixed rate settings to all peers due to mcs/nss incompatibility\n");
nss = min_t(u32, ar->num_tx_chains,
max(max(ath11k_mac_max_ht_nss(ht_mcs_mask),
ath11k_mac_max_vht_nss(vht_mcs_mask)),

View File

@ -855,7 +855,32 @@ static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
}
}
static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
static void ath11k_pci_msi_config(struct ath11k_pci *ab_pci, bool enable)
{
struct pci_dev *dev = ab_pci->pdev;
u16 control;
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
if (enable)
control |= PCI_MSI_FLAGS_ENABLE;
else
control &= ~PCI_MSI_FLAGS_ENABLE;
pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
}
static void ath11k_pci_msi_enable(struct ath11k_pci *ab_pci)
{
ath11k_pci_msi_config(ab_pci, true);
}
static void ath11k_pci_msi_disable(struct ath11k_pci *ab_pci)
{
ath11k_pci_msi_config(ab_pci, false);
}
static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)
{
struct ath11k_base *ab = ab_pci->ab;
const struct ath11k_msi_config *msi_config = ab_pci->msi_config;
@ -876,6 +901,7 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
else
return num_vectors;
}
ath11k_pci_msi_disable(ab_pci);
msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
if (!msi_desc) {
@ -898,7 +924,7 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
return ret;
}
static void ath11k_pci_disable_msi(struct ath11k_pci *ab_pci)
static void ath11k_pci_free_msi(struct ath11k_pci *ab_pci)
{
pci_free_irq_vectors(ab_pci->pdev);
}
@ -1019,6 +1045,8 @@ static int ath11k_pci_power_up(struct ath11k_base *ab)
*/
ath11k_pci_aspm_disable(ab_pci);
ath11k_pci_msi_enable(ab_pci);
ret = ath11k_mhi_start(ab_pci);
if (ret) {
ath11k_err(ab, "failed to start mhi: %d\n", ret);
@ -1039,6 +1067,9 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)
ath11k_pci_aspm_restore(ab_pci);
ath11k_pci_force_wake(ab_pci->ab);
ath11k_pci_msi_disable(ab_pci);
ath11k_mhi_stop(ab_pci);
clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
ath11k_pci_sw_reset(ab_pci->ab, false);
@ -1263,7 +1294,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
goto err_pci_free_region;
}
ret = ath11k_pci_enable_msi(ab_pci);
ret = ath11k_pci_alloc_msi(ab_pci);
if (ret) {
ath11k_err(ab, "failed to enable msi: %d\n", ret);
goto err_pci_free_region;
@ -1317,7 +1348,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
ath11k_mhi_unregister(ab_pci);
err_pci_disable_msi:
ath11k_pci_disable_msi(ab_pci);
ath11k_pci_free_msi(ab_pci);
err_pci_free_region:
ath11k_pci_free_region(ab_pci);
@ -1348,7 +1379,7 @@ static void ath11k_pci_remove(struct pci_dev *pdev)
ath11k_mhi_unregister(ab_pci);
ath11k_pci_free_irq(ab);
ath11k_pci_disable_msi(ab_pci);
ath11k_pci_free_msi(ab_pci);
ath11k_pci_free_region(ab_pci);
ath11k_hal_srng_deinit(ab);

View File

@ -2135,7 +2135,6 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab)
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf_type %d\n", bdf_type);
fw_size = bd.len;
fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len);
ret = ath11k_qmi_load_file_target_mem(ab, bd.data, fw_size, bdf_type);

View File

@ -2371,6 +2371,8 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
chan_info->info |= WMI_CHAN_INFO_QUARTER_RATE;
if (tchan_info->psc_channel)
chan_info->info |= WMI_CHAN_INFO_PSC;
if (tchan_info->dfs_set)
chan_info->info |= WMI_CHAN_INFO_DFS;
chan_info->info |= FIELD_PREP(WMI_CHAN_INFO_MODE,
tchan_info->phy_mode);
@ -4065,8 +4067,8 @@ static int ath11k_wmi_tlv_mac_phy_caps_parse(struct ath11k_base *soc,
len = min_t(u16, len, sizeof(struct wmi_mac_phy_capabilities));
if (!svc_rdy_ext->n_mac_phy_caps) {
svc_rdy_ext->mac_phy_caps = kzalloc((svc_rdy_ext->tot_phy_id) * len,
GFP_ATOMIC);
svc_rdy_ext->mac_phy_caps = kcalloc(svc_rdy_ext->tot_phy_id,
len, GFP_ATOMIC);
if (!svc_rdy_ext->mac_phy_caps)
return -ENOMEM;
}
@ -4466,8 +4468,8 @@ static struct cur_reg_rule
struct cur_reg_rule *reg_rule_ptr;
u32 count;
reg_rule_ptr = kzalloc((num_reg_rules * sizeof(*reg_rule_ptr)),
GFP_ATOMIC);
reg_rule_ptr = kcalloc(num_reg_rules, sizeof(*reg_rule_ptr),
GFP_ATOMIC);
if (!reg_rule_ptr)
return NULL;

View File

@ -14,7 +14,7 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
{ \
struct ieee80211_hw *hw = dev_get_drvdata(dev); \
struct ath5k_hw *ah = hw->priv; \
return snprintf(buf, PAGE_SIZE, "%d\n", get); \
return sysfs_emit(buf, "%d\n", get); \
} \
\
static ssize_t ath5k_attr_store_##name(struct device *dev, \
@ -41,7 +41,7 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
{ \
struct ieee80211_hw *hw = dev_get_drvdata(dev); \
struct ath5k_hw *ah = hw->priv; \
return snprintf(buf, PAGE_SIZE, "%d\n", get); \
return sysfs_emit(buf, "%d\n", get); \
} \
static DEVICE_ATTR(name, 0444, ath5k_attr_show_##name, NULL)
@ -64,7 +64,7 @@ static ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_NOISE_IMM_LVL);
return sysfs_emit(buf, "%d\n", ATH5K_ANI_MAX_NOISE_IMM_LVL);
}
static DEVICE_ATTR(noise_immunity_level_max, 0444,
ath5k_attr_show_noise_immunity_level_max, NULL);
@ -73,7 +73,7 @@ static ssize_t ath5k_attr_show_firstep_level_max(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_FIRSTEP_LVL);
return sysfs_emit(buf, "%d\n", ATH5K_ANI_MAX_FIRSTEP_LVL);
}
static DEVICE_ATTR(firstep_level_max, 0444,
ath5k_attr_show_firstep_level_max, NULL);

View File

@ -3781,6 +3781,7 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
{
struct net_device *ndev;
struct ath6kl_vif *vif;
u8 addr[ETH_ALEN];
ndev = alloc_netdev(sizeof(*vif), name, name_assign_type, ether_setup);
if (!ndev)
@ -3803,14 +3804,14 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
vif->htcap[NL80211_BAND_2GHZ].ht_enable = true;
vif->htcap[NL80211_BAND_5GHZ].ht_enable = true;
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
ether_addr_copy(addr, ar->mac_addr);
if (fw_vif_idx != 0) {
ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
0x2;
addr[0] = (addr[0] ^ (1 << fw_vif_idx)) | 0x2;
if (test_bit(ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR,
ar->fw_capabilities))
ndev->dev_addr[4] ^= 0x80;
addr[4] ^= 0x80;
}
eth_hw_addr_set(ndev, addr);
init_netdev(ndev);

View File

@ -749,9 +749,9 @@ static int read_file_misc(struct seq_file *file, void *data)
static int read_file_reset(struct seq_file *file, void *data)
{
struct ieee80211_hw *hw = dev_get_drvdata(file->private);
struct ath_softc *sc = hw->priv;
struct ath_softc *sc = file->private;
static const char * const reset_cause[__RESET_TYPE_MAX] = {
[RESET_TYPE_USER] = "User reset",
[RESET_TYPE_BB_HANG] = "Baseband Hang",
[RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog",
[RESET_TYPE_FATAL_INT] = "Fatal HW Error",
@ -779,6 +779,55 @@ static int read_file_reset(struct seq_file *file, void *data)
return 0;
}
static int open_file_reset(struct inode *inode, struct file *f)
{
return single_open(f, read_file_reset, inode->i_private);
}
static ssize_t write_file_reset(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file_inode(file)->i_private;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val != 1)
return -EINVAL;
/* avoid rearming hw_reset_work on shutdown */
mutex_lock(&sc->mutex);
if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
mutex_unlock(&sc->mutex);
return -EBUSY;
}
ath9k_queue_reset(sc, RESET_TYPE_USER);
mutex_unlock(&sc->mutex);
return count;
}
static const struct file_operations fops_reset = {
.read = seq_read,
.write = write_file_reset,
.open = open_file_reset,
.owner = THIS_MODULE,
.llseek = seq_lseek,
.release = single_release,
};
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, struct ath_txq *txq,
unsigned int flags)
@ -1393,8 +1442,8 @@ int ath9k_init_debug(struct ath_hw *ah)
read_file_queues);
debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy,
read_file_misc);
debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy,
read_file_reset);
debugfs_create_file("reset", 0600, sc->debug.debugfs_phy,
sc, &fops_reset);
ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);
ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);

View File

@ -39,6 +39,7 @@ struct fft_sample_tlv;
#endif
enum ath_reset_type {
RESET_TYPE_USER,
RESET_TYPE_BB_HANG,
RESET_TYPE_BB_WATCHDOG,
RESET_TYPE_FATAL_INT,

View File

@ -610,8 +610,8 @@ static int ath9k_nvmem_request_eeprom(struct ath_softc *sc)
/* devres manages the calibration values release on shutdown */
ah->nvmem_blob = (u16 *)devm_kmemdup(sc->dev, buf, len, GFP_KERNEL);
kfree(buf);
if (IS_ERR(ah->nvmem_blob))
return PTR_ERR(ah->nvmem_blob);
if (!ah->nvmem_blob)
return -ENOMEM;
ah->nvmem_blob_len = len;
ah->ah_flags &= ~AH_USE_EEPROM;
@ -1094,6 +1094,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
ARRAY_SIZE(ath9k_tpt_blink));
#endif
wiphy_read_of_freq_limits(hw->wiphy);
/* Register with mac80211 */
error = ieee80211_register_hw(hw);
if (error)

View File

@ -533,8 +533,10 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_debug_sync_cause(sc, sync_cause);
status &= ah->imask; /* discard unasked-for bits */
if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) {
ath9k_hw_kill_interrupts(sc->sc_ah);
return IRQ_HANDLED;
}
/*
* If there are no status bits set, then this interrupt was not

View File

@ -183,10 +183,12 @@ static void channel_detector_exit(struct dfs_pattern_detector *dpd,
if (cd == NULL)
return;
list_del(&cd->head);
for (i = 0; i < dpd->num_radar_types; i++) {
struct pri_detector *de = cd->detectors[i];
if (de != NULL)
de->exit(de);
if (cd->detectors) {
for (i = 0; i < dpd->num_radar_types; i++) {
struct pri_detector *de = cd->detectors[i];
if (de != NULL)
de->exit(de);
}
}
kfree(cd->detectors);
kfree(cd);

View File

@ -723,11 +723,13 @@ wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name,
ndev = vif_to_ndev(vif);
ether_addr_copy(ndev->perm_addr, ndev_main->perm_addr);
if (is_valid_ether_addr(params->macaddr)) {
ether_addr_copy(ndev->dev_addr, params->macaddr);
eth_hw_addr_set(ndev, params->macaddr);
} else {
ether_addr_copy(ndev->dev_addr, ndev_main->perm_addr);
ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << vif->mid)) |
0x2; /* locally administered */
u8 addr[ETH_ALEN];
ether_addr_copy(addr, ndev_main->perm_addr);
addr[0] = (addr[0] ^ (1 << vif->mid)) | 0x2; /* locally administered */
eth_hw_addr_set(ndev, addr);
}
wdev = vif_to_wdev(vif);
ether_addr_copy(wdev->address, ndev->dev_addr);

View File

@ -1358,7 +1358,7 @@ static int wil_get_bl_info(struct wil6210_priv *wil)
ether_addr_copy(ndev->perm_addr, mac);
ether_addr_copy(wiphy->perm_addr, mac);
if (!is_valid_ether_addr(ndev->dev_addr))
ether_addr_copy(ndev->dev_addr, mac);
eth_hw_addr_set(ndev, mac);
if (rf_status) {/* bad RF cable? */
wil_err(wil, "RF communication error 0x%04x",
@ -1431,7 +1431,7 @@ static int wil_get_otp_info(struct wil6210_priv *wil)
ether_addr_copy(ndev->perm_addr, mac);
ether_addr_copy(wiphy->perm_addr, mac);
if (!is_valid_ether_addr(ndev->dev_addr))
ether_addr_copy(ndev->dev_addr, mac);
eth_hw_addr_set(ndev, mac);
return 0;
}
@ -1609,7 +1609,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
struct net_device *ndev = wil->main_ndev;
ether_addr_copy(ndev->perm_addr, mac);
ether_addr_copy(ndev->dev_addr, ndev->perm_addr);
eth_hw_addr_set(ndev, ndev->perm_addr);
return 0;
}

View File

@ -1341,7 +1341,7 @@ struct wil6210_priv *wil_cfg80211_init(struct device *dev);
void wil_cfg80211_deinit(struct wil6210_priv *wil);
void wil_p2p_wdev_free(struct wil6210_priv *wil);
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
int wmi_set_mac_address(struct wil6210_priv *wil, const void *addr);
int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype, u8 chan,
u8 edmg_chan, u8 hidden_ssid, u8 is_go);
int wmi_pcp_stop(struct wil6210_vif *vif);

View File

@ -2097,7 +2097,7 @@ int wmi_echo(struct wil6210_priv *wil)
WIL_WMI_CALL_GENERAL_TO_MS);
}
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
int wmi_set_mac_address(struct wil6210_priv *wil, const void *addr)
{
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
struct wmi_set_mac_address_cmd cmd;

View File

@ -600,7 +600,7 @@ static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index,
static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
u16 data);
static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
u8 *data, int data_len);
const u8 *data, int data_len);
static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
u8 *data, int data_len);
static void atmel_scan(struct atmel_private *priv, int specific_ssid);
@ -1296,7 +1296,7 @@ static int atmel_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
eth_hw_addr_set(dev, addr->sa_data);
return atmel_open(dev);
}
@ -3669,6 +3669,7 @@ static int probe_atmel_card(struct net_device *dev)
{
int rc = 0;
struct atmel_private *priv = netdev_priv(dev);
u8 addr[ETH_ALEN] = {};
/* reset pccard */
if (priv->bus_type == BUS_TYPE_PCCARD)
@ -3693,7 +3694,9 @@ static int probe_atmel_card(struct net_device *dev)
if (i == 0) {
printk(KERN_ALERT "%s: MAC failed to boot MAC address reader.\n", dev->name);
} else {
atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
atmel_copy_to_host(dev, addr, atmel_read16(dev, MR2), 6);
eth_hw_addr_set(dev, addr);
/* got address, now squash it again until the network
interface is opened */
if (priv->bus_type == BUS_TYPE_PCCARD)
@ -3705,7 +3708,8 @@ static int probe_atmel_card(struct net_device *dev)
/* Mac address easy in this case. */
priv->card_type = CARD_TYPE_PARALLEL_FLASH;
atmel_write16(dev, BSR, 1);
atmel_copy_to_host(dev, dev->dev_addr, 0xc000, 6);
atmel_copy_to_host(dev, addr, 0xc000, 6);
eth_hw_addr_set(dev, addr);
atmel_write16(dev, BSR, 0x200);
rc = 1;
} else {
@ -3713,7 +3717,8 @@ static int probe_atmel_card(struct net_device *dev)
for the Mac Address */
priv->card_type = CARD_TYPE_SPI_FLASH;
if (atmel_wakeup_firmware(priv) == 0) {
atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);
atmel_get_mib(priv, Mac_Address_Mib_Type, 0, addr, 6);
eth_hw_addr_set(dev, addr);
/* got address, now squash it again until the network
interface is opened */
@ -3730,7 +3735,7 @@ static int probe_atmel_card(struct net_device *dev)
0x00, 0x04, 0x25, 0x00, 0x00, 0x00
};
printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name);
memcpy(dev->dev_addr, default_mac, ETH_ALEN);
eth_hw_addr_set(dev, default_mac);
}
}
@ -4103,7 +4108,7 @@ static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
}
static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
u8 *data, int data_len)
const u8 *data, int data_len)
{
struct get_set_mib m;
m.type = type;

View File

@ -2297,7 +2297,7 @@ static u8 b43_gphy_aci_scan(struct b43_wldev *dev)
b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF);
b43_set_all_gains(dev, 3, 8, 1);
start = (channel - 5 > 0) ? channel - 5 : 1;
start = (channel > 5) ? channel - 5 : 1;
end = (channel + 5 < 14) ? channel + 5 : 13;
for (i = start; i <= end; i++) {

View File

@ -283,7 +283,7 @@ u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev)
& 0x7FFF);
b43legacy_set_all_gains(dev, 3, 8, 1);
start = (channel - 5 > 0) ? channel - 5 : 1;
start = (channel > 5) ? channel - 5 : 1;
end = (channel + 5 < 14) ? channel + 5 : 13;
for (i = start; i <= end; i++) {

View File

@ -244,7 +244,7 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
} else {
brcmf_dbg(TRACE, "updated to %pM\n", sa->sa_data);
memcpy(ifp->mac_addr, sa->sa_data, ETH_ALEN);
memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
eth_hw_addr_set(ifp->ndev, ifp->mac_addr);
}
return err;
}
@ -655,7 +655,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool locked)
ndev->ethtool_ops = &brcmf_ethtool_ops;
/* set the mac address & netns */
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
eth_hw_addr_set(ndev, ifp->mac_addr);
dev_net_set(ndev, wiphy_net(cfg_to_wiphy(drvr->config)));
INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
@ -830,7 +830,7 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
ndev->netdev_ops = &brcmf_netdev_ops_p2p;
/* set the mac address */
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
eth_hw_addr_set(ndev, ifp->mac_addr);
if (register_netdev(ndev) != 0) {
bphy_err(drvr, "couldn't register the p2p net device\n");

View File

@ -2125,7 +2125,7 @@ static int brcmf_p2p_disable_p2p_if(struct brcmf_cfg80211_vif *vif)
struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
struct net_device *pri_ndev = cfg_to_ndev(cfg);
struct brcmf_if *ifp = netdev_priv(pri_ndev);
u8 *addr = vif->wdev.netdev->dev_addr;
const u8 *addr = vif->wdev.netdev->dev_addr;
return brcmf_fil_iovar_data_set(ifp, "p2p_ifdis", addr, ETH_ALEN);
}
@ -2135,7 +2135,7 @@ static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif)
struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
struct net_device *pri_ndev = cfg_to_ndev(cfg);
struct brcmf_if *ifp = netdev_priv(pri_ndev);
u8 *addr = vif->wdev.netdev->dev_addr;
const u8 *addr = vif->wdev.netdev->dev_addr;
return brcmf_fil_iovar_data_set(ifp, "p2p_ifdel", addr, ETH_ALEN);
}

View File

@ -1109,7 +1109,7 @@ struct airo_info;
static int get_dec_u16(char *buffer, int *start, int limit);
static void OUT4500(struct airo_info *, u16 reg, u16 value);
static unsigned short IN4500(struct airo_info *, u16 reg);
static u16 setup_card(struct airo_info*, u8 *mac, int lock);
static u16 setup_card(struct airo_info*, struct net_device *dev, int lock);
static int enable_MAC(struct airo_info *ai, int lock);
static void disable_MAC(struct airo_info *ai, int lock);
static void enable_interrupts(struct airo_info*);
@ -2337,9 +2337,9 @@ static int airo_set_mac_address(struct net_device *dev, void *p)
disable_MAC(ai, 1);
writeConfigRid (ai, 1);
enable_MAC(ai, 1);
memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len);
dev_addr_set(ai->dev, addr->sa_data);
if (ai->wifidev)
memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len);
dev_addr_set(ai->wifidev, addr->sa_data);
return 0;
}
@ -2854,7 +2854,7 @@ static struct net_device *_init_airo_card(unsigned short irq, int port,
}
if (probe) {
if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) {
if (setup_card(ai, dev, 1) != SUCCESS) {
airo_print_err(dev->name, "MAC could not be enabled");
rc = -EIO;
goto err_out_map;
@ -2972,7 +2972,7 @@ int reset_airo_card(struct net_device *dev)
if (reset_card (dev, 1))
return -1;
if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) {
if (setup_card(ai, dev, 1) != SUCCESS) {
airo_print_err(dev->name, "MAC could not be enabled");
return -1;
}
@ -3817,7 +3817,8 @@ static inline void set_auth_type(struct airo_info *local, int auth_type)
local->last_auth = auth_type;
}
static int noinline_for_stack airo_readconfig(struct airo_info *ai, u8 *mac, int lock)
static int noinline_for_stack airo_readconfig(struct airo_info *ai,
struct net_device *dev, int lock)
{
int i, status;
/* large variables, so don't inline this function,
@ -3861,9 +3862,7 @@ static int noinline_for_stack airo_readconfig(struct airo_info *ai, u8 *mac, int
}
/* Save off the MAC */
for (i = 0; i < ETH_ALEN; i++) {
mac[i] = ai->config.macAddr[i];
}
eth_hw_addr_set(dev, ai->config.macAddr);
/* Check to see if there are any insmod configured
rates to add */
@ -3879,7 +3878,7 @@ static int noinline_for_stack airo_readconfig(struct airo_info *ai, u8 *mac, int
}
static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
static u16 setup_card(struct airo_info *ai, struct net_device *dev, int lock)
{
Cmd cmd;
Resp rsp;
@ -3925,7 +3924,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
if (lock)
up(&ai->sem);
if (ai->config.len == 0) {
status = airo_readconfig(ai, mac, lock);
status = airo_readconfig(ai, dev, lock);
if (status != SUCCESS)
return ERROR;
}
@ -5654,7 +5653,7 @@ static int __maybe_unused airo_pci_resume(struct device *dev_d)
if (prev_state != PCI_D1) {
reset_card(dev, 0);
mpi_init_descriptors(ai);
setup_card(ai, dev->dev_addr, 0);
setup_card(ai, dev, 0);
clear_bit(FLAG_RADIO_OFF, &ai->flags);
clear_bit(FLAG_PENDING_XMIT, &ai->flags);
} else {
@ -7534,7 +7533,7 @@ static int airo_config_commit(struct net_device *dev,
readSsidRid(local, &SSID_rid);
if (test_bit(FLAG_MPI,&local->flags))
setup_card(local, dev->dev_addr, 1);
setup_card(local, dev, 1);
else
reset_airo_card(dev);
disable_MAC(local, 1);
@ -8208,7 +8207,7 @@ static int flashrestart(struct airo_info *ai, struct net_device *dev)
if (status != SUCCESS)
return status;
}
status = setup_card(ai, dev->dev_addr, 1);
status = setup_card(ai, dev, 1);
if (!test_bit(FLAG_MPI,&ai->flags))
for (i = 0; i < MAX_FIDS; i++) {

View File

@ -4685,7 +4685,7 @@ static int ipw2100_read_mac_address(struct ipw2100_priv *priv)
return -EIO;
}
memcpy(priv->net_dev->dev_addr, addr, ETH_ALEN);
eth_hw_addr_set(priv->net_dev, addr);
IPW_DEBUG_INFO("card MAC is %pM\n", priv->net_dev->dev_addr);
return 0;
@ -4712,7 +4712,7 @@ static int ipw2100_set_mac_address(struct ipw2100_priv *priv, int batch_mode)
if (priv->config & CFG_CUSTOM_MAC) {
memcpy(cmd.host_command_parameters, priv->mac_addr, ETH_ALEN);
memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
eth_hw_addr_set(priv->net_dev, priv->mac_addr);
} else
memcpy(cmd.host_command_parameters, priv->net_dev->dev_addr,
ETH_ALEN);

View File

@ -199,7 +199,7 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
struct clx2_tx_queue *txq, int qindex);
static int ipw_queue_reset(struct ipw_priv *priv);
static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf,
static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, const void *buf,
int len, int sync);
static void ipw_tx_queue_free(struct ipw_priv *);
@ -2264,7 +2264,7 @@ static int ipw_send_cmd_simple(struct ipw_priv *priv, u8 command)
}
static int ipw_send_cmd_pdu(struct ipw_priv *priv, u8 command, u8 len,
void *data)
const void *data)
{
struct host_cmd cmd = {
.cmd = command,
@ -5033,7 +5033,7 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
return used;
}
static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf,
static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, const void *buf,
int len, int sync)
{
struct clx2_tx_queue *txq = &priv->txq_cmd;
@ -11185,7 +11185,7 @@ static int ipw_up(struct ipw_priv *priv)
ipw_init_ordinals(priv);
if (!(priv->config & CFG_CUSTOM_MAC))
eeprom_parse_mac(priv, priv->mac_addr);
memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
eth_hw_addr_set(priv->net_dev, priv->mac_addr);
ipw_set_geo(priv);
@ -11542,7 +11542,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv)
priv->prom_priv->priv = priv;
strcpy(priv->prom_net_dev->name, "rtap%d");
memcpy(priv->prom_net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
eth_hw_addr_set(priv->prom_net_dev, priv->mac_addr);
priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops;

View File

@ -1945,7 +1945,7 @@ struct host_cmd {
u8 cmd;
u8 len;
u16 reserved;
u32 *param;
const u32 *param;
} __packed; /* XXX */
struct cmdlog_host_cmd {

View File

@ -3819,7 +3819,6 @@ il3945_pci_remove(struct pci_dev *pdev)
il3945_unset_hw_params(il);
/*netif_stop_queue(dev); */
flush_workqueue(il->workqueue);
/* ieee80211_unregister_hw calls il3945_mac_stop, which flushes
* il->workqueue... so we can't take down the workqueue

View File

@ -6731,7 +6731,6 @@ il4965_pci_remove(struct pci_dev *pdev)
il_eeprom_free(il);
/*netif_stop_queue(dev); */
flush_workqueue(il->workqueue);
/* ieee80211_unregister_hw calls il_mac_stop, which flushes
* il->workqueue... so we can't take down the workqueue

View File

@ -355,7 +355,7 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
.base_params = &iwl_ax210_base_params,
.umac_prph_offset = 0x300000,
.integrated = true,
/* TODO: the following values need to be checked */
.low_latency_xtal = true,
.xtal_latency = 12000,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};

View File

@ -1525,7 +1525,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
kfree(priv->nvm_data);
/*netif_stop_queue(dev); */
flush_workqueue(priv->workqueue);
/* ieee80211_unregister_hw calls iwlagn_mac_stop, which flushes
* priv->workqueue... so we can't take down the workqueue

View File

@ -284,16 +284,19 @@ int iwl_pnvm_load(struct iwl_trans *trans,
/* First attempt to get the PNVM from BIOS */
package = iwl_uefi_get_pnvm(trans, &len);
if (!IS_ERR_OR_NULL(package)) {
data = kmemdup(package->data, len, GFP_KERNEL);
if (len >= sizeof(*package)) {
/* we need only the data */
len -= sizeof(*package);
data = kmemdup(package->data, len, GFP_KERNEL);
} else {
data = NULL;
}
/* free package regardless of whether kmemdup succeeded */
kfree(package);
if (data) {
/* we need only the data size */
len -= sizeof(*package);
if (data)
goto parse;
}
}
/* If it's not available, try from the filesystem */

View File

@ -2336,7 +2336,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
false, 0);
ret = 1;
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
goto err;
}
@ -2385,6 +2384,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
}
}
/* after the successful handshake, we're out of D3 */
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
/*
@ -2455,6 +2455,9 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
*/
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
/* regardless of what happened, we're now out of D3 */
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
return 1;
}

View File

@ -931,9 +931,9 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_b0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_b0_hr_b0, iwl_ax203_name),
/* Qu C step */
@ -945,7 +945,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_c0_hr_b0, iwl_ax203_name),
/* QuZ */

View File

@ -1403,14 +1403,17 @@ static int prism2_hw_init2(struct net_device *dev, int initial)
hfa384x_events_only_cmd(dev);
if (initial) {
u8 addr[ETH_ALEN] = {};
struct list_head *ptr;
prism2_check_sta_fw_version(local);
if (hfa384x_get_rid(dev, HFA384X_RID_CNFOWNMACADDR,
dev->dev_addr, 6, 1) < 0) {
addr, ETH_ALEN, 1) < 0) {
printk("%s: could not get own MAC address\n",
dev->name);
}
eth_hw_addr_set(dev, addr);
list_for_each(ptr, &local->hostap_interfaces) {
iface = list_entry(ptr, struct hostap_interface, list);
eth_hw_addr_inherit(iface->dev, dev);

View File

@ -713,9 +713,9 @@ static int prism2_set_mac_address(struct net_device *dev, void *p)
read_lock_bh(&local->iface_lock);
list_for_each(ptr, &local->hostap_interfaces) {
iface = list_entry(ptr, struct hostap_interface, list);
memcpy(iface->dev->dev_addr, addr->sa_data, ETH_ALEN);
eth_hw_addr_set(iface->dev, addr->sa_data);
}
memcpy(local->dev->dev_addr, addr->sa_data, ETH_ALEN);
eth_hw_addr_set(local->dev, addr->sa_data);
read_unlock_bh(&local->iface_lock);
return 0;

View File

@ -2265,7 +2265,7 @@ int orinoco_if_add(struct orinoco_private *priv,
netif_carrier_off(dev);
memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
eth_hw_addr_set(dev, wiphy->perm_addr);
dev->base_addr = base_addr;
dev->irq = irq;

View File

@ -150,10 +150,9 @@ int lbs_update_hw_spec(struct lbs_private *priv)
memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
if (!priv->copied_hwaddr) {
memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
eth_hw_addr_set(priv->dev, priv->current_addr);
if (priv->mesh_dev)
memcpy(priv->mesh_dev->dev_addr,
priv->current_addr, ETH_ALEN);
eth_hw_addr_set(priv->mesh_dev, priv->current_addr);
priv->copied_hwaddr = 1;
}

View File

@ -302,9 +302,9 @@ int lbs_set_mac_address(struct net_device *dev, void *addr)
dev = priv->dev;
memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
eth_hw_addr_set(dev, phwaddr->sa_data);
if (priv->mesh_dev)
memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
eth_hw_addr_set(priv->mesh_dev, phwaddr->sa_data);
return ret;
}

View File

@ -125,7 +125,7 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
tx_ba_tbl->ra);
} else { /*
* In case of failure, recreate the deleted stream in case
* we initiated the ADDBA
* we initiated the DELBA
*/
if (!INITIATOR_BIT(del_ba_param_set))
return 0;
@ -657,14 +657,15 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
uint16_t del_ba_param_set;
memset(&delba, 0, sizeof(delba));
delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS);
del_ba_param_set = le16_to_cpu(delba.del_ba_param_set);
del_ba_param_set = tid << DELBA_TID_POS;
if (initiator)
del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK;
else
del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK;
delba.del_ba_param_set = cpu_to_le16(del_ba_param_set);
memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN);
/* We don't wait for the response of this command */

View File

@ -519,8 +519,14 @@ mwifiex_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
encrypt_key.is_igtk_def_key = true;
eth_broadcast_addr(encrypt_key.mac_addr);
return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
HostCmd_ACT_GEN_SET, true, &encrypt_key, true);
if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
HostCmd_ACT_GEN_SET, true, &encrypt_key, true)) {
mwifiex_dbg(priv->adapter, ERROR,
"Sending KEY_MATERIAL command failed\n");
return -1;
}
return 0;
}
/*
@ -3218,13 +3224,11 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
cfg80211_unregister_netdevice(wdev->netdev);
if (priv->dfs_cac_workqueue) {
flush_workqueue(priv->dfs_cac_workqueue);
destroy_workqueue(priv->dfs_cac_workqueue);
priv->dfs_cac_workqueue = NULL;
}
if (priv->dfs_chan_sw_workqueue) {
flush_workqueue(priv->dfs_chan_sw_workqueue);
destroy_workqueue(priv->dfs_chan_sw_workqueue);
priv->dfs_chan_sw_workqueue = NULL;
}
@ -3494,7 +3498,7 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
}
if (!wowlan) {
mwifiex_dbg(adapter, ERROR,
mwifiex_dbg(adapter, INFO,
"None of the WOWLAN triggers enabled\n");
ret = 0;
goto done;

View File

@ -608,6 +608,11 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
return -1;
}
if (priv->adapter->hs_activated_manually &&
cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) {
mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
priv->adapter->hs_activated_manually = false;
}
/* Get a new command node */
cmd_node = mwifiex_get_cmd_node(adapter);
@ -714,6 +719,15 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
}
}
/* Same with exit host sleep cmd, luckily that can't happen at the same time as EXIT_PS */
if (command == HostCmd_CMD_802_11_HS_CFG_ENH) {
struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg =
&host_cmd->params.opt_hs_cfg;
if (le16_to_cpu(hs_cfg->action) == HS_ACTIVATE)
add_tail = false;
}
spin_lock_bh(&adapter->cmd_pending_q_lock);
if (add_tail)
list_add_tail(&cmd_node->list, &adapter->cmd_pending_q);
@ -1216,6 +1230,13 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
__func__);
adapter->if_ops.wakeup(adapter);
if (adapter->hs_activated_manually) {
mwifiex_cancel_hs(mwifiex_get_priv (adapter, MWIFIEX_BSS_ROLE_ANY),
MWIFIEX_ASYNC_CMD);
adapter->hs_activated_manually = false;
}
adapter->hs_activated = false;
clear_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags);
clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);

View File

@ -401,6 +401,12 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
!adapter->scan_processing) &&
!adapter->data_sent &&
!skb_queue_empty(&adapter->tx_data_q)) {
if (adapter->hs_activated_manually) {
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY),
MWIFIEX_ASYNC_CMD);
adapter->hs_activated_manually = false;
}
mwifiex_process_tx_queue(adapter);
if (adapter->hs_activated) {
clear_bit(MWIFIEX_IS_HS_CONFIGURED,
@ -418,6 +424,12 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
!mwifiex_bypass_txlist_empty(adapter) &&
!mwifiex_is_tdls_chan_switching
(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
if (adapter->hs_activated_manually) {
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY),
MWIFIEX_ASYNC_CMD);
adapter->hs_activated_manually = false;
}
mwifiex_process_bypass_tx(adapter);
if (adapter->hs_activated) {
clear_bit(MWIFIEX_IS_HS_CONFIGURED,
@ -434,6 +446,12 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
!adapter->data_sent && !mwifiex_wmm_lists_empty(adapter) &&
!mwifiex_is_tdls_chan_switching
(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
if (adapter->hs_activated_manually) {
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY),
MWIFIEX_ASYNC_CMD);
adapter->hs_activated_manually = false;
}
mwifiex_wmm_process_tx(adapter);
if (adapter->hs_activated) {
clear_bit(MWIFIEX_IS_HS_CONFIGURED,
@ -498,13 +516,11 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
{
if (adapter->workqueue) {
flush_workqueue(adapter->workqueue);
destroy_workqueue(adapter->workqueue);
adapter->workqueue = NULL;
}
if (adapter->rx_workqueue) {
flush_workqueue(adapter->rx_workqueue);
destroy_workqueue(adapter->rx_workqueue);
adapter->rx_workqueue = NULL;
}
@ -987,7 +1003,7 @@ int mwifiex_set_mac_address(struct mwifiex_private *priv,
return ret;
}
ether_addr_copy(dev->dev_addr, priv->curr_addr);
eth_hw_addr_set(dev, priv->curr_addr);
return 0;
}

View File

@ -986,6 +986,7 @@ struct mwifiex_adapter {
struct timer_list wakeup_timer;
struct mwifiex_hs_config_param hs_cfg;
u8 hs_activated;
u8 hs_activated_manually;
u16 hs_activate_wait_q_woken;
wait_queue_head_t hs_activate_wait_q;
u8 event_body[MAX_EVENT_SIZE];

View File

@ -17,6 +17,7 @@
* this warranty disclaimer.
*/
#include <linux/iopoll.h>
#include <linux/firmware.h>
#include "decl.h"
@ -647,11 +648,15 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
"max count reached while accessing sleep cookie\n");
}
#define N_WAKEUP_TRIES_SHORT_INTERVAL 15
#define N_WAKEUP_TRIES_LONG_INTERVAL 35
/* This function wakes up the card by reading fw_status register. */
static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
int retval;
mwifiex_dbg(adapter, EVENT,
"event: Wakeup device...\n");
@ -659,11 +664,24 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
if (reg->sleep_cookie)
mwifiex_pcie_dev_wakeup_delay(adapter);
/* Accessing fw_status register will wakeup device */
if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
mwifiex_dbg(adapter, ERROR,
"Writing fw_status register failed\n");
return -1;
/* The 88W8897 PCIe+USB firmware (latest version 15.68.19.p21) sometimes
* appears to ignore or miss our wakeup request, so we continue trying
* until we receive an interrupt from the card.
*/
if (read_poll_timeout(mwifiex_write_reg, retval,
READ_ONCE(adapter->int_status) != 0,
500, 500 * N_WAKEUP_TRIES_SHORT_INTERVAL,
false,
adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
if (read_poll_timeout(mwifiex_write_reg, retval,
READ_ONCE(adapter->int_status) != 0,
10000, 10000 * N_WAKEUP_TRIES_LONG_INTERVAL,
false,
adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
mwifiex_dbg(adapter, ERROR,
"Firmware didn't wake up\n");
return -EIO;
}
}
if (reg->sleep_cookie) {
@ -1490,6 +1508,14 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
ret = -1;
goto done_unmap;
}
/* The firmware (latest version 15.68.19.p21) of the 88W8897 PCIe+USB card
* seems to crash randomly after setting the TX ring write pointer when
* ASPM powersaving is enabled. A workaround seems to be keeping the bus
* busy by reading a random register afterwards.
*/
mwifiex_read_reg(adapter, PCI_VENDOR_ID, &rx_val);
if ((mwifiex_pcie_txbd_not_full(card)) &&
tx_param->next_pkt_len) {
/* have more packets and TxBD still can hold more */

View File

@ -396,6 +396,10 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
if (hs_activate) {
hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED);
adapter->hs_activated_manually = true;
mwifiex_dbg(priv->adapter, CMD,
"cmd: Activating host sleep manually\n");
} else {
hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
hs_cfg->params.hs_config.conditions = hscfg_param->conditions;

View File

@ -197,8 +197,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
mwifiex_dbg(adapter, EVENT,
"AP EVENT: event id: %#x\n", eventcause);
priv->port_open = false;
memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
ETH_ALEN);
eth_hw_addr_set(priv->netdev, adapter->event_body + 2);
if (priv->hist_data)
mwifiex_hist_data_reset(priv);
mwifiex_check_uap_capabilities(priv, adapter->event_skb);

View File

@ -5800,8 +5800,8 @@ static void mwl8k_fw_state_machine(const struct firmware *fw, void *context)
fail:
priv->fw_state = FW_STATE_ERROR;
complete(&priv->firmware_loading_complete);
device_release_driver(&priv->pdev->dev);
mwl8k_release_firmware(priv);
device_release_driver(&priv->pdev->dev);
}
#define MAX_RESTART_ATTEMPTS 1

View File

@ -14,7 +14,7 @@ mt76-$(CONFIG_PCI) += pci.o
mt76-$(CONFIG_NL80211_TESTMODE) += testmode.o
mt76-usb-y := usb.o usb_trace.o
mt76-sdio-y := sdio.o
mt76-sdio-y := sdio.o sdio_txrx.o
CFLAGS_trace.o := -I$(src)
CFLAGS_usb_trace.o := -I$(src)

View File

@ -56,14 +56,14 @@ int mt76_queues_read(struct seq_file *s, void *data)
struct mt76_dev *dev = dev_get_drvdata(s->private);
int i;
seq_puts(s, " queue | hw-queued | head | tail |\n");
for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) {
struct mt76_queue *q = dev->phy.q_tx[i];
if (!q)
continue;
seq_printf(s,
"%d: queued=%d head=%d tail=%d\n",
seq_printf(s, " %9d | %9d | %9d | %9d |\n",
i, q->queued, q->head, q->tail);
}
@ -76,12 +76,13 @@ static int mt76_rx_queues_read(struct seq_file *s, void *data)
struct mt76_dev *dev = dev_get_drvdata(s->private);
int i, queued;
seq_puts(s, " queue | hw-queued | head | tail |\n");
mt76_for_each_q_rx(dev, i) {
struct mt76_queue *q = &dev->q_rx[i];
queued = mt76_is_usb(dev) ? q->ndesc - q->queued : q->queued;
seq_printf(s, "%d: queued=%d head=%d tail=%d\n",
i, queued, q->head, q->tail);
seq_printf(s, " %9d | %9d | %9d | %9d |\n",
i, q->queued, q->head, q->tail);
}
return 0;
@ -116,18 +117,21 @@ static int mt76_read_rate_txpower(struct seq_file *s, void *data)
return 0;
}
struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
struct dentry *
mt76_register_debugfs_fops(struct mt76_phy *phy,
const struct file_operations *ops)
{
const struct file_operations *fops = ops ? ops : &fops_regval;
struct mt76_dev *dev = phy->dev;
struct dentry *dir;
dir = debugfs_create_dir("mt76", dev->hw->wiphy->debugfsdir);
dir = debugfs_create_dir("mt76", phy->hw->wiphy->debugfsdir);
if (!dir)
return NULL;
debugfs_create_u8("led_pin", 0600, dir, &dev->led_pin);
debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg);
debugfs_create_file_unsafe("regval", 0600, dir, dev,
&fops_regval);
debugfs_create_file_unsafe("regval", 0600, dir, dev, fops);
debugfs_create_file_unsafe("napi_threaded", 0600, dir, dev,
&fops_napi_threaded);
debugfs_create_blob("eeprom", 0400, dir, &dev->eeprom);
@ -140,4 +144,4 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
return dir;
}
EXPORT_SYMBOL_GPL(mt76_register_debugfs);
EXPORT_SYMBOL_GPL(mt76_register_debugfs_fops);

View File

@ -15,6 +15,7 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
struct device_node *np = dev->dev->of_node;
struct mtd_info *mtd;
const __be32 *list;
const void *data;
const char *part;
phandle phandle;
int size;
@ -24,6 +25,16 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
if (!np)
return -ENOENT;
data = of_get_property(np, "mediatek,eeprom-data", &size);
if (data) {
if (size > len)
return -EINVAL;
memcpy(eep, data, size);
return 0;
}
list = of_get_property(np, "mediatek,mtd-eeprom", &size);
if (!list)
return -ENOENT;
@ -285,6 +296,9 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
case NL80211_BAND_5GHZ:
band = '5';
break;
case NL80211_BAND_6GHZ:
band = '6';
break;
default:
return target_power;
}

View File

@ -20,6 +20,13 @@
.max_power = 30, \
}
#define CHAN6G(_idx, _freq) { \
.band = NL80211_BAND_6GHZ, \
.center_freq = (_freq), \
.hw_value = (_idx), \
.max_power = 30, \
}
static const struct ieee80211_channel mt76_channels_2ghz[] = {
CHAN2G(1, 2412),
CHAN2G(2, 2417),
@ -70,6 +77,72 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
CHAN5G(173, 5865),
};
static const struct ieee80211_channel mt76_channels_6ghz[] = {
/* UNII-5 */
CHAN6G(1, 5955),
CHAN6G(5, 5975),
CHAN6G(9, 5995),
CHAN6G(13, 6015),
CHAN6G(17, 6035),
CHAN6G(21, 6055),
CHAN6G(25, 6075),
CHAN6G(29, 6095),
CHAN6G(33, 6115),
CHAN6G(37, 6135),
CHAN6G(41, 6155),
CHAN6G(45, 6175),
CHAN6G(49, 6195),
CHAN6G(53, 6215),
CHAN6G(57, 6235),
CHAN6G(61, 6255),
CHAN6G(65, 6275),
CHAN6G(69, 6295),
CHAN6G(73, 6315),
CHAN6G(77, 6335),
CHAN6G(81, 6355),
CHAN6G(85, 6375),
CHAN6G(89, 6395),
CHAN6G(93, 6415),
/* UNII-6 */
CHAN6G(97, 6435),
CHAN6G(101, 6455),
CHAN6G(105, 6475),
CHAN6G(109, 6495),
CHAN6G(113, 6515),
CHAN6G(117, 6535),
/* UNII-7 */
CHAN6G(121, 6555),
CHAN6G(125, 6575),
CHAN6G(129, 6595),
CHAN6G(133, 6615),
CHAN6G(137, 6635),
CHAN6G(141, 6655),
CHAN6G(145, 6675),
CHAN6G(149, 6695),
CHAN6G(153, 6715),
CHAN6G(157, 6735),
CHAN6G(161, 6755),
CHAN6G(165, 6775),
CHAN6G(169, 6795),
CHAN6G(173, 6815),
CHAN6G(177, 6835),
CHAN6G(181, 6855),
CHAN6G(185, 6875),
/* UNII-8 */
CHAN6G(189, 6895),
CHAN6G(193, 6915),
CHAN6G(197, 6935),
CHAN6G(201, 6955),
CHAN6G(205, 6975),
CHAN6G(209, 6995),
CHAN6G(213, 7015),
CHAN6G(217, 7035),
CHAN6G(221, 7055),
CHAN6G(225, 7075),
CHAN6G(229, 7095),
CHAN6G(233, 7115),
};
static const struct ieee80211_tpt_blink mt76_tpt_blink[] = {
{ .throughput = 0 * 1024, .blink_time = 334 },
{ .throughput = 1 * 1024, .blink_time = 260 },
@ -99,6 +172,21 @@ struct ieee80211_rate mt76_rates[] = {
};
EXPORT_SYMBOL_GPL(mt76_rates);
static const struct cfg80211_sar_freq_ranges mt76_sar_freq_ranges[] = {
{ .start_freq = 2402, .end_freq = 2494, },
{ .start_freq = 5150, .end_freq = 5350, },
{ .start_freq = 5350, .end_freq = 5470, },
{ .start_freq = 5470, .end_freq = 5725, },
{ .start_freq = 5725, .end_freq = 5950, },
};
const struct cfg80211_sar_capa mt76_sar_capa = {
.type = NL80211_SAR_TYPE_POWER,
.num_freq_ranges = ARRAY_SIZE(mt76_sar_freq_ranges),
.freq_ranges = &mt76_sar_freq_ranges[0],
};
EXPORT_SYMBOL_GPL(mt76_sar_capa);
static int mt76_led_init(struct mt76_dev *dev)
{
struct device_node *np = dev->dev->of_node;
@ -179,13 +267,16 @@ void mt76_set_stream_caps(struct mt76_phy *phy, bool vht)
mt76_init_stream_cap(phy, &phy->sband_2g.sband, false);
if (phy->cap.has_5ghz)
mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht);
if (phy->cap.has_6ghz)
mt76_init_stream_cap(phy, &phy->sband_6g.sband, vht);
}
EXPORT_SYMBOL_GPL(mt76_set_stream_caps);
static int
mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband,
const struct ieee80211_channel *chan, int n_chan,
struct ieee80211_rate *rates, int n_rates, bool vht)
struct ieee80211_rate *rates, int n_rates,
bool ht, bool vht)
{
struct ieee80211_supported_band *sband = &msband->sband;
struct ieee80211_sta_vht_cap *vht_cap;
@ -209,6 +300,9 @@ mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband,
sband->bitrates = rates;
sband->n_bitrates = n_rates;
if (!ht)
return 0;
ht_cap = &sband->ht_cap;
ht_cap->ht_supported = true;
ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
@ -245,7 +339,7 @@ mt76_init_sband_2g(struct mt76_phy *phy, struct ieee80211_rate *rates,
return mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz,
ARRAY_SIZE(mt76_channels_2ghz), rates,
n_rates, false);
n_rates, true, false);
}
static int
@ -256,7 +350,18 @@ mt76_init_sband_5g(struct mt76_phy *phy, struct ieee80211_rate *rates,
return mt76_init_sband(phy, &phy->sband_5g, mt76_channels_5ghz,
ARRAY_SIZE(mt76_channels_5ghz), rates,
n_rates, vht);
n_rates, true, vht);
}
static int
mt76_init_sband_6g(struct mt76_phy *phy, struct ieee80211_rate *rates,
int n_rates)
{
phy->hw->wiphy->bands[NL80211_BAND_6GHZ] = &phy->sband_6g.sband;
return mt76_init_sband(phy, &phy->sband_6g, mt76_channels_6ghz,
ARRAY_SIZE(mt76_channels_6ghz), rates,
n_rates, false, false);
}
static void
@ -322,12 +427,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) {
ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST);
}
ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST);
ieee80211_hw_set(hw, MFP_CAPABLE);
ieee80211_hw_set(hw, AP_LINK_PS);
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
@ -385,9 +486,16 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht,
return ret;
}
if (phy->cap.has_6ghz) {
ret = mt76_init_sband_6g(phy, rates + 4, n_rates - 4);
if (ret)
return ret;
}
wiphy_read_of_freq_limits(phy->hw->wiphy);
mt76_check_sband(phy, &phy->sband_2g, NL80211_BAND_2GHZ);
mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ);
mt76_check_sband(phy, &phy->sband_6g, NL80211_BAND_6GHZ);
ret = ieee80211_register_hw(phy->hw);
if (ret)
@ -403,7 +511,7 @@ void mt76_unregister_phy(struct mt76_phy *phy)
{
struct mt76_dev *dev = phy->dev;
mt76_tx_status_check(dev, NULL, true);
mt76_tx_status_check(dev, true);
ieee80211_unregister_hw(phy->hw);
dev->phy2 = NULL;
}
@ -435,9 +543,9 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
spin_lock_init(&dev->rx_lock);
spin_lock_init(&dev->lock);
spin_lock_init(&dev->cc_lock);
spin_lock_init(&dev->status_lock);
mutex_init(&dev->mutex);
init_waitqueue_head(&dev->tx_wait);
skb_queue_head_init(&dev->status_list);
skb_queue_head_init(&dev->mcu.res_q);
init_waitqueue_head(&dev->mcu.wait);
@ -458,6 +566,8 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
spin_lock_init(&dev->token_lock);
idr_init(&dev->token);
INIT_LIST_HEAD(&dev->wcid_list);
INIT_LIST_HEAD(&dev->txwi_cache);
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
@ -495,9 +605,16 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
return ret;
}
if (phy->cap.has_6ghz) {
ret = mt76_init_sband_6g(phy, rates + 4, n_rates - 4);
if (ret)
return ret;
}
wiphy_read_of_freq_limits(hw->wiphy);
mt76_check_sband(&dev->phy, &phy->sband_2g, NL80211_BAND_2GHZ);
mt76_check_sband(&dev->phy, &phy->sband_5g, NL80211_BAND_5GHZ);
mt76_check_sband(&dev->phy, &phy->sband_6g, NL80211_BAND_6GHZ);
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
ret = mt76_led_init(dev);
@ -522,7 +639,7 @@ void mt76_unregister_device(struct mt76_dev *dev)
if (IS_ENABLED(CONFIG_MT76_LEDS))
mt76_led_cleanup(dev);
mt76_tx_status_check(dev, NULL, true);
mt76_tx_status_check(dev, true);
ieee80211_unregister_hw(hw);
}
EXPORT_SYMBOL_GPL(mt76_unregister_device);
@ -642,6 +759,8 @@ mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c)
if (c->band == NL80211_BAND_2GHZ)
msband = &phy->sband_2g;
else if (c->band == NL80211_BAND_6GHZ)
msband = &phy->sband_6g;
else
msband = &phy->sband_5g;
@ -717,10 +836,16 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx,
if (idx == 0 && dev->drv->update_survey)
mt76_update_survey(phy);
sband = &phy->sband_2g;
if (idx >= sband->sband.n_channels) {
idx -= sband->sband.n_channels;
if (idx >= phy->sband_2g.sband.n_channels +
phy->sband_5g.sband.n_channels) {
idx -= (phy->sband_2g.sband.n_channels +
phy->sband_5g.sband.n_channels);
sband = &phy->sband_6g;
} else if (idx >= phy->sband_2g.sband.n_channels) {
idx -= phy->sband_2g.sband.n_channels;
sband = &phy->sband_5g;
} else {
sband = &phy->sband_2g;
}
if (idx >= sband->sband.n_channels) {
@ -777,10 +902,17 @@ void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
return;
wcid->rx_check_pn = true;
/* data frame */
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
ieee80211_get_key_rx_seq(key, i, &seq);
memcpy(wcid->rx_key_pn[i], seq.ccmp.pn, sizeof(seq.ccmp.pn));
}
/* robust management frame */
ieee80211_get_key_rx_seq(key, -1, &seq);
memcpy(wcid->rx_key_pn[i], seq.ccmp.pn, sizeof(seq.ccmp.pn));
}
EXPORT_SYMBOL(mt76_wcid_key_setup);
@ -790,6 +922,7 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_sta **sta)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
struct mt76_rx_status mstat;
mstat = *((struct mt76_rx_status *)skb->cb);
@ -812,6 +945,10 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
status->device_timestamp = mstat.timestamp;
status->mactime = mstat.timestamp;
if (ieee80211_is_beacon(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control))
status->boottime_ns = ktime_get_boottime_ns();
BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb));
BUILD_BUG_ON(sizeof(status->chain_signal) !=
sizeof(mstat.chain_signal));
@ -828,7 +965,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_wcid *wcid = status->wcid;
struct ieee80211_hdr *hdr;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
int security_idx;
int ret;
if (!(status->flag & RX_FLAG_DECRYPTED))
@ -837,24 +974,39 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
if (!wcid || !wcid->rx_check_pn)
return 0;
security_idx = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
if (status->flag & RX_FLAG_8023)
goto skip_hdr_check;
hdr = mt76_skb_get_hdr(skb);
if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
/*
* Validate the first fragment both here and in mac80211
* All further fragments will be validated by mac80211 only.
*/
hdr = mt76_skb_get_hdr(skb);
if (ieee80211_is_frag(hdr) &&
!ieee80211_is_first_frag(hdr->frame_control))
return 0;
}
/* IEEE 802.11-2020, 12.5.3.4.4 "PN and replay detection" c):
*
* the recipient shall maintain a single replay counter for received
* individually addressed robust Management frames that are received
* with the To DS subfield equal to 0, [...]
*/
if (ieee80211_is_mgmt(hdr->frame_control) &&
!ieee80211_has_tods(hdr->frame_control))
security_idx = IEEE80211_NUM_TIDS;
skip_hdr_check:
BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0]));
ret = memcmp(status->iv, wcid->rx_key_pn[tidno],
ret = memcmp(status->iv, wcid->rx_key_pn[security_idx],
sizeof(status->iv));
if (ret <= 0)
return -EINVAL; /* replay */
memcpy(wcid->rx_key_pn[tidno], status->iv, sizeof(status->iv));
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;
@ -1109,6 +1261,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
wcid->ext_phy = ext_phy;
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
mt76_packet_id_init(wcid);
out:
mutex_unlock(&dev->mutex);
@ -1127,7 +1280,8 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
if (dev->drv->sta_remove)
dev->drv->sta_remove(dev, vif, sta);
mt76_tx_status_check(dev, wcid, true);
mt76_packet_id_flush(dev, wcid);
mt76_wcid_mask_clear(dev->wcid_mask, idx);
mt76_wcid_mask_clear(dev->wcid_phy_mask, idx);
}
@ -1270,7 +1424,7 @@ int mt76_get_rate(struct mt76_dev *dev,
int i, offset = 0, len = sband->n_bitrates;
if (cck) {
if (sband == &dev->phy.sband_5g.sband)
if (sband != &dev->phy.sband_2g.sband)
return 0;
idx &= ~BIT(2); /* short preamble */
@ -1336,3 +1490,49 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
return hwq;
}
EXPORT_SYMBOL_GPL(mt76_init_queue);
u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx)
{
int offset = 0;
struct ieee80211_rate *rate;
if (phy->chandef.chan->band != NL80211_BAND_2GHZ)
offset = 4;
/* pick the lowest rate for hidden nodes */
if (rateidx < 0)
rateidx = 0;
rate = &mt76_rates[offset + rateidx];
return rate->hw_value;
}
EXPORT_SYMBOL_GPL(mt76_calculate_default_rate);
void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
struct mt76_sta_stats *stats)
{
int i, ei = wi->initial_stat_idx;
u64 *data = wi->data;
wi->sta_count++;
data[ei++] += stats->tx_mode[MT_PHY_TYPE_CCK];
data[ei++] += stats->tx_mode[MT_PHY_TYPE_OFDM];
data[ei++] += stats->tx_mode[MT_PHY_TYPE_HT];
data[ei++] += stats->tx_mode[MT_PHY_TYPE_HT_GF];
data[ei++] += stats->tx_mode[MT_PHY_TYPE_VHT];
data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_SU];
data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_EXT_SU];
data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_TB];
data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_MU];
for (i = 0; i < ARRAY_SIZE(stats->tx_bw); i++)
data[ei++] += stats->tx_bw[i];
for (i = 0; i < 12; i++)
data[ei++] += stats->tx_mcs[i];
wi->worker_stat_count = ei - wi->initial_stat_idx;
}
EXPORT_SYMBOL_GPL(mt76_ethtool_worker);

View File

@ -106,13 +106,13 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(mt76_mcu_skb_send_and_get_msg);
int mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data,
int len)
int __mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data,
int len, int max_len)
{
int err, cur_len;
while (len > 0) {
cur_len = min_t(int, 4096 - dev->mcu_ops->headroom, len);
cur_len = min_t(int, max_len, len);
err = mt76_mcu_send_msg(dev, cmd, data, cur_len, false);
if (err)
@ -129,4 +129,4 @@ int mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data,
return 0;
}
EXPORT_SYMBOL_GPL(mt76_mcu_send_firmware);
EXPORT_SYMBOL_GPL(__mt76_mcu_send_firmware);

View File

@ -29,6 +29,7 @@
struct mt76_dev;
struct mt76_phy;
struct mt76_wcid;
struct mt76s_intr;
struct mt76_reg_pair {
u32 reg;
@ -244,6 +245,8 @@ struct mt76_wcid {
struct ewma_signal rssi;
int inactive_count;
struct rate_info rate;
u16 idx;
u8 hw_key_idx;
u8 hw_key_idx2;
@ -253,13 +256,14 @@ struct mt76_wcid {
u8 amsdu:1;
u8 rx_check_pn;
u8 rx_key_pn[IEEE80211_NUM_TIDS][6];
u8 rx_key_pn[IEEE80211_NUM_TIDS + 1][6];
u16 cipher;
u32 tx_info;
bool sw_iv;
u8 packet_id;
struct list_head list;
struct idr pktid;
};
struct mt76_txq {
@ -305,8 +309,13 @@ struct mt76_rx_tid {
#define MT_PACKET_ID_NO_SKB 1
#define MT_PACKET_ID_FIRST 2
#define MT_PACKET_ID_HAS_RATE BIT(7)
#define MT_TX_STATUS_SKB_TIMEOUT HZ
/* This is timer for when to give up when waiting for TXS callback,
* with starting time being the time at which the DMA_DONE callback
* was seen (so, we know packet was processed then, it should not take
* long after that for firmware to send the TXS callback if it is going
* to do so.)
*/
#define MT_TX_STATUS_SKB_TIMEOUT (HZ / 4)
struct mt76_tx_cb {
unsigned long jiffies;
@ -344,7 +353,6 @@ struct mt76_hw_cap {
#define MT_DRV_SW_RX_AIRTIME BIT(2)
#define MT_DRV_RX_DMA_HDR BIT(3)
#define MT_DRV_HW_MGMT_TXQ BIT(4)
#define MT_DRV_AMSDU_OFFLOAD BIT(5)
struct mt76_driver_ops {
u32 drv_flags;
@ -498,13 +506,18 @@ struct mt76_sdio {
struct sdio_func *func;
void *intr_data;
u8 hw_ver;
wait_queue_head_t wait;
struct {
int pse_data_quota;
int ple_data_quota;
int pse_mcu_quota;
int pse_page_size;
int deficit;
} sched;
int (*parse_irq)(struct mt76_dev *dev, struct mt76s_intr *intr);
};
struct mt76_mmio {
@ -545,6 +558,11 @@ struct mt76_rx_status {
s8 chain_signal[IEEE80211_MAX_CHAINS];
};
struct mt76_freq_range_power {
const struct cfg80211_sar_freq_ranges *range;
s8 power;
};
struct mt76_testmode_ops {
int (*set_state)(struct mt76_phy *phy, enum mt76_testmode_state state);
int (*set_params)(struct mt76_phy *phy, struct nlattr **tb,
@ -617,6 +635,7 @@ struct mt76_phy {
struct mt76_hw_cap cap;
struct mt76_sband sband_2g;
struct mt76_sband sband_5g;
struct mt76_sband sband_6g;
u8 macaddr[ETH_ALEN];
@ -636,6 +655,8 @@ struct mt76_phy {
struct sk_buff **tail;
u16 seqno;
} rx_amsdu[__MT_RXQ_MAX];
struct mt76_freq_range_power *frp;
};
struct mt76_dev {
@ -683,7 +704,8 @@ struct mt76_dev {
int token_count;
wait_queue_head_t tx_wait;
struct sk_buff_head status_list;
/* spinclock used to protect wcid pktid linked list */
spinlock_t status_lock;
u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
@ -692,6 +714,7 @@ struct mt76_dev {
struct mt76_wcid global_wcid;
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
struct list_head wcid_list;
u32 rev;
@ -753,6 +776,22 @@ enum mt76_phy_type {
MT_PHY_TYPE_HE_EXT_SU,
MT_PHY_TYPE_HE_TB,
MT_PHY_TYPE_HE_MU,
__MT_PHY_TYPE_HE_MAX,
};
struct mt76_sta_stats {
u64 tx_mode[__MT_PHY_TYPE_HE_MAX];
u64 tx_bw[4]; /* 20, 40, 80, 160 */
u64 tx_nss[4]; /* 1, 2, 3, 4 */
u64 tx_mcs[16]; /* mcs idx */
};
struct mt76_ethtool_worker_info {
u64 *data;
int idx;
int initial_stat_idx;
int worker_stat_count;
int sta_count;
};
#define CCK_RATE(_idx, _rate) { \
@ -769,6 +808,7 @@ enum mt76_phy_type {
}
extern struct ieee80211_rate mt76_rates[12];
extern const struct cfg80211_sar_capa mt76_sar_capa;
#define __mt76_rr(dev, ...) (dev)->bus->rr((dev), __VA_ARGS__)
#define __mt76_wr(dev, ...) (dev)->bus->wr((dev), __VA_ARGS__)
@ -869,7 +909,13 @@ struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
int mt76_register_phy(struct mt76_phy *phy, bool vht,
struct ieee80211_rate *rates, int n_rates);
struct dentry *mt76_register_debugfs(struct mt76_dev *dev);
struct dentry *mt76_register_debugfs_fops(struct mt76_phy *phy,
const struct file_operations *ops);
static inline struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
{
return mt76_register_debugfs_fops(&dev->phy, NULL);
}
int mt76_queues_read(struct seq_file *s, void *data);
void mt76_seq_puts_array(struct seq_file *file, const char *str,
s8 *val, int len);
@ -881,6 +927,7 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
struct mt76_queue *
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
int ring_base);
u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx);
static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx,
int n_desc, int ring_base)
{
@ -1077,9 +1124,9 @@ void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key);
void mt76_tx_status_lock(struct mt76_dev *dev, struct sk_buff_head *list)
__acquires(&dev->status_list.lock);
__acquires(&dev->status_lock);
void mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
__releases(&dev->status_list.lock);
__releases(&dev->status_lock);
int mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
struct sk_buff *skb);
@ -1096,8 +1143,7 @@ mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid, struct sk_buff *skb)
__mt76_tx_complete_skb(dev, wcid, skb, NULL);
}
void mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid,
bool flush);
void mt76_tx_status_check(struct mt76_dev *dev, bool flush);
int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
@ -1203,6 +1249,8 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
}
void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
struct mt76_sta_stats *stats);
int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
u8 req_type, u16 val, u16 offset,
@ -1220,8 +1268,27 @@ void mt76u_queues_deinit(struct mt76_dev *dev);
int mt76s_init(struct mt76_dev *dev, struct sdio_func *func,
const struct mt76_bus_ops *bus_ops);
int mt76s_alloc_queues(struct mt76_dev *dev);
int mt76s_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid);
int mt76s_alloc_tx(struct mt76_dev *dev);
void mt76s_deinit(struct mt76_dev *dev);
void mt76s_sdio_irq(struct sdio_func *func);
void mt76s_txrx_worker(struct mt76_sdio *sdio);
bool mt76s_txqs_empty(struct mt76_dev *dev);
int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func,
int hw_ver);
u32 mt76s_rr(struct mt76_dev *dev, u32 offset);
void mt76s_wr(struct mt76_dev *dev, u32 offset, u32 val);
u32 mt76s_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val);
u32 mt76s_read_pcr(struct mt76_dev *dev);
void mt76s_write_copy(struct mt76_dev *dev, u32 offset,
const void *data, int len);
void mt76s_read_copy(struct mt76_dev *dev, u32 offset,
void *data, int len);
int mt76s_wr_rp(struct mt76_dev *dev, u32 base,
const struct mt76_reg_pair *data,
int len);
int mt76s_rd_rp(struct mt76_dev *dev, u32 base,
struct mt76_reg_pair *data, int len);
struct sk_buff *
mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
@ -1233,8 +1300,17 @@ int mt76_mcu_send_and_get_msg(struct mt76_dev *dev, int cmd, const void *data,
int len, bool wait_resp, struct sk_buff **ret);
int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
int cmd, bool wait_resp, struct sk_buff **ret);
int mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data,
int len);
int __mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data,
int len, int max_len);
static inline int
mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data,
int len)
{
int max_len = 4096 - dev->mcu_ops->headroom;
return __mt76_mcu_send_firmware(dev, cmd, data, len, max_len);
}
static inline int
mt76_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, int len,
bool wait_resp)
@ -1293,14 +1369,22 @@ mt76_token_put(struct mt76_dev *dev, int token)
return txwi;
}
static inline int
mt76_get_next_pkt_id(struct mt76_wcid *wcid)
static inline void mt76_packet_id_init(struct mt76_wcid *wcid)
{
wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
wcid->packet_id == MT_PACKET_ID_NO_SKB)
wcid->packet_id = MT_PACKET_ID_FIRST;
return wcid->packet_id;
INIT_LIST_HEAD(&wcid->list);
idr_init(&wcid->pktid);
}
static inline void
mt76_packet_id_flush(struct mt76_dev *dev, struct mt76_wcid *wcid)
{
struct sk_buff_head list;
mt76_tx_status_lock(dev, &list);
mt76_tx_status_skb_get(dev, wcid, -1, &list);
mt76_tx_status_unlock(dev, &list);
idr_destroy(&wcid->pktid);
}
#endif

View File

@ -1458,7 +1458,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
mt76_queue_rx_reset(dev, i);
}
mt76_tx_status_check(&dev->mt76, NULL, true);
mt76_tx_status_check(&dev->mt76, true);
mt7603_dma_sched_reset(dev);
@ -1471,17 +1471,20 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
mutex_unlock(&dev->mt76.mutex);
mt76_worker_enable(&dev->mt76.tx_worker);
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
mt7603_beacon_set_timer(dev, -1, beacon_int);
local_bh_disable();
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]);
local_bh_enable();
ieee80211_wake_queues(dev->mt76.hw);
mt76_txq_schedule_all(&dev->mphy);
@ -1814,7 +1817,7 @@ void mt7603_mac_work(struct work_struct *work)
bool reset = false;
int i, idx;
mt76_tx_status_check(&dev->mt76, NULL, false);
mt76_tx_status_check(&dev->mt76, false);
mutex_lock(&dev->mt76.mutex);

View File

@ -69,6 +69,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.hw_key_idx = -1;
mt76_packet_id_init(&mvif->sta.wcid);
eth_broadcast_addr(bc_addr);
mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
@ -107,6 +108,8 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mutex_lock(&dev->mt76.mutex);
dev->mt76.vif_mask &= ~BIT(mvif->idx);
mutex_unlock(&dev->mt76.mutex);
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
}
void mt7603_init_edcca(struct mt7603_dev *dev)

View File

@ -28,7 +28,7 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;

View File

@ -17,4 +17,4 @@ mt7615e-$(CONFIG_MT7622_WMAC) += soc.o
mt7663-usb-sdio-common-y := usb_sdio.o
mt7663u-y := usb.o usb_mcu.o
mt7663s-y := sdio.o sdio_mcu.o sdio_txrx.o
mt7663s-y := sdio.o sdio_mcu.o

View File

@ -2,6 +2,33 @@
#include "mt7615.h"
static int
mt7615_reg_set(void *data, u64 val)
{
struct mt7615_dev *dev = data;
mt7615_mutex_acquire(dev);
mt76_wr(dev, dev->mt76.debugfs_reg, val);
mt7615_mutex_release(dev);
return 0;
}
static int
mt7615_reg_get(void *data, u64 *val)
{
struct mt7615_dev *dev = data;
mt7615_mutex_acquire(dev);
*val = mt76_rr(dev, dev->mt76.debugfs_reg);
mt7615_mutex_release(dev);
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7615_reg_get, mt7615_reg_set,
"0x%08llx\n");
static int
mt7615_radar_pattern_set(void *data, u64 val)
{
@ -506,7 +533,7 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
{
struct dentry *dir;
dir = mt76_register_debugfs(&dev->mt76);
dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
if (!dir)
return -ENOMEM;

View File

@ -49,12 +49,14 @@ int mt7615_thermal_init(struct mt7615_dev *dev)
{
struct wiphy *wiphy = mt76_hw(dev)->wiphy;
struct device *hwmon;
const char *name;
if (!IS_REACHABLE(CONFIG_HWMON))
return 0;
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev,
wiphy_name(wiphy), dev,
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7615_%s",
wiphy_name(wiphy));
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev,
mt7615_hwmon_groups);
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);

View File

@ -755,12 +755,15 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
txwi[3] |= cpu_to_le32(MT_TXD3_NO_ACK);
txwi[7] = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype) |
FIELD_PREP(MT_TXD7_SPE_IDX, 0x18);
if (!is_mmio)
txwi[8] = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) |
FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype);
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype) |
FIELD_PREP(MT_TXD7_SPE_IDX, 0x18);
txwi[7] = cpu_to_le32(val);
if (!is_mmio) {
val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) |
FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype);
txwi[8] = cpu_to_le32(val);
}
return 0;
}
@ -1493,31 +1496,40 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
rcu_read_unlock();
}
static void
mt7615_txwi_free(struct mt7615_dev *dev, struct mt76_txwi_cache *txwi)
{
struct mt76_dev *mdev = &dev->mt76;
__le32 *txwi_data;
u32 val;
u8 wcid;
mt7615_txp_skb_unmap(mdev, txwi);
if (!txwi->skb)
goto out;
txwi_data = (__le32 *)mt76_get_txwi_ptr(mdev, txwi);
val = le32_to_cpu(txwi_data[1]);
wcid = FIELD_GET(MT_TXD1_WLAN_IDX, val);
mt76_tx_complete_skb(mdev, wcid, txwi->skb);
out:
txwi->skb = NULL;
mt76_put_txwi(mdev, txwi);
}
static void
mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token)
{
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;
__le32 *txwi_data;
u32 val;
u8 wcid;
trace_mac_tx_free(dev, token);
txwi = mt76_token_put(mdev, token);
if (!txwi)
return;
txwi_data = (__le32 *)mt76_get_txwi_ptr(mdev, txwi);
val = le32_to_cpu(txwi_data[1]);
wcid = FIELD_GET(MT_TXD1_WLAN_IDX, val);
mt7615_txp_skb_unmap(mdev, txwi);
if (txwi->skb) {
mt76_tx_complete_skb(mdev, wcid, txwi->skb);
txwi->skb = NULL;
}
mt76_put_txwi(mdev, txwi);
mt7615_txwi_free(dev, txwi);
}
static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb)
@ -2014,7 +2026,7 @@ void mt7615_mac_work(struct work_struct *work)
mt7615_mutex_release(phy->dev);
mt76_tx_status_check(mphy->dev, NULL, false);
mt76_tx_status_check(mphy->dev, false);
timeout = mt7615_get_macwork_timeout(phy->dev);
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, timeout);
@ -2026,16 +2038,8 @@ void mt7615_tx_token_put(struct mt7615_dev *dev)
int id;
spin_lock_bh(&dev->mt76.token_lock);
idr_for_each_entry(&dev->mt76.token, txwi, id) {
mt7615_txp_skb_unmap(&dev->mt76, txwi);
if (txwi->skb) {
struct ieee80211_hw *hw;
hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb);
ieee80211_free_txskb(hw, txwi->skb);
}
mt76_put_txwi(&dev->mt76, txwi);
}
idr_for_each_entry(&dev->mt76.token, txwi, id)
mt7615_txwi_free(dev, txwi);
spin_unlock_bh(&dev->mt76.token_lock);
idr_destroy(&dev->mt76.token);
}

View File

@ -231,6 +231,8 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
mvif->sta.wcid.hw_key_idx = -1;
mt76_packet_id_init(&mvif->sta.wcid);
mt7615_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@ -281,6 +283,8 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
}
static void mt7615_init_dfs_state(struct mt7615_phy *phy)
@ -567,8 +571,8 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
mt7615_mcu_add_bss_info(phy, vif, NULL, true);
mt7615_mcu_sta_add(phy, vif, NULL, true);
if (vif->p2p)
mt7615_mcu_set_p2p_oppps(hw, vif);
if (mt7615_firmware_offload(dev) && vif->p2p)
mt76_connac_mcu_set_p2p_oppps(hw, vif);
}
if (changed & (BSS_CHANGED_BEACON |
@ -858,8 +862,6 @@ mt7615_get_stats(struct ieee80211_hw *hw,
stats->dot11FCSErrorCount = mib->fcs_err_cnt;
stats->dot11ACKFailureCount = mib->ack_fail_cnt;
memset(mib, 0, sizeof(*mib));
mt7615_mutex_release(phy->dev);
return 0;

View File

@ -808,7 +808,8 @@ mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)
static int
mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enable)
struct ieee80211_sta *sta, struct mt7615_phy *phy,
bool enable)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
u32 type = vif->p2p ? NETWORK_P2P : NETWORK_INFRA;
@ -821,6 +822,7 @@ mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
switch (vif->type) {
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MONITOR:
break;
case NL80211_IFTYPE_STATION:
/* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */
@ -840,14 +842,19 @@ mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
}
bss = (struct bss_info_basic *)tlv;
memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN);
bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
bss->network_type = cpu_to_le32(type);
bss->dtim_period = vif->bss_conf.dtim_period;
bss->bmc_tx_wlan_idx = wlan_idx;
bss->wmm_idx = mvif->mt76.wmm_idx;
bss->active = enable;
if (vif->type != NL80211_IFTYPE_MONITOR) {
memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN);
bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
bss->dtim_period = vif->bss_conf.dtim_period;
} else {
memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN);
}
return 0;
}
@ -863,6 +870,7 @@ mt7615_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac));
switch (vif->type) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
if (vif->p2p)
@ -929,7 +937,7 @@ mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,
if (enable)
mt7615_mcu_bss_omac_tlv(skb, vif);
mt7615_mcu_bss_basic_tlv(skb, vif, sta, enable);
mt7615_mcu_bss_basic_tlv(skb, vif, sta, phy, enable);
if (enable && mvif->mt76.omac_idx >= EXT_BSSID_START &&
mvif->mt76.omac_idx < REPEATER_BSSID_START)
@ -2761,53 +2769,3 @@ int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req,
sizeof(req), false);
}
int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
int ct_window = vif->bss_conf.p2p_noa_attr.oppps_ctwindow;
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct {
__le32 ct_win;
u8 bss_idx;
u8 rsv[3];
} __packed req = {
.ct_win = cpu_to_le32(ct_window),
.bss_idx = mvif->mt76.idx,
};
if (!mt7615_firmware_offload(dev))
return -ENOTSUPP;
return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_P2P_OPPPS, &req,
sizeof(req), false);
}
u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset)
{
struct {
__le32 addr;
__le32 val;
} __packed req = {
.addr = cpu_to_le32(offset),
};
return mt76_mcu_send_msg(dev, MCU_CMD_REG_READ, &req, sizeof(req),
true);
}
EXPORT_SYMBOL_GPL(mt7615_mcu_reg_rr);
void mt7615_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val)
{
struct {
__le32 addr;
__le32 val;
} __packed req = {
.addr = cpu_to_le32(offset),
.val = cpu_to_le32(val),
};
mt76_mcu_send_msg(dev, MCU_CMD_REG_WRITE, &req, sizeof(req), false);
}
EXPORT_SYMBOL_GPL(mt7615_mcu_reg_wr);

View File

@ -107,6 +107,18 @@ struct mt7615_wtbl_rate_desc {
struct mt7615_sta *sta;
};
struct mt7663s_intr {
u32 isr;
struct {
u32 wtqcr[8];
} tx;
struct {
u16 num[2];
u16 len[2][16];
} rx;
u32 rec_mb[2];
} __packed;
struct mt7615_sta {
struct mt76_wcid wcid; /* must be first */
@ -541,8 +553,6 @@ int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy);
int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy);
int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy);
int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_channel *chan, int duration);
@ -555,8 +565,6 @@ int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy,
int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,
bool enable);
int __mt7663_load_firmware(struct mt7615_dev *dev);
u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset);
void mt7615_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
void mt7615_coredump_work(struct work_struct *work);
void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en);
@ -573,10 +581,6 @@ int mt7663_usb_sdio_register_device(struct mt7615_dev *dev);
int mt7663u_mcu_init(struct mt7615_dev *dev);
/* sdio */
u32 mt7663s_read_pcr(struct mt7615_dev *dev);
int mt7663s_mcu_init(struct mt7615_dev *dev);
void mt7663s_txrx_worker(struct mt76_worker *w);
void mt7663s_rx_work(struct work_struct *work);
void mt7663s_sdio_irq(struct sdio_func *func);
#endif

View File

@ -39,7 +39,7 @@ static int mt7615_pci_probe(struct pci_dev *pdev,
if (ret < 0)
return ret;
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
goto error;
@ -164,12 +164,14 @@ static int mt7615_pci_resume(struct pci_dev *pdev)
dev_err(mdev->dev, "PDMA engine must be reinitialized\n");
mt76_worker_enable(&mdev->tx_worker);
local_bh_disable();
mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
local_bh_enable();
if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&
mt7615_firmware_offload(dev))

View File

@ -198,7 +198,7 @@ void mt7615_dma_reset(struct mt7615_dev *dev)
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_rx_reset(dev, i);
mt76_tx_status_check(&dev->mt76, NULL, true);
mt76_tx_status_check(&dev->mt76, true);
mt7615_dma_start(dev);
}
@ -326,6 +326,8 @@ void mt7615_mac_reset_work(struct work_struct *work)
clear_bit(MT76_RESET, &phy2->mt76->state);
mt76_worker_enable(&dev->mt76.tx_worker);
local_bh_disable();
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
@ -334,6 +336,7 @@ void mt7615_mac_reset_work(struct work_struct *work)
napi_enable(&dev->mt76.napi[1]);
napi_schedule(&dev->mt76.napi[1]);
local_bh_enable();
ieee80211_wake_queues(mt76_hw(dev));
if (ext_phy)

View File

@ -14,8 +14,8 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
#include "../sdio.h"
#include "mt7615.h"
#include "sdio.h"
#include "mac.h"
#include "mcu.h"
@ -24,200 +24,19 @@ static const struct sdio_device_id mt7663s_table[] = {
{ } /* Terminating entry */
};
static u32 mt7663s_read_whisr(struct mt76_dev *dev)
static void mt7663s_txrx_worker(struct mt76_worker *w)
{
return sdio_readl(dev->sdio.func, MCR_WHISR, NULL);
}
struct mt76_sdio *sdio = container_of(w, struct mt76_sdio,
txrx_worker);
struct mt76_dev *mdev = container_of(sdio, struct mt76_dev, sdio);
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
u32 mt7663s_read_pcr(struct mt7615_dev *dev)
{
struct mt76_sdio *sdio = &dev->mt76.sdio;
return sdio_readl(sdio->func, MCR_WHLPCR, NULL);
}
static u32 mt7663s_read_mailbox(struct mt76_dev *dev, u32 offset)
{
struct sdio_func *func = dev->sdio.func;
u32 val = ~0, status;
int err;
sdio_claim_host(func);
sdio_writel(func, offset, MCR_H2DSM0R, &err);
if (err < 0) {
dev_err(dev->dev, "failed setting address [err=%d]\n", err);
goto out;
if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
queue_work(mdev->wq, &dev->pm.wake_work);
return;
}
sdio_writel(func, H2D_SW_INT_READ, MCR_WSICR, &err);
if (err < 0) {
dev_err(dev->dev, "failed setting read mode [err=%d]\n", err);
goto out;
}
err = readx_poll_timeout(mt7663s_read_whisr, dev, status,
status & H2D_SW_INT_READ, 0, 1000000);
if (err < 0) {
dev_err(dev->dev, "query whisr timeout\n");
goto out;
}
sdio_writel(func, H2D_SW_INT_READ, MCR_WHISR, &err);
if (err < 0) {
dev_err(dev->dev, "failed setting read mode [err=%d]\n", err);
goto out;
}
val = sdio_readl(func, MCR_H2DSM0R, &err);
if (err < 0) {
dev_err(dev->dev, "failed reading h2dsm0r [err=%d]\n", err);
goto out;
}
if (val != offset) {
dev_err(dev->dev, "register mismatch\n");
val = ~0;
goto out;
}
val = sdio_readl(func, MCR_D2HRM1R, &err);
if (err < 0)
dev_err(dev->dev, "failed reading d2hrm1r [err=%d]\n", err);
out:
sdio_release_host(func);
return val;
}
static void mt7663s_write_mailbox(struct mt76_dev *dev, u32 offset, u32 val)
{
struct sdio_func *func = dev->sdio.func;
u32 status;
int err;
sdio_claim_host(func);
sdio_writel(func, offset, MCR_H2DSM0R, &err);
if (err < 0) {
dev_err(dev->dev, "failed setting address [err=%d]\n", err);
goto out;
}
sdio_writel(func, val, MCR_H2DSM1R, &err);
if (err < 0) {
dev_err(dev->dev,
"failed setting write value [err=%d]\n", err);
goto out;
}
sdio_writel(func, H2D_SW_INT_WRITE, MCR_WSICR, &err);
if (err < 0) {
dev_err(dev->dev, "failed setting write mode [err=%d]\n", err);
goto out;
}
err = readx_poll_timeout(mt7663s_read_whisr, dev, status,
status & H2D_SW_INT_WRITE, 0, 1000000);
if (err < 0) {
dev_err(dev->dev, "query whisr timeout\n");
goto out;
}
sdio_writel(func, H2D_SW_INT_WRITE, MCR_WHISR, &err);
if (err < 0) {
dev_err(dev->dev, "failed setting write mode [err=%d]\n", err);
goto out;
}
val = sdio_readl(func, MCR_H2DSM0R, &err);
if (err < 0) {
dev_err(dev->dev, "failed reading h2dsm0r [err=%d]\n", err);
goto out;
}
if (val != offset)
dev_err(dev->dev, "register mismatch\n");
out:
sdio_release_host(func);
}
static u32 mt7663s_rr(struct mt76_dev *dev, u32 offset)
{
if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state))
return dev->mcu_ops->mcu_rr(dev, offset);
else
return mt7663s_read_mailbox(dev, offset);
}
static void mt7663s_wr(struct mt76_dev *dev, u32 offset, u32 val)
{
if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state))
dev->mcu_ops->mcu_wr(dev, offset, val);
else
mt7663s_write_mailbox(dev, offset, val);
}
static u32 mt7663s_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val)
{
val |= mt7663s_rr(dev, offset) & ~mask;
mt7663s_wr(dev, offset, val);
return val;
}
static void mt7663s_write_copy(struct mt76_dev *dev, u32 offset,
const void *data, int len)
{
const u32 *val = data;
int i;
for (i = 0; i < len / sizeof(u32); i++) {
mt7663s_wr(dev, offset, val[i]);
offset += sizeof(u32);
}
}
static void mt7663s_read_copy(struct mt76_dev *dev, u32 offset,
void *data, int len)
{
u32 *val = data;
int i;
for (i = 0; i < len / sizeof(u32); i++) {
val[i] = mt7663s_rr(dev, offset);
offset += sizeof(u32);
}
}
static int mt7663s_wr_rp(struct mt76_dev *dev, u32 base,
const struct mt76_reg_pair *data,
int len)
{
int i;
for (i = 0; i < len; i++) {
mt7663s_wr(dev, data->reg, data->value);
data++;
}
return 0;
}
static int mt7663s_rd_rp(struct mt76_dev *dev, u32 base,
struct mt76_reg_pair *data,
int len)
{
int i;
for (i = 0; i < len; i++) {
data->value = mt7663s_rr(dev, data->reg);
data++;
}
return 0;
mt76s_txrx_worker(sdio);
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
}
static void mt7663s_init_work(struct work_struct *work)
@ -231,64 +50,24 @@ static void mt7663s_init_work(struct work_struct *work)
mt7615_init_work(dev);
}
static int mt7663s_hw_init(struct mt7615_dev *dev, struct sdio_func *func)
static int mt7663s_parse_intr(struct mt76_dev *dev, struct mt76s_intr *intr)
{
u32 status, ctrl;
int ret;
struct mt76_sdio *sdio = &dev->sdio;
struct mt7663s_intr *irq_data = sdio->intr_data;
int i, err;
sdio_claim_host(func);
err = sdio_readsb(sdio->func, irq_data, MCR_WHISR, sizeof(*irq_data));
if (err)
return err;
ret = sdio_enable_func(func);
if (ret < 0)
goto release;
/* Get ownership from the device */
sdio_writel(func, WHLPCR_INT_EN_CLR | WHLPCR_FW_OWN_REQ_CLR,
MCR_WHLPCR, &ret);
if (ret < 0)
goto disable_func;
ret = readx_poll_timeout(mt7663s_read_pcr, dev, status,
status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
if (ret < 0) {
dev_err(dev->mt76.dev, "Cannot get ownership from device");
goto disable_func;
}
ret = sdio_set_block_size(func, 512);
if (ret < 0)
goto disable_func;
/* Enable interrupt */
sdio_writel(func, WHLPCR_INT_EN_SET, MCR_WHLPCR, &ret);
if (ret < 0)
goto disable_func;
ctrl = WHIER_RX0_DONE_INT_EN | WHIER_TX_DONE_INT_EN;
sdio_writel(func, ctrl, MCR_WHIER, &ret);
if (ret < 0)
goto disable_func;
/* set WHISR as read clear and Rx aggregation number as 16 */
ctrl = FIELD_PREP(MAX_HIF_RX_LEN_NUM, 16);
sdio_writel(func, ctrl, MCR_WHCR, &ret);
if (ret < 0)
goto disable_func;
ret = sdio_claim_irq(func, mt7663s_sdio_irq);
if (ret < 0)
goto disable_func;
sdio_release_host(func);
intr->isr = irq_data->isr;
intr->rec_mb = irq_data->rec_mb;
intr->tx.wtqcr = irq_data->tx.wtqcr;
intr->rx.num = irq_data->rx.num;
for (i = 0; i < 2 ; i++)
intr->rx.len[i] = irq_data->rx.len[i];
return 0;
disable_func:
sdio_disable_func(func);
release:
sdio_release_host(func);
return ret;
}
static int mt7663s_probe(struct sdio_func *func,
@ -307,13 +86,13 @@ static int mt7663s_probe(struct sdio_func *func,
.update_survey = mt7615_update_channel,
};
static const struct mt76_bus_ops mt7663s_ops = {
.rr = mt7663s_rr,
.rmw = mt7663s_rmw,
.wr = mt7663s_wr,
.write_copy = mt7663s_write_copy,
.read_copy = mt7663s_read_copy,
.wr_rp = mt7663s_wr_rp,
.rd_rp = mt7663s_rd_rp,
.rr = mt76s_rr,
.rmw = mt76s_rmw,
.wr = mt76s_wr,
.write_copy = mt76s_write_copy,
.read_copy = mt76s_read_copy,
.wr_rp = mt76s_wr_rp,
.rd_rp = mt76s_rd_rp,
.type = MT76_BUS_SDIO,
};
struct ieee80211_ops *ops;
@ -341,7 +120,7 @@ static int mt7663s_probe(struct sdio_func *func,
if (ret < 0)
goto error;
ret = mt7663s_hw_init(dev, func);
ret = mt76s_hw_init(mdev, func, MT76_CONNAC_SDIO);
if (ret)
goto error;
@ -349,8 +128,9 @@ static int mt7663s_probe(struct sdio_func *func,
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
mdev->sdio.parse_irq = mt7663s_parse_intr;
mdev->sdio.intr_data = devm_kmalloc(mdev->dev,
sizeof(struct mt76s_intr),
sizeof(struct mt7663s_intr),
GFP_KERNEL);
if (!mdev->sdio.intr_data) {
ret = -ENOMEM;
@ -367,7 +147,11 @@ static int mt7663s_probe(struct sdio_func *func,
}
}
ret = mt76s_alloc_queues(&dev->mt76);
ret = mt76s_alloc_rx_queue(mdev, MT_RXQ_MAIN);
if (ret)
goto error;
ret = mt76s_alloc_tx(mdev);
if (ret)
goto error;
@ -432,7 +216,7 @@ static int mt7663s_suspend(struct device *dev)
cancel_work_sync(&mdev->mt76.sdio.stat_work);
clear_bit(MT76_READING_STATS, &mdev->mphy.state);
mt76_tx_status_check(&mdev->mt76, NULL, true);
mt76_tx_status_check(&mdev->mt76, true);
return 0;
}

View File

@ -10,11 +10,11 @@
#include <linux/module.h>
#include <linux/iopoll.h>
#include "../sdio.h"
#include "mt7615.h"
#include "mac.h"
#include "mcu.h"
#include "regs.h"
#include "sdio.h"
static int mt7663s_mcu_init_sched(struct mt7615_dev *dev)
{
@ -27,6 +27,7 @@ static int mt7663s_mcu_init_sched(struct mt7615_dev *dev)
MT_HIF1_MIN_QUOTA);
sdio->sched.ple_data_quota = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP,
MT_HIF0_MIN_QUOTA);
sdio->sched.pse_page_size = MT_PSE_PAGE_SZ;
txdwcnt = mt76_get_field(dev, MT_PP_TXDWCNT,
MT_PP_TXDWCNT_TX1_ADD_DW_CNT);
sdio->sched.deficit = txdwcnt << 2;
@ -63,7 +64,7 @@ static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
sdio_writel(func, WHLPCR_FW_OWN_REQ_CLR, MCR_WHLPCR, NULL);
ret = readx_poll_timeout(mt7663s_read_pcr, dev, status,
ret = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
if (ret < 0) {
dev_err(dev->mt76.dev, "Cannot get ownership from device");
@ -111,7 +112,7 @@ static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)
sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, NULL);
ret = readx_poll_timeout(mt7663s_read_pcr, dev, status,
ret = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
!(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000);
if (ret < 0) {
dev_err(dev->mt76.dev, "Cannot set ownership to device");
@ -137,8 +138,8 @@ int mt7663s_mcu_init(struct mt7615_dev *dev)
.mcu_skb_send_msg = mt7663s_mcu_send_message,
.mcu_parse_response = mt7615_mcu_parse_response,
.mcu_restart = mt7615_mcu_restart,
.mcu_rr = mt7615_mcu_reg_rr,
.mcu_wr = mt7615_mcu_reg_wr,
.mcu_rr = mt76_connac_mcu_reg_rr,
.mcu_wr = mt76_connac_mcu_reg_wr,
};
struct mt7615_mcu_ops *mcu_ops;
int ret;

View File

@ -169,7 +169,7 @@ bool mt7663_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)
mt7615_mac_sta_poll(dev);
mt7615_mutex_release(dev);
return 0;
return false;
}
EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_status_data);

View File

@ -85,9 +85,14 @@ struct mt76_connac_coredump {
extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
static inline bool is_mt7922(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7922;
}
static inline bool is_mt7921(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7961;
return mt76_chip(dev) == 0x7961 || is_mt7922(dev);
}
static inline bool is_mt7663(struct mt76_dev *dev)

View File

@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_init_download);
int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy)
{
struct mt76_dev *dev = phy->dev;
int len, i, n_max_channels, n_2ch = 0, n_5ch = 0, n_6ch = 0;
struct mt76_connac_mcu_channel_domain {
u8 alpha2[4]; /* regulatory_request.alpha2 */
u8 bw_2g; /* BW_20_40M 0
@ -84,25 +84,29 @@ int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy)
* BW_20_40_80_8080M 4
*/
u8 bw_5g;
__le16 pad;
u8 bw_6g;
u8 pad;
u8 n_2ch;
u8 n_5ch;
__le16 pad2;
u8 n_6ch;
u8 pad2;
} __packed hdr = {
.bw_2g = 0,
.bw_5g = 3,
.bw_5g = 3, /* BW_20_40_80_160M */
.bw_6g = 3,
};
struct mt76_connac_mcu_chan {
__le16 hw_value;
__le16 pad;
__le32 flags;
} __packed channel;
int len, i, n_max_channels, n_2ch = 0, n_5ch = 0;
struct mt76_dev *dev = phy->dev;
struct ieee80211_channel *chan;
struct sk_buff *skb;
n_max_channels = phy->sband_2g.sband.n_channels +
phy->sband_5g.sband.n_channels;
phy->sband_5g.sband.n_channels +
phy->sband_6g.sband.n_channels;
len = sizeof(hdr) + n_max_channels * sizeof(channel);
skb = mt76_mcu_msg_alloc(dev, NULL, len);
@ -135,11 +139,24 @@ int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy)
skb_put_data(skb, &channel, sizeof(channel));
n_5ch++;
}
for (i = 0; i < phy->sband_6g.sband.n_channels; i++) {
chan = &phy->sband_6g.sband.channels[i];
if (chan->flags & IEEE80211_CHAN_DISABLED)
continue;
channel.hw_value = cpu_to_le16(chan->hw_value);
channel.flags = cpu_to_le32(chan->flags);
channel.pad = 0;
skb_put_data(skb, &channel, sizeof(channel));
n_6ch++;
}
BUILD_BUG_ON(sizeof(dev->alpha2) > sizeof(hdr.alpha2));
memcpy(hdr.alpha2, dev->alpha2, sizeof(dev->alpha2));
hdr.n_2ch = n_2ch;
hdr.n_5ch = n_5ch;
hdr.n_6ch = n_6ch;
memcpy(__skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
@ -689,9 +706,9 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
if (ht_cap->ht_supported)
mode |= PHY_TYPE_BIT_HT;
if (he_cap->has_he)
if (he_cap && he_cap->has_he)
mode |= PHY_TYPE_BIT_HE;
} else if (band == NL80211_BAND_5GHZ) {
} else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
mode |= PHY_TYPE_BIT_OFDM;
if (ht_cap->ht_supported)
@ -700,7 +717,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
if (vht_cap->vht_supported)
mode |= PHY_TYPE_BIT_VHT;
if (he_cap->has_he)
if (he_cap && he_cap->has_he)
mode |= PHY_TYPE_BIT_HE;
}
@ -719,6 +736,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
struct sta_rec_state *state;
struct sta_rec_phy *phy;
struct tlv *tlv;
u16 supp_rates;
/* starec ht */
if (sta->ht_cap.ht_supported) {
@ -748,12 +766,22 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
if (!is_mt7921(dev))
return;
if (sta->ht_cap.ht_supported)
if (sta->ht_cap.ht_supported || sta->he_cap.has_he)
mt76_connac_mcu_sta_amsdu_tlv(skb, sta, vif);
/* starec he */
if (sta->he_cap.has_he)
if (sta->he_cap.has_he) {
mt76_connac_mcu_sta_he_tlv(skb, sta);
if (band == NL80211_BAND_6GHZ &&
sta_state == MT76_STA_INFO_STATE_ASSOC) {
struct sta_rec_he_6g_capa *he_6g_capa;
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_6G,
sizeof(*he_6g_capa));
he_6g_capa = (struct sta_rec_he_6g_capa *)tlv;
he_6g_capa->capa = sta->he_6ghz_capa.capa;
}
}
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PHY, sizeof(*phy));
phy = (struct sta_rec_phy *)tlv;
@ -767,7 +795,15 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info));
ra_info = (struct sta_rec_ra_info *)tlv;
ra_info->legacy = cpu_to_le16((u16)sta->supp_rates[band]);
supp_rates = sta->supp_rates[band];
if (band == NL80211_BAND_2GHZ)
supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates >> 4) |
FIELD_PREP(RA_LEGACY_CCK, supp_rates & 0xf);
else
supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates);
ra_info->legacy = cpu_to_le16(supp_rates);
if (sta->ht_cap.ht_supported)
memcpy(ra_info->rx_mcs_bitmask, sta->ht_cap.mcs.rx_mask,
@ -1145,7 +1181,7 @@ mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif,
if (he_cap->has_he)
mode |= PHY_MODE_AX_24G;
} else if (band == NL80211_BAND_5GHZ) {
} else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
mode |= PHY_MODE_A;
if (ht_cap->ht_supported)
@ -1154,8 +1190,12 @@ mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif,
if (vht_cap->vht_supported)
mode |= PHY_MODE_AC;
if (he_cap->has_he)
mode |= PHY_MODE_AX_5G;
if (he_cap->has_he) {
if (band == NL80211_BAND_6GHZ)
mode |= PHY_MODE_AX_6G;
else
mode |= PHY_MODE_AX_5G;
}
}
return mode;
@ -1252,7 +1292,8 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
u8 short_st;
u8 ht_op_info;
u8 sco;
u8 pad[3];
u8 band;
u8 pad[2];
} __packed rlm;
} __packed rlm_req = {
.hdr = {
@ -1268,13 +1309,19 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
.ht_op_info = 4, /* set HT 40M allowed */
.rx_streams = phy->chainmask,
.short_st = true,
.band = band,
},
};
int err, conn_type;
u8 idx;
u8 idx, basic_phy;
idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx;
basic_req.basic.hw_bss_idx = idx;
if (band == NL80211_BAND_6GHZ)
basic_req.basic.phymode_ext = BIT(0);
basic_phy = mt76_connac_get_phy_mode_v2(phy, vif, band, NULL);
basic_req.basic.nonht_basic_phy = cpu_to_le16(basic_phy);
switch (vif->type) {
case NL80211_IFTYPE_MESH_POINT:
@ -1445,7 +1492,17 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
else
chan = &req->channels[i];
chan->band = scan_list[i]->band == NL80211_BAND_2GHZ ? 1 : 2;
switch (scan_list[i]->band) {
case NL80211_BAND_2GHZ:
chan->band = 1;
break;
case NL80211_BAND_6GHZ:
chan->band = 3;
break;
default:
chan->band = 2;
break;
}
chan->channel_num = scan_list[i]->hw_value;
}
req->channel_type = sreq->n_channels ? 4 : 0;
@ -1531,8 +1588,10 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
get_random_mask_addr(addr, sreq->mac_addr,
sreq->mac_addr_mask);
}
if (is_mt7921(phy->dev))
if (is_mt7921(phy->dev)) {
req->mt7921.bss_idx = mvif->idx;
req->mt7921.delay = cpu_to_le32(sreq->delay);
}
req->ssids_num = sreq->n_ssids;
for (i = 0; i < req->ssids_num; i++) {
@ -1554,7 +1613,18 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
req->channels_num = min_t(u8, sreq->n_channels, 64);
for (i = 0; i < req->channels_num; i++) {
chan = &req->channels[i];
chan->band = scan_list[i]->band == NL80211_BAND_2GHZ ? 1 : 2;
switch (scan_list[i]->band) {
case NL80211_BAND_2GHZ:
chan->band = 1;
break;
case NL80211_BAND_6GHZ:
chan->band = 3;
break;
default:
chan->band = 2;
break;
}
chan->channel_num = scan_list[i]->hw_value;
}
@ -1652,6 +1722,61 @@ void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_coredump_event);
static void mt76_connac_mcu_parse_tx_resource(struct mt76_dev *dev,
struct sk_buff *skb)
{
struct mt76_sdio *sdio = &dev->sdio;
struct mt76_connac_tx_resource {
__le32 version;
__le32 pse_data_quota;
__le32 pse_mcu_quota;
__le32 ple_data_quota;
__le32 ple_mcu_quota;
__le16 pse_page_size;
__le16 ple_page_size;
u8 pp_padding;
u8 pad[3];
} __packed * tx_res;
tx_res = (struct mt76_connac_tx_resource *)skb->data;
sdio->sched.pse_data_quota = le32_to_cpu(tx_res->pse_data_quota);
sdio->sched.pse_mcu_quota = le32_to_cpu(tx_res->pse_mcu_quota);
sdio->sched.ple_data_quota = le32_to_cpu(tx_res->ple_data_quota);
sdio->sched.pse_page_size = le16_to_cpu(tx_res->pse_page_size);
sdio->sched.deficit = tx_res->pp_padding;
}
static void mt76_connac_mcu_parse_phy_cap(struct mt76_dev *dev,
struct sk_buff *skb)
{
struct mt76_connac_phy_cap {
u8 ht;
u8 vht;
u8 _5g;
u8 max_bw;
u8 nss;
u8 dbdc;
u8 tx_ldpc;
u8 rx_ldpc;
u8 tx_stbc;
u8 rx_stbc;
u8 hw_path;
u8 he;
} __packed * cap;
enum {
WF0_24G,
WF0_5G
};
cap = (struct mt76_connac_phy_cap *)skb->data;
dev->phy.antenna_mask = BIT(cap->nss) - 1;
dev->phy.chainmask = dev->phy.antenna_mask;
dev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);
dev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);
}
int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy)
{
struct mt76_connac_cap_hdr {
@ -1694,6 +1819,17 @@ int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy)
case MT_NIC_CAP_6G:
phy->cap.has_6ghz = skb->data[0];
break;
case MT_NIC_CAP_MAC_ADDR:
memcpy(phy->macaddr, (void *)skb->data, ETH_ALEN);
break;
case MT_NIC_CAP_PHY:
mt76_connac_mcu_parse_phy_cap(phy->dev, skb);
break;
case MT_NIC_CAP_TX_RESOURCE:
if (mt76_is_sdio(phy->dev))
mt76_connac_mcu_parse_tx_resource(phy->dev,
skb);
break;
default:
break;
}
@ -1749,6 +1885,70 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
}
}
static s8 mt76_connac_get_sar_power(struct mt76_phy *phy,
struct ieee80211_channel *chan,
s8 target_power)
{
const struct cfg80211_sar_capa *capa = phy->hw->wiphy->sar_capa;
struct mt76_freq_range_power *frp = phy->frp;
int freq, i;
if (!capa || !frp)
return target_power;
freq = ieee80211_channel_to_frequency(chan->hw_value, chan->band);
for (i = 0 ; i < capa->num_freq_ranges; i++) {
if (frp[i].range &&
freq >= frp[i].range->start_freq &&
freq < frp[i].range->end_freq) {
target_power = min_t(s8, frp[i].power, target_power);
break;
}
}
return target_power;
}
static s8 mt76_connac_get_ch_power(struct mt76_phy *phy,
struct ieee80211_channel *chan,
s8 target_power)
{
struct mt76_dev *dev = phy->dev;
struct ieee80211_supported_band *sband;
int i;
switch (chan->band) {
case NL80211_BAND_2GHZ:
sband = &phy->sband_2g.sband;
break;
case NL80211_BAND_5GHZ:
sband = &phy->sband_5g.sband;
break;
case NL80211_BAND_6GHZ:
sband = &phy->sband_6g.sband;
break;
default:
return target_power;
}
for (i = 0; i < sband->n_channels; i++) {
struct ieee80211_channel *ch = &sband->channels[i];
if (ch->hw_value == chan->hw_value) {
if (!(ch->flags & IEEE80211_CHAN_DISABLED)) {
int power = 2 * ch->max_reg_power;
if (is_mt7663(dev) && (power > 63 || power < -64))
power = 63;
target_power = min_t(s8, power, target_power);
}
break;
}
}
return target_power;
}
static int
mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
enum nl80211_band band)
@ -1768,6 +1968,24 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
142, 144, 149, 151, 153, 155, 157,
159, 161, 165
};
static const u8 chan_list_6ghz[] = {
1, 3, 5, 7, 9, 11, 13,
15, 17, 19, 21, 23, 25, 27,
29, 33, 35, 37, 39, 41, 43,
45, 47, 49, 51, 53, 55, 57,
59, 61, 65, 67, 69, 71, 73,
75, 77, 79, 81, 83, 85, 87,
89, 91, 93, 97, 99, 101, 103,
105, 107, 109, 111, 113, 115, 117,
119, 121, 123, 125, 129, 131, 133,
135, 137, 139, 141, 143, 145, 147,
149, 151, 153, 155, 157, 161, 163,
165, 167, 169, 171, 173, 175, 177,
179, 181, 183, 185, 187, 189, 193,
195, 197, 199, 201, 203, 205, 207,
209, 211, 213, 215, 217, 219, 221,
225, 227, 229, 233
};
int i, n_chan, batch_size, idx = 0, tx_power, last_ch;
struct mt76_connac_sku_tlv sku_tlbv;
struct mt76_power_limits limits;
@ -1781,6 +1999,9 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
if (band == NL80211_BAND_2GHZ) {
n_chan = ARRAY_SIZE(chan_list_2ghz);
ch_list = chan_list_2ghz;
} else if (band == NL80211_BAND_6GHZ) {
n_chan = ARRAY_SIZE(chan_list_6ghz);
ch_list = chan_list_6ghz;
} else {
n_chan = ARRAY_SIZE(chan_list_5ghz);
ch_list = chan_list_5ghz;
@ -1789,13 +2010,13 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
if (!phy->cap.has_5ghz)
last_ch = chan_list_2ghz[n_chan - 1];
else if (phy->cap.has_6ghz)
last_ch = chan_list_6ghz[n_chan - 1];
else
last_ch = chan_list_5ghz[n_chan - 1];
for (i = 0; i < batch_size; i++) {
struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {
.band = band == NL80211_BAND_2GHZ ? 1 : 2,
};
struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {};
int j, err, msg_len, num_ch;
struct sk_buff *skb;
@ -1811,14 +2032,32 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
memcpy(tx_power_tlv.alpha2, dev->alpha2, sizeof(dev->alpha2));
tx_power_tlv.n_chan = num_ch;
switch (band) {
case NL80211_BAND_2GHZ:
tx_power_tlv.band = 1;
break;
case NL80211_BAND_6GHZ:
tx_power_tlv.band = 3;
break;
default:
tx_power_tlv.band = 2;
break;
}
for (j = 0; j < num_ch; j++, idx++) {
struct ieee80211_channel chan = {
.hw_value = ch_list[idx],
.band = band,
};
s8 reg_power, sar_power;
reg_power = mt76_connac_get_ch_power(phy, &chan,
tx_power);
sar_power = mt76_connac_get_sar_power(phy, &chan,
reg_power);
mt76_get_rate_power_limits(phy, &chan, &limits,
tx_power);
sar_power);
tx_power_tlv.last_msg = ch_list[idx] == last_ch;
sku_tlbv.channel = ch_list[idx];
@ -1855,6 +2094,12 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
if (err < 0)
return err;
}
if (phy->cap.has_6ghz) {
err = mt76_connac_mcu_rate_txpower_band(phy,
NL80211_BAND_6GHZ);
if (err < 0)
return err;
}
return 0;
}
@ -1902,6 +2147,26 @@ int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev,
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_update_arp_filter);
int mt76_connac_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
int ct_window = vif->bss_conf.p2p_noa_attr.oppps_ctwindow;
struct mt76_phy *phy = hw->priv;
struct {
__le32 ct_win;
u8 bss_idx;
u8 rsv[3];
} __packed req = {
.ct_win = cpu_to_le32(ct_window),
.bss_idx = mvif->idx,
};
return mt76_mcu_send_msg(phy->dev, MCU_CMD_SET_P2P_OPPPS, &req,
sizeof(req), false);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_p2p_oppps);
#ifdef CONFIG_PM
const struct wiphy_wowlan_support mt76_connac_wowlan_support = {
@ -1929,19 +2194,22 @@ mt76_connac_mcu_key_iter(struct ieee80211_hw *hw,
key->cipher != WLAN_CIPHER_SUITE_TKIP)
return;
if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_1);
if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
cipher = BIT(3);
} else {
gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_2);
else
cipher = BIT(4);
}
/* we are assuming here to have a single pairwise key */
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_1);
else
gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_2);
gtk_tlv->pairwise_cipher = cpu_to_le32(cipher);
gtk_tlv->group_cipher = cpu_to_le32(cipher);
gtk_tlv->keyid = key->keyidx;
} else {
gtk_tlv->group_cipher = cpu_to_le32(cipher);
}
}
@ -2210,6 +2478,33 @@ void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_suspend_iter);
u32 mt76_connac_mcu_reg_rr(struct mt76_dev *dev, u32 offset)
{
struct {
__le32 addr;
__le32 val;
} __packed req = {
.addr = cpu_to_le32(offset),
};
return mt76_mcu_send_msg(dev, MCU_CMD_REG_READ, &req, sizeof(req),
true);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_reg_rr);
void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val)
{
struct {
__le32 addr;
__le32 val;
} __packed req = {
.addr = cpu_to_le32(offset),
.val = cpu_to_le32(val),
};
mt76_mcu_send_msg(dev, MCU_CMD_REG_WRITE, &req, sizeof(req), false);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_reg_wr);
#endif /* CONFIG_PM */
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");

View File

@ -124,6 +124,8 @@ struct sta_rec_state {
u8 rsv[1];
} __packed;
#define RA_LEGACY_OFDM GENMASK(13, 6)
#define RA_LEGACY_CCK GENMASK(3, 0)
#define HT_MCS_MASK_NUM 10
struct sta_rec_ra_info {
__le16 tag;
@ -143,6 +145,13 @@ struct sta_rec_phy {
u8 rsv[2];
} __packed;
struct sta_rec_he_6g_capa {
__le16 tag;
__le16 len;
__le16 capa;
u8 rsv[2];
} __packed;
/* wtbl_rec */
struct wtbl_req_hdr {
@ -301,6 +310,7 @@ struct wtbl_raw {
sizeof(struct sta_rec_vht) + \
sizeof(struct sta_rec_uapsd) + \
sizeof(struct sta_rec_amsdu) + \
sizeof(struct sta_rec_he_6g_capa) + \
sizeof(struct tlv) + \
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
@ -327,6 +337,7 @@ enum {
STA_REC_MUEDCA,
STA_REC_BFEE,
STA_REC_PHY = 0x15,
STA_REC_HE_6G = 0x17,
STA_REC_MAX_NUM
};
@ -548,6 +559,7 @@ enum {
/* offload mcu commands */
enum {
MCU_CMD_TEST_CTRL = MCU_CE_PREFIX | 0x01,
MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03,
MCU_CMD_SET_PS_PROFILE = MCU_CE_PREFIX | 0x05,
MCU_CMD_SET_CHAN_DOMAIN = MCU_CE_PREFIX | 0x0f,
@ -560,6 +572,7 @@ enum {
MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61,
MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62,
MCU_CMD_GET_NIC_CAPAB = MCU_CE_PREFIX | 0x8a,
MCU_CMD_SET_MU_EDCA_PARMS = MCU_CE_PREFIX | 0xb0,
MCU_CMD_REG_WRITE = MCU_CE_PREFIX | 0xc0,
MCU_CMD_REG_READ = MCU_CE_PREFIX | MCU_QUERY_MASK | 0xc0,
MCU_CMD_CHIP_CONFIG = MCU_CE_PREFIX | 0xca,
@ -656,10 +669,14 @@ struct mt76_connac_bss_basic_tlv {
* bit(3): GN
* bit(4): AN
* bit(5): AC
* bit(6): AX2
* bit(7): AX5
* bit(8): AX6
*/
__le16 sta_idx;
u8 nonht_basic_phy;
u8 pad[3];
__le16 nonht_basic_phy;
u8 phymode_ext; /* bit(0) AX_6G */
u8 pad[1];
} __packed;
struct mt76_connac_bss_qos_tlv {
@ -802,7 +819,9 @@ struct mt76_connac_sched_scan_req {
} mt7663;
struct {
u8 bss_idx;
u8 pad2[19];
u8 pad1[3];
__le32 delay;
u8 pad2[12];
u8 random_mac[ETH_ALEN];
u8 pad3[38];
} mt7921;
@ -844,14 +863,14 @@ struct mt76_connac_gtk_rekey_tlv {
* 2: rekey update
*/
u8 keyid;
u8 pad[2];
u8 option; /* 1: rekey data update without enabling offload */
u8 pad[1];
__le32 proto; /* WPA-RSN-WAPI-OPSN */
__le32 pairwise_cipher;
__le32 group_cipher;
__le32 key_mgmt; /* NONE-PSK-IEEE802.1X */
__le32 mgmt_group_cipher;
u8 option; /* 1: rekey data update without enabling offload */
u8 reserverd[3];
u8 reserverd[4];
} __packed;
#define MT76_CONNAC_WOW_MASK_MAX_LEN 16
@ -961,7 +980,7 @@ struct mt76_connac_tx_power_limit_tlv {
__le16 len;
/* DW1 - cmd hint */
u8 n_chan; /* # channel */
u8 band; /* 2.4GHz - 5GHz */
u8 band; /* 2.4GHz - 5GHz - 6GHz */
u8 last_msg;
u8 pad1;
/* DW3 */
@ -1093,4 +1112,8 @@ int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable);
void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
struct mt76_connac_coredump *coredump);
int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy);
int mt76_connac_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
u32 mt76_connac_mcu_reg_rr(struct mt76_dev *dev, u32 offset);
void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
#endif /* __MT76_CONNAC_MCU_H */

View File

@ -201,7 +201,7 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev,
t->stbc[6] = t->stbc[7] = s6_to_s8(val >> 8);
/* vht mcs 8, 9 5GHz */
val = mt76x02_eeprom_get(dev, 0x132);
val = mt76x02_eeprom_get(dev, 0x12c);
t->vht[8] = s6_to_s8(val);
t->vht[9] = s6_to_s8(val >> 8);

View File

@ -176,7 +176,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
@ -276,6 +276,7 @@ static int mt76x0e_resume(struct pci_dev *pdev)
mt76_worker_enable(&mdev->tx_worker);
local_bh_disable();
mt76_for_each_q_rx(mdev, i) {
mt76_queue_rx_reset(dev, i);
napi_enable(&mdev->napi[i]);
@ -284,6 +285,7 @@ static int mt76x0e_resume(struct pci_dev *pdev)
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
local_bh_enable();
return mt76x0e_init_hardware(dev, true);
}

View File

@ -176,7 +176,7 @@ void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop)
mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop));
}
static __le16
static u16
mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev,
const struct ieee80211_tx_rate *rate, u8 *nss_val)
{
@ -222,14 +222,14 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev,
rateval |= MT_RXWI_RATE_SGI;
*nss_val = nss;
return cpu_to_le16(rateval);
return rateval;
}
void mt76x02_mac_wcid_set_rate(struct mt76x02_dev *dev, struct mt76_wcid *wcid,
const struct ieee80211_tx_rate *rate)
{
s8 max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate);
__le16 rateval;
u16 rateval;
u32 tx_info;
s8 nss;
@ -342,7 +342,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
struct ieee80211_key_conf *key = info->control.hw_key;
u32 wcid_tx_info;
u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2));
u16 txwi_flags = 0;
u16 txwi_flags = 0, rateval;
u8 nss;
s8 txpwr_adj, max_txpwr_adj;
u8 ccmp_pn[8], nstreams = dev->mphy.chainmask & 0xf;
@ -380,14 +380,15 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
if (wcid && (rate->idx < 0 || !rate->count)) {
wcid_tx_info = wcid->tx_info;
txwi->rate = FIELD_GET(MT_WCID_TX_INFO_RATE, wcid_tx_info);
rateval = FIELD_GET(MT_WCID_TX_INFO_RATE, wcid_tx_info);
max_txpwr_adj = FIELD_GET(MT_WCID_TX_INFO_TXPWR_ADJ,
wcid_tx_info);
nss = FIELD_GET(MT_WCID_TX_INFO_NSS, wcid_tx_info);
} else {
txwi->rate = mt76x02_mac_tx_rate_val(dev, rate, &nss);
rateval = mt76x02_mac_tx_rate_val(dev, rate, &nss);
max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate);
}
txwi->rate = cpu_to_le16(rateval);
txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->txpower_conf,
max_txpwr_adj);
@ -1185,7 +1186,7 @@ void mt76x02_mac_work(struct work_struct *work)
mutex_unlock(&dev->mt76.mutex);
mt76_tx_status_check(&dev->mt76, NULL, false);
mt76_tx_status_check(&dev->mt76, false);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
MT_MAC_WORK_INTERVAL);

View File

@ -53,7 +53,7 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
mt76_skb_set_moredata(data.tail[i], false);
}
spin_lock_bh(&q->lock);
spin_lock(&q->lock);
while ((skb = __skb_dequeue(&data.q)) != NULL) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
@ -61,7 +61,7 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
mt76_tx_queue_skb(dev, q, skb, &mvif->group_wcid, NULL);
}
spin_unlock_bh(&q->lock);
spin_unlock(&q->lock);
}
static void mt76x02e_pre_tbtt_enable(struct mt76x02_dev *dev, bool en)
@ -472,7 +472,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
mt76_queue_rx_reset(dev, i);
}
mt76_tx_status_check(&dev->mt76, NULL, true);
mt76_tx_status_check(&dev->mt76, true);
mt76x02_mac_start(dev);
@ -491,15 +491,17 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
clear_bit(MT76_RESET, &dev->mphy.state);
mt76_worker_enable(&dev->mt76.tx_worker);
tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
local_bh_disable();
napi_enable(&dev->mt76.tx_napi);
napi_schedule(&dev->mt76.tx_napi);
tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
mt76_for_each_q_rx(&dev->mt76, i) {
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
local_bh_enable();
if (restart) {
set_bit(MT76_RESTART, &dev->mphy.state);

View File

@ -287,6 +287,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
mvif->idx = idx;
mvif->group_wcid.idx = MT_VIF_WCID(idx);
mvif->group_wcid.hw_key_idx = -1;
mt76_packet_id_init(&mvif->group_wcid);
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
mtxq->wcid = &mvif->group_wcid;
}
@ -341,6 +343,7 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
dev->mt76.vif_mask &= ~BIT(mvif->idx);
mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid);
}
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);

View File

@ -47,7 +47,7 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
@ -149,12 +149,15 @@ mt76x2e_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
mt76_worker_enable(&mdev->tx_worker);
local_bh_disable();
mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
local_bh_enable();
return mt76x2_resume_device(dev);
}

View File

@ -7,6 +7,13 @@
/** global debugfs **/
struct hw_queue_map {
const char *name;
u8 index;
u8 pid;
u8 qid;
};
static int
mt7915_implicit_txbf_set(void *data, u64 val)
{
@ -113,13 +120,10 @@ static void
mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,
struct seq_file *file)
{
struct mt7915_dev *dev = file->private;
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
int bound[15], range[4], i, n;
if (!phy)
return;
/* Tx ampdu stat */
for (i = 0; i < ARRAY_SIZE(range); i++)
range[i] = mt76_rr(dev, MT_MIB_ARNG(ext_phy, i));
@ -146,56 +150,46 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,
static void
mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
{
struct mt7915_dev *dev = s->private;
bool ext_phy = phy != &dev->phy;
static const char * const bw[] = {
"BW20", "BW40", "BW80", "BW160"
};
int cnt;
if (!phy)
return;
struct mib_stats *mib = &phy->mib;
/* Tx Beamformer monitor */
seq_puts(s, "\nTx Beamformer applied PPDU counts: ");
cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy));
seq_printf(s, "iBF: %ld, eBF: %ld\n",
FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt),
FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt));
seq_printf(s, "iBF: %d, eBF: %d\n",
mib->tx_bf_ibf_ppdu_cnt,
mib->tx_bf_ebf_ppdu_cnt);
/* Tx Beamformer Rx feedback monitor */
seq_puts(s, "Tx Beamformer Rx feedback statistics: ");
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));
seq_printf(s, "All: %ld, HE: %ld, VHT: %ld, HT: %ld, ",
FIELD_GET(MT_ETBF_RX_FB_ALL, cnt),
FIELD_GET(MT_ETBF_RX_FB_HE, cnt),
FIELD_GET(MT_ETBF_RX_FB_VHT, cnt),
FIELD_GET(MT_ETBF_RX_FB_HT, cnt));
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));
seq_printf(s, "%s, NC: %ld, NR: %ld\n",
bw[FIELD_GET(MT_ETBF_RX_FB_BW, cnt)],
FIELD_GET(MT_ETBF_RX_FB_NC, cnt),
FIELD_GET(MT_ETBF_RX_FB_NR, cnt));
seq_printf(s, "All: %d, HE: %d, VHT: %d, HT: %d, ",
mib->tx_bf_rx_fb_all_cnt,
mib->tx_bf_rx_fb_he_cnt,
mib->tx_bf_rx_fb_vht_cnt,
mib->tx_bf_rx_fb_ht_cnt);
seq_printf(s, "%s, NC: %d, NR: %d\n",
bw[mib->tx_bf_rx_fb_bw],
mib->tx_bf_rx_fb_nc_cnt,
mib->tx_bf_rx_fb_nr_cnt);
/* Tx Beamformee Rx NDPA & Tx feedback report */
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));
seq_printf(s, "Tx Beamformee successful feedback frames: %ld\n",
FIELD_GET(MT_ETBF_TX_FB_CPL, cnt));
seq_printf(s, "Tx Beamformee feedback triggered counts: %ld\n",
FIELD_GET(MT_ETBF_TX_FB_TRI, cnt));
seq_printf(s, "Tx Beamformee successful feedback frames: %d\n",
mib->tx_bf_fb_cpl_cnt);
seq_printf(s, "Tx Beamformee feedback triggered counts: %d\n",
mib->tx_bf_fb_trig_cnt);
/* Tx SU & MU counters */
cnt = mt76_rr(dev, MT_MIB_SDR34(ext_phy));
seq_printf(s, "Tx multi-user Beamforming counts: %ld\n",
FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt));
cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy));
seq_printf(s, "Tx multi-user MPDU counts: %d\n", cnt);
cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy));
seq_printf(s, "Tx multi-user successful MPDU counts: %d\n", cnt);
cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));
seq_printf(s, "Tx single-user successful MPDU counts: %d\n", cnt);
seq_printf(s, "Tx multi-user Beamforming counts: %d\n",
mib->tx_bf_cnt);
seq_printf(s, "Tx multi-user MPDU counts: %d\n", mib->tx_mu_mpdu_cnt);
seq_printf(s, "Tx multi-user successful MPDU counts: %d\n",
mib->tx_mu_acked_mpdu_cnt);
seq_printf(s, "Tx single-user successful MPDU counts: %d\n",
mib->tx_su_acked_mpdu_cnt);
seq_puts(s, "\n");
}
@ -203,91 +197,189 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
static int
mt7915_tx_stats_show(struct seq_file *file, void *data)
{
struct mt7915_dev *dev = file->private;
int stat[8], i, n;
struct mt7915_phy *phy = file->private;
struct mt7915_dev *dev = phy->dev;
struct mib_stats *mib = &phy->mib;
int i;
mt7915_ampdu_stat_read_phy(&dev->phy, file);
mt7915_txbf_stat_read_phy(&dev->phy, file);
mutex_lock(&dev->mt76.mutex);
mt7915_ampdu_stat_read_phy(mt7915_ext_phy(dev), file);
mt7915_txbf_stat_read_phy(mt7915_ext_phy(dev), file);
mt7915_ampdu_stat_read_phy(phy, file);
mt7915_mac_update_stats(phy);
mt7915_txbf_stat_read_phy(phy, file);
/* Tx amsdu info */
seq_puts(file, "Tx MSDU statistics:\n");
for (i = 0, n = 0; i < ARRAY_SIZE(stat); i++) {
stat[i] = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
n += stat[i];
}
for (i = 0; i < ARRAY_SIZE(stat); i++) {
seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ",
i + 1, stat[i]);
if (n != 0)
seq_printf(file, "(%d%%)\n", stat[i] * 100 / n);
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ",
i + 1, mib->tx_amsdu[i]);
if (mib->tx_amsdu_cnt)
seq_printf(file, "(%3d%%)\n",
mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt);
else
seq_puts(file, "\n");
}
mutex_unlock(&dev->mt76.mutex);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(mt7915_tx_stats);
static int
mt7915_queues_acq(struct seq_file *s, void *data)
static void
mt7915_hw_queue_read(struct seq_file *s, u32 base, u32 size,
const struct hw_queue_map *map)
{
struct mt7915_dev *dev = dev_get_drvdata(s->private);
int i;
struct mt7915_phy *phy = s->private;
struct mt7915_dev *dev = phy->dev;
u32 i, val;
for (i = 0; i < 16; i++) {
int j, acs = i / 4, index = i % 4;
u32 ctrl, val, qlen = 0;
val = mt76_rr(dev, base + MT_FL_Q_EMPTY);
for (i = 0; i < size; i++) {
u32 ctrl, head, tail, queued;
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index));
ctrl = BIT(31) | BIT(15) | (acs << 8);
if (val & BIT(map[i].index))
continue;
for (j = 0; j < 32; j++) {
if (val & BIT(j))
continue;
ctrl = BIT(31) | (map[i].pid << 10) | (map[i].qid << 24);
mt76_wr(dev, base + MT_FL_Q0_CTRL, ctrl);
mt76_wr(dev, MT_PLE_FL_Q0_CTRL,
ctrl | (j + (index << 5)));
qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
GENMASK(11, 0));
}
seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen);
head = mt76_get_field(dev, base + MT_FL_Q2_CTRL,
GENMASK(11, 0));
tail = mt76_get_field(dev, base + MT_FL_Q2_CTRL,
GENMASK(27, 16));
queued = mt76_get_field(dev, base + MT_FL_Q3_CTRL,
GENMASK(11, 0));
seq_printf(s, "\t%s: ", map[i].name);
seq_printf(s, "queued:0x%03x head:0x%03x tail:0x%03x\n",
queued, head, tail);
}
}
static void
mt7915_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
{
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct mt7915_dev *dev = msta->vif->phy->dev;
struct seq_file *s = data;
u8 ac;
for (ac = 0; ac < 4; ac++) {
u32 qlen, ctrl, val;
u32 idx = msta->wcid.idx >> 5;
u8 offs = msta->wcid.idx & GENMASK(4, 0);
ctrl = BIT(31) | BIT(11) | (ac << 24);
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
if (val & BIT(offs))
continue;
mt76_wr(dev, MT_PLE_BASE + MT_FL_Q0_CTRL, ctrl | msta->wcid.idx);
qlen = mt76_get_field(dev, MT_PLE_BASE + MT_FL_Q3_CTRL,
GENMASK(11, 0));
seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
sta->addr, msta->wcid.idx, msta->vif->wmm_idx,
ac, qlen);
}
}
static int
mt7915_hw_queues_show(struct seq_file *file, void *data)
{
struct mt7915_phy *phy = file->private;
struct mt7915_dev *dev = phy->dev;
static const struct hw_queue_map ple_queue_map[] = {
{ "CPU_Q0", 0, 1, MT_CTX0 },
{ "CPU_Q1", 1, 1, MT_CTX0 + 1 },
{ "CPU_Q2", 2, 1, MT_CTX0 + 2 },
{ "CPU_Q3", 3, 1, MT_CTX0 + 3 },
{ "ALTX_Q0", 8, 2, MT_LMAC_ALTX0 },
{ "BMC_Q0", 9, 2, MT_LMAC_BMC0 },
{ "BCN_Q0", 10, 2, MT_LMAC_BCN0 },
{ "PSMP_Q0", 11, 2, MT_LMAC_PSMP0 },
{ "ALTX_Q1", 12, 2, MT_LMAC_ALTX0 + 4 },
{ "BMC_Q1", 13, 2, MT_LMAC_BMC0 + 4 },
{ "BCN_Q1", 14, 2, MT_LMAC_BCN0 + 4 },
{ "PSMP_Q1", 15, 2, MT_LMAC_PSMP0 + 4 },
};
static const struct hw_queue_map pse_queue_map[] = {
{ "CPU Q0", 0, 1, MT_CTX0 },
{ "CPU Q1", 1, 1, MT_CTX0 + 1 },
{ "CPU Q2", 2, 1, MT_CTX0 + 2 },
{ "CPU Q3", 3, 1, MT_CTX0 + 3 },
{ "HIF_Q0", 8, 0, MT_HIF0 },
{ "HIF_Q1", 9, 0, MT_HIF0 + 1 },
{ "HIF_Q2", 10, 0, MT_HIF0 + 2 },
{ "HIF_Q3", 11, 0, MT_HIF0 + 3 },
{ "HIF_Q4", 12, 0, MT_HIF0 + 4 },
{ "HIF_Q5", 13, 0, MT_HIF0 + 5 },
{ "LMAC_Q", 16, 2, 0 },
{ "MDP_TXQ", 17, 2, 1 },
{ "MDP_RXQ", 18, 2, 2 },
{ "SEC_TXQ", 19, 2, 3 },
{ "SEC_RXQ", 20, 2, 4 },
};
u32 val, head, tail;
/* ple queue */
val = mt76_rr(dev, MT_PLE_FREEPG_CNT);
head = mt76_get_field(dev, MT_PLE_FREEPG_HEAD_TAIL, GENMASK(11, 0));
tail = mt76_get_field(dev, MT_PLE_FREEPG_HEAD_TAIL, GENMASK(27, 16));
seq_puts(file, "PLE page info:\n");
seq_printf(file,
"\tTotal free page: 0x%08x head: 0x%03x tail: 0x%03x\n",
val, head, tail);
val = mt76_rr(dev, MT_PLE_PG_HIF_GROUP);
head = mt76_get_field(dev, MT_PLE_HIF_PG_INFO, GENMASK(11, 0));
tail = mt76_get_field(dev, MT_PLE_HIF_PG_INFO, GENMASK(27, 16));
seq_printf(file, "\tHIF free page: 0x%03x res: 0x%03x used: 0x%03x\n",
val, head, tail);
seq_puts(file, "PLE non-empty queue info:\n");
mt7915_hw_queue_read(file, MT_PLE_BASE, ARRAY_SIZE(ple_queue_map),
&ple_queue_map[0]);
/* iterate per-sta ple queue */
ieee80211_iterate_stations_atomic(phy->mt76->hw,
mt7915_sta_hw_queue_read, file);
/* pse queue */
seq_puts(file, "PSE non-empty queue info:\n");
mt7915_hw_queue_read(file, MT_PSE_BASE, ARRAY_SIZE(pse_queue_map),
&pse_queue_map[0]);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(mt7915_hw_queues);
static int
mt7915_queues_read(struct seq_file *s, void *data)
mt7915_xmit_queues_show(struct seq_file *file, void *data)
{
struct mt7915_dev *dev = dev_get_drvdata(s->private);
struct mt76_phy *mphy_ext = dev->mt76.phy2;
struct mt76_queue *ext_q = mphy_ext ? mphy_ext->q_tx[MT_TXQ_BE] : NULL;
struct mt7915_phy *phy = file->private;
struct mt7915_dev *dev = phy->dev;
struct {
struct mt76_queue *q;
char *queue;
} queue_map[] = {
{ dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
{ ext_q, "WFDMA1" },
{ dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
{ dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" },
{ dev->mt76.q_mcu[MT_MCUQ_WA], "MCUWA" },
{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
{ phy->mt76->q_tx[MT_TXQ_BE], " MAIN" },
{ dev->mt76.q_mcu[MT_MCUQ_WM], " MCUWM" },
{ dev->mt76.q_mcu[MT_MCUQ_WA], " MCUWA" },
{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWDL" },
};
int i;
seq_puts(file, " queue | hw-queued | head | tail |\n");
for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
struct mt76_queue *q = queue_map[i].q;
if (!q)
continue;
seq_printf(s,
"%s: queued=%d head=%d tail=%d\n",
seq_printf(file, " %s | %9d | %9d | %9d |\n",
queue_map[i].queue, q->queued, q->head,
q->tail);
}
@ -295,8 +387,10 @@ mt7915_queues_read(struct seq_file *s, void *data)
return 0;
}
static void
mt7915_puts_rate_txpower(struct seq_file *s, struct mt7915_phy *phy)
DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues);
static int
mt7915_rate_txpower_show(struct seq_file *file, void *data)
{
static const char * const sku_group_name[] = {
"CCK", "OFDM", "HT20", "HT40",
@ -304,14 +398,11 @@ mt7915_puts_rate_txpower(struct seq_file *s, struct mt7915_phy *phy)
"RU26", "RU52", "RU106", "RU242/SU20",
"RU484/SU40", "RU996/SU80", "RU2x996/SU160"
};
struct mt7915_phy *phy = file->private;
s8 txpower[MT7915_SKU_RATE_NUM], *buf;
int i;
if (!phy)
return;
seq_printf(s, "\nBand %d\n", phy != &phy->dev->phy);
seq_printf(file, "\nBand %d\n", phy != &phy->dev->phy);
mt7915_mcu_get_txpower_sku(phy, txpower, sizeof(txpower));
for (i = 0, buf = txpower; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {
u8 mcs_num = mt7915_sku_group_len[i];
@ -319,45 +410,70 @@ mt7915_puts_rate_txpower(struct seq_file *s, struct mt7915_phy *phy)
if (i >= SKU_VHT_BW20 && i <= SKU_VHT_BW160)
mcs_num = 10;
mt76_seq_puts_array(s, sku_group_name[i], buf, mcs_num);
mt76_seq_puts_array(file, sku_group_name[i], buf, mcs_num);
buf += mt7915_sku_group_len[i];
}
}
static int
mt7915_read_rate_txpower(struct seq_file *s, void *data)
{
struct mt7915_dev *dev = dev_get_drvdata(s->private);
mt7915_puts_rate_txpower(s, &dev->phy);
mt7915_puts_rate_txpower(s, mt7915_ext_phy(dev));
return 0;
}
int mt7915_init_debugfs(struct mt7915_dev *dev)
DEFINE_SHOW_ATTRIBUTE(mt7915_rate_txpower);
static int
mt7915_twt_stats(struct seq_file *s, void *data)
{
struct mt7915_dev *dev = dev_get_drvdata(s->private);
struct mt7915_twt_flow *iter;
rcu_read_lock();
seq_puts(s, " wcid | id | flags | exp | mantissa");
seq_puts(s, " | duration | tsf |\n");
list_for_each_entry_rcu(iter, &dev->twt_list, list)
seq_printf(s,
"%9d | %8d | %5c%c%c%c | %8d | %8d | %8d | %14lld |\n",
iter->wcid, iter->id,
iter->sched ? 's' : 'u',
iter->protection ? 'p' : '-',
iter->trigger ? 't' : '-',
iter->flowtype ? '-' : 'a',
iter->exp, iter->mantissa,
iter->duration, iter->tsf);
rcu_read_unlock();
return 0;
}
int mt7915_init_debugfs(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
struct dentry *dir;
dir = mt76_register_debugfs(&dev->mt76);
dir = mt76_register_debugfs_fops(phy->mt76, NULL);
if (!dir)
return -ENOMEM;
debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
mt7915_queues_read);
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
mt7915_queues_acq);
debugfs_create_file("tx_stats", 0400, dir, dev, &mt7915_tx_stats_fops);
debugfs_create_file("hw-queues", 0400, dir, phy,
&mt7915_hw_queues_fops);
debugfs_create_file("xmit-queues", 0400, dir, phy,
&mt7915_xmit_queues_fops);
debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops);
debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
debugfs_create_file("implicit_txbf", 0600, dir, dev,
&fops_implicit_txbf);
debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern);
/* test knobs */
debugfs_create_file("radar_trigger", 0200, dir, dev,
&fops_radar_trigger);
debugfs_create_file("txpower_sku", 0400, dir, phy,
&mt7915_rate_txpower_fops);
debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
mt7915_twt_stats);
debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger);
debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
mt7915_read_rate_txpower);
if (!dev->dbdc_support || ext_phy) {
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
&dev->hw_pattern);
debugfs_create_file("radar_trigger", 0200, dir, dev,
&fops_radar_trigger);
}
return 0;
}
@ -365,12 +481,14 @@ int mt7915_init_debugfs(struct mt7915_dev *dev)
#ifdef CONFIG_MAC80211_DEBUGFS
/** per-station debugfs **/
/* usage: <tx mode> <ldpc> <stbc> <bw> <gi> <nss> <mcs> */
static int mt7915_sta_fixed_rate_set(void *data, u64 rate)
{
struct ieee80211_sta *sta = data;
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
/* usage: <he ltf> <tx mode> <ldpc> <stbc> <bw> <gi> <nss> <mcs>
* <tx mode>: see enum mt76_phy_type
*/
return mt7915_mcu_set_fixed_rate(msta->vif->phy->dev, sta, rate);
}
@ -378,55 +496,22 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_fixed_rate, NULL,
mt7915_sta_fixed_rate_set, "%llx\n");
static int
mt7915_sta_stats_show(struct seq_file *s, void *data)
mt7915_queues_show(struct seq_file *s, void *data)
{
struct ieee80211_sta *sta = s->private;
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct mt7915_sta_stats *stats = &msta->stats;
struct rate_info *rate = &stats->prob_rate;
static const char * const bw[] = {
"BW20", "BW5", "BW10", "BW40",
"BW80", "BW160", "BW_HE_RU"
};
if (!rate->legacy && !rate->flags)
return 0;
seq_puts(s, "Probing rate - ");
if (rate->flags & RATE_INFO_FLAGS_MCS)
seq_puts(s, "HT ");
else if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
seq_puts(s, "VHT ");
else if (rate->flags & RATE_INFO_FLAGS_HE_MCS)
seq_puts(s, "HE ");
else
seq_printf(s, "Bitrate %d\n", rate->legacy);
if (rate->flags) {
seq_printf(s, "%s NSS%d MCS%d ",
bw[rate->bw], rate->nss, rate->mcs);
if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
seq_puts(s, "SGI ");
else if (rate->he_gi)
seq_puts(s, "HE GI ");
if (rate->he_dcm)
seq_puts(s, "DCM ");
}
seq_printf(s, "\nPPDU PER: %ld.%1ld%%\n",
stats->per / 10, stats->per % 10);
mt7915_sta_hw_queue_read(s, sta);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(mt7915_sta_stats);
DEFINE_SHOW_ATTRIBUTE(mt7915_queues);
void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir)
{
debugfs_create_file("fixed_rate", 0600, dir, sta, &fops_fixed_rate);
debugfs_create_file("stats", 0400, dir, sta, &mt7915_sta_stats_fops);
debugfs_create_file("hw-queues", 0400, dir, sta, &mt7915_queues_fops);
}
#endif

View File

@ -42,13 +42,17 @@ static const struct ieee80211_iface_combination if_comb[] = {
}
};
static ssize_t mt7915_thermal_show_temp(struct device *dev,
static ssize_t mt7915_thermal_temp_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct mt7915_phy *phy = dev_get_drvdata(dev);
int i = to_sensor_dev_attr(attr)->index;
int temperature;
if (i)
return sprintf(buf, "%u\n", phy->throttle_temp[i - 1] * 1000);
temperature = mt7915_mcu_get_temperature(phy);
if (temperature < 0)
return temperature;
@ -57,11 +61,34 @@ static ssize_t mt7915_thermal_show_temp(struct device *dev,
return sprintf(buf, "%u\n", temperature * 1000);
}
static SENSOR_DEVICE_ATTR(temp1_input, 0444, mt7915_thermal_show_temp,
NULL, 0);
static ssize_t mt7915_thermal_temp_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct mt7915_phy *phy = dev_get_drvdata(dev);
int ret, i = to_sensor_dev_attr(attr)->index;
long val;
ret = kstrtol(buf, 10, &val);
if (ret < 0)
return ret;
mutex_lock(&phy->dev->mt76.mutex);
val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 60, 130);
phy->throttle_temp[i - 1] = val;
mutex_unlock(&phy->dev->mt76.mutex);
return count;
}
static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7915_thermal_temp, 0);
static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7915_thermal_temp, 1);
static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7915_thermal_temp, 2);
static struct attribute *mt7915_hwmon_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(mt7915_hwmon);
@ -96,6 +123,9 @@ mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
if (state > MT7915_THERMAL_THROTTLE_MAX)
return -EINVAL;
if (phy->throttle_temp[0] > phy->throttle_temp[1])
return 0;
if (state == phy->throttle_state)
return 0;
@ -130,9 +160,12 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
struct wiphy *wiphy = phy->mt76->hw->wiphy;
struct thermal_cooling_device *cdev;
struct device *hwmon;
const char *name;
cdev = thermal_cooling_device_register(wiphy_name(wiphy), phy,
&mt7915_thermal_ops);
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7915_%s",
wiphy_name(wiphy));
cdev = thermal_cooling_device_register(name, phy, &mt7915_thermal_ops);
if (!IS_ERR(cdev)) {
if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
"cooling_device") < 0)
@ -144,15 +177,76 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
if (!IS_REACHABLE(CONFIG_HWMON))
return 0;
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev,
wiphy_name(wiphy), phy,
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
mt7915_hwmon_groups);
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
/* initialize critical/maximum high temperature */
phy->throttle_temp[0] = 110;
phy->throttle_temp[1] = 120;
return 0;
}
static void mt7915_led_set_config(struct led_classdev *led_cdev,
u8 delay_on, u8 delay_off)
{
struct mt7915_dev *dev;
struct mt76_dev *mt76;
u32 val;
mt76 = container_of(led_cdev, struct mt76_dev, led_cdev);
dev = container_of(mt76, struct mt7915_dev, mt76);
/* select TX blink mode, 2: only data frames */
mt76_rmw_field(dev, MT_TMAC_TCR0(0), MT_TMAC_TCR0_TX_BLINK, 2);
/* enable LED */
mt76_wr(dev, MT_LED_EN(0), 1);
/* set LED Tx blink on/off time */
val = FIELD_PREP(MT_LED_TX_BLINK_ON_MASK, delay_on) |
FIELD_PREP(MT_LED_TX_BLINK_OFF_MASK, delay_off);
mt76_wr(dev, MT_LED_TX_BLINK(0), val);
/* control LED */
val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK;
if (dev->mt76.led_al)
val |= MT_LED_CTRL_POLARITY;
mt76_wr(dev, MT_LED_CTRL(0), val);
mt76_clear(dev, MT_LED_CTRL(0), MT_LED_CTRL_KICK);
}
static int mt7915_led_set_blink(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
u16 delta_on = 0, delta_off = 0;
#define HW_TICK 10
#define TO_HW_TICK(_t) (((_t) > HW_TICK) ? ((_t) / HW_TICK) : HW_TICK)
if (*delay_on)
delta_on = TO_HW_TICK(*delay_on);
if (*delay_off)
delta_off = TO_HW_TICK(*delay_off);
mt7915_led_set_config(led_cdev, delta_on, delta_off);
return 0;
}
static void mt7915_led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
if (!brightness)
mt7915_led_set_config(led_cdev, 0, 0xff);
else
mt7915_led_set_config(led_cdev, 0xff, 0);
}
static void
mt7915_init_txpower(struct mt7915_dev *dev,
struct ieee80211_supported_band *sband)
@ -232,7 +326,12 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
wiphy->reg_notifier = mt7915_regd_notifier;
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
@ -287,9 +386,7 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF);
mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set);
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 0x680);
/* disable rx rate report by default due to hw issues */
mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
}
@ -298,7 +395,7 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
{
int i;
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 0x400);
/* enable hardware de-agg */
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
@ -307,6 +404,11 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
for (i = 0; i < 2; i++)
mt7915_mac_init_band(dev, i);
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
i = dev->mt76.led_pin ? MT_LED_GPIO_MUX3 : MT_LED_GPIO_MUX2;
mt76_rmw_field(dev, i, MT_LED_GPIO_SEL_MASK, 4);
}
}
static int mt7915_txbf_init(struct mt7915_dev *dev)
@ -350,7 +452,6 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask;
mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1;
INIT_LIST_HEAD(&phy->stats_list);
INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work);
mt7915_eeprom_parse_band_config(phy);
@ -374,6 +475,10 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
if (ret)
goto error;
ret = mt7915_init_debugfs(phy);
if (ret)
goto error;
return 0;
error:
@ -480,7 +585,7 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
}
/* Beacon and mgmt frames should occupy wcid 0 */
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA - 1);
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
if (idx)
return -ENOSPC;
@ -525,7 +630,6 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
int vif, int nss)
{
struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
struct ieee80211_he_mcs_nss_supp *mcs = &he_cap->he_mcs_nss_supp;
u8 c;
#ifdef CONFIG_MAC80211_MESH
@ -577,8 +681,11 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
/* num_snd_dim */
c = (nss - 1) | (max_t(int, le16_to_cpu(mcs->tx_mcs_160), 1) << 3);
/* num_snd_dim
* for mt7915, max supported nss is 2 for bw > 80MHz
*/
c = (nss - 1) |
IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2;
elem->phy_cap_info[5] |= c;
c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
@ -613,12 +720,19 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
{
int i, idx = 0, nss = hweight8(phy->mt76->chainmask);
u16 mcs_map = 0;
u16 mcs_map_160 = 0;
for (i = 0; i < 8; i++) {
if (i < nss)
mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));
else
mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
/* Can do 1/2 of NSS streams in 160Mhz mode. */
if (i < nss / 2)
mcs_map_160 |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));
else
mcs_map_160 |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
}
for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
@ -667,6 +781,8 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
switch (i) {
case NL80211_IFTYPE_AP:
he_cap_elem->mac_cap_info[0] |=
IEEE80211_HE_MAC_CAP0_TWT_RES;
he_cap_elem->mac_cap_info[2] |=
IEEE80211_HE_MAC_CAP2_BSR;
he_cap_elem->mac_cap_info[4] |=
@ -677,7 +793,11 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
he_cap_elem->phy_cap_info[6] |=
IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
case NL80211_IFTYPE_STATION:
he_cap_elem->mac_cap_info[1] |=
@ -720,10 +840,10 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);
he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);
he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map);
he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map);
he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map);
he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map);
he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map_160);
he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map_160);
he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map_160);
he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map_160);
mt7915_set_stream_he_txbf_caps(he_cap, i, nss);
@ -787,11 +907,11 @@ int mt7915_register_device(struct mt7915_dev *dev)
dev->phy.dev = dev;
dev->phy.mt76 = &dev->mt76.phy;
dev->mt76.phy.priv = &dev->phy;
INIT_LIST_HEAD(&dev->phy.stats_list);
INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work);
INIT_LIST_HEAD(&dev->sta_rc_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
INIT_LIST_HEAD(&dev->twt_list);
spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
@ -816,6 +936,12 @@ int mt7915_register_device(struct mt7915_dev *dev)
dev->mt76.test_ops = &mt7915_testmode_ops;
#endif
/* init led callbacks */
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
dev->mt76.led_cdev.brightness_set = mt7915_led_set_brightness;
dev->mt76.led_cdev.blink_set = mt7915_led_set_blink;
}
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret)
@ -831,7 +957,7 @@ int mt7915_register_device(struct mt7915_dev *dev)
if (ret)
return ret;
return mt7915_init_debugfs(dev);
return mt7915_init_debugfs(&dev->phy);
}
void mt7915_unregister_device(struct mt7915_dev *dev)

View File

@ -6,6 +6,7 @@
#include "mt7915.h"
#include "../dma.h"
#include "mac.h"
#include "mcu.h"
#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
@ -88,15 +89,14 @@ bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask)
0, 5000);
}
static u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid)
static u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw)
{
mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
return MT_WTBL_LMAC_OFFS(wcid, 0);
return MT_WTBL_LMAC_OFFS(wcid, dw);
}
/* TODO: use txfree airtime info to avoid runtime accessing in the long run */
static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
{
static const u8 ac_to_tid[] = {
@ -107,6 +107,7 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
};
struct ieee80211_sta *sta;
struct mt7915_sta *msta;
struct rate_info *rate;
u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
LIST_HEAD(sta_poll_list);
int i;
@ -119,8 +120,9 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
while (true) {
bool clear = false;
u32 addr;
u32 addr, val;
u16 idx;
u8 bw;
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&sta_poll_list)) {
@ -133,7 +135,7 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
spin_unlock_bh(&dev->sta_poll_lock);
idx = msta->wcid.idx;
addr = mt7915_mac_wtbl_lmac_addr(dev, idx) + 20 * 4;
addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 20);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
u32 tx_last = msta->airtime_ac[i];
@ -174,6 +176,43 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
ieee80211_sta_register_airtime(sta, tid, tx_cur,
rx_cur);
}
/*
* We don't support reading GI info from txs packets.
* For accurate tx status reporting and AQL improvement,
* we need to make sure that flags match so polling GI
* from per-sta counters directly.
*/
rate = &msta->wcid.rate;
addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 7);
val = mt76_rr(dev, addr);
switch (rate->bw) {
case RATE_INFO_BW_160:
bw = IEEE80211_STA_RX_BW_160;
break;
case RATE_INFO_BW_80:
bw = IEEE80211_STA_RX_BW_80;
break;
case RATE_INFO_BW_40:
bw = IEEE80211_STA_RX_BW_40;
break;
default:
bw = IEEE80211_STA_RX_BW_20;
break;
}
if (rate->flags & RATE_INFO_FLAGS_HE_MCS) {
u8 offs = 24 + 2 * bw;
rate->he_gi = (val & (0x3 << offs)) >> offs;
} else if (rate->flags &
(RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) {
if (val & BIT(12 + bw))
rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
else
rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI;
}
}
rcu_read_unlock();
@ -228,12 +267,51 @@ mt7915_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
}
static void
mt7915_mac_decode_he_mu_radiotap(struct sk_buff *skb,
struct mt76_rx_status *status,
__le32 *rxv)
{
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),
.flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
};
struct ieee80211_radiotap_he_mu *he_mu = NULL;
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
mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
struct mt76_rx_status *status,
__le32 *rxv, u32 phy)
{
/* TODO: struct ieee80211_radiotap_he_mu */
static const struct ieee80211_radiotap_he known = {
.data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
HE_BITS(DATA1_DATA_DCM_KNOWN) |
@ -241,6 +319,7 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
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) |
@ -255,9 +334,12 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
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]);
@ -265,12 +347,10 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
case MT_PHY_TYPE_HE_SU:
he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
HE_BITS(DATA1_UL_DL_KNOWN) |
HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE_KNOWN);
HE_BITS(DATA1_BEAM_CHANGE_KNOWN);
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
he->data4 |= HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
break;
case MT_PHY_TYPE_HE_EXT_SU:
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
@ -280,23 +360,20 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
break;
case MT_PHY_TYPE_HE_MU:
he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
HE_BITS(DATA1_UL_DL_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE_KNOWN);
HE_BITS(DATA1_UL_DL_KNOWN);
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
he->data4 |= HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
mt7915_mac_decode_he_radiotap_ru(status, he, rxv);
break;
case MT_PHY_TYPE_HE_TB:
he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) |
HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) |
he->data4 |= 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]);
@ -610,8 +687,11 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
status->flag |= RX_FLAG_8023;
}
if (rxv && status->flag & RX_FLAG_RADIOTAP_HE)
if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) {
mt7915_mac_decode_he_radiotap(skb, status, rxv, mode);
if (status->flag & RX_FLAG_RADIOTAP_HE_MU)
mt7915_mac_decode_he_mu_radiotap(skb, status, rxv);
}
if (!status->wcid || !ieee80211_is_data_qos(fc))
return 0;
@ -825,17 +905,19 @@ mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi,
static void
mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct ieee80211_key_conf *key)
struct sk_buff *skb, struct ieee80211_key_conf *key,
bool *mcast)
{
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;
*mcast = is_multicast_ether_addr(hdr->addr1);
if (ieee80211_is_action(fc) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) {
@ -861,15 +943,16 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) |
FIELD_PREP(MT_TXD2_MULTICAST, multicast);
FIELD_PREP(MT_TXD2_MULTICAST, *mcast);
if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
if (key && *mcast && 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)
if (!ieee80211_is_data(fc) || *mcast ||
info->flags & IEEE80211_TX_CTL_USE_MINRATE)
val |= MT_TXD2_FIX_RATE;
txwi[2] |= cpu_to_le32(val);
@ -899,6 +982,51 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
txwi[7] |= cpu_to_le32(val);
}
static u16
mt7915_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 (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);
}
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
struct ieee80211_key_conf *key, bool beacon)
@ -909,6 +1037,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
bool mcast = false;
u16 tx_count = 15;
u32 val;
@ -939,7 +1068,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
txwi[0] = cpu_to_le32(val);
val = MT_TXD1_LONG_FORMAT |
val = MT_TXD1_LONG_FORMAT | MT_TXD1_VTA |
FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
@ -971,19 +1100,14 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
if (is_8023)
mt7915_mac_write_txwi_8023(dev, txwi, skb, wcid);
else
mt7915_mac_write_txwi_80211(dev, txwi, skb, key);
mt7915_mac_write_txwi_80211(dev, txwi, skb, key, &mcast);
if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) {
u16 rate;
u16 rate = mt7915_mac_tx_rate_val(mphy, vif, beacon, mcast);
/* hardware won't add HTC for mgmt/ctrl frame */
txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD);
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
rate = MT7915_5G_RATE_DEFAULT;
else
rate = MT7915_2G_RATE_DEFAULT;
val = MT_TXD6_FIXED_BW |
FIELD_PREP(MT_TXD6_TX_RATE, rate);
txwi[6] |= cpu_to_le32(val);
@ -1016,6 +1140,17 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (!wcid)
wcid = &dev->mt76.global_wcid;
if (sta) {
struct mt7915_sta *msta;
msta = (struct mt7915_sta *)sta->drv_priv;
if (time_after(jiffies, msta->jiffies + HZ / 4)) {
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
msta->jiffies = jiffies;
}
}
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
@ -1162,7 +1297,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
count = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl));
for (i = 0; i < count; i++) {
u32 msdu, info = le32_to_cpu(free->info[i]);
u8 stat;
/*
* 1'b1: new wcid pair.
@ -1170,7 +1304,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
*/
if (info & MT_TX_FREE_PAIR) {
struct mt7915_sta *msta;
struct mt7915_phy *phy;
struct mt76_wcid *wcid;
u16 idx;
@ -1182,10 +1315,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
continue;
msta = container_of(wcid, struct mt7915_sta, wcid);
phy = msta->vif->phy;
spin_lock_bh(&dev->sta_poll_lock);
if (list_empty(&msta->stats_list))
list_add_tail(&msta->stats_list, &phy->stats_list);
if (list_empty(&msta->poll_list))
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
@ -1193,8 +1323,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
}
msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info);
stat = FIELD_GET(MT_TX_FREE_STATUS, info);
txwi = mt76_token_release(mdev, msdu, &wake);
if (!txwi)
continue;
@ -1219,20 +1347,27 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
static bool
mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,
__le32 *txs_data)
__le32 *txs_data, struct mt76_sta_stats *stats)
{
struct ieee80211_supported_band *sband;
struct mt76_dev *mdev = &dev->mt76;
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(mdev, &list);
skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
if (!skb)
goto out;
goto out_no_skb;
txs = le32_to_cpu(txs_data[0]);
info = IEEE80211_SKB_CB(skb);
if (!(txs_data[0] & le32_to_cpu(MT_TXS0_ACK_ERROR_MASK)))
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.ampdu_len = 1;
@ -1240,9 +1375,92 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,
IEEE80211_TX_STAT_ACK);
info->status.rates[0].idx = -1;
mt76_tx_status_skb_done(mdev, skb, &list);
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->mphy;
if (wcid->ext_phy && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
sband = &mphy->sband_5g.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:
rate.mcs += (rate.nss - 1) * 8;
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:
mt76_tx_status_skb_done(mdev, skb, &list);
out_no_skb:
mt76_tx_status_unlock(mdev, &list);
return !!skb;
@ -1279,12 +1497,13 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
if (!wcid)
goto out;
mt7915_mac_add_txs_skb(dev, wcid, pid, txs_data);
msta = container_of(wcid, struct mt7915_sta, wcid);
mt7915_mac_add_txs_skb(dev, wcid, pid, txs_data, &msta->stats);
if (!wcid->sta)
goto out;
msta = container_of(wcid, struct mt7915_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);
@ -1333,15 +1552,11 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
{
struct mt7915_dev *dev;
if (!e->txwi) {
dev_kfree_skb_any(e->skb);
return;
}
dev = container_of(mdev, struct mt7915_dev, mt76);
/* error path */
if (e->skb == DMA_DUMMY_DATA) {
struct mt76_txwi_cache *t;
@ -1403,17 +1618,12 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
int sifs, offset;
int offset;
bool is_5ghz = phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ;
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
return;
if (is_5ghz)
sifs = 16;
else
sifs = 10;
if (ext_phy) {
coverage_class = max_t(s16, dev->phy.coverage_class,
coverage_class);
@ -1435,11 +1645,14 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
mt76_wr(dev, MT_TMAC_CDTR(ext_phy), cck + reg_offset);
mt76_wr(dev, MT_TMAC_ODTR(ext_phy), ofdm + reg_offset);
mt76_wr(dev, MT_TMAC_ICR0(ext_phy),
FIELD_PREP(MT_IFS_EIFS, 360) |
FIELD_PREP(MT_IFS_EIFS_OFDM, is_5ghz ? 84 : 78) |
FIELD_PREP(MT_IFS_RIFS, 2) |
FIELD_PREP(MT_IFS_SIFS, sifs) |
FIELD_PREP(MT_IFS_SIFS, 10) |
FIELD_PREP(MT_IFS_SLOT, phy->slottime));
mt76_wr(dev, MT_TMAC_ICR1(ext_phy),
FIELD_PREP(MT_IFS_EIFS_CCK, 314));
if (phy->slottime < 20 || is_5ghz)
val = MT7915_CFEND_RATE_DEFAULT;
else
@ -1580,7 +1793,7 @@ mt7915_dma_reset(struct mt7915_dev *dev)
mt76_for_each_q_rx(&dev->mt76, i)
mt76_queue_rx_reset(dev, i);
mt76_tx_status_check(&dev->mt76, NULL, true);
mt76_tx_status_check(&dev->mt76, true);
/* re-init prefetch settings after reset */
mt7915_dma_prefetch(dev);
@ -1668,6 +1881,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
if (phy2)
clear_bit(MT76_RESET, &phy2->mt76->state);
local_bh_disable();
napi_enable(&dev->mt76.napi[0]);
napi_schedule(&dev->mt76.napi[0]);
@ -1676,6 +1890,8 @@ void mt7915_mac_reset_work(struct work_struct *work)
napi_enable(&dev->mt76.napi[2]);
napi_schedule(&dev->mt76.napi[2]);
local_bh_enable();
tasklet_schedule(&dev->irq_tasklet);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
@ -1702,17 +1918,117 @@ void mt7915_mac_reset_work(struct work_struct *work)
MT7915_WATCHDOG_TIME);
}
static void
mt7915_mac_update_stats(struct mt7915_phy *phy)
void mt7915_mac_update_stats(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct mib_stats *mib = &phy->mib;
bool ext_phy = phy != &dev->phy;
int i, aggr0, aggr1;
int i, aggr0, aggr1, cnt;
mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy),
MT_MIB_SDR3_FCS_ERR_MASK);
cnt = mt76_rr(dev, MT_MIB_SDR4(ext_phy));
mib->rx_fifo_full_cnt += FIELD_GET(MT_MIB_SDR4_RX_FIFO_FULL_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR5(ext_phy));
mib->rx_mpdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR6(ext_phy));
mib->channel_idle_cnt += FIELD_GET(MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR7(ext_phy));
mib->rx_vector_mismatch_cnt += FIELD_GET(MT_MIB_SDR7_RX_VECTOR_MISMATCH_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR8(ext_phy));
mib->rx_delimiter_fail_cnt += FIELD_GET(MT_MIB_SDR8_RX_DELIMITER_FAIL_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR11(ext_phy));
mib->rx_len_mismatch_cnt += FIELD_GET(MT_MIB_SDR11_RX_LEN_MISMATCH_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR12(ext_phy));
mib->tx_ampdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR13(ext_phy));
mib->tx_stop_q_empty_cnt += FIELD_GET(MT_MIB_SDR13_TX_STOP_Q_EMPTY_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR14(ext_phy));
mib->tx_mpdu_attempts_cnt += FIELD_GET(MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR15(ext_phy));
mib->tx_mpdu_success_cnt += FIELD_GET(MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR22(ext_phy));
mib->rx_ampdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR23(ext_phy));
mib->rx_ampdu_bytes_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR24(ext_phy));
mib->rx_ampdu_valid_subframe_cnt += FIELD_GET(MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR25(ext_phy));
mib->rx_ampdu_valid_subframe_bytes_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR27(ext_phy));
mib->tx_rwp_fail_cnt += FIELD_GET(MT_MIB_SDR27_TX_RWP_FAIL_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR28(ext_phy));
mib->tx_rwp_need_cnt += FIELD_GET(MT_MIB_SDR28_TX_RWP_NEED_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR29(ext_phy));
mib->rx_pfdrop_cnt += FIELD_GET(MT_MIB_SDR29_RX_PFDROP_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR30(ext_phy));
mib->rx_vec_queue_overflow_drop_cnt +=
FIELD_GET(MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR31(ext_phy));
mib->rx_ba_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR32(ext_phy));
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR33(ext_phy));
mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR33_TX_PKT_IBF_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR34(ext_phy));
mib->tx_bf_cnt += FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt);
cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy));
mib->tx_mu_mpdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy));
mib->tx_mu_acked_mpdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));
mib->tx_su_acked_mpdu_cnt += cnt;
cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy));
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt);
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt);
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));
mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt);
mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt);
mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt);
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));
mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);
mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
mib->tx_amsdu[i] += cnt;
mib->tx_amsdu_cnt += cnt;
}
aggr0 = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) {
u32 val;
@ -1737,30 +2053,6 @@ mt7915_mac_update_stats(struct mt7915_phy *phy)
}
}
static void
mt7915_mac_sta_stats_work(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct mt7915_sta *msta;
LIST_HEAD(list);
spin_lock_bh(&dev->sta_poll_lock);
list_splice_init(&phy->stats_list, &list);
while (!list_empty(&list)) {
msta = list_first_entry(&list, struct mt7915_sta, stats_list);
list_del_init(&msta->stats_list);
spin_unlock_bh(&dev->sta_poll_lock);
/* use MT_TX_FREE_RATE to report Tx rate for further devices */
mt7915_mcu_get_tx_rate(dev, RATE_CTRL_RU_INFO, msta->wcid.idx);
spin_lock_bh(&dev->sta_poll_lock);
}
spin_unlock_bh(&dev->sta_poll_lock);
}
void mt7915_mac_sta_rc_work(struct work_struct *work)
{
struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work);
@ -1776,8 +2068,8 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
while (!list_empty(&list)) {
msta = list_first_entry(&list, struct mt7915_sta, rc_list);
list_del_init(&msta->rc_list);
changed = msta->stats.changed;
msta->stats.changed = 0;
changed = msta->changed;
msta->changed = 0;
spin_unlock_bh(&dev->sta_poll_lock);
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
@ -1817,14 +2109,9 @@ void mt7915_mac_work(struct work_struct *work)
mt7915_mac_update_stats(phy);
}
if (++phy->sta_work_count == 10) {
phy->sta_work_count = 0;
mt7915_mac_sta_stats_work(phy);
}
mutex_unlock(&mphy->dev->mutex);
mt76_tx_status_check(mphy->dev, NULL, false);
mt76_tx_status_check(mphy->dev, false);
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
MT7915_WATCHDOG_TIME);
@ -1961,3 +2248,182 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
mt7915_dfs_stop_radar_detector(phy);
return 0;
}
static int
mt7915_mac_twt_duration_align(int duration)
{
return duration << 8;
}
static u64
mt7915_mac_twt_sched_list_add(struct mt7915_dev *dev,
struct mt7915_twt_flow *flow)
{
struct mt7915_twt_flow *iter, *iter_next;
u32 duration = flow->duration << 8;
u64 start_tsf;
iter = list_first_entry_or_null(&dev->twt_list,
struct mt7915_twt_flow, list);
if (!iter || !iter->sched || iter->start_tsf > duration) {
/* add flow as first entry in the list */
list_add(&flow->list, &dev->twt_list);
return 0;
}
list_for_each_entry_safe(iter, iter_next, &dev->twt_list, list) {
start_tsf = iter->start_tsf +
mt7915_mac_twt_duration_align(iter->duration);
if (list_is_last(&iter->list, &dev->twt_list))
break;
if (!iter_next->sched ||
iter_next->start_tsf > start_tsf + duration) {
list_add(&flow->list, &iter->list);
goto out;
}
}
/* add flow as last entry in the list */
list_add_tail(&flow->list, &dev->twt_list);
out:
return start_tsf;
}
static int mt7915_mac_check_twt_req(struct ieee80211_twt_setup *twt)
{
struct ieee80211_twt_params *twt_agrt;
u64 interval, duration;
u16 mantissa;
u8 exp;
/* only individual agreement supported */
if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST)
return -EOPNOTSUPP;
/* only 256us unit supported */
if (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT)
return -EOPNOTSUPP;
twt_agrt = (struct ieee80211_twt_params *)twt->params;
/* explicit agreement not supported */
if (!(twt_agrt->req_type & cpu_to_le16(IEEE80211_TWT_REQTYPE_IMPLICIT)))
return -EOPNOTSUPP;
exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP,
le16_to_cpu(twt_agrt->req_type));
mantissa = le16_to_cpu(twt_agrt->mantissa);
duration = twt_agrt->min_twt_dur << 8;
interval = (u64)mantissa << exp;
if (interval < duration)
return -EOPNOTSUPP;
return 0;
}
void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct ieee80211_twt_setup *twt)
{
enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT;
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
u16 req_type = le16_to_cpu(twt_agrt->req_type);
enum ieee80211_twt_setup_cmd sta_setup_cmd;
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mt7915_twt_flow *flow;
int flowid, table_id;
u8 exp;
if (mt7915_mac_check_twt_req(twt))
goto out;
mutex_lock(&dev->mt76.mutex);
if (dev->twt.n_agrt == MT7915_MAX_TWT_AGRT)
goto unlock;
if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
goto unlock;
flowid = ffs(~msta->twt.flowid_mask) - 1;
le16p_replace_bits(&twt_agrt->req_type, flowid,
IEEE80211_TWT_REQTYPE_FLOWID);
table_id = ffs(~dev->twt.table_mask) - 1;
exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type);
sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type);
flow = &msta->twt.flow[flowid];
memset(flow, 0, sizeof(*flow));
INIT_LIST_HEAD(&flow->list);
flow->wcid = msta->wcid.idx;
flow->table_id = table_id;
flow->id = flowid;
flow->duration = twt_agrt->min_twt_dur;
flow->mantissa = twt_agrt->mantissa;
flow->exp = exp;
flow->protection = !!(req_type & IEEE80211_TWT_REQTYPE_PROTECTION);
flow->flowtype = !!(req_type & IEEE80211_TWT_REQTYPE_FLOWTYPE);
flow->trigger = !!(req_type & IEEE80211_TWT_REQTYPE_TRIGGER);
if (sta_setup_cmd == TWT_SETUP_CMD_REQUEST ||
sta_setup_cmd == TWT_SETUP_CMD_SUGGEST) {
u64 interval = (u64)le16_to_cpu(twt_agrt->mantissa) << exp;
u64 flow_tsf, curr_tsf;
u32 rem;
flow->sched = true;
flow->start_tsf = mt7915_mac_twt_sched_list_add(dev, flow);
curr_tsf = __mt7915_get_tsf(hw, msta->vif);
div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem);
flow_tsf = curr_tsf + interval - rem;
twt_agrt->twt = cpu_to_le64(flow_tsf);
} else {
list_add_tail(&flow->list, &dev->twt_list);
}
flow->tsf = le64_to_cpu(twt_agrt->twt);
if (mt7915_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD))
goto unlock;
setup_cmd = TWT_SETUP_CMD_ACCEPT;
dev->twt.table_mask |= BIT(table_id);
msta->twt.flowid_mask |= BIT(flowid);
dev->twt.n_agrt++;
unlock:
mutex_unlock(&dev->mt76.mutex);
out:
le16p_replace_bits(&twt_agrt->req_type, setup_cmd,
IEEE80211_TWT_REQTYPE_SETUP_CMD);
twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) |
(twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED);
}
void mt7915_mac_twt_teardown_flow(struct mt7915_dev *dev,
struct mt7915_sta *msta,
u8 flowid)
{
struct mt7915_twt_flow *flow;
lockdep_assert_held(&dev->mt76.mutex);
if (flowid >= ARRAY_SIZE(msta->twt.flow))
return;
if (!(msta->twt.flowid_mask & BIT(flowid)))
return;
flow = &msta->twt.flow[flowid];
if (mt7915_mcu_twt_agrt_update(dev, msta->vif, flow,
MCU_TWT_AGRT_DELETE))
return;
list_del_init(&flow->list);
msta->twt.flowid_mask &= ~BIT(flowid);
dev->twt.table_mask &= ~BIT(flow->table_id);
dev->twt.n_agrt--;
}

View File

@ -117,6 +117,7 @@ enum rx_pkt_type {
#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)
@ -133,7 +134,14 @@ enum rx_pkt_type {
#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)
@ -272,7 +280,8 @@ enum tx_mcu_port_q_idx {
#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)
/* VHT/HE only use bits 0-3 */
#define MT_TX_RATE_IDX GENMASK(5, 0)
#define MT_TXP_MAX_BUF_NUM 6

View File

@ -215,7 +215,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
mvif->phy = phy;
mvif->band_idx = ext_phy;
if (ext_phy)
if (dev->mt76.phy2)
mvif->wmm_idx = ext_phy * (MT7915_MAX_WMM_SETS / 2) +
mvif->idx % (MT7915_MAX_WMM_SETS / 2);
else
@ -231,12 +231,13 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
idx = MT7915_WTBL_RESERVED - mvif->idx;
INIT_LIST_HEAD(&mvif->sta.rc_list);
INIT_LIST_HEAD(&mvif->sta.stats_list);
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.ext_phy = mvif->band_idx;
mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
mt76_packet_id_init(&mvif->sta.wcid);
mt7915_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@ -252,6 +253,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
mt7915_init_bitrate_mask(vif);
memset(&mvif->cap, -1, sizeof(mvif->cap));
out:
mutex_unlock(&dev->mt76.mutex);
@ -291,6 +293,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
}
static void mt7915_init_dfs_state(struct mt7915_phy *phy)
@ -538,6 +542,29 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
mutex_unlock(&dev->mt76.mutex);
}
static void
mt7915_update_bss_color(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_he_bss_color *bss_color)
{
struct mt7915_dev *dev = mt7915_hw_dev(hw);
switch (vif->type) {
case NL80211_IFTYPE_AP: {
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
if (mvif->omac_idx > HW_BSSID_MAX)
return;
fallthrough;
}
case NL80211_IFTYPE_STATION:
mt7915_mcu_update_bss_color(dev, vif, bss_color);
break;
default:
break;
}
}
static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
@ -586,6 +613,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_HE_OBSS_PD)
mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
if (changed & BSS_CHANGED_HE_BSS_COLOR)
mt7915_update_bss_color(hw, vif, &info->he_bss_color);
if (changed & (BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED))
mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
@ -613,19 +643,18 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
int ret, idx;
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA - 1);
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
if (idx < 0)
return -ENOSPC;
INIT_LIST_HEAD(&msta->rc_list);
INIT_LIST_HEAD(&msta->stats_list);
INIT_LIST_HEAD(&msta->poll_list);
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
msta->wcid.ext_phy = mvif->band_idx;
msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
msta->stats.jiffies = jiffies;
msta->jiffies = jiffies;
mt7915_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@ -634,7 +663,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (ret)
return ret;
return mt7915_mcu_add_sta_adv(dev, vif, sta, true);
return mt7915_mcu_add_rate_ctrl(dev, vif, sta);
}
void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
@ -642,18 +671,19 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
int i;
mt7915_mcu_add_sta_adv(dev, vif, sta, false);
mt7915_mcu_add_sta(dev, vif, sta, false);
mt7915_mac_wtbl_update(dev, msta->wcid.idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
mt7915_mac_twt_teardown_flow(dev, msta, i);
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
if (!list_empty(&msta->stats_list))
list_del_init(&msta->stats_list);
if (!list_empty(&msta->rc_list))
list_del_init(&msta->rc_list);
spin_unlock_bh(&dev->sta_poll_lock);
@ -781,22 +811,19 @@ mt7915_get_stats(struct ieee80211_hw *hw,
struct mib_stats *mib = &phy->mib;
mutex_lock(&dev->mt76.mutex);
stats->dot11RTSSuccessCount = mib->rts_cnt;
stats->dot11RTSFailureCount = mib->rts_retries_cnt;
stats->dot11FCSErrorCount = mib->fcs_err_cnt;
stats->dot11ACKFailureCount = mib->ack_fail_cnt;
memset(mib, 0, sizeof(*mib));
mutex_unlock(&dev->mt76.mutex);
return 0;
}
static u64
mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mt7915_phy *phy = mt7915_hw_phy(hw);
bool band = phy != &dev->phy;
@ -806,7 +833,7 @@ mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
} tsf;
u16 n;
mutex_lock(&dev->mt76.mutex);
lockdep_assert_held(&dev->mt76.mutex);
n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx;
/* TSF software read */
@ -815,9 +842,21 @@ mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band));
tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band));
return tsf.t64;
}
static u64
mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt7915_dev *dev = mt7915_hw_dev(hw);
u64 ret;
mutex_lock(&dev->mt76.mutex);
ret = __mt7915_get_tsf(hw, mvif);
mutex_unlock(&dev->mt76.mutex);
return tsf.t64;
return ret;
}
static void
@ -926,7 +965,7 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
{
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct mt7915_sta_stats *stats = &msta->stats;
struct rate_info *txrate = &msta->wcid.rate;
struct rate_info rxrate = {};
if (!mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) {
@ -934,20 +973,20 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
}
if (!stats->tx_rate.legacy && !stats->tx_rate.flags)
if (!txrate->legacy && !txrate->flags)
return;
if (stats->tx_rate.legacy) {
sinfo->txrate.legacy = stats->tx_rate.legacy;
if (txrate->legacy) {
sinfo->txrate.legacy = txrate->legacy;
} else {
sinfo->txrate.mcs = stats->tx_rate.mcs;
sinfo->txrate.nss = stats->tx_rate.nss;
sinfo->txrate.bw = stats->tx_rate.bw;
sinfo->txrate.he_gi = stats->tx_rate.he_gi;
sinfo->txrate.he_dcm = stats->tx_rate.he_dcm;
sinfo->txrate.he_ru_alloc = stats->tx_rate.he_ru_alloc;
sinfo->txrate.mcs = txrate->mcs;
sinfo->txrate.nss = txrate->nss;
sinfo->txrate.bw = txrate->bw;
sinfo->txrate.he_gi = txrate->he_gi;
sinfo->txrate.he_dcm = txrate->he_dcm;
sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;
}
sinfo->txrate.flags = stats->tx_rate.flags;
sinfo->txrate.flags = txrate->flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
@ -959,7 +998,7 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
u32 *changed = data;
spin_lock_bh(&dev->sta_poll_lock);
msta->stats.changed |= *changed;
msta->changed |= *changed;
if (list_empty(&msta->rc_list))
list_add_tail(&msta->rc_list, &dev->sta_rc_list);
spin_unlock_bh(&dev->sta_poll_lock);
@ -1032,6 +1071,240 @@ static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,
mt7915_mcu_sta_update_hdr_trans(dev, vif, sta);
}
static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx_ampdu_cnt",
"tx_stop_q_empty_cnt",
"tx_mpdu_attempts",
"tx_mpdu_success",
"tx_rwp_fail_cnt",
"tx_rwp_need_cnt",
"tx_pkt_ebf_cnt",
"tx_pkt_ibf_cnt",
"tx_ampdu_len:0-1",
"tx_ampdu_len:2-10",
"tx_ampdu_len:11-19",
"tx_ampdu_len:20-28",
"tx_ampdu_len:29-37",
"tx_ampdu_len:38-46",
"tx_ampdu_len:47-55",
"tx_ampdu_len:56-79",
"tx_ampdu_len:80-103",
"tx_ampdu_len:104-127",
"tx_ampdu_len:128-151",
"tx_ampdu_len:152-175",
"tx_ampdu_len:176-199",
"tx_ampdu_len:200-223",
"tx_ampdu_len:224-247",
"ba_miss_count",
"tx_beamformer_ppdu_iBF",
"tx_beamformer_ppdu_eBF",
"tx_beamformer_rx_feedback_all",
"tx_beamformer_rx_feedback_he",
"tx_beamformer_rx_feedback_vht",
"tx_beamformer_rx_feedback_ht",
"tx_beamformer_rx_feedback_bw", /* zero based idx: 20, 40, 80, 160 */
"tx_beamformer_rx_feedback_nc",
"tx_beamformer_rx_feedback_nr",
"tx_beamformee_ok_feedback_pkts",
"tx_beamformee_feedback_trig",
"tx_mu_beamforming",
"tx_mu_mpdu",
"tx_mu_successful_mpdu",
"tx_su_successful_mpdu",
"tx_msdu_pack_1",
"tx_msdu_pack_2",
"tx_msdu_pack_3",
"tx_msdu_pack_4",
"tx_msdu_pack_5",
"tx_msdu_pack_6",
"tx_msdu_pack_7",
"tx_msdu_pack_8",
/* rx counters */
"rx_fifo_full_cnt",
"rx_mpdu_cnt",
"channel_idle_cnt",
"rx_vector_mismatch_cnt",
"rx_delimiter_fail_cnt",
"rx_len_mismatch_cnt",
"rx_ampdu_cnt",
"rx_ampdu_bytes_cnt",
"rx_ampdu_valid_subframe_cnt",
"rx_ampdu_valid_subframe_b_cnt",
"rx_pfdrop_cnt",
"rx_vec_queue_overflow_drop_cnt",
"rx_ba_cnt",
/* per vif counters */
"v_tx_mode_cck",
"v_tx_mode_ofdm",
"v_tx_mode_ht",
"v_tx_mode_ht_gf",
"v_tx_mode_vht",
"v_tx_mode_he_su",
"v_tx_mode_he_ext_su",
"v_tx_mode_he_tb",
"v_tx_mode_he_mu",
"v_tx_bw_20",
"v_tx_bw_40",
"v_tx_bw_80",
"v_tx_bw_160",
"v_tx_mcs_0",
"v_tx_mcs_1",
"v_tx_mcs_2",
"v_tx_mcs_3",
"v_tx_mcs_4",
"v_tx_mcs_5",
"v_tx_mcs_6",
"v_tx_mcs_7",
"v_tx_mcs_8",
"v_tx_mcs_9",
"v_tx_mcs_10",
"v_tx_mcs_11",
};
#define MT7915_SSTATS_LEN ARRAY_SIZE(mt7915_gstrings_stats)
/* Ethtool related API */
static
void mt7915_get_et_strings(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 sset, u8 *data)
{
if (sset == ETH_SS_STATS)
memcpy(data, *mt7915_gstrings_stats,
sizeof(mt7915_gstrings_stats));
}
static
int mt7915_get_et_sset_count(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, int sset)
{
if (sset == ETH_SS_STATS)
return MT7915_SSTATS_LEN;
return 0;
}
static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
{
struct mt76_ethtool_worker_info *wi = wi_data;
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
if (msta->vif->idx != wi->idx)
return;
mt76_ethtool_worker(wi, &msta->stats);
}
static
void mt7915_get_et_stats(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ethtool_stats *stats, u64 *data)
{
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;
struct mt76_ethtool_worker_info wi = {
.data = data,
.idx = mvif->idx,
};
struct mib_stats *mib = &phy->mib;
/* See mt7915_ampdu_stat_read_phy, etc */
bool ext_phy = phy != &dev->phy;
int i, n, ei = 0;
mutex_lock(&dev->mt76.mutex);
mt7915_mac_update_stats(phy);
data[ei++] = mib->tx_ampdu_cnt;
data[ei++] = mib->tx_stop_q_empty_cnt;
data[ei++] = mib->tx_mpdu_attempts_cnt;
data[ei++] = mib->tx_mpdu_success_cnt;
data[ei++] = mib->tx_rwp_fail_cnt;
data[ei++] = mib->tx_rwp_need_cnt;
data[ei++] = mib->tx_pkt_ebf_cnt;
data[ei++] = mib->tx_pkt_ibf_cnt;
/* Tx ampdu stat */
n = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++)
data[ei++] = dev->mt76.aggr_stats[i + n];
data[ei++] = phy->mib.ba_miss_cnt;
/* Tx Beamformer monitor */
data[ei++] = mib->tx_bf_ibf_ppdu_cnt;
data[ei++] = mib->tx_bf_ebf_ppdu_cnt;
/* Tx Beamformer Rx feedback monitor */
data[ei++] = mib->tx_bf_rx_fb_all_cnt;
data[ei++] = mib->tx_bf_rx_fb_he_cnt;
data[ei++] = mib->tx_bf_rx_fb_vht_cnt;
data[ei++] = mib->tx_bf_rx_fb_ht_cnt;
data[ei++] = mib->tx_bf_rx_fb_bw;
data[ei++] = mib->tx_bf_rx_fb_nc_cnt;
data[ei++] = mib->tx_bf_rx_fb_nr_cnt;
/* Tx Beamformee Rx NDPA & Tx feedback report */
data[ei++] = mib->tx_bf_fb_cpl_cnt;
data[ei++] = mib->tx_bf_fb_trig_cnt;
/* Tx SU & MU counters */
data[ei++] = mib->tx_bf_cnt;
data[ei++] = mib->tx_mu_mpdu_cnt;
data[ei++] = mib->tx_mu_acked_mpdu_cnt;
data[ei++] = mib->tx_su_acked_mpdu_cnt;
/* Tx amsdu info (pack-count histogram) */
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++)
data[ei++] = mib->tx_amsdu[i];
/* rx counters */
data[ei++] = mib->rx_fifo_full_cnt;
data[ei++] = mib->rx_mpdu_cnt;
data[ei++] = mib->channel_idle_cnt;
data[ei++] = mib->rx_vector_mismatch_cnt;
data[ei++] = mib->rx_delimiter_fail_cnt;
data[ei++] = mib->rx_len_mismatch_cnt;
data[ei++] = mib->rx_ampdu_cnt;
data[ei++] = mib->rx_ampdu_bytes_cnt;
data[ei++] = mib->rx_ampdu_valid_subframe_cnt;
data[ei++] = mib->rx_ampdu_valid_subframe_bytes_cnt;
data[ei++] = mib->rx_pfdrop_cnt;
data[ei++] = mib->rx_vec_queue_overflow_drop_cnt;
data[ei++] = mib->rx_ba_cnt;
/* Add values for all stations owned by this vif */
wi.initial_stat_idx = ei;
ieee80211_iterate_stations_atomic(hw, mt7915_ethtool_worker, &wi);
mutex_unlock(&dev->mt76.mutex);
if (wi.sta_count == 0)
return;
ei += wi.worker_stat_count;
if (ei != MT7915_SSTATS_LEN)
dev_err(dev->mt76.dev, "ei: %d MT7915_SSTATS_LEN: %d",
ei, (int)MT7915_SSTATS_LEN);
}
static void
mt7915_twt_teardown_request(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
u8 flowid)
{
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct mt7915_dev *dev = mt7915_hw_dev(hw);
mutex_lock(&dev->mt76.mutex);
mt7915_mac_twt_teardown_flow(dev, msta, flowid);
mutex_unlock(&dev->mt76.mutex);
}
const struct ieee80211_ops mt7915_ops = {
.tx = mt7915_tx,
.start = mt7915_start,
@ -1056,6 +1329,9 @@ const struct ieee80211_ops mt7915_ops = {
.get_txpower = mt76_get_txpower,
.channel_switch_beacon = mt7915_channel_switch_beacon,
.get_stats = mt7915_get_stats,
.get_et_sset_count = mt7915_get_et_sset_count,
.get_et_stats = mt7915_get_et_stats,
.get_et_strings = mt7915_get_et_strings,
.get_tsf = mt7915_get_tsf,
.set_tsf = mt7915_set_tsf,
.offset_tsf = mt7915_offset_tsf,
@ -1067,6 +1343,8 @@ const struct ieee80211_ops mt7915_ops = {
.sta_statistics = mt7915_sta_statistics,
.sta_set_4addr = mt7915_sta_set_4addr,
.sta_set_decap_offload = mt7915_sta_set_decap_offload,
.add_twt_setup = mt7915_mac_add_twt_setup,
.twt_teardown_request = mt7915_twt_teardown_request,
CFG80211_TESTMODE_CMD(mt76_testmode_cmd)
CFG80211_TESTMODE_DUMP(mt76_testmode_dump)
#ifdef CONFIG_MAC80211_DEBUGFS

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@ enum {
MCU_EXT_EVENT_ASSERT_DUMP = 0x23,
MCU_EXT_EVENT_RDD_REPORT = 0x3a,
MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
MCU_EXT_EVENT_RATE_REPORT = 0x87,
MCU_EXT_EVENT_BCC_NOTIFY = 0x75,
};
enum {
@ -164,41 +164,6 @@ struct mt7915_mcu_eeprom_info {
u8 data[16];
} __packed;
struct mt7915_mcu_ra_info {
struct mt7915_mcu_rxd rxd;
__le32 event_id;
__le16 wlan_idx;
__le16 ru_idx;
__le16 direction;
__le16 dump_group;
__le32 suggest_rate;
__le32 min_rate; /* for dynamic sounding */
__le32 max_rate; /* for dynamic sounding */
__le32 init_rate_down_rate;
__le16 curr_rate;
__le16 init_rate_down_total;
__le16 init_rate_down_succ;
__le16 success;
__le16 attempts;
__le16 prev_rate;
__le16 prob_up_rate;
u8 no_rate_up_cnt;
u8 ppdu_cnt;
u8 gi;
u8 try_up_fail;
u8 try_up_total;
u8 suggest_wf;
u8 try_up_check;
u8 prob_up_period;
u8 prob_down_pending;
} __packed;
struct mt7915_mcu_phy_rx_info {
u8 category;
u8 rate;
@ -210,12 +175,6 @@ struct mt7915_mcu_phy_rx_info {
u8 bw;
};
#define MT_RA_RATE_NSS GENMASK(8, 6)
#define MT_RA_RATE_MCS GENMASK(3, 0)
#define MT_RA_RATE_TX_MODE GENMASK(12, 9)
#define MT_RA_RATE_DCM_EN BIT(4)
#define MT_RA_RATE_BW GENMASK(14, 13)
struct mt7915_mcu_mib {
__le32 band;
__le32 offs;
@ -312,21 +271,31 @@ enum {
MCU_EXT_CMD_MAC_INIT_CTRL = 0x46,
MCU_EXT_CMD_RX_HDR_TRANS = 0x47,
MCU_EXT_CMD_MUAR_UPDATE = 0x48,
MCU_EXT_CMD_RX_AIRTIME_CTRL = 0x4a,
MCU_EXT_CMD_SET_RX_PATH = 0x4e,
MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
MCU_EXT_CMD_GET_MIB_INFO = 0x5a,
MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
MCU_EXT_CMD_SET_SER_TRIGGER = 0x81,
MCU_EXT_CMD_SCS_CTRL = 0x82,
MCU_EXT_CMD_RATE_CTRL = 0x87,
MCU_EXT_CMD_TWT_AGRT_UPDATE = 0x94,
MCU_EXT_CMD_FW_DBG_CTRL = 0x95,
MCU_EXT_CMD_SET_RDD_TH = 0x9d,
MCU_EXT_CMD_MURU_CTRL = 0x9f,
MCU_EXT_CMD_SET_SPR = 0xa8,
MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab,
MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac,
MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
};
enum {
MCU_TWT_AGRT_ADD,
MCU_TWT_AGRT_MODIFY,
MCU_TWT_AGRT_DELETE,
MCU_TWT_AGRT_TEARDOWN,
MCU_TWT_AGRT_GET_TSF,
};
enum {
MCU_WA_PARAM_CMD_QUERY,
MCU_WA_PARAM_CMD_SET,
@ -545,6 +514,14 @@ struct bss_info_hw_amsdu {
u8 rsv;
} __packed;
struct bss_info_color {
__le16 tag;
__le16 len;
u8 disable;
u8 color;
u8 rsv[2];
} __packed;
struct bss_info_he {
__le16 tag;
__le16 len;
@ -563,14 +540,7 @@ struct bss_info_bcn {
__le16 sub_ntlv;
} __packed __aligned(4);
struct bss_info_bcn_csa {
__le16 tag;
__le16 len;
u8 cnt;
u8 rsv[3];
} __packed __aligned(4);
struct bss_info_bcn_bcc {
struct bss_info_bcn_cntdwn {
__le16 tag;
__le16 len;
u8 cnt;
@ -716,6 +686,7 @@ struct wtbl_ba {
__le16 sn;
u8 ba_en;
u8 ba_winsize_idx;
/* originator & recipient */
__le16 ba_winsize;
/* recipient only */
u8 peer_addr[ETH_ALEN];
@ -989,6 +960,7 @@ struct sta_rec_ra_fixed {
#define RATE_CFG_STBC GENMASK(19, 16)
#define RATE_CFG_LDPC GENMASK(23, 20)
#define RATE_CFG_PHY_TYPE GENMASK(27, 24)
#define RATE_CFG_HE_LTF GENMASK(31, 28)
struct sta_rec_bf {
__le16 tag;
@ -1002,8 +974,8 @@ struct sta_rec_bf {
u8 ndp_rate;
u8 rept_poll_rate;
u8 tx_mode; /* 0: legacy, 1: OFDM, 2: HT, 4: VHT ... */
u8 nc;
u8 nr;
u8 ncol;
u8 nrow;
u8 bw; /* 0: 20M, 1: 40M, 2: 80M, 3: 160M */
u8 mem_total;
@ -1023,8 +995,8 @@ struct sta_rec_bf {
u8 ibf_dbw;
u8 ibf_ncol;
u8 ibf_nrow;
u8 nr_bw160;
u8 nc_bw160;
u8 nrow_bw160;
u8 ncol_bw160;
u8 ru_start_idx;
u8 ru_end_idx;
@ -1036,7 +1008,7 @@ struct sta_rec_bf {
bool codebook75_mu;
u8 he_ltf;
u8 rsv[2];
u8 rsv[3];
} __packed;
struct sta_rec_bfee {
@ -1115,17 +1087,22 @@ enum {
THERMAL_PROTECT_STATE_ACT,
};
enum {
MT_EBF = BIT(0), /* explicit beamforming */
MT_IBF = BIT(1) /* implicit beamforming */
};
enum {
MT_BF_SOUNDING_ON = 1,
MT_BF_TYPE_UPDATE = 20,
MT_BF_MODULE_UPDATE = 25
};
enum {
MURU_SET_ARB_OP_MODE = 14,
MURU_SET_PLATFORM_TYPE = 25,
};
enum {
MURU_PLATFORM_TYPE_PERF_LEVEL_1 = 1,
MURU_PLATFORM_TYPE_PERF_LEVEL_2,
};
#define MT7915_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_generic) + \
sizeof(struct wtbl_rx) + \
@ -1137,12 +1114,15 @@ enum {
#define MT7915_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct sta_rec_basic) + \
sizeof(struct sta_rec_bf) + \
sizeof(struct sta_rec_ht) + \
sizeof(struct sta_rec_he) + \
sizeof(struct sta_rec_ba) + \
sizeof(struct sta_rec_vht) + \
sizeof(struct sta_rec_uapsd) + \
sizeof(struct sta_rec_amsdu) + \
sizeof(struct sta_rec_muru) + \
sizeof(struct sta_rec_bfee) + \
sizeof(struct tlv) + \
MT7915_WTBL_UPDATE_MAX_SIZE)
@ -1157,8 +1137,7 @@ enum {
sizeof(struct bss_info_ext_bss))
#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct bss_info_bcn_csa) + \
sizeof(struct bss_info_bcn_bcc) + \
sizeof(struct bss_info_bcn_cntdwn) + \
sizeof(struct bss_info_bcn_mbss) + \
sizeof(struct bss_info_bcn_cont))

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