mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
wireless-next patches for 6.4
Major changes:
cfg80211
* 6 GHz improvements
* HW timestamping support
* support for randomized auth/deauth TA for PASN privacy
(also for mac80211)
mac80211
* radiotap TLV and EHT support for the iwlwifi sniffer
* HW timestamping support
* per-link debugfs for multi-link
brcmfmac
* support for Apple (M1 Pro/Max) devices
iwlwifi
* support for a few new devices
* EHT sniffer support
rtw88
* better support for some SDIO devices
(e.g. MAC address from efuse)
rtw89
* HW scan support for 8852b
* better support for 6 GHz scanning
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmQLG7oACgkQ10qiO8sP
aAAqsBAAmiGDd9CDToWmXiyf3Qwv7eazNtqqz5LUKbSnmAXyyDDpHR28A8DlsEU0
OTlrQK0yQr3R4sUhLVY+tL49gZvgqp0B9pj7NqnK3HIOniFdfpZdTXdFNdx3KuEs
k1c/D+wGAIhVHP8csIKhh49KpGFa4U2YMXCUx4mNrUQKGhO+b/XbiMKS8jmoQAF9
1GQk/KcGblBmuKFWE1euSScyBh2CvvcJq+F9f25eiX/+OgVXNYWWfAHfr3jjX7RG
lSdlMvKvF4LImCW0vnhmFUeSSl+GpszNXwaqIh6OGLrw2CBZDcujGTT88cOw3A1t
JFTB3EgeuFL3fDHQogWFxQ/RhfZB/tHeBYEQSx+1WizHKtJEMY2pvjuj9rZ7TEWy
HHFfP1OaU1tbqMIkkhchAhOyciVJpk77Cl6yO0TcpRLt9VR1LvACMAd3/3eqfQGf
gJxS8x7qWHp3pSWTNa3X8Q2NPatstKz/LUO0JMQP690/sRwdta9RwR11CYm0/Mdb
22TwOSa6lfAlOF/l/YkEy39U8J1XNxPschkdAz4h001N88h8dAf6UZieDqqPYZFK
4sYsGLqtACEU5W/Y5PG7v3/ZZ+QtEtfWU057tEtvHkVws2BKvRRQ3c0DBG5QTVG0
4k9QU6mxKxL/R2Nkf6+rB8lvQkHEyXp6voF3LmqRlB/gnh1FKY0=
=sPir
-----END PGP SIGNATURE-----
Merge tag 'wireless-next-2023-03-10' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Johannes Berg says:
====================
wireless-next patches for 6.4
Major changes:
cfg80211
* 6 GHz improvements
* HW timestamping support
* support for randomized auth/deauth TA for PASN privacy
(also for mac80211)
mac80211
* radiotap TLV and EHT support for the iwlwifi sniffer
* HW timestamping support
* per-link debugfs for multi-link
brcmfmac
* support for Apple (M1 Pro/Max) devices
iwlwifi
* support for a few new devices
* EHT sniffer support
rtw88
* better support for some SDIO devices
(e.g. MAC address from efuse)
rtw89
* HW scan support for 8852b
* better support for 6 GHz scanning
* tag 'wireless-next-2023-03-10' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (84 commits)
wifi: iwlwifi: mvm: fix EOF bit reporting
wifi: iwlwifi: Do not include radiotap EHT user info if not needed
wifi: iwlwifi: mvm: add EHT RU allocation to radiotap
wifi: iwlwifi: Update logs for yoyo reset sw changes
wifi: iwlwifi: mvm: clean up duplicated defines
wifi: iwlwifi: rs-fw: break out for unsupported bandwidth
wifi: iwlwifi: Add support for B step of BnJ-Fm4
wifi: iwlwifi: mvm: make flush code a bit clearer
wifi: iwlwifi: mvm: avoid UB shift of snif_queue
wifi: iwlwifi: mvm: add primary 80 known for EHT radiotap
wifi: iwlwifi: mvm: parse FW frame metadata for EHT sniffer mode
wifi: iwlwifi: mvm: decode USIG_B1_B7 RU to nl80211 RU width
wifi: iwlwifi: mvm: rename define to generic name
wifi: iwlwifi: mvm: allow Microsoft to use TAS
wifi: iwlwifi: mvm: add all EHT based on data0 info from HW
wifi: iwlwifi: mvm: add EHT radiotap info based on rate_n_flags
wifi: iwlwifi: mvm: add an helper function radiotap TLVs
wifi: radiotap: separate vendor TLV into header/content
wifi: iwlwifi: reduce verbosity of some logging events
wifi: iwlwifi: Adding the code to get RF name for MsP device
...
====================
Link: https://lore.kernel.org/r/20230310120159.36518-1-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
2af560e5a5
|
|
@ -48,6 +48,8 @@ brcmfmac-$(CONFIG_OF) += \
|
|||
of.o
|
||||
brcmfmac-$(CONFIG_DMI) += \
|
||||
dmi.o
|
||||
brcmfmac-$(CONFIG_ACPI) += \
|
||||
acpi.o
|
||||
|
||||
ifeq ($(CONFIG_BRCMFMAC),m)
|
||||
obj-m += wcc/
|
||||
|
|
|
|||
51
drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c
Normal file
51
drivers/net/wireless/broadcom/brcm80211/brcmfmac/acpi.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/*
|
||||
* Copyright The Asahi Linux Contributors
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include "debug.h"
|
||||
#include "core.h"
|
||||
#include "common.h"
|
||||
|
||||
void brcmf_acpi_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
||||
struct brcmf_mp_device *settings)
|
||||
{
|
||||
acpi_status status;
|
||||
const union acpi_object *o;
|
||||
struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
|
||||
if (!adev)
|
||||
return;
|
||||
|
||||
if (!ACPI_FAILURE(acpi_dev_get_property(adev, "module-instance",
|
||||
ACPI_TYPE_STRING, &o))) {
|
||||
brcmf_dbg(INFO, "ACPI module-instance=%s\n", o->string.pointer);
|
||||
settings->board_type = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"apple,%s",
|
||||
o->string.pointer);
|
||||
} else {
|
||||
brcmf_dbg(INFO, "No ACPI module-instance\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = acpi_evaluate_object(adev->handle, "RWCV", NULL, &buf);
|
||||
o = buf.pointer;
|
||||
if (!ACPI_FAILURE(status) && o && o->type == ACPI_TYPE_BUFFER &&
|
||||
o->buffer.length >= 2) {
|
||||
char *antenna_sku = devm_kzalloc(dev, 3, GFP_KERNEL);
|
||||
|
||||
if (antenna_sku) {
|
||||
memcpy(antenna_sku, o->buffer.pointer, 2);
|
||||
brcmf_dbg(INFO, "ACPI RWCV data=%*phN antenna-sku=%s\n",
|
||||
(int)o->buffer.length, o->buffer.pointer,
|
||||
antenna_sku);
|
||||
settings->antenna_sku = antenna_sku;
|
||||
}
|
||||
|
||||
kfree(buf.pointer);
|
||||
} else {
|
||||
brcmf_dbg(INFO, "No ACPI antenna-sku\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -55,6 +55,7 @@ enum brcmf_bus_protocol_type {
|
|||
/* Firmware blobs that may be available */
|
||||
enum brcmf_blob_type {
|
||||
BRCMF_BLOB_CLM,
|
||||
BRCMF_BLOB_TXCAP,
|
||||
};
|
||||
|
||||
struct brcmf_mp_device;
|
||||
|
|
|
|||
|
|
@ -1039,12 +1039,134 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
|
|||
}
|
||||
}
|
||||
|
||||
static void brcmf_scan_params_v2_to_v1(struct brcmf_scan_params_v2_le *params_v2_le,
|
||||
struct brcmf_scan_params_le *params_le)
|
||||
{
|
||||
size_t params_size;
|
||||
u32 ch;
|
||||
int n_channels, n_ssids;
|
||||
|
||||
memcpy(¶ms_le->ssid_le, ¶ms_v2_le->ssid_le,
|
||||
sizeof(params_le->ssid_le));
|
||||
memcpy(¶ms_le->bssid, ¶ms_v2_le->bssid,
|
||||
sizeof(params_le->bssid));
|
||||
|
||||
params_le->bss_type = params_v2_le->bss_type;
|
||||
params_le->scan_type = le32_to_cpu(params_v2_le->scan_type);
|
||||
params_le->nprobes = params_v2_le->nprobes;
|
||||
params_le->active_time = params_v2_le->active_time;
|
||||
params_le->passive_time = params_v2_le->passive_time;
|
||||
params_le->home_time = params_v2_le->home_time;
|
||||
params_le->channel_num = params_v2_le->channel_num;
|
||||
|
||||
ch = le32_to_cpu(params_v2_le->channel_num);
|
||||
n_channels = ch & BRCMF_SCAN_PARAMS_COUNT_MASK;
|
||||
n_ssids = ch >> BRCMF_SCAN_PARAMS_NSSID_SHIFT;
|
||||
|
||||
params_size = sizeof(u16) * n_channels;
|
||||
if (n_ssids > 0) {
|
||||
params_size = roundup(params_size, sizeof(u32));
|
||||
params_size += sizeof(struct brcmf_ssid_le) * n_ssids;
|
||||
}
|
||||
|
||||
memcpy(¶ms_le->channel_list[0],
|
||||
¶ms_v2_le->channel_list[0], params_size);
|
||||
}
|
||||
|
||||
static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_scan_params_v2_le *params_le,
|
||||
struct cfg80211_scan_request *request)
|
||||
{
|
||||
u32 n_ssids;
|
||||
u32 n_channels;
|
||||
s32 i;
|
||||
s32 offset;
|
||||
u16 chanspec;
|
||||
char *ptr;
|
||||
int length;
|
||||
struct brcmf_ssid_le ssid_le;
|
||||
|
||||
eth_broadcast_addr(params_le->bssid);
|
||||
|
||||
length = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
|
||||
|
||||
params_le->version = cpu_to_le16(BRCMF_SCAN_PARAMS_VERSION_V2);
|
||||
params_le->bss_type = DOT11_BSSTYPE_ANY;
|
||||
params_le->scan_type = cpu_to_le32(BRCMF_SCANTYPE_ACTIVE);
|
||||
params_le->channel_num = 0;
|
||||
params_le->nprobes = cpu_to_le32(-1);
|
||||
params_le->active_time = cpu_to_le32(-1);
|
||||
params_le->passive_time = cpu_to_le32(-1);
|
||||
params_le->home_time = cpu_to_le32(-1);
|
||||
memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le));
|
||||
|
||||
/* Scan abort */
|
||||
if (!request) {
|
||||
length += sizeof(u16);
|
||||
params_le->channel_num = cpu_to_le32(1);
|
||||
params_le->channel_list[0] = cpu_to_le16(-1);
|
||||
params_le->length = cpu_to_le16(length);
|
||||
return;
|
||||
}
|
||||
|
||||
n_ssids = request->n_ssids;
|
||||
n_channels = request->n_channels;
|
||||
|
||||
/* Copy channel array if applicable */
|
||||
brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
|
||||
n_channels);
|
||||
if (n_channels > 0) {
|
||||
length += roundup(sizeof(u16) * n_channels, sizeof(u32));
|
||||
for (i = 0; i < n_channels; i++) {
|
||||
chanspec = channel_to_chanspec(&cfg->d11inf,
|
||||
request->channels[i]);
|
||||
brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
|
||||
request->channels[i]->hw_value, chanspec);
|
||||
params_le->channel_list[i] = cpu_to_le16(chanspec);
|
||||
}
|
||||
} else {
|
||||
brcmf_dbg(SCAN, "Scanning all channels\n");
|
||||
}
|
||||
|
||||
/* Copy ssid array if applicable */
|
||||
brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);
|
||||
if (n_ssids > 0) {
|
||||
offset = offsetof(struct brcmf_scan_params_v2_le, channel_list) +
|
||||
n_channels * sizeof(u16);
|
||||
offset = roundup(offset, sizeof(u32));
|
||||
length += sizeof(ssid_le) * n_ssids,
|
||||
ptr = (char *)params_le + offset;
|
||||
for (i = 0; i < n_ssids; i++) {
|
||||
memset(&ssid_le, 0, sizeof(ssid_le));
|
||||
ssid_le.SSID_len =
|
||||
cpu_to_le32(request->ssids[i].ssid_len);
|
||||
memcpy(ssid_le.SSID, request->ssids[i].ssid,
|
||||
request->ssids[i].ssid_len);
|
||||
if (!ssid_le.SSID_len)
|
||||
brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
|
||||
else
|
||||
brcmf_dbg(SCAN, "%d: scan for %.32s size=%d\n",
|
||||
i, ssid_le.SSID, ssid_le.SSID_len);
|
||||
memcpy(ptr, &ssid_le, sizeof(ssid_le));
|
||||
ptr += sizeof(ssid_le);
|
||||
}
|
||||
} else {
|
||||
brcmf_dbg(SCAN, "Performing passive scan\n");
|
||||
params_le->scan_type = cpu_to_le32(BRCMF_SCANTYPE_PASSIVE);
|
||||
}
|
||||
params_le->length = cpu_to_le16(length);
|
||||
/* Adding mask to channel numbers */
|
||||
params_le->channel_num =
|
||||
cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
|
||||
(n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
|
||||
}
|
||||
|
||||
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_if *ifp, bool aborted,
|
||||
bool fw_abort)
|
||||
{
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
struct brcmf_scan_params_le params_le;
|
||||
struct brcmf_scan_params_v2_le params_v2_le;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
u64 reqid;
|
||||
u32 bucket;
|
||||
|
|
@ -1063,20 +1185,23 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
|||
if (fw_abort) {
|
||||
/* Do a scan abort to stop the driver's scan engine */
|
||||
brcmf_dbg(SCAN, "ABORT scan in firmware\n");
|
||||
memset(¶ms_le, 0, sizeof(params_le));
|
||||
eth_broadcast_addr(params_le.bssid);
|
||||
params_le.bss_type = DOT11_BSSTYPE_ANY;
|
||||
params_le.scan_type = 0;
|
||||
params_le.channel_num = cpu_to_le32(1);
|
||||
params_le.nprobes = cpu_to_le32(1);
|
||||
params_le.active_time = cpu_to_le32(-1);
|
||||
params_le.passive_time = cpu_to_le32(-1);
|
||||
params_le.home_time = cpu_to_le32(-1);
|
||||
/* Scan is aborted by setting channel_list[0] to -1 */
|
||||
params_le.channel_list[0] = cpu_to_le16(-1);
|
||||
|
||||
brcmf_escan_prep(cfg, ¶ms_v2_le, NULL);
|
||||
|
||||
/* E-Scan (or anyother type) can be aborted by SCAN */
|
||||
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
|
||||
¶ms_le, sizeof(params_le));
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {
|
||||
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
|
||||
¶ms_v2_le,
|
||||
sizeof(params_v2_le));
|
||||
} else {
|
||||
struct brcmf_scan_params_le params_le;
|
||||
|
||||
brcmf_scan_params_v2_to_v1(¶ms_v2_le, ¶ms_le);
|
||||
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
|
||||
¶ms_le,
|
||||
sizeof(params_le));
|
||||
}
|
||||
|
||||
if (err)
|
||||
bphy_err(drvr, "Scan abort failed\n");
|
||||
}
|
||||
|
|
@ -1295,83 +1420,13 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_scan_params_le *params_le,
|
||||
struct cfg80211_scan_request *request)
|
||||
{
|
||||
u32 n_ssids;
|
||||
u32 n_channels;
|
||||
s32 i;
|
||||
s32 offset;
|
||||
u16 chanspec;
|
||||
char *ptr;
|
||||
struct brcmf_ssid_le ssid_le;
|
||||
|
||||
eth_broadcast_addr(params_le->bssid);
|
||||
params_le->bss_type = DOT11_BSSTYPE_ANY;
|
||||
params_le->scan_type = BRCMF_SCANTYPE_ACTIVE;
|
||||
params_le->channel_num = 0;
|
||||
params_le->nprobes = cpu_to_le32(-1);
|
||||
params_le->active_time = cpu_to_le32(-1);
|
||||
params_le->passive_time = cpu_to_le32(-1);
|
||||
params_le->home_time = cpu_to_le32(-1);
|
||||
memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le));
|
||||
|
||||
n_ssids = request->n_ssids;
|
||||
n_channels = request->n_channels;
|
||||
|
||||
/* Copy channel array if applicable */
|
||||
brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
|
||||
n_channels);
|
||||
if (n_channels > 0) {
|
||||
for (i = 0; i < n_channels; i++) {
|
||||
chanspec = channel_to_chanspec(&cfg->d11inf,
|
||||
request->channels[i]);
|
||||
brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
|
||||
request->channels[i]->hw_value, chanspec);
|
||||
params_le->channel_list[i] = cpu_to_le16(chanspec);
|
||||
}
|
||||
} else {
|
||||
brcmf_dbg(SCAN, "Scanning all channels\n");
|
||||
}
|
||||
/* Copy ssid array if applicable */
|
||||
brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);
|
||||
if (n_ssids > 0) {
|
||||
offset = offsetof(struct brcmf_scan_params_le, channel_list) +
|
||||
n_channels * sizeof(u16);
|
||||
offset = roundup(offset, sizeof(u32));
|
||||
ptr = (char *)params_le + offset;
|
||||
for (i = 0; i < n_ssids; i++) {
|
||||
memset(&ssid_le, 0, sizeof(ssid_le));
|
||||
ssid_le.SSID_len =
|
||||
cpu_to_le32(request->ssids[i].ssid_len);
|
||||
memcpy(ssid_le.SSID, request->ssids[i].ssid,
|
||||
request->ssids[i].ssid_len);
|
||||
if (!ssid_le.SSID_len)
|
||||
brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
|
||||
else
|
||||
brcmf_dbg(SCAN, "%d: scan for %.32s size=%d\n",
|
||||
i, ssid_le.SSID, ssid_le.SSID_len);
|
||||
memcpy(ptr, &ssid_le, sizeof(ssid_le));
|
||||
ptr += sizeof(ssid_le);
|
||||
}
|
||||
} else {
|
||||
brcmf_dbg(SCAN, "Performing passive scan\n");
|
||||
params_le->scan_type = BRCMF_SCANTYPE_PASSIVE;
|
||||
}
|
||||
/* Adding mask to channel numbers */
|
||||
params_le->channel_num =
|
||||
cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
|
||||
(n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
|
||||
struct cfg80211_scan_request *request)
|
||||
{
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
|
||||
offsetof(struct brcmf_escan_params_le, params_le);
|
||||
s32 params_size = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE +
|
||||
offsetof(struct brcmf_escan_params_le, params_v2_le);
|
||||
struct brcmf_escan_params_le *params;
|
||||
s32 err = 0;
|
||||
|
||||
|
|
@ -1391,8 +1446,22 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
|
|||
goto exit;
|
||||
}
|
||||
BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
|
||||
brcmf_escan_prep(cfg, ¶ms->params_le, request);
|
||||
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
|
||||
brcmf_escan_prep(cfg, ¶ms->params_v2_le, request);
|
||||
|
||||
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION_V2);
|
||||
|
||||
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {
|
||||
struct brcmf_escan_params_le *params_v1;
|
||||
|
||||
params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
|
||||
params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE;
|
||||
params_v1 = kzalloc(params_size, GFP_KERNEL);
|
||||
params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
|
||||
brcmf_scan_params_v2_to_v1(¶ms->params_v2_le, ¶ms_v1->params_le);
|
||||
kfree(params);
|
||||
params = params_v1;
|
||||
}
|
||||
|
||||
params->action = cpu_to_le16(WL_ESCAN_ACTION_START);
|
||||
params->sync_id = cpu_to_le16(0x1234);
|
||||
|
||||
|
|
@ -1617,13 +1686,14 @@ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
|
|||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct brcmf_wsec_pmk_le pmk;
|
||||
int i, err;
|
||||
int err;
|
||||
|
||||
/* convert to firmware key format */
|
||||
pmk.key_len = cpu_to_le16(pmk_len << 1);
|
||||
pmk.flags = cpu_to_le16(BRCMF_WSEC_PASSPHRASE);
|
||||
for (i = 0; i < pmk_len; i++)
|
||||
snprintf(&pmk.key[2 * i], 3, "%02x", pmk_data[i]);
|
||||
memset(&pmk, 0, sizeof(pmk));
|
||||
|
||||
/* pass pmk directly */
|
||||
pmk.key_len = cpu_to_le16(pmk_len);
|
||||
pmk.flags = cpu_to_le16(0);
|
||||
memcpy(pmk.key, pmk_data, pmk_len);
|
||||
|
||||
/* store psk in firmware */
|
||||
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,
|
||||
|
|
@ -4237,6 +4307,37 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa,
|
||||
bool alive)
|
||||
{
|
||||
struct brcmf_pmk_op_v3_le *pmk_op;
|
||||
int length = offsetof(struct brcmf_pmk_op_v3_le, pmk);
|
||||
int ret;
|
||||
|
||||
pmk_op = kzalloc(sizeof(*pmk_op), GFP_KERNEL);
|
||||
pmk_op->version = cpu_to_le16(BRCMF_PMKSA_VER_3);
|
||||
|
||||
if (!pmksa) {
|
||||
/* Flush operation, operate on entire list */
|
||||
pmk_op->count = cpu_to_le16(0);
|
||||
} else {
|
||||
/* Single PMK operation */
|
||||
pmk_op->count = cpu_to_le16(1);
|
||||
length += sizeof(struct brcmf_pmksa_v3);
|
||||
memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN);
|
||||
memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
|
||||
pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN;
|
||||
pmk_op->pmk[0].time_left = cpu_to_le32(alive ? BRCMF_PMKSA_NO_EXPIRY : 0);
|
||||
}
|
||||
|
||||
pmk_op->length = cpu_to_le16(length);
|
||||
|
||||
ret = brcmf_fil_iovar_data_set(ifp, "pmkid_info", pmk_op, sizeof(*pmk_op));
|
||||
kfree(pmk_op);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __used s32
|
||||
brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)
|
||||
{
|
||||
|
|
@ -4270,6 +4371,14 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
|
|||
if (!check_vif_up(ifp->vif))
|
||||
return -EIO;
|
||||
|
||||
brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmksa->bssid);
|
||||
brcmf_dbg(CONN, "%*ph\n", WLAN_PMKID_LEN, pmksa->pmkid);
|
||||
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))
|
||||
return brcmf_pmksa_v3_op(ifp, pmksa, true);
|
||||
|
||||
/* TODO: implement PMKID_V2 */
|
||||
|
||||
npmk = le32_to_cpu(cfg->pmk_list.npmk);
|
||||
for (i = 0; i < npmk; i++)
|
||||
if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
|
||||
|
|
@ -4286,9 +4395,6 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmk[npmk].bssid);
|
||||
brcmf_dbg(CONN, "%*ph\n", WLAN_PMKID_LEN, pmk[npmk].pmkid);
|
||||
|
||||
err = brcmf_update_pmklist(cfg, ifp);
|
||||
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
|
|
@ -4312,6 +4418,11 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
|
|||
|
||||
brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", pmksa->bssid);
|
||||
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))
|
||||
return brcmf_pmksa_v3_op(ifp, pmksa, false);
|
||||
|
||||
/* TODO: implement PMKID_V2 */
|
||||
|
||||
npmk = le32_to_cpu(cfg->pmk_list.npmk);
|
||||
for (i = 0; i < npmk; i++)
|
||||
if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
|
||||
|
|
@ -4348,6 +4459,11 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
|
|||
if (!check_vif_up(ifp->vif))
|
||||
return -EIO;
|
||||
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))
|
||||
return brcmf_pmksa_v3_op(ifp, NULL, false);
|
||||
|
||||
/* TODO: implement PMKID_V2 */
|
||||
|
||||
memset(&cfg->pmk_list, 0, sizeof(cfg->pmk_list));
|
||||
err = brcmf_update_pmklist(cfg, ifp);
|
||||
|
||||
|
|
@ -6489,18 +6605,20 @@ static s32 brcmf_notify_rssi(struct brcmf_if *ifp,
|
|||
{
|
||||
struct brcmf_cfg80211_vif *vif = ifp->vif;
|
||||
struct brcmf_rssi_be *info = data;
|
||||
s32 rssi, snr, noise;
|
||||
s32 rssi, snr = 0, noise = 0;
|
||||
s32 low, high, last;
|
||||
|
||||
if (e->datalen < sizeof(*info)) {
|
||||
if (e->datalen >= sizeof(*info)) {
|
||||
rssi = be32_to_cpu(info->rssi);
|
||||
snr = be32_to_cpu(info->snr);
|
||||
noise = be32_to_cpu(info->noise);
|
||||
} else if (e->datalen >= sizeof(rssi)) {
|
||||
rssi = be32_to_cpu(*(__be32 *)data);
|
||||
} else {
|
||||
brcmf_err("insufficient RSSI event data\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rssi = be32_to_cpu(info->rssi);
|
||||
snr = be32_to_cpu(info->snr);
|
||||
noise = be32_to_cpu(info->noise);
|
||||
|
||||
low = vif->cqm_rssi_low;
|
||||
high = vif->cqm_rssi_high;
|
||||
last = vif->cqm_rssi_last;
|
||||
|
|
|
|||
|
|
@ -212,8 +212,9 @@ struct sbsocramregs {
|
|||
#define ARMCR4_TCBANB_MASK 0xf
|
||||
#define ARMCR4_TCBANB_SHIFT 0
|
||||
|
||||
#define ARMCR4_BSZ_MASK 0x3f
|
||||
#define ARMCR4_BSZ_MASK 0x7f
|
||||
#define ARMCR4_BSZ_MULT 8192
|
||||
#define ARMCR4_BLK_1K_MASK 0x200
|
||||
|
||||
struct brcmf_core_priv {
|
||||
struct brcmf_core pub;
|
||||
|
|
@ -684,6 +685,7 @@ static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
|
|||
u32 nbb;
|
||||
u32 totb;
|
||||
u32 bxinfo;
|
||||
u32 blksize;
|
||||
u32 idx;
|
||||
|
||||
corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP);
|
||||
|
|
@ -695,7 +697,11 @@ static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
|
|||
for (idx = 0; idx < totb; idx++) {
|
||||
brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx);
|
||||
bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO);
|
||||
memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
|
||||
blksize = ARMCR4_BSZ_MULT;
|
||||
if (bxinfo & ARMCR4_BLK_1K_MASK)
|
||||
blksize >>= 3;
|
||||
|
||||
memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * blksize;
|
||||
}
|
||||
|
||||
return memsize;
|
||||
|
|
@ -737,6 +743,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
|
|||
return 0x170000;
|
||||
case BRCM_CC_4378_CHIP_ID:
|
||||
return 0x352000;
|
||||
case BRCM_CC_4387_CHIP_ID:
|
||||
return 0x740000;
|
||||
default:
|
||||
brcmf_err("unknown chip: %s\n", ci->pub.name);
|
||||
break;
|
||||
|
|
@ -1292,15 +1300,18 @@ static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip)
|
|||
static inline void
|
||||
brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip)
|
||||
{
|
||||
int i;
|
||||
struct brcmf_core *core;
|
||||
|
||||
brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
|
||||
|
||||
core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
|
||||
brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
|
||||
D11_BCMA_IOCTL_PHYCLOCKEN,
|
||||
D11_BCMA_IOCTL_PHYCLOCKEN,
|
||||
D11_BCMA_IOCTL_PHYCLOCKEN);
|
||||
/* Disable the cores only and let the firmware enable them.
|
||||
* Releasing reset ourselves breaks BCM4387 in weird ways.
|
||||
*/
|
||||
for (i = 0; (core = brcmf_chip_get_d11core(&chip->pub, i)); i++)
|
||||
brcmf_chip_coredisable(core, D11_BCMA_IOCTL_PHYRESET |
|
||||
D11_BCMA_IOCTL_PHYCLOCKEN,
|
||||
D11_BCMA_IOCTL_PHYCLOCKEN);
|
||||
}
|
||||
|
||||
static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
|
|||
|
||||
static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
|
||||
struct brcmf_dload_data_le *dload_buf,
|
||||
u32 len)
|
||||
u32 len, const char *var)
|
||||
{
|
||||
s32 err;
|
||||
|
||||
|
|
@ -111,18 +111,18 @@ static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
|
|||
dload_buf->len = cpu_to_le32(len);
|
||||
dload_buf->crc = cpu_to_le32(0);
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf,
|
||||
err = brcmf_fil_iovar_data_set(ifp, var, dload_buf,
|
||||
struct_size(dload_buf, data, len));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
||||
static int brcmf_c_download_blob(struct brcmf_if *ifp,
|
||||
const void *data, size_t size,
|
||||
const char *loadvar, const char *statvar)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct brcmf_bus *bus = drvr->bus_if;
|
||||
struct brcmf_dload_data_le *chunk_buf;
|
||||
const struct firmware *clm = NULL;
|
||||
u32 chunk_len;
|
||||
u32 datalen;
|
||||
u32 cumulative_len;
|
||||
|
|
@ -132,21 +132,14 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
|||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
err = brcmf_bus_get_blob(bus, &clm, BRCMF_BLOB_CLM);
|
||||
if (err || !clm) {
|
||||
brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
|
||||
err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
chunk_buf = kzalloc(struct_size(chunk_buf, data, MAX_CHUNK_LEN),
|
||||
GFP_KERNEL);
|
||||
if (!chunk_buf) {
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
datalen = clm->size;
|
||||
datalen = size;
|
||||
cumulative_len = 0;
|
||||
do {
|
||||
if (datalen > MAX_CHUNK_LEN) {
|
||||
|
|
@ -155,9 +148,10 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
|||
chunk_len = datalen;
|
||||
dl_flag |= DL_END;
|
||||
}
|
||||
memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len);
|
||||
memcpy(chunk_buf->data, data + cumulative_len, chunk_len);
|
||||
|
||||
err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len);
|
||||
err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len,
|
||||
loadvar);
|
||||
|
||||
dl_flag &= ~DL_BEGIN;
|
||||
|
||||
|
|
@ -166,20 +160,64 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
|||
} while ((datalen > 0) && (err == 0));
|
||||
|
||||
if (err) {
|
||||
bphy_err(drvr, "clmload (%zu byte file) failed (%d)\n",
|
||||
clm->size, err);
|
||||
/* Retrieve clmload_status and print */
|
||||
err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status);
|
||||
bphy_err(drvr, "%s (%zu byte file) failed (%d)\n",
|
||||
loadvar, size, err);
|
||||
/* Retrieve status and print */
|
||||
err = brcmf_fil_iovar_int_get(ifp, statvar, &status);
|
||||
if (err)
|
||||
bphy_err(drvr, "get clmload_status failed (%d)\n", err);
|
||||
bphy_err(drvr, "get %s failed (%d)\n", statvar, err);
|
||||
else
|
||||
brcmf_dbg(INFO, "clmload_status=%d\n", status);
|
||||
brcmf_dbg(INFO, "%s=%d\n", statvar, status);
|
||||
err = -EIO;
|
||||
}
|
||||
|
||||
kfree(chunk_buf);
|
||||
done:
|
||||
release_firmware(clm);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct brcmf_bus *bus = drvr->bus_if;
|
||||
const struct firmware *fw = NULL;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_CLM);
|
||||
if (err || !fw) {
|
||||
brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
|
||||
err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = brcmf_c_download_blob(ifp, fw->data, fw->size,
|
||||
"clmload", "clmload_status");
|
||||
|
||||
release_firmware(fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int brcmf_c_process_txcap_blob(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct brcmf_bus *bus = drvr->bus_if;
|
||||
const struct firmware *fw = NULL;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
err = brcmf_bus_get_blob(bus, &fw, BRCMF_BLOB_TXCAP);
|
||||
if (err || !fw) {
|
||||
brcmf_info("no txcap_blob available (err=%d)\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
brcmf_info("TxCap blob found, loading\n");
|
||||
err = brcmf_c_download_blob(ifp, fw->data, fw->size,
|
||||
"txcapload", "txcapload_status");
|
||||
|
||||
release_firmware(fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -208,6 +246,23 @@ static const u8 brcmf_default_mac_address[ETH_ALEN] = {
|
|||
0x00, 0x90, 0x4c, 0xc5, 0x12, 0x38
|
||||
};
|
||||
|
||||
static int brcmf_c_process_cal_blob(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct brcmf_mp_device *settings = drvr->settings;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (!settings->cal_blob || !settings->cal_size)
|
||||
return 0;
|
||||
|
||||
brcmf_info("Calibration blob provided by platform, loading\n");
|
||||
err = brcmf_c_download_blob(ifp, settings->cal_blob, settings->cal_size,
|
||||
"calload", "calload_status");
|
||||
return err;
|
||||
}
|
||||
|
||||
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
|
@ -291,6 +346,20 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Do TxCap downloading, if needed */
|
||||
err = brcmf_c_process_txcap_blob(ifp);
|
||||
if (err < 0) {
|
||||
bphy_err(drvr, "download TxCap blob file failed, %d\n", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Download external calibration blob, if available */
|
||||
err = brcmf_c_process_cal_blob(ifp);
|
||||
if (err < 0) {
|
||||
bphy_err(drvr, "download calibration blob file failed, %d\n", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* query for 'ver' to get version info from firmware */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
|
||||
|
|
@ -487,6 +556,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
|
|||
/* No platform data for this device, try OF and DMI data */
|
||||
brcmf_dmi_probe(settings, chip, chiprev);
|
||||
brcmf_of_probe(dev, bus_type, settings);
|
||||
brcmf_acpi_probe(dev, bus_type, settings);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ struct brcmf_mp_device {
|
|||
const char *board_type;
|
||||
unsigned char mac[ETH_ALEN];
|
||||
const char *antenna_sku;
|
||||
const void *cal_blob;
|
||||
int cal_size;
|
||||
union {
|
||||
struct brcmfmac_sdio_pd sdio;
|
||||
} bus;
|
||||
|
|
@ -77,6 +79,15 @@ static inline void
|
|||
brcmf_dmi_probe(struct brcmf_mp_device *settings, u32 chip, u32 chiprev) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
void brcmf_acpi_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
||||
struct brcmf_mp_device *settings);
|
||||
#else
|
||||
static inline void brcmf_acpi_probe(struct device *dev,
|
||||
enum brcmf_bus_type bus_type,
|
||||
struct brcmf_mp_device *settings) {}
|
||||
#endif
|
||||
|
||||
u8 brcmf_map_prio_to_prec(void *cfg, u8 prio);
|
||||
|
||||
u8 brcmf_map_prio_to_aci(void *cfg, u8 prio);
|
||||
|
|
|
|||
|
|
@ -126,6 +126,53 @@ static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv)
|
|||
drv->feat_flags |= feat_flags;
|
||||
}
|
||||
|
||||
struct brcmf_feat_wlcfeat {
|
||||
u16 min_ver_major;
|
||||
u16 min_ver_minor;
|
||||
u32 feat_flags;
|
||||
};
|
||||
|
||||
static const struct brcmf_feat_wlcfeat brcmf_feat_wlcfeat_map[] = {
|
||||
{ 12, 0, BIT(BRCMF_FEAT_PMKID_V2) },
|
||||
{ 13, 0, BIT(BRCMF_FEAT_PMKID_V3) },
|
||||
};
|
||||
|
||||
static void brcmf_feat_wlc_version_overrides(struct brcmf_pub *drv)
|
||||
{
|
||||
struct brcmf_if *ifp = brcmf_get_ifp(drv, 0);
|
||||
const struct brcmf_feat_wlcfeat *e;
|
||||
struct brcmf_wlc_version_le ver;
|
||||
u32 feat_flags = 0;
|
||||
int i, err, major, minor;
|
||||
|
||||
err = brcmf_fil_iovar_data_get(ifp, "wlc_ver", &ver, sizeof(ver));
|
||||
if (err)
|
||||
return;
|
||||
|
||||
major = le16_to_cpu(ver.wlc_ver_major);
|
||||
minor = le16_to_cpu(ver.wlc_ver_minor);
|
||||
|
||||
brcmf_dbg(INFO, "WLC version: %d.%d\n", major, minor);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(brcmf_feat_wlcfeat_map); i++) {
|
||||
e = &brcmf_feat_wlcfeat_map[i];
|
||||
if (major > e->min_ver_major ||
|
||||
(major == e->min_ver_major &&
|
||||
minor >= e->min_ver_minor)) {
|
||||
feat_flags |= e->feat_flags;
|
||||
}
|
||||
}
|
||||
|
||||
if (!feat_flags)
|
||||
return;
|
||||
|
||||
for (i = 0; i < BRCMF_FEAT_LAST; i++)
|
||||
if (feat_flags & BIT(i))
|
||||
brcmf_dbg(INFO, "enabling firmware feature: %s\n",
|
||||
brcmf_feat_names[i]);
|
||||
drv->feat_flags |= feat_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_feat_iovar_int_get() - determine feature through iovar query.
|
||||
*
|
||||
|
|
@ -290,6 +337,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
|
|||
ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_RANDOM_MAC);
|
||||
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_SCAN_V2, "scan_ver");
|
||||
|
||||
if (drvr->settings->feature_disable) {
|
||||
brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
|
||||
|
|
@ -298,6 +346,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
|
|||
ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
|
||||
}
|
||||
|
||||
brcmf_feat_wlc_version_overrides(drvr);
|
||||
brcmf_feat_firmware_overrides(drvr);
|
||||
|
||||
/* set chip related quirks */
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
* SAE: simultaneous authentication of equals
|
||||
* FWAUTH: Firmware authenticator
|
||||
* DUMP_OBSS: Firmware has capable to dump obss info to support ACS
|
||||
* SCAN_V2: Version 2 scan params
|
||||
*/
|
||||
#define BRCMF_FEAT_LIST \
|
||||
BRCMF_FEAT_DEF(MBSS) \
|
||||
|
|
@ -53,7 +54,10 @@
|
|||
BRCMF_FEAT_DEF(DOT11H) \
|
||||
BRCMF_FEAT_DEF(SAE) \
|
||||
BRCMF_FEAT_DEF(FWAUTH) \
|
||||
BRCMF_FEAT_DEF(DUMP_OBSS)
|
||||
BRCMF_FEAT_DEF(DUMP_OBSS) \
|
||||
BRCMF_FEAT_DEF(SCAN_V2) \
|
||||
BRCMF_FEAT_DEF(PMKID_V2) \
|
||||
BRCMF_FEAT_DEF(PMKID_V3)
|
||||
|
||||
/*
|
||||
* Quirks:
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@
|
|||
|
||||
/* size of brcmf_scan_params not including variable length array */
|
||||
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
|
||||
#define BRCMF_SCAN_PARAMS_V2_FIXED_SIZE 72
|
||||
|
||||
/* version of brcmf_scan_params structure */
|
||||
#define BRCMF_SCAN_PARAMS_VERSION_V2 2
|
||||
|
||||
/* masks for channel and ssid count */
|
||||
#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
|
||||
|
|
@ -67,6 +71,7 @@
|
|||
#define BRCMF_PRIMARY_KEY (1 << 1)
|
||||
#define DOT11_BSSTYPE_ANY 2
|
||||
#define BRCMF_ESCAN_REQ_VERSION 1
|
||||
#define BRCMF_ESCAN_REQ_VERSION_V2 2
|
||||
|
||||
#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */
|
||||
|
||||
|
|
@ -169,6 +174,10 @@
|
|||
|
||||
#define BRCMF_HE_CAP_MCS_MAP_NSS_MAX 8
|
||||
|
||||
#define BRCMF_PMKSA_VER_2 2
|
||||
#define BRCMF_PMKSA_VER_3 3
|
||||
#define BRCMF_PMKSA_NO_EXPIRY 0xffffffff
|
||||
|
||||
/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each
|
||||
* ioctl. It is relatively small because firmware has small maximum size input
|
||||
* playload restriction for ioctls.
|
||||
|
|
@ -350,6 +359,12 @@ struct brcmf_ssid_le {
|
|||
unsigned char SSID[IEEE80211_MAX_SSID_LEN];
|
||||
};
|
||||
|
||||
/* Alternate SSID structure used in some places... */
|
||||
struct brcmf_ssid8_le {
|
||||
u8 SSID_len;
|
||||
unsigned char SSID[IEEE80211_MAX_SSID_LEN];
|
||||
};
|
||||
|
||||
struct brcmf_scan_params_le {
|
||||
struct brcmf_ssid_le ssid_le; /* default: {0, ""} */
|
||||
u8 bssid[ETH_ALEN]; /* default: bcast */
|
||||
|
|
@ -386,6 +401,45 @@ struct brcmf_scan_params_le {
|
|||
__le16 channel_list[1]; /* list of chanspecs */
|
||||
};
|
||||
|
||||
struct brcmf_scan_params_v2_le {
|
||||
__le16 version; /* structure version */
|
||||
__le16 length; /* structure length */
|
||||
struct brcmf_ssid_le ssid_le; /* default: {0, ""} */
|
||||
u8 bssid[ETH_ALEN]; /* default: bcast */
|
||||
s8 bss_type; /* default: any,
|
||||
* DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
|
||||
*/
|
||||
u8 pad;
|
||||
__le32 scan_type; /* flags, 0 use default */
|
||||
__le32 nprobes; /* -1 use default, number of probes per channel */
|
||||
__le32 active_time; /* -1 use default, dwell time per channel for
|
||||
* active scanning
|
||||
*/
|
||||
__le32 passive_time; /* -1 use default, dwell time per channel
|
||||
* for passive scanning
|
||||
*/
|
||||
__le32 home_time; /* -1 use default, dwell time for the
|
||||
* home channel between channel scans
|
||||
*/
|
||||
__le32 channel_num; /* count of channels and ssids that follow
|
||||
*
|
||||
* low half is count of channels in
|
||||
* channel_list, 0 means default (use all
|
||||
* available channels)
|
||||
*
|
||||
* high half is entries in struct brcmf_ssid
|
||||
* array that follows channel_list, aligned for
|
||||
* s32 (4 bytes) meaning an odd channel count
|
||||
* implies a 2-byte pad between end of
|
||||
* channel_list and first ssid
|
||||
*
|
||||
* if ssid count is zero, single ssid in the
|
||||
* fixed parameter portion is assumed, otherwise
|
||||
* ssid in the fixed portion is ignored
|
||||
*/
|
||||
__le16 channel_list[1]; /* list of chanspecs */
|
||||
};
|
||||
|
||||
struct brcmf_scan_results {
|
||||
u32 buflen;
|
||||
u32 version;
|
||||
|
|
@ -397,7 +451,10 @@ struct brcmf_escan_params_le {
|
|||
__le32 version;
|
||||
__le16 action;
|
||||
__le16 sync_id;
|
||||
struct brcmf_scan_params_le params_le;
|
||||
union {
|
||||
struct brcmf_scan_params_le params_le;
|
||||
struct brcmf_scan_params_v2_le params_v2_le;
|
||||
};
|
||||
};
|
||||
|
||||
struct brcmf_escan_result_le {
|
||||
|
|
@ -741,6 +798,31 @@ struct brcmf_rev_info_le {
|
|||
__le32 nvramrev;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_wlc_version_le - firmware revision info.
|
||||
*
|
||||
* @version: structure version.
|
||||
* @length: structure length.
|
||||
* @epi_ver_major: EPI major version
|
||||
* @epi_ver_minor: EPI minor version
|
||||
* @epi_ver_rc: EPI rc version
|
||||
* @epi_ver_incr: EPI increment version
|
||||
* @wlc_ver_major: WLC major version
|
||||
* @wlc_ver_minor: WLC minor version
|
||||
*/
|
||||
struct brcmf_wlc_version_le {
|
||||
__le16 version;
|
||||
__le16 length;
|
||||
|
||||
__le16 epi_ver_major;
|
||||
__le16 epi_ver_minor;
|
||||
__le16 epi_ver_rc;
|
||||
__le16 epi_ver_incr;
|
||||
|
||||
__le16 wlc_ver_major;
|
||||
__le16 wlc_ver_minor;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_assoclist_le - request assoc list.
|
||||
*
|
||||
|
|
@ -803,6 +885,51 @@ struct brcmf_pmksa {
|
|||
u8 pmkid[WLAN_PMKID_LEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pmksa_v2 - PMK Security Association
|
||||
*
|
||||
* @length: Length of the structure.
|
||||
* @bssid: The AP's BSSID.
|
||||
* @pmkid: The PMK ID.
|
||||
* @pmk: PMK material for FILS key derivation.
|
||||
* @pmk_len: Length of PMK data.
|
||||
* @ssid: The AP's SSID.
|
||||
* @fils_cache_id: FILS cache identifier
|
||||
*/
|
||||
struct brcmf_pmksa_v2 {
|
||||
__le16 length;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 pmkid[WLAN_PMKID_LEN];
|
||||
u8 pmk[WLAN_PMK_LEN_SUITE_B_192];
|
||||
__le16 pmk_len;
|
||||
struct brcmf_ssid8_le ssid;
|
||||
u16 fils_cache_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pmksa_v3 - PMK Security Association
|
||||
*
|
||||
* @bssid: The AP's BSSID.
|
||||
* @pmkid: The PMK ID.
|
||||
* @pmkid_len: The length of the PMK ID.
|
||||
* @pmk: PMK material for FILS key derivation.
|
||||
* @pmk_len: Length of PMK data.
|
||||
* @fils_cache_id: FILS cache identifier
|
||||
* @ssid: The AP's SSID.
|
||||
* @time_left: Remaining time until expiry. 0 = expired, ~0 = no expiry.
|
||||
*/
|
||||
struct brcmf_pmksa_v3 {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 pmkid[WLAN_PMKID_LEN];
|
||||
u8 pmkid_len;
|
||||
u8 pmk[WLAN_PMK_LEN_SUITE_B_192];
|
||||
u8 pmk_len;
|
||||
__le16 fils_cache_id;
|
||||
u8 pad;
|
||||
struct brcmf_ssid8_le ssid;
|
||||
__le32 time_left;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pmk_list_le - List of pmksa's.
|
||||
*
|
||||
|
|
@ -814,6 +941,34 @@ struct brcmf_pmk_list_le {
|
|||
struct brcmf_pmksa pmk[BRCMF_MAXPMKID];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pmk_list_v2_le - List of pmksa's.
|
||||
*
|
||||
* @version: Request version.
|
||||
* @length: Length of this structure.
|
||||
* @pmk: PMK SA information.
|
||||
*/
|
||||
struct brcmf_pmk_list_v2_le {
|
||||
__le16 version;
|
||||
__le16 length;
|
||||
struct brcmf_pmksa_v2 pmk[BRCMF_MAXPMKID];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pmk_op_v3_le - Operation on PMKSA list.
|
||||
*
|
||||
* @version: Request version.
|
||||
* @length: Length of this structure.
|
||||
* @pmk: PMK SA information.
|
||||
*/
|
||||
struct brcmf_pmk_op_v3_le {
|
||||
__le16 version;
|
||||
__le16 length;
|
||||
__le16 count;
|
||||
__le16 pad;
|
||||
struct brcmf_pmksa_v3 pmk[BRCMF_MAXPMKID];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pno_param_le - PNO scan configuration parameters
|
||||
*
|
||||
|
|
|
|||
|
|
@ -86,6 +86,13 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
|||
if (!of_property_read_string(np, "apple,antenna-sku", &prop))
|
||||
settings->antenna_sku = prop;
|
||||
|
||||
/* The WLAN calibration blob is normally stored in SROM, but Apple
|
||||
* ARM64 platforms pass it via the DT instead.
|
||||
*/
|
||||
prop = of_get_property(np, "brcm,cal-blob", &settings->cal_size);
|
||||
if (prop && settings->cal_size)
|
||||
settings->cal_blob = prop;
|
||||
|
||||
/* Set board-type to the first string of the machine compatible prop */
|
||||
root = of_find_node_by_path("/");
|
||||
if (root && err) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/sched/signal.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/random.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <soc.h>
|
||||
|
|
@ -57,6 +58,7 @@ BRCMF_FW_CLM_DEF(4356, "brcmfmac4356-pcie");
|
|||
BRCMF_FW_CLM_DEF(43570, "brcmfmac43570-pcie");
|
||||
BRCMF_FW_DEF(4358, "brcmfmac4358-pcie");
|
||||
BRCMF_FW_DEF(4359, "brcmfmac4359-pcie");
|
||||
BRCMF_FW_DEF(4359C, "brcmfmac4359c-pcie");
|
||||
BRCMF_FW_CLM_DEF(4364B2, "brcmfmac4364b2-pcie");
|
||||
BRCMF_FW_CLM_DEF(4364B3, "brcmfmac4364b3-pcie");
|
||||
BRCMF_FW_DEF(4365B, "brcmfmac4365b-pcie");
|
||||
|
|
@ -66,6 +68,8 @@ BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
|
|||
BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
|
||||
BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie");
|
||||
BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
|
||||
BRCMF_FW_CLM_DEF(4378B3, "brcmfmac4378b3-pcie");
|
||||
BRCMF_FW_CLM_DEF(4387C2, "brcmfmac4387c2-pcie");
|
||||
|
||||
/* firmware config files */
|
||||
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
|
||||
|
|
@ -74,6 +78,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");
|
|||
/* per-board firmware binaries */
|
||||
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin");
|
||||
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob");
|
||||
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txcap_blob");
|
||||
|
||||
static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
||||
BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
|
||||
|
|
@ -88,7 +93,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
|||
BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0x000001FF, 4359),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFE00, 4359C),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0x0000000F, 4364B2), /* 3 */
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0xFFFFFFF0, 4364B3), /* 4 */
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B),
|
||||
|
|
@ -99,7 +105,9 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
|||
BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* revision ID 4 */
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFFF, 4378B1), /* revision ID 3 */
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4387_CHIP_ID, 0xFFFFFFFF, 4387C2), /* revision ID 7 */
|
||||
};
|
||||
|
||||
#define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */
|
||||
|
|
@ -326,7 +334,9 @@ struct brcmf_pciedev_info {
|
|||
char fw_name[BRCMF_FW_NAME_LEN];
|
||||
char nvram_name[BRCMF_FW_NAME_LEN];
|
||||
char clm_name[BRCMF_FW_NAME_LEN];
|
||||
char txcap_name[BRCMF_FW_NAME_LEN];
|
||||
const struct firmware *clm_fw;
|
||||
const struct firmware *txcap_fw;
|
||||
const struct brcmf_pcie_reginfo *reginfo;
|
||||
void __iomem *regs;
|
||||
void __iomem *tcm;
|
||||
|
|
@ -1517,6 +1527,10 @@ static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw,
|
|||
*fw = devinfo->clm_fw;
|
||||
devinfo->clm_fw = NULL;
|
||||
break;
|
||||
case BRCMF_BLOB_TXCAP:
|
||||
*fw = devinfo->txcap_fw;
|
||||
devinfo->txcap_fw = NULL;
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
|
@ -1653,6 +1667,13 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct brcmf_random_seed_footer {
|
||||
__le32 length;
|
||||
__le32 magic;
|
||||
};
|
||||
|
||||
#define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de
|
||||
#define BRCMF_RANDOM_SEED_LENGTH 0x100
|
||||
|
||||
static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
|
||||
const struct firmware *fw, void *nvram,
|
||||
|
|
@ -1689,6 +1710,30 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
|
|||
nvram_len;
|
||||
memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
|
||||
brcmf_fw_nvram_free(nvram);
|
||||
|
||||
if (devinfo->otp.valid) {
|
||||
size_t rand_len = BRCMF_RANDOM_SEED_LENGTH;
|
||||
struct brcmf_random_seed_footer footer = {
|
||||
.length = cpu_to_le32(rand_len),
|
||||
.magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),
|
||||
};
|
||||
void *randbuf;
|
||||
|
||||
/* Some Apple chips/firmwares expect a buffer of random
|
||||
* data to be present before NVRAM
|
||||
*/
|
||||
brcmf_dbg(PCIE, "Download random seed\n");
|
||||
|
||||
address -= sizeof(footer);
|
||||
memcpy_toio(devinfo->tcm + address, &footer,
|
||||
sizeof(footer));
|
||||
|
||||
address -= rand_len;
|
||||
randbuf = kzalloc(rand_len, GFP_KERNEL);
|
||||
get_random_bytes(randbuf, rand_len);
|
||||
memcpy_toio(devinfo->tcm + address, randbuf, rand_len);
|
||||
kfree(randbuf);
|
||||
}
|
||||
} else {
|
||||
brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
|
||||
devinfo->nvram_name);
|
||||
|
|
@ -2016,6 +2061,11 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
|
|||
base = 0x1120;
|
||||
words = 0x170;
|
||||
break;
|
||||
case BRCM_CC_4387_CHIP_ID:
|
||||
coreid = BCMA_CORE_GCI;
|
||||
base = 0x113c;
|
||||
words = 0x170;
|
||||
break;
|
||||
default:
|
||||
/* OTP not supported on this chip */
|
||||
return 0;
|
||||
|
|
@ -2073,6 +2123,7 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
|
|||
#define BRCMF_PCIE_FW_CODE 0
|
||||
#define BRCMF_PCIE_FW_NVRAM 1
|
||||
#define BRCMF_PCIE_FW_CLM 2
|
||||
#define BRCMF_PCIE_FW_TXCAP 3
|
||||
|
||||
static void brcmf_pcie_setup(struct device *dev, int ret,
|
||||
struct brcmf_fw_request *fwreq)
|
||||
|
|
@ -2099,6 +2150,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
|
|||
nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
|
||||
nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
|
||||
devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary;
|
||||
devinfo->txcap_fw = fwreq->items[BRCMF_PCIE_FW_TXCAP].binary;
|
||||
kfree(fwreq);
|
||||
|
||||
ret = brcmf_chip_get_raminfo(devinfo->ci);
|
||||
|
|
@ -2180,6 +2232,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
|
|||
{ ".bin", devinfo->fw_name },
|
||||
{ ".txt", devinfo->nvram_name },
|
||||
{ ".clm_blob", devinfo->clm_name },
|
||||
{ ".txcap_blob", devinfo->txcap_name },
|
||||
};
|
||||
|
||||
fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
|
||||
|
|
@ -2194,6 +2247,8 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
|
|||
fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
|
||||
fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
|
||||
fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
|
||||
fwreq->items[BRCMF_PCIE_FW_TXCAP].type = BRCMF_FW_TYPE_BINARY;
|
||||
fwreq->items[BRCMF_PCIE_FW_TXCAP].flags = BRCMF_FW_REQF_OPTIONAL;
|
||||
/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
|
||||
fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
|
||||
fwreq->bus_nr = devinfo->pdev->bus->number;
|
||||
|
|
@ -2491,6 +2546,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
|
|||
brcmf_pcie_reset_device(devinfo);
|
||||
brcmf_pcie_release_resource(devinfo);
|
||||
release_firmware(devinfo->clm_fw);
|
||||
release_firmware(devinfo->txcap_fw);
|
||||
|
||||
if (devinfo->ci)
|
||||
brcmf_chip_detach(devinfo->ci);
|
||||
|
|
@ -2630,6 +2686,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = {
|
|||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43596_DEVICE_ID, CYW),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC),
|
||||
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#define BRCM_CC_4371_CHIP_ID 0x4371
|
||||
#define BRCM_CC_4377_CHIP_ID 0x4377
|
||||
#define BRCM_CC_4378_CHIP_ID 0x4378
|
||||
#define BRCM_CC_4387_CHIP_ID 0x4387
|
||||
#define CY_CC_4373_CHIP_ID 0x4373
|
||||
#define CY_CC_43012_CHIP_ID 43012
|
||||
#define CY_CC_43439_CHIP_ID 43439
|
||||
|
|
@ -95,6 +96,7 @@
|
|||
#define BRCM_PCIE_43596_DEVICE_ID 0x4415
|
||||
#define BRCM_PCIE_4377_DEVICE_ID 0x4488
|
||||
#define BRCM_PCIE_4378_DEVICE_ID 0x4425
|
||||
#define BRCM_PCIE_4387_DEVICE_ID 0x4433
|
||||
|
||||
/* brcmsmac IDs */
|
||||
#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@
|
|||
#define IWL_BZ_Z_GF_A_FW_PRE "iwlwifi-bz-z0-gf-a0-"
|
||||
#define IWL_BNJ_A_FM_A_FW_PRE "iwlwifi-BzBnj-a0-fm-a0-"
|
||||
#define IWL_BNJ_A_FM4_A_FW_PRE "iwlwifi-BzBnj-a0-fm4-a0-"
|
||||
#define IWL_BNJ_B_FM4_B_FW_PRE "iwlwifi-BzBnj-b0-fm4-b0-"
|
||||
#define IWL_BNJ_A_GF_A_FW_PRE "iwlwifi-BzBnj-a0-gf-a0-"
|
||||
#define IWL_BNJ_A_GF4_A_FW_PRE "iwlwifi-BzBnj-a0-gf4-a0-"
|
||||
#define IWL_BNJ_A_HR_B_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-"
|
||||
|
|
@ -132,6 +133,8 @@
|
|||
IWL_BNJ_A_FM_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_A_FM4_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_B_FM4_B_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_B_FM4_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_A_GF_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BNJ_A_GF_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(api) \
|
||||
|
|
@ -998,6 +1001,14 @@ const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0 = {
|
|||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0 = {
|
||||
.fw_name_pre = IWL_BNJ_B_FM4_B_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0 = {
|
||||
.fw_name_pre = IWL_BNJ_A_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
|
|
@ -1059,6 +1070,7 @@ MODULE_FIRMWARE(IWL_BZ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|||
MODULE_FIRMWARE(IWL_GL_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_B_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_BNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
|
|
|
|||
|
|
@ -373,9 +373,6 @@ enum {
|
|||
|
||||
/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */
|
||||
#define RATE_VHT_MCS_RATE_CODE_MSK 0xf
|
||||
#define RATE_VHT_MCS_NSS_POS 4
|
||||
#define RATE_VHT_MCS_NSS_MSK (3 << RATE_VHT_MCS_NSS_POS)
|
||||
#define RATE_VHT_MCS_MIMO2_MSK BIT(RATE_VHT_MCS_NSS_POS)
|
||||
|
||||
/*
|
||||
* Legacy OFDM rate format for bits 7:0
|
||||
|
|
@ -449,11 +446,16 @@ enum {
|
|||
* 1 2xLTF+0.8us
|
||||
* 2 2xLTF+1.6us
|
||||
* 3 4xLTF+3.2us
|
||||
* HE TRIG:
|
||||
* HE-EHT TRIG:
|
||||
* 0 1xLTF+1.6us
|
||||
* 1 2xLTF+1.6us
|
||||
* 2 4xLTF+3.2us
|
||||
* 3 (does not occur)
|
||||
* EHT MU:
|
||||
* 0 2xLTF+0.8us
|
||||
* 1 2xLTF+1.6us
|
||||
* 2 4xLTF+0.8us
|
||||
* 3 4xLTF+3.2us
|
||||
*/
|
||||
#define RATE_MCS_HE_GI_LTF_POS 20
|
||||
#define RATE_MCS_HE_GI_LTF_MSK_V1 (3 << RATE_MCS_HE_GI_LTF_POS)
|
||||
|
|
@ -546,12 +548,17 @@ enum {
|
|||
/*
|
||||
* Bits 13-11: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz, (4) 320MHz
|
||||
*/
|
||||
#define RATE_MCS_CHAN_WIDTH_MSK (0x7 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_20 (0 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_40 (1 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_80 (2 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_160 (3 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_320 (4 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_MSK (0x7 << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_20_VAL 0
|
||||
#define RATE_MCS_CHAN_WIDTH_20 (RATE_MCS_CHAN_WIDTH_20_VAL << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_40_VAL 1
|
||||
#define RATE_MCS_CHAN_WIDTH_40 (RATE_MCS_CHAN_WIDTH_40_VAL << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_80_VAL 2
|
||||
#define RATE_MCS_CHAN_WIDTH_80 (RATE_MCS_CHAN_WIDTH_80_VAL << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_160_VAL 3
|
||||
#define RATE_MCS_CHAN_WIDTH_160 (RATE_MCS_CHAN_WIDTH_160_VAL << RATE_MCS_CHAN_WIDTH_POS)
|
||||
#define RATE_MCS_CHAN_WIDTH_320_VAL 4
|
||||
#define RATE_MCS_CHAN_WIDTH_320 (RATE_MCS_CHAN_WIDTH_320_VAL << RATE_MCS_CHAN_WIDTH_POS)
|
||||
|
||||
/* Bit 15-14: Antenna selection:
|
||||
* Bit 14: Ant A active
|
||||
|
|
|
|||
|
|
@ -367,7 +367,8 @@ enum iwl_rx_phy_eht_data1 {
|
|||
/* number of EHT-LTF symbols 0 - 1 EHT-LTF, 1 - 2 EHT-LTFs, 2 - 4 EHT-LTFs,
|
||||
* 3 - 6 EHT-LTFs, 4 - 8 EHT-LTFs */
|
||||
IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM = 0x000000e0,
|
||||
IWL_RX_PHY_DATA1_EHT_RU_ALLOC = 0x0000ff00,
|
||||
IWL_RX_PHY_DATA1_EHT_B0 = 0x00000100,
|
||||
IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC = 0x0000fe00,
|
||||
};
|
||||
|
||||
/* goes into Metadata DW 7 */
|
||||
|
|
@ -413,7 +414,7 @@ enum iwl_rx_phy_eht_data2 {
|
|||
/* OFDM_RX_VECTOR_COMMON_RU_ALLOC_0_OUT */
|
||||
IWL_RX_PHY_DATA2_EHT_MU_EXT_RU_ALLOC_A1 = 0x000001ff,
|
||||
IWL_RX_PHY_DATA2_EHT_MU_EXT_RU_ALLOC_A2 = 0x0003fe00,
|
||||
IWL_RX_PHY_DATA2_EHT_MU_EXT_RU_ALLOC_A3 = 0x01fc0000,
|
||||
IWL_RX_PHY_DATA2_EHT_MU_EXT_RU_ALLOC_B1 = 0x07fc0000,
|
||||
|
||||
/* info type: EHT-TB-EXT */
|
||||
IWL_RX_PHY_DATA2_EHT_TB_EXT_TRIG_SIGA1 = 0xffffffff,
|
||||
|
|
@ -423,19 +424,18 @@ enum iwl_rx_phy_eht_data2 {
|
|||
enum iwl_rx_phy_eht_data3 {
|
||||
/* info type: EHT-MU-EXT */
|
||||
/* OFDM_RX_VECTOR_COMMON_RU_ALLOC_1_OUT */
|
||||
IWL_RX_PHY_DATA3_EHT_MU_EXT_RU_ALLOC_B1 = 0x000001ff,
|
||||
IWL_RX_PHY_DATA3_EHT_MU_EXT_RU_ALLOC_B2 = 0x0003fe00,
|
||||
IWL_RX_PHY_DATA3_EHT_MU_EXT_RU_ALLOC_B3 = 0x01fc0000,
|
||||
IWL_RX_PHY_DATA3_EHT_MU_EXT_RU_ALLOC_B2 = 0x000001ff,
|
||||
IWL_RX_PHY_DATA3_EHT_MU_EXT_RU_ALLOC_C1 = 0x0003fe00,
|
||||
IWL_RX_PHY_DATA3_EHT_MU_EXT_RU_ALLOC_C2 = 0x07fc0000,
|
||||
};
|
||||
|
||||
/* goes into Metadata DW 4 */
|
||||
enum iwl_rx_phy_eht_data4 {
|
||||
/* info type: EHT-MU-EXT */
|
||||
/* OFDM_RX_VECTOR_COMMON_RU_ALLOC_2_OUT */
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_RU_ALLOC_C1 = 0x000001ff,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_RU_ALLOC_C2 = 0x0003fe00,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_RU_ALLOC_C3 = 0x01fc0000,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_SIGB_MCS = 0x18000000,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_RU_ALLOC_D1 = 0x000001ff,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_RU_ALLOC_D2 = 0x0003fe00,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_SIGB_MCS = 0x000c0000,
|
||||
};
|
||||
|
||||
/* goes into Metadata DW 16 */
|
||||
|
|
@ -673,22 +673,31 @@ struct iwl_rx_mpdu_desc {
|
|||
* @mac_phy_idx: MAC/PHY index
|
||||
*/
|
||||
u8 mac_phy_idx;
|
||||
/* DW4 - carries csum data only when rpa_en == 1 */
|
||||
/**
|
||||
* @raw_csum: raw checksum (alledgedly unreliable)
|
||||
*/
|
||||
__le16 raw_csum;
|
||||
|
||||
/* DW4 */
|
||||
union {
|
||||
/**
|
||||
* @l3l4_flags: &enum iwl_rx_l3l4_flags
|
||||
*/
|
||||
__le16 l3l4_flags;
|
||||
struct {
|
||||
/* carries csum data only when rpa_en == 1 */
|
||||
/**
|
||||
* @raw_csum: raw checksum (alledgedly unreliable)
|
||||
*/
|
||||
__le16 raw_csum;
|
||||
|
||||
union {
|
||||
/**
|
||||
* @l3l4_flags: &enum iwl_rx_l3l4_flags
|
||||
*/
|
||||
__le16 l3l4_flags;
|
||||
|
||||
/**
|
||||
* @phy_data4: depends on info type, see phy_data1
|
||||
*/
|
||||
__le16 phy_data4;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* @phy_data4: depends on info type, see phy_data1
|
||||
* @phy_eht_data4: depends on info type, see phy_data1
|
||||
*/
|
||||
__le16 phy_data4;
|
||||
__le32 phy_eht_data4;
|
||||
};
|
||||
/* DW5 */
|
||||
/**
|
||||
|
|
@ -725,7 +734,7 @@ struct iwl_rx_mpdu_desc {
|
|||
#define RX_NO_DATA_INFO_TYPE_RX_ERR 1
|
||||
#define RX_NO_DATA_INFO_TYPE_NDP 2
|
||||
#define RX_NO_DATA_INFO_TYPE_MU_UNMATCHED 3
|
||||
#define RX_NO_DATA_INFO_TYPE_HE_TB_UNMATCHED 4
|
||||
#define RX_NO_DATA_INFO_TYPE_TB_UNMATCHED 4
|
||||
|
||||
#define RX_NO_DATA_INFO_ERR_POS 8
|
||||
#define RX_NO_DATA_INFO_ERR_MSK (0xff << RX_NO_DATA_INFO_ERR_POS)
|
||||
|
|
@ -743,6 +752,35 @@ struct iwl_rx_mpdu_desc {
|
|||
#define RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK 0x38000000
|
||||
#define RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK 0x00f00000
|
||||
|
||||
/* content of OFDM_RX_VECTOR_USIG_A1_OUT */
|
||||
enum iwl_rx_usig_a1 {
|
||||
IWL_RX_USIG_A1_ENHANCED_WIFI_VER_ID = 0x00000007,
|
||||
IWL_RX_USIG_A1_BANDWIDTH = 0x00000038,
|
||||
IWL_RX_USIG_A1_UL_FLAG = 0x00000040,
|
||||
IWL_RX_USIG_A1_BSS_COLOR = 0x00001f80,
|
||||
IWL_RX_USIG_A1_TXOP_DURATION = 0x000fe000,
|
||||
IWL_RX_USIG_A1_DISREGARD = 0x01f00000,
|
||||
IWL_RX_USIG_A1_VALIDATE = 0x02000000,
|
||||
IWL_RX_USIG_A1_EHT_BW320_SLOT = 0x04000000,
|
||||
IWL_RX_USIG_A1_EHT_TYPE = 0x18000000,
|
||||
IWL_RX_USIG_A1_RDY = 0x80000000,
|
||||
};
|
||||
|
||||
/* content of OFDM_RX_VECTOR_USIG_A2_EHT_OUT */
|
||||
enum iwl_rx_usig_a2_eht {
|
||||
IWL_RX_USIG_A2_EHT_PPDU_TYPE = 0x00000003,
|
||||
IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2 = 0x00000004,
|
||||
IWL_RX_USIG_A2_EHT_PUNC_CHANNEL = 0x000000f8,
|
||||
IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B8 = 0x00000100,
|
||||
IWL_RX_USIG_A2_EHT_SIG_MCS = 0x00000600,
|
||||
IWL_RX_USIG_A2_EHT_SIG_SYM_NUM = 0x0000f800,
|
||||
IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_1 = 0x000f0000,
|
||||
IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_2 = 0x00f00000,
|
||||
IWL_RX_USIG_A2_EHT_TRIG_USIG2_DISREGARD = 0x1f000000,
|
||||
IWL_RX_USIG_A2_EHT_CRC_OK = 0x40000000,
|
||||
IWL_RX_USIG_A2_EHT_RDY = 0x80000000,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_rx_no_data - RX no data descriptor
|
||||
* @info: 7:0 frame type, 15:8 RX error type
|
||||
|
|
@ -780,7 +818,7 @@ struct iwl_rx_no_data {
|
|||
* @rx_vec: DW-12:9 raw RX vectors from DSP according to modulation type.
|
||||
* for VHT: OFDM_RX_VECTOR_SIGA1_OUT, OFDM_RX_VECTOR_SIGA2_OUT
|
||||
* for HE: OFDM_RX_VECTOR_HE_SIGA1_OUT, OFDM_RX_VECTOR_HE_SIGA2_OUT
|
||||
* for EHT: OFDM_RX_VECTOR_USIG_A1_OUT, OFDM_RX_VECTOR_USIG_A2_OUT,
|
||||
* for EHT: OFDM_RX_VECTOR_USIG_A1_OUT, OFDM_RX_VECTOR_USIG_A2_EHT_OUT,
|
||||
* OFDM_RX_VECTOR_EHT_OUT, OFDM_RX_VECTOR_EHT_USER_FIELD_OUT
|
||||
*/
|
||||
struct iwl_rx_no_data_ver_3 {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2021 Intel Corporation
|
||||
* Copyright (C) 2021-2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
|
@ -126,7 +126,7 @@ u32 iwl_new_rate_from_v1(u32 rate_v1)
|
|||
rate_v1 & RATE_MCS_HE_MSK_V1) {
|
||||
rate_v2 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK;
|
||||
|
||||
rate_v2 |= rate_v1 & RATE_VHT_MCS_MIMO2_MSK;
|
||||
rate_v2 |= rate_v1 & RATE_MCS_NSS_MSK;
|
||||
|
||||
if (rate_v1 & RATE_MCS_HE_MSK_V1) {
|
||||
u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1;
|
||||
|
|
|
|||
|
|
@ -659,6 +659,7 @@ extern const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0;
|
|||
extern const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0;
|
||||
extern const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0;
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
#endif /* __IWL_CONFIG_H__ */
|
||||
|
|
|
|||
|
|
@ -348,6 +348,7 @@ enum {
|
|||
#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00)
|
||||
#define CSR_HW_RF_ID_TYPE_GF (0x0010D000)
|
||||
#define CSR_HW_RF_ID_TYPE_GF4 (0x0010E000)
|
||||
#define CSR_HW_RF_ID_TYPE_MS (0x00111000)
|
||||
|
||||
/* HW_RF CHIP STEP */
|
||||
#define CSR_HW_RF_STEP(_val) (((_val) >> 8) & 0xF)
|
||||
|
|
|
|||
|
|
@ -350,9 +350,9 @@ void iwl_dbg_tlv_alloc(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv,
|
|||
|
||||
ret = dbg_tlv_alloc[tlv_idx](trans, tlv);
|
||||
if (ret) {
|
||||
IWL_ERR(trans,
|
||||
"WRT: Failed to allocate TLV 0x%x, ret %d, (ext=%d)\n",
|
||||
type, ret, ext);
|
||||
IWL_WARN(trans,
|
||||
"WRT: Failed to allocate TLV 0x%x, ret %d, (ext=%d)\n",
|
||||
type, ret, ext);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
|
|
@ -1218,11 +1218,12 @@ iwl_dbg_tlv_tp_trigger(struct iwl_fw_runtime *fwrt, bool sync,
|
|||
}
|
||||
|
||||
fwrt->trans->dbg.restart_required = FALSE;
|
||||
IWL_DEBUG_INFO(fwrt, "WRT: tp %d, reset_fw %d\n",
|
||||
tp, dump_data.trig->reset_fw);
|
||||
IWL_DEBUG_INFO(fwrt, "WRT: restart_required %d, last_tp_resetfw %d\n",
|
||||
fwrt->trans->dbg.restart_required,
|
||||
fwrt->trans->dbg.last_tp_resetfw);
|
||||
IWL_DEBUG_FW(fwrt, "WRT: tp %d, reset_fw %d\n",
|
||||
tp, dump_data.trig->reset_fw);
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: restart_required %d, last_tp_resetfw %d\n",
|
||||
fwrt->trans->dbg.restart_required,
|
||||
fwrt->trans->dbg.last_tp_resetfw);
|
||||
|
||||
if (fwrt->trans->trans_cfg->device_family ==
|
||||
IWL_DEVICE_FAMILY_9000) {
|
||||
|
|
@ -1235,18 +1236,19 @@ iwl_dbg_tlv_tp_trigger(struct iwl_fw_runtime *fwrt, bool sync,
|
|||
IWL_DEBUG_FW(fwrt, "WRT: FW_ASSERT due to reset_fw_mode-no restart\n");
|
||||
} else if (le32_to_cpu(dump_data.trig->reset_fw) ==
|
||||
IWL_FW_INI_RESET_FW_MODE_STOP_AND_RELOAD_FW) {
|
||||
IWL_DEBUG_INFO(fwrt, "WRT: stop and reload firmware\n");
|
||||
IWL_DEBUG_FW(fwrt, "WRT: stop and reload firmware\n");
|
||||
fwrt->trans->dbg.restart_required = TRUE;
|
||||
} else if (le32_to_cpu(dump_data.trig->reset_fw) ==
|
||||
IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY) {
|
||||
IWL_DEBUG_INFO(fwrt, "WRT: stop only and no reload firmware\n");
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: stop only and no reload firmware\n");
|
||||
fwrt->trans->dbg.restart_required = FALSE;
|
||||
fwrt->trans->dbg.last_tp_resetfw =
|
||||
le32_to_cpu(dump_data.trig->reset_fw);
|
||||
} else if (le32_to_cpu(dump_data.trig->reset_fw) ==
|
||||
IWL_FW_INI_RESET_FW_MODE_NOTHING) {
|
||||
IWL_DEBUG_INFO(fwrt,
|
||||
"WRT: nothing need to be done after debug collection\n");
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: nothing need to be done after debug collection\n");
|
||||
} else {
|
||||
IWL_ERR(fwrt, "WRT: wrong resetfw %d\n",
|
||||
le32_to_cpu(dump_data.trig->reset_fw));
|
||||
|
|
|
|||
|
|
@ -1084,6 +1084,11 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
},
|
||||
},
|
||||
{ .ident = "MSFT",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
|
||||
},
|
||||
},
|
||||
|
||||
/* keep last */
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -654,7 +654,7 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
|
|||
u32 action)
|
||||
{
|
||||
struct iwl_mac_ctx_cmd cmd = {};
|
||||
u32 tfd_queue_msk = BIT(mvm->snif_queue);
|
||||
u32 tfd_queue_msk = 0;
|
||||
int ret;
|
||||
|
||||
WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
|
||||
|
|
@ -669,6 +669,14 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
|
|||
MAC_FILTER_ACCEPT_GRP);
|
||||
ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
|
||||
|
||||
/*
|
||||
* the queue mask is only relevant for old TX API, and
|
||||
* mvm->snif_queue isn't set here (it's still set to
|
||||
* IWL_MVM_INVALID_QUEUE so the BIT() of it is UB)
|
||||
*/
|
||||
if (!iwl_mvm_has_new_tx_api(mvm))
|
||||
tfd_queue_msk = BIT(mvm->snif_queue);
|
||||
|
||||
/* Allocate sniffer station */
|
||||
ret = iwl_mvm_allocate_int_sta(mvm, &mvm->snif_sta, tfd_queue_msk,
|
||||
vif->type, IWL_STA_GENERAL_PURPOSE);
|
||||
|
|
|
|||
|
|
@ -1362,6 +1362,28 @@ static void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk)
|
|||
ieee80211_chswitch_done(vif, false);
|
||||
}
|
||||
|
||||
static u8
|
||||
iwl_mvm_chandef_get_primary_80(struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
int data_start;
|
||||
int control_start;
|
||||
int bw;
|
||||
|
||||
if (chandef->width == NL80211_CHAN_WIDTH_320)
|
||||
bw = 320;
|
||||
else if (chandef->width == NL80211_CHAN_WIDTH_160)
|
||||
bw = 160;
|
||||
else
|
||||
return 0;
|
||||
|
||||
/* data is bw wide so the start is half the width */
|
||||
data_start = chandef->center_freq1 - bw / 2;
|
||||
/* control is 20Mhz width */
|
||||
control_start = chandef->chan->center_freq - 10;
|
||||
|
||||
return (control_start - data_start) / 80;
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
@ -1478,8 +1500,11 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
INIT_DELAYED_WORK(&mvmvif->csa_work,
|
||||
iwl_mvm_channel_switch_disconnect_wk);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_MONITOR)
|
||||
if (vif->type == NL80211_IFTYPE_MONITOR) {
|
||||
mvm->monitor_on = true;
|
||||
mvm->monitor_p80 =
|
||||
iwl_mvm_chandef_get_primary_80(&vif->bss_conf.chandef);
|
||||
}
|
||||
|
||||
iwl_mvm_vif_dbgfs_register(mvm, vif);
|
||||
|
||||
|
|
@ -5033,9 +5058,10 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
|
|||
if (iwl_mvm_flush_sta(mvm, mvmsta, false))
|
||||
IWL_ERR(mvm, "flush request fail\n");
|
||||
} else {
|
||||
msk |= mvmsta->tfd_queue_msk;
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
iwl_mvm_wait_sta_queues_empty(mvm, mvmsta);
|
||||
else /* only used for !iwl_mvm_has_new_tx_api() below */
|
||||
msk |= mvmsta->tfd_queue_msk;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1096,6 +1096,11 @@ struct iwl_mvm {
|
|||
|
||||
/* does a monitor vif exist (only one can exist hence bool) */
|
||||
bool monitor_on;
|
||||
/*
|
||||
* primary channel position relative to he whole bandwidth,
|
||||
* in steps of 80 MHz
|
||||
*/
|
||||
u8 monitor_p80;
|
||||
|
||||
/* sniffer data to include in radiotap */
|
||||
__le16 cur_aid;
|
||||
|
|
|
|||
|
|
@ -337,10 +337,14 @@ static void rs_fw_eht_set_enabled_rates(const struct ieee80211_sta *sta,
|
|||
const struct ieee80211_eht_mcs_nss_supp_bw *mcs_tx =
|
||||
rs_fw_rs_mcs2eht_mcs(bw, eht_tx_mcs);
|
||||
|
||||
/* got unsuppored index for bw */
|
||||
/* got unsupported index for bw */
|
||||
if (!mcs_rx || !mcs_tx)
|
||||
continue;
|
||||
|
||||
/* break out if we don't support the bandwidth */
|
||||
if (cmd->max_ch_width < (bw + IWL_TLC_MNG_CH_WIDTH_80MHZ))
|
||||
break;
|
||||
|
||||
rs_fw_set_eht_mcs_nss(cmd->ht_rates, bw,
|
||||
MAX_NSS_MCS(9, mcs_rx, mcs_tx), GENMASK(9, 0));
|
||||
rs_fw_set_eht_mcs_nss(cmd->ht_rates, bw,
|
||||
|
|
@ -550,7 +554,7 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
struct iwl_tlc_config_cmd_v4 cfg_cmd = {
|
||||
.sta_id = mvmsta->sta_id,
|
||||
.max_ch_width = update ?
|
||||
rs_fw_bw_from_sta_bw(sta) : RATE_MCS_CHAN_WIDTH_20,
|
||||
rs_fw_bw_from_sta_bw(sta) : IWL_TLC_MNG_CH_WIDTH_20MHZ,
|
||||
.flags = cpu_to_le16(rs_fw_get_config_flags(mvm, sta, sband)),
|
||||
.chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
|
||||
.sgi_ch_width_supp = rs_fw_sgi_cw_support(sta),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2005 - 2014, 2018 - 2021 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2005 - 2014, 2018 - 2022 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*****************************************************************************/
|
||||
|
|
@ -895,8 +895,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
|
|||
WARN_ON_ONCE(1);
|
||||
}
|
||||
} else if (ucode_rate & RATE_MCS_VHT_MSK_V1) {
|
||||
nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>
|
||||
RATE_VHT_MCS_NSS_POS) + 1;
|
||||
nss = FIELD_GET(RATE_MCS_NSS_MSK, ucode_rate) + 1;
|
||||
|
||||
if (nss == 1) {
|
||||
rate->type = LQ_VHT_SISO;
|
||||
|
|
@ -910,8 +909,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
|
|||
WARN_ON_ONCE(1);
|
||||
}
|
||||
} else if (ucode_rate & RATE_MCS_HE_MSK_V1) {
|
||||
nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>
|
||||
RATE_VHT_MCS_NSS_POS) + 1;
|
||||
nss = FIELD_GET(RATE_MCS_NSS_MSK, ucode_rate) + 1;
|
||||
|
||||
if (nss == 1) {
|
||||
rate->type = LQ_HE_SISO;
|
||||
|
|
@ -2885,8 +2883,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
|
|||
nss = ((rate & RATE_HT_MCS_NSS_MSK_V1) >> RATE_HT_MCS_NSS_POS_V1) + 1;
|
||||
} else if (rate & RATE_MCS_VHT_MSK_V1) {
|
||||
mvm->drv_rx_stats.vht_frames++;
|
||||
nss = ((rate & RATE_VHT_MCS_NSS_MSK) >>
|
||||
RATE_VHT_MCS_NSS_POS) + 1;
|
||||
nss = FIELD_GET(RATE_MCS_NSS_MSK, rate) + 1;
|
||||
} else {
|
||||
mvm->drv_rx_stats.legacy_frames++;
|
||||
}
|
||||
|
|
@ -3665,8 +3662,7 @@ int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate)
|
|||
if (rate & RATE_MCS_VHT_MSK_V1) {
|
||||
type = "VHT";
|
||||
mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
|
||||
nss = ((rate & RATE_VHT_MCS_NSS_MSK)
|
||||
>> RATE_VHT_MCS_NSS_POS) + 1;
|
||||
nss = FIELD_GET(RATE_MCS_NSS_MSK, rate) + 1;
|
||||
} else if (rate & RATE_MCS_HT_MSK_V1) {
|
||||
type = "HT";
|
||||
mcs = rate & RATE_HT_MCS_INDEX_MSK_V1;
|
||||
|
|
@ -3675,8 +3671,7 @@ int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate)
|
|||
} else if (rate & RATE_MCS_HE_MSK_V1) {
|
||||
type = "HE";
|
||||
mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
|
||||
nss = ((rate & RATE_VHT_MCS_NSS_MSK)
|
||||
>> RATE_VHT_MCS_NSS_POS) + 1;
|
||||
nss = FIELD_GET(RATE_MCS_NSS_MSK, rate) + 1;
|
||||
} else {
|
||||
type = "Unknown"; /* shouldn't happen */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
|
|||
default:
|
||||
/* Expected in monitor (not having the keys) */
|
||||
if (!mvm->monitor_on)
|
||||
IWL_ERR(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status);
|
||||
IWL_WARN(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -253,8 +253,7 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,
|
|||
ARRAY_SIZE(thresh_tpt)))
|
||||
return;
|
||||
thr = thresh_tpt[rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK];
|
||||
thr *= 1 + ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
|
||||
RATE_VHT_MCS_NSS_POS);
|
||||
thr *= 1 + FIELD_GET(RATE_MCS_NSS_MSK, rate_n_flags);
|
||||
}
|
||||
|
||||
thr <<= ((rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) >>
|
||||
|
|
@ -500,8 +499,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
|
||||
RATE_MCS_STBC_POS;
|
||||
rx_status->nss =
|
||||
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
|
||||
RATE_VHT_MCS_NSS_POS) + 1;
|
||||
FIELD_GET(RATE_MCS_NSS_MSK, rate_n_flags) + 1;
|
||||
rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
|
||||
rx_status->encoding = RX_ENC_VHT;
|
||||
rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
|
@ -205,37 +205,47 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* put a TLV on the skb and return data pointer
|
||||
*
|
||||
* Also pad to 4 the len and zero out all data part
|
||||
*/
|
||||
static void *
|
||||
iwl_mvm_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len)
|
||||
{
|
||||
struct ieee80211_radiotap_tlv *tlv;
|
||||
|
||||
tlv = skb_put(skb, sizeof(*tlv));
|
||||
tlv->type = cpu_to_le16(type);
|
||||
tlv->len = cpu_to_le16(len);
|
||||
return skb_put_zero(skb, ALIGN(len, 4));
|
||||
}
|
||||
|
||||
static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_vendor_radiotap *radiotap;
|
||||
const int size = sizeof(*radiotap) + sizeof(__le16);
|
||||
struct ieee80211_radiotap_vendor_content *radiotap;
|
||||
const u16 vendor_data_len = sizeof(mvm->cur_aid);
|
||||
|
||||
if (!mvm->cur_aid)
|
||||
return;
|
||||
|
||||
/* ensure alignment */
|
||||
BUILD_BUG_ON((size + 2) % 4);
|
||||
radiotap = iwl_mvm_radiotap_put_tlv(skb,
|
||||
IEEE80211_RADIOTAP_VENDOR_NAMESPACE,
|
||||
sizeof(*radiotap) + vendor_data_len);
|
||||
|
||||
radiotap = skb_put(skb, size + 2);
|
||||
radiotap->align = 1;
|
||||
/* Intel OUI */
|
||||
radiotap->oui[0] = 0xf6;
|
||||
radiotap->oui[1] = 0x54;
|
||||
radiotap->oui[2] = 0x25;
|
||||
/* radiotap sniffer config sub-namespace */
|
||||
radiotap->subns = 1;
|
||||
radiotap->present = 0x1;
|
||||
radiotap->len = size - sizeof(*radiotap);
|
||||
radiotap->pad = 2;
|
||||
radiotap->oui_subtype = 1;
|
||||
radiotap->vendor_type = 0;
|
||||
|
||||
/* fill the data now */
|
||||
memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid));
|
||||
/* and clear the padding */
|
||||
memset(radiotap->data + sizeof(__le16), 0, radiotap->pad);
|
||||
|
||||
rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA;
|
||||
rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
|
||||
}
|
||||
|
||||
/* iwl_mvm_pass_packet_to_mac80211 - passes the packet for mac80211 */
|
||||
|
|
@ -443,7 +453,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
*/
|
||||
if (!is_multicast_ether_addr(hdr->addr1) &&
|
||||
!mvm->monitor_on && net_ratelimit())
|
||||
IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status);
|
||||
IWL_WARN(mvm, "Unhandled alg: 0x%x\n", status);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1167,8 +1177,11 @@ static void iwl_mvm_flip_address(u8 *addr)
|
|||
|
||||
struct iwl_mvm_rx_phy_data {
|
||||
enum iwl_rx_phy_info_type info_type;
|
||||
__le32 d0, d1, d2, d3;
|
||||
__le32 d0, d1, d2, d3, eht_d4, d5;
|
||||
__le16 d4;
|
||||
bool with_data;
|
||||
bool first_subframe;
|
||||
__le32 rx_vec[4];
|
||||
|
||||
u32 rate_n_flags;
|
||||
u32 gp2_on_air_rise;
|
||||
|
|
@ -1446,6 +1459,528 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
|
|||
}
|
||||
}
|
||||
|
||||
#define LE32_DEC_ENC(value, dec_bits, enc_bits) \
|
||||
le32_encode_bits(le32_get_bits(value, dec_bits), enc_bits)
|
||||
|
||||
#define IWL_MVM_ENC_USIG_VALUE_MASK(usig, in_value, dec_bits, enc_bits) do { \
|
||||
typeof(enc_bits) _enc_bits = enc_bits; \
|
||||
typeof(usig) _usig = usig; \
|
||||
(_usig)->mask |= cpu_to_le32(_enc_bits); \
|
||||
(_usig)->value |= LE32_DEC_ENC(in_value, dec_bits, _enc_bits); \
|
||||
} while (0)
|
||||
|
||||
#define __IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \
|
||||
eht->data[(rt_data)] |= \
|
||||
(cpu_to_le32 \
|
||||
(IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru ## _KNOWN) | \
|
||||
LE32_DEC_ENC(data ## fw_data, \
|
||||
IWL_RX_PHY_DATA ## fw_data ## _EHT_MU_EXT_RU_ALLOC_ ## fw_ru, \
|
||||
IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru))
|
||||
|
||||
#define _IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \
|
||||
__IWL_MVM_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru)
|
||||
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_1_1 1
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_1_1 2
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_1_2 2
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_1_2 2
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_2_1 3
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_2_1 3
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_1_2_2 3
|
||||
#define IEEE80211_RADIOTAP_RU_DATA_2_2_2 4
|
||||
|
||||
#define IWL_RX_RU_DATA_A1 2
|
||||
#define IWL_RX_RU_DATA_A2 2
|
||||
#define IWL_RX_RU_DATA_B1 2
|
||||
#define IWL_RX_RU_DATA_B2 3
|
||||
#define IWL_RX_RU_DATA_C1 3
|
||||
#define IWL_RX_RU_DATA_C2 3
|
||||
#define IWL_RX_RU_DATA_D1 4
|
||||
#define IWL_RX_RU_DATA_D2 4
|
||||
|
||||
#define IWL_MVM_ENC_EHT_RU(rt_ru, fw_ru) \
|
||||
_IWL_MVM_ENC_EHT_RU(IEEE80211_RADIOTAP_RU_DATA_ ## rt_ru, \
|
||||
rt_ru, \
|
||||
IWL_RX_RU_DATA_ ## fw_ru, \
|
||||
fw_ru)
|
||||
|
||||
static void iwl_mvm_decode_eht_ext_mu(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_rx_phy_data *phy_data,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_radiotap_eht *eht,
|
||||
struct ieee80211_radiotap_eht_usig *usig)
|
||||
{
|
||||
if (phy_data->with_data) {
|
||||
__le32 data1 = phy_data->d1;
|
||||
__le32 data2 = phy_data->d2;
|
||||
__le32 data3 = phy_data->d3;
|
||||
__le32 data4 = phy_data->eht_d4;
|
||||
__le32 data5 = phy_data->d5;
|
||||
u32 phy_bw = phy_data->rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;
|
||||
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
|
||||
IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
|
||||
IWL_RX_PHY_DATA5_EHT_MU_PUNC_CH_CODE,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, data4,
|
||||
IWL_RX_PHY_DATA4_EHT_MU_EXT_SIGB_MCS,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK
|
||||
(usig, data1, IWL_RX_PHY_DATA1_EHT_MU_NUM_SIG_SYM_USIGA2,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS);
|
||||
|
||||
eht->user_info[0] |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN) |
|
||||
LE32_DEC_ENC(data5, IWL_RX_PHY_DATA5_EHT_MU_STA_ID_USR,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID);
|
||||
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NR_NON_OFDMA_USERS_M);
|
||||
eht->data[7] |= LE32_DEC_ENC
|
||||
(data5, IWL_RX_PHY_DATA5_EHT_MU_NUM_USR_NON_OFDMA,
|
||||
IEEE80211_RADIOTAP_EHT_DATA7_NUM_OF_NON_OFDMA_USERS);
|
||||
|
||||
/*
|
||||
* Hardware labels the content channels/RU allocation values
|
||||
* as follows:
|
||||
* Content Channel 1 Content Channel 2
|
||||
* 20 MHz: A1
|
||||
* 40 MHz: A1 B1
|
||||
* 80 MHz: A1 C1 B1 D1
|
||||
* 160 MHz: A1 C1 A2 C2 B1 D1 B2 D2
|
||||
* 320 MHz: A1 C1 A2 C2 A3 C3 A4 C4 B1 D1 B2 D2 B3 D3 B4 D4
|
||||
*
|
||||
* However firmware can only give us A1-D2, so the higher
|
||||
* frequencies are missing.
|
||||
*/
|
||||
|
||||
switch (phy_bw) {
|
||||
case RATE_MCS_CHAN_WIDTH_320:
|
||||
/* additional values are missing in RX metadata */
|
||||
case RATE_MCS_CHAN_WIDTH_160:
|
||||
/* content channel 1 */
|
||||
IWL_MVM_ENC_EHT_RU(1_2_1, A2);
|
||||
IWL_MVM_ENC_EHT_RU(1_2_2, C2);
|
||||
/* content channel 2 */
|
||||
IWL_MVM_ENC_EHT_RU(2_2_1, B2);
|
||||
IWL_MVM_ENC_EHT_RU(2_2_2, D2);
|
||||
fallthrough;
|
||||
case RATE_MCS_CHAN_WIDTH_80:
|
||||
/* content channel 1 */
|
||||
IWL_MVM_ENC_EHT_RU(1_1_2, C1);
|
||||
/* content channel 2 */
|
||||
IWL_MVM_ENC_EHT_RU(2_1_2, D1);
|
||||
fallthrough;
|
||||
case RATE_MCS_CHAN_WIDTH_40:
|
||||
/* content channel 2 */
|
||||
IWL_MVM_ENC_EHT_RU(2_1_1, B1);
|
||||
fallthrough;
|
||||
case RATE_MCS_CHAN_WIDTH_20:
|
||||
IWL_MVM_ENC_EHT_RU(1_1_1, A1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
__le32 usig_a1 = phy_data->rx_vec[0];
|
||||
__le32 usig_a2 = phy_data->rx_vec[1];
|
||||
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1,
|
||||
IWL_RX_USIG_A1_DISREGARD,
|
||||
IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1,
|
||||
IWL_RX_USIG_A1_VALIDATE,
|
||||
IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_PPDU_TYPE,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_PUNC_CHANNEL,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B8,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_SIG_MCS,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK
|
||||
(usig, usig_a2, IWL_RX_USIG_A2_EHT_SIG_SYM_NUM,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_CRC_OK,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_decode_eht_ext_tb(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_rx_phy_data *phy_data,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_radiotap_eht *eht,
|
||||
struct ieee80211_radiotap_eht_usig *usig)
|
||||
{
|
||||
if (phy_data->with_data) {
|
||||
__le32 data5 = phy_data->d5;
|
||||
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
|
||||
IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
|
||||
IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE1,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1);
|
||||
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, data5,
|
||||
IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE2,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2);
|
||||
} else {
|
||||
__le32 usig_a1 = phy_data->rx_vec[0];
|
||||
__le32 usig_a2 = phy_data->rx_vec[1];
|
||||
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a1,
|
||||
IWL_RX_USIG_A1_DISREGARD,
|
||||
IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_PPDU_TYPE,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_1,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_2,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_TRIG_USIG2_DISREGARD,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD);
|
||||
IWL_MVM_ENC_USIG_VALUE_MASK(usig, usig_a2,
|
||||
IWL_RX_USIG_A2_EHT_CRC_OK,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_decode_eht_ru(struct iwl_mvm *mvm,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_radiotap_eht *eht)
|
||||
{
|
||||
u32 ru = le32_get_bits(eht->data[8],
|
||||
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);
|
||||
enum nl80211_eht_ru_alloc nl_ru;
|
||||
|
||||
/* Using D1.5 Table 9-53a - Encoding of PS160 and RU Allocation subfields
|
||||
* in an EHT variant User Info field
|
||||
*/
|
||||
|
||||
switch (ru) {
|
||||
case 0 ... 36:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_26;
|
||||
break;
|
||||
case 37 ... 52:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_52;
|
||||
break;
|
||||
case 53 ... 60:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_106;
|
||||
break;
|
||||
case 61 ... 64:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_242;
|
||||
break;
|
||||
case 65 ... 66:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_484;
|
||||
break;
|
||||
case 67:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996;
|
||||
break;
|
||||
case 68:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_2x996;
|
||||
break;
|
||||
case 69:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_4x996;
|
||||
break;
|
||||
case 70 ... 81:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_52P26;
|
||||
break;
|
||||
case 82 ... 89:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_106P26;
|
||||
break;
|
||||
case 90 ... 93:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_484P242;
|
||||
break;
|
||||
case 94 ... 95:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996P484;
|
||||
break;
|
||||
case 96 ... 99:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242;
|
||||
break;
|
||||
case 100 ... 103:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484;
|
||||
break;
|
||||
case 104:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_3x996;
|
||||
break;
|
||||
case 105 ... 106:
|
||||
nl_ru = NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
rx_status->bw = RATE_INFO_BW_EHT_RU;
|
||||
rx_status->eht.ru = nl_ru;
|
||||
}
|
||||
|
||||
static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_rx_phy_data *phy_data,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_radiotap_eht *eht,
|
||||
struct ieee80211_radiotap_eht_usig *usig)
|
||||
|
||||
{
|
||||
__le32 data0 = phy_data->d0;
|
||||
__le32 data1 = phy_data->d1;
|
||||
__le32 usig_a1 = phy_data->rx_vec[0];
|
||||
u8 info_type = phy_data->info_type;
|
||||
|
||||
/* Not in EHT range */
|
||||
if (info_type < IWL_RX_PHY_INFO_TYPE_EHT_MU ||
|
||||
info_type > IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT)
|
||||
return;
|
||||
|
||||
usig->common |= cpu_to_le32
|
||||
(IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN |
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN);
|
||||
if (phy_data->with_data) {
|
||||
usig->common |= LE32_DEC_ENC(data0,
|
||||
IWL_RX_PHY_DATA0_EHT_UPLINK,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);
|
||||
usig->common |= LE32_DEC_ENC(data0,
|
||||
IWL_RX_PHY_DATA0_EHT_BSS_COLOR_MASK,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
|
||||
} else {
|
||||
usig->common |= LE32_DEC_ENC(usig_a1,
|
||||
IWL_RX_USIG_A1_UL_FLAG,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);
|
||||
usig->common |= LE32_DEC_ENC(usig_a1,
|
||||
IWL_RX_USIG_A1_BSS_COLOR,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
|
||||
}
|
||||
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE);
|
||||
eht->data[0] |= LE32_DEC_ENC(data0,
|
||||
IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE);
|
||||
|
||||
/* All RU allocating size/index is in TB format */
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT);
|
||||
eht->data[8] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PS160,
|
||||
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160);
|
||||
eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_B0,
|
||||
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0);
|
||||
eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC,
|
||||
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);
|
||||
|
||||
iwl_mvm_decode_eht_ru(mvm, rx_status, eht);
|
||||
|
||||
/* We only get here in case of IWL_RX_MPDU_PHY_TSF_OVERLOAD is set
|
||||
* which is on only in case of monitor mode so no need to check monitor
|
||||
* mode
|
||||
*/
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRIMARY_80);
|
||||
eht->data[1] |=
|
||||
le32_encode_bits(mvm->monitor_p80,
|
||||
IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80);
|
||||
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN);
|
||||
if (phy_data->with_data)
|
||||
usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_TXOP_DUR_MASK,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
|
||||
else
|
||||
usig->common |= LE32_DEC_ENC(usig_a1, IWL_RX_USIG_A1_TXOP_DURATION,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
|
||||
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM);
|
||||
eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_LDPC_EXT_SYM,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM);
|
||||
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM);
|
||||
eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PRE_FEC_PAD_MASK,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM);
|
||||
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM);
|
||||
eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PE_DISAMBIG,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM);
|
||||
|
||||
/* TODO: what about IWL_RX_PHY_DATA0_EHT_BW320_SLOT */
|
||||
|
||||
if (!le32_get_bits(data0, IWL_RX_PHY_DATA0_EHT_SIGA_CRC_OK))
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
|
||||
|
||||
usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN);
|
||||
usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PHY_VER,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER);
|
||||
|
||||
/*
|
||||
* TODO: what about TB - IWL_RX_PHY_DATA1_EHT_TB_PILOT_TYPE,
|
||||
* IWL_RX_PHY_DATA1_EHT_TB_LOW_SS
|
||||
*/
|
||||
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF);
|
||||
eht->data[0] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF);
|
||||
|
||||
if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT ||
|
||||
info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB)
|
||||
iwl_mvm_decode_eht_ext_tb(mvm, phy_data, rx_status, eht, usig);
|
||||
|
||||
if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT ||
|
||||
info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU)
|
||||
iwl_mvm_decode_eht_ext_mu(mvm, phy_data, rx_status, eht, usig);
|
||||
}
|
||||
|
||||
static void iwl_mvm_rx_eht(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
struct iwl_mvm_rx_phy_data *phy_data,
|
||||
int queue)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
struct ieee80211_radiotap_eht *eht;
|
||||
struct ieee80211_radiotap_eht_usig *usig;
|
||||
size_t eht_len = sizeof(*eht);
|
||||
|
||||
u32 rate_n_flags = phy_data->rate_n_flags;
|
||||
u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
|
||||
/* EHT and HE have the same valus for LTF */
|
||||
u8 ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;
|
||||
u16 phy_info = phy_data->phy_info;
|
||||
u32 bw;
|
||||
|
||||
/* u32 for 1 user_info */
|
||||
if (phy_data->with_data)
|
||||
eht_len += sizeof(u32);
|
||||
|
||||
eht = iwl_mvm_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len);
|
||||
|
||||
usig = iwl_mvm_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG,
|
||||
sizeof(*usig));
|
||||
rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
|
||||
usig->common |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN);
|
||||
|
||||
/* specific handling for 320MHz */
|
||||
bw = FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, rate_n_flags);
|
||||
if (bw == RATE_MCS_CHAN_WIDTH_320_VAL)
|
||||
bw += FIELD_GET(IWL_RX_PHY_DATA0_EHT_BW320_SLOT,
|
||||
le32_to_cpu(phy_data->d0));
|
||||
|
||||
usig->common |= cpu_to_le32
|
||||
(FIELD_PREP(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW, bw));
|
||||
|
||||
/* report the AMPDU-EOF bit on single frames */
|
||||
if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
|
||||
rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
|
||||
if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
|
||||
}
|
||||
|
||||
/* update aggregation data for monitor sake on default queue */
|
||||
if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) &&
|
||||
(phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) {
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
|
||||
if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
|
||||
}
|
||||
|
||||
if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
|
||||
iwl_mvm_decode_eht_phy_data(mvm, phy_data, rx_status, eht, usig);
|
||||
|
||||
#define CHECK_TYPE(F) \
|
||||
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_ ## F != \
|
||||
(RATE_MCS_HE_TYPE_ ## F >> RATE_MCS_HE_TYPE_POS))
|
||||
|
||||
CHECK_TYPE(SU);
|
||||
CHECK_TYPE(EXT_SU);
|
||||
CHECK_TYPE(MU);
|
||||
CHECK_TYPE(TRIG);
|
||||
|
||||
switch (FIELD_GET(RATE_MCS_HE_GI_LTF_MSK, rate_n_flags)) {
|
||||
case 0:
|
||||
if (he_type == RATE_MCS_HE_TYPE_TRIG) {
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6;
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X;
|
||||
} else {
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8;
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6;
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X;
|
||||
break;
|
||||
case 2:
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
|
||||
if (he_type == RATE_MCS_HE_TYPE_TRIG)
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2;
|
||||
else
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8;
|
||||
break;
|
||||
case 3:
|
||||
if (he_type != RATE_MCS_HE_TYPE_TRIG) {
|
||||
ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
|
||||
rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* nothing here */
|
||||
break;
|
||||
}
|
||||
|
||||
if (ltf != IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN) {
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_GI);
|
||||
eht->data[0] |= cpu_to_le32
|
||||
(FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_LTF,
|
||||
ltf) |
|
||||
FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_GI,
|
||||
rx_status->eht.gi));
|
||||
}
|
||||
|
||||
|
||||
if (!phy_data->with_data) {
|
||||
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NSS_S |
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_BEAMFORMED_S);
|
||||
eht->data[7] |=
|
||||
le32_encode_bits(le32_get_bits(phy_data->rx_vec[2],
|
||||
RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK),
|
||||
IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);
|
||||
if (rate_n_flags & RATE_MCS_BF_MSK)
|
||||
eht->data[7] |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_EHT_DATA7_BEAMFORMED_S);
|
||||
} else {
|
||||
eht->user_info[0] |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN |
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN |
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O |
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_KNOWN_O |
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_DATA_FOR_USER);
|
||||
|
||||
if (rate_n_flags & RATE_MCS_BF_MSK)
|
||||
eht->user_info[0] |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_O);
|
||||
|
||||
if (rate_n_flags & RATE_MCS_LDPC_MSK)
|
||||
eht->user_info[0] |=
|
||||
cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_CODING);
|
||||
|
||||
eht->user_info[0] |= cpu_to_le32
|
||||
(FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS,
|
||||
FIELD_GET(RATE_VHT_MCS_RATE_CODE_MSK,
|
||||
rate_n_flags)) |
|
||||
FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O,
|
||||
FIELD_GET(RATE_MCS_NSS_MSK, rate_n_flags)));
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
struct iwl_mvm_rx_phy_data *phy_data,
|
||||
int queue)
|
||||
|
|
@ -1497,15 +2032,10 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
|
||||
/* update aggregation data for monitor sake on default queue */
|
||||
if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) &&
|
||||
(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
|
||||
bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
|
||||
|
||||
/* toggle is switched whenever new aggregation starts */
|
||||
if (toggle_bit != mvm->ampdu_toggle) {
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
|
||||
if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF))
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
|
||||
}
|
||||
(phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) {
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
|
||||
if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
|
||||
}
|
||||
|
||||
if (he_type == RATE_MCS_HE_TYPE_EXT_SU &&
|
||||
|
|
@ -1593,6 +2123,10 @@ static void iwl_mvm_decode_lsig(struct sk_buff *skb,
|
|||
case IWL_RX_PHY_INFO_TYPE_HE_MU:
|
||||
case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
|
||||
case IWL_RX_PHY_INFO_TYPE_HE_TB:
|
||||
case IWL_RX_PHY_INFO_TYPE_EHT_MU:
|
||||
case IWL_RX_PHY_INFO_TYPE_EHT_TB:
|
||||
case IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT:
|
||||
case IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT:
|
||||
lsig = skb_put(skb, sizeof(*lsig));
|
||||
lsig->data1 = cpu_to_le16(IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN);
|
||||
lsig->data2 = le16_encode_bits(le32_get_bits(phy_data->d1,
|
||||
|
|
@ -1689,6 +2223,10 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,
|
|||
iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags,
|
||||
phy_data->energy_a, phy_data->energy_b);
|
||||
|
||||
/* using TLV format and must be after all fixed len fields */
|
||||
if (format == RATE_MCS_EHT_MSK)
|
||||
iwl_mvm_rx_eht(mvm, skb, phy_data, queue);
|
||||
|
||||
if (unlikely(mvm->monitor_on))
|
||||
iwl_mvm_add_rtap_sniffer_config(mvm, skb);
|
||||
|
||||
|
|
@ -1788,6 +2326,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
phy_data.d1 = desc->v3.phy_data1;
|
||||
phy_data.d2 = desc->v3.phy_data2;
|
||||
phy_data.d3 = desc->v3.phy_data3;
|
||||
phy_data.eht_d4 = desc->phy_eht_data4;
|
||||
phy_data.d5 = desc->v3.phy_data5;
|
||||
} else {
|
||||
phy_data.rate_n_flags = le32_to_cpu(desc->v1.rate_n_flags);
|
||||
phy_data.channel = desc->v1.channel;
|
||||
|
|
@ -1817,6 +2357,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
return;
|
||||
}
|
||||
|
||||
phy_data.with_data = true;
|
||||
phy_data.phy_info = le16_to_cpu(desc->phy_info);
|
||||
phy_data.d4 = desc->phy_data4;
|
||||
|
||||
|
|
@ -1897,6 +2438,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
if (mvm->ampdu_ref == 0)
|
||||
mvm->ampdu_ref++;
|
||||
mvm->ampdu_toggle = toggle_bit;
|
||||
phy_data.first_subframe = true;
|
||||
}
|
||||
rx_status->ampdu_reference = mvm->ampdu_ref;
|
||||
}
|
||||
|
|
@ -2079,6 +2621,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
phy_data.energy_a = u32_get_bits(rssi, RX_NO_DATA_CHAIN_A_MSK);
|
||||
phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK);
|
||||
phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK);
|
||||
phy_data.with_data = false;
|
||||
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
|
||||
RX_NO_DATA_NOTIF, 0) < 2) {
|
||||
|
|
@ -2097,6 +2640,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
sizeof(struct iwl_rx_no_data_ver_3)))
|
||||
/* invalid len for ver 3 */
|
||||
return;
|
||||
memcpy(phy_data.rx_vec, desc->rx_vec, sizeof(phy_data.rx_vec));
|
||||
} else {
|
||||
if (format == RATE_MCS_EHT_MSK)
|
||||
/* no support for EHT before version 3 API */
|
||||
|
|
@ -2123,7 +2667,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
|
||||
break;
|
||||
case RX_NO_DATA_INFO_TYPE_MU_UNMATCHED:
|
||||
case RX_NO_DATA_INFO_TYPE_HE_TB_UNMATCHED:
|
||||
case RX_NO_DATA_INFO_TYPE_TB_UNMATCHED:
|
||||
rx_status->zero_length_psdu_type =
|
||||
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED;
|
||||
break;
|
||||
|
|
@ -2142,11 +2686,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
*
|
||||
* We mark it as mac header, for upper layers to know where
|
||||
* all radio tap header ends.
|
||||
*
|
||||
* Since data doesn't move data while putting data on skb and that is
|
||||
* the only way we use, data + len is the next place that hdr would be put
|
||||
*/
|
||||
skb_set_mac_header(skb, skb->len);
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
/*
|
||||
* Override the nss from the rx_vec since the rate_n_flags has
|
||||
|
|
|
|||
|
|
@ -1396,8 +1396,8 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
|
|||
r->idx = rate;
|
||||
} else if (format == RATE_MCS_VHT_MSK) {
|
||||
ieee80211_rate_set_vht(r, rate,
|
||||
((rate_n_flags & RATE_MCS_NSS_MSK) >>
|
||||
RATE_MCS_NSS_POS) + 1);
|
||||
FIELD_GET(RATE_MCS_NSS_MSK,
|
||||
rate_n_flags) + 1);
|
||||
r->flags |= IEEE80211_TX_RC_VHT_MCS;
|
||||
} else if (format == RATE_MCS_HE_MSK) {
|
||||
/* mac80211 cannot do this without ieee80211_tx_status_ext()
|
||||
|
|
@ -1428,8 +1428,7 @@ void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags,
|
|||
} else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) {
|
||||
ieee80211_rate_set_vht(
|
||||
r, rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK,
|
||||
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
|
||||
RATE_VHT_MCS_NSS_POS) + 1);
|
||||
FIELD_GET(RATE_MCS_NSS_MSK, rate_n_flags) + 1);
|
||||
r->flags |= IEEE80211_TX_RC_VHT_MCS;
|
||||
} else {
|
||||
r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
|
||||
|
|
|
|||
|
|
@ -1193,6 +1193,11 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
|
||||
iwl_cfg_bnj_a0_fm4_a0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
|
||||
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
|
||||
iwl_cfg_bnj_b0_fm4_b0, iwl_bz_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
*/
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
|
|
@ -277,6 +277,9 @@ static void iwl_pcie_get_rf_name(struct iwl_trans *trans)
|
|||
case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HRCDB):
|
||||
pos = scnprintf(buf, buflen, "HRCDB");
|
||||
break;
|
||||
case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_MS):
|
||||
pos = scnprintf(buf, buflen, "MS");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1534,37 +1534,38 @@ static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb)
|
|||
* the values accordingly.
|
||||
*/
|
||||
#ifdef HWSIM_RADIOTAP_OUI
|
||||
struct ieee80211_vendor_radiotap *rtap;
|
||||
struct ieee80211_radiotap_vendor_tlv *rtap;
|
||||
static const char vendor_data[8] = "ABCDEFGH";
|
||||
|
||||
// Make sure no padding is needed
|
||||
BUILD_BUG_ON(sizeof(vendor_data) % 4);
|
||||
/* this is last radiotap info before the mac header, so
|
||||
* skb_reset_mac_header for mac8022 to know the end of
|
||||
* the radiotap TLV/beginning of the 802.11 header
|
||||
*/
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
/*
|
||||
* Note that this code requires the headroom in the SKB
|
||||
* that was allocated earlier.
|
||||
*/
|
||||
rtap = skb_push(skb, sizeof(*rtap) + 8 + 4);
|
||||
rtap->oui[0] = HWSIM_RADIOTAP_OUI[0];
|
||||
rtap->oui[1] = HWSIM_RADIOTAP_OUI[1];
|
||||
rtap->oui[2] = HWSIM_RADIOTAP_OUI[2];
|
||||
rtap->subns = 127;
|
||||
rtap = skb_push(skb, sizeof(*rtap) + sizeof(vendor_data));
|
||||
|
||||
/*
|
||||
* Radiotap vendor namespaces can (and should) also be
|
||||
* split into fields by using the standard radiotap
|
||||
* presence bitmap mechanism. Use just BIT(0) here for
|
||||
* the presence bitmap.
|
||||
*/
|
||||
rtap->present = BIT(0);
|
||||
/* We have 8 bytes of (dummy) data */
|
||||
rtap->len = 8;
|
||||
/* For testing, also require it to be aligned */
|
||||
rtap->align = 8;
|
||||
/* And also test that padding works, 4 bytes */
|
||||
rtap->pad = 4;
|
||||
/* push the data */
|
||||
memcpy(rtap->data, "ABCDEFGH", 8);
|
||||
/* make sure to clear padding, mac80211 doesn't */
|
||||
memset(rtap->data + 8, 0, 4);
|
||||
rtap->len = cpu_to_le16(sizeof(*rtap) -
|
||||
sizeof(struct ieee80211_radiotap_tlv) +
|
||||
sizeof(vendor_data));
|
||||
rtap->type = cpu_to_le16(IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
|
||||
|
||||
IEEE80211_SKB_RXCB(skb)->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA;
|
||||
rtap->content.oui[0] = HWSIM_RADIOTAP_OUI[0];
|
||||
rtap->content.oui[1] = HWSIM_RADIOTAP_OUI[1];
|
||||
rtap->content.oui[2] = HWSIM_RADIOTAP_OUI[2];
|
||||
rtap->content.oui_subtype = 127;
|
||||
/* clear reserved field */
|
||||
rtap->content.reserved = 0;
|
||||
rtap->content.vendor_type = 0;
|
||||
memcpy(rtap->content.data, vendor_data, sizeof(vendor_data));
|
||||
|
||||
IEEE80211_SKB_RXCB(skb)->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -4446,6 +4447,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||
wiphy_ext_feature_set(hw->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
|
||||
|
||||
wiphy_ext_feature_set(hw->wiphy,
|
||||
NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT);
|
||||
|
||||
hw->wiphy->interface_modes = param->iftypes;
|
||||
|
||||
/* ask mac80211 to reserve space for magic */
|
||||
|
|
|
|||
|
|
@ -1699,6 +1699,12 @@ void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *s
|
|||
|
||||
dev_dbg(dev, "%s: len: %d items: %d\n", __func__, tx_rpt_len, items);
|
||||
|
||||
/* We only use macid 0, so only the first item is relevant.
|
||||
* AP mode will use more of them if it's ever implemented.
|
||||
*/
|
||||
if (!priv->vif || priv->vif->type == NL80211_IFTYPE_STATION)
|
||||
items = 1;
|
||||
|
||||
for (macid = 0; macid < items; macid++) {
|
||||
valid = false;
|
||||
|
||||
|
|
@ -1741,12 +1747,6 @@ void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *s
|
|||
min_rpt_time = ra->rpt_time;
|
||||
|
||||
rpt += TX_RPT2_ITEM_SIZE;
|
||||
|
||||
/*
|
||||
* We only use macid 0, so only the first item is relevant.
|
||||
* AP mode will use more of them if it's ever implemented.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (min_rpt_time != ra->pre_min_rpt_time) {
|
||||
|
|
|
|||
|
|
@ -1575,11 +1575,7 @@ rtl8xxxu_set_spec_sifs(struct rtl8xxxu_priv *priv, u16 cck, u16 ofdm)
|
|||
static void rtl8xxxu_print_chipinfo(struct rtl8xxxu_priv *priv)
|
||||
{
|
||||
struct device *dev = &priv->udev->dev;
|
||||
char cut = '?';
|
||||
|
||||
/* Currently always true: chip_cut is 4 bits. */
|
||||
if (priv->chip_cut <= 15)
|
||||
cut = 'A' + priv->chip_cut;
|
||||
char cut = 'A' + priv->chip_cut;
|
||||
|
||||
dev_info(dev,
|
||||
"RTL%s rev %c (%s) romver %d, %iT%iR, TX queues %i, WiFi=%i, BT=%i, GPS=%i, HI PA=%i\n",
|
||||
|
|
|
|||
|
|
@ -1428,7 +1428,9 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
|
|||
|
||||
for (rf_path = 0; rf_path < 2; rf_path++) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!autoload_fail) {
|
||||
if (!autoload_fail &&
|
||||
hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i] != 0xff &&
|
||||
hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 + i] != 0xff) {
|
||||
rtlefuse->
|
||||
eeprom_chnlarea_txpwr_cck[rf_path][i] =
|
||||
hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i];
|
||||
|
|
@ -1448,7 +1450,8 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!autoload_fail)
|
||||
if (!autoload_fail &&
|
||||
hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i] != 0xff)
|
||||
tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i];
|
||||
else
|
||||
tempval = EEPROM_DEFAULT_HT40_2SDIFF;
|
||||
|
|
@ -1518,7 +1521,9 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!autoload_fail) {
|
||||
if (!autoload_fail &&
|
||||
hwinfo[EEPROM_TXPWR_GROUP + i] != 0xff &&
|
||||
hwinfo[EEPROM_TXPWR_GROUP + 3 + i] != 0xff) {
|
||||
rtlefuse->eeprom_pwrlimit_ht40[i] =
|
||||
hwinfo[EEPROM_TXPWR_GROUP + i];
|
||||
rtlefuse->eeprom_pwrlimit_ht20[i] =
|
||||
|
|
@ -1563,7 +1568,8 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
|
|||
for (i = 0; i < 14; i++) {
|
||||
index = rtl92c_get_chnl_group((u8)i);
|
||||
|
||||
if (!autoload_fail)
|
||||
if (!autoload_fail &&
|
||||
hwinfo[EEPROM_TXPOWERHT20DIFF + index] != 0xff)
|
||||
tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index];
|
||||
else
|
||||
tempval = EEPROM_DEFAULT_HT20_DIFF;
|
||||
|
|
@ -1580,7 +1586,8 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
|
|||
|
||||
index = rtl92c_get_chnl_group((u8)i);
|
||||
|
||||
if (!autoload_fail)
|
||||
if (!autoload_fail &&
|
||||
hwinfo[EEPROM_TXPOWER_OFDMDIFF + index] != 0xff)
|
||||
tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index];
|
||||
else
|
||||
tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
|
||||
|
|
@ -1610,14 +1617,16 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
|
|||
"RF-B Legacy to HT40 Diff[%d] = 0x%x\n",
|
||||
i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]);
|
||||
|
||||
if (!autoload_fail)
|
||||
if (!autoload_fail && hwinfo[RF_OPTION1] != 0xff)
|
||||
rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7);
|
||||
else
|
||||
rtlefuse->eeprom_regulatory = 0;
|
||||
RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
|
||||
"eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
|
||||
|
||||
if (!autoload_fail) {
|
||||
if (!autoload_fail &&
|
||||
hwinfo[EEPROM_TSSI_A] != 0xff &&
|
||||
hwinfo[EEPROM_TSSI_B] != 0xff) {
|
||||
rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A];
|
||||
rtlefuse->eeprom_tssi[RF90_PATH_B] = hwinfo[EEPROM_TSSI_B];
|
||||
} else {
|
||||
|
|
@ -1628,7 +1637,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
|
|||
rtlefuse->eeprom_tssi[RF90_PATH_A],
|
||||
rtlefuse->eeprom_tssi[RF90_PATH_B]);
|
||||
|
||||
if (!autoload_fail)
|
||||
if (!autoload_fail && hwinfo[EEPROM_THERMAL_METER] != 0xff)
|
||||
tempval = hwinfo[EEPROM_THERMAL_METER];
|
||||
else
|
||||
tempval = EEPROM_DEFAULT_THERMALMETER;
|
||||
|
|
|
|||
|
|
@ -1047,7 +1047,6 @@ static int _rtl92de_set_media_status(struct ieee80211_hw *hw,
|
|||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
|
||||
enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
|
||||
u8 bcnfunc_enable;
|
||||
|
||||
bt_msr &= 0xfc;
|
||||
|
||||
|
|
@ -1064,31 +1063,26 @@ static int _rtl92de_set_media_status(struct ieee80211_hw *hw,
|
|||
"Set HW_VAR_MEDIA_STATUS: No such media status(%x)\n",
|
||||
type);
|
||||
}
|
||||
bcnfunc_enable = rtl_read_byte(rtlpriv, REG_BCN_CTRL);
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
bt_msr |= MSR_NOLINK;
|
||||
ledaction = LED_CTL_LINK;
|
||||
bcnfunc_enable &= 0xF7;
|
||||
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
|
||||
"Set Network type to NO LINK!\n");
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
bt_msr |= MSR_ADHOC;
|
||||
bcnfunc_enable |= 0x08;
|
||||
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
|
||||
"Set Network type to Ad Hoc!\n");
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
bt_msr |= MSR_INFRA;
|
||||
ledaction = LED_CTL_LINK;
|
||||
bcnfunc_enable &= 0xF7;
|
||||
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
|
||||
"Set Network type to STA!\n");
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
bt_msr |= MSR_AP;
|
||||
bcnfunc_enable |= 0x08;
|
||||
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
|
||||
"Set Network type to AP!\n");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1552,8 +1552,6 @@ void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw)
|
|||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
u16 bcntime_cfg = 0;
|
||||
u16 bcn_cw = 6, bcn_ifs = 0xf;
|
||||
u16 atim_window = 2;
|
||||
|
||||
/* ATIM Window (in unit of TU). */
|
||||
|
|
@ -1576,13 +1574,6 @@ void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw)
|
|||
* other ad hoc STA */
|
||||
rtl_write_byte(rtlpriv, BCN_ERR_THRESH, 100);
|
||||
|
||||
/* Beacon Time Configuration */
|
||||
if (mac->opmode == NL80211_IFTYPE_ADHOC)
|
||||
bcntime_cfg |= (bcn_cw << BCN_TCFG_CW_SHIFT);
|
||||
|
||||
/* TODO: bcn_ifs may required to be changed on ASIC */
|
||||
bcntime_cfg |= bcn_ifs << BCN_TCFG_IFS;
|
||||
|
||||
/*for beacon changed */
|
||||
rtl92s_phy_set_beacon_hwreg(hw, mac->beacon_interval);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,6 +222,9 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
|
|||
case RTW_HCI_TYPE_USB:
|
||||
intf_mask = RTW_PWR_INTF_USB_MSK;
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
intf_mask = RTW_PWR_INTF_SDIO_MSK;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -233,7 +236,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
|
|||
|
||||
ret = rtw_sub_pwr_seq_parser(rtwdev, intf_mask, cut_mask, cmd);
|
||||
if (ret)
|
||||
return -EBUSY;
|
||||
return ret;
|
||||
|
||||
idx++;
|
||||
} while (1);
|
||||
|
|
@ -247,6 +250,7 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
|
|||
const struct rtw_pwr_seq_cmd **pwr_seq;
|
||||
u8 rpwm;
|
||||
bool cur_pwr;
|
||||
int ret;
|
||||
|
||||
if (rtw_chip_wcpu_11ac(rtwdev)) {
|
||||
rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
|
||||
|
|
@ -270,8 +274,9 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
|
|||
return -EALREADY;
|
||||
|
||||
pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq;
|
||||
if (rtw_pwr_seq_parser(rtwdev, pwr_seq))
|
||||
return -EINVAL;
|
||||
ret = rtw_pwr_seq_parser(rtwdev, pwr_seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pwr_on)
|
||||
set_bit(RTW_FLAG_POWERON, rtwdev->flags);
|
||||
|
|
@ -1040,6 +1045,9 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev)
|
|||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rqpn = &chip->rqpn_table[0];
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1202,6 +1210,9 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev)
|
|||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
pg_tbl = &chip->page_table[0];
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ static void rtw8821cu_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8821cs_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8821c_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->s.mac_addr);
|
||||
}
|
||||
|
||||
enum rtw8821ce_rf_set {
|
||||
SWITCH_TO_BTG,
|
||||
SWITCH_TO_WLG,
|
||||
|
|
@ -77,6 +83,9 @@ static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_USB:
|
||||
rtw8821cu_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rtw8821cs_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ struct rtw8821ce_efuse {
|
|||
u8 res7;
|
||||
};
|
||||
|
||||
struct rtw8821cs_efuse {
|
||||
u8 res4[0x4a]; /* 0xd0 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x11a */
|
||||
} __packed;
|
||||
|
||||
struct rtw8821c_efuse {
|
||||
__le16 rtl_id;
|
||||
u8 res0[0x0e];
|
||||
|
|
@ -94,6 +99,7 @@ struct rtw8821c_efuse {
|
|||
union {
|
||||
struct rtw8821ce_efuse e;
|
||||
struct rtw8821cu_efuse u;
|
||||
struct rtw8821cs_efuse s;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ static void rtw8822bu_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8822bs_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8822b_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->s.mac_addr);
|
||||
}
|
||||
|
||||
static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
|
@ -65,6 +71,9 @@ static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_USB:
|
||||
rtw8822bu_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rtw8822bs_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ struct rtw8822be_efuse {
|
|||
u8 res7;
|
||||
};
|
||||
|
||||
struct rtw8822bs_efuse {
|
||||
u8 res4[0x4a]; /* 0xd0 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x11a */
|
||||
} __packed;
|
||||
|
||||
struct rtw8822b_efuse {
|
||||
__le16 rtl_id;
|
||||
u8 res0[0x0e];
|
||||
|
|
@ -92,8 +97,9 @@ struct rtw8822b_efuse {
|
|||
u8 country_code[2];
|
||||
u8 res[3];
|
||||
union {
|
||||
struct rtw8822bu_efuse u;
|
||||
struct rtw8822be_efuse e;
|
||||
struct rtw8822bu_efuse u;
|
||||
struct rtw8822bs_efuse s;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ static void rtw8822cu_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8822cs_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8822c_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->s.mac_addr);
|
||||
}
|
||||
|
||||
static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
|
@ -67,6 +73,9 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_USB:
|
||||
rtw8822cu_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rtw8822cs_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ struct rtw8822cu_efuse {
|
|||
u8 res2[0x3d];
|
||||
};
|
||||
|
||||
struct rtw8822cs_efuse {
|
||||
u8 res0[0x4a]; /* 0x120 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x16a */
|
||||
} __packed;
|
||||
|
||||
struct rtw8822ce_efuse {
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x120 */
|
||||
u8 vender_id[2];
|
||||
|
|
@ -91,8 +96,9 @@ struct rtw8822c_efuse {
|
|||
u8 res9;
|
||||
u8 res10[0x42];
|
||||
union {
|
||||
struct rtw8822cu_efuse u;
|
||||
struct rtw8822ce_efuse e;
|
||||
struct rtw8822cu_efuse u;
|
||||
struct rtw8822cs_efuse s;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1400,6 +1400,34 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
|
|||
}
|
||||
}
|
||||
|
||||
static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
|
||||
struct rtw89_pktofld_info *info;
|
||||
const u8 *ies = mgmt->u.beacon.variable, *ssid_ie;
|
||||
|
||||
if (rx_status->band != NL80211_BAND_6GHZ)
|
||||
return;
|
||||
|
||||
ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, ies, skb->len);
|
||||
|
||||
list_for_each_entry(info, &pkt_list[NL80211_BAND_6GHZ], list) {
|
||||
if (ether_addr_equal(info->bssid, mgmt->bssid)) {
|
||||
rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ssid_ie || ssid_ie[1] != info->ssid_len || info->ssid_len == 0)
|
||||
continue;
|
||||
|
||||
if (memcmp(&ssid_ie[2], info->ssid, info->ssid_len) == 0)
|
||||
rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
@ -1412,6 +1440,11 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
|
|||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
const u8 *bssid = iter_data->bssid;
|
||||
|
||||
if (rtwdev->scanning &&
|
||||
(ieee80211_is_beacon(hdr->frame_control) ||
|
||||
ieee80211_is_probe_resp(hdr->frame_control)))
|
||||
rtw89_core_cancel_6ghz_probe_tx(rtwdev, skb);
|
||||
|
||||
if (!vif->bss_conf.bssid)
|
||||
return;
|
||||
|
||||
|
|
@ -3372,7 +3405,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
|
|||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
|
||||
WIPHY_FLAG_TDLS_EXTERNAL_SETUP |
|
||||
WIPHY_FLAG_AP_UAPSD;
|
||||
WIPHY_FLAG_AP_UAPSD | WIPHY_FLAG_SPLIT_SCAN_6GHZ;
|
||||
hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
|
||||
|
||||
hw->wiphy->max_scan_ssids = RTW89_SCANOFLD_MAX_SSID;
|
||||
|
|
|
|||
|
|
@ -3023,7 +3023,7 @@ enum rtw89_fw_feature {
|
|||
RTW89_FW_FEATURE_SCAN_OFFLOAD,
|
||||
RTW89_FW_FEATURE_TX_WAKE,
|
||||
RTW89_FW_FEATURE_CRASH_TRIGGER,
|
||||
RTW89_FW_FEATURE_PACKET_DROP,
|
||||
RTW89_FW_FEATURE_NO_PACKET_DROP,
|
||||
RTW89_FW_FEATURE_NO_DEEP_PS,
|
||||
RTW89_FW_FEATURE_NO_LPS_PG,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ static bool __fw_feat_cond_ ## __cond(u32 suit_ver_code, u32 comp_ver_code) \
|
|||
|
||||
__DEF_FW_FEAT_COND(ge, >=); /* greater or equal */
|
||||
__DEF_FW_FEAT_COND(le, <=); /* less or equal */
|
||||
__DEF_FW_FEAT_COND(lt, <); /* less than */
|
||||
|
||||
struct __fw_feat_cfg {
|
||||
enum rtw89_core_chip_id chip_id;
|
||||
|
|
@ -256,9 +257,11 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
|
|||
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD),
|
||||
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE),
|
||||
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 36, 0, CRASH_TRIGGER),
|
||||
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 38, 0, PACKET_DROP),
|
||||
__CFG_FW_FEAT(RTL8852A, lt, 0, 13, 38, 0, NO_PACKET_DROP),
|
||||
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, NO_LPS_PG),
|
||||
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 20, 0, PACKET_DROP),
|
||||
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, TX_WAKE),
|
||||
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER),
|
||||
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD),
|
||||
__CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS),
|
||||
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE),
|
||||
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD),
|
||||
|
|
@ -2702,9 +2705,29 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
|
|||
}
|
||||
}
|
||||
|
||||
static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif,
|
||||
struct rtw89_pktofld_info *info,
|
||||
enum nl80211_band band, u8 ssid_idx)
|
||||
{
|
||||
struct cfg80211_scan_request *req = rtwvif->scan_req;
|
||||
|
||||
if (band != NL80211_BAND_6GHZ)
|
||||
return false;
|
||||
|
||||
if (req->ssids[ssid_idx].ssid_len) {
|
||||
memcpy(info->ssid, req->ssids[ssid_idx].ssid,
|
||||
req->ssids[ssid_idx].ssid_len);
|
||||
info->ssid_len = req->ssids[ssid_idx].ssid_len;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif,
|
||||
struct sk_buff *skb)
|
||||
struct sk_buff *skb, u8 ssid_idx)
|
||||
{
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
|
||||
|
|
@ -2732,6 +2755,13 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (rtw89_is_6ghz_wildcard_probe_req(rtwdev, rtwvif, info, band,
|
||||
ssid_idx)) {
|
||||
kfree_skb(new);
|
||||
kfree(info);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, new);
|
||||
if (ret) {
|
||||
kfree_skb(new);
|
||||
|
|
@ -2762,7 +2792,7 @@ static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
|
|||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = rtw89_append_probe_req_ie(rtwdev, rtwvif, skb);
|
||||
ret = rtw89_append_probe_req_ie(rtwdev, rtwvif, skb, i);
|
||||
kfree_skb(skb);
|
||||
|
||||
if (ret)
|
||||
|
|
@ -2772,6 +2802,77 @@ static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev,
|
||||
struct cfg80211_scan_request *req,
|
||||
struct rtw89_mac_chinfo *ch_info)
|
||||
{
|
||||
struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
|
||||
struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
|
||||
struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
|
||||
struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
|
||||
struct cfg80211_scan_6ghz_params *params;
|
||||
struct rtw89_pktofld_info *info, *tmp;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct sk_buff *skb;
|
||||
bool found;
|
||||
int ret = 0;
|
||||
u8 i;
|
||||
|
||||
if (!req->n_6ghz_params)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < req->n_6ghz_params; i++) {
|
||||
params = &req->scan_6ghz_params[i];
|
||||
|
||||
if (req->channels[params->channel_idx]->hw_value !=
|
||||
ch_info->pri_ch)
|
||||
continue;
|
||||
|
||||
found = false;
|
||||
list_for_each_entry(tmp, &pkt_list[NL80211_BAND_6GHZ], list) {
|
||||
if (ether_addr_equal(tmp->bssid, params->bssid)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr,
|
||||
NULL, 0, req->ie_len);
|
||||
skb_put_data(skb, ies->ies[NL80211_BAND_6GHZ], ies->len[NL80211_BAND_6GHZ]);
|
||||
skb_put_data(skb, ies->common_ies, ies->common_ie_len);
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
ether_addr_copy(hdr->addr3, params->bssid);
|
||||
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, skb);
|
||||
if (ret) {
|
||||
kfree_skb(skb);
|
||||
kfree(info);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ether_addr_copy(info->bssid, params->bssid);
|
||||
info->channel_6ghz = req->channels[params->channel_idx]->hw_value;
|
||||
list_add_tail(&info->list, &rtwdev->scan_info.pkt_list[NL80211_BAND_6GHZ]);
|
||||
|
||||
ch_info->tx_pkt = true;
|
||||
ch_info->period = RTW89_CHANNEL_TIME_6G + RTW89_DWELL_TIME_6G;
|
||||
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
|
||||
int ssid_num,
|
||||
struct rtw89_mac_chinfo *ch_info)
|
||||
|
|
@ -2782,6 +2883,7 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
|
|||
struct cfg80211_scan_request *req = rtwvif->scan_req;
|
||||
struct rtw89_pktofld_info *info;
|
||||
u8 band, probe_count = 0;
|
||||
int ret;
|
||||
|
||||
ch_info->notify_action = RTW89_SCANOFLD_DEBUG_MASK;
|
||||
ch_info->dfs_ch = chan_type == RTW89_CHAN_DFS;
|
||||
|
|
@ -2793,27 +2895,33 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
|
|||
ch_info->pause_data = false;
|
||||
ch_info->probe_id = RTW89_SCANOFLD_PKT_NONE;
|
||||
|
||||
if (ssid_num) {
|
||||
ch_info->num_pkt = ssid_num;
|
||||
band = rtw89_hw_to_nl80211_band(ch_info->ch_band);
|
||||
|
||||
list_for_each_entry(info, &scan_info->pkt_list[band], list) {
|
||||
ch_info->pkt_id[probe_count] = info->id;
|
||||
if (++probe_count >= ssid_num)
|
||||
break;
|
||||
}
|
||||
if (probe_count != ssid_num)
|
||||
rtw89_err(rtwdev, "SSID num differs from list len\n");
|
||||
}
|
||||
|
||||
if (ch_info->ch_band == RTW89_BAND_6G) {
|
||||
if (ssid_num == 1 && req->ssids[0].ssid_len == 0) {
|
||||
if ((ssid_num == 1 && req->ssids[0].ssid_len == 0) ||
|
||||
!ch_info->is_psc) {
|
||||
ch_info->tx_pkt = false;
|
||||
if (!req->duration_mandatory)
|
||||
ch_info->period -= RTW89_DWELL_TIME_6G;
|
||||
}
|
||||
}
|
||||
|
||||
ret = rtw89_update_6ghz_rnr_chan(rtwdev, req, ch_info);
|
||||
if (ret)
|
||||
rtw89_warn(rtwdev, "RNR fails: %d\n", ret);
|
||||
|
||||
if (ssid_num) {
|
||||
band = rtw89_hw_to_nl80211_band(ch_info->ch_band);
|
||||
|
||||
list_for_each_entry(info, &scan_info->pkt_list[band], list) {
|
||||
if (info->channel_6ghz &&
|
||||
ch_info->pri_ch != info->channel_6ghz)
|
||||
continue;
|
||||
ch_info->pkt_id[probe_count++] = info->id;
|
||||
if (probe_count >= RTW89_SCANOFLD_MAX_SSID)
|
||||
break;
|
||||
}
|
||||
ch_info->num_pkt = probe_count;
|
||||
}
|
||||
|
||||
switch (chan_type) {
|
||||
case RTW89_CHAN_OPERATE:
|
||||
ch_info->central_ch = scan_info->op_chan;
|
||||
|
|
@ -2872,6 +2980,7 @@ static int rtw89_hw_scan_add_chan_list(struct rtw89_dev *rtwdev,
|
|||
ch_info->central_ch = channel->hw_value;
|
||||
ch_info->pri_ch = channel->hw_value;
|
||||
ch_info->rand_seq_num = random_seq;
|
||||
ch_info->is_psc = cfg80211_channel_is_psc(channel);
|
||||
|
||||
if (channel->flags &
|
||||
(IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR))
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ struct rtw89_mac_chinfo {
|
|||
u16 tx_pwr_idx;
|
||||
u8 rsvd1;
|
||||
struct list_head list;
|
||||
bool is_psc;
|
||||
};
|
||||
|
||||
struct rtw89_scan_option {
|
||||
|
|
@ -247,6 +248,12 @@ struct rtw89_scan_option {
|
|||
struct rtw89_pktofld_info {
|
||||
struct list_head list;
|
||||
u8 id;
|
||||
|
||||
/* Below fields are for 6 GHz RNR use only */
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 ssid_len;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u16 channel_6ghz;
|
||||
};
|
||||
|
||||
static inline void RTW89_SET_FWCMD_RA_IS_DIS(void *cmd, u32 val)
|
||||
|
|
|
|||
|
|
@ -5426,7 +5426,7 @@ int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev,
|
|||
for (i = 0; i < try_cnt; i++) {
|
||||
ret = read_poll_timeout(mac_is_txq_empty, empty, empty, 50,
|
||||
50000, false, rtwdev);
|
||||
if (ret)
|
||||
if (ret && !RTW89_CHK_FW_FEATURE(NO_PACKET_DROP, &rtwdev->fw))
|
||||
rtw89_fw_h2c_pkt_drop(rtwdev, ¶ms);
|
||||
else
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -676,7 +676,7 @@ static void rtw89_ops_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
rtw89_leave_lps(rtwdev);
|
||||
rtw89_hci_flush_queues(rtwdev, queues, drop);
|
||||
|
||||
if (drop && RTW89_CHK_FW_FEATURE(PACKET_DROP, &rtwdev->fw))
|
||||
if (drop && !RTW89_CHK_FW_FEATURE(NO_PACKET_DROP, &rtwdev->fw))
|
||||
__rtw89_drop_packets(rtwdev, vif);
|
||||
else
|
||||
rtw89_mac_flush_txq(rtwdev, queues, drop);
|
||||
|
|
|
|||
|
|
@ -4294,3 +4294,75 @@ void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev,
|
|||
data[RTW89_TSSI_SBW20]);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_phy_tssi_ctrl_set_bandedge_cfg);
|
||||
|
||||
static
|
||||
const u8 rtw89_ch_base_table[16] = {1, 0xff,
|
||||
36, 100, 132, 149, 0xff,
|
||||
1, 33, 65, 97, 129, 161, 193, 225, 0xff};
|
||||
#define RTW89_CH_BASE_IDX_2G 0
|
||||
#define RTW89_CH_BASE_IDX_5G_FIRST 2
|
||||
#define RTW89_CH_BASE_IDX_5G_LAST 5
|
||||
#define RTW89_CH_BASE_IDX_6G_FIRST 7
|
||||
#define RTW89_CH_BASE_IDX_6G_LAST 14
|
||||
|
||||
#define RTW89_CH_BASE_IDX_MASK GENMASK(7, 4)
|
||||
#define RTW89_CH_OFFSET_MASK GENMASK(3, 0)
|
||||
|
||||
u8 rtw89_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band)
|
||||
{
|
||||
u8 chan_idx;
|
||||
u8 last, first;
|
||||
u8 idx;
|
||||
|
||||
switch (band) {
|
||||
case RTW89_BAND_2G:
|
||||
chan_idx = FIELD_PREP(RTW89_CH_BASE_IDX_MASK, RTW89_CH_BASE_IDX_2G) |
|
||||
FIELD_PREP(RTW89_CH_OFFSET_MASK, central_ch);
|
||||
return chan_idx;
|
||||
case RTW89_BAND_5G:
|
||||
first = RTW89_CH_BASE_IDX_5G_FIRST;
|
||||
last = RTW89_CH_BASE_IDX_5G_LAST;
|
||||
break;
|
||||
case RTW89_BAND_6G:
|
||||
first = RTW89_CH_BASE_IDX_6G_FIRST;
|
||||
last = RTW89_CH_BASE_IDX_6G_LAST;
|
||||
break;
|
||||
default:
|
||||
rtw89_warn(rtwdev, "Unsupported band %d\n", band);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (idx = last; idx >= first; idx--)
|
||||
if (central_ch >= rtw89_ch_base_table[idx])
|
||||
break;
|
||||
|
||||
if (idx < first) {
|
||||
rtw89_warn(rtwdev, "Unknown band %d channel %d\n", band, central_ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
chan_idx = FIELD_PREP(RTW89_CH_BASE_IDX_MASK, idx) |
|
||||
FIELD_PREP(RTW89_CH_OFFSET_MASK,
|
||||
(central_ch - rtw89_ch_base_table[idx]) >> 1);
|
||||
return chan_idx;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_encode_chan_idx);
|
||||
|
||||
void rtw89_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx,
|
||||
u8 *ch, enum nl80211_band *band)
|
||||
{
|
||||
u8 idx, offset;
|
||||
|
||||
idx = FIELD_GET(RTW89_CH_BASE_IDX_MASK, chan_idx);
|
||||
offset = FIELD_GET(RTW89_CH_OFFSET_MASK, chan_idx);
|
||||
|
||||
if (idx == RTW89_CH_BASE_IDX_2G) {
|
||||
*band = NL80211_BAND_2GHZ;
|
||||
*ch = offset;
|
||||
return;
|
||||
}
|
||||
|
||||
*band = idx <= RTW89_CH_BASE_IDX_5G_LAST ? NL80211_BAND_5GHZ : NL80211_BAND_6GHZ;
|
||||
*ch = rtw89_ch_base_table[idx] + (offset << 1);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_decode_chan_idx);
|
||||
|
|
|
|||
|
|
@ -555,5 +555,8 @@ void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev,
|
|||
enum rtw89_tssi_bandedge_cfg bandedge_cfg);
|
||||
void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
|
||||
void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev);
|
||||
u8 rtw89_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band);
|
||||
void rtw89_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx,
|
||||
u8 *ch, enum nl80211_band *band);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1422,6 +1422,7 @@ static void rtw8852b_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89
|
|||
{
|
||||
bool cck_en = chan->channel <= 14;
|
||||
u8 pri_ch_idx = chan->pri_ch_idx;
|
||||
u8 band = chan->band_type, chan_idx;
|
||||
|
||||
if (cck_en)
|
||||
rtw8852b_ctrl_sco_cck(rtwdev, chan->primary_channel);
|
||||
|
|
@ -1444,8 +1445,8 @@ static void rtw8852b_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89
|
|||
B_BT_DYN_DC_EST_EN_MSK, 0x0);
|
||||
rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0);
|
||||
}
|
||||
rtw89_phy_write32_mask(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0,
|
||||
chan->primary_channel);
|
||||
chan_idx = rtw89_encode_chan_idx(rtwdev, chan->primary_channel, band);
|
||||
rtw89_phy_write32_mask(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0, chan_idx);
|
||||
rtw8852b_5m_mask(rtwdev, chan, phy_idx);
|
||||
rtw8852b_bb_set_pop(rtwdev);
|
||||
rtw8852b_bb_reset_all(rtwdev, phy_idx);
|
||||
|
|
@ -2299,13 +2300,14 @@ static void rtw8852b_fill_freq_with_ppdu(struct rtw89_dev *rtwdev,
|
|||
struct ieee80211_rx_status *status)
|
||||
{
|
||||
u16 chan = phy_ppdu->chan_idx;
|
||||
u8 band;
|
||||
enum nl80211_band band;
|
||||
u8 ch;
|
||||
|
||||
if (chan == 0)
|
||||
return;
|
||||
|
||||
band = chan <= 14 ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
|
||||
status->freq = ieee80211_channel_to_frequency(chan, band);
|
||||
rtw89_decode_chan_idx(rtwdev, chan, &ch, &band);
|
||||
status->freq = ieee80211_channel_to_frequency(ch, band);
|
||||
status->band = band;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -852,76 +852,6 @@ static void rtw8852c_set_gain_error(struct rtw89_dev *rtwdev,
|
|||
}
|
||||
}
|
||||
|
||||
static
|
||||
const u8 rtw8852c_ch_base_table[16] = {1, 0xff,
|
||||
36, 100, 132, 149, 0xff,
|
||||
1, 33, 65, 97, 129, 161, 193, 225, 0xff};
|
||||
#define RTW8852C_CH_BASE_IDX_2G 0
|
||||
#define RTW8852C_CH_BASE_IDX_5G_FIRST 2
|
||||
#define RTW8852C_CH_BASE_IDX_5G_LAST 5
|
||||
#define RTW8852C_CH_BASE_IDX_6G_FIRST 7
|
||||
#define RTW8852C_CH_BASE_IDX_6G_LAST 14
|
||||
|
||||
#define RTW8852C_CH_BASE_IDX_MASK GENMASK(7, 4)
|
||||
#define RTW8852C_CH_OFFSET_MASK GENMASK(3, 0)
|
||||
|
||||
static u8 rtw8852c_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band)
|
||||
{
|
||||
u8 chan_idx;
|
||||
u8 last, first;
|
||||
u8 idx;
|
||||
|
||||
switch (band) {
|
||||
case RTW89_BAND_2G:
|
||||
chan_idx = FIELD_PREP(RTW8852C_CH_BASE_IDX_MASK, RTW8852C_CH_BASE_IDX_2G) |
|
||||
FIELD_PREP(RTW8852C_CH_OFFSET_MASK, central_ch);
|
||||
return chan_idx;
|
||||
case RTW89_BAND_5G:
|
||||
first = RTW8852C_CH_BASE_IDX_5G_FIRST;
|
||||
last = RTW8852C_CH_BASE_IDX_5G_LAST;
|
||||
break;
|
||||
case RTW89_BAND_6G:
|
||||
first = RTW8852C_CH_BASE_IDX_6G_FIRST;
|
||||
last = RTW8852C_CH_BASE_IDX_6G_LAST;
|
||||
break;
|
||||
default:
|
||||
rtw89_warn(rtwdev, "Unsupported band %d\n", band);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (idx = last; idx >= first; idx--)
|
||||
if (central_ch >= rtw8852c_ch_base_table[idx])
|
||||
break;
|
||||
|
||||
if (idx < first) {
|
||||
rtw89_warn(rtwdev, "Unknown band %d channel %d\n", band, central_ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
chan_idx = FIELD_PREP(RTW8852C_CH_BASE_IDX_MASK, idx) |
|
||||
FIELD_PREP(RTW8852C_CH_OFFSET_MASK,
|
||||
(central_ch - rtw8852c_ch_base_table[idx]) >> 1);
|
||||
return chan_idx;
|
||||
}
|
||||
|
||||
static void rtw8852c_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx,
|
||||
u8 *ch, enum nl80211_band *band)
|
||||
{
|
||||
u8 idx, offset;
|
||||
|
||||
idx = FIELD_GET(RTW8852C_CH_BASE_IDX_MASK, chan_idx);
|
||||
offset = FIELD_GET(RTW8852C_CH_OFFSET_MASK, chan_idx);
|
||||
|
||||
if (idx == RTW8852C_CH_BASE_IDX_2G) {
|
||||
*band = NL80211_BAND_2GHZ;
|
||||
*ch = offset;
|
||||
return;
|
||||
}
|
||||
|
||||
*band = idx <= RTW8852C_CH_BASE_IDX_5G_LAST ? NL80211_BAND_5GHZ : NL80211_BAND_6GHZ;
|
||||
*ch = rtw8852c_ch_base_table[idx] + (offset << 1);
|
||||
}
|
||||
|
||||
static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx,
|
||||
|
|
@ -1084,7 +1014,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
|
|||
}
|
||||
}
|
||||
|
||||
chan_idx = rtw8852c_encode_chan_idx(rtwdev, chan->primary_channel, band);
|
||||
chan_idx = rtw89_encode_chan_idx(rtwdev, chan->primary_channel, band);
|
||||
rtw89_phy_write32_idx(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0, chan_idx, phy_idx);
|
||||
}
|
||||
|
||||
|
|
@ -2730,7 +2660,7 @@ static void rtw8852c_fill_freq_with_ppdu(struct rtw89_dev *rtwdev,
|
|||
if (chan_idx == 0)
|
||||
return;
|
||||
|
||||
rtw8852c_decode_chan_idx(rtwdev, chan_idx, &ch, &band);
|
||||
rtw89_decode_chan_idx(rtwdev, chan_idx, &ch, &band);
|
||||
status->freq = ieee80211_channel_to_frequency(ch, band);
|
||||
status->band = band;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -414,8 +414,11 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)
|
|||
|
||||
static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt)
|
||||
{
|
||||
struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
|
||||
|
||||
switch (evt) {
|
||||
case SER_EV_STATE_IN:
|
||||
cancel_delayed_work_sync(&rtwdev->track_work);
|
||||
drv_stop_tx(ser);
|
||||
|
||||
if (hal_stop_dma(ser)) {
|
||||
|
|
@ -446,6 +449,8 @@ static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt)
|
|||
hal_enable_dma(ser);
|
||||
drv_resume_rx(ser);
|
||||
drv_resume_tx(ser);
|
||||
ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->track_work,
|
||||
RTW89_TRACK_WORK_PERIOD);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -358,13 +358,9 @@ int wfx_probe(struct wfx_dev *wdev)
|
|||
|
||||
wfx_bh_poll_irq(wdev);
|
||||
err = wait_for_completion_timeout(&wdev->firmware_ready, 1 * HZ);
|
||||
if (err <= 0) {
|
||||
if (err == 0) {
|
||||
dev_err(wdev->dev, "timeout while waiting for startup indication\n");
|
||||
err = -ETIMEDOUT;
|
||||
} else if (err == -ERESTARTSYS) {
|
||||
dev_info(wdev->dev, "probe interrupted by user\n");
|
||||
}
|
||||
if (err == 0) {
|
||||
dev_err(wdev->dev, "timeout while waiting for startup indication\n");
|
||||
err = -ETIMEDOUT;
|
||||
goto bh_unregister;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -827,6 +827,18 @@ struct cfg80211_fils_aad {
|
|||
const u8 *anonce;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_set_hw_timestamp - enable/disable HW timestamping
|
||||
* @macaddr: peer MAC address. NULL to enable/disable HW timestamping for all
|
||||
* addresses.
|
||||
* @enable: if set, enable HW timestamping for the specified MAC address.
|
||||
* Otherwise disable HW timestamping for the specified MAC address.
|
||||
*/
|
||||
struct cfg80211_set_hw_timestamp {
|
||||
const u8 *macaddr;
|
||||
bool enable;
|
||||
};
|
||||
|
||||
/**
|
||||
* cfg80211_get_chandef_type - return old channel type from chandef
|
||||
* @chandef: the channel definition
|
||||
|
|
@ -4330,6 +4342,8 @@ struct mgmt_frame_regs {
|
|||
* @add_link_station: Add a link to a station.
|
||||
* @mod_link_station: Modify a link of a station.
|
||||
* @del_link_station: Remove a link of a station.
|
||||
*
|
||||
* @set_hw_timestamp: Enable/disable HW timestamping of TM/FTM frames.
|
||||
*/
|
||||
struct cfg80211_ops {
|
||||
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
||||
|
|
@ -4683,6 +4697,8 @@ struct cfg80211_ops {
|
|||
struct link_station_parameters *params);
|
||||
int (*del_link_station)(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct link_station_del_parameters *params);
|
||||
int (*set_hw_timestamp)(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_set_hw_timestamp *hwts);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -5139,6 +5155,8 @@ struct wiphy_iftype_akm_suites {
|
|||
int n_akm_suites;
|
||||
};
|
||||
|
||||
#define CFG80211_HW_TIMESTAMP_ALL_PEERS 0xffff
|
||||
|
||||
/**
|
||||
* struct wiphy - wireless hardware description
|
||||
* @mtx: mutex for the data (structures) of this device
|
||||
|
|
@ -5348,6 +5366,13 @@ struct wiphy_iftype_akm_suites {
|
|||
* NL80211_MAX_NR_AKM_SUITES in order to avoid compatibility issues with
|
||||
* legacy userspace and maximum allowed value is
|
||||
* CFG80211_MAX_NUM_AKM_SUITES.
|
||||
*
|
||||
* @hw_timestamp_max_peers: maximum number of peers that the driver supports
|
||||
* enabling HW timestamping for concurrently. Setting this field to a
|
||||
* non-zero value indicates that the driver supports HW timestamping.
|
||||
* A value of %CFG80211_HW_TIMESTAMP_ALL_PEERS indicates the driver
|
||||
* supports enabling HW timestamping for all peers (i.e. no need to
|
||||
* specify a mac address).
|
||||
*/
|
||||
struct wiphy {
|
||||
struct mutex mtx;
|
||||
|
|
@ -5496,6 +5521,8 @@ struct wiphy {
|
|||
u8 ema_max_profile_periodicity;
|
||||
u16 max_num_akm_suites;
|
||||
|
||||
u16 hw_timestamp_max_peers;
|
||||
|
||||
char priv[] __aligned(NETDEV_ALIGN);
|
||||
};
|
||||
|
||||
|
|
@ -6814,13 +6841,11 @@ enum cfg80211_bss_frame_type {
|
|||
* @ie: IEs
|
||||
* @ielen: length of IEs
|
||||
* @band: enum nl80211_band of the channel
|
||||
* @ftype: frame type
|
||||
*
|
||||
* Returns the channel number, or -1 if none could be determined.
|
||||
*/
|
||||
int cfg80211_get_ies_channel_number(const u8 *ie, size_t ielen,
|
||||
enum nl80211_band band,
|
||||
enum cfg80211_bss_frame_type ftype);
|
||||
enum nl80211_band band);
|
||||
|
||||
/**
|
||||
* cfg80211_inform_bss_data - inform cfg80211 of a new BSS
|
||||
|
|
@ -8101,6 +8126,7 @@ void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
|
|||
* responsible for any cleanup. The caller must also ensure that
|
||||
* skb->protocol is set appropriately.
|
||||
* @unencrypted: Whether the frame was received unencrypted
|
||||
* @link_id: the link the frame was received on, -1 if not applicable or unknown
|
||||
*
|
||||
* This function is used to inform userspace about a received control port
|
||||
* frame. It should only be used if userspace indicated it wants to receive
|
||||
|
|
@ -8111,8 +8137,8 @@ void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
|
|||
*
|
||||
* Return: %true if the frame was passed to userspace
|
||||
*/
|
||||
bool cfg80211_rx_control_port(struct net_device *dev,
|
||||
struct sk_buff *skb, bool unencrypted);
|
||||
bool cfg80211_rx_control_port(struct net_device *dev, struct sk_buff *skb,
|
||||
bool unencrypted, int link_id);
|
||||
|
||||
/**
|
||||
* cfg80211_cqm_rssi_notify - connection quality monitoring rssi event
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Deutschland GmbH
|
||||
* Copyright (c) 2018-2019, 2021 Intel Corporation
|
||||
* Copyright (c) 2018-2019, 2021-2022 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
|
@ -82,11 +82,14 @@ enum ieee80211_radiotap_presence {
|
|||
IEEE80211_RADIOTAP_HE_MU = 24,
|
||||
IEEE80211_RADIOTAP_ZERO_LEN_PSDU = 26,
|
||||
IEEE80211_RADIOTAP_LSIG = 27,
|
||||
IEEE80211_RADIOTAP_TLV = 28,
|
||||
|
||||
/* valid in every it_present bitmap, even vendor namespaces */
|
||||
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
|
||||
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
|
||||
IEEE80211_RADIOTAP_EXT = 31
|
||||
IEEE80211_RADIOTAP_EXT = 31,
|
||||
IEEE80211_RADIOTAP_EHT_USIG = 33,
|
||||
IEEE80211_RADIOTAP_EHT = 34,
|
||||
};
|
||||
|
||||
/* for IEEE80211_RADIOTAP_FLAGS */
|
||||
|
|
@ -360,6 +363,214 @@ enum ieee80211_radiotap_zero_len_psdu_type {
|
|||
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR = 0xff,
|
||||
};
|
||||
|
||||
struct ieee80211_radiotap_tlv {
|
||||
__le16 type;
|
||||
__le16 len;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct ieee80211_radiotap_vendor_content - radiotap vendor data content
|
||||
* @oui: radiotap vendor namespace OUI
|
||||
* @oui_subtype: radiotap vendor sub namespace
|
||||
* @vendor_type: radiotap vendor type
|
||||
* @reserved: should always be set to zero (to avoid leaking memory)
|
||||
* @data: the actual vendor namespace data
|
||||
*/
|
||||
struct ieee80211_radiotap_vendor_content {
|
||||
u8 oui[3];
|
||||
u8 oui_subtype;
|
||||
__le16 vendor_type;
|
||||
__le16 reserved;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct ieee80211_radiotap_vendor_tlv - vendor radiotap data information
|
||||
* @type: should always be set to IEEE80211_RADIOTAP_VENDOR_NAMESPACE
|
||||
* @len: length of data
|
||||
* @content: vendor content see @ieee80211_radiotap_vendor_content
|
||||
*/
|
||||
struct ieee80211_radiotap_vendor_tlv {
|
||||
__le16 type; /* IEEE80211_RADIOTAP_VENDOR_NAMESPACE */
|
||||
__le16 len;
|
||||
struct ieee80211_radiotap_vendor_content content;
|
||||
};
|
||||
|
||||
/* ieee80211_radiotap_eht_usig - content of U-SIG tlv (type 33)
|
||||
* see www.radiotap.org/fields/U-SIG.html for details
|
||||
*/
|
||||
struct ieee80211_radiotap_eht_usig {
|
||||
__le32 common;
|
||||
__le32 value;
|
||||
__le32 mask;
|
||||
} __packed;
|
||||
|
||||
/* ieee80211_radiotap_eht - content of EHT tlv (type 34)
|
||||
* see www.radiotap.org/fields/EHT.html for details
|
||||
*/
|
||||
struct ieee80211_radiotap_eht {
|
||||
__le32 known;
|
||||
__le32 data[9];
|
||||
__le32 user_info[];
|
||||
} __packed;
|
||||
|
||||
/* Known field for EHT TLV
|
||||
* The ending defines for what the field applies as following
|
||||
* O - OFDMA (including TB), M - MU-MIMO, S - EHT sounding.
|
||||
*/
|
||||
enum ieee80211_radiotap_eht_known {
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE = 0x00000002,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_GI = 0x00000004,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF = 0x00000010,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM = 0x00000020,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM = 0x00000040,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM = 0x00000080,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_DISREGARD_O = 0x00000100,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_DISREGARD_S = 0x00000200,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_CRC1 = 0x00002000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_TAIL1 = 0x00004000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_CRC2_O = 0x00008000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_TAIL2_O = 0x00010000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_NSS_S = 0x00020000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_BEAMFORMED_S = 0x00040000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_NR_NON_OFDMA_USERS_M = 0x00080000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_ENCODING_BLOCK_CRC_M = 0x00100000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_ENCODING_BLOCK_TAIL_M = 0x00200000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_RU_MRU_SIZE_OM = 0x00400000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_RU_MRU_INDEX_OM = 0x00800000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT = 0x01000000,
|
||||
IEEE80211_RADIOTAP_EHT_KNOWN_PRIMARY_80 = 0x02000000,
|
||||
};
|
||||
|
||||
enum ieee80211_radiotap_eht_data {
|
||||
/* Data 0 */
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE = 0x00000078,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_GI = 0x00000180,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_LTF = 0x00000600,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF = 0x00003800,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM = 0x00004000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM = 0x00018000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM = 0x00020000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_DISREGARD_S = 0x000c0000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_DISREGARD_O = 0x003c0000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_CRC1_O = 0x03c00000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA0_TAIL1_O = 0xfc000000,
|
||||
/* Data 1 */
|
||||
IEEE80211_RADIOTAP_EHT_DATA1_RU_SIZE = 0x0000001f,
|
||||
IEEE80211_RADIOTAP_EHT_DATA1_RU_INDEX = 0x00001fe0,
|
||||
IEEE80211_RADIOTAP_EHT_DATA1_RU_ALLOC_CC_1_1_1 = 0x003fe000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA1_RU_ALLOC_CC_1_1_1_KNOWN = 0x00400000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80 = 0xc0000000,
|
||||
/* Data 2 */
|
||||
IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_2_1_1 = 0x000001ff,
|
||||
IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_2_1_1_KNOWN = 0x00000200,
|
||||
IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_1_1_2 = 0x0007fc00,
|
||||
IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_1_1_2_KNOWN = 0x00080000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_2_1_2 = 0x1ff00000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA2_RU_ALLOC_CC_2_1_2_KNOWN = 0x20000000,
|
||||
/* Data 3 */
|
||||
IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_1 = 0x000001ff,
|
||||
IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_1_KNOWN = 0x00000200,
|
||||
IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_2_2_1 = 0x0007fc00,
|
||||
IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_2_2_1_KNOWN = 0x00080000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_2 = 0x1ff00000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA3_RU_ALLOC_CC_1_2_2_KNOWN = 0x20000000,
|
||||
/* Data 4 */
|
||||
IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_2_2_2 = 0x000001ff,
|
||||
IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_2_2_2_KNOWN = 0x00000200,
|
||||
IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_1_2_3 = 0x0007fc00,
|
||||
IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_1_2_3_KNOWN = 0x00080000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_2_2_3 = 0x1ff00000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA4_RU_ALLOC_CC_2_2_3_KNOWN = 0x20000000,
|
||||
/* Data 5 */
|
||||
IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_4 = 0x000001ff,
|
||||
IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_4_KNOWN = 0x00000200,
|
||||
IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_2_2_4 = 0x0007fc00,
|
||||
IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_2_2_4_KNOWN = 0x00080000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_5 = 0x1ff00000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA5_RU_ALLOC_CC_1_2_5_KNOWN = 0x20000000,
|
||||
/* Data 6 */
|
||||
IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_2_2_5 = 0x000001ff,
|
||||
IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_2_2_5_KNOWN = 0x00000200,
|
||||
IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_1_2_6 = 0x0007fc00,
|
||||
IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_1_2_6_KNOWN = 0x00080000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_2_2_6 = 0x1ff00000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA6_RU_ALLOC_CC_2_2_6_KNOWN = 0x20000000,
|
||||
/* Data 7 */
|
||||
IEEE80211_RADIOTAP_EHT_DATA7_CRC2_O = 0x0000000f,
|
||||
IEEE80211_RADIOTAP_EHT_DATA7_TAIL_2_O = 0x000003f0,
|
||||
IEEE80211_RADIOTAP_EHT_DATA7_NSS_S = 0x0000f000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA7_BEAMFORMED_S = 0x00010000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA7_NUM_OF_NON_OFDMA_USERS = 0x000e0000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA7_USER_ENCODING_BLOCK_CRC = 0x00f00000,
|
||||
IEEE80211_RADIOTAP_EHT_DATA7_USER_ENCODING_BLOCK_TAIL = 0x3f000000,
|
||||
/* Data 8 */
|
||||
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160 = 0x00000001,
|
||||
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0 = 0x00000002,
|
||||
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1 = 0x000001fc,
|
||||
};
|
||||
|
||||
enum ieee80211_radiotap_eht_user_info {
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN = 0x00000001,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN = 0x00000002,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN = 0x00000004,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O = 0x00000010,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_KNOWN_O = 0x00000020,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_SPATIAL_CONFIG_KNOWN_M = 0x00000040,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_DATA_FOR_USER = 0x00000080,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID = 0x0007ff00,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_CODING = 0x00080000,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_MCS = 0x00f00000,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O = 0x0f000000,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_BEAMFORMING_O = 0x20000000,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_SPATIAL_CONFIG_M = 0x3f000000,
|
||||
IEEE80211_RADIOTAP_EHT_USER_INFO_RESEVED_c0000000 = 0xc0000000,
|
||||
};
|
||||
|
||||
enum ieee80211_radiotap_eht_usig_common {
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN = 0x00000001,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN = 0x00000002,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN = 0x00000004,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN = 0x00000008,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN = 0x00000010,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC = 0x00000020,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER = 0x00007000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW = 0x00038000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL = 0x00040000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR = 0x01f80000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP = 0xfe000000,
|
||||
};
|
||||
|
||||
enum ieee80211_radiotap_eht_usig_mu {
|
||||
/* MU-USIG-1 */
|
||||
IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD = 0x0000001f,
|
||||
IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE = 0x00000020,
|
||||
/* MU-USIG-2 */
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE = 0x000000c0,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE = 0x00000100,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO = 0x00003e00,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE = 0x00004000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS = 0x00018000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS = 0x003e0000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC = 0x03c00000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_MU_B20_B25_TAIL = 0xfc000000,
|
||||
};
|
||||
|
||||
enum ieee80211_radiotap_eht_usig_tb {
|
||||
/* TB-USIG-1 */
|
||||
IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD = 0x0000001f,
|
||||
|
||||
/* TB-USIG-2 */
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE = 0x000000c0,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE = 0x00000100,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1 = 0x00001e00,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2 = 0x0001e000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD = 0x003e0000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC = 0x03c00000,
|
||||
IEEE80211_RADIOTAP_EHT_USIG2_TB_B20_B25_TAIL = 0xfc000000,
|
||||
};
|
||||
|
||||
/**
|
||||
* ieee80211_get_radiotap_len - get radiotap header length
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -534,6 +534,7 @@ struct ieee80211_fils_discovery {
|
|||
* This structure keeps information about a BSS (and an association
|
||||
* to that BSS) that can change during the lifetime of the BSS.
|
||||
*
|
||||
* @vif: reference to owning VIF
|
||||
* @addr: (link) address used locally
|
||||
* @link_id: link ID, or 0 for non-MLO
|
||||
* @htc_trig_based_pkt_ext: default PE in 4us units, if BSS supports HE
|
||||
|
|
@ -656,6 +657,9 @@ struct ieee80211_fils_discovery {
|
|||
* write-protected by sdata_lock and local->mtx so holding either is fine
|
||||
* for read access.
|
||||
* @color_change_color: the bss color that will be used after the change.
|
||||
* @ht_ldpc: in AP mode, indicates interface has HT LDPC capability.
|
||||
* @vht_ldpc: in AP mode, indicates interface has VHT LDPC capability.
|
||||
* @he_ldpc: in AP mode, indicates interface has HE LDPC capability.
|
||||
* @vht_su_beamformer: in AP mode, does this BSS support operation as an VHT SU
|
||||
* beamformer
|
||||
* @vht_su_beamformee: in AP mode, does this BSS support operation as an VHT SU
|
||||
|
|
@ -673,8 +677,16 @@ struct ieee80211_fils_discovery {
|
|||
* @he_full_ul_mumimo: does this BSS support the reception (AP) or transmission
|
||||
* (non-AP STA) of an HE TB PPDU on an RU that spans the entire PPDU
|
||||
* bandwidth
|
||||
* @eht_su_beamformer: in AP-mode, does this BSS enable operation as an EHT SU
|
||||
* beamformer
|
||||
* @eht_su_beamformee: in AP-mode, does this BSS enable operation as an EHT SU
|
||||
* beamformee
|
||||
* @eht_mu_beamformer: in AP-mode, does this BSS enable operation as an EHT MU
|
||||
* beamformer
|
||||
*/
|
||||
struct ieee80211_bss_conf {
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
const u8 *bssid;
|
||||
unsigned int link_id;
|
||||
u8 addr[ETH_ALEN] __aligned(2);
|
||||
|
|
@ -750,6 +762,9 @@ struct ieee80211_bss_conf {
|
|||
bool color_change_active;
|
||||
u8 color_change_color;
|
||||
|
||||
bool ht_ldpc;
|
||||
bool vht_ldpc;
|
||||
bool he_ldpc;
|
||||
bool vht_su_beamformer;
|
||||
bool vht_su_beamformee;
|
||||
bool vht_mu_beamformer;
|
||||
|
|
@ -758,6 +773,9 @@ struct ieee80211_bss_conf {
|
|||
bool he_su_beamformee;
|
||||
bool he_mu_beamformer;
|
||||
bool he_full_ul_mumimo;
|
||||
bool eht_su_beamformer;
|
||||
bool eht_su_beamformee;
|
||||
bool eht_mu_beamformer;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1372,9 +1390,12 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
|
|||
* subframes share the same sequence number. Reported subframes can be
|
||||
* either regular MSDU or singly A-MSDUs. Subframes must not be
|
||||
* interleaved with other frames.
|
||||
* @RX_FLAG_RADIOTAP_VENDOR_DATA: This frame contains vendor-specific
|
||||
* radiotap data in the skb->data (before the frame) as described by
|
||||
* the &struct ieee80211_vendor_radiotap.
|
||||
* @RX_FLAG_RADIOTAP_TLV_AT_END: This frame contains radiotap TLVs in the
|
||||
* skb->data (before the 802.11 header).
|
||||
* If used, the SKB's mac_header pointer must be set to point
|
||||
* to the 802.11 header after the TLVs, and any padding added after TLV
|
||||
* data to align to 4 must be cleared by the driver putting the TLVs
|
||||
* in the skb.
|
||||
* @RX_FLAG_ALLOW_SAME_PN: Allow the same PN as same packet before.
|
||||
* This is used for AMSDU subframes which can have the same PN as
|
||||
* the first subframe.
|
||||
|
|
@ -1426,7 +1447,7 @@ enum mac80211_rx_flags {
|
|||
RX_FLAG_ONLY_MONITOR = BIT(17),
|
||||
RX_FLAG_SKIP_MONITOR = BIT(18),
|
||||
RX_FLAG_AMSDU_MORE = BIT(19),
|
||||
RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(20),
|
||||
RX_FLAG_RADIOTAP_TLV_AT_END = BIT(20),
|
||||
RX_FLAG_MIC_STRIPPED = BIT(21),
|
||||
RX_FLAG_ALLOW_SAME_PN = BIT(22),
|
||||
RX_FLAG_ICV_STRIPPED = BIT(23),
|
||||
|
|
@ -1566,39 +1587,6 @@ ieee80211_rx_status_to_khz(struct ieee80211_rx_status *rx_status)
|
|||
(rx_status->freq_offset ? 500 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* struct ieee80211_vendor_radiotap - vendor radiotap data information
|
||||
* @present: presence bitmap for this vendor namespace
|
||||
* (this could be extended in the future if any vendor needs more
|
||||
* bits, the radiotap spec does allow for that)
|
||||
* @align: radiotap vendor namespace alignment. This defines the needed
|
||||
* alignment for the @data field below, not for the vendor namespace
|
||||
* description itself (which has a fixed 2-byte alignment)
|
||||
* Must be a power of two, and be set to at least 1!
|
||||
* @oui: radiotap vendor namespace OUI
|
||||
* @subns: radiotap vendor sub namespace
|
||||
* @len: radiotap vendor sub namespace skip length, if alignment is done
|
||||
* then that's added to this, i.e. this is only the length of the
|
||||
* @data field.
|
||||
* @pad: number of bytes of padding after the @data, this exists so that
|
||||
* the skb data alignment can be preserved even if the data has odd
|
||||
* length
|
||||
* @data: the actual vendor namespace data
|
||||
*
|
||||
* This struct, including the vendor data, goes into the skb->data before
|
||||
* the 802.11 header. It's split up in mac80211 using the align/oui/subns
|
||||
* data.
|
||||
*/
|
||||
struct ieee80211_vendor_radiotap {
|
||||
u32 present;
|
||||
u8 align;
|
||||
u8 oui[3];
|
||||
u8 subns;
|
||||
u8 pad;
|
||||
u16 len;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum ieee80211_conf_flags - configuration flags
|
||||
*
|
||||
|
|
@ -3841,6 +3829,12 @@ struct ieee80211_prep_tx_info {
|
|||
* the station. See @sta_pre_rcu_remove if needed.
|
||||
* This callback can sleep.
|
||||
*
|
||||
* @link_add_debugfs: Drivers can use this callback to add debugfs files
|
||||
* when a link is added to a mac80211 vif. This callback should be within
|
||||
* a CONFIG_MAC80211_DEBUGFS conditional. This callback can sleep.
|
||||
* For non-MLO the callback will be called once for the default bss_conf
|
||||
* with the vif's directory rather than a separate subdirectory.
|
||||
*
|
||||
* @sta_add_debugfs: Drivers can use this callback to add debugfs files
|
||||
* when a station is added to mac80211's station list. This callback
|
||||
* should be within a CONFIG_MAC80211_DEBUGFS conditional. This
|
||||
|
|
@ -4230,6 +4224,9 @@ struct ieee80211_prep_tx_info {
|
|||
* Note that a sta can also be inserted or removed with valid links,
|
||||
* i.e. passed to @sta_add/@sta_state with sta->valid_links not zero.
|
||||
* In fact, cannot change from having valid_links and not having them.
|
||||
* @set_hw_timestamp: Enable/disable HW timestamping of TM/FTM frames. This is
|
||||
* not restored at HW reset by mac80211 so drivers need to take care of
|
||||
* that.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
|
|
@ -4319,6 +4316,10 @@ struct ieee80211_ops {
|
|||
int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
void (*link_add_debugfs)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct dentry *dir);
|
||||
void (*sta_add_debugfs)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
|
|
@ -4589,6 +4590,9 @@ struct ieee80211_ops {
|
|||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
u16 old_links, u16 new_links);
|
||||
int (*set_hw_timestamp)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_set_hw_timestamp *hwts);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -5984,6 +5988,20 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
|
|||
struct delayed_work *dwork,
|
||||
unsigned long delay);
|
||||
|
||||
/**
|
||||
* ieee80211_refresh_tx_agg_session_timer - Refresh a tx agg session timer.
|
||||
* @sta: the station for which to start a BA session
|
||||
* @tid: the TID to BA on.
|
||||
*
|
||||
* This function allows low level driver to refresh tx agg session timer
|
||||
* to maintain BA session, the session level will still be managed by the
|
||||
* mac80211.
|
||||
*
|
||||
* Note: must be called in an RCU critical section.
|
||||
*/
|
||||
void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *sta,
|
||||
u16 tid);
|
||||
|
||||
/**
|
||||
* ieee80211_start_tx_ba_session - Start a tx Block Ack session.
|
||||
* @sta: the station for which to start a BA session
|
||||
|
|
|
|||
|
|
@ -1299,6 +1299,16 @@
|
|||
* @NL80211_CMD_MODIFY_LINK_STA: Modify a link of an MLD station
|
||||
* @NL80211_CMD_REMOVE_LINK_STA: Remove a link of an MLD station
|
||||
*
|
||||
* @NL80211_CMD_SET_HW_TIMESTAMP: Enable/disable HW timestamping of Timing
|
||||
* measurement and Fine timing measurement frames. If %NL80211_ATTR_MAC
|
||||
* is included, enable/disable HW timestamping only for frames to/from the
|
||||
* specified MAC address. Otherwise enable/disable HW timestamping for
|
||||
* all TM/FTM frames (including ones that were enabled with specific MAC
|
||||
* address). If %NL80211_ATTR_HW_TIMESTAMP_ENABLED is not included, disable
|
||||
* HW timestamping.
|
||||
* The number of peers that HW timestamping can be enabled for concurrently
|
||||
* is indicated by %NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS.
|
||||
*
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
|
|
@ -1550,6 +1560,8 @@ enum nl80211_commands {
|
|||
NL80211_CMD_MODIFY_LINK_STA,
|
||||
NL80211_CMD_REMOVE_LINK_STA,
|
||||
|
||||
NL80211_CMD_SET_HW_TIMESTAMP,
|
||||
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
|
|
@ -2775,6 +2787,13 @@ enum nl80211_commands {
|
|||
* indicates that the sub-channel is punctured. Higher 16 bits are
|
||||
* reserved.
|
||||
*
|
||||
* @NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS: Maximum number of peers that HW
|
||||
* timestamping can be enabled for concurrently (u16), a wiphy attribute.
|
||||
* A value of 0xffff indicates setting for all peers (i.e. not specifying
|
||||
* an address with %NL80211_CMD_SET_HW_TIMESTAMP) is supported.
|
||||
* @NL80211_ATTR_HW_TIMESTAMP_ENABLED: Indicates whether HW timestamping should
|
||||
* be enabled or not (flag attribute).
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
|
|
@ -3306,6 +3325,9 @@ enum nl80211_attrs {
|
|||
|
||||
NL80211_ATTR_PUNCT_BITMAP,
|
||||
|
||||
NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS,
|
||||
NL80211_ATTR_HW_TIMESTAMP_ENABLED,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
|
@ -6326,6 +6348,10 @@ enum nl80211_feature_flags {
|
|||
* @NL80211_EXT_FEATURE_SECURE_NAN: Device supports NAN Pairing which enables
|
||||
* authentication, data encryption and message integrity.
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA: Device supports randomized TA
|
||||
* in authentication and deauthentication frames sent to unassociated peer
|
||||
* using @NL80211_CMD_FRAME.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
|
|
@ -6396,6 +6422,7 @@ enum nl80211_ext_feature_index {
|
|||
NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE,
|
||||
NL80211_EXT_FEATURE_PUNCT,
|
||||
NL80211_EXT_FEATURE_SECURE_NAN,
|
||||
NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
|
|
@ -6510,8 +6537,14 @@ enum nl80211_timeout_reason {
|
|||
* @NL80211_SCAN_FLAG_FREQ_KHZ: report scan results with
|
||||
* %NL80211_ATTR_SCAN_FREQ_KHZ. This also means
|
||||
* %NL80211_ATTR_SCAN_FREQUENCIES will not be included.
|
||||
* @NL80211_SCAN_FLAG_COLOCATED_6GHZ: scan for colocated APs reported by
|
||||
* 2.4/5 GHz APs
|
||||
* @NL80211_SCAN_FLAG_COLOCATED_6GHZ: scan for collocated APs reported by
|
||||
* 2.4/5 GHz APs. When the flag is set, the scan logic will use the
|
||||
* information from the RNR element found in beacons/probe responses
|
||||
* received on the 2.4/5 GHz channels to actively scan only the 6GHz
|
||||
* channels on which APs are expected to be found. Note that when not set,
|
||||
* the scan logic would scan all 6GHz channels, but since transmission of
|
||||
* probe requests on non PSC channels is limited, it is highly likely that
|
||||
* these channels would passively be scanned.
|
||||
*/
|
||||
enum nl80211_scan_flags {
|
||||
NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0,
|
||||
|
|
|
|||
|
|
@ -554,6 +554,23 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
|
|||
ieee80211_send_addba_with_timeout(sta, tid_tx);
|
||||
}
|
||||
|
||||
void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *pubsta,
|
||||
u16 tid)
|
||||
{
|
||||
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
|
||||
if (WARN_ON_ONCE(tid >= IEEE80211_NUM_TIDS))
|
||||
return;
|
||||
|
||||
tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
|
||||
if (!tid_tx)
|
||||
return;
|
||||
|
||||
tid_tx->last_tx = jiffies;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_refresh_tx_agg_session_timer);
|
||||
|
||||
/*
|
||||
* After accepting the AddBA Response we activated a timer,
|
||||
* resetting it after each frame that we send.
|
||||
|
|
|
|||
|
|
@ -1252,7 +1252,15 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
prev_beacon_int = link_conf->beacon_int;
|
||||
link_conf->beacon_int = params->beacon_interval;
|
||||
|
||||
if (params->ht_cap)
|
||||
link_conf->ht_ldpc =
|
||||
params->ht_cap->cap_info &
|
||||
cpu_to_le16(IEEE80211_HT_CAP_LDPC_CODING);
|
||||
|
||||
if (params->vht_cap) {
|
||||
link_conf->vht_ldpc =
|
||||
params->vht_cap->vht_cap_info &
|
||||
cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC);
|
||||
link_conf->vht_su_beamformer =
|
||||
params->vht_cap->vht_cap_info &
|
||||
cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
|
||||
|
|
@ -1282,6 +1290,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
|
||||
if (params->he_cap) {
|
||||
link_conf->he_ldpc =
|
||||
params->he_cap->phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
|
||||
link_conf->he_su_beamformer =
|
||||
params->he_cap->phy_cap_info[3] &
|
||||
IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
|
||||
|
|
@ -1299,6 +1310,22 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
if (params->eht_cap) {
|
||||
link_conf->eht_puncturing = params->punct_bitmap;
|
||||
changed |= BSS_CHANGED_EHT_PUNCTURING;
|
||||
|
||||
link_conf->eht_su_beamformer =
|
||||
params->eht_cap->fixed.phy_cap_info[0] &
|
||||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER;
|
||||
link_conf->eht_su_beamformee =
|
||||
params->eht_cap->fixed.phy_cap_info[0] &
|
||||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
|
||||
link_conf->eht_mu_beamformer =
|
||||
params->eht_cap->fixed.phy_cap_info[7] &
|
||||
(IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ);
|
||||
} else {
|
||||
link_conf->eht_su_beamformer = false;
|
||||
link_conf->eht_su_beamformee = false;
|
||||
link_conf->eht_mu_beamformer = false;
|
||||
}
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP &&
|
||||
|
|
@ -1788,7 +1815,7 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
|
|||
(void *)params->he_6ghz_capa,
|
||||
link_sta);
|
||||
|
||||
if (params->eht_capa)
|
||||
if (params->he_capa && params->eht_capa)
|
||||
ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband,
|
||||
(u8 *)params->he_capa,
|
||||
params->he_capa_len,
|
||||
|
|
@ -4904,6 +4931,22 @@ ieee80211_del_link_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ieee80211_set_hw_timestamp(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_set_hw_timestamp *hwts)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
if (!local->ops->set_hw_timestamp)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
return local->ops->set_hw_timestamp(&local->hw, &sdata->vif, hwts);
|
||||
}
|
||||
|
||||
const struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
|
|
@ -5014,4 +5057,5 @@ const struct cfg80211_ops mac80211_config_ops = {
|
|||
.add_link_station = ieee80211_add_link_station,
|
||||
.mod_link_station = ieee80211_mod_link_station,
|
||||
.del_link_station = ieee80211_del_link_station,
|
||||
.set_hw_timestamp = ieee80211_set_hw_timestamp,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,16 +23,16 @@
|
|||
#include "driver-ops.h"
|
||||
|
||||
static ssize_t ieee80211_if_read(
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
void *data,
|
||||
char __user *userbuf,
|
||||
size_t count, loff_t *ppos,
|
||||
ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
|
||||
ssize_t (*format)(const void *, char *, int))
|
||||
{
|
||||
char buf[200];
|
||||
ssize_t ret = -EINVAL;
|
||||
|
||||
read_lock(&dev_base_lock);
|
||||
ret = (*format)(sdata, buf, sizeof(buf));
|
||||
ret = (*format)(data, buf, sizeof(buf));
|
||||
read_unlock(&dev_base_lock);
|
||||
|
||||
if (ret >= 0)
|
||||
|
|
@ -42,10 +42,10 @@ static ssize_t ieee80211_if_read(
|
|||
}
|
||||
|
||||
static ssize_t ieee80211_if_write(
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
void *data,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos,
|
||||
ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int))
|
||||
ssize_t (*write)(void *, const char *, int))
|
||||
{
|
||||
char buf[64];
|
||||
ssize_t ret;
|
||||
|
|
@ -58,64 +58,64 @@ static ssize_t ieee80211_if_write(
|
|||
buf[count] = '\0';
|
||||
|
||||
rtnl_lock();
|
||||
ret = (*write)(sdata, buf, count);
|
||||
ret = (*write)(data, buf, count);
|
||||
rtnl_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define IEEE80211_IF_FMT(name, field, format_string) \
|
||||
#define IEEE80211_IF_FMT(name, type, field, format_string) \
|
||||
static ssize_t ieee80211_if_fmt_##name( \
|
||||
const struct ieee80211_sub_if_data *sdata, char *buf, \
|
||||
const type *data, char *buf, \
|
||||
int buflen) \
|
||||
{ \
|
||||
return scnprintf(buf, buflen, format_string, sdata->field); \
|
||||
return scnprintf(buf, buflen, format_string, data->field); \
|
||||
}
|
||||
#define IEEE80211_IF_FMT_DEC(name, field) \
|
||||
IEEE80211_IF_FMT(name, field, "%d\n")
|
||||
#define IEEE80211_IF_FMT_HEX(name, field) \
|
||||
IEEE80211_IF_FMT(name, field, "%#x\n")
|
||||
#define IEEE80211_IF_FMT_LHEX(name, field) \
|
||||
IEEE80211_IF_FMT(name, field, "%#lx\n")
|
||||
#define IEEE80211_IF_FMT_DEC(name, type, field) \
|
||||
IEEE80211_IF_FMT(name, type, field, "%d\n")
|
||||
#define IEEE80211_IF_FMT_HEX(name, type, field) \
|
||||
IEEE80211_IF_FMT(name, type, field, "%#x\n")
|
||||
#define IEEE80211_IF_FMT_LHEX(name, type, field) \
|
||||
IEEE80211_IF_FMT(name, type, field, "%#lx\n")
|
||||
|
||||
#define IEEE80211_IF_FMT_HEXARRAY(name, field) \
|
||||
#define IEEE80211_IF_FMT_HEXARRAY(name, type, field) \
|
||||
static ssize_t ieee80211_if_fmt_##name( \
|
||||
const struct ieee80211_sub_if_data *sdata, \
|
||||
const type *data, \
|
||||
char *buf, int buflen) \
|
||||
{ \
|
||||
char *p = buf; \
|
||||
int i; \
|
||||
for (i = 0; i < sizeof(sdata->field); i++) { \
|
||||
for (i = 0; i < sizeof(data->field); i++) { \
|
||||
p += scnprintf(p, buflen + buf - p, "%.2x ", \
|
||||
sdata->field[i]); \
|
||||
data->field[i]); \
|
||||
} \
|
||||
p += scnprintf(p, buflen + buf - p, "\n"); \
|
||||
return p - buf; \
|
||||
}
|
||||
|
||||
#define IEEE80211_IF_FMT_ATOMIC(name, field) \
|
||||
#define IEEE80211_IF_FMT_ATOMIC(name, type, field) \
|
||||
static ssize_t ieee80211_if_fmt_##name( \
|
||||
const struct ieee80211_sub_if_data *sdata, \
|
||||
const type *data, \
|
||||
char *buf, int buflen) \
|
||||
{ \
|
||||
return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
|
||||
return scnprintf(buf, buflen, "%d\n", atomic_read(&data->field));\
|
||||
}
|
||||
|
||||
#define IEEE80211_IF_FMT_MAC(name, field) \
|
||||
#define IEEE80211_IF_FMT_MAC(name, type, field) \
|
||||
static ssize_t ieee80211_if_fmt_##name( \
|
||||
const struct ieee80211_sub_if_data *sdata, char *buf, \
|
||||
const type *data, char *buf, \
|
||||
int buflen) \
|
||||
{ \
|
||||
return scnprintf(buf, buflen, "%pM\n", sdata->field); \
|
||||
return scnprintf(buf, buflen, "%pM\n", data->field); \
|
||||
}
|
||||
|
||||
#define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, field) \
|
||||
#define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, type, field) \
|
||||
static ssize_t ieee80211_if_fmt_##name( \
|
||||
const struct ieee80211_sub_if_data *sdata, \
|
||||
const type *data, \
|
||||
char *buf, int buflen) \
|
||||
{ \
|
||||
return scnprintf(buf, buflen, "%d\n", \
|
||||
jiffies_to_msecs(sdata->field)); \
|
||||
jiffies_to_msecs(data->field)); \
|
||||
}
|
||||
|
||||
#define _IEEE80211_IF_FILE_OPS(name, _read, _write) \
|
||||
|
|
@ -126,43 +126,67 @@ static const struct file_operations name##_ops = { \
|
|||
.llseek = generic_file_llseek, \
|
||||
}
|
||||
|
||||
#define _IEEE80211_IF_FILE_R_FN(name) \
|
||||
#define _IEEE80211_IF_FILE_R_FN(name, type) \
|
||||
static ssize_t ieee80211_if_read_##name(struct file *file, \
|
||||
char __user *userbuf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
ssize_t (*fn)(const void *, char *, int) = (void *) \
|
||||
((ssize_t (*)(const type, char *, int)) \
|
||||
ieee80211_if_fmt_##name); \
|
||||
return ieee80211_if_read(file->private_data, \
|
||||
userbuf, count, ppos, \
|
||||
ieee80211_if_fmt_##name); \
|
||||
userbuf, count, ppos, fn); \
|
||||
}
|
||||
|
||||
#define _IEEE80211_IF_FILE_W_FN(name) \
|
||||
#define _IEEE80211_IF_FILE_W_FN(name, type) \
|
||||
static ssize_t ieee80211_if_write_##name(struct file *file, \
|
||||
const char __user *userbuf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
ssize_t (*fn)(void *, const char *, int) = (void *) \
|
||||
((ssize_t (*)(type, const char *, int)) \
|
||||
ieee80211_if_parse_##name); \
|
||||
return ieee80211_if_write(file->private_data, userbuf, count, \
|
||||
ppos, ieee80211_if_parse_##name); \
|
||||
ppos, fn); \
|
||||
}
|
||||
|
||||
#define IEEE80211_IF_FILE_R(name) \
|
||||
_IEEE80211_IF_FILE_R_FN(name) \
|
||||
_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_sub_if_data *) \
|
||||
_IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, NULL)
|
||||
|
||||
#define IEEE80211_IF_FILE_W(name) \
|
||||
_IEEE80211_IF_FILE_W_FN(name) \
|
||||
_IEEE80211_IF_FILE_W_FN(name, struct ieee80211_sub_if_data *) \
|
||||
_IEEE80211_IF_FILE_OPS(name, NULL, ieee80211_if_write_##name)
|
||||
|
||||
#define IEEE80211_IF_FILE_RW(name) \
|
||||
_IEEE80211_IF_FILE_R_FN(name) \
|
||||
_IEEE80211_IF_FILE_W_FN(name) \
|
||||
_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_sub_if_data *) \
|
||||
_IEEE80211_IF_FILE_W_FN(name, struct ieee80211_sub_if_data *) \
|
||||
_IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, \
|
||||
ieee80211_if_write_##name)
|
||||
|
||||
#define IEEE80211_IF_FILE(name, field, format) \
|
||||
IEEE80211_IF_FMT_##format(name, field) \
|
||||
IEEE80211_IF_FMT_##format(name, struct ieee80211_sub_if_data, field) \
|
||||
IEEE80211_IF_FILE_R(name)
|
||||
|
||||
/* Same but with a link_ prefix in the ops variable name and different type */
|
||||
#define IEEE80211_IF_LINK_FILE_R(name) \
|
||||
_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_link_data *) \
|
||||
_IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, NULL)
|
||||
|
||||
#define IEEE80211_IF_LINK_FILE_W(name) \
|
||||
_IEEE80211_IF_FILE_W_FN(name) \
|
||||
_IEEE80211_IF_FILE_OPS(link_##name, NULL, ieee80211_if_write_##name)
|
||||
|
||||
#define IEEE80211_IF_LINK_FILE_RW(name) \
|
||||
_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_link_data *) \
|
||||
_IEEE80211_IF_FILE_W_FN(name, struct ieee80211_link_data *) \
|
||||
_IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, \
|
||||
ieee80211_if_write_##name)
|
||||
|
||||
#define IEEE80211_IF_LINK_FILE(name, field, format) \
|
||||
IEEE80211_IF_FMT_##format(name, struct ieee80211_link_data, field) \
|
||||
IEEE80211_IF_LINK_FILE_R(name)
|
||||
|
||||
/* common attributes */
|
||||
IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[NL80211_BAND_2GHZ],
|
||||
HEX);
|
||||
|
|
@ -207,9 +231,9 @@ IEEE80211_IF_FILE_R(rc_rateidx_vht_mcs_mask_5ghz);
|
|||
|
||||
IEEE80211_IF_FILE(flags, flags, HEX);
|
||||
IEEE80211_IF_FILE(state, state, LHEX);
|
||||
IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC);
|
||||
IEEE80211_IF_FILE(ap_power_level, deflink.ap_power_level, DEC);
|
||||
IEEE80211_IF_FILE(user_power_level, deflink.user_power_level, DEC);
|
||||
IEEE80211_IF_LINK_FILE(txpower, conf->txpower, DEC);
|
||||
IEEE80211_IF_LINK_FILE(ap_power_level, ap_power_level, DEC);
|
||||
IEEE80211_IF_LINK_FILE(user_power_level, user_power_level, DEC);
|
||||
|
||||
static ssize_t
|
||||
ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data *sdata,
|
||||
|
|
@ -236,9 +260,10 @@ IEEE80211_IF_FILE(bssid, deflink.u.mgd.bssid, MAC);
|
|||
IEEE80211_IF_FILE(aid, vif.cfg.aid, DEC);
|
||||
IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS);
|
||||
|
||||
static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
||||
static int ieee80211_set_smps(struct ieee80211_link_data *link,
|
||||
enum ieee80211_smps_mode smps_mode)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = link->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int err;
|
||||
|
||||
|
|
@ -256,7 +281,7 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
sdata_lock(sdata);
|
||||
err = __ieee80211_request_smps_mgd(sdata, &sdata->deflink, smps_mode);
|
||||
err = __ieee80211_request_smps_mgd(link->sdata, link, smps_mode);
|
||||
sdata_unlock(sdata);
|
||||
|
||||
return err;
|
||||
|
|
@ -269,24 +294,24 @@ static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
|
|||
[IEEE80211_SMPS_DYNAMIC] = "dynamic",
|
||||
};
|
||||
|
||||
static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
|
||||
static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_link_data *link,
|
||||
char *buf, int buflen)
|
||||
{
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
return snprintf(buf, buflen, "request: %s\nused: %s\n",
|
||||
smps_modes[sdata->deflink.u.mgd.req_smps],
|
||||
smps_modes[sdata->deflink.smps_mode]);
|
||||
smps_modes[link->u.mgd.req_smps],
|
||||
smps_modes[link->smps_mode]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
|
||||
static ssize_t ieee80211_if_parse_smps(struct ieee80211_link_data *link,
|
||||
const char *buf, int buflen)
|
||||
{
|
||||
enum ieee80211_smps_mode mode;
|
||||
|
||||
for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) {
|
||||
if (strncmp(buf, smps_modes[mode], buflen) == 0) {
|
||||
int err = ieee80211_set_smps(sdata, mode);
|
||||
int err = ieee80211_set_smps(link, mode);
|
||||
if (!err)
|
||||
return buflen;
|
||||
return err;
|
||||
|
|
@ -295,7 +320,7 @@ static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
return -EINVAL;
|
||||
}
|
||||
IEEE80211_IF_FILE_RW(smps);
|
||||
IEEE80211_IF_LINK_FILE_RW(smps);
|
||||
|
||||
static ssize_t ieee80211_if_parse_tkip_mic_test(
|
||||
struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
|
||||
|
|
@ -595,6 +620,8 @@ static ssize_t ieee80211_if_parse_active_links(struct ieee80211_sub_if_data *sda
|
|||
}
|
||||
IEEE80211_IF_FILE_RW(active_links);
|
||||
|
||||
IEEE80211_IF_LINK_FILE(addr, conf->addr, MAC);
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);
|
||||
|
||||
|
|
@ -685,7 +712,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
|
|||
DEBUGFS_ADD(bssid);
|
||||
DEBUGFS_ADD(aid);
|
||||
DEBUGFS_ADD(beacon_timeout);
|
||||
DEBUGFS_ADD_MODE(smps, 0600);
|
||||
DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
|
||||
DEBUGFS_ADD_MODE(beacon_loss, 0200);
|
||||
DEBUGFS_ADD_MODE(uapsd_queues, 0600);
|
||||
|
|
@ -698,7 +724,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
|
|||
static void add_ap_files(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
DEBUGFS_ADD(num_mcast_sta);
|
||||
DEBUGFS_ADD_MODE(smps, 0600);
|
||||
DEBUGFS_ADD(num_sta_ps);
|
||||
DEBUGFS_ADD(dtim_count);
|
||||
DEBUGFS_ADD(num_buffered_multicast);
|
||||
|
|
@ -789,9 +814,6 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
|
|||
|
||||
DEBUGFS_ADD(flags);
|
||||
DEBUGFS_ADD(state);
|
||||
DEBUGFS_ADD(txpower);
|
||||
DEBUGFS_ADD(user_power_level);
|
||||
DEBUGFS_ADD(ap_power_level);
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
|
||||
add_common_files(sdata);
|
||||
|
|
@ -821,6 +843,31 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
|
|||
}
|
||||
}
|
||||
|
||||
#undef DEBUGFS_ADD_MODE
|
||||
#undef DEBUGFS_ADD
|
||||
|
||||
#define DEBUGFS_ADD_MODE(dentry, name, mode) \
|
||||
debugfs_create_file(#name, mode, dentry, \
|
||||
link, &link_##name##_ops)
|
||||
|
||||
#define DEBUGFS_ADD(dentry, name) DEBUGFS_ADD_MODE(dentry, name, 0400)
|
||||
|
||||
static void add_link_files(struct ieee80211_link_data *link,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
DEBUGFS_ADD(dentry, txpower);
|
||||
DEBUGFS_ADD(dentry, user_power_level);
|
||||
DEBUGFS_ADD(dentry, ap_power_level);
|
||||
|
||||
switch (link->sdata->vif.type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
DEBUGFS_ADD_MODE(dentry, smps, 0600);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
char buf[10+IFNAMSIZ];
|
||||
|
|
@ -831,6 +878,9 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
|
|||
sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
|
||||
sdata->vif.debugfs_dir);
|
||||
add_files(sdata);
|
||||
|
||||
if (!(sdata->local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))
|
||||
add_link_files(&sdata->deflink, sdata->vif.debugfs_dir);
|
||||
}
|
||||
|
||||
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
|
||||
|
|
@ -856,3 +906,66 @@ void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
|
|||
sprintf(buf, "netdev:%s", sdata->name);
|
||||
debugfs_rename(dir->d_parent, dir, dir->d_parent, buf);
|
||||
}
|
||||
|
||||
void ieee80211_link_debugfs_add(struct ieee80211_link_data *link)
|
||||
{
|
||||
char link_dir_name[10];
|
||||
|
||||
if (WARN_ON(!link->sdata->vif.debugfs_dir))
|
||||
return;
|
||||
|
||||
/* For now, this should not be called for non-MLO capable drivers */
|
||||
if (WARN_ON(!(link->sdata->local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO)))
|
||||
return;
|
||||
|
||||
snprintf(link_dir_name, sizeof(link_dir_name),
|
||||
"link-%d", link->link_id);
|
||||
|
||||
link->debugfs_dir =
|
||||
debugfs_create_dir(link_dir_name,
|
||||
link->sdata->vif.debugfs_dir);
|
||||
|
||||
DEBUGFS_ADD(link->debugfs_dir, addr);
|
||||
add_link_files(link, link->debugfs_dir);
|
||||
}
|
||||
|
||||
void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link)
|
||||
{
|
||||
if (!link->sdata->vif.debugfs_dir || !link->debugfs_dir) {
|
||||
link->debugfs_dir = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (link->debugfs_dir == link->sdata->vif.debugfs_dir) {
|
||||
WARN_ON(link != &link->sdata->deflink);
|
||||
link->debugfs_dir = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
debugfs_remove_recursive(link->debugfs_dir);
|
||||
link->debugfs_dir = NULL;
|
||||
}
|
||||
|
||||
void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link)
|
||||
{
|
||||
if (WARN_ON(!link->debugfs_dir))
|
||||
return;
|
||||
|
||||
drv_link_add_debugfs(link->sdata->local, link->sdata,
|
||||
link->conf, link->debugfs_dir);
|
||||
}
|
||||
|
||||
void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link)
|
||||
{
|
||||
if (!link || !link->debugfs_dir)
|
||||
return;
|
||||
|
||||
if (WARN_ON(link->debugfs_dir == link->sdata->vif.debugfs_dir))
|
||||
return;
|
||||
|
||||
/* Recreate the directory excluding the driver data */
|
||||
debugfs_remove_recursive(link->debugfs_dir);
|
||||
link->debugfs_dir = NULL;
|
||||
|
||||
ieee80211_link_debugfs_add(link);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,12 @@
|
|||
void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
void ieee80211_link_debugfs_add(struct ieee80211_link_data *link);
|
||||
void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link);
|
||||
|
||||
void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link);
|
||||
void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link);
|
||||
#else
|
||||
static inline void ieee80211_debugfs_add_netdev(
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
|
|
@ -20,6 +26,16 @@ static inline void ieee80211_debugfs_remove_netdev(
|
|||
static inline void ieee80211_debugfs_rename_netdev(
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{}
|
||||
|
||||
static inline void ieee80211_link_debugfs_add(struct ieee80211_link_data *link)
|
||||
{}
|
||||
static inline void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link)
|
||||
{}
|
||||
|
||||
static inline void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link)
|
||||
{}
|
||||
static inline void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link)
|
||||
{}
|
||||
#endif
|
||||
|
||||
#endif /* __IEEE80211_DEBUGFS_NETDEV_H */
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "trace.h"
|
||||
#include "driver-ops.h"
|
||||
#include "debugfs_sta.h"
|
||||
#include "debugfs_netdev.h"
|
||||
|
||||
int drv_start(struct ieee80211_local *local)
|
||||
{
|
||||
|
|
@ -477,6 +478,10 @@ int drv_change_vif_links(struct ieee80211_local *local,
|
|||
u16 old_links, u16 new_links,
|
||||
struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
|
||||
{
|
||||
struct ieee80211_link_data *link;
|
||||
unsigned long links_to_add;
|
||||
unsigned long links_to_rem;
|
||||
unsigned int link_id;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
might_sleep();
|
||||
|
|
@ -487,13 +492,31 @@ int drv_change_vif_links(struct ieee80211_local *local,
|
|||
if (old_links == new_links)
|
||||
return 0;
|
||||
|
||||
links_to_add = ~old_links & new_links;
|
||||
links_to_rem = old_links & ~new_links;
|
||||
|
||||
for_each_set_bit(link_id, &links_to_rem, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
link = rcu_access_pointer(sdata->link[link_id]);
|
||||
|
||||
ieee80211_link_debugfs_drv_remove(link);
|
||||
}
|
||||
|
||||
trace_drv_change_vif_links(local, sdata, old_links, new_links);
|
||||
if (local->ops->change_vif_links)
|
||||
ret = local->ops->change_vif_links(&local->hw, &sdata->vif,
|
||||
old_links, new_links, old);
|
||||
trace_drv_return_int(local, ret);
|
||||
|
||||
return ret;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_set_bit(link_id, &links_to_add, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
link = rcu_access_pointer(sdata->link[link_id]);
|
||||
|
||||
ieee80211_link_debugfs_drv_add(link);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_change_sta_links(struct ieee80211_local *local,
|
||||
|
|
|
|||
|
|
@ -465,6 +465,22 @@ static inline void drv_sta_remove(struct ieee80211_local *local,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
static inline void drv_link_add_debugfs(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct dentry *dir)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
if (local->ops->link_add_debugfs)
|
||||
local->ops->link_add_debugfs(&local->hw, &sdata->vif,
|
||||
link_conf, dir);
|
||||
}
|
||||
|
||||
static inline void drv_sta_add_debugfs(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta,
|
||||
|
|
|
|||
|
|
@ -999,6 +999,10 @@ struct ieee80211_link_data {
|
|||
struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
|
||||
|
||||
struct ieee80211_bss_conf *conf;
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
struct dentry *debugfs_dir;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ieee80211_sub_if_data {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "ieee80211_i.h"
|
||||
#include "driver-ops.h"
|
||||
#include "key.h"
|
||||
#include "debugfs_netdev.h"
|
||||
|
||||
void ieee80211_link_setup(struct ieee80211_link_data *link)
|
||||
{
|
||||
|
|
@ -34,6 +35,7 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
|
|||
link->link_id = link_id;
|
||||
link->conf = link_conf;
|
||||
link_conf->link_id = link_id;
|
||||
link_conf->vif = &sdata->vif;
|
||||
|
||||
INIT_WORK(&link->csa_finalize_work,
|
||||
ieee80211_csa_finalize_work);
|
||||
|
|
@ -60,6 +62,8 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
|
|||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
ieee80211_link_debugfs_add(link);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -93,6 +97,7 @@ static void ieee80211_tear_down_links(struct ieee80211_sub_if_data *sdata,
|
|||
if (WARN_ON(!link))
|
||||
continue;
|
||||
ieee80211_remove_link_keys(link, &keys);
|
||||
ieee80211_link_debugfs_remove(link);
|
||||
ieee80211_link_stop(link);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2744,7 +2744,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_link_data *link,
|
|||
return changed;
|
||||
}
|
||||
|
||||
static u32 ieee80211_link_set_associated(struct ieee80211_link_data *link,
|
||||
static u64 ieee80211_link_set_associated(struct ieee80211_link_data *link,
|
||||
struct cfg80211_bss *cbss)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = link->sdata;
|
||||
|
|
@ -3227,7 +3227,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
bool already = false;
|
||||
|
||||
if (WARN_ON(sdata->vif.valid_links))
|
||||
if (WARN_ON_ONCE(sdata->vif.valid_links))
|
||||
return;
|
||||
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
|
|
@ -5893,7 +5893,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
|
|||
goto free;
|
||||
}
|
||||
|
||||
if (sta && elems->opmode_notif)
|
||||
if (elems->opmode_notif)
|
||||
ieee80211_vht_handle_opmode(sdata, link_sta,
|
||||
*elems->opmode_notif,
|
||||
rx_status->band);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ static struct sk_buff *ieee80211_clean_skb(struct sk_buff *skb,
|
|||
unsigned int present_fcs_len,
|
||||
unsigned int rtap_space)
|
||||
{
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr;
|
||||
unsigned int hdrlen;
|
||||
__le16 fc;
|
||||
|
|
@ -51,6 +52,14 @@ static struct sk_buff *ieee80211_clean_skb(struct sk_buff *skb,
|
|||
__pskb_trim(skb, skb->len - present_fcs_len);
|
||||
pskb_pull(skb, rtap_space);
|
||||
|
||||
/* After pulling radiotap header, clear all flags that indicate
|
||||
* info in skb->data.
|
||||
*/
|
||||
status->flag &= ~(RX_FLAG_RADIOTAP_TLV_AT_END |
|
||||
RX_FLAG_RADIOTAP_LSIG |
|
||||
RX_FLAG_RADIOTAP_HE_MU |
|
||||
RX_FLAG_RADIOTAP_HE);
|
||||
|
||||
hdr = (void *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
|
||||
|
|
@ -117,9 +126,6 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
|
|||
/* allocate extra bitmaps */
|
||||
if (status->chains)
|
||||
len += 4 * hweight8(status->chains);
|
||||
/* vendor presence bitmap */
|
||||
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)
|
||||
len += 4;
|
||||
|
||||
if (ieee80211_have_rx_timestamp(status)) {
|
||||
len = ALIGN(len, 8);
|
||||
|
|
@ -181,34 +187,28 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
|
|||
len += 2 * hweight8(status->chains);
|
||||
}
|
||||
|
||||
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
|
||||
struct ieee80211_vendor_radiotap *rtap;
|
||||
int vendor_data_offset = 0;
|
||||
if (status->flag & RX_FLAG_RADIOTAP_TLV_AT_END) {
|
||||
int tlv_offset = 0;
|
||||
|
||||
/*
|
||||
* The position to look at depends on the existence (or non-
|
||||
* existence) of other elements, so take that into account...
|
||||
*/
|
||||
if (status->flag & RX_FLAG_RADIOTAP_HE)
|
||||
vendor_data_offset +=
|
||||
tlv_offset +=
|
||||
sizeof(struct ieee80211_radiotap_he);
|
||||
if (status->flag & RX_FLAG_RADIOTAP_HE_MU)
|
||||
vendor_data_offset +=
|
||||
tlv_offset +=
|
||||
sizeof(struct ieee80211_radiotap_he_mu);
|
||||
if (status->flag & RX_FLAG_RADIOTAP_LSIG)
|
||||
vendor_data_offset +=
|
||||
tlv_offset +=
|
||||
sizeof(struct ieee80211_radiotap_lsig);
|
||||
|
||||
rtap = (void *)&skb->data[vendor_data_offset];
|
||||
/* ensure 4 byte alignment for TLV */
|
||||
len = ALIGN(len, 4);
|
||||
|
||||
/* alignment for fixed 6-byte vendor data header */
|
||||
len = ALIGN(len, 2);
|
||||
/* vendor data header */
|
||||
len += 6;
|
||||
if (WARN_ON(rtap->align == 0))
|
||||
rtap->align = 1;
|
||||
len = ALIGN(len, rtap->align);
|
||||
len += rtap->len + rtap->pad;
|
||||
/* TLVs until the mac header */
|
||||
len += skb_mac_header(skb) - &skb->data[tlv_offset];
|
||||
}
|
||||
|
||||
return len;
|
||||
|
|
@ -304,9 +304,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
u32 it_present_val;
|
||||
u16 rx_flags = 0;
|
||||
u16 channel_flags = 0;
|
||||
u32 tlvs_len = 0;
|
||||
int mpdulen, chain;
|
||||
unsigned long chains = status->chains;
|
||||
struct ieee80211_vendor_radiotap rtap = {};
|
||||
struct ieee80211_radiotap_he he = {};
|
||||
struct ieee80211_radiotap_he_mu he_mu = {};
|
||||
struct ieee80211_radiotap_lsig lsig = {};
|
||||
|
|
@ -327,18 +327,17 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
skb_pull(skb, sizeof(lsig));
|
||||
}
|
||||
|
||||
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
|
||||
rtap = *(struct ieee80211_vendor_radiotap *)skb->data;
|
||||
/* rtap.len and rtap.pad are undone immediately */
|
||||
skb_pull(skb, sizeof(rtap) + rtap.len + rtap.pad);
|
||||
if (status->flag & RX_FLAG_RADIOTAP_TLV_AT_END) {
|
||||
/* data is pointer at tlv all other info was pulled off */
|
||||
tlvs_len = skb_mac_header(skb) - skb->data;
|
||||
}
|
||||
|
||||
mpdulen = skb->len;
|
||||
if (!(has_fcs && ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)))
|
||||
mpdulen += FCS_LEN;
|
||||
|
||||
rthdr = skb_push(skb, rtap_len);
|
||||
memset(rthdr, 0, rtap_len - rtap.len - rtap.pad);
|
||||
rthdr = skb_push(skb, rtap_len - tlvs_len);
|
||||
memset(rthdr, 0, rtap_len - tlvs_len);
|
||||
it_present = &rthdr->it_present;
|
||||
|
||||
/* radiotap header, set always present flags */
|
||||
|
|
@ -360,13 +359,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
|
||||
}
|
||||
|
||||
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
|
||||
it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
|
||||
BIT(IEEE80211_RADIOTAP_EXT);
|
||||
put_unaligned_le32(it_present_val, it_present);
|
||||
it_present++;
|
||||
it_present_val = rtap.present;
|
||||
}
|
||||
if (status->flag & RX_FLAG_RADIOTAP_TLV_AT_END)
|
||||
it_present_val |= BIT(IEEE80211_RADIOTAP_TLV);
|
||||
|
||||
put_unaligned_le32(it_present_val, it_present);
|
||||
|
||||
|
|
@ -697,22 +691,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
*pos++ = status->chain_signal[chain];
|
||||
*pos++ = chain;
|
||||
}
|
||||
|
||||
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
|
||||
/* ensure 2 byte alignment for the vendor field as required */
|
||||
if ((pos - (u8 *)rthdr) & 1)
|
||||
*pos++ = 0;
|
||||
*pos++ = rtap.oui[0];
|
||||
*pos++ = rtap.oui[1];
|
||||
*pos++ = rtap.oui[2];
|
||||
*pos++ = rtap.subns;
|
||||
put_unaligned_le16(rtap.len, pos);
|
||||
pos += 2;
|
||||
/* align the actual payload as requested */
|
||||
while ((pos - (u8 *)rthdr) & (rtap.align - 1))
|
||||
*pos++ = 0;
|
||||
/* data (and possible padding) already follows */
|
||||
}
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
|
|
@ -788,6 +766,13 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
bool only_monitor = false;
|
||||
unsigned int min_head_len;
|
||||
|
||||
if (WARN_ON_ONCE(status->flag & RX_FLAG_RADIOTAP_TLV_AT_END &&
|
||||
!skb_mac_header_was_set(origskb))) {
|
||||
/* with this skb no way to know where frame payload starts */
|
||||
dev_kfree_skb(origskb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (status->flag & RX_FLAG_RADIOTAP_HE)
|
||||
rtap_space += sizeof(struct ieee80211_radiotap_he);
|
||||
|
||||
|
|
@ -797,12 +782,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
if (status->flag & RX_FLAG_RADIOTAP_LSIG)
|
||||
rtap_space += sizeof(struct ieee80211_radiotap_lsig);
|
||||
|
||||
if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) {
|
||||
struct ieee80211_vendor_radiotap *rtap =
|
||||
(void *)(origskb->data + rtap_space);
|
||||
|
||||
rtap_space += sizeof(*rtap) + rtap->len + rtap->pad;
|
||||
}
|
||||
if (status->flag & RX_FLAG_RADIOTAP_TLV_AT_END)
|
||||
rtap_space += skb_mac_header(origskb) - &origskb->data[rtap_space];
|
||||
|
||||
min_head_len = rtap_space;
|
||||
|
||||
|
|
@ -2582,7 +2563,7 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
|
|||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
bool noencrypt = !(status->flag & RX_FLAG_DECRYPTED);
|
||||
|
||||
cfg80211_rx_control_port(dev, skb, noencrypt);
|
||||
cfg80211_rx_control_port(dev, skb, noencrypt, rx->link_id);
|
||||
dev_kfree_skb(skb);
|
||||
} else {
|
||||
struct ethhdr *ehdr = (void *)skb_mac_header(skb);
|
||||
|
|
@ -3916,8 +3897,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
|
|||
if (!local->cooked_mntrs)
|
||||
goto out_free_skb;
|
||||
|
||||
/* vendor data is long removed here */
|
||||
status->flag &= ~RX_FLAG_RADIOTAP_VENDOR_DATA;
|
||||
/* room for the radiotap header based on driver features */
|
||||
needed_headroom = ieee80211_rx_radiotap_hdrlen(local, status, skb);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2018-2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/if_arp.h>
|
||||
|
|
@ -1246,11 +1246,11 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only call this function when a scan can't be queued -- under RTNL.
|
||||
*/
|
||||
void ieee80211_scan_cancel(struct ieee80211_local *local)
|
||||
{
|
||||
/* ensure a new scan cannot be queued */
|
||||
lockdep_assert_wiphy(local->hw.wiphy);
|
||||
|
||||
/*
|
||||
* We are canceling software scan, or deferred scan that was not
|
||||
* yet really started (see __ieee80211_start_scan ).
|
||||
|
|
|
|||
|
|
@ -5115,6 +5115,16 @@ static int ieee80211_beacon_protect(struct sk_buff *skb,
|
|||
tx.key = rcu_dereference(link->default_beacon_key);
|
||||
if (!tx.key)
|
||||
return 0;
|
||||
|
||||
if (unlikely(tx.key->flags & KEY_FLAG_TAINTED)) {
|
||||
tx.key = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(tx.key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT_TX) &&
|
||||
tx.key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
|
||||
IEEE80211_SKB_CB(skb)->control.hw_key = &tx.key->conf;
|
||||
|
||||
tx.local = local;
|
||||
tx.sdata = sdata;
|
||||
__skb_queue_head_init(&tx.skbs);
|
||||
|
|
|
|||
|
|
@ -673,6 +673,39 @@ static bool cfg80211_allowed_address(struct wireless_dev *wdev, const u8 *addr)
|
|||
return ether_addr_equal(addr, wdev_address(wdev));
|
||||
}
|
||||
|
||||
static bool cfg80211_allowed_random_address(struct wireless_dev *wdev,
|
||||
const struct ieee80211_mgmt *mgmt)
|
||||
{
|
||||
if (ieee80211_is_auth(mgmt->frame_control) ||
|
||||
ieee80211_is_deauth(mgmt->frame_control)) {
|
||||
/* Allow random TA to be used with authentication and
|
||||
* deauthentication frames if the driver has indicated support.
|
||||
*/
|
||||
if (wiphy_ext_feature_isset(
|
||||
wdev->wiphy,
|
||||
NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA))
|
||||
return true;
|
||||
} else if (ieee80211_is_action(mgmt->frame_control) &&
|
||||
mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
|
||||
/* Allow random TA to be used with Public Action frames if the
|
||||
* driver has indicated support.
|
||||
*/
|
||||
if (!wdev->connected &&
|
||||
wiphy_ext_feature_isset(
|
||||
wdev->wiphy,
|
||||
NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA))
|
||||
return true;
|
||||
|
||||
if (wdev->connected &&
|
||||
wiphy_ext_feature_isset(
|
||||
wdev->wiphy,
|
||||
NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
struct cfg80211_mgmt_tx_params *params, u64 *cookie)
|
||||
|
|
@ -774,25 +807,9 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
|||
return err;
|
||||
}
|
||||
|
||||
if (!cfg80211_allowed_address(wdev, mgmt->sa)) {
|
||||
/* Allow random TA to be used with Public Action frames if the
|
||||
* driver has indicated support for this. Otherwise, only allow
|
||||
* the local address to be used.
|
||||
*/
|
||||
if (!ieee80211_is_action(mgmt->frame_control) ||
|
||||
mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
|
||||
return -EINVAL;
|
||||
if (!wdev->connected &&
|
||||
!wiphy_ext_feature_isset(
|
||||
&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA))
|
||||
return -EINVAL;
|
||||
if (wdev->connected &&
|
||||
!wiphy_ext_feature_isset(
|
||||
&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED))
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!cfg80211_allowed_address(wdev, mgmt->sa) &&
|
||||
!cfg80211_allowed_random_address(wdev, mgmt))
|
||||
return -EINVAL;
|
||||
|
||||
/* Transmit the management frame as requested by user space */
|
||||
return rdev_mgmt_tx(rdev, wdev, params, cookie);
|
||||
|
|
|
|||
|
|
@ -806,6 +806,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||
[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
|
||||
[NL80211_ATTR_PUNCT_BITMAP] = NLA_POLICY_RANGE(NLA_U8, 0, 0xffff),
|
||||
|
||||
[NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_HW_TIMESTAMP_ENABLED] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
|
@ -2964,6 +2967,11 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO)
|
||||
nla_put_flag(msg, NL80211_ATTR_MLO_SUPPORT);
|
||||
|
||||
if (rdev->wiphy.hw_timestamp_max_peers &&
|
||||
nla_put_u16(msg, NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS,
|
||||
rdev->wiphy.hw_timestamp_max_peers))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
break;
|
||||
|
|
@ -9019,7 +9027,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||
struct nlattr *attr;
|
||||
struct wiphy *wiphy;
|
||||
int err, tmp, n_ssids = 0, n_channels, i;
|
||||
size_t ie_len;
|
||||
size_t ie_len, size;
|
||||
|
||||
wiphy = &rdev->wiphy;
|
||||
|
||||
|
|
@ -9064,10 +9072,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||
if (ie_len > wiphy->max_scan_ie_len)
|
||||
return -EINVAL;
|
||||
|
||||
request = kzalloc(sizeof(*request)
|
||||
+ sizeof(*request->ssids) * n_ssids
|
||||
+ sizeof(*request->channels) * n_channels
|
||||
+ ie_len, GFP_KERNEL);
|
||||
size = struct_size(request, channels, n_channels);
|
||||
size = size_add(size, array_size(sizeof(*request->ssids), n_ssids));
|
||||
size = size_add(size, ie_len);
|
||||
request = kzalloc(size, GFP_KERNEL);
|
||||
if (!request)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -9400,7 +9408,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
struct nlattr *attr;
|
||||
int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
|
||||
enum nl80211_band band;
|
||||
size_t ie_len;
|
||||
size_t ie_len, size;
|
||||
struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
|
||||
s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
|
||||
|
||||
|
|
@ -9509,12 +9517,14 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
request = kzalloc(sizeof(*request)
|
||||
+ sizeof(*request->ssids) * n_ssids
|
||||
+ sizeof(*request->match_sets) * n_match_sets
|
||||
+ sizeof(*request->scan_plans) * n_plans
|
||||
+ sizeof(*request->channels) * n_channels
|
||||
+ ie_len, GFP_KERNEL);
|
||||
size = struct_size(request, channels, n_channels);
|
||||
size = size_add(size, array_size(sizeof(*request->ssids), n_ssids));
|
||||
size = size_add(size, array_size(sizeof(*request->match_sets),
|
||||
n_match_sets));
|
||||
size = size_add(size, array_size(sizeof(*request->scan_plans),
|
||||
n_plans));
|
||||
size = size_add(size, ie_len);
|
||||
request = kzalloc(size, GFP_KERNEL);
|
||||
if (!request)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
|
@ -16162,6 +16172,29 @@ nl80211_remove_link_station(struct sk_buff *skb, struct genl_info *info)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int nl80211_set_hw_timestamp(struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct cfg80211_set_hw_timestamp hwts = {};
|
||||
|
||||
if (!rdev->wiphy.hw_timestamp_max_peers)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_MAC] &&
|
||||
rdev->wiphy.hw_timestamp_max_peers != CFG80211_HW_TIMESTAMP_ALL_PEERS)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MAC])
|
||||
hwts.macaddr = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
|
||||
hwts.enable =
|
||||
nla_get_flag(info->attrs[NL80211_ATTR_HW_TIMESTAMP_ENABLED]);
|
||||
|
||||
return rdev_set_hw_timestamp(rdev, dev, &hwts);
|
||||
}
|
||||
|
||||
#define NL80211_FLAG_NEED_WIPHY 0x01
|
||||
#define NL80211_FLAG_NEED_NETDEV 0x02
|
||||
#define NL80211_FLAG_NEED_RTNL 0x04
|
||||
|
|
@ -17336,6 +17369,12 @@ static const struct genl_small_ops nl80211_small_ops[] = {
|
|||
.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_MLO_VALID_LINK_ID),
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_SET_HW_TIMESTAMP,
|
||||
.doit = nl80211_set_hw_timestamp,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_family nl80211_fam __ro_after_init = {
|
||||
|
|
@ -18717,7 +18756,9 @@ EXPORT_SYMBOL(cfg80211_mgmt_tx_status_ext);
|
|||
|
||||
static int __nl80211_rx_control_port(struct net_device *dev,
|
||||
struct sk_buff *skb,
|
||||
bool unencrypted, gfp_t gfp)
|
||||
bool unencrypted,
|
||||
int link_id,
|
||||
gfp_t gfp)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
|
|
@ -18749,6 +18790,8 @@ static int __nl80211_rx_control_port(struct net_device *dev,
|
|||
NL80211_ATTR_PAD) ||
|
||||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
|
||||
nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
|
||||
(link_id >= 0 &&
|
||||
nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) ||
|
||||
(unencrypted && nla_put_flag(msg,
|
||||
NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
|
||||
goto nla_put_failure;
|
||||
|
|
@ -18767,13 +18810,14 @@ static int __nl80211_rx_control_port(struct net_device *dev,
|
|||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
bool cfg80211_rx_control_port(struct net_device *dev,
|
||||
struct sk_buff *skb, bool unencrypted)
|
||||
bool cfg80211_rx_control_port(struct net_device *dev, struct sk_buff *skb,
|
||||
bool unencrypted, int link_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
trace_cfg80211_rx_control_port(dev, skb, unencrypted);
|
||||
ret = __nl80211_rx_control_port(dev, skb, unencrypted, GFP_ATOMIC);
|
||||
trace_cfg80211_rx_control_port(dev, skb, unencrypted, link_id);
|
||||
ret = __nl80211_rx_control_port(dev, skb, unencrypted, link_id,
|
||||
GFP_ATOMIC);
|
||||
trace_cfg80211_return_bool(ret == 0);
|
||||
return ret == 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1494,4 +1494,21 @@ rdev_del_link_station(struct cfg80211_registered_device *rdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
rdev_set_hw_timestamp(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_set_hw_timestamp *hwts)
|
||||
{
|
||||
struct wiphy *wiphy = &rdev->wiphy;
|
||||
int ret;
|
||||
|
||||
if (!rdev->ops->set_hw_timestamp)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
trace_rdev_set_hw_timestamp(wiphy, dev, hwts);
|
||||
ret = rdev->ops->set_hw_timestamp(wiphy, dev, hwts);
|
||||
trace_rdev_return_int(wiphy, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* __CFG80211_RDEV_OPS */
|
||||
|
|
|
|||
|
|
@ -1810,8 +1810,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
|
||||
int cfg80211_get_ies_channel_number(const u8 *ie, size_t ielen,
|
||||
enum nl80211_band band,
|
||||
enum cfg80211_bss_frame_type ftype)
|
||||
enum nl80211_band band)
|
||||
{
|
||||
const struct element *tmp;
|
||||
|
||||
|
|
@ -1830,9 +1829,7 @@ int cfg80211_get_ies_channel_number(const u8 *ie, size_t ielen,
|
|||
if (!he_6ghz_oper)
|
||||
return -1;
|
||||
|
||||
if (ftype != CFG80211_BSS_FTYPE_BEACON ||
|
||||
he_6ghz_oper->control & IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON)
|
||||
return he_6ghz_oper->primary;
|
||||
return he_6ghz_oper->primary;
|
||||
}
|
||||
} else if (band == NL80211_BAND_S1GHZ) {
|
||||
tmp = cfg80211_find_elem(WLAN_EID_S1G_OPERATION, ie, ielen);
|
||||
|
|
@ -1870,15 +1867,14 @@ EXPORT_SYMBOL(cfg80211_get_ies_channel_number);
|
|||
static struct ieee80211_channel *
|
||||
cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
|
||||
struct ieee80211_channel *channel,
|
||||
enum nl80211_bss_scan_width scan_width,
|
||||
enum cfg80211_bss_frame_type ftype)
|
||||
enum nl80211_bss_scan_width scan_width)
|
||||
{
|
||||
u32 freq;
|
||||
int channel_number;
|
||||
struct ieee80211_channel *alt_channel;
|
||||
|
||||
channel_number = cfg80211_get_ies_channel_number(ie, ielen,
|
||||
channel->band, ftype);
|
||||
channel->band);
|
||||
|
||||
if (channel_number < 0) {
|
||||
/* No channel information in frame payload */
|
||||
|
|
@ -1888,22 +1884,21 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
|
|||
freq = ieee80211_channel_to_freq_khz(channel_number, channel->band);
|
||||
|
||||
/*
|
||||
* In 6GHz, duplicated beacon indication is relevant for
|
||||
* beacons only.
|
||||
* Frame info (beacon/prob res) is the same as received channel,
|
||||
* no need for further processing.
|
||||
*/
|
||||
if (channel->band == NL80211_BAND_6GHZ &&
|
||||
(freq == channel->center_freq ||
|
||||
abs(freq - channel->center_freq) > 80))
|
||||
if (freq == ieee80211_channel_to_khz(channel))
|
||||
return channel;
|
||||
|
||||
alt_channel = ieee80211_get_channel_khz(wiphy, freq);
|
||||
if (!alt_channel) {
|
||||
if (channel->band == NL80211_BAND_2GHZ) {
|
||||
if (channel->band == NL80211_BAND_2GHZ ||
|
||||
channel->band == NL80211_BAND_6GHZ) {
|
||||
/*
|
||||
* Better not allow unexpected channels when that could
|
||||
* be going beyond the 1-11 range (e.g., discovering
|
||||
* BSS on channel 12 when radio is configured for
|
||||
* channel 11.
|
||||
* channel 11) or beyond the 6 GHz channel range.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1957,7 +1952,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
|
|||
return NULL;
|
||||
|
||||
channel = cfg80211_get_bss_channel(wiphy, ie, ielen, data->chan,
|
||||
data->scan_width, ftype);
|
||||
data->scan_width);
|
||||
if (!channel)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -2391,7 +2386,6 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
|
|||
size_t ielen, min_hdr_len = offsetof(struct ieee80211_mgmt,
|
||||
u.probe_resp.variable);
|
||||
int bss_type;
|
||||
enum cfg80211_bss_frame_type ftype;
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
|
||||
offsetof(struct ieee80211_mgmt, u.beacon.variable));
|
||||
|
|
@ -2428,16 +2422,8 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
|
|||
variable = ext->u.s1g_beacon.variable;
|
||||
}
|
||||
|
||||
if (ieee80211_is_beacon(mgmt->frame_control))
|
||||
ftype = CFG80211_BSS_FTYPE_BEACON;
|
||||
else if (ieee80211_is_probe_resp(mgmt->frame_control))
|
||||
ftype = CFG80211_BSS_FTYPE_PRESP;
|
||||
else
|
||||
ftype = CFG80211_BSS_FTYPE_UNKNOWN;
|
||||
|
||||
channel = cfg80211_get_bss_channel(wiphy, variable,
|
||||
ielen, data->chan, data->scan_width,
|
||||
ftype);
|
||||
ielen, data->chan, data->scan_width);
|
||||
if (!channel)
|
||||
return NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -3165,14 +3165,15 @@ TRACE_EVENT(cfg80211_control_port_tx_status,
|
|||
|
||||
TRACE_EVENT(cfg80211_rx_control_port,
|
||||
TP_PROTO(struct net_device *netdev, struct sk_buff *skb,
|
||||
bool unencrypted),
|
||||
TP_ARGS(netdev, skb, unencrypted),
|
||||
bool unencrypted, int link_id),
|
||||
TP_ARGS(netdev, skb, unencrypted, link_id),
|
||||
TP_STRUCT__entry(
|
||||
NETDEV_ENTRY
|
||||
__field(int, len)
|
||||
MAC_ENTRY(from)
|
||||
__field(u16, proto)
|
||||
__field(bool, unencrypted)
|
||||
__field(int, link_id)
|
||||
),
|
||||
TP_fast_assign(
|
||||
NETDEV_ASSIGN;
|
||||
|
|
@ -3180,10 +3181,12 @@ TRACE_EVENT(cfg80211_rx_control_port,
|
|||
MAC_ASSIGN(from, eth_hdr(skb)->h_source);
|
||||
__entry->proto = be16_to_cpu(skb->protocol);
|
||||
__entry->unencrypted = unencrypted;
|
||||
__entry->link_id = link_id;
|
||||
),
|
||||
TP_printk(NETDEV_PR_FMT ", len=%d, %pM, proto: 0x%x, unencrypted: %s",
|
||||
TP_printk(NETDEV_PR_FMT ", len=%d, %pM, proto: 0x%x, unencrypted: %s, link: %d",
|
||||
NETDEV_PR_ARG, __entry->len, __entry->from,
|
||||
__entry->proto, BOOL_TO_STR(__entry->unencrypted))
|
||||
__entry->proto, BOOL_TO_STR(__entry->unencrypted),
|
||||
__entry->link_id)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_cqm_rssi_notify,
|
||||
|
|
@ -3918,6 +3921,31 @@ TRACE_EVENT(rdev_del_link_station,
|
|||
__entry->link_id)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_set_hw_timestamp,
|
||||
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
|
||||
struct cfg80211_set_hw_timestamp *hwts),
|
||||
|
||||
TP_ARGS(wiphy, netdev, hwts),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
NETDEV_ENTRY
|
||||
MAC_ENTRY(macaddr)
|
||||
__field(bool, enable)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
NETDEV_ASSIGN;
|
||||
MAC_ASSIGN(macaddr, hwts->macaddr);
|
||||
__entry->enable = hwts->enable;
|
||||
),
|
||||
|
||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mac %pM, enable: %u",
|
||||
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->macaddr,
|
||||
__entry->enable)
|
||||
);
|
||||
|
||||
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user